fix(base64): use js-base64 to handle non ascii text

Use js-base64 to handle non ascii text and ignore whitespaces
Fix #879 and #409
This commit is contained in:
sharevb 2024-02-25 11:05:41 +01:00
parent a07806cd15
commit 3f61e3569e
3 changed files with 15 additions and 10 deletions

View file

@ -62,6 +62,7 @@
"highlight.js": "^11.7.0", "highlight.js": "^11.7.0",
"iarna-toml-esm": "^3.0.5", "iarna-toml-esm": "^3.0.5",
"ibantools": "^4.3.3", "ibantools": "^4.3.3",
"js-base64": "^3.7.6",
"json5": "^2.2.3", "json5": "^2.2.3",
"jwt-decode": "^3.1.2", "jwt-decode": "^3.1.2",
"libphonenumber-js": "^1.10.28", "libphonenumber-js": "^1.10.28",

View file

@ -38,7 +38,8 @@ describe('base64 utils', () => {
it('should throw for incorrect base64 string', () => { it('should throw for incorrect base64 string', () => {
expect(() => base64ToText('a')).to.throw('Incorrect base64 string'); expect(() => base64ToText('a')).to.throw('Incorrect base64 string');
expect(() => base64ToText(' ')).to.throw('Incorrect base64 string'); // should not really be false because trimming of space is now implied
// expect(() => base64ToText(' ')).to.throw('Incorrect base64 string');
expect(() => base64ToText('é')).to.throw('Incorrect base64 string'); expect(() => base64ToText('é')).to.throw('Incorrect base64 string');
// missing final '=' // missing final '='
expect(() => base64ToText('bG9yZW0gaXBzdW0')).to.throw('Incorrect base64 string'); expect(() => base64ToText('bG9yZW0gaXBzdW0')).to.throw('Incorrect base64 string');
@ -56,17 +57,17 @@ describe('base64 utils', () => {
it('should return false for incorrect base64 string', () => { it('should return false for incorrect base64 string', () => {
expect(isValidBase64('a')).to.eql(false); expect(isValidBase64('a')).to.eql(false);
expect(isValidBase64(' ')).to.eql(false);
expect(isValidBase64('é')).to.eql(false); expect(isValidBase64('é')).to.eql(false);
expect(isValidBase64('data:text/plain;notbase64,YQ==')).to.eql(false); expect(isValidBase64('data:text/plain;notbase64,YQ==')).to.eql(false);
// missing final '=' // missing final '='
expect(isValidBase64('bG9yZW0gaXBzdW0')).to.eql(false); expect(isValidBase64('bG9yZW0gaXBzdW0')).to.eql(false);
}); });
it('should return false for untrimmed correct base64 string', () => { it('should return true for untrimmed correct base64 string', () => {
expect(isValidBase64('bG9yZW0gaXBzdW0= ')).to.eql(false); expect(isValidBase64('bG9yZW0gaXBzdW0= ')).to.eql(true);
expect(isValidBase64(' LTE=')).to.eql(false); expect(isValidBase64(' LTE=')).to.eql(true);
expect(isValidBase64(' YQ== ')).to.eql(false); expect(isValidBase64(' YQ== ')).to.eql(true);
expect(isValidBase64(' ')).to.eql(true);
}); });
}); });

View file

@ -1,7 +1,9 @@
import { Base64 } from 'js-base64';
export { textToBase64, base64ToText, isValidBase64, removePotentialDataAndMimePrefix }; export { textToBase64, base64ToText, isValidBase64, removePotentialDataAndMimePrefix };
function textToBase64(str: string, { makeUrlSafe = false }: { makeUrlSafe?: boolean } = {}) { function textToBase64(str: string, { makeUrlSafe = false }: { makeUrlSafe?: boolean } = {}) {
const encoded = window.btoa(str); const encoded = Base64.encode(str);
return makeUrlSafe ? makeUriSafe(encoded) : encoded; return makeUrlSafe ? makeUriSafe(encoded) : encoded;
} }
@ -16,7 +18,7 @@ function base64ToText(str: string, { makeUrlSafe = false }: { makeUrlSafe?: bool
} }
try { try {
return window.atob(cleanStr); return Base64.decode(cleanStr);
} }
catch (_) { catch (_) {
throw new Error('Incorrect base64 string'); throw new Error('Incorrect base64 string');
@ -34,10 +36,11 @@ function isValidBase64(str: string, { makeUrlSafe = false }: { makeUrlSafe?: boo
} }
try { try {
const reEncodedBase64 = Base64.fromUint8Array(Base64.toUint8Array(cleanStr));
if (makeUrlSafe) { if (makeUrlSafe) {
return removePotentialPadding(window.btoa(window.atob(cleanStr))) === cleanStr; return removePotentialPadding(reEncodedBase64) === cleanStr;
} }
return window.btoa(window.atob(cleanStr)) === cleanStr; return reEncodedBase64 === cleanStr.replace(/\s/g, '');
} }
catch (err) { catch (err) {
return false; return false;