mirror of
https://codeberg.org/emersion/gamja.git
synced 2024-11-24 16:28:05 -05:00
Workaround the sad state of base64 web APIs
This is necessary to make usernames/passwords with UTF-8 in them work correctly.
This commit is contained in:
parent
8e30806fec
commit
505a6fd5ab
2 changed files with 45 additions and 2 deletions
42
lib/base64.js
Normal file
42
lib/base64.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
/* The JS world is still in the stone age. We're in 2022 and we still don't
|
||||
* have the technology to correctly base64-encode a UTF-8 string. Can't wait
|
||||
* the next industrial revolution.
|
||||
*
|
||||
* For more info, see:
|
||||
* https://developer.mozilla.org/en-US/docs/Glossary/Base64#the_unicode_problem
|
||||
*/
|
||||
export function encode(data) {
|
||||
if (!window.TextEncoder) {
|
||||
return btoa(data);
|
||||
}
|
||||
|
||||
var encoder = new TextEncoder();
|
||||
var bytes = encoder.encode(data);
|
||||
|
||||
var trailing = bytes.length % 3;
|
||||
var out = "";
|
||||
for (var i = 0; i < bytes.length - trailing; i += 3) {
|
||||
var u24 = (bytes[i] << 16) + (bytes[i + 1] << 8) + bytes[i + 2];
|
||||
out += alphabet[(u24 >> 18) & 0x3F];
|
||||
out += alphabet[(u24 >> 12) & 0x3F];
|
||||
out += alphabet[(u24 >> 6) & 0x3F];
|
||||
out += alphabet[u24 & 0x3F];
|
||||
}
|
||||
|
||||
if (trailing == 1) {
|
||||
var u8 = bytes[bytes.length - 1];
|
||||
out += alphabet[u8 >> 2];
|
||||
out += alphabet[(u8 << 4) & 0x3F];
|
||||
out += "==";
|
||||
} else if (trailing == 2) {
|
||||
var u16 = (bytes[bytes.length - 2] << 8) + bytes[bytes.length - 1];
|
||||
out += alphabet[u16 >> 10];
|
||||
out += alphabet[(u16 >> 4) & 0x3F];
|
||||
out += alphabet[(u16 << 2) & 0x3F];
|
||||
out += "=";
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
import * as irc from "./irc.js";
|
||||
import * as base64 from "./base64.js";
|
||||
|
||||
// Static list of capabilities that are always requested when supported by the
|
||||
// server
|
||||
|
@ -460,11 +461,11 @@ export default class Client extends EventTarget {
|
|||
let initialResp = null;
|
||||
switch (mechanism) {
|
||||
case "PLAIN":
|
||||
let respStr = btoa("\0" + params.username + "\0" + params.password);
|
||||
let respStr = base64.encode("\0" + params.username + "\0" + params.password);
|
||||
initialResp = { command: "AUTHENTICATE", params: [respStr] };
|
||||
break;
|
||||
case "EXTERNAL":
|
||||
initialResp = { command: "AUTHENTICATE", params: [btoa("")] };
|
||||
initialResp = { command: "AUTHENTICATE", params: [base64.encode("")] };
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unknown authentication mechanism '${mechanism}'`);
|
||||
|
|
Loading…
Reference in a new issue