@qooxdoo/framework
Version:
The JS Framework for Coders
318 lines (277 loc) • 8.27 kB
JavaScript
/* ************************************************************************
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(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(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(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(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);
}
}
});