/* * Copyright (c) 2013 Kevin van Zonneveld (http://kvz.io) * and Contributors (http://phpjs.org/authors) * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is furnished to do * so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ // Deprecated and removed in TypeScript declare function unescape(s: string): string; /** * Decodes a url safe Base 64 encoded string * @remarks See: {@link http://tools.ietf.org/html/rfc4648#page-7} * @param data - String to decode * @returns The decoded string */ export function base64urldecode(data: string): string { if (!data) { return data; } const padding = 4 - (data.length % 4); switch (padding) { case 2: data += '=='; break; case 3: data += '='; break; } const b64Data = data.replace(/-/g, '+').replace(/_/g, '/'); return base64decode(b64Data); } /** * Encodes a string into a url safe Base 64 encoded string * @remarks See: {@link http://tools.ietf.org/html/rfc4648#page-7} * @param data - String to encode * @returns The url safe Base 64 string */ export function base64urlencode(data: string): string { if (!data) { return data; } const enc = base64encode(data); return enc.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_'); } const b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; /** * Encode string as base64. * Any type can be passed, but will be stringified * * @param data - string to encode * @returns base64-encoded string */ export function base64encode(data: string): string { // discuss at: http://phpjs.org/functions/base64_encode/ // original by: Tyler Akins (http://rumkin.com) // improved by: Bayron Guevara // improved by: Thunder.m // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // improved by: Rafał Kukawski (http://kukawski.pl) // bugfixed by: Pellentesque Malesuada // example 1: base64_encode('Kevin van Zonneveld'); // returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA==' // example 2: base64_encode('a'); // returns 2: 'YQ==' // example 3: base64_encode('✓ à la mode'); // returns 3: '4pyTIMOgIGxhIG1vZGU=' let o1, o2, o3, h1, h2, h3, h4, bits, i = 0, ac = 0; const tmp_arr: Array = []; if (!data) { return data; } data = unescape(encodeURIComponent(data)); do { // pack three octets into four hexets o1 = data.charCodeAt(i++); o2 = data.charCodeAt(i++); o3 = data.charCodeAt(i++); bits = (o1 << 16) | (o2 << 8) | o3; h1 = (bits >> 18) & 0x3f; h2 = (bits >> 12) & 0x3f; h3 = (bits >> 6) & 0x3f; h4 = bits & 0x3f; // use hexets to index into b64, and append result to encoded string tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4); } while (i < data.length); const enc = tmp_arr.join(''); const r = data.length % 3; return (r ? enc.slice(0, r - 3) : enc) + '==='.slice(r || 3); } /** * Decode base64 to string * * @param data - base64 to string * @returns decoded string */ export function base64decode(encodedData: string): string { // discuss at: http://locutus.io/php/base64_decode/ // original by: Tyler Akins (http://rumkin.com) // improved by: Thunder.m // improved by: Kevin van Zonneveld (http://kvz.io) // improved by: Kevin van Zonneveld (http://kvz.io) // input by: Aman Gupta // input by: Brett Zamir (http://brett-zamir.me) // bugfixed by: Onno Marsman (https://twitter.com/onnomarsman) // bugfixed by: Pellentesque Malesuada // bugfixed by: Kevin van Zonneveld (http://kvz.io) // improved by: Indigo744 // example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA==') // returns 1: 'Kevin van Zonneveld' // example 2: base64_decode('YQ==') // returns 2: 'a' // example 3: base64_decode('4pyTIMOgIGxhIG1vZGU=') // returns 3: '✓ à la mode' // decodeUTF8string() // Internal function to decode properly UTF8 string // Adapted from Solution #1 at https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding const decodeUTF8string = function (str: string) { // Going backwards: from bytestream, to percent-encoding, to original string. return decodeURIComponent( str .split('') .map(function (c) { return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); }) .join('') ); }; let o1, o2, o3, h1, h2, h3, h4, bits, i = 0, ac = 0, dec = ''; const tmpArr: Array = []; if (!encodedData) { return encodedData; } encodedData += ''; do { // unpack four hexets into three octets using index points in b64 h1 = b64.indexOf(encodedData.charAt(i++)); h2 = b64.indexOf(encodedData.charAt(i++)); h3 = b64.indexOf(encodedData.charAt(i++)); h4 = b64.indexOf(encodedData.charAt(i++)); bits = (h1 << 18) | (h2 << 12) | (h3 << 6) | h4; o1 = (bits >> 16) & 0xff; o2 = (bits >> 8) & 0xff; o3 = bits & 0xff; if (h3 === 64) { tmpArr[ac++] = String.fromCharCode(o1); } else if (h4 === 64) { tmpArr[ac++] = String.fromCharCode(o1, o2); } else { tmpArr[ac++] = String.fromCharCode(o1, o2, o3); } } while (i < encodedData.length); dec = tmpArr.join(''); return decodeUTF8string(dec.replace(/\0+$/, '')); }