diff --git a/LICENSE b/LICENSE.txt
similarity index 100%
rename from LICENSE
rename to LICENSE.txt
diff --git a/platform/chromium/manifest.json b/platform/chromium/manifest.json
index 7df8b94..b454c4e 100644
--- a/platform/chromium/manifest.json
+++ b/platform/chromium/manifest.json
@@ -1,6 +1,6 @@
{
"manifest_version": 2,
- "name": "__MSG_extName__",
+ "name": "µMatrix",
"short_name": "µMatrix",
"version": "0.8.1.4",
"description": "__MSG_extShortDesc__",
@@ -12,7 +12,7 @@
"default_icon": {
"19": "img/browsericons/icon19-off.png"
},
- "default_title": "__MSG_extName__",
+ "default_title": "µMatrix",
"default_popup": "popup.html"
},
"author": "Raymond Hill",
diff --git a/platform/firefox/img/browsericons/icon19-19.png b/platform/firefox/img/browsericons/icon19-19.png
new file mode 100644
index 0000000..500242b
Binary files /dev/null and b/platform/firefox/img/browsericons/icon19-19.png differ
diff --git a/platform/firefox/img/browsericons/icon19-off.png b/platform/firefox/img/browsericons/icon19-off.png
new file mode 100644
index 0000000..036a7a3
Binary files /dev/null and b/platform/firefox/img/browsericons/icon19-off.png differ
diff --git a/platform/firefox/vapi-background.js b/platform/firefox/vapi-background.js
index 691893a..bcc0f81 100644
--- a/platform/firefox/vapi-background.js
+++ b/platform/firefox/vapi-background.js
@@ -49,6 +49,16 @@ vAPI.app = {
/******************************************************************************/
+vAPI.app.start = function() {
+};
+
+/******************************************************************************/
+
+vAPI.app.stop = function() {
+};
+
+/******************************************************************************/
+
vAPI.app.restart = function() {
// Listening in bootstrap.js
Cc['@mozilla.org/childprocessmessagemanager;1']
@@ -454,7 +464,7 @@ vAPI.tabs.getTabsForIds = function(tabIds) {
if ( singleTab ) {
tabIds = [tabIds];
}
- for ( var tab of this.getAll() ) {
+ for ( var tab of this.getAllSync() ) {
var tabId = this.stack.get(getBrowserForTab(tab));
if ( !tabId ) {
continue;
@@ -513,7 +523,7 @@ vAPI.tabs.get = function(tabId, callback) {
/******************************************************************************/
-vAPI.tabs.getAll = function(window) {
+vAPI.tabs.getAllSync = function(window) {
var win, tab;
var tabs = [];
@@ -537,6 +547,27 @@ vAPI.tabs.getAll = function(window) {
/******************************************************************************/
+vAPI.tabs.getAll = function(callback) {
+ var tabs = [];
+ var win, tab;
+
+ for ( win of this.getWindows() ) {
+ var tabBrowser = getTabBrowser(win);
+ if ( tabBrowser === null ) {
+ continue;
+ }
+ for ( tab of tabBrowser.tabs ) {
+ tabs.push({
+ id: this.getTabId(tab),
+ url: getBrowserForTab(tab).currentURI.asciiSpec
+ });
+ }
+ }
+ callback(tabs);
+};
+
+/******************************************************************************/
+
vAPI.tabs.getWindows = function() {
var winumerator = Services.wm.getEnumerator('navigator:browser');
var windows = [];
@@ -575,7 +606,7 @@ vAPI.tabs.open = function(details) {
if ( details.select ) {
var URI = Services.io.newURI(details.url, null, null);
- for ( tab of this.getAll() ) {
+ for ( tab of this.getAllSync() ) {
var browser = getBrowserForTab(tab);
// Or simply .equals if we care about the fragment
@@ -712,10 +743,12 @@ vAPI.tabs.injectScript = function(tabId, details, callback) {
/******************************************************************************/
-vAPI.setIcon = function(tabId, iconStatus, badge) {
+vAPI.setIcon = function(tabId, iconId, badge) {
+ var iconStatus = typeof iconId === 'number';
+
// If badge is undefined, then setIcon was called from the TabSelect event
var win = badge === undefined
- ? iconStatus
+ ? iconId
: Services.wm.getMostRecentWindow('navigator:browser');
var curTabId = vAPI.tabs.getTabId(getTabBrowser(win).selectedTab);
var tb = vAPI.toolbarButton;
@@ -1030,7 +1063,10 @@ var httpObserver = {
var onBeforeRequest = vAPI.net.onBeforeRequest;
var type = this.typeMap[details.type] || 'other';
- if ( onBeforeRequest.types.has(type) === false ) {
+ if (
+ onBeforeRequest.types.size !== 0 &&
+ onBeforeRequest.types.has(type) === false
+ ) {
return false;
}
@@ -1239,7 +1275,7 @@ vAPI.net.registerListeners = function() {
// Popup candidate
if ( details.openerURL ) {
- for ( var tab of vAPI.tabs.getAll() ) {
+ for ( var tab of vAPI.tabs.getAllSync() ) {
var URI = getBrowserForTab(tab).currentURI;
// Probably isn't the best method to identify the source tab
@@ -1306,7 +1342,7 @@ vAPI.net.registerListeners = function() {
tabId: tabId,
url: details.url,
});
- }
+ };
vAPI.messaging.globalMessageManager.addMessageListener(
locationChangedListenerMessageName,
@@ -1356,7 +1392,7 @@ vAPI.toolbarButton.init = function() {
this.styleURI = [
'#' + this.id + ' {',
'list-style-image: url(',
- vAPI.getURL('img/browsericons/icon16-off.svg'),
+ vAPI.getURL('img/browsericons/icon19-off.png'),
');',
'}',
'#' + this.viewId + ', #' + this.viewId + ' > iframe {',
@@ -1568,7 +1604,7 @@ vAPI.toolbarButton.updateState = function(win, tabId) {
icon = '';
}
else {
- icon = 'url(' + vAPI.getURL('img/browsericons/icon16.svg') + ')';
+ icon = 'url(' + vAPI.getURL('img/browsericons/icon19-19.png') + ')';
}
button.style.listStyleImage = icon;
@@ -1648,7 +1684,7 @@ vAPI.contextMenu.register = function(doc) {
var menuitem = doc.createElement('menuitem');
menuitem.setAttribute('id', this.menuItemId);
menuitem.setAttribute('label', this.menuLabel);
- menuitem.setAttribute('image', vAPI.getURL('img/browsericons/icon16.svg'));
+ menuitem.setAttribute('image', vAPI.getURL('img/browsericons/icon19-19.png'));
menuitem.setAttribute('class', 'menuitem-iconic');
menuitem.addEventListener('command', this.onCommand);
contextMenu.addEventListener('popupshowing', this.displayMenuItem);
@@ -1788,7 +1824,7 @@ vAPI.lastError = function() {
vAPI.onLoadAllCompleted = function() {
var µb = µBlock;
- for ( var tab of this.tabs.getAll() ) {
+ for ( var tab of this.tabs.getAllSync() ) {
// We're insterested in only the tabs that were already loaded
var tabId = this.tabs.getTabId(tab);
var browser = getBrowserForTab(tab);
@@ -1821,6 +1857,49 @@ vAPI.punycodeURL = function(url) {
/******************************************************************************/
+/******************************************************************************/
+
+vAPI.browserCache = {};
+
+/******************************************************************************/
+
+vAPI.browserCache.clearByTime = function(since) {
+ // TODO
+};
+
+vAPI.browserCache.clearByOrigin = function(/* domain */) {
+ // TODO
+};
+
+/******************************************************************************/
+
+vAPI.cookies = {};
+
+/******************************************************************************/
+
+vAPI.cookies.registerListeners = function() {
+ // TODO
+};
+
+/******************************************************************************/
+
+vAPI.cookies.getAll = function(callback) {
+ // TODO
+ if ( typeof callback === 'function' ) {
+ callback([]);
+ }
+};
+
+/******************************************************************************/
+
+vAPI.cookies.remove = function(details, callback) {
+ // TODO
+ if ( typeof callback === 'function' ) {
+ callback();
+ }
+};
+/******************************************************************************/
+
})();
/******************************************************************************/
diff --git a/src/background.html b/src/background.html
index adee2b0..026f61e 100644
--- a/src/background.html
+++ b/src/background.html
@@ -5,9 +5,9 @@
µMatrix
-
-
-
+
+
+
diff --git a/src/css/popup.css b/src/css/popup.css
index 4caafbf..ce53cf7 100644
--- a/src/css/popup.css
+++ b/src/css/popup.css
@@ -1,11 +1,13 @@
body {
- margin: 0;
+ background-color: white;
border: 0;
- padding: 0;
+ float: left;
font: 13px httpsb,sans-serif;
- background-color: white;
+ margin: 0;
+ min-height: 16em;
min-width: 32em;
- min-height: 15em;
+ overflow: hidden;
+ padding: 0;
}
*:focus {
outline: none;
@@ -396,8 +398,8 @@ body.tScopeSite #scopeCell {
padding: 0;
border: 0;
height: 6px;
- background: url('/img/matrix-group-hide.png') no-repeat center top,
- url('/img/matrix-group-hline.png') repeat-x center top 3px;
+ background: url('img/matrix-group-hide.png') no-repeat center top,
+ url('img/matrix-group-hline.png') repeat-x center top 3px;
opacity: 0.2;
cursor: pointer;
}
@@ -405,8 +407,8 @@ body.tScopeSite #scopeCell {
opacity: 0.4;
}
.matrix .g4Meta.g4Collapsed {
- background: url('/img/matrix-group-show.png') no-repeat center top,
- url('/img/matrix-group-hline.png') repeat-x center top 3px;
+ background: url('img/matrix-group-show.png') no-repeat center top,
+ url('img/matrix-group-hline.png') repeat-x center top 3px;
}
.matrix .g4Meta.g4Collapsed ~ .matSection {
display: none;
@@ -448,12 +450,12 @@ body.powerOff .matrix .g4Meta.g4Collapsed ~ .matRow.ro {
background-color: #d0f0d0;
}
.matCell.p81 {
- background-image: url('/img/permanent-black-small.png');
+ background-image: url('img/permanent-black-small.png');
background-repeat: no-repeat;
background-position: -1px -1px;
}
.matCell.p82 {
- background-image: url('/img/permanent-white-small.png');
+ background-image: url('img/permanent-white-small.png');
background-repeat: no-repeat;
background-position: -1px -1px;
}
@@ -479,10 +481,10 @@ body.colorblind .t2 {
background-color: #ccc;
}
body.colorblind .matCell.p81 {
- background-image: url('/img/permanent-black-small-cb.png');
+ background-image: url('img/permanent-black-small-cb.png');
}
body.colorblind .matCell.p82 {
- background-image: url('/img/permanent-white-small-cb.png');
+ background-image: url('img/permanent-white-small-cb.png');
}
diff --git a/src/lib/publicsuffixlist.js b/src/lib/publicsuffixlist.js
new file mode 100644
index 0000000..fa18037
--- /dev/null
+++ b/src/lib/publicsuffixlist.js
@@ -0,0 +1,326 @@
+/*******************************************************************************
+
+ publicsuffixlist.js - an efficient javascript implementation to deal with
+ Mozilla Foundation's Public Suffix List
+ Copyright (C) 2013 Raymond Hill
+
+ 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://github.com/gorhill/publicsuffixlist.js */
+
+/*
+ This code is mostly dumb: I consider this to be lower-level code, thus
+ in order to ensure efficiency, the caller is responsible for sanitizing
+ the inputs.
+*/
+
+/******************************************************************************/
+
+// A single instance of PublicSuffixList is enough.
+
+;(function(root) {
+
+/******************************************************************************/
+
+var exceptions = {};
+var rules = {};
+var selfieMagic = 'iscjsfsaolnm';
+
+// This value dictate how the search will be performed:
+// < this.cutoffLength = indexOf()
+// >= this.cutoffLength = binary search
+var cutoffLength = 256;
+var mustPunycode = /[^a-z0-9.-]/;
+
+/******************************************************************************/
+
+// In the context of this code, a domain is defined as:
+// "{label}.{public suffix}".
+// A single standalone label is a public suffix as per
+// http://publicsuffix.org/list/:
+// "If no rules match, the prevailing rule is '*' "
+// This means 'localhost' is not deemed a domain by this
+// code, since according to the definition above, it would be
+// evaluated as a public suffix. The caller is therefore responsible to
+// decide how to further interpret such public suffix.
+//
+// `hostname` must be a valid ascii-based hostname.
+
+function getDomain(hostname) {
+ // A hostname starting with a dot is not a valid hostname.
+ if ( !hostname || hostname.charAt(0) === '.' ) {
+ return '';
+ }
+ hostname = hostname.toLowerCase();
+ var suffix = getPublicSuffix(hostname);
+ if ( suffix === hostname ) {
+ return '';
+ }
+ var pos = hostname.lastIndexOf('.', hostname.lastIndexOf('.', hostname.length - suffix.length) - 1);
+ if ( pos <= 0 ) {
+ return hostname;
+ }
+ return hostname.slice(pos + 1);
+}
+
+/******************************************************************************/
+
+// Return longest public suffix.
+//
+// `hostname` must be a valid ascii-based string which respect hostname naming.
+
+function getPublicSuffix(hostname) {
+ if ( !hostname ) {
+ return '';
+ }
+ // Since we slice down the hostname with each pass, the first match
+ // is the longest, so no need to find all the matching rules.
+ var pos;
+ while ( true ) {
+ pos = hostname.indexOf('.');
+ if ( pos < 0 ) {
+ return hostname;
+ }
+ if ( search(exceptions, hostname) ) {
+ return hostname.slice(pos + 1);
+ }
+ if ( search(rules, hostname) ) {
+ return hostname;
+ }
+ if ( search(rules, '*' + hostname.slice(pos)) ) {
+ return hostname;
+ }
+ hostname = hostname.slice(pos + 1);
+ }
+ // unreachable
+}
+
+/******************************************************************************/
+
+// Look up a specific hostname.
+
+function search(store, hostname) {
+ // Extract TLD
+ var pos = hostname.lastIndexOf('.');
+ var tld, remainder;
+ if ( pos < 0 ) {
+ tld = hostname;
+ remainder = hostname;
+ } else {
+ tld = hostname.slice(pos + 1);
+ remainder = hostname.slice(0, pos);
+ }
+ var substore = store[tld];
+ if ( !substore ) {
+ return false;
+ }
+ // If substore is a string, use indexOf()
+ if ( typeof substore === 'string' ) {
+ return substore.indexOf(' ' + remainder + ' ') >= 0;
+ }
+ // It is an array: use binary search.
+ var l = remainder.length;
+ var haystack = substore[l];
+ if ( !haystack ) {
+ return false;
+ }
+ var left = 0;
+ var right = Math.floor(haystack.length / l + 0.5);
+ var i, needle;
+ while ( left < right ) {
+ i = left + right >> 1;
+ needle = haystack.substr( l * i, l );
+ if ( remainder < needle ) {
+ right = i;
+ } else if ( remainder > needle ) {
+ left = i + 1;
+ } else {
+ return true;
+ }
+ }
+ return false;
+}
+
+/******************************************************************************/
+
+// Parse and set a UTF-8 text-based suffix list. Format is same as found at:
+// http://publicsuffix.org/list/
+//
+// `toAscii` is a converter from unicode to punycode. Required since the
+// Public Suffix List contains unicode characters.
+// Suggestion: use it's quite good.
+
+function parse(text, toAscii) {
+ exceptions = {};
+ rules = {};
+
+ // http://publicsuffix.org/list/:
+ // "... all rules must be canonicalized in the normal way
+ // for hostnames - lower-case, Punycode ..."
+ text = text.toLowerCase();
+
+ var lineBeg = 0, lineEnd;
+ var textEnd = text.length;
+ var line, store, pos, tld;
+
+ while ( lineBeg < textEnd ) {
+ lineEnd = text.indexOf('\n', lineBeg);
+ if ( lineEnd < 0 ) {
+ lineEnd = text.indexOf('\r', lineBeg);
+ if ( lineEnd < 0 ) {
+ lineEnd = textEnd;
+ }
+ }
+ line = text.slice(lineBeg, lineEnd).trim();
+ lineBeg = lineEnd + 1;
+
+ if ( line.length === 0 ) {
+ continue;
+ }
+
+ // Ignore comments
+ pos = line.indexOf('//');
+ if ( pos >= 0 ) {
+ line = line.slice(0, pos);
+ }
+
+ // Ignore surrounding whitespaces
+ line = line.trim();
+ if ( !line ) {
+ continue;
+ }
+
+ if ( mustPunycode.test(line) ) {
+ line = toAscii(line);
+ }
+
+ // Is this an exception rule?
+ if ( line.charAt(0) === '!' ) {
+ store = exceptions;
+ line = line.slice(1);
+ } else {
+ store = rules;
+ }
+
+ // Extract TLD
+ pos = line.lastIndexOf('.');
+ if ( pos < 0 ) {
+ tld = line;
+ } else {
+ tld = line.slice(pos + 1);
+ line = line.slice(0, pos);
+ }
+
+ // Store suffix using tld as key
+ if ( !store.hasOwnProperty(tld) ) {
+ store[tld] = [];
+ }
+ if ( line ) {
+ store[tld].push(line);
+ }
+ }
+ crystallize(exceptions);
+ crystallize(rules);
+}
+
+/******************************************************************************/
+
+// Cristallize the storage of suffixes using optimal internal representation
+// for future look up.
+
+function crystallize(store) {
+ var suffixes, suffix, i, l;
+
+ for ( var tld in store ) {
+ if ( !store.hasOwnProperty(tld) ) {
+ continue;
+ }
+ suffixes = store[tld].join(' ');
+ // No suffix
+ if ( !suffixes ) {
+ store[tld] = '';
+ continue;
+ }
+ // Concatenated list of suffixes less than cutoff length:
+ // Store as string, lookup using indexOf()
+ if ( suffixes.length < cutoffLength ) {
+ store[tld] = ' ' + suffixes + ' ';
+ continue;
+ }
+ // Concatenated list of suffixes greater or equal to cutoff length
+ // Store as array keyed on suffix length, lookup using binary search.
+ // I borrowed the idea to key on string length here:
+ // http://ejohn.org/blog/dictionary-lookups-in-javascript/#comment-392072
+
+ i = store[tld].length;
+ suffixes = [];
+ while ( i-- ) {
+ suffix = store[tld][i];
+ l = suffix.length;
+ if ( !suffixes[l] ) {
+ suffixes[l] = [];
+ }
+ suffixes[l].push(suffix);
+ }
+ l = suffixes.length;
+ while ( l-- ) {
+ if ( suffixes[l] ) {
+ suffixes[l] = suffixes[l].sort().join('');
+ }
+ }
+ store[tld] = suffixes;
+ }
+ return store;
+}
+
+/******************************************************************************/
+
+function toSelfie() {
+ return {
+ magic: selfieMagic,
+ rules: rules,
+ exceptions: exceptions
+ };
+}
+
+function fromSelfie(selfie) {
+ if ( typeof selfie !== 'object' || typeof selfie.magic !== 'string' || selfie.magic !== selfieMagic ) {
+ return false;
+ }
+ rules = selfie.rules;
+ exceptions = selfie.exceptions;
+ return true;
+}
+
+/******************************************************************************/
+
+// Public API
+
+root = root || window;
+
+root.publicSuffixList = {
+ 'version': '1.0',
+ 'parse': parse,
+ 'getDomain': getDomain,
+ 'getPublicSuffix': getPublicSuffix,
+ 'toSelfie': toSelfie,
+ 'fromSelfie': fromSelfie
+};
+
+/******************************************************************************/
+
+})(this);
+
diff --git a/src/lib/publicsuffixlist.min.js b/src/lib/publicsuffixlist.min.js
deleted file mode 100644
index a2607d4..0000000
--- a/src/lib/publicsuffixlist.min.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/*! Home: https://github.com/gorhill/publicsuffixlist.js */
-;(function(f){var b={};var h={};var a=480;
-var g=/[^a-z0-9.-]/;function i(k){if(!k||k.charAt(0)==="."){return""}k=k.toLowerCase();var l=c(k);if(l===k){return""
-}var m=k.lastIndexOf(".",k.lastIndexOf(".",k.length-l.length)-1);if(m<=0){return k}return k.slice(m+1)
-}function c(k){if(!k){return""}var l;while(true){l=k.indexOf(".");if(l<0){return k}if(j(b,k)){return k.slice(l+1)
-}if(j(h,k)){return k}if(j(h,"*"+k.slice(l))){return k}k=k.slice(l+1)}}function j(t,r){var q=r.lastIndexOf(".");
-var m,v;if(q<0){m=r;v=r}else{m=r.slice(q+1);v=r.slice(0,q)}var s=t[m];if(!s){return false}if(typeof s==="string"){return s.indexOf(" "+v+" ")>=0
-}var n=v.length;var w=s[n];if(!w){return false}var k=0;var u=Math.floor(w.length/n+0.5);var p,o;while(k>1;
-o=w.substr(n*p,n);if(vo){k=p+1}else{return true}}}return false}function d(r,p){b={};
-h={};r=r.toLowerCase();var o=0,l;var m=r.length;var s,q,n,k;while(o=0){s=s.slice(0,n)}s=s.trim();
-if(!s){continue}if(g.test(s)){s=p(s)}if(s.charAt(0)==="!"){q=b;s=s.slice(1)}else{q=h}n=s.lastIndexOf(".");
-if(n<0){k=s}else{k=s.slice(n+1);s=s.slice(0,n)}if(!q[k]){q[k]=[]}if(s){q[k].push(s)}}e(b);e(h)}function e(m){var o,q,p,k;
-for(var n in m){if(!m.hasOwnProperty(n)){continue}o=m[n].join(" ");if(!o){m[n]="";continue}if(o.length= 0x80 (not a basic code point)',
+ 'invalid-input': 'Invalid input'
+ },
+
+ /** Convenience shortcuts */
+ baseMinusTMin = base - tMin,
+ floor = Math.floor,
+ stringFromCharCode = String.fromCharCode,
+
+ /** Temporary variable */
+ key;
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * A generic error utility function.
+ * @private
+ * @param {String} type The error type.
+ * @returns {Error} Throws a `RangeError` with the applicable error message.
+ */
+ function error(type) {
+ throw RangeError(errors[type]);
+ }
+
+ /**
+ * A generic `Array#map` utility function.
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} callback The function that gets called for every array
+ * item.
+ * @returns {Array} A new array of values returned by the callback function.
+ */
+ function map(array, fn) {
+ var length = array.length;
+ var result = [];
+ while (length--) {
+ result[length] = fn(array[length]);
+ }
+ return result;
+ }
+
+ /**
+ * A simple `Array#map`-like wrapper to work with domain name strings or email
+ * addresses.
+ * @private
+ * @param {String} domain The domain name or email address.
+ * @param {Function} callback The function that gets called for every
+ * character.
+ * @returns {Array} A new string of characters returned by the callback
+ * function.
+ */
+ function mapDomain(string, fn) {
+ var parts = string.split('@');
+ var result = '';
+ if (parts.length > 1) {
+ // In email addresses, only the domain name should be punycoded. Leave
+ // the local part (i.e. everything up to `@`) intact.
+ result = parts[0] + '@';
+ string = parts[1];
+ }
+ // Avoid `split(regex)` for IE8 compatibility. See #17.
+ string = string.replace(regexSeparators, '\x2E');
+ var labels = string.split('.');
+ var encoded = map(labels, fn).join('.');
+ return result + encoded;
+ }
+
+ /**
+ * Creates an array containing the numeric code points of each Unicode
+ * character in the string. While JavaScript uses UCS-2 internally,
+ * this function will convert a pair of surrogate halves (each of which
+ * UCS-2 exposes as separate characters) into a single code point,
+ * matching UTF-16.
+ * @see `punycode.ucs2.encode`
+ * @see
+ * @memberOf punycode.ucs2
+ * @name decode
+ * @param {String} string The Unicode input string (UCS-2).
+ * @returns {Array} The new array of code points.
+ */
+ function ucs2decode(string) {
+ var output = [],
+ counter = 0,
+ length = string.length,
+ value,
+ extra;
+ while (counter < length) {
+ value = string.charCodeAt(counter++);
+ if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
+ // high surrogate, and there is a next character
+ extra = string.charCodeAt(counter++);
+ if ((extra & 0xFC00) == 0xDC00) { // low surrogate
+ output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
+ } else {
+ // unmatched surrogate; only append this code unit, in case the next
+ // code unit is the high surrogate of a surrogate pair
+ output.push(value);
+ counter--;
+ }
+ } else {
+ output.push(value);
+ }
+ }
+ return output;
+ }
+
+ /**
+ * Creates a string based on an array of numeric code points.
+ * @see `punycode.ucs2.decode`
+ * @memberOf punycode.ucs2
+ * @name encode
+ * @param {Array} codePoints The array of numeric code points.
+ * @returns {String} The new Unicode string (UCS-2).
+ */
+ function ucs2encode(array) {
+ return map(array, function(value) {
+ var output = '';
+ if (value > 0xFFFF) {
+ value -= 0x10000;
+ output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
+ value = 0xDC00 | value & 0x3FF;
+ }
+ output += stringFromCharCode(value);
+ return output;
+ }).join('');
+ }
+
+ /**
+ * Converts a basic code point into a digit/integer.
+ * @see `digitToBasic()`
+ * @private
+ * @param {Number} codePoint The basic numeric code point value.
+ * @returns {Number} The numeric value of a basic code point (for use in
+ * representing integers) in the range `0` to `base - 1`, or `base` if
+ * the code point does not represent a value.
+ */
+ function basicToDigit(codePoint) {
+ if (codePoint - 48 < 10) {
+ return codePoint - 22;
+ }
+ if (codePoint - 65 < 26) {
+ return codePoint - 65;
+ }
+ if (codePoint - 97 < 26) {
+ return codePoint - 97;
+ }
+ return base;
+ }
+
+ /**
+ * Converts a digit/integer into a basic code point.
+ * @see `basicToDigit()`
+ * @private
+ * @param {Number} digit The numeric value of a basic code point.
+ * @returns {Number} The basic code point whose value (when used for
+ * representing integers) is `digit`, which needs to be in the range
+ * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
+ * used; else, the lowercase form is used. The behavior is undefined
+ * if `flag` is non-zero and `digit` has no uppercase form.
+ */
+ function digitToBasic(digit, flag) {
+ // 0..25 map to ASCII a..z or A..Z
+ // 26..35 map to ASCII 0..9
+ return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
+ }
+
+ /**
+ * Bias adaptation function as per section 3.4 of RFC 3492.
+ * http://tools.ietf.org/html/rfc3492#section-3.4
+ * @private
+ */
+ function adapt(delta, numPoints, firstTime) {
+ var k = 0;
+ delta = firstTime ? floor(delta / damp) : delta >> 1;
+ delta += floor(delta / numPoints);
+ for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
+ delta = floor(delta / baseMinusTMin);
+ }
+ return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
+ }
+
+ /**
+ * Converts a Punycode string of ASCII-only symbols to a string of Unicode
+ * symbols.
+ * @memberOf punycode
+ * @param {String} input The Punycode string of ASCII-only symbols.
+ * @returns {String} The resulting string of Unicode symbols.
+ */
+ function decode(input) {
+ // Don't use UCS-2
+ var output = [],
+ inputLength = input.length,
+ out,
+ i = 0,
+ n = initialN,
+ bias = initialBias,
+ basic,
+ j,
+ index,
+ oldi,
+ w,
+ k,
+ digit,
+ t,
+ /** Cached calculation results */
+ baseMinusT;
+
+ // Handle the basic code points: let `basic` be the number of input code
+ // points before the last delimiter, or `0` if there is none, then copy
+ // the first basic code points to the output.
+
+ basic = input.lastIndexOf(delimiter);
+ if (basic < 0) {
+ basic = 0;
+ }
+
+ for (j = 0; j < basic; ++j) {
+ // if it's not a basic code point
+ if (input.charCodeAt(j) >= 0x80) {
+ error('not-basic');
+ }
+ output.push(input.charCodeAt(j));
+ }
+
+ // Main decoding loop: start just after the last delimiter if any basic code
+ // points were copied; start at the beginning otherwise.
+
+ for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
+
+ // `index` is the index of the next character to be consumed.
+ // Decode a generalized variable-length integer into `delta`,
+ // which gets added to `i`. The overflow checking is easier
+ // if we increase `i` as we go, then subtract off its starting
+ // value at the end to obtain `delta`.
+ for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
+
+ if (index >= inputLength) {
+ error('invalid-input');
+ }
+
+ digit = basicToDigit(input.charCodeAt(index++));
+
+ if (digit >= base || digit > floor((maxInt - i) / w)) {
+ error('overflow');
+ }
+
+ i += digit * w;
+ t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+
+ if (digit < t) {
+ break;
+ }
+
+ baseMinusT = base - t;
+ if (w > floor(maxInt / baseMinusT)) {
+ error('overflow');
+ }
+
+ w *= baseMinusT;
+
+ }
+
+ out = output.length + 1;
+ bias = adapt(i - oldi, out, oldi == 0);
+
+ // `i` was supposed to wrap around from `out` to `0`,
+ // incrementing `n` each time, so we'll fix that now:
+ if (floor(i / out) > maxInt - n) {
+ error('overflow');
+ }
+
+ n += floor(i / out);
+ i %= out;
+
+ // Insert `n` at position `i` of the output
+ output.splice(i++, 0, n);
+
+ }
+
+ return ucs2encode(output);
+ }
+
+ /**
+ * Converts a string of Unicode symbols (e.g. a domain name label) to a
+ * Punycode string of ASCII-only symbols.
+ * @memberOf punycode
+ * @param {String} input The string of Unicode symbols.
+ * @returns {String} The resulting Punycode string of ASCII-only symbols.
+ */
+ function encode(input) {
+ var n,
+ delta,
+ handledCPCount,
+ basicLength,
+ bias,
+ j,
+ m,
+ q,
+ k,
+ t,
+ currentValue,
+ output = [],
+ /** `inputLength` will hold the number of code points in `input`. */
+ inputLength,
+ /** Cached calculation results */
+ handledCPCountPlusOne,
+ baseMinusT,
+ qMinusT;
+
+ // Convert the input in UCS-2 to Unicode
+ input = ucs2decode(input);
+
+ // Cache the length
+ inputLength = input.length;
+
+ // Initialize the state
+ n = initialN;
+ delta = 0;
+ bias = initialBias;
+
+ // Handle the basic code points
+ for (j = 0; j < inputLength; ++j) {
+ currentValue = input[j];
+ if (currentValue < 0x80) {
+ output.push(stringFromCharCode(currentValue));
+ }
+ }
+
+ handledCPCount = basicLength = output.length;
+
+ // `handledCPCount` is the number of code points that have been handled;
+ // `basicLength` is the number of basic code points.
+
+ // Finish the basic string - if it is not empty - with a delimiter
+ if (basicLength) {
+ output.push(delimiter);
+ }
+
+ // Main encoding loop:
+ while (handledCPCount < inputLength) {
+
+ // All non-basic code points < n have been handled already. Find the next
+ // larger one:
+ for (m = maxInt, j = 0; j < inputLength; ++j) {
+ currentValue = input[j];
+ if (currentValue >= n && currentValue < m) {
+ m = currentValue;
+ }
+ }
+
+ // Increase `delta` enough to advance the decoder's state to ,
+ // but guard against overflow
+ handledCPCountPlusOne = handledCPCount + 1;
+ if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
+ error('overflow');
+ }
+
+ delta += (m - n) * handledCPCountPlusOne;
+ n = m;
+
+ for (j = 0; j < inputLength; ++j) {
+ currentValue = input[j];
+
+ if (currentValue < n && ++delta > maxInt) {
+ error('overflow');
+ }
+
+ if (currentValue == n) {
+ // Represent delta as a generalized variable-length integer
+ for (q = delta, k = base; /* no condition */; k += base) {
+ t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+ if (q < t) {
+ break;
+ }
+ qMinusT = q - t;
+ baseMinusT = base - t;
+ output.push(
+ stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
+ );
+ q = floor(qMinusT / baseMinusT);
+ }
+
+ output.push(stringFromCharCode(digitToBasic(q, 0)));
+ bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
+ delta = 0;
+ ++handledCPCount;
+ }
+ }
+
+ ++delta;
+ ++n;
+
+ }
+ return output.join('');
+ }
+
+ /**
+ * Converts a Punycode string representing a domain name or an email address
+ * to Unicode. Only the Punycoded parts of the input will be converted, i.e.
+ * it doesn't matter if you call it on a string that has already been
+ * converted to Unicode.
+ * @memberOf punycode
+ * @param {String} input The Punycoded domain name or email address to
+ * convert to Unicode.
+ * @returns {String} The Unicode representation of the given Punycode
+ * string.
+ */
+ function toUnicode(input) {
+ return mapDomain(input, function(string) {
+ return regexPunycode.test(string)
+ ? decode(string.slice(4).toLowerCase())
+ : string;
+ });
+ }
+
+ /**
+ * Converts a Unicode string representing a domain name or an email address to
+ * Punycode. Only the non-ASCII parts of the domain name will be converted,
+ * i.e. it doesn't matter if you call it with a domain that's already in
+ * ASCII.
+ * @memberOf punycode
+ * @param {String} input The domain name or email address to convert, as a
+ * Unicode string.
+ * @returns {String} The Punycode representation of the given domain name or
+ * email address.
+ */
+ function toASCII(input) {
+ return mapDomain(input, function(string) {
+ return regexNonASCII.test(string)
+ ? 'xn--' + encode(string)
+ : string;
+ });
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /** Define the public API */
+ punycode = {
+ /**
+ * A string representing the current Punycode.js version number.
+ * @memberOf punycode
+ * @type String
+ */
+ 'version': '1.3.2',
+ /**
+ * An object of methods to convert from JavaScript's internal character
+ * representation (UCS-2) to Unicode code points, and back.
+ * @see
+ * @memberOf punycode
+ * @type Object
+ */
+ 'ucs2': {
+ 'decode': ucs2decode,
+ 'encode': ucs2encode
+ },
+ 'decode': decode,
+ 'encode': encode,
+ 'toASCII': toASCII,
+ 'toUnicode': toUnicode
+ };
+
+ /** Expose `punycode` */
+ // Some AMD build optimizers, like r.js, check for specific condition patterns
+ // like the following:
+ if (
+ typeof define == 'function' &&
+ typeof define.amd == 'object' &&
+ define.amd
+ ) {
+ define('punycode', function() {
+ return punycode;
+ });
+ } else if (freeExports && freeModule) {
+ if (module.exports == freeExports) { // in Node.js or RingoJS v0.8.0+
+ freeModule.exports = punycode;
+ } else { // in Narwhal or RingoJS v0.7.0-
+ for (key in punycode) {
+ punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
+ }
+ }
+ } else { // in Rhino or a web browser
+ root.punycode = punycode;
+ }
+
+}(this));
diff --git a/src/lib/punycode.min.js b/src/lib/punycode.min.js
deleted file mode 100644
index 4016a00..0000000
--- a/src/lib/punycode.min.js
+++ /dev/null
@@ -1,2 +0,0 @@
-/*! http://mths.be/punycode v1.2.4 by @mathias */
-!function(a){function b(a){throw RangeError(E[a])}function c(a,b){for(var c=a.length;c--;)a[c]=b(a[c]);return a}function d(a,b){return c(a.split(D),b).join(".")}function e(a){for(var b,c,d=[],e=0,f=a.length;f>e;)b=a.charCodeAt(e++),b>=55296&&56319>=b&&f>e?(c=a.charCodeAt(e++),56320==(64512&c)?d.push(((1023&b)<<10)+(1023&c)+65536):(d.push(b),e--)):d.push(b);return d}function f(a){return c(a,function(a){var b="";return a>65535&&(a-=65536,b+=H(a>>>10&1023|55296),a=56320|1023&a),b+=H(a)}).join("")}function g(a){return 10>a-48?a-22:26>a-65?a-65:26>a-97?a-97:t}function h(a,b){return a+22+75*(26>a)-((0!=b)<<5)}function i(a,b,c){var d=0;for(a=c?G(a/x):a>>1,a+=G(a/b);a>F*v>>1;d+=t)a=G(a/F);return G(d+(F+1)*a/(a+w))}function j(a){var c,d,e,h,j,k,l,m,n,o,p=[],q=a.length,r=0,w=z,x=y;for(d=a.lastIndexOf(A),0>d&&(d=0),e=0;d>e;++e)a.charCodeAt(e)>=128&&b("not-basic"),p.push(a.charCodeAt(e));for(h=d>0?d+1:0;q>h;){for(j=r,k=1,l=t;h>=q&&b("invalid-input"),m=g(a.charCodeAt(h++)),(m>=t||m>G((s-r)/k))&&b("overflow"),r+=m*k,n=x>=l?u:l>=x+v?v:l-x,!(n>m);l+=t)o=t-n,k>G(s/o)&&b("overflow"),k*=o;c=p.length+1,x=i(r-j,c,0==j),G(r/c)>s-w&&b("overflow"),w+=G(r/c),r%=c,p.splice(r++,0,w)}return f(p)}function k(a){var c,d,f,g,j,k,l,m,n,o,p,q,r,w,x,B=[];for(a=e(a),q=a.length,c=z,d=0,j=y,k=0;q>k;++k)p=a[k],128>p&&B.push(H(p));for(f=g=B.length,g&&B.push(A);q>f;){for(l=s,k=0;q>k;++k)p=a[k],p>=c&&l>p&&(l=p);for(r=f+1,l-c>G((s-d)/r)&&b("overflow"),d+=(l-c)*r,c=l,k=0;q>k;++k)if(p=a[k],c>p&&++d>s&&b("overflow"),p==c){for(m=d,n=t;o=j>=n?u:n>=j+v?v:n-j,!(o>m);n+=t)x=m-o,w=t-o,B.push(H(h(o+x%w,0))),m=G(x/w);B.push(H(h(m,0))),j=i(d,r,f==g),d=0,++f}++d,++c}return B.join("")}function l(a){return d(a,function(a){return B.test(a)?j(a.slice(4).toLowerCase()):a})}function m(a){return d(a,function(a){return C.test(a)?"xn--"+k(a):a})}var n="object"==typeof exports&&exports,o="object"==typeof module&&module&&module.exports==n&&module,p="object"==typeof global&&global;(p.global===p||p.window===p)&&(a=p);var q,r,s=2147483647,t=36,u=1,v=26,w=38,x=700,y=72,z=128,A="-",B=/^xn--/,C=/[^ -~]/,D=/\x2E|\u3002|\uFF0E|\uFF61/g,E={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},F=t-u,G=Math.floor,H=String.fromCharCode;if(q={version:"1.2.4",ucs2:{decode:e,encode:f},decode:j,encode:k,toASCII:m,toUnicode:l},"function"==typeof define&&"object"==typeof define.amd&&define.amd)define("punycode",function(){return q});else if(n&&!n.nodeType)if(o)o.exports=q;else for(r in q)q.hasOwnProperty(r)&&(n[r]=q[r]);else a.punycode=q}(this);
diff --git a/src/lib/yamd5.js b/src/lib/yamd5.js
new file mode 100644
index 0000000..582b576
--- /dev/null
+++ b/src/lib/yamd5.js
@@ -0,0 +1,402 @@
+/*******************************************************************************
+
+YaMD5 - Yet another MD5 hasher.
+home: https://github.com/gorhill/yamd5.js
+
+I needed an MD5 hasher, and as usual I want small code base, and fast.
+
+Originally found md5-o-matic [1]. It was fast but did not work with Unicode
+strings. Also, eventually realized it was really based on code from
+Joseph Myers [2] with no proper credits given (not nice).
+
+Then I found SparkMD5 [3], which works with Unicode strings, but at a steep
+cost to performance. Also, glancing at the code I saw avoidable redundancies
+causing the code base to be much larger than needed.
+
+So from this point I set out to write my own version, YaMD5 (sorry, I am
+not good with naming projects), of course heavily relying on the original
+code from Joseph Myers [2], and bits from SparkMD5 -- I started to work from
+SparkMD5 implementation, so there might be bits of code original to SparkMD5
+code left in a few places (like say, MD5.end()).
+
+Advantages of YaMD5:
+
+- Can handle Unicode strings
+- Natively incremental
+- Small code base
+- Fastest MD5 hasher out there so far for large input [4]
+- Even faster than versions supporting only simpler ascii strings
+
+
+ [1] https://github.com/trentmillar/md5-o-matic
+ [2] http://www.myersdaily.org/joseph/javascript/md5-text.html
+ [3] https://github.com/satazor/SparkMD5
+ [4] http://jsperf.com/md5-shootout/75
+
+So with that said, I don't know what license covers Joseph Myers' code (need
+to find out). In any case, concerning whatever original code I contributed in
+there:
+
+The MIT License (MIT)
+
+Copyright (C) 2014 Raymond Hill
+
+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.
+
+**/
+
+/* jshint bitwise: false */
+
+(function(root) {
+
+ 'use strict';
+
+ /*
+ * Fastest md5 implementation around (JKM md5)
+ * Credits: Joseph Myers
+ *
+ * @see http://www.myersdaily.org/joseph/javascript/md5-text.html
+ * @see http://jsperf.com/md5-shootout/7
+ */
+
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence
+
+ var md5cycle = function(x, k) {
+ var a = x[0],
+ b = x[1],
+ c = x[2],
+ d = x[3];
+ // ff()
+ a += (b & c | ~b & d) + k[0] - 680876936 | 0;
+ a = (a << 7 | a >>> 25) + b | 0;
+ d += (a & b | ~a & c) + k[1] - 389564586 | 0;
+ d = (d << 12 | d >>> 20) + a | 0;
+ c += (d & a | ~d & b) + k[2] + 606105819 | 0;
+ c = (c << 17 | c >>> 15) + d | 0;
+ b += (c & d | ~c & a) + k[3] - 1044525330 | 0;
+ b = (b << 22 | b >>> 10) + c | 0;
+ a += (b & c | ~b & d) + k[4] - 176418897 | 0;
+ a = (a << 7 | a >>> 25) + b | 0;
+ d += (a & b | ~a & c) + k[5] + 1200080426 | 0;
+ d = (d << 12 | d >>> 20) + a | 0;
+ c += (d & a | ~d & b) + k[6] - 1473231341 | 0;
+ c = (c << 17 | c >>> 15) + d | 0;
+ b += (c & d | ~c & a) + k[7] - 45705983 | 0;
+ b = (b << 22 | b >>> 10) + c | 0;
+ a += (b & c | ~b & d) + k[8] + 1770035416 | 0;
+ a = (a << 7 | a >>> 25) + b | 0;
+ d += (a & b | ~a & c) + k[9] - 1958414417 | 0;
+ d = (d << 12 | d >>> 20) + a | 0;
+ c += (d & a | ~d & b) + k[10] - 42063 | 0;
+ c = (c << 17 | c >>> 15) + d | 0;
+ b += (c & d | ~c & a) + k[11] - 1990404162 | 0;
+ b = (b << 22 | b >>> 10) + c | 0;
+ a += (b & c | ~b & d) + k[12] + 1804603682 | 0;
+ a = (a << 7 | a >>> 25) + b | 0;
+ d += (a & b | ~a & c) + k[13] - 40341101 | 0;
+ d = (d << 12 | d >>> 20) + a | 0;
+ c += (d & a | ~d & b) + k[14] - 1502002290 | 0;
+ c = (c << 17 | c >>> 15) + d | 0;
+ b += (c & d | ~c & a) + k[15] + 1236535329 | 0;
+ b = (b << 22 | b >>> 10) + c | 0;
+ // gg()
+ a += (b & d | c & ~d) + k[1] - 165796510 | 0;
+ a = (a << 5 | a >>> 27) + b | 0;
+ d += (a & c | b & ~c) + k[6] - 1069501632 | 0;
+ d = (d << 9 | d >>> 23) + a | 0;
+ c += (d & b | a & ~b) + k[11] + 643717713 | 0;
+ c = (c << 14 | c >>> 18) + d | 0;
+ b += (c & a | d & ~a) + k[0] - 373897302 | 0;
+ b = (b << 20 | b >>> 12) + c | 0;
+ a += (b & d | c & ~d) + k[5] - 701558691 | 0;
+ a = (a << 5 | a >>> 27) + b | 0;
+ d += (a & c | b & ~c) + k[10] + 38016083 | 0;
+ d = (d << 9 | d >>> 23) + a | 0;
+ c += (d & b | a & ~b) + k[15] - 660478335 | 0;
+ c = (c << 14 | c >>> 18) + d | 0;
+ b += (c & a | d & ~a) + k[4] - 405537848 | 0;
+ b = (b << 20 | b >>> 12) + c | 0;
+ a += (b & d | c & ~d) + k[9] + 568446438 | 0;
+ a = (a << 5 | a >>> 27) + b | 0;
+ d += (a & c | b & ~c) + k[14] - 1019803690 | 0;
+ d = (d << 9 | d >>> 23) + a | 0;
+ c += (d & b | a & ~b) + k[3] - 187363961 | 0;
+ c = (c << 14 | c >>> 18) + d | 0;
+ b += (c & a | d & ~a) + k[8] + 1163531501 | 0;
+ b = (b << 20 | b >>> 12) + c | 0;
+ a += (b & d | c & ~d) + k[13] - 1444681467 | 0;
+ a = (a << 5 | a >>> 27) + b | 0;
+ d += (a & c | b & ~c) + k[2] - 51403784 | 0;
+ d = (d << 9 | d >>> 23) + a | 0;
+ c += (d & b | a & ~b) + k[7] + 1735328473 | 0;
+ c = (c << 14 | c >>> 18) + d | 0;
+ b += (c & a | d & ~a) + k[12] - 1926607734 | 0;
+ b = (b << 20 | b >>> 12) + c | 0;
+ // hh()
+ a += (b ^ c ^ d) + k[5] - 378558 | 0;
+ a = (a << 4 | a >>> 28) + b | 0;
+ d += (a ^ b ^ c) + k[8] - 2022574463 | 0;
+ d = (d << 11 | d >>> 21) + a | 0;
+ c += (d ^ a ^ b) + k[11] + 1839030562 | 0;
+ c = (c << 16 | c >>> 16) + d | 0;
+ b += (c ^ d ^ a) + k[14] - 35309556 | 0;
+ b = (b << 23 | b >>> 9) + c | 0;
+ a += (b ^ c ^ d) + k[1] - 1530992060 | 0;
+ a = (a << 4 | a >>> 28) + b | 0;
+ d += (a ^ b ^ c) + k[4] + 1272893353 | 0;
+ d = (d << 11 | d >>> 21) + a | 0;
+ c += (d ^ a ^ b) + k[7] - 155497632 | 0;
+ c = (c << 16 | c >>> 16) + d | 0;
+ b += (c ^ d ^ a) + k[10] - 1094730640 | 0;
+ b = (b << 23 | b >>> 9) + c | 0;
+ a += (b ^ c ^ d) + k[13] + 681279174 | 0;
+ a = (a << 4 | a >>> 28) + b | 0;
+ d += (a ^ b ^ c) + k[0] - 358537222 | 0;
+ d = (d << 11 | d >>> 21) + a | 0;
+ c += (d ^ a ^ b) + k[3] - 722521979 | 0;
+ c = (c << 16 | c >>> 16) + d | 0;
+ b += (c ^ d ^ a) + k[6] + 76029189 | 0;
+ b = (b << 23 | b >>> 9) + c | 0;
+ a += (b ^ c ^ d) + k[9] - 640364487 | 0;
+ a = (a << 4 | a >>> 28) + b | 0;
+ d += (a ^ b ^ c) + k[12] - 421815835 | 0;
+ d = (d << 11 | d >>> 21) + a | 0;
+ c += (d ^ a ^ b) + k[15] + 530742520 | 0;
+ c = (c << 16 | c >>> 16) + d | 0;
+ b += (c ^ d ^ a) + k[2] - 995338651 | 0;
+ b = (b << 23 | b >>> 9) + c | 0;
+ // ii()
+ a += (c ^ (b | ~d)) + k[0] - 198630844 | 0;
+ a = (a << 6 | a >>> 26) + b | 0;
+ d += (b ^ (a | ~c)) + k[7] + 1126891415 | 0;
+ d = (d << 10 | d >>> 22) + a | 0;
+ c += (a ^ (d | ~b)) + k[14] - 1416354905 | 0;
+ c = (c << 15 | c >>> 17) + d | 0;
+ b += (d ^ (c | ~a)) + k[5] - 57434055 | 0;
+ b = (b << 21 |b >>> 11) + c | 0;
+ a += (c ^ (b | ~d)) + k[12] + 1700485571 | 0;
+ a = (a << 6 | a >>> 26) + b | 0;
+ d += (b ^ (a | ~c)) + k[3] - 1894986606 | 0;
+ d = (d << 10 | d >>> 22) + a | 0;
+ c += (a ^ (d | ~b)) + k[10] - 1051523 | 0;
+ c = (c << 15 | c >>> 17) + d | 0;
+ b += (d ^ (c | ~a)) + k[1] - 2054922799 | 0;
+ b = (b << 21 |b >>> 11) + c | 0;
+ a += (c ^ (b | ~d)) + k[8] + 1873313359 | 0;
+ a = (a << 6 | a >>> 26) + b | 0;
+ d += (b ^ (a | ~c)) + k[15] - 30611744 | 0;
+ d = (d << 10 | d >>> 22) + a | 0;
+ c += (a ^ (d | ~b)) + k[6] - 1560198380 | 0;
+ c = (c << 15 | c >>> 17) + d | 0;
+ b += (d ^ (c | ~a)) + k[13] + 1309151649 | 0;
+ b = (b << 21 |b >>> 11) + c | 0;
+ a += (c ^ (b | ~d)) + k[4] - 145523070 | 0;
+ a = (a << 6 | a >>> 26) + b | 0;
+ d += (b ^ (a | ~c)) + k[11] - 1120210379 | 0;
+ d = (d << 10 | d >>> 22) + a | 0;
+ c += (a ^ (d | ~b)) + k[2] + 718787259 | 0;
+ c = (c << 15 | c >>> 17) + d | 0;
+ b += (d ^ (c | ~a)) + k[9] - 343485551 | 0;
+ b = (b << 21 | b >>> 11) + c | 0;
+
+ x[0] = a + x[0] | 0;
+ x[1] = b + x[1] | 0;
+ x[2] = c + x[2] | 0;
+ x[3] = d + x[3] | 0;
+ };
+
+ var hexChars = '0123456789abcdef';
+ var hexOut = [];
+
+ var hex = function(x) {
+ var hc = hexChars;
+ var ho = hexOut;
+ var n, offset, j;
+ for (var i = 0; i < 4; i++) {
+ offset = i * 8;
+ n = x[i];
+ for ( j = 0; j < 8; j += 2 ) {
+ ho[offset+1+j] = hc.charAt(n & 0x0F);
+ n >>>= 4;
+ ho[offset+0+j] = hc.charAt(n & 0x0F);
+ n >>>= 4;
+ }
+ }
+ return ho.join('');
+ };
+
+ var MD5 = function() {
+ this._dataLength = 0;
+ this._state = new Int32Array(4);
+ this._buffer = new ArrayBuffer(68);
+ this._bufferLength = 0;
+ this._buffer8 = new Uint8Array(this._buffer, 0, 68);
+ this._buffer32 = new Uint32Array(this._buffer, 0, 17);
+ this.start();
+ };
+
+ var stateIdentity = new Int32Array([1732584193, -271733879, -1732584194, 271733878]);
+ var buffer32Identity = new Int32Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
+
+ // Char to code point to to array conversion:
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charCodeAt#Example.3A_Fixing_charCodeAt_to_handle_non-Basic-Multilingual-Plane_characters_if_their_presence_earlier_in_the_string_is_unknown
+ MD5.prototype.appendStr = function(str) {
+ var buf8 = this._buffer8;
+ var buf32 = this._buffer32;
+ var bufLen = this._bufferLength;
+ var code;
+ for ( var i = 0; i < str.length; i++ ) {
+ code = str.charCodeAt(i);
+ if ( code < 128 ) {
+ buf8[bufLen++] = code;
+ } else if ( code < 0x800 ) {
+ buf8[bufLen++] = (code >>> 6) + 0xC0;
+ buf8[bufLen++] = code & 0x3F | 0x80;
+ } else if ( code < 0xD800 || code > 0xDBFF ) {
+ buf8[bufLen++] = (code >>> 12) + 0xE0;
+ buf8[bufLen++] = (code >>> 6 & 0x3F) | 0x80;
+ buf8[bufLen++] = (code & 0x3F) | 0x80;
+ } else {
+ code = ((code - 0xD800) * 0x400) + (str.charCodeAt(++i) - 0xDC00) + 0x10000;
+ if ( code > 0x10FFFF ) {
+ throw 'Unicode standard supports code points up to U+10FFFF';
+ }
+ buf8[bufLen++] = (code >>> 18) + 0xF0;
+ buf8[bufLen++] = (code >>> 12 & 0x3F) | 0x80;
+ buf8[bufLen++] = (code >>> 6 & 0x3F) | 0x80;
+ buf8[bufLen++] = (code & 0x3F) | 0x80;
+ }
+ if ( bufLen >= 64 ) {
+ this._dataLength += 64;
+ md5cycle(this._state, buf32);
+ bufLen -= 64;
+ buf32[0] = buf32[16];
+ }
+ }
+ this._bufferLength = bufLen;
+ return this;
+ };
+
+ MD5.prototype.appendAsciiStr = function(str) {
+ var buf8 = this._buffer8;
+ var buf32 = this._buffer32;
+ var bufLen = this._bufferLength;
+ var i, j = 0;
+ for (;;) {
+ i = Math.min(str.length-j, 64-bufLen);
+ while ( i-- ) {
+ buf8[bufLen++] = str.charCodeAt(j++);
+ }
+ if ( bufLen < 64 ) {
+ break;
+ }
+ this._dataLength += 64;
+ md5cycle(this._state, buf32);
+ bufLen = 0;
+ }
+ this._bufferLength = bufLen;
+ return this;
+ };
+
+ MD5.prototype.appendByteArray = function(input) {
+ var buf8 = this._buffer8;
+ var buf32 = this._buffer32;
+ var bufLen = this._bufferLength;
+ var i, j = 0;
+ for (;;) {
+ i = Math.min(input.length-j, 64-bufLen);
+ while ( i-- ) {
+ buf8[bufLen++] = input[j++];
+ }
+ if ( bufLen < 64 ) {
+ break;
+ }
+ this._dataLength += 64;
+ md5cycle(this._state, buf32);
+ bufLen = 0;
+ }
+ this._bufferLength = bufLen;
+ return this;
+ };
+
+ MD5.prototype.start = function() {
+ this._dataLength = 0;
+ this._bufferLength = 0;
+ this._state.set(stateIdentity);
+ return this;
+ };
+
+ MD5.prototype.end = function(raw) {
+ var bufLen = this._bufferLength;
+ this._dataLength += bufLen;
+ var buf8 = this._buffer8;
+ buf8[bufLen] = 0x80;
+ buf8[bufLen+1] = buf8[bufLen+2] = buf8[bufLen+3] = 0;
+ var buf32 = this._buffer32;
+ var i = (bufLen >> 2) + 1;
+ buf32.set(buffer32Identity.subarray(i), i);
+ if (bufLen > 55) {
+ md5cycle(this._state, buf32);
+ buf32.set(buffer32Identity);
+ }
+ // Do the final computation based on the tail and length
+ // Beware that the final length may not fit in 32 bits so we take care of that
+ var dataBitsLen = this._dataLength * 8;
+ if ( dataBitsLen <= 0xFFFFFFFF ) {
+ buf32[14] = dataBitsLen;
+ } else {
+ var matches = dataBitsLen.toString(16).match(/(.*?)(.{0,8})$/);
+ var lo = parseInt(matches[2], 16);
+ var hi = parseInt(matches[1], 16) || 0;
+ buf32[14] = lo;
+ buf32[15] = hi;
+ }
+ md5cycle(this._state, buf32);
+
+ return !!raw ? this._state : hex(this._state);
+ };
+
+ // This permanent instance is to use for one-call hashing
+ var onePassHasher = new MD5();
+
+ MD5.hashStr = function(str, raw) {
+ return onePassHasher
+ .start()
+ .appendStr(str)
+ .end(raw);
+ };
+
+ MD5.hashAsciiStr = function(str, raw) {
+ return onePassHasher
+ .start()
+ .appendAsciiStr(str)
+ .end(raw);
+ };
+
+ // Self-test
+ // In some cases the fast add32 function cannot be used..
+ if ( MD5.hashStr('hello') !== '5d41402abc4b2a76b9719d911017c592' ) {
+ console.error('YaMD5> this javascript engine does not support YaMD5. Sorry.');
+ }
+
+ if ( typeof root === 'object' ) {
+ root.YaMD5 = MD5;
+ }
+ return MD5;
+})(this);
diff --git a/src/lib/yamd5.min.js b/src/lib/yamd5.min.js
deleted file mode 100644
index cc20da3..0000000
--- a/src/lib/yamd5.min.js
+++ /dev/null
@@ -1,22 +0,0 @@
-// project home: https://github.com/gorhill/yamd5.js
-// minified using http://lisperator.net/uglifyjs/
-!function(t){"use strict";var r=function(t,r,e,n,i,s,f){return t+=(r&e|~r&n)+i+f,(t<>>32-s)+r|0
-},e=function(t,r,e,n,i,s,f){return t+=(r&n|e&~n)+i+f,(t<>>32-s)+r|0},n=function(t,r,e,n,i,s,f){return t+=(r^e^n)+i+f,(t<>>32-s)+r|0
-},i=function(t,r,e,n,i,s,f){return t+=(e^(r|~n))+i+f,(t<>>32-s)+r|0},s=function(t,s){var f=t[0],a=t[1],h=t[2],o=t[3];
-f=r(f,a,h,o,s[0],7,-680876936),o=r(o,f,a,h,s[1],12,-389564586),h=r(h,o,f,a,s[2],17,606105819),a=r(a,h,o,f,s[3],22,-1044525330),f=r(f,a,h,o,s[4],7,-176418897),o=r(o,f,a,h,s[5],12,1200080426),h=r(h,o,f,a,s[6],17,-1473231341),a=r(a,h,o,f,s[7],22,-45705983),f=r(f,a,h,o,s[8],7,1770035416),o=r(o,f,a,h,s[9],12,-1958414417),h=r(h,o,f,a,s[10],17,-42063),a=r(a,h,o,f,s[11],22,-1990404162),f=r(f,a,h,o,s[12],7,1804603682),o=r(o,f,a,h,s[13],12,-40341101),h=r(h,o,f,a,s[14],17,-1502002290),a=r(a,h,o,f,s[15],22,1236535329),f=e(f,a,h,o,s[1],5,-165796510),o=e(o,f,a,h,s[6],9,-1069501632),h=e(h,o,f,a,s[11],14,643717713),a=e(a,h,o,f,s[0],20,-373897302),f=e(f,a,h,o,s[5],5,-701558691),o=e(o,f,a,h,s[10],9,38016083),h=e(h,o,f,a,s[15],14,-660478335),a=e(a,h,o,f,s[4],20,-405537848),f=e(f,a,h,o,s[9],5,568446438),o=e(o,f,a,h,s[14],9,-1019803690),h=e(h,o,f,a,s[3],14,-187363961),a=e(a,h,o,f,s[8],20,1163531501),f=e(f,a,h,o,s[13],5,-1444681467),o=e(o,f,a,h,s[2],9,-51403784),h=e(h,o,f,a,s[7],14,1735328473),a=e(a,h,o,f,s[12],20,-1926607734),f=n(f,a,h,o,s[5],4,-378558),o=n(o,f,a,h,s[8],11,-2022574463),h=n(h,o,f,a,s[11],16,1839030562),a=n(a,h,o,f,s[14],23,-35309556),f=n(f,a,h,o,s[1],4,-1530992060),o=n(o,f,a,h,s[4],11,1272893353),h=n(h,o,f,a,s[7],16,-155497632),a=n(a,h,o,f,s[10],23,-1094730640),f=n(f,a,h,o,s[13],4,681279174),o=n(o,f,a,h,s[0],11,-358537222),h=n(h,o,f,a,s[3],16,-722521979),a=n(a,h,o,f,s[6],23,76029189),f=n(f,a,h,o,s[9],4,-640364487),o=n(o,f,a,h,s[12],11,-421815835),h=n(h,o,f,a,s[15],16,530742520),a=n(a,h,o,f,s[2],23,-995338651),f=i(f,a,h,o,s[0],6,-198630844),o=i(o,f,a,h,s[7],10,1126891415),h=i(h,o,f,a,s[14],15,-1416354905),a=i(a,h,o,f,s[5],21,-57434055),f=i(f,a,h,o,s[12],6,1700485571),o=i(o,f,a,h,s[3],10,-1894986606),h=i(h,o,f,a,s[10],15,-1051523),a=i(a,h,o,f,s[1],21,-2054922799),f=i(f,a,h,o,s[8],6,1873313359),o=i(o,f,a,h,s[15],10,-30611744),h=i(h,o,f,a,s[6],15,-1560198380),a=i(a,h,o,f,s[13],21,1309151649),f=i(f,a,h,o,s[4],6,-145523070),o=i(o,f,a,h,s[11],10,-1120210379),h=i(h,o,f,a,s[2],15,718787259),a=i(a,h,o,f,s[9],21,-343485551),t[0]=f+t[0]|0,t[1]=a+t[1]|0,t[2]=h+t[2]|0,t[3]=o+t[3]|0
-},f=function(t){for(var r,e,n="0123456789abcdef",i=[],s=0;sf;f+=2)i[e+1+f]=n.charAt(15&r),r>>>=4,i[e+0+f]=n.charAt(15&r),r>>>=4
-}return i.join("")},a=function(){this._dataLength=0,this._state=new Int32Array(4),this._buffer=new ArrayBuffer(68),this._bufferLength=0,this._buffer8=new Uint8Array(this._buffer,0,68),this._buffer32=new Uint32Array(this._buffer,0,17),this.start()
-};a.prototype.appendStr=function(t){for(var r,e=this._buffer8,n=this._buffer32,i=this._bufferLength,f=0;fr)e[i++]=r;
-else if(2048>r)e[i++]=(r>>>6)+192,e[i++]=63&r|128;else if(55296>r||r>56319)e[i++]=(r>>>12)+224,e[i++]=r>>>6&63|128,e[i++]=63&r|128;
-else{if(r=1024*(r-55296)+(t.charCodeAt(++f)-56320)+65536,r>1114111)throw"Unicode standard supports code points up to U+10FFFF";
-e[i++]=(r>>>18)+240,e[i++]=r>>>12&63|128,e[i++]=r>>>6&63|128,e[i++]=63&r|128}if(i>=64)this._dataLength+=64,s(this._state,n),i-=64,n[0]=n[16]
-}return this._bufferLength=i,this},a.prototype.start=function(){this._dataLength=0,this._bufferLength=0;
-var t=this._state;return t[0]=1732584193,t[1]=-271733879,t[2]=-1732584194,t[3]=271733878,this
-},a.prototype.end=function(t){var r=this._bufferLength;this._dataLength+=r;var e=this._buffer8;
-e[r]=128,e[r+1]=e[r+2]=e[r+3]=0;var n,i=this._buffer32;for(n=(r>>2)+1;16>n;n++)i[n]=0;
-if(r>55)for(s(this._state,i),n=0;16>n;n++)i[n]=0;var a=8*this._dataLength;if(4294967295>=a)i[14]=a;
-else{var h=a.toString(16).match(/(.*?)(.{0,8})$/),o=parseInt(h[2],16),u=parseInt(h[1],16)||0;
-i[14]=o,i[15]=u}return s(this._state,i),t?this._state:f(this._state)};var h=new a;
-if(a.hashStr=function(t,r){return h.start().appendStr(t).end(r)},"5d41402abc4b2a76b9719d911017c592"!==a.hashStr("hello"))throw"This javascript engine does not support YaMD5. Sorry.";
-if("object"==typeof t)t.YaMD5=a;return a}(this);
diff --git a/tools/make-chromium.sh b/tools/make-chromium.sh
index bb907ee..aacc5e5 100755
--- a/tools/make-chromium.sh
+++ b/tools/make-chromium.sh
@@ -16,7 +16,7 @@ cp ./platform/chromium/*.html $DES/
cp ./platform/chromium/*.js $DES/js/
cp -R ./platform/chromium/img/* $DES/img/
cp ./platform/chromium/manifest.json $DES/
-cp LICENSE $DES/
+cp LICENSE.txt $DES/
if [ "$1" = all ]; then
echo "*** µMatrix.chromium: Creating package..."
diff --git a/tools/make-firefox-meta.py b/tools/make-firefox-meta.py
index 284fa96..f4fff35 100644
--- a/tools/make-firefox-meta.py
+++ b/tools/make-firefox-meta.py
@@ -6,6 +6,7 @@ import sys
from io import open
from shutil import rmtree
from collections import OrderedDict
+from xml.sax.saxutils import escape
if len(sys.argv) == 1 or not sys.argv[1]:
raise SystemExit('Build dir missing.')
@@ -56,13 +57,13 @@ for alpha2 in sorted(os.listdir(source_locale_dir)):
chrome_manifest = pj(build_dir, 'chrome.manifest')
with open(chrome_manifest, 'at', encoding='utf-8', newline='\n') as f:
- f.write(u'\nlocale ublock0 en ./locale/en/\n')
+ f.write(u'\nlocale umatrix en ./locale/en/\n')
for alpha2 in language_codes:
if alpha2 == 'en':
continue
- f.write(u'locale ublock0 ' + alpha2 + ' ./locale/' + alpha2 + '/\n')
+ f.write(u'locale umatrix ' + alpha2 + ' ./locale/' + alpha2 + '/\n')
rmtree(source_locale_dir)
@@ -73,8 +74,8 @@ chromium_manifest = pj(proj_dir, 'platform', 'chromium', 'manifest.json')
with open(chromium_manifest, encoding='utf-8') as m:
manifest = json.load(m)
-manifest['homepage'] = 'https://github.com/gorhill/uBlock'
-manifest['description'] = descriptions['en']
+manifest['homepage'] = 'https://github.com/gorhill/uMatrix'
+manifest['description'] = escape(descriptions['en'])
del descriptions['en']
manifest['localized'] = []
@@ -89,7 +90,7 @@ for alpha2 in descriptions:
'\n' + t*2 + '\n' +
t3 + '' + alpha2 + '\n' +
t3 + '' + manifest['name'] + '\n' +
- t3 + '' + descriptions[alpha2] + '\n' +
+ t3 + '' + escape(descriptions[alpha2]) + '\n' +
t3 + '' + manifest['author'] + '\n' +
# t3 + '' + ??? + '\n' +
t3 + '' + manifest['homepage'] + '\n' +
diff --git a/tools/make-firefox.sh b/tools/make-firefox.sh
index 85beb60..c082271 100755
--- a/tools/make-firefox.sh
+++ b/tools/make-firefox.sh
@@ -2,38 +2,32 @@
#
# This script assumes a linux environment
-echo "*** uBlock0.firefox: Copying files"
+echo "*** uMatrix.firefox: Copying files"
-DES=dist/build/uBlock0.firefox
+DES=dist/build/uMatrix.firefox
rm -rf $DES
mkdir -p $DES
-cp -R assets $DES/
-rm $DES/assets/*.sh
-cp -R src/css $DES/
-cp -R src/img $DES/
-cp -R src/js $DES/
-cp -R src/lib $DES/
-cp -R src/_locales $DES/
-cp src/*.html $DES/
-mv $DES/img/icon_128.png $DES/icon.png
-cp platform/firefox/vapi-*.js $DES/js/
-cp platform/firefox/bootstrap.js $DES/
-cp platform/firefox/frame*.js $DES/
-cp -R platform/firefox/img $DES/
-cp platform/firefox/chrome.manifest $DES/
-cp platform/firefox/install.rdf $DES/
-cp platform/firefox/*.xul $DES/
-cp LICENSE.txt $DES/
+cp -R ./assets $DES/
+cp -R ./src/* $DES/
+mv $DES/img/icon_128.png $DES/icon.png
+cp ./platform/firefox/vapi-*.js $DES/js/
+cp ./platform/firefox/bootstrap.js $DES/
+cp ./platform/firefox/frame*.js $DES/
+cp -R ./platform/firefox/img $DES/
+cp ./platform/firefox/chrome.manifest $DES/
+cp ./platform/firefox/install.rdf $DES/
+cp ./platform/firefox/*.xul $DES/
+cp ./LICENSE.txt $DES/
-echo "*** uBlock0.firefox: Generating meta..."
+echo "*** uMatrix.firefox: Generating meta..."
python tools/make-firefox-meta.py $DES/
if [ "$1" = all ]; then
- echo "*** uBlock0.firefox: Creating package..."
+ echo "*** uMatrix.firefox: Creating package..."
pushd $DES/
- zip ../uBlock0.firefox.xpi -qr *
+ zip ../uMatrix.firefox.xpi -qr *
popd
fi
-echo "*** uBlock0.firefox: Package done."
+echo "*** uMatrix.firefox: Package done."