From 284aac2883ec492f3ba501f827f73c2f654460a1 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Fri, 14 Aug 2015 05:08:54 -0400 Subject: [PATCH] Really make base64 encoding unicode-aware --- program/js/common.js | 67 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 59 insertions(+), 8 deletions(-) diff --git a/program/js/common.js b/program/js/common.js index 2c699d0f6..7a0c3036f 100644 --- a/program/js/common.js +++ b/program/js/common.js @@ -683,12 +683,61 @@ rcube_parse_query = function(query) }; -// This code was written by Tyler Akins and has been placed in the -// public domain. It would be nice if you left this header intact. // Base64 code from Tyler Akins -- http://rumkin.com var Base64 = (function () { var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + // private method for UTF-8 encoding + var utf8_encode = function(string) { + string = string.replace(/\r\n/g, "\n"); + var utftext = ''; + + for (var n = 0; n < string.length; n++) { + var c = string.charCodeAt(n); + + if (c < 128) { + utftext += String.fromCharCode(c); + } + else if(c > 127 && c < 2048) { + utftext += String.fromCharCode((c >> 6) | 192); + utftext += String.fromCharCode((c & 63) | 128); + } + else { + utftext += String.fromCharCode((c >> 12) | 224); + utftext += String.fromCharCode(((c >> 6) & 63) | 128); + utftext += String.fromCharCode((c & 63) | 128); + } + } + + return utftext; + }; + + // private method for UTF-8 decoding + var utf8_decode = function (utftext) { + var i = 0, string = '', c = c2 = c3 = 0; + + while (i < utftext.length) { + c = utftext.charCodeAt(i); + if (c < 128) { + string += String.fromCharCode(c); + i++; + } + else if (c > 191 && c < 224) { + c2 = utftext.charCodeAt(i + 1); + string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); + i += 2; + } + else { + c2 = utftext.charCodeAt(i + 1); + c3 = utftext.charCodeAt(i + 2); + string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); + i += 3; + } + } + + return string; + }; + var obj = { /** * Encodes a string in base64 @@ -703,9 +752,11 @@ var Base64 = (function () { catch (e) {}; } + input = utf8_encode(input); + var chr1, chr2, chr3, enc1, enc2, enc3, enc4, i = 0, output = '', len = input.length; - do { + while (i < len) { chr1 = input.charCodeAt(i++); chr2 = input.charCodeAt(i++); chr3 = input.charCodeAt(i++); @@ -723,7 +774,7 @@ var Base64 = (function () { output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4); - } while (i < len); + } return output; }, @@ -736,7 +787,7 @@ var Base64 = (function () { if (typeof(window.atob) === 'function') { // it may fail on unicode characters, the fallback can handle them try { - return atob(input); + return utf8_decode(atob(input)); } catch (e) {}; } @@ -747,7 +798,7 @@ var Base64 = (function () { input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); len = input.length; - do { + while (i < len) { enc1 = keyStr.indexOf(input.charAt(i++)); enc2 = keyStr.indexOf(input.charAt(i++)); enc3 = keyStr.indexOf(input.charAt(i++)); @@ -763,9 +814,9 @@ var Base64 = (function () { output = output + String.fromCharCode(chr2); if (enc4 != 64) output = output + String.fromCharCode(chr3); - } while (i < len); + } - return output; + return utf8_decode(output); } };