UNPKG

@qooxdoo/framework

Version:

The JS Framework for Coders

263 lines (220 loc) 7.75 kB
/* ************************************************************************ qooxdoo - the new era of web development http://qooxdoo.org Copyright: 2004-2008 1&1 Internet AG, Germany, http://www.1und1.de License: MIT: https://opensource.org/licenses/MIT See the LICENSE file in the project's top-level directory for details. Authors: * Sebastian Werner (wpbasti) * Adrian Olaru (adrianolaru) ************************************************************************ */ /** * Base64 encoder */ qx.Class.define("qx.util.Base64", { statics : { /** Characters allowed in a Base 64 encoded string */ __base64Chars : [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' ], /** * Encode a string using base64 encoding (http://en.wikipedia.org/wiki/Base64). * * @param input {String} the input string to encode * * @param is8bit {Boolean?} Whether the character set is 8-bit, not * multi-byte. If this parameter is not provided, the character set is * determined from the 'document' object. * * @return {String} The base64 encoded input string. */ encode : function(input, is8bit) { var isMultiByte; if (typeof is8bit == "undefined") { var charSet = document.characterSet || document.charset; isMultiByte = charSet.toLowerCase().indexOf('utf') != -1; if (!isMultiByte && window.btoa instanceof Function) { return btoa(input); } } else { isMultiByte = ! is8bit; } var padding = '='; var base64Chars = this.__base64Chars; var length = input.length; var output = []; var result = []; var i = 0; var translateUTF8 = this.__translateUTF8; while (i < length) { translateUTF8(input.charCodeAt(i++), output, !isMultiByte); } for (var k=0, l=output.length; k<l; k+=3) { if (k + 1 === l) { result.push(base64Chars[output[k] >> 2]); result.push(base64Chars[(output[k] & 3) << 4]); result.push(padding + padding); break; } if (k + 2 === l) { result.push(base64Chars[output[k] >> 2]); result.push(base64Chars[(output[k] & 3) << 4 | output[k + 1] >> 4]); result.push(base64Chars[(output[k + 1] & 15) << 2]); result.push(padding); break; } result.push(base64Chars[output[k] >> 2]); result.push(base64Chars[(output[k] & 3) << 4 | output[k + 1] >> 4]); result.push(base64Chars[(output[k + 1] & 15) << 2 | output[k + 2] >> 6]); result.push(base64Chars[output[k + 2] & 63]); } return result.join(''); }, /** * Adds to output array the UTF-8 bytes needed to represent the character (http://en.wikipedia.org/wiki/UTF8) * * @param characterCode {Integer} the code of the character * @param output {Array} the array of bytes to be filled * @param is8bit {Boolean} specifies whether we should not treat the array as a multi byte string */ __translateUTF8 : function(characterCode, output, is8bit) { if (characterCode < 128) { output.push(characterCode); return; } if (characterCode < 256 && is8bit) { output.push(characterCode); return; } if (characterCode < 2048) { output.push(192 | characterCode >> 6); output.push(128 | characterCode & 63); return; } if (characterCode < 65536) { output.push(224 | characterCode >> 12); output.push(128 | (characterCode >> 6) & 63); output.push(128 | characterCode & 63); return; } else { output.push(240 | characterCode >> 18); output.push(128 | (characterCode >> 12) & 63); output.push(128 | (characterCode >> 6) & 63); output.push(128 | characterCode & 63); return; } }, /** * Returns a String from an array of bytes, with special treatment * if the bytes are UTF-8 bytes (http://en.wikipedia.org/wiki/UTF8) * * @param bytes {Array} the byte array [8it integers] * @param is8bit {Boolean} specifies whether we should not treat the array as a multi byte string * @return {String} the string backed by the byte array */ __getUTF8StringFromBytes : function(bytes, is8bit) { var charString = ''; var result = []; if (is8bit) { result = bytes; } else { for (var i=0; i<bytes.length; i++) { var utfByte = bytes[i]; if (utfByte >> 7 === 0) { result.push(utfByte); } if (utfByte >> 5 === 6) { var nextByte = bytes[++i]; result.push(((utfByte & 28) >> 2) << 8 | ((utfByte & 3) << 6) | nextByte & 63); } if (utfByte >> 4 === 14) { var nextBytes = [ bytes[++i], bytes[++i] ]; result.push((utfByte & 15) << 12 | ((nextBytes[0] & 60) >> 2) << 8 | (nextBytes[0] & 3) << 6 | (nextBytes[1] & 63)); } if (utfByte >> 3 === 30) { var nextBytes = [ bytes[++i], bytes[++i], bytes[++i] ]; result.push((utfByte & 7) << 18 | (utfByte & 48) << 16 | (nextBytes[0] & 15) << 12 | ((nextBytes[1] & 60) >> 2) << 8 | (nextBytes[1] & 3) << 6 | (nextBytes[2] & 63)); } } } for (var i=0, l=result.length; i<l; i++) { charString += String.fromCharCode(result[i]); } return charString; }, /** * Decode a base64 string (http://en.wikipedia.org/wiki/Base64). * * @param input {String} the input string to decode * * @param is8bit {Boolean?} Whether the character set is 8-bit, not * multi-byte. If this parameter is not provided, the character set is * determined from the 'document' object. * * @return {String} The decoded input string. */ decode : function(input, is8bit) { var base64Chars = this.__base64Chars; var isMultiByte; if (typeof is8bit == "undefined") { var charSet = document.characterSet || document.charset; isMultiByte = charSet.toLowerCase().indexOf('utf') != -1; if (!isMultiByte && window.atob instanceof Function) { return atob(input); } } else { isMultiByte = ! is8bit; } var ilength = input.length; var stringBytes = [], i = 0; while (i < ilength) { var base64Byte1 = base64Chars.indexOf(input.charAt(i++)); var base64Byte2 = base64Chars.indexOf(input.charAt(i++)); var c1 = base64Byte1 << 2 | base64Byte2 >> 4; stringBytes.push(c1); var specialChar = input.charAt(i++); if (specialChar !== '=') { var base64Byte3 = base64Chars.indexOf(specialChar); var c2 = (base64Byte2 & 15) << 4 | (base64Byte3 & 60) >> 2; stringBytes.push(c2); } specialChar = input.charAt(i++); if (specialChar !== '=') { var base64Byte4 = base64Chars.indexOf(specialChar); var c3 = (base64Byte3 & 3) << 6 | base64Byte4; stringBytes.push(c3); } } return this.__getUTF8StringFromBytes(stringBytes, !isMultiByte); } } });