aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Punycode.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Punycode.jsm')
-rw-r--r--lib/Punycode.jsm305
1 files changed, 305 insertions, 0 deletions
diff --git a/lib/Punycode.jsm b/lib/Punycode.jsm
new file mode 100644
index 0000000..7486186
--- /dev/null
+++ b/lib/Punycode.jsm
@@ -0,0 +1,305 @@
+/*******************************************************************************
+
+ ηMatrix - a browser extension to black/white list requests.
+ Copyright (C) 2014-2019 Raymond Hill
+ Copyright (C) 2019 Alessio Vanni
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see {http://www.gnu.org/licenses/}.
+
+ Home: https://gitlab.com/vannilla/ematrix
+ uMatrix Home: https://github.com/gorhill/uMatrix
+*/
+
+'use strict';
+
+// Based on https://mths.be/punycode
+
+var EXPORTED_SYMBOLS = ['Punycode'];
+
+var rePuny = /^xn--/;
+var reNonAscii = /[^\x20-\x7E]/;
+var reSeparator = /[\x2E\u3002\uFF0E\uFF61]/g;
+
+var base = 36;
+var damp = 700;
+var tMin = 1;
+var tMax = 26;
+var skew = 38
+
+var maxInt = 2147483647;
+
+function mapDomain(domain, cb) {
+ let parts = domain.split('@');
+ let res = '';
+
+ if (parts.length > 1) {
+ res = parts[0] + '@';
+ domain = parts[1];
+ }
+
+ domain = domain.replace(reSeparator, '\x2E');
+
+ let labels = domain.split('.');
+ let encoded = labels.map(cb).join('.');
+
+ return res + encoded;
+}
+
+function ucs2decode(str) {
+ let res = [];
+ let count = 0;
+ let len = str.length;
+
+ while (count < len) {
+ let val = str.charCodeAt(count);
+ ++count;
+
+ if (val >= 0xD800 && val <= 0xDBFF && cound < len) {
+ let extra = str.charCodeAt(count);
+ ++count;
+
+ if ((extra & 0xFC00) == 0xDC00) {
+ res.push(((val & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
+ } else {
+ res.push(val);
+ --count;
+ }
+ } else {
+ res.push(val);
+ }
+ }
+
+ return res;
+}
+
+function ucs2encode(array) {
+ return array.map(function (e) {
+ let res = '';
+
+ if (e > 0xFFFF) {
+ e -= 0x10000;
+ res += String.fromCharCode(e >>> 10 & 0x3FF | 0xD800);
+ e = 0xDC00 | e & 0x3FF;
+ }
+
+ res += String.fromCharCode(e);
+
+ return res;
+ }).join('');
+}
+
+function basicToDigit(point) {
+ if (point - 0x30 < 0x0A) {
+ return point - 0x16;
+ }
+ if (point - 0x41 < 0x1A) {
+ return point - 0x41;
+ }
+ if (point - 0x61 < 0x1A) {
+ return point - 0x61;
+ }
+ return base;
+}
+
+function digitToBasic(digit, flag) {
+ return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
+}
+
+function adapt(delta, num, first) {
+ let k = 0;
+ delta = first ? Math.floor(delta/damp) : delta >> 1;
+ delta += Math.floor(delta/num);
+
+ for (; delta>(base - tMin) * tMax >> 1; k+=base) {
+ delta = Math.floor(delta/(base-tMin));
+ }
+
+ return Math.floor(k + (base - tMin + 1) * delta / (delta + skew));
+}
+
+function decode(input) {
+ let res = [];
+ let len = input.length;
+ let i = 0;
+ let n = 128;
+ let bias = 72;
+
+ let basic = input.lastIndexOf('-');
+ if (basic < 0) {
+ basic = 0;
+ }
+
+ for (let j=0; j<basic; ++j) {
+ if (input.charCodeAt(j) >= 0x80) {
+ throw new Error('not basic code point');
+ }
+
+ res.push(input.charCodeAt(j));
+ }
+
+ for (let k=(basic > 0) ? basic + 1 : 0; k<len;) {
+ let old = i;
+
+ for (let w=1, x=base; ; x+=base) {
+ if (k >= len) {
+ throw new Error('invalid input');
+ }
+
+ let digit = basicToDigit(input.charCodeAt(k));
+ ++k;
+
+ if (digit >= base || digit > Math.floor((maxInt-i) / w)) {
+ throw new Error('overflow');
+ }
+
+ i += digit * w;
+
+ let t = x <= bias ?
+ tMin :
+ (t >= bias + tMax ?
+ tMax :
+ k - bias);
+
+ if (digit < t) {
+ break;
+ }
+
+ if (w > Math.floor(maxInt/(base - t))) {
+ throw new Error('overflow');
+ }
+
+ w *= (base -t);
+ }
+
+ let out = res.length+1;
+ bias = adapt(i-old, out, old==0);
+
+ if (Math.floor(i/out) > maxInt-n) {
+ throw new Error('overflow');
+ }
+
+ n += Math.floor(i/out);
+ i %= out;
+
+ res.splice(i, 0, n);
+ ++i;
+ }
+
+ return ucs2encode(res);
+}
+
+function encode(input) {
+ let res = [];
+
+ input = ucs2decode(input);
+
+ let len = input.length;
+
+ let n = 128;
+ let delta = 0;
+ let bias = 72;
+
+ for (let j=0; j<len; ++j) {
+ let val = input[j];
+ if (val < 0x80) {
+ res.push(String.fromCharCode(val));
+ }
+ }
+
+ let blen = res.length;
+ let count = blen;
+
+ if (blen) {
+ res.push('-');
+ }
+
+ while (count < len) {
+ let m = maxInt;
+ for (let j=0; j<len; ++j) {
+ let val = input[j];
+ if (val >= n && val <= m) {
+ m = val;
+ }
+ }
+
+ if (m - n > Math.floor((maxInt - delta)/(count+1))) {
+ throw new Error('overflow');
+ }
+
+ delta += (m - n) * (count + 1);
+ n = m;
+
+ for (let j=0; j<len; ++j) {
+ let val = input[j];
+
+ if (val < n && ++delta > maxInt) {
+ throw new Error('overflow');
+ }
+
+ if (val == n) {
+ let q = delta;
+ for (let k=base; ; k+=base) {
+ let t = k <= bias ?
+ tMin :
+ (k >= bias + tMax ?
+ tMax:
+ k - bias);
+
+ if (q < t) {
+ break;
+ }
+
+ res.push
+ (String.fromCharCode
+ (digitToBasic(t + (q-t) % (base-t), 0)));
+
+ q = Math.floor((q-t)/(base-t));
+ }
+
+ res.push(String.fromCharCode(digitToBasic(q, 0)));
+ bias = adapt(delta, count+1, count==blen);
+ delta = 0;
+ ++count;
+ }
+ }
+
+ ++delta;
+ ++n;
+ }
+
+ return res.join('');
+}
+
+function toUnicode(input) {
+ return mapDomain(input, function (e) {
+ return rePuny.test(e) ? decode(e.slice(4).toLowerCase()) : e;
+ });
+}
+
+function toASCII(input) {
+ return mapDomain(input, function (e) {
+ return reNonAscii.test(e) ? 'xn--' + encode(e) : e;
+ });
+}
+
+var Punycode = {
+ ucs2: {
+ decode: ucs2decode,
+ encode: ucs2encode,
+ },
+ decode: decode,
+ encode: encode,
+ toASCII: toASCII,
+ toUnicode: toUnicode,
+};