summaryrefslogtreecommitdiff
path: root/data/extensions/https-everywhere@eff.org/chrome/content
diff options
context:
space:
mode:
authorRuben Rodriguez <ruben@gnu.org>2014-10-20 02:24:51 +0200
committerRuben Rodriguez <ruben@gnu.org>2014-10-20 02:24:51 +0200
commit6e7918b6ccb69876d339a320091fdee811445395 (patch)
tree31cb88ee438d652fddefca1193f70289a8b3dcc8 /data/extensions/https-everywhere@eff.org/chrome/content
parent60e5b13c35d4d3ba21bb03b026750a0a414f6c77 (diff)
Generalize data directory
Diffstat (limited to 'data/extensions/https-everywhere@eff.org/chrome/content')
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/about.xul72
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/code/ApplicableList.js266
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/code/ChannelReplacement.js387
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/code/Cookie.js148
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/code/HTTPS.js296
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/code/HTTPSRules.js762
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/code/IOUtil.js263
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/code/NSS.js491
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/code/Root-CAs.js348
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/code/STS.js228
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/code/Thread.js100
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/code/X509ChainWhitelist.js1007
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/code/sha256.js249
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/fetch-source.js161
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/fetch-source.xul29
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/meta-preferences.xul30
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/observatory-popup.xul61
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/observatory-preferences.xul106
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/observatory-warning.xul49
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/observatory-xul.js194
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/preferences.css11
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/preferences.js269
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/preferences.xul62
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/rules/00README17
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/ruleset-tests-status.css14
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/ruleset-tests-status.js31
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/ruleset-tests-status.xul44
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/ruleset-tests.js155
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/toolbar_button.js369
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/toolbar_button.xul71
-rw-r--r--data/extensions/https-everywhere@eff.org/chrome/content/toolbar_button_binding.xml33
31 files changed, 6323 insertions, 0 deletions
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/about.xul b/data/extensions/https-everywhere@eff.org/chrome/content/about.xul
new file mode 100644
index 0000000..cf57e9d
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/about.xul
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://https-everywhere/content/preferences.css" type="text/css"?>
+
+<!DOCTYPE overlay SYSTEM "chrome://https-everywhere/locale/https-everywhere.dtd">
+
+<dialog id="https-everywhere-about"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ xmlns:html="http://www.w3.org/1999/xhtml"
+ buttons="accept"
+ title="&https-everywhere.about.title;"
+ width="640"
+ height="480"
+ align="center">
+
+ <script type="application/x-javascript"
+ src="chrome://https-everywhere/content/preferences.js"/>
+ <vbox style="overflow:auto" flex="1">
+ <label style="text-align:center; font-weight:bold; font-size:22px;">&https-everywhere.about.ext_name;</label>
+ <label style="text-align:center; font-size:18px; margin-bottom:10px;">&https-everywhere.about.ext_description;</label>
+
+ <groupbox>
+ <caption label="&https-everywhere.about.version;" />
+ <label>3.5.1</label>
+ </groupbox>
+
+ <groupbox>
+ <caption label="&https-everywhere.about.created_by;" />
+ <label>Mike Perry and Peter Eckersley</label>
+ </groupbox>
+
+ <groupbox>
+ <caption label="&https-everywhere.about.librarians;" />
+ <label>Seth Schoen, MB and Andreas Jonsson</label>
+ </groupbox>
+
+ <groupbox>
+ <caption label="&https-everywhere.about.thanks;" />
+ <label>Many many contributors, including Aaron Swartz, Alec Moskvin,
+ Aleksey Kosterin, Alex Xu, Anas Qtiesh, Artyom Gavrichenkov, Brian
+ Carpenter, Chris Palmer, Christian Inci, Christopher Liu, Claudio
+ Moretti, Colonel Graff, Dan Auerbach, Daniel Kahn Gillmor, dm0, The
+ Doctor, Felix Geyer, Fruitless Creek, George Kargiotakis, haviah, Heiko
+ Adams, Jeroen van der Gun, Jay Weisskopf, Jacob Taylor, Jonathan Davies, Jorge Bernal,
+ katmagic, Kevin Jacobs, Korte, Liam K, Leonardo Brondani Schenkel, Marti Raudsepp, Micah Lee, Mike
+ Cardwell, Mangix, Matthias-Christian Ott, Mikko Harhanen, Mishari Muqbil, Neheb, Ori Avtalion, Osama Khalid,
+ nitrox, Pablo Castellano, Paul Wise, Pavel Kazakov, Phol Paucar, Richard
+ Green, Roan Kattouw, Rules Moore, Stefan Tomanek, Sam Reed, Steve
+ Milner, Sujit Rao, TK-999, Vendo, Victor Garin, Weiland Hoffmann, Whizz
+ Mo and Yan Zhu. Also, portions of HTTPS Everywhere are based on code
+ from NoScript, by Giorgio Maone and others. We are grateful for their
+ excellent work!</label>
+ </groupbox>
+
+ <label style="font-weight:bold; margin-top:10px;">
+ &https-everywhere.about.contribute;
+ <label id="donate link"
+ value="&https-everywhere.about.donate_tor;"
+ style="color: blue; cursor:hand; text-decoration:underline; font-style:bold"
+ onmouseover="event.target.style.cursor='pointer'"
+ onmouseout="event.target.style.cursor='default'"
+ onclick="window_opener('https://www.torproject.org/donate/donate.html.en')"/>
+ or
+ <label id="donate link2"
+ value="&https-everywhere.about.donate_eff;"
+ style="color: blue; cursor:hand; text-decoration:underline; font-style:bold"
+ onmouseover="event.target.style.cursor='pointer'"
+ onmouseout="event.target.style.cursor='default'"
+ onclick="window_opener('https://www.eff.org/donate')"/>
+ </label>
+ </vbox>
+</dialog>
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/code/ApplicableList.js b/data/extensions/https-everywhere@eff.org/chrome/content/code/ApplicableList.js
new file mode 100644
index 0000000..6949167
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/code/ApplicableList.js
@@ -0,0 +1,266 @@
+// An ApplicableList is a structure used to keep track of which rulesets
+// were applied, and which ones weren't but might have been, to the contents
+// of a given page (top level nsIDOMWindow)
+
+serial_number = 0;
+
+function ApplicableList(logger, doc, domWin) {
+ this.domWin = domWin;
+ this.uri = doc.baseURIObject.clone();
+ if (!this.uri) {
+ this.log(WARN,"NULL CLONING URI " + doc);
+ if (doc)
+ this.log(WARN,"NULL CLONING URI " + doc.baseURIObject);
+ if (doc.baseURIObject)
+ this.log(WARN,"NULL CLONING URI " + doc.baseURIObject.spec);
+ }
+ this.home = doc.baseURIObject.spec; // what doc we're housekeeping for
+ this.log = logger;
+ this.active = {};
+ this.breaking = {}; // rulesets with redirection loops
+ this.inactive = {};
+ this.moot={}; // rulesets that might be applicable but uris are already https
+ this.all={}; // active + breaking + inactive + moot
+ serial_number += 1;
+ this.serial = serial_number;
+ this.log(DBUG,"Alist serial #" + this.serial + " for " + this.home);
+}
+
+ApplicableList.prototype = {
+
+ empty: function() {
+ // Empty everything, used when toggles occur in order to ensure that if
+ // the reload fails, the resulting list is not eroneous
+ this.active = {};
+ this.breaking = {};
+ this.inactive = {};
+ this.moot={};
+ this.all={};
+ },
+
+ active_rule: function(ruleset) {
+ this.log(INFO,"active rule " + ruleset.name +" in "+ this.home +" -> " +
+ this.domWin.document.baseURIObject.spec+ " serial " + this.serial);
+ this.active[ruleset.name] = ruleset;
+ this.all[ruleset.name] = ruleset;
+ },
+
+ breaking_rule: function(ruleset) {
+ this.log(NOTE,"breaking rule " + ruleset.name +" in "+ this.home +" -> " +
+ this.domWin.document.baseURIObject.spec+ " serial " + this.serial);
+ this.breaking[ruleset.name] = ruleset;
+ this.all[ruleset.name] = ruleset;
+ },
+
+ inactive_rule: function(ruleset) {
+
+ this.log(INFO,"inactive rule " + ruleset.name +" in "+ this.home +" -> " +
+ this.domWin.document.baseURIObject.spec+ " serial " + this.serial);
+ this.inactive[ruleset.name] = ruleset;
+ this.all[ruleset.name] = ruleset;
+ },
+
+ moot_rule: function(ruleset) {
+ this.log(INFO,"moot rule " + ruleset.name +" in "+ this.home + " serial " + this.serial);
+ this.moot[ruleset.name] = ruleset;
+ this.all[ruleset.name] = ruleset;
+ },
+
+ dom_handler: function(operation,key,data,src,dst) {
+ // See https://developer.mozilla.org/En/DOM/UserDataHandler
+ if (src && dst)
+ dst.setUserData(key, data, this.dom_handler);
+ },
+
+ populate_list: function() {
+ // The base URI of the dom tends to be loaded from some /other/
+ // ApplicableList, so pretend we're loading it from here.
+ HTTPSEverywhere.instance.https_rules.rewrittenURI(this, this.uri);
+ this.log(DBUG, "populating using alist #" + this.serial);
+ },
+
+ populate_menu: function(document, menupopup, weird) {
+ this.populate_list();
+ this.document = document;
+
+ var https_everywhere = CC["@eff.org/https-everywhere;1"].getService(Components.interfaces.nsISupports).wrappedJSObject;
+
+ // get the menu popup
+ this.menupopup = menupopup;
+
+ // empty it all of its menuitems
+ while(this.menupopup.firstChild.tagName != "menuseparator") {
+ this.menupopup.removeChild(this.menupopup.firstChild);
+ }
+
+ // add global enable/disable toggle button
+ var strings = document.getElementById("HttpsEverywhereStrings");
+
+ var enableLabel = document.createElement('menuitem');
+ var text = strings.getString("https-everywhere.menu.globalDisable");
+ if(!https_everywhere.prefs.getBoolPref("globalEnabled"))
+ text = strings.getString("https-everywhere.menu.globalEnable");
+
+ enableLabel.setAttribute('label', text);
+ enableLabel.setAttribute('command', 'https-everywhere-menuitem-globalEnableToggle');
+ this.prepend_child(enableLabel);
+
+ // add the label at the top
+ var any_rules = false;
+ for(var x in this.all) {
+ any_rules = true; // how did JavaScript get this ugly?
+ break;
+ }
+ var label = document.createElement('menuitem');
+ label.setAttribute('label', strings.getString('https-everywhere.menu.enableDisable'));
+ label.setAttribute('command', 'https-everywhere-menuitem-preferences');
+ var label2 = false;
+ if (!any_rules) {
+ label2 = document.createElement('menuitem');
+ if (!weird) text = strings.getString('https-everywhere.menu.noRules');
+ else text = strings.getString('https-everywhere.menu.unknownRules');
+ label2.setAttribute('label', text);
+ label2.setAttribute('command', 'https-everywhere-menuitem-preferences');
+ label2.setAttribute('style', 'color:#909090;');
+ }
+
+ // create a commandset if it doesn't already exist
+ this.commandset = document.getElementById('https-everywhere-commandset');
+ if(!this.commandset) {
+ this.commandset = document.createElement('commandset');
+ this.commandset.setAttribute('id', 'https-everywhere-commandset');
+ var win = document.getElementById('main-window');
+ win.appendChild(this.commandset);
+ } else {
+ // empty commandset
+ while(this.commandset.firstChild)
+ this.commandset.removeChild(this.commandset.firstChild);
+ }
+
+ var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Components.interfaces.nsIWindowMediator);
+
+ var domWin = wm.getMostRecentWindow("navigator:browser").content.document.defaultView.top;
+ var location = domWin.document.baseURIObject.asciiSpec; //full url, including about:certerror details
+
+ if(location.substr(0, 6) == "about:"){
+ //"From" portion of the rule is retrieved from the location bar via document.getElementById("urlbar").value
+
+ var fromHost = document.getElementById("urlbar").value;
+
+ //scheme must be trimmed out to check for applicable rulesets
+ if(fromHost.indexOf("://") != -1)
+ fromHost = fromHost.substr(fromHost.indexOf("://") + 3, fromHost.length);
+
+ //trim off any page locations - we only want the host - e.g. domain.com
+ if(fromHost.indexOf("/") != -1)
+ fromHost = fromHost.substr(0, fromHost.indexOf("/"));
+
+ // Search for applicable rulesets for the host listed in the location bar
+ var plist = HTTPSRules.potentiallyApplicableRulesets(fromHost);
+ for (var i = 0 ; i < plist.length ; i++){
+ //For each applicable rulset, determine active/inactive, and append to proper list.
+ var ruleOn = false;
+ try {
+ if(https_everywhere.rule_toggle_prefs.getBoolPref(plist[i].name))
+ ruleOn = true;
+ } catch(e) {
+ if(https_everywhere.https_rules.rulesetsByName[plist[i].name].active)
+ ruleOn = true;
+ }
+ if(ruleOn)
+ this.active_rule(plist[i]);
+ else
+ this.inactive_rule(plist[i]);
+ }
+ }
+
+ // add all applicable commands
+ for(var x in this.breaking)
+ this.add_command(this.breaking[x]);
+ for(var x in this.active)
+ this.add_command(this.active[x]);
+ for(var x in this.moot)
+ this.add_command(this.moot[x]);
+ for(var x in this.inactive)
+ this.add_command(this.inactive[x]);
+
+ if(https_everywhere.prefs.getBoolPref("globalEnabled")){
+ // add all the menu items
+ for (var x in this.inactive)
+ this.add_menuitem(this.inactive[x], 'inactive');
+ // rules that are active for some uris are not really moot
+ for (var x in this.moot)
+ if (!(x in this.active))
+ this.add_menuitem(this.moot[x], 'moot');
+ // break once break everywhere
+ for (var x in this.active)
+ if (!(x in this.breaking))
+ this.add_menuitem(this.active[x], 'active');
+ for (var x in this.breaking)
+ this.add_menuitem(this.breaking[x], 'breaking');
+
+ if (label2) this.prepend_child(label2);
+ this.prepend_child(label);
+ }
+
+ },
+
+ prepend_child: function(node) {
+ this.menupopup.insertBefore(node, this.menupopup.firstChild);
+ },
+
+ add_command: function(rule) {
+ var command = this.document.createElement("command");
+ command.setAttribute('id', rule.id+'-command');
+ command.setAttribute('label', rule.name);
+ command.setAttribute('oncommand', 'toggle_rule("'+rule.id+'")');
+ this.commandset.appendChild(command);
+ },
+
+ // add a menu item for a rule -- type is "active", "inactive", "moot",
+ // or "breaking"
+
+ add_menuitem: function(rule, type) {
+ // create the menuitem
+ var item = this.document.createElement('menuitem');
+ item.setAttribute('command', rule.id+'-command');
+ item.setAttribute('class', type+'-item menuitem-iconic');
+ item.setAttribute('label', rule.name);
+
+ // we can get confused if rulesets have their state changed after the
+ // ApplicableList was constructed
+ if (!rule.active && (type == 'active' || type == 'moot'))
+ type = 'inactive';
+ if (rule.active && type == 'inactive')
+ type = 'moot';
+
+ // set the icon
+ var image_src;
+ if (type == 'active') image_src = 'tick.png';
+ else if (type == 'inactive') image_src = 'cross.png';
+ else if (type == 'moot') image_src = 'tick-moot.png';
+ else if (type == 'breaking') image_src = 'loop.png';
+ item.setAttribute('image', 'chrome://https-everywhere/skin/'+image_src);
+
+ // all done
+ this.prepend_child(item);
+ },
+
+ show_applicable: function() {
+ this.log(WARN, "Applicable list number " + this.serial);
+ for (var x in this.active)
+ this.log(WARN,"Active: " + this.active[x].name);
+
+ for (var x in this.breaking)
+ this.log(WARN,"Breaking: " + this.breaking[x].name);
+
+ for (x in this.inactive)
+ this.log(WARN,"Inactive: " + this.inactive[x].name);
+
+ for (x in this.moot)
+ this.log(WARN,"Moot: " + this.moot[x].name);
+
+ }
+};
+
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/code/ChannelReplacement.js b/data/extensions/https-everywhere@eff.org/chrome/content/code/ChannelReplacement.js
new file mode 100644
index 0000000..551bcab
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/code/ChannelReplacement.js
@@ -0,0 +1,387 @@
+function CtxCapturingListener(tracingChannel, captureObserver) {
+ this.originalListener = tracingChannel.setNewListener(this);
+ this.captureObserver = captureObserver;
+}
+CtxCapturingListener.prototype = {
+ originalListener: null,
+ originalCtx: null,
+ onStartRequest: function(request, ctx) {
+ this.originalCtx = ctx;
+ if (this.captureObserver) {
+ this.captureObserver.observeCapture(request, this);
+ }
+ },
+ onDataAvailable: function(request, ctx, inputStream, offset, count) {},
+ onStopRequest: function(request, ctx, statusCode) {},
+ QueryInterface: xpcom_generateQI([Ci.nsIStreamListener])
+};
+
+function ChannelReplacement(chan, newURI, newMethod) {
+ return this._init(chan, newURI, newMethod);
+}
+
+ChannelReplacement.supported = "nsITraceableChannel" in Ci;
+
+ChannelReplacement.runWhenPending = function(channel, callback) {
+ if (channel.isPending()) {
+ callback();
+ return false;
+ } else {
+ new LoadGroupWrapper(channel, callback);
+ return true;
+ }
+};
+
+
+ChannelReplacement.prototype = {
+ listener: null,
+ context: null,
+ oldChannel: null,
+ channel: null,
+ window: null,
+ suspended: false,
+
+ get _unsupportedError() {
+ return new Error("Can't replace channels without nsITraceableChannel!");
+ },
+
+ get _classifierClass() {
+ delete this.__proto__._classifierClass;
+ return this.__proto__._classifierClass = Cc["@mozilla.org/channelclassifier"];
+ },
+
+ _autoHeadersRx: /^(?:Host|Cookie|Authorization)$|Cache|^If-/,
+ visitHeader: function(key, val) {
+ try {
+ // we skip authorization and cache-related fields which should be automatically set
+ if (!this._autoHeadersRx.test(key)) this.channel.setRequestHeader(key, val, false);
+ } catch (e) {
+ dump(e + "\n");
+ }
+ },
+
+ _init: function(chan, newURI, newMethod) {
+ if (!(ChannelReplacement.supported && chan instanceof Ci.nsITraceableChannel))
+ throw this._unsupportedError;
+
+ newURI = newURI || chan.URI;
+
+ var newChan = IOS.newChannelFromURI(newURI);
+
+ this.oldChannel = chan;
+ this.channel = newChan;
+
+ // porting of http://mxr.mozilla.org/mozilla-central/source/netwerk/protocol/http/src/nsHttpChannel.cpp#2750
+
+ var loadFlags = chan.loadFlags;
+
+ if (chan.URI.schemeIs("https"))
+ loadFlags &= ~chan.INHIBIT_PERSISTENT_CACHING;
+
+
+ newChan.loadGroup = chan.loadGroup;
+ newChan.notificationCallbacks = chan.notificationCallbacks;
+ newChan.loadFlags = loadFlags | newChan.LOAD_REPLACE;
+
+ if (!(newChan instanceof Ci.nsIHttpChannel))
+ return this;
+
+ // copy headers
+ chan.visitRequestHeaders(this);
+
+ if (!newMethod || newMethod === chan.requestMethod) {
+ if (newChan instanceof Ci.nsIUploadChannel && chan instanceof Ci.nsIUploadChannel && chan.uploadStream ) {
+ var stream = chan.uploadStream;
+ if (stream instanceof Ci.nsISeekableStream) {
+ stream.seek(stream.NS_SEEK_SET, 0);
+ }
+
+ try {
+ let ctype = chan.getRequestHeader("Content-type");
+ let clen = chan.getRequestHeader("Content-length");
+ if (ctype && clen) {
+ newChan.setUploadStream(stream, ctype, parseInt(clen, 10));
+ }
+ } catch(e) {
+ newChan.setUploadStream(stream, '', -1);
+ }
+
+ newChan.requestMethod = chan.requestMethod;
+ }
+ } else {
+ newChan.requestMethod = newMethod;
+ }
+
+ if (chan.referrer) newChan.referrer = chan.referrer;
+ newChan.allowPipelining = chan.allowPipelining;
+ newChan.redirectionLimit = chan.redirectionLimit - 1;
+ if (chan instanceof Ci.nsIHttpChannelInternal && newChan instanceof Ci.nsIHttpChannelInternal) {
+ if (chan.URI == chan.documentURI) {
+ newChan.documentURI = newURI;
+ } else {
+ newChan.documentURI = chan.documentURI;
+ }
+ }
+
+ if (chan instanceof Ci.nsIEncodedChannel && newChan instanceof Ci.nsIEncodedChannel) {
+ newChan.applyConversion = chan.applyConversion;
+ }
+
+ // we can't transfer resume information because we can't access mStartPos and mEntityID :(
+ // http://mxr.mozilla.org/mozilla-central/source/netwerk/protocol/http/src/nsHttpChannel.cpp#2826
+
+ if ("nsIApplicationCacheChannel" in Ci &&
+ chan instanceof Ci.nsIApplicationCacheChannel && newChan instanceof Ci.nsIApplicationCacheChannel) {
+ newChan.applicationCache = chan.applicationCache;
+ newChan.inheritApplicationCache = chan.inheritApplicationCache;
+ }
+
+ if (chan instanceof Ci.nsIPropertyBag && newChan instanceof Ci.nsIWritablePropertyBag)
+ for (var properties = chan.enumerator, p; properties.hasMoreElements();)
+ if ((p = properties.getNext()) instanceof Ci.nsIProperty)
+ newChan.setProperty(p.name, p.value);
+
+ if (chan.loadFlags & chan.LOAD_DOCUMENT_URI) {
+ this.window = IOUtil.findWindow(chan);
+ if (this.window) this.window._replacedChannel = chan;
+ }
+
+ return this;
+ },
+
+ _onChannelRedirect: function() {
+ var oldChan = this.oldChannel;
+ var newChan = this.channel;
+
+ if (this.realRedirect) {
+ if (oldChan.redirectionLimit === 0) {
+ oldChan.cancel(NS_ERROR_REDIRECT_LOOP);
+ throw NS_ERROR_REDIRECT_LOOP;
+ }
+ } else newChan.redirectionLimit += 1;
+
+
+
+ // nsHttpHandler::OnChannelRedirect()
+
+ const CES = Ci.nsIChannelEventSink;
+ const flags = CES.REDIRECT_INTERNAL;
+ this._callSink(
+ Cc["@mozilla.org/netwerk/global-channel-event-sink;1"].getService(CES),
+ oldChan, newChan, flags);
+ var sink;
+
+ for (let cess = Cc['@mozilla.org/categorymanager;1'].getService(CI.nsICategoryManager)
+ .enumerateCategory("net-channel-event-sinks");
+ cess.hasMoreElements();
+ ) {
+ sink = cess.getNext();
+ if (sink instanceof CES)
+ this._callSink(sink, oldChan, newChan, flags);
+ }
+ sink = IOUtil.queryNotificationCallbacks(oldChan, CES);
+ if (sink) this._callSink(sink, oldChan, newChan, flags);
+
+ // ----------------------------------
+
+ newChan.originalURI = oldChan.originalURI;
+
+ sink = IOUtil.queryNotificationCallbacks(oldChan, Ci.nsIHttpEventSink);
+ if (sink) sink.onRedirect(oldChan, newChan);
+ },
+
+ _callSink: function(sink, oldChan, newChan, flags) {
+ try {
+ if ("onChannelRedirect" in sink) sink.onChannelRedirect(oldChan, newChan, flags);
+ else sink.asyncOnChannelRedirect(oldChan, newChan, flags, this._redirectCallback);
+ } catch(e) {
+ if (e.toString().indexOf("(NS_ERROR_DOM_BAD_URI)") !== -1 && oldChan.URI.spec !== newChan.URI.spec) {
+ let oldURL = oldChan.URI.spec;
+ try {
+ oldChan.URI.spec = newChan.URI.spec;
+ this._callSink(sink, oldChan, newChan, flags);
+ } catch(e1) {
+ throw e;
+ } finally {
+ oldChan.URI.spec = oldURL;
+ }
+ } else if (e.message.indexOf("(NS_ERROR_NOT_AVAILABLE)") === -1) throw e;
+ }
+ },
+
+ _redirectCallback: ("nsIAsyncVerifyRedirectCallback" in Ci)
+ ? {
+ QueryInterface: xpcom_generateQI([Ci.nsIAsyncVerifyRedirectCallback]),
+ onRedirectVerifyCallback: function(result) {}
+ }
+ : null
+ ,
+
+ replace: function(realRedirect, callback) {
+ let self = this;
+ let oldChan = this.oldChannel;
+ this.realRedirect = !!realRedirect;
+ if (typeof(callback) !== "function") {
+ callback = this._defaultCallback;
+ }
+ ChannelReplacement.runWhenPending(oldChan, function() {
+ if (oldChan.status) return; // channel's doom had been already defined
+
+ let ccl = new CtxCapturingListener(oldChan, self);
+ self.loadGroup = oldChan.loadGroup;
+
+ oldChan.loadGroup = null; // prevents the wheel from stopping spinning
+
+
+ if (self._redirectCallback) { // Gecko >= 2
+ // this calls asyncAbort, which calls onStartRequest on our listener
+ oldChan.cancel(NS_BINDING_REDIRECTED);
+ self.suspend(); // believe it or not, this will defer asyncAbort() notifications until resume()
+ callback(self);
+ } else {
+ // legacy (Gecko < 2)
+ self.observeCapture = function(req, ccl) {
+ self.open = function() { self._redirect(ccl); };
+ callback(self);
+ };
+ oldChan.cancel(NS_BINDING_REDIRECTED);
+ }
+
+
+ });
+ },
+
+ observeCapture: function(req, ccl) {
+ this._redirect(ccl);
+ },
+
+ _defaultCallback: function(replacement) {
+ replacement.open();
+ },
+
+ open: function() {
+ this.resume(); // this triggers asyncAbort and the listeners in cascade
+ },
+ _redirect: function(ccl) {
+ let oldChan = this.oldChannel,
+ newChan = this.channel,
+ overlap;
+
+ if (!(this.window && (overlap = this.window._replacedChannel) !== oldChan)) {
+ try {
+ if (ABE.consoleDump && this.window) {
+ ABE.log("Opening delayed channel: " + oldChan.name + " - (current loading channel for this window " + (overlap && overlap.name) + ")");
+ }
+
+ oldChan.loadGroup = this.loadGroup;
+
+ this._onChannelRedirect();
+ newChan.asyncOpen(ccl.originalListener, ccl.originalCtx);
+
+ if (this.window && this.window != IOUtil.findWindow(newChan)) {
+ // late diverted load, unwanted artifact, abort
+ IOUtil.abort(newChan);
+ } else {
+ // safe browsing hook
+ if (this._classifierClass)
+ this._classifierClass.createInstance(Ci.nsIChannelClassifier).start(newChan, true);
+ }
+ } catch (e) {
+ ABE.log(e);
+ }
+ } else {
+ if (ABE.consoleDump) {
+ ABE.log("Detected double load on the same window: " + oldChan.name + " - " + (overlap && overlap.name));
+ }
+ }
+
+ this.dispose();
+ },
+
+ suspend: function() {
+ if (!this.suspended) {
+ this.oldChannel.suspend();
+ this.suspended = true;
+ }
+ },
+ resume: function() {
+ if (this.suspended) {
+ this.suspended = false;
+ try {
+ this.oldChannel.resume();
+ } catch (e) {}
+ }
+ },
+
+ dispose: function() {
+ this.resume();
+ if (this.loadGroup) {
+ try {
+ this.loadGroup.removeRequest(this.oldChannel, null, NS_BINDING_REDIRECTED);
+ } catch (e) {}
+ this.loadGroup = null;
+ }
+
+ }
+};
+
+function LoadGroupWrapper(channel, callback) {
+ this._channel = channel;
+ this._inner = channel.loadGroup;
+ this._callback = callback;
+ channel.loadGroup = this;
+}
+LoadGroupWrapper.prototype = {
+ QueryInterface: xpcom_generateQI([Ci.nsILoadGroup]),
+
+ get activeCount() {
+ return this._inner ? this._inner.activeCount : 0;
+ },
+ set defaultLoadRequest(v) {
+ return this._inner ? this._inner.defaultLoadRequest = v : v;
+ },
+ get defaultLoadRequest() {
+ return this._inner ? this._inner.defaultLoadRequest : null;
+ },
+ set groupObserver(v) {
+ return this._inner ? this._inner.groupObserver = v : v;
+ },
+ get groupObserver() {
+ return this._inner ? this._inner.groupObserver : null;
+ },
+ set notificationCallbacks(v) {
+ return this._inner ? this._inner.notificationCallbacks = v : v;
+ },
+ get notificationCallbacks() {
+ return this._inner ? this._inner.notificationCallbacks : null;
+ },
+ get requests() {
+ return this._inner ? this._inner.requests : this._emptyEnum;
+ },
+
+ addRequest: function(r, ctx) {
+ this.detach();
+ if (this._inner) try {
+ this._inner.addRequest(r, ctx);
+ } catch(e) {
+ // addRequest may have not been implemented
+ }
+ if (r === this._channel)
+ try {
+ this._callback(r, ctx);
+ } catch (e) {}
+ },
+ removeRequest: function(r, ctx, status) {
+ this.detach();
+ if (this._inner) this._inner.removeRequest(r, ctx, status);
+ },
+
+ detach: function() {
+ if (this._channel.loadGroup) this._channel.loadGroup = this._inner;
+ },
+ _emptyEnum: {
+ QueryInterface: xpcom_generateQI([Ci.nsISimpleEnumerator]),
+ getNext: function() { return null; },
+ hasMoreElements: function() { return false; }
+ }
+};
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/code/Cookie.js b/data/extensions/https-everywhere@eff.org/chrome/content/code/Cookie.js
new file mode 100644
index 0000000..9afe0a8
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/code/Cookie.js
@@ -0,0 +1,148 @@
+function Cookie(s, host) {
+ this.parse(s, host);
+}
+Cookie.computeId = function(c) {
+ return c.name + ";" + c.host + "/" + c.path;
+};
+Cookie.find = function(f) {
+ var cc = Cookie.prototype.cookieManager.enumerator;
+ var c;
+ while (cc.hasMoreElements()) {
+ if (f(c = cc.getNext())) return c;
+ }
+ return null;
+};
+
+Cookie.attributes = { host: 'domain', path: 'path', expires: 'expires', isHttpOnly: 'HttpOnly', isSecure: 'Secure' };
+Cookie.prototype = {
+
+ name: '',
+ value: '',
+ source: '',
+ domain: '',
+ host: '',
+ rawHost: '',
+ path: '',
+ secure: false,
+ httponly: false,
+ session: true,
+ expires: 0,
+
+ id: '',
+
+
+ toString: function() {
+ var c = [this['name'] + "=" + this.value];
+ var v;
+ const aa = Cookie.attributes;
+ for (var k in aa) {
+ var p = aa[k];
+ v = this[k];
+ switch(typeof(v)) {
+ case "string":
+ if (v) c.push(p + "=" + v);
+ break;
+ case "boolean":
+ if (v) c.push(p);
+ break;
+ case "number":
+ if (!this.isSession) c.push(p + "=" + new Date(v * 1000).toUTCString());
+ break;
+ }
+ }
+ return c.join("; ");
+ },
+ parse: function(s, host) {
+ var p;
+ if (this.source) {
+ // cleanup for recycle
+ for (p in this) {
+ if (typeof (p) != "function") delete this[p];
+ }
+ }
+ this.source = s;
+ this.host = host;
+
+ var parts = s.split(/;\s*/);
+ var nv = parts.shift().split("=");
+
+ this.name = nv.shift() || '';
+ this.value = nv.join('=') || '';
+
+ var n, v;
+ for each (p in parts) {
+ nv = p.split("=");
+ switch (n = nv[0].toLowerCase()) {
+ case 'expires':
+ v = Math.round(Date.parse((nv[1] || '').replace(/\-/g, ' ')) / 1000);
+ break;
+ case 'domain':
+ case 'path':
+ v = nv[1] || '';
+ break;
+ case 'secure':
+ case 'httponly':
+ v = true;
+ break;
+ default:
+ n = 'unknown';
+ }
+ this[n] = v;
+ }
+ if (!this.expires) {
+ this.session = true;
+ this.expires = Math.round(new Date() / 1000) + 31536000;
+ }
+ if (this.domain) {
+ if (!this.isDomain) this.domain = "." + this.domain;
+ this.host = this.domain;
+ }
+ this.rawHost = this.host.replace(/^\./, '');
+
+ this.id = Cookie.computeId(this);
+ },
+
+
+ get cookieManager() {
+ delete Cookie.prototype.cookieManager;
+ var cman = Cc["@mozilla.org/cookiemanager;1"]
+ .getService(Ci.nsICookieManager2).QueryInterface(Ci.nsICookieManager);
+ return Cookie.prototype.cookieManager = cman;
+ },
+ belongsTo: function(host, path) {
+ if (path && this.path && path.indexOf(this.path) != 0) return false;
+ if (host == this.rawHost) return true;
+ var d = this.domain;
+ return d && (host == d || this.isDomain && host.slice(-d.length) == d);
+ },
+ save: function() {
+ this.save = ("cookieExists" in this.cookieManager)
+ ? function() { this.cookieManager.add(this.host, this.path, this.name, this.value, this.secure, this.httponly, this.session, this.expires); }
+ : function() { this.cookieManager.add(this.host, this.path, this.name, this.value, this.secure, this.session, this.expires);}
+ ;
+ return this.save();
+ },
+ exists: function() {
+ var cc = this.cookieManager.enumerator;
+ while(cc.hasMoreElements()) {
+ if (this.sameAs(cc.getNext())) return true;
+ }
+ return false;
+ },
+
+ sameAs: function(c) {
+ (c instanceof Ci.nsICookie) && (c instanceof Ci.nsICookie2);
+ return Cookie.computeId(c) == this.id;
+ },
+
+ // nsICookie2 interface extras
+ get isSecure() { return this.secure; },
+ get expiry() { return this.expires; },
+ get isSession() { return this.session; },
+ get isHttpOnly() { return this.httponly; },
+ get isDomain() { return this.domain && this.domain[0] == '.'; },
+ policy: 0,
+ status: 0,
+ QueryInterface: xpcom_generateQI([Ci.nsICookie, Ci.nsICookie2])
+
+};
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/code/HTTPS.js b/data/extensions/https-everywhere@eff.org/chrome/content/code/HTTPS.js
new file mode 100644
index 0000000..c39a0ef
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/code/HTTPS.js
@@ -0,0 +1,296 @@
+INCLUDE('Cookie');
+// XXX: Disable STS for now.
+var STS = {
+ isSTSURI : function(uri) {
+ return false;
+ }
+};
+
+// Hack. We only need the part of the policystate that tracks content
+// policy loading.
+const PolicyState = {
+ attach: function(channel) {
+ IOUtil.attachToChannel(channel, "httpseverywhere.policyLoaded", true);
+ },
+
+ extract: function(channel) {
+ var res = IOUtil.extractFromChannel(channel,
+ "httpseverywhere.policyLoaded", true);
+ return res;
+ },
+};
+
+const HTTPS = {
+ ready: false,
+
+ secureCookies: true,
+ secureCookiesExceptions: null,
+ secureCookiesForced: null,
+ httpsForced: null,
+ httpsForcedExceptions: null,
+ httpsRewrite: null,
+
+ replaceChannel: function(applicable_list, channel) {
+ var blob = HTTPSRules.rewrittenURI(applicable_list, channel.URI.clone());
+ if (null == blob) return false; // no rewrite
+ var uri = blob.newuri;
+ if (!uri) this.log(WARN, "OH NO BAD ARGH\nARGH");
+
+ var c2 = channel.QueryInterface(CI.nsIHttpChannel);
+ this.log(DBUG, channel.URI.spec+": Redirection limit is " + c2.redirectionLimit);
+ // XXX This used to be (c2.redirectionLimit == 1), but that's very
+ // inefficient in a case (eg amazon) where this may happen A LOT.
+ // Rather than number like 10, we should use the starting value
+ // in network.http.redirection-limit minus some counter
+ if (c2.redirectionLimit < 10) {
+ this.log(WARN, "Redirection loop trying to set HTTPS on:\n " +
+ channel.URI.spec +"\n(falling back to HTTP)");
+ if (!blob.applied_ruleset) {
+ this.log(WARN,"Blacklisting rule for: " + channel.URI.spec);
+ https_everywhere_blacklist[channel.URI.spec] = true;
+ }
+ https_everywhere_blacklist[channel.URI.spec] = blob.applied_ruleset;
+ var domain = null;
+ try { domain = channel.URI.host; } catch (e) {}
+ if (domain) https_blacklist_domains[domain] = true;
+ return false;
+ }
+
+ // Check for the new internal redirect API. If it exists, use it.
+ if (!"redirectTo" in channel) {
+ this.log(WARN, "nsIHTTPChannel.redirectTo API is missing. This version of HTTPS Everywhere is useless!!!!\n!!!\n");
+ return false;
+ }
+
+ this.log(INFO, "Using nsIHttpChannel.redirectTo: " + channel.URI.spec + " -> " + uri.spec);
+ try {
+ channel.redirectTo(uri);
+ return true;
+ } catch(e) {
+ // This should not happen. We should only get exceptions if
+ // the channel was already open.
+ this.log(WARN, "Exception on nsIHttpChannel.redirectTo: "+e);
+
+ // Don't return: Fallback to NoScript ChannelReplacement.js
+ }
+ this.log(WARN,"Aborting redirection " + channel.name + ", should be HTTPS!");
+ IOUtil.abort(channel);
+ return false;
+ },
+
+ // getApplicableListForContext was remove along with the nsIContentPolicy
+ // bindings and the and forceURI path that used them.
+
+ onCrossSiteRequest: function(channel, origin, browser, rw) {
+ try {
+ this.handleCrossSiteCookies(channel, origin, browser);
+ } catch(e) {
+ this.log(WARN, e + " --- " + e.stack);
+ }
+ },
+
+ registered: false,
+ handleSecureCookies: function(req) {
+
+ try {
+ req = req.QueryInterface(CI.nsIHttpChannel);
+ } catch(e) {
+ this.log(WARN, "Request is not an nsIHttpChannel: " + req);
+ return;
+ }
+ if (!this.secureCookies) return;
+ var uri = req.URI;
+ if (!uri) {
+ this.log(WARN,"No URI inside request " +req);
+ return;
+ }
+ //this.log(DBUG, "Cookie hunting in " + uri.spec);
+ var alist = HTTPSEverywhere.instance.getApplicableListForChannel(req);
+ if (!alist)
+ this.log(INFO, "No alist for cookies for "+(req.URI) ? req.URI.spec : "???");
+
+ if (uri.schemeIs("https")) {
+ var host = uri.host;
+ try {
+ var cookies = req.getResponseHeader("Set-Cookie");
+ } catch(mayHappen) {
+ //this.log(VERB,"Exception hunting Set-Cookie in headers: " + mayHappen);
+ return;
+ }
+ if (!cookies) return;
+ var c;
+ for each (var cs in cookies.split("\n")) {
+ this.log(DBUG, "Examining cookie: ");
+ c = new Cookie(cs, host);
+ if (!c.secure && HTTPSRules.shouldSecureCookie(alist, c, true)) {
+ this.log(INFO, "Securing cookie: " + c.domain + " " + c.name);
+ c.secure = true;
+ req.setResponseHeader("Set-Cookie", c.source + ";Secure", true);
+ }
+ }
+
+ }
+ },
+
+ handleInsecureCookie: function(c) {
+ if (HTTPSRules.shouldSecureCookie(null, c, false)) {
+ this.log(INFO, "Securing cookie from event: " + c.domain + " " + c.name);
+ var cookieManager = Components.classes["@mozilla.org/cookiemanager;1"]
+ .getService(Components.interfaces.nsICookieManager2);
+ //some braindead cookies apparently use umghzabilliontrabilions
+ var expiry = Math.min(c.expiry, Math.pow(2,31));
+ cookieManager.remove(c.host, c.name, c.path, false);
+ cookieManager.add(c.host, c.path, c.name, c.value, true, c.isHTTPOnly, c.isSession, expiry);
+ }
+ },
+
+ handleCrossSiteCookies: function(req, origin, browser) {
+
+ var unsafeCookies = this.getUnsafeCookies(browser);
+ if (!unsafeCookies) return;
+
+ var uri = req.URI;
+ var dscheme = uri.scheme;
+
+ var oparts = origin && origin.match(/^(https?):\/\/([^\/:]+).*?(\/.*)/);
+ if (!(oparts && /https?/.test(dscheme))) return;
+
+ var oscheme = oparts[1];
+ if (oscheme == dscheme) return; // we want to check only cross-scheme requests
+
+ var dsecure = dscheme == "https";
+
+ if (dsecure && !ns.getPref("secureCookies.recycle", false)) return;
+
+ var dhost = uri.host;
+ var dpath = uri.path;
+
+ var ohost = oparts[2];
+ var opath = oparts[3];
+
+ var ocookieCount = 0, totCount = 0;
+ var dcookies = [];
+ var c;
+
+ for (var k in unsafeCookies) {
+ c = unsafeCookies[k];
+ if (!c.exists()) {
+ delete unsafeCookies[k];
+ } else {
+ totCount++;
+ if (c.belongsTo(dhost, dpath) && c.secure != dsecure) { // either secure on http or not secure on https
+ dcookies.push(c);
+ }
+ if (c.belongsTo(ohost, opath)) {
+ ocookieCount++;
+ }
+ }
+ }
+
+ if (!totCount) {
+ this.setUnsafeCookies(browser, null);
+ return;
+ }
+
+ // We want to "desecurify" cookies only if cross-navigation to unsafe
+ // destination originates from a site sharing some secured cookies
+
+ if (ocookieCount == 0 && !dsecure || !dcookies.length) return;
+
+ if (dsecure) {
+ this.log(WARN,"Detected cross-site navigation with secured cookies: " + origin + " -> " + uri.spec);
+
+ } else {
+ this.log(WARN,"Detected unsafe navigation with NoScript-secured cookies: " + origin + " -> " + uri.spec);
+ this.log(WARN,uri.prePath + " cannot support secure cookies because it does not use HTTPS. Consider forcing HTTPS for " + uri.host + " in NoScript's Advanced HTTPS options panel.");
+ }
+
+ var cs = CC['@mozilla.org/cookieService;1'].getService(CI.nsICookieService).getCookieString(uri, req);
+
+ for each (c in dcookies) {
+ c.secure = dsecure;
+ c.save();
+ this.log(WARN,"Toggled secure flag on " + c);
+ }
+
+ if (cs) {
+ dcookies.push.apply(
+ dcookies, cs.split(/\s*;\s*/).map(function(cs) { var nv = cs.split("="); return { name: nv.shift(), value: nv.join("=") }; })
+ .filter(function(c) { return dcookies.every(function(x) { return x.name != c.name; }); })
+ );
+ }
+
+ cs = dcookies.map(function(c) { return c.name + "=" + c.value; }).join("; ");
+
+ this.log(WARN,"Sending Cookie for " + dhost + ": " + cs);
+ req.setRequestHeader("Cookie", cs, false); // "false" because merge syntax breaks Cookie header
+ },
+
+
+ cookiesCleanup: function(refCookie) {
+ var downgraded = [];
+
+ var ignored = this.secureCookiesExceptions;
+ var disabled = !this.secureCookies;
+ var bi = DOM.createBrowserIterator();
+ var unsafe, k, c, total, deleted;
+ for (var browser; browser = bi.next();) {
+ unsafe = this.getUnsafeCookies(browser);
+ if (!unsafe) continue;
+ total = deleted = 0;
+ for (k in unsafe) {
+ c = unsafe[k];
+ total++;
+ if (disabled || (refCookie ? c.belongsTo(refCookie.host) : ignored && ignored.test(c.rawHost))) {
+ if (c.exists()) {
+ this.log(WARN,"Cleaning Secure flag from " + c);
+ c.secure = false;
+ c.save();
+ }
+ delete unsafe[k];
+ deleted++;
+ }
+ }
+ if (total == deleted) this.setUnsafeCookies(browser, null);
+ if (!this.cookiesPerTab) break;
+ }
+ },
+
+ get cookiesPerTab() {
+ return ns.getPref("secureCookies.perTab", false);
+ },
+
+ _globalUnsafeCookies: {},
+ getUnsafeCookies: function(browser) {
+ return this.cookiesPerTab
+ ? browser && ns.getExpando(browser, "unsafeCookies")
+ : this._globalUnsafeCookies;
+ },
+ setUnsafeCookies: function(browser, value) {
+ return this.cookiesPerTab
+ ? browser && ns.setExpando(browser, "unsafeCookies", value)
+ : this._globalUnsafeCookies = value;
+ },
+
+ _getParent: function(req, w) {
+ return w && w.frameElement || DOM.findBrowserForNode(w || IOUtil.findWindow(req));
+ }
+
+};
+
+(function () {
+ ["secureCookies", "secureCookiesExceptions", "secureCookiesForced"].forEach(function(p) {
+ var v = HTTPS[p];
+ delete HTTPS[p];
+ HTTPS.__defineGetter__(p, function() {
+ return v;
+ });
+ HTTPS.__defineSetter__(p, function(n) {
+ v = n;
+ if (HTTPS.ready) HTTPS.cookiesCleanup();
+ return v;
+ });
+ });
+})();
+
+HTTPS.ready = true;
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/code/HTTPSRules.js b/data/extensions/https-everywhere@eff.org/chrome/content/code/HTTPSRules.js
new file mode 100644
index 0000000..ecbaf76
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/code/HTTPSRules.js
@@ -0,0 +1,762 @@
+// Compilation of RegExps is now delayed until they are first used...
+
+function Rule(from, to) {
+ this.to = to;
+ this.from_c = from; // This will become a RegExp after compilation
+}
+
+function Exclusion(pattern) {
+ this.pattern_c = pattern; // Will become a RegExp after compilation
+}
+
+function CookieRule(host, cookiename) {
+ this.host = host;
+ this.name = cookiename;
+
+ // These will be made during compilation:
+
+ //this.host_c = new RegExp(host);
+ //this.name_c = new RegExp(cookiename);
+}
+
+function RuleSet(id, name, xmlName, match_rule, default_off, platform) {
+ if(xmlName == "WordPress.xml" || xmlName == "Github.xml") {
+ this.log(NOTE, "RuleSet( name="+name+", xmlName="+xmlName+", match_rule="+match_rule+", default_off="+default_off+", platform="+platform+" )");
+ }
+
+ this.id=id;
+ this.on_by_default = true;
+ this.compiled = false;
+ this.name = name;
+ this.xmlName = xmlName;
+ this.notes = "";
+ if (match_rule) this.ruleset_match_c = new RegExp(match_rule);
+ else this.ruleset_match_c = null;
+ if (default_off) {
+ // Perhaps problematically, this currently ignores the actual content of
+ // the default_off XML attribute. Ideally we'd like this attribute to be
+ // "valueless"
+ this.notes = default_off;
+ this.on_by_default = false;
+ }
+ if (platform)
+ if (platform.search(HTTPSRules.localPlatformRegexp) == -1) {
+ this.on_by_default = false;
+ this.notes = "Only for " + platform;
+ }
+
+ this.rules = [];
+ this.exclusions = [];
+ this.cookierules = [];
+
+ this.rule_toggle_prefs = HTTPSEverywhere.instance.rule_toggle_prefs;
+
+ try {
+ // if this pref exists, use it
+ this.active = this.rule_toggle_prefs.getBoolPref(name);
+ } catch(e) {
+ // if not, use the default
+ this.active = this.on_by_default;
+ }
+}
+
+var dom_parser = Cc["@mozilla.org/xmlextras/domparser;1"].createInstance(Ci.nsIDOMParser);
+
+RuleSet.prototype = {
+
+ ensureCompiled: function() {
+ // Postpone compilation of exclusions, rules and cookies until now, to accelerate
+ // browser load time.
+ if (this.compiled) return;
+ var i;
+
+ for (i = 0; i < this.exclusions.length; ++i) {
+ this.exclusions[i].pattern_c = new RegExp(this.exclusions[i].pattern_c);
+ }
+ for (i = 0; i < this.rules.length; ++i) {
+ this.rules[i].from_c = new RegExp(this.rules[i].from_c);
+ }
+
+ for (i = 0; i < this.cookierules.length; i++) {
+ var cr = this.cookierules[i];
+ cr.host_c = new RegExp(cr.host);
+ cr.name_c = new RegExp(cr.name);
+ }
+
+ this.compiled = true;
+ },
+
+ apply: function(urispec) {
+ // return null if it does not apply
+ // and the new url if it does apply
+ var i;
+ var returl = null;
+ this.ensureCompiled();
+ // If a rulset has a match_rule and it fails, go no further
+ if (this.ruleset_match_c && !this.ruleset_match_c.test(urispec)) {
+ this.log(VERB, "ruleset_match_c excluded " + urispec);
+ return null;
+ }
+ // Even so, if we're covered by an exclusion, go home
+ for (i = 0; i < this.exclusions.length; ++i) {
+ if (this.exclusions[i].pattern_c.test(urispec)) {
+ this.log(DBUG,"excluded uri " + urispec);
+ return null;
+ }
+ }
+ // Okay, now find the first rule that triggers
+ for (i = 0; i < this.rules.length; ++i) {
+ // This is just for displaying inactive rules
+ returl = urispec.replace(this.rules[i].from_c, this.rules[i].to);
+ if (returl != urispec) return returl;
+ }
+
+ return null;
+ },
+ log: function(level, msg) {
+ https_everywhereLog(level, msg);
+ },
+
+ wouldMatch: function(hypothetical_uri, alist) {
+ // return true if this ruleset would match the uri, assuming it were http
+ // used for judging moot / inactive rulesets
+ // alist is optional
+
+ // if the ruleset is already somewhere in this applicable list, we don't
+ // care about hypothetical wouldMatch questions
+ if (alist && (this.name in alist.all)) return false;
+
+ this.log(DBUG,"Would " +this.name + " match " +hypothetical_uri.spec +
+ "? serial " + (alist && alist.serial));
+
+ var uri = hypothetical_uri.clone();
+ if (uri.scheme == "https") uri.scheme = "http";
+ var urispec = uri.spec;
+
+ this.ensureCompiled();
+
+ if (this.ruleset_match_c && !this.ruleset_match_c.test(urispec))
+ return false;
+
+ for (var i = 0; i < this.exclusions.length; ++i)
+ if (this.exclusions[i].pattern_c.test(urispec)) return false;
+
+ for (var i = 0; i < this.rules.length; ++i)
+ if (this.rules[i].from_c.test(urispec)) return true;
+ return false;
+ },
+
+ transformURI: function(uri) {
+ // If no rule applies, return null; if a rule would have applied but was
+ // inactive, return 0; otherwise, return a fresh uri instance
+ // for the target
+ var newurl = this.apply(uri.spec);
+ if (null == newurl)
+ return null;
+ var newuri = Components.classes["@mozilla.org/network/standard-url;1"].
+ createInstance(CI.nsIStandardURL);
+ newuri.init(CI.nsIStandardURL.URLTYPE_STANDARD, 80,
+ newurl, uri.originCharset, null);
+ newuri = newuri.QueryInterface(CI.nsIURI);
+ return newuri;
+ },
+
+ enable: function() {
+ // Enable us.
+ this.rule_toggle_prefs.setBoolPref(this.name, true);
+ this.active = true;
+ },
+
+ disable: function() {
+ // Disable us.
+ this.rule_toggle_prefs.setBoolPref(this.name, false);
+ this.active = false;
+ },
+
+ toggle: function() {
+ this.active = !this.active;
+ this.rule_toggle_prefs.setBoolPref(this.name, this.active);
+ },
+
+ clear: function() {
+ try {
+ this.rule_toggle_prefs.clearUserPref(this.name);
+ } catch(e) {
+ // this ruleset has never been toggled
+ }
+ this.active = this.on_by_default;
+ }
+};
+
+const RuleWriter = {
+
+ getCustomRuleDir: function() {
+ var loc = "ProfD"; // profile directory
+ var file =
+ CC["@mozilla.org/file/directory_service;1"]
+ .getService(CI.nsIProperties)
+ .get(loc, CI.nsILocalFile)
+ .clone();
+ file.append("HTTPSEverywhereUserRules");
+ // Check for existence, if not, create.
+ if (!file.exists()) {
+ file.create(CI.nsIFile.DIRECTORY_TYPE, 0700);
+ }
+ if (!file.isDirectory()) {
+ // XXX: Arg, death!
+ }
+ return file;
+ },
+
+ chromeToPath: function (aPath) {
+ if (!aPath || !(/^chrome:/.test(aPath)))
+ return; //not a chrome url
+
+ var ios =
+ CC['@mozilla.org/network/io-service;1']
+ .getService(CI.nsIIOService);
+ var uri = ios.newURI(aPath, "UTF-8", null);
+ var cr =
+ CC['@mozilla.org/chrome/chrome-registry;1']
+ .getService(CI.nsIChromeRegistry);
+ var rv = cr.convertChromeURL(uri).spec;
+
+ if (/^file:/.test(rv))
+ rv = this.urlToPath(rv);
+ else
+ rv = this.urlToPath("file://"+rv);
+
+ return rv;
+ },
+
+ urlToPath: function (aPath) {
+ if (!aPath || !/^file:/.test(aPath))
+ return ;
+
+ var ph =
+ CC["@mozilla.org/network/protocol;1?name=file"]
+ .createInstance(CI.nsIFileProtocolHandler);
+ var rv = ph.getFileFromURLSpec(aPath).path;
+
+ return rv;
+ },
+
+ read: function(file, rule_store, ruleset_id) {
+ if (!file.exists())
+ return null;
+ if ((rule_store.targets == null) && (rule_store.targets != {}))
+ this.log(WARN, "TARGETS IS NULL");
+ var data = "";
+ var fstream = CC["@mozilla.org/network/file-input-stream;1"]
+ .createInstance(CI.nsIFileInputStream);
+ var sstream = CC["@mozilla.org/scriptableinputstream;1"]
+ .createInstance(CI.nsIScriptableInputStream);
+ fstream.init(file, -1, 0, 0);
+ sstream.init(fstream);
+
+ var str = sstream.read(4096);
+ while (str.length > 0) {
+ data += str;
+ str = sstream.read(4096);
+ }
+
+ sstream.close();
+ fstream.close();
+ return this.readFromString(data, rule_store, ruleset_id);
+ },
+
+ readFromString: function(data, rule_store, ruleset_id) {
+ try {
+ var xmlruleset = dom_parser.parseFromString(data, "text/xml");
+ } catch(e) { // file has been corrupted; XXX: handle error differently
+ this.log(WARN,"Error in XML data: " + e + "\n" + data);
+ return null;
+ }
+ this.parseOneRuleset(xmlruleset.documentElement, rule_store, ruleset_id);
+ },
+
+ parseOneRuleset: function(xmlruleset, rule_store, ruleset_id) {
+ // Extract an xmlruleset into the rulestore
+ if (!xmlruleset.getAttribute("name")) {
+ this.log(WARN, "This blob: '" + xmlruleset + "' is not a ruleset\n");
+ return null;
+ }
+
+ this.log(DBUG, "Parsing " + xmlruleset.getAttribute("name"));
+
+ var match_rl = xmlruleset.getAttribute("match_rule");
+ var dflt_off = xmlruleset.getAttribute("default_off");
+ var platform = xmlruleset.getAttribute("platform");
+ var rs = new RuleSet(ruleset_id, xmlruleset.getAttribute("name"), xmlruleset.getAttribute("f"), match_rl, dflt_off, platform);
+
+ // see if this ruleset has the same name as an existing ruleset;
+ // if so, this ruleset is ignored; DON'T add or return it.
+ if (rs.name in rule_store.rulesetsByName) {
+ this.log(WARN, "Error: found duplicate rule name " + rs.name);
+ return null;
+ }
+
+ // Add this ruleset id into HTTPSRules.targets if it's not already there.
+ // This should only happen for custom user rules. Built-in rules get
+ // their ids preloaded into the targets map, and have their <target>
+ // tags stripped when the sqlite database is built.
+ var targets = xmlruleset.getElementsByTagName("target");
+ for (var i = 0; i < targets.length; i++) {
+ var host = targets[i].getAttribute("host");
+ if (!host) {
+ this.log(WARN, "<target> missing host in " + xmlruleset.getAttribute("name"));
+ return null;
+ }
+ if (! rule_store.targets[host])
+ rule_store.targets[host] = [];
+ this.log(DBUG, "Adding " + host + " to targets, pointing at " + ruleset_id);
+ rule_store.targets[host].push(ruleset_id);
+ }
+
+ var exclusions = xmlruleset.getElementsByTagName("exclusion");
+ for (var i = 0; i < exclusions.length; i++) {
+ var exclusion = new Exclusion(exclusions[i].getAttribute("pattern"));
+ rs.exclusions.push(exclusion);
+ }
+
+ var rules = xmlruleset.getElementsByTagName("rule");
+ for (var i = 0; i < rules.length; i++) {
+ var rule = new Rule(rules[i].getAttribute("from"),
+ rules[i].getAttribute("to"));
+ rs.rules.push(rule);
+ }
+
+ var securecookies = xmlruleset.getElementsByTagName("securecookie");
+ for (var i = 0; i < securecookies.length; i++) {
+ var c_rule = new CookieRule(securecookies[i].getAttribute("host"),
+ securecookies[i].getAttribute("name"));
+ rs.cookierules.push(c_rule);
+ this.log(DBUG,"Cookie rule "+ c_rule.host+ " " +c_rule.name);
+ }
+
+ rule_store.rulesets.push(rs);
+ rule_store.rulesetsByID[rs.id] = rs;
+ rule_store.rulesetsByName[rs.name] = rs;
+ },
+
+ enumerate: function(dir) {
+ // file is the given directory (nsIFile)
+ var entries = dir.directoryEntries;
+ var ret = [];
+ while(entries.hasMoreElements()) {
+ var entry = entries.getNext();
+ entry.QueryInterface(Components.interfaces.nsIFile);
+ ret.push(entry);
+ }
+ return ret;
+ },
+};
+
+
+
+const HTTPSRules = {
+ init: function() {
+ try {
+ this.rulesets = [];
+ this.targets = {}; // dict mapping target host pattern -> list of
+ // applicable ruleset ids
+ this.rulesetsByID = {};
+ this.rulesetsByName = {};
+ var t1 = new Date().getTime();
+ this.checkMixedContentHandling();
+ var rulefiles = RuleWriter.enumerate(RuleWriter.getCustomRuleDir());
+ this.scanRulefiles(rulefiles);
+
+ // Initialize database connection.
+ var dbFile = new FileUtils.File(RuleWriter.chromeToPath("chrome://https-everywhere/content/rulesets.sqlite"));
+ var rulesetDBConn = Services.storage.openDatabase(dbFile);
+ this.queryForRuleset = rulesetDBConn.createStatement(
+ "select contents from rulesets where id = :id");
+
+ // Preload the mapping of hostname target -> ruleset ID from DB.
+ // This is a little slow (287 ms on a Core2 Duo @ 2.2GHz with SSD),
+ // but is faster than loading all of the rulesets. If this becomes a
+ // bottleneck, change it to load in a background webworker, or load
+ // a smaller bloom filter instead.
+ var targetsQuery = rulesetDBConn.createStatement("select host, ruleset_id from targets");
+ this.log(DBUG, "Loading targets...");
+ while (targetsQuery.executeStep()) {
+ var host = targetsQuery.row.host;
+ var id = targetsQuery.row.ruleset_id;
+ if (!this.targets[host]) {
+ this.targets[host] = [id];
+ } else {
+ this.targets[host].push(id);
+ }
+ }
+ this.log(DBUG, "Loading adding targets.");
+ } catch(e) {
+ this.log(DBUG,"Rules Failed: "+e);
+ }
+ var t2 = new Date().getTime();
+ this.log(NOTE,"Loading targets took " + (t2 - t1) / 1000.0 + " seconds");
+
+ var gitCommitQuery = rulesetDBConn.createStatement("select git_commit from git_commit");
+ if (gitCommitQuery.executeStep()) {
+ this.GITCommitID = gitCommitQuery.row.git_commit;
+ }
+
+ try {
+ if (HTTPSEverywhere.instance.prefs.getBoolPref("performance_tests")) {
+ this.testRulesetRetrievalPerformance();
+ }
+ } catch(e) {
+ this.log(WARN, "Exception during testing " + e);
+ }
+ return;
+ },
+
+ checkMixedContentHandling: function() {
+ // Firefox 23+ blocks mixed content by default, so rulesets that create
+ // mixed content situations should be disabled there
+ var appInfo = CC["@mozilla.org/xre/app-info;1"].getService(CI.nsIXULAppInfo);
+ var platformVer = appInfo.platformVersion;
+ var versionChecker = CC["@mozilla.org/xpcom/version-comparator;1"]
+ .getService(CI.nsIVersionComparator);
+ var prefs = Components.classes["@mozilla.org/preferences-service;1"]
+ .getService(Components.interfaces.nsIPrefService).getBranch("");
+
+
+ // If mixed content is present and enabled, and the user hasn't opted to enable
+ // mixed content triggering rules, leave them out. Otherwise add them in.
+ if(versionChecker.compare(appInfo.version, "23.0a1") >= 0
+ && prefs.getBoolPref("security.mixed_content.block_active_content")
+ && !prefs.getBoolPref("extensions.https_everywhere.enable_mixed_rulesets")) {
+ this.log(INFO, "Not activating rules that trigger mixed content errors.");
+ this.localPlatformRegexp = new RegExp("firefox");
+ } else {
+ this.log(INFO, "Activating rules that would normally trigger mixed content");
+ this.localPlatformRegexp = new RegExp("(firefox|mixedcontent)");
+ }
+ },
+
+ scanRulefiles: function(rulefiles) {
+ var i = 0;
+ var r = null;
+ for(i = 0; i < rulefiles.length; ++i) {
+ try {
+ this.log(DBUG,"Loading ruleset file: "+rulefiles[i].path);
+ var ruleset_id = "custom_" + i;
+ RuleWriter.read(rulefiles[i], this, ruleset_id);
+ } catch(e) {
+ this.log(WARN, "Error in ruleset file: " + e);
+ if (e.lineNumber)
+ this.log(WARN, "(line number: " + e.lineNumber + ")");
+ }
+ }
+ },
+
+ resetRulesetsToDefaults: function() {
+ // Callable from within the prefs UI and also for cleaning up buggy
+ // configurations...
+ for (var i in this.rulesets) {
+ this.rulesets[i].clear();
+ }
+ },
+
+ rewrittenURI: function(alist, input_uri) {
+ // This function oversees the task of working out if a uri should be
+ // rewritten, what it should be rewritten to, and recordkeeping of which
+ // applicable rulesets are and aren't active. Previously this returned
+ // the new uri if there was a rewrite. Now it returns a JS object with a
+ // newuri attribute and an applied_ruleset attribute (or null if there's
+ // no rewrite).
+ var i = 0;
+ userpass_present = false; // Global so that sanitiseURI can tweak it.
+ // Why does JS have no tuples, again?
+ var blob = {}; blob.newuri = null;
+ if (!alist) this.log(DBUG, "No applicable list rewriting " + input_uri.spec);
+ this.log(NOTE, "Processing " + input_uri.spec);
+
+ var uri = this.sanitiseURI(input_uri);
+
+ // Get the list of rulesets that target this host
+ try {
+ var rs = this.potentiallyApplicableRulesets(uri.host);
+ } catch(e) {
+ this.log(NOTE, 'Could not check applicable rules for '+uri.spec + '\n'+e);
+ return null;
+ }
+
+ // ponder each potentially applicable ruleset, working out if it applies
+ // and recording it as active/inactive/moot/breaking in the applicable list
+ for (i = 0; i < rs.length; ++i) {
+ if (!rs[i].active) {
+ if (alist && rs[i].wouldMatch(uri, alist))
+ alist.inactive_rule(rs[i]);
+ continue;
+ }
+ blob.newuri = rs[i].transformURI(uri);
+ if (blob.newuri) {
+ // we rewrote the uri
+ this.log(DBUG, "Rewrote "+input_uri.spec);
+ if (alist) {
+ if (uri.spec in https_everywhere_blacklist)
+ alist.breaking_rule(rs[i]);
+ else
+ alist.active_rule(rs[i]);
+ }
+ if (userpass_present) blob.newuri.userPass = input_uri.userPass;
+ blob.applied_ruleset = rs[i];
+ return blob;
+ }
+ if (uri.scheme == "https" && alist) {
+ // we didn't rewrite but the rule applies to this domain and the
+ // requests are going over https
+ if (rs[i].wouldMatch(uri, alist)) alist.moot_rule(rs[i]);
+ continue;
+ }
+ }
+ return null;
+ },
+
+ sanitiseURI: function(input_uri) {
+ // Rulesets shouldn't try to parse usernames and passwords. If we find
+ // those, apply the ruleset without them (and then add them back later).
+ // When .userPass is absent, sometimes it is false and sometimes trying
+ // to read it raises an exception (probably depending on the URI type).
+ var uri = input_uri;
+ try {
+ if (input_uri.userPass) {
+ uri = input_uri.clone();
+ userpass_present = true; // tweaking a global in our caller :(
+ uri.userPass = null;
+ }
+ } catch(e) {}
+
+ // example.com. is equivalent to example.com
+ // example.com.. is invalid, but firefox would load it anyway
+ try {
+ if (uri.host)
+ try {
+ var h = uri.host;
+ if (h.charAt(h.length - 1) == ".") {
+ while (h.charAt(h.length - 1) == ".")
+ h = h.slice(0,-1);
+ uri = uri.clone();
+ uri.host = h;
+ }
+ } catch(e) {
+ this.log(WARN, "Failed to normalise domain: ");
+ try {this.log(WARN, input_uri.host);}
+ catch(e2) {this.log(WARN, "bang" + e + " & " + e2 + " & "+ input_uri);}
+ }
+ } catch(e3) {
+ this.log(INFO, "uri.host is explosive!");
+ try { this.log(INFO, "(" + uri.spec + ")"); } // happens for about: uris and soforth
+ catch(e4) { this.log(WARN, "(and unprintable!!!!!!)"); }
+ }
+ return uri;
+ },
+
+ setInsert: function(intoList, fromList) {
+ // Insert any elements from fromList into intoList, if they are not
+ // already there. fromList may be null.
+ if (!fromList) return;
+ for (var i = 0; i < fromList.length; i++)
+ if (intoList.indexOf(fromList[i]) == -1)
+ intoList.push(fromList[i]);
+ },
+
+ loadAllRulesets: function() {
+ for (var host in this.targets) {
+ var ruleset_ids = this.targets[host];
+ for (var i = 0; i < ruleset_ids.length; i++) {
+ var id = ruleset_ids[i];
+ if (!this.rulesetsByID[id]) {
+ this.loadRulesetById(id);
+ }
+ }
+ }
+ },
+
+ // Load a ruleset by numeric id, e.g. 234
+ // NOTE: This call runs synchronously, which can lock up the browser UI. Is
+ // there any way to fix that, given that we need to run blocking in the request
+ // flow? Perhaps we can preload all targets from the DB into memory at startup
+ // so we only hit the DB when we know there is something to be had.
+ loadRulesetById: function(ruleset_id) {
+ this.log(DBUG, "Querying DB for ruleset id " + ruleset_id);
+ this.queryForRuleset.params.id = ruleset_id;
+
+ try {
+ if (this.queryForRuleset.executeStep()) {
+ this.log(INFO, "Found ruleset in DB for id " + ruleset_id);
+ RuleWriter.readFromString(this.queryForRuleset.row.contents, this, ruleset_id);
+ } else {
+ this.log(WARN,"Couldn't find ruleset for id " + ruleset_id);
+ }
+ } finally {
+ this.queryForRuleset.reset();
+ }
+ },
+
+ // Get all rulesets matching a given target, lazy-loading from DB as necessary.
+ rulesetsByTarget: function(target) {
+ var rulesetIds = this.targets[target];
+
+ var output = [];
+ if (rulesetIds) {
+ this.log(INFO, "For target " + target + ", found ids " + rulesetIds.toString());
+ for (var i = 0; i < rulesetIds.length; i++) {
+ var id = rulesetIds[i];
+ if (!this.rulesetsByID[id]) {
+ this.loadRulesetById(id);
+ }
+ if (this.rulesetsByID[id]) {
+ output.push(this.rulesetsByID[id]);
+ }
+ }
+ } else {
+ this.log(INFO, "For target " + target + ", found no ids in DB");
+ }
+ return output;
+ },
+
+ potentiallyApplicableRulesets: function(host) {
+ // Return a list of rulesets that declare targets matching this host
+ var i, tmp, t;
+ var results = [];
+
+ var attempt = function(target) {
+ this.setInsert(results, this.rulesetsByTarget(target));
+ }.bind(this);
+
+ attempt(host);
+
+ // replace each portion of the domain with a * in turn
+ var segmented = host.split(".");
+ for (i = 0; i < segmented.length; ++i) {
+ tmp = segmented[i];
+ segmented[i] = "*";
+ t = segmented.join(".");
+ segmented[i] = tmp;
+ attempt(t);
+ }
+ // now eat away from the left, with *, so that for x.y.z.google.com we
+ // check *.z.google.com and *.google.com (we did *.y.z.google.com above)
+ for (i = 2; i <= segmented.length - 2; ++i) {
+ t = "*." + segmented.slice(i,segmented.length).join(".");
+ attempt(t);
+ }
+ this.log(DBUG,"Potentially applicable rules for " + host + ":");
+ for (i = 0; i < results.length; ++i)
+ this.log(DBUG, " " + results[i].name);
+ return results;
+ },
+
+ testRulesetRetrievalPerformance: function() {
+ // We can use this function to measure the impact of changes in the ruleset
+ // storage architecture, potentiallyApplicableRulesets() caching
+ // implementations, etc.
+ var req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
+ .createInstance(Ci.nsIXMLHttpRequest);
+ req.open("GET", "https://eff.org/files/alexa-top-10000-global.txt", false);
+ req.send();
+ var domains = req.response.split("\n");
+ var domains_l = domains.length - 1; // The last entry in this thing is bogus
+ var prefix = "";
+ this.log(WARN, "Calling potentiallyApplicableRulesets() with " + domains_l + " domains");
+ var count = 0;
+ var t1 = new Date().getTime();
+ for (var n = 0; n < domains_l; n++) {
+ if (this.potentiallyApplicableRulesets(prefix + domains[n]).length != 0)
+ count++;
+ }
+ var t2 = new Date().getTime();
+ this.log(NOTE, count + " hits: average call to potentiallyApplicableRulesets took " + (t2 - t1) / domains_l + " milliseconds");
+ count = 0;
+ t1 = new Date().getTime();
+ for (var n = 0; n < domains_l; n++) {
+ if (this.potentiallyApplicableRulesets(prefix + domains[n]).length != 0)
+ count++;
+ }
+ t2 = new Date().getTime();
+ this.log(NOTE, count + " hits: average subsequent call to potentiallyApplicableRulesets took " + (t2 - t1) / domains_l + " milliseconds");
+ },
+
+ shouldSecureCookie: function(applicable_list, c, known_https) {
+ // Check to see if the Cookie object c meets any of our cookierule citeria
+ // for being marked as secure.
+ // @applicable_list : an ApplicableList or record keeping
+ // @c : an nsICookie2
+ // @known_https : true if we know the page setting the cookie is https
+
+ this.log(DBUG," rawhost: " + c.rawHost + "\n name: " + c.name + "\n host" + c.host);
+ var i,j;
+ var rs = this.potentiallyApplicableRulesets(c.host);
+ for (i = 0; i < rs.length; ++i) {
+ var ruleset = rs[i];
+ if (ruleset.active) {
+ ruleset.ensureCompiled();
+ // Never secure a cookie if this page might be HTTP
+ if (!known_https && !this.safeToSecureCookie(c.rawHost))
+ continue;
+ for (j = 0; j < ruleset.cookierules.length; j++) {
+ var cr = ruleset.cookierules[j];
+ if (cr.host_c.test(c.host) && cr.name_c.test(c.name)) {
+ if (applicable_list) applicable_list.active_rule(ruleset);
+ this.log(INFO,"Active cookie rule " + ruleset.name);
+ return true;
+ }
+ }
+ if (ruleset.cookierules.length > 0)
+ if (applicable_list) applicable_list.moot_rule(ruleset);
+ } else if (ruleset.cookierules.length > 0) {
+ if (applicable_list) applicable_list.inactive_rule(ruleset);
+ this.log(INFO,"Inactive cookie rule " + ruleset.name);
+ }
+ }
+ return false;
+ },
+
+ safeToSecureCookie: function(domain) {
+ // Check if the domain might be being served over HTTP. If so, it isn't
+ // safe to secure a cookie! We can't always know this for sure because
+ // observing cookie-changed doesn't give us enough context to know the
+ // full origin URI.
+
+ // First, if there are any redirect loops on this domain, don't secure
+ // cookies. XXX This is not a very satisfactory heuristic. Sometimes we
+ // would want to secure the cookie anyway, because the URLs that loop are
+ // not authenticated or not important. Also by the time the loop has been
+ // observed and the domain blacklisted, a cookie might already have been
+ // flagged as secure.
+
+ if (domain in https_blacklist_domains) {
+ this.log(INFO, "cookies for " + domain + "blacklisted");
+ return false;
+ }
+
+ // If we passed that test, make up a random URL on the domain, and see if
+ // we would HTTPSify that.
+
+ try {
+ var nonce_path = "/" + Math.random().toString();
+ nonce_path = nonce_path + nonce_path;
+ var test_uri = "http://" + domain + nonce_path;
+ } catch (e) {
+ this.log(WARN, "explosion in safeToSecureCookie for " + domain + "\n"
+ + "(" + e + ")");
+ return false;
+ }
+
+ this.log(INFO, "Testing securecookie applicability with " + test_uri);
+ var rs = this.potentiallyApplicableRulesets(domain);
+ for (var i = 0; i < rs.length; ++i) {
+ if (!rs[i].active) continue;
+ var rewrite = rs[i].apply(test_uri);
+ if (rewrite) {
+ this.log(INFO, "Yes: " + rewrite);
+ return true;
+ }
+ }
+ this.log(INFO, "(NO)");
+ return false;
+ }
+};
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/code/IOUtil.js b/data/extensions/https-everywhere@eff.org/chrome/content/code/IOUtil.js
new file mode 100644
index 0000000..96c2500
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/code/IOUtil.js
@@ -0,0 +1,263 @@
+const IO = {
+ readFile: function(file, charset) {
+ var res;
+
+ const is = Cc["@mozilla.org/network/file-input-stream;1"]
+ .createInstance(Ci.nsIFileInputStream );
+ is.init(file ,0x01, 256 /*0400*/, null);
+ const sis = Cc["@mozilla.org/scriptableinputstream;1"]
+ .createInstance(Ci.nsIScriptableInputStream);
+ sis.init(is);
+
+ res = sis.read(sis.available());
+ is.close();
+
+ if (charset !== null) { // use "null" if you want uncoverted data...
+ const unicodeConverter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
+ .createInstance(Ci.nsIScriptableUnicodeConverter);
+ try {
+ unicodeConverter.charset = charset || "UTF-8";
+ } catch(ex) {
+ unicodeConverter.charset = "UTF-8";
+ }
+ res = unicodeConverter.ConvertToUnicode(res);
+ }
+
+ return res;
+ },
+ writeFile: function(file, content, charset) {
+ const unicodeConverter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
+ .createInstance(Ci.nsIScriptableUnicodeConverter);
+ try {
+ unicodeConverter.charset = charset || "UTF-8";
+ } catch(ex) {
+ unicodeConverter.charset = "UTF-8";
+ }
+
+ content = unicodeConverter.ConvertFromUnicode(content);
+ const os = Cc["@mozilla.org/network/file-output-stream;1"]
+ .createInstance(Ci.nsIFileOutputStream);
+ os.init(file, 0x02 | 0x08 | 0x20, 448 /*0700*/, 0);
+ os.write(content, content.length);
+ os.close();
+ },
+
+ safeWriteFile: function(file, content, charset) {
+ var tmp = file.clone();
+ var name = file.leafName;
+ tmp.leafName = name + ".tmp";
+ tmp.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, file.exists() ? file.permissions : 384 /*0600*/);
+ this.writeFile(tmp, content, charset);
+ tmp.moveTo(file.parent, name);
+ }
+};
+
+
+function nsISupportsWrapper(wrapped) {
+ this.wrappedJSObject = wrapped;
+}
+nsISupportsWrapper.prototype = {
+ QueryInterface: xpcom_generateQI([])
+};
+
+const IOUtil = {
+ asyncNetworking: true,
+ proxiedDNS: 0,
+
+ attachToChannel: function(channel, key, requestInfo) {
+ if (channel instanceof Ci.nsIWritablePropertyBag2)
+ channel.setPropertyAsInterface(key, requestInfo);
+ },
+ extractFromChannel: function(channel, key, preserve) {
+ if (channel instanceof Ci.nsIPropertyBag2) {
+ let p = channel.get(key);
+ if (p) {
+ if (!preserve && (channel instanceof Ci.nsIWritablePropertyBag)) channel.deleteProperty(key);
+ if (p.wrappedJSObject) return p.wrappedJSObject;
+ p instanceof Ci.nsIURL || p instanceof Ci.nsIURL;
+ return p;
+ }
+ }
+ return null;
+ },
+
+ extractInternalReferrer: function(channel) {
+ if (channel instanceof Ci.nsIPropertyBag2) {
+ const key = "docshell.internalReferrer";
+ if (channel.hasKey(key))
+ try {
+ return channel.getPropertyAsInterface(key, Ci.nsIURL);
+ } catch(e) {}
+ }
+ return null;
+ },
+ extractInternalReferrerSpec: function(channel) {
+ var ref = this.extractInternalReferrer(channel);
+ return ref && ref.spec || null;
+ },
+
+ getProxyInfo: function(channel) {
+ return Ci.nsIProxiedChannel && (channel instanceof Ci.nsIProxiedChannel)
+ ? channel.proxyInfo
+ : Components.classes["@mozilla.org/network/protocol-proxy-service;1"]
+ .getService(Components.interfaces.nsIProtocolProxyService)
+ .resolve(channel.URI, 0);
+ },
+
+
+ canDoDNS: function(channel) {
+ if (!channel || IOS.offline) return false;
+
+ var proxyInfo = this.getProxyInfo(channel);
+ switch(this.proxiedDNS) {
+ case 1:
+ return !(proxyInfo && (proxyInfo.flags & Ci.nsIProxyInfo.TRANSPARENT_PROXY_RESOLVES_HOST));
+ case 2:
+ return true;
+ default:
+ return !proxyInfo || proxyInfo.type == "direct";
+ }
+
+ },
+
+ abort: function(channel, noNetwork) {
+ channel.cancel(Cr.NS_ERROR_ABORT);
+ },
+
+ findWindow: function(channel) {
+ for each(var cb in [channel.notificationCallbacks,
+ channel.loadGroup && channel.loadGroup.notificationCallbacks]) {
+ if (cb instanceof Ci.nsIInterfaceRequestor) {
+ if (Ci.nsILoadContext) try {
+ // For Gecko 1.9.1
+ return cb.getInterface(Ci.nsILoadContext).associatedWindow;
+ } catch(e) {}
+
+ try {
+ // For Gecko 1.9.0
+ return cb.getInterface(Ci.nsIDOMWindow);
+ } catch(e) {}
+ }
+ }
+ return null;
+ },
+
+ readFile: IO.readFile,
+ writeFile: IO.writeFile,
+ safeWriteFIle: IO.safeWriteFile,
+
+ _protocols: {}, // caching them we gain a 33% speed boost in URI creation :)
+ newURI: function(url) {
+ try {
+ let scheme = url.substring(0, url.indexOf(':'));
+ return (this._protocols[scheme] ||
+ (this._protocols[scheme] =
+ Cc["@mozilla.org/network/protocol;1?name=" + scheme]
+ .getService(Ci.nsIProtocolHandler)))
+ .newURI(url, null, null);
+ } catch(e) {
+ return IOS.newURI(url, null, null);
+ }
+ },
+
+ unwrapURL: function(url) {
+ try {
+ if (!(url instanceof Ci.nsIURI))
+ url = this.newURI(url);
+
+ switch (url.scheme) {
+ case "view-source":
+ return this.unwrapURL(url.path);
+ case "feed":
+ let u = url.spec.substring(5);
+ if (u.substring(0, 2) == '//') u = "http:" + u;
+ return this.unwrapURL(u);
+ case "wyciwyg":
+ return this.unwrapURL(url.path.replace(/^\/\/\d+\//, ""));
+ case "jar":
+ if (url instanceof Ci.nsIJARURI)
+ return this.unwrapURL(url.JARFile);
+ }
+ }
+ catch (e) {}
+
+ return url;
+ },
+
+
+ get _channelFlags() {
+ delete this._channelFlags;
+ const constRx = /^[A-Z_]+$/;
+ const ff = {};
+ [Ci.nsIHttpChannel, Ci.nsICachingChannel].forEach(function(c) {
+ for (var p in c) {
+ if (constRx.test(p)) ff[p] = c[p];
+ }
+ });
+ return this._channelFlags = ff;
+ },
+ humanFlags: function(loadFlags) {
+ var hf = [];
+ var c = this._channelFlags;
+ for (var p in c) {
+ if (loadFlags & c[p]) hf.push(p + "=" + c[p]);
+ }
+ return hf.join("\n");
+ },
+
+ queryNotificationCallbacks: function(chan, iid) {
+ var cb;
+ try {
+ cb = chan.notificationCallbacks.getInterface(iid);
+ if (cb) return cb;
+ } catch(e) {}
+
+ try {
+ return chan.loadGroup && chan.loadGroup.notificationCallbacks.getInterface(iid);
+ } catch(e) {}
+
+ return null;
+ },
+
+
+ anonymizeURI: function(uri, cookie) {
+ if (uri instanceof Ci.nsIURL) {
+ uri.query = this.anonymizeQS(uri.query, cookie);
+ } else return this.anonymizeURL(uri, cookie);
+ return uri;
+ },
+ anonymizeURL: function(url, cookie) {
+ var parts = url.split("?");
+ if (parts.length < 2) return url;
+ parts[1] = this.anonymizeQS(parts[1], cookie);
+ return parts.join("?");
+ },
+
+ _splitName: function(nv) nv.split("=")[0],
+ _qsRx: /[&=]/,
+ _anonRx: /(?:auth|s\w+(?:id|key)$)/,
+ anonymizeQS: function(qs, cookie) {
+ if (!qs) return qs;
+ if (!this._qsRx.test(qs)) return '';
+
+ var cookieNames, hasCookies;
+ if ((hasCookies = !!cookie)) cookieNames = cookie.split(/\s*;\s*/).map(this._splitName);
+
+ let parms = qs.split("&");
+ for (j = parms.length; j-- > 0;) {
+ let nv = parms[j].split("=");
+ let name = nv[0];
+ if (this._anonRx.test(name) || cookie && cookieNames.indexOf(name) > -1)
+ parms.splice(j, 1);
+ }
+ return parms.join("&");
+ },
+
+ get TLDService() {
+ delete this.TLDService;
+ return this.TLDService = Cc["@mozilla.org/network/effective-tld-service;1"].getService(Ci.nsIEffectiveTLDService);
+ }
+
+};
+
+
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/code/NSS.js b/data/extensions/https-everywhere@eff.org/chrome/content/code/NSS.js
new file mode 100644
index 0000000..97a7e78
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/code/NSS.js
@@ -0,0 +1,491 @@
+// Copyright (c) 2011 Moxie Marlinspike <moxie@thoughtcrime.org>
+// 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, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+// USA
+
+
+/**
+ * This class manages the ctypes bridge to the NSS (crypto) libraries
+ * distributed with Mozilla.
+ *
+ **/
+
+function NSS() {
+
+}
+
+NSS.initialize = function(nssPath) {
+ var sharedLib;
+
+ try {
+ sharedLib = ctypes.open(nssPath);
+ } catch (e) {
+ dump("Failed to find nss3 in installed directory, checking system paths.\n");
+ sharedLib = ctypes.open(ctypes.libraryName("nss3"));
+ }
+
+ NSS.types = new Object();
+
+ NSS.types.CERTDistNames = ctypes.StructType("CERTDistNames");
+
+ NSS.types.SECItem = ctypes.StructType("SECItem",
+ [{'type' : ctypes.int},
+ {'data' : ctypes.unsigned_char.ptr},
+ {'len' : ctypes.uint32_t}]);
+
+ NSS.types.PLArenaPool = ctypes.StructType("PLArenaPool");
+
+ NSS.types.CERTCertificateList = ctypes.StructType("CERTCertificateList",
+ [{'certs' : NSS.types.SECItem.ptr},
+ {'len' : ctypes.int},
+ {'arena' : NSS.types.PLArenaPool.ptr}]),
+
+ NSS.types.CERTAVA = ctypes.StructType("CERTAVA",
+ [{'type' : NSS.types.SECItem},
+ {'value' : NSS.types.SECItem}]);
+
+ NSS.types.CERTRDN = ctypes.StructType("CERTRDN",
+ [{'avas' : NSS.types.CERTAVA.ptr.ptr}]);
+
+ NSS.types.SECAlgorithmID = ctypes.StructType("SECAlgorithmID",
+ [{'algorithm' : NSS.types.SECItem},
+ {'parameters' : NSS.types.SECItem}]);
+
+ NSS.types.CERTSignedData = ctypes.StructType("CERTSignedData",
+ [{'data' : NSS.types.SECItem},
+ {'signatureAlgorithm' : NSS.types.SECAlgorithmID},
+ {'signature' : NSS.types.SECItem}]);
+
+ NSS.types.CERTOKDomainName = ctypes.StructType("CERTOKDomainName");
+
+ NSS.types.NSSCertificateStr = ctypes.StructType("NSSCertificateStr");
+
+ NSS.types.CERTAuthKeyID = ctypes.StructType("CERTAuthKeyID");
+
+ NSS.types.CERTName = ctypes.StructType("CERTName",
+ [{'arena' : ctypes.voidptr_t},
+ {'rdns' : NSS.types.CERTRDN.ptr.ptr}]);
+
+ NSS.types.CERTValidity = ctypes.StructType("CERTValidity",
+ [{'arena' : ctypes.voidptr_t},
+ {'notBefore' : NSS.types.SECItem},
+ {'notAfter' : NSS.types.SECItem}]);
+
+ NSS.types.CERTCertExtension = ctypes.StructType("CERTCertExtension",
+ [{'id' : NSS.types.SECItem},
+ {'critical' : NSS.types.SECItem},
+ {'value' : NSS.types.SECItem}]);
+
+ NSS.types.CERTCertDBHandle = ctypes.StructType("CERTCertDBHandle");
+
+ NSS.types.PK11SlotInfo = ctypes.StructType("PK11SlotInfo");
+
+ NSS.types.PK11SlotListElement = ctypes.StructType("PK11SlotListElement",
+ [{'next' : ctypes.StructType("PK11SlotListElement").ptr},
+ {'prev' : ctypes.StructType("PK11SlotListElement").ptr},
+ {'slot' : NSS.types.PK11SlotInfo.ptr},
+ {'refCount' : ctypes.int}]),
+
+ NSS.types.PK11SlotList = ctypes.StructType("PK11SlotList",
+ [{'head' : NSS.types.PK11SlotListElement.ptr},
+ {'tail' : NSS.types.PK11SlotListElement.ptr},
+ {'lock' : ctypes.StructType("PZLock").ptr}]),
+
+ NSS.types.SECKEYPrivateKey = ctypes.StructType("SECKEYPrivateKey",
+ [{'arena' : NSS.types.PLArenaPool.ptr},
+ {'keyType' : ctypes.int},
+ {'pkcs11Slot' : NSS.types.PK11SlotInfo.ptr},
+ {'pkcs11ID' : ctypes.unsigned_long},
+ {'pkcs11IsTemp' : ctypes.int},
+ {'wincx' : ctypes.voidptr_t},
+ {'staticflags' : ctypes.int32_t}]);
+
+ NSS.types.SECKEYPublicKey = ctypes.StructType("SECKEYPublicKey");
+
+ NSS.types.CERTSubjectPublicKeyInfo = ctypes.StructType("CERTSubjectPublicKeyInfo",
+ [{'arena' : NSS.types.PLArenaPool.ptr},
+ {'algorithm' : NSS.types.SECAlgorithmID},
+ {'subjectPublicKey' : NSS.types.SECItem}]);
+
+ NSS.types.CERTCertificateRequest = ctypes.StructType("CERTCertificateRequest");
+
+ NSS.types.SEC_ASN1Template = ctypes.StructType("SEC_ASN1Template",
+ [{'kind' : ctypes.unsigned_long},
+ {'offset' : ctypes.unsigned_long},
+ {'sub' : ctypes.voidptr_t},
+ {'size' : ctypes.unsigned_int}]);
+
+ NSS.types.PK11RSAGenParams = ctypes.StructType("PK11RSAGenParams",
+ [{'keySizeInBits' : ctypes.int},
+ {'pe' : ctypes.unsigned_long}]);
+
+ NSS.types.CERTCertTrust = ctypes.StructType("CERTCertTrust",
+ [{'sslFlags' : ctypes.uint32_t},
+ {'emailFlags' : ctypes.uint32_t},
+ {'objectSigningFlags' : ctypes.uint32_t}]);
+
+ NSS.types.CERTSubjectList = ctypes.StructType("CERTSubjectList");
+
+ NSS.types.CERTGeneralName = ctypes.StructType("CERTGeneralName");
+
+ NSS.types.CERTCertificate = ctypes.StructType("CERTCertificate",
+ [{'arena' : NSS.types.PLArenaPool.ptr},
+ {'subjectName' : ctypes.char.ptr},
+ {'issuerName' : ctypes.char.ptr},
+ {'signatureWrap' : NSS.types.CERTSignedData},
+ {'derCert' : NSS.types.SECItem},
+ {'derIssuer' : NSS.types.SECItem},
+ {'derSubject' : NSS.types.SECItem},
+ {'derPublicKey' : NSS.types.SECItem},
+ {'certKey' : NSS.types.SECItem},
+ {'version' : NSS.types.SECItem},
+ {'serialNumber' : NSS.types.SECItem},
+ {'signature' : NSS.types.SECAlgorithmID},
+ {'issuer' : NSS.types.CERTName},
+ {'validity' : NSS.types.CERTValidity},
+ {'subject' : NSS.types.CERTName},
+ {'subjectPublicKeyInfo' : NSS.types.CERTSubjectPublicKeyInfo},
+ {'issuerID' : NSS.types.SECItem},
+ {'subjectID' : NSS.types.SECItem},
+ {'extensions' : NSS.types.CERTCertExtension.ptr.ptr},
+ {'emailAddr' : ctypes.char.ptr},
+ {'dbhandle' : NSS.types.CERTCertDBHandle.ptr},
+ {'subjectKeyID' : NSS.types.SECItem},
+ {'keyIDGenerated' : ctypes.int},
+ {'keyUsage' : ctypes.unsigned_int},
+ {'rawKeyUsage' : ctypes.unsigned_int},
+ {'keyUsagePresent' : ctypes.int},
+ {'nsCertType' : ctypes.uint32_t},
+ {'keepSession' : ctypes.int},
+ {'timeOK' : ctypes.int},
+ {'domainOK' : NSS.types.CERTOKDomainName.ptr},
+ {'isperm' : ctypes.int},
+ {'istemp' : ctypes.int},
+ {'nickname' : ctypes.char.ptr},
+ {'dbnickname' : ctypes.char.ptr},
+ {'nssCertificate' : NSS.types.NSSCertificateStr.ptr},
+ {'trust' : NSS.types.CERTCertTrust.ptr},
+ {'referenceCount' : ctypes.int},
+ {'subjectList' : NSS.types.CERTSubjectList.ptr},
+ {'authKeyID' : NSS.types.CERTAuthKeyID.ptr},
+ {'isRoot' : ctypes.int},
+ {'options' : ctypes.voidptr_t},
+ {'series' : ctypes.int},
+ {'slot' : NSS.types.PK11SlotInfo.ptr},
+ {'pkcs11ID' : ctypes.unsigned_long},
+ {'ownSlot' : ctypes.int}]);
+
+ NSS.types.CERTBasicConstraints = ctypes.StructType("CERTBasicConstraints",
+ [{'isCA': ctypes.int},
+ {'pathLenConstraint' : ctypes.int}]);
+
+
+ NSS.lib = {
+ SEC_OID_MD5 : 3,
+ SEC_OID_SHA1 : 4,
+ SEC_OID_X509_KEY_USAGE : 81,
+ SEC_OID_NS_CERT_EXT_COMMENT : 75,
+ CKM_RSA_PKCS_KEY_PAIR_GEN : 0,
+ buffer : ctypes.ArrayType(ctypes.char),
+ ubuffer : ctypes.ArrayType(ctypes.unsigned_char),
+
+ // CERT_CertificateTemplate : sharedLib.declare("CERT_CertificateTemplate",
+ // NSS.types.SEC_ASN1Template),
+
+ NSS_Get_CERT_CertificateTemplate : sharedLib.declare("NSS_Get_CERT_CertificateTemplate",
+ ctypes.default_abi,
+ NSS.types.SEC_ASN1Template.ptr),
+
+ PK11_HashBuf : sharedLib.declare("PK11_HashBuf",
+ ctypes.default_abi,
+ ctypes.int,
+ ctypes.int,
+ ctypes.unsigned_char.ptr,
+ ctypes.unsigned_char.ptr,
+ ctypes.int32_t),
+
+ CERT_GetDefaultCertDB : sharedLib.declare("CERT_GetDefaultCertDB",
+ ctypes.default_abi,
+ NSS.types.CERTCertDBHandle.ptr),
+
+ CERT_ChangeCertTrust : sharedLib.declare("CERT_ChangeCertTrust",
+ ctypes.default_abi,
+ ctypes.int32_t,
+ NSS.types.CERTCertDBHandle.ptr,
+ NSS.types.CERTCertificate.ptr,
+ NSS.types.CERTCertTrust.ptr),
+
+ CERT_FindCertByNickname : sharedLib.declare("CERT_FindCertByNickname",
+ ctypes.default_abi,
+ NSS.types.CERTCertificate.ptr,
+ NSS.types.CERTCertDBHandle.ptr,
+ ctypes.char.ptr),
+
+ CERT_FindCertByDERCert : sharedLib.declare("CERT_FindCertByDERCert",
+ ctypes.default_abi,
+ NSS.types.CERTCertificate.ptr,
+ NSS.types.CERTCertDBHandle.ptr,
+ NSS.types.SECItem.ptr),
+
+ CERT_VerifyCertNow : sharedLib.declare("CERT_VerifyCertNow",
+ ctypes.default_abi,
+ ctypes.int,
+ NSS.types.CERTCertDBHandle.ptr,
+ NSS.types.CERTCertificate.ptr,
+ ctypes.int,
+ ctypes.int,
+ ctypes.voidptr_t),
+
+ CERT_CertChainFromCert : sharedLib.declare("CERT_CertChainFromCert",
+ ctypes.default_abi,
+ NSS.types.CERTCertificateList.ptr,
+ NSS.types.CERTCertificate.ptr,
+ ctypes.int,
+ ctypes.int),
+
+ PK11_FindKeyByAnyCert : sharedLib.declare("PK11_FindKeyByAnyCert",
+ ctypes.default_abi,
+ NSS.types.SECKEYPrivateKey.ptr,
+ NSS.types.CERTCertificate.ptr,
+ ctypes.voidptr_t),
+
+ PK11_GetInternalKeySlot : sharedLib.declare("PK11_GetInternalKeySlot",
+ ctypes.default_abi,
+ NSS.types.PK11SlotInfo.ptr),
+
+ PK11_GetAllSlotsForCert : sharedLib.declare("PK11_GetAllSlotsForCert",
+ ctypes.default_abi,
+ NSS.types.PK11SlotList.ptr,
+ NSS.types.CERTCertificate.ptr,
+ ctypes.voidptr_t),
+
+ PK11_GetTokenName : sharedLib.declare("PK11_GetTokenName",
+ ctypes.default_abi,
+ ctypes.char.ptr,
+ NSS.types.PK11SlotInfo.ptr),
+
+ PK11_GenerateKeyPair : sharedLib.declare("PK11_GenerateKeyPair",
+ ctypes.default_abi,
+ NSS.types.SECKEYPrivateKey.ptr,
+ NSS.types.PK11SlotInfo.ptr,
+ ctypes.int,
+ NSS.types.PK11RSAGenParams.ptr,
+ NSS.types.SECKEYPublicKey.ptr.ptr,
+ ctypes.int,
+ ctypes.int,
+ ctypes.voidptr_t),
+
+ PK11_SetPrivateKeyNickname : sharedLib.declare("PK11_SetPrivateKeyNickname",
+ ctypes.default_abi,
+ ctypes.int,
+ NSS.types.SECKEYPrivateKey.ptr,
+ ctypes.char.ptr),
+
+ SEC_ASN1EncodeItem : sharedLib.declare("SEC_ASN1EncodeItem",
+ ctypes.default_abi,
+ NSS.types.SECItem.ptr,
+ NSS.types.PLArenaPool.ptr,
+ NSS.types.SECItem.ptr,
+ ctypes.voidptr_t,
+ NSS.types.SEC_ASN1Template.ptr),
+
+ SEC_DerSignData : sharedLib.declare("SEC_DerSignData",
+ ctypes.default_abi,
+ ctypes.int,
+ NSS.types.PLArenaPool.ptr,
+ NSS.types.SECItem.ptr,
+ ctypes.unsigned_char.ptr,
+ ctypes.int,
+ NSS.types.SECKEYPrivateKey.ptr,
+ ctypes.int),
+
+ SEC_GetSignatureAlgorithmOidTag : sharedLib.declare("SEC_GetSignatureAlgorithmOidTag",
+ ctypes.default_abi,
+ ctypes.int,
+ ctypes.int,
+ ctypes.int),
+
+ SECOID_SetAlgorithmID : sharedLib.declare("SECOID_SetAlgorithmID",
+ ctypes.default_abi,
+ ctypes.int,
+ NSS.types.PLArenaPool.ptr,
+ NSS.types.SECAlgorithmID.ptr,
+ ctypes.int,
+ NSS.types.SECItem.ptr),
+
+
+ CERT_Hexify : sharedLib.declare("CERT_Hexify",
+ ctypes.default_abi,
+ ctypes.char.ptr,
+ NSS.types.SECItem.ptr,
+ ctypes.int),
+
+ CERT_AsciiToName : sharedLib.declare("CERT_AsciiToName",
+ ctypes.default_abi,
+ NSS.types.CERTName.ptr,
+ ctypes.char.ptr),
+
+ SECKEY_CreateSubjectPublicKeyInfo : sharedLib.declare("SECKEY_CreateSubjectPublicKeyInfo",
+ ctypes.default_abi,
+ NSS.types.CERTSubjectPublicKeyInfo.ptr,
+ NSS.types.SECKEYPublicKey.ptr),
+
+ CERT_CreateCertificateRequest : sharedLib.declare("CERT_CreateCertificateRequest",
+ ctypes.default_abi,
+ NSS.types.CERTCertificateRequest.ptr,
+ NSS.types.CERTName.ptr,
+ NSS.types.CERTSubjectPublicKeyInfo.ptr,
+ NSS.types.SECItem.ptr.ptr),
+
+ CERT_CreateCertificate : sharedLib.declare("CERT_CreateCertificate",
+ ctypes.default_abi,
+ NSS.types.CERTCertificate.ptr,
+ ctypes.uint32_t,
+ NSS.types.CERTName.ptr,
+ NSS.types.CERTValidity.ptr,
+ NSS.types.CERTCertificateRequest.ptr),
+
+ CERT_DestroyCertificate : sharedLib.declare("CERT_DestroyCertificate",
+ ctypes.default_abi,
+ ctypes.int,
+ NSS.types.CERTCertificate.ptr),
+
+ CERT_DestroyCertificateList : sharedLib.declare("CERT_DestroyCertificateList",
+ ctypes.default_abi,
+ ctypes.int,
+ NSS.types.CERTCertificateList.ptr),
+
+ CERT_NewTempCertificate : sharedLib.declare("CERT_NewTempCertificate",
+ ctypes.default_abi,
+ NSS.types.CERTCertificate.ptr,
+ NSS.types.CERTCertDBHandle.ptr,
+ NSS.types.SECItem.ptr,
+ ctypes.char.ptr,
+ ctypes.int,
+ ctypes.int),
+
+ CERT_CreateValidity : sharedLib.declare("CERT_CreateValidity",
+ ctypes.default_abi,
+ NSS.types.CERTValidity.ptr,
+ ctypes.int64_t,
+ ctypes.int64_t),
+
+ CERT_CertListFromCert : sharedLib.declare("CERT_CertListFromCert",
+ ctypes.default_abi,
+ NSS.types.CERTCertificateList.ptr,
+ NSS.types.CERTCertificate.ptr),
+
+ CERT_StartCertExtensions : sharedLib.declare("CERT_StartCertExtensions",
+ ctypes.default_abi,
+ ctypes.voidptr_t,
+ NSS.types.CERTCertificate.ptr),
+
+ CERT_AddExtension : sharedLib.declare("CERT_AddExtension",
+ ctypes.default_abi,
+ ctypes.int,
+ ctypes.voidptr_t,
+ ctypes.int,
+ NSS.types.SECItem.ptr,
+ ctypes.int,
+ ctypes.int),
+
+
+ CERT_EncodeBasicConstraintValue : sharedLib.declare("CERT_EncodeBasicConstraintValue",
+ ctypes.default_abi,
+ ctypes.int,
+ NSS.types.PLArenaPool.ptr,
+ NSS.types.CERTBasicConstraints.ptr,
+ NSS.types.SECItem.ptr),
+
+ CERT_EncodeAndAddBitStrExtension : sharedLib.declare("CERT_EncodeAndAddBitStrExtension",
+ ctypes.default_abi,
+ ctypes.int,
+ ctypes.voidptr_t,
+ ctypes.int,
+ NSS.types.SECItem.ptr,
+ ctypes.int),
+
+ CERT_EncodeAltNameExtension : sharedLib.declare("CERT_EncodeAltNameExtension",
+ ctypes.default_abi,
+ ctypes.int,
+ NSS.types.PLArenaPool.ptr,
+ NSS.types.CERTGeneralName.ptr,
+ NSS.types.SECItem.ptr),
+
+ CERT_FinishExtensions : sharedLib.declare("CERT_FinishExtensions",
+ ctypes.default_abi,
+ ctypes.int,
+ ctypes.voidptr_t),
+
+ CERT_ImportCerts : sharedLib.declare("CERT_ImportCerts",
+ ctypes.default_abi,
+ ctypes.int,
+ NSS.types.CERTCertDBHandle.ptr,
+ ctypes.int,
+ ctypes.int,
+ NSS.types.SECItem.ptr.ptr,
+ NSS.types.CERTCertificate.ptr.ptr.ptr,
+ ctypes.int,
+ ctypes.int,
+ ctypes.char.ptr),
+
+ PORT_NewArena : sharedLib.declare("PORT_NewArena",
+ ctypes.default_abi,
+ NSS.types.PLArenaPool.ptr,
+ ctypes.uint32_t),
+
+ PORT_ArenaZAlloc : sharedLib.declare("PORT_ArenaZAlloc",
+ ctypes.default_abi,
+ ctypes.voidptr_t,
+ NSS.types.PLArenaPool.ptr,
+ ctypes.int),
+
+ PORT_FreeArena : sharedLib.declare("PORT_FreeArena",
+ ctypes.default_abi,
+ ctypes.void_t,
+ NSS.types.PLArenaPool.ptr,
+ ctypes.int),
+
+ CERT_GetCommonName : sharedLib.declare("CERT_GetCommonName",
+ ctypes.default_abi,
+ ctypes.char.ptr,
+ NSS.types.CERTName.ptr),
+
+ CERT_GetOrgUnitName : sharedLib.declare("CERT_GetOrgUnitName",
+ ctypes.default_abi,
+ ctypes.char.ptr,
+ NSS.types.CERTName.ptr),
+
+ CERT_GetCertificateNames : sharedLib.declare("CERT_GetCertificateNames",
+ ctypes.default_abi,
+ NSS.types.CERTGeneralName.ptr,
+ NSS.types.CERTCertificate.ptr,
+ NSS.types.PLArenaPool.ptr),
+
+ CERT_DecodeDERCertificate : sharedLib.declare("__CERT_DecodeDERCertificate",
+ ctypes.default_abi,
+ NSS.types.CERTCertificate.ptr,
+ NSS.types.SECItem.ptr,
+ ctypes.int,
+ ctypes.char.ptr),
+
+ CERT_FindCertExtension : sharedLib.declare("CERT_FindCertExtension",
+ ctypes.default_abi,
+ ctypes.int,
+ NSS.types.CERTCertificate.ptr,
+ ctypes.int,
+ NSS.types.SECItem.ptr),
+ };
+
+};
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/code/Root-CAs.js b/data/extensions/https-everywhere@eff.org/chrome/content/code/Root-CAs.js
new file mode 100644
index 0000000..49777fa
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/code/Root-CAs.js
@@ -0,0 +1,348 @@
+// These are concatenated md5 and sha1 fingerprints for the Firefox and
+// Microsoft root CAs as of Aug 2010
+
+root_ca_hashes = {
+ '00531D1D7201D423C820D00B6088C5D143DDB1FFF3B49B73831407F6BC8B975023D07C50' : true,
+ '015A99C3D64FA94B3C3BB1A3AB274CBFFC219A76112F76C1C508833C9A2FA2BA84AC087A' : true,
+ '019408DE857F8D806CE602CA89522848750251B2C632536F9D917279543C137CD721C6E0' : true,
+ '0208EE8CAAB8387A6824DCB4E26A52337E206939CC5FA883635F64C750EBF5FDA9AEE653' : true,
+ '0226C3015E08303743A9D07DCF37E6BF323C118E1BF7B8B65254E2E2100DD6029037F096' : true,
+ '034287D7C1167D18AFA4703CB8312C3E4EF2E6670AC9B5091FE06BE0E5483EAAD6BA32D9' : true,
+ '03DC08EEC4703FFA20E5E179E81AE7C59ED18028FB1E8A9701480A7890A59ACD73DFF871' : true,
+ '044BFDC96CDA2A32857C598461468A64BEB5A995746B9EDF738B56E6DF437A77BE106B81' : true,
+ '0468E9247E41CED76C441630703DDDB9AB16DD144ECDC0FC4BAAB62ECF0408896FDE52B7' : true,
+ '068690F2195471FDDD3DE6EEA161CAFF7030AABF8432A800666CCCC42A887E42B7553E2B' : true,
+ '069F6979166690021B8C8CA2C3076F3A627F8D7827656399D27D7F9044C9FEB3F33EFA9A' : true,
+ '06F0171EB1E961ED7A363CA594A1374AFAAA27B8CAF5FDF5CDA98AC3378572E04CE8F2E0' : true,
+ '06F9EBECCC569D88BA90F5BAB01AE00216D424FE9610E17519AF232BB68774E24144BE6E' : true,
+ '076192047EA6B9CD5E6B007AE3BF1D0434D499426F9FC2BB27B075BAB682AAE5EFFCBA74' : true,
+ '087C581F522B44B43B79CD01F8C5C3C995E6ADF8D77146024DD56A21B2E73FCDF23B35FF' : true,
+ '0B092C1CD721866F94376FE6A7F3224D0409565B77DA582E6495AC0060A72354E64B0192' : true,
+ '0C412F135BA054F596662D7ECD0E03F4DA79C1711150C23439AA2B0B0C62FD55B2F9F580' : true,
+ '0C5ADD5AAE29F7A77679FA4151FEF035B865130BEDCA38D27F69929420770BED86EFBC10' : true,
+ '0C7FDD6AF42AB9C89BBD207EA9DB5C3760D68974B5C2659E8A0FC1887C88D246691B182C' : true,
+ '0CF89E17FCD403BDE68D9B3C0587FE8433A335C23CE8034B04E13DE5C48E791AEB8C3204' : true,
+ '0E40A76CDE035D8FD10FE4D18DF96CA9A9E9780814375888F20519B06D2B0D2B6016907D' : true,
+ '0EFA4BF7D760CD65F7A7068857986239D29F6C98BEFC6D986521543EE8BE56CEBC288CF3' : true,
+ '0FA01300C3558AB7D37E2D04739EDE3C8B1A1106B8E26B232980FD652E6181376441FD11' : true,
+ '100EADF35C841D8E035F2DC93937F552742CDF1594049CBF17A2046CC639BB3888E02E33' : true,
+ '10FC635DF6263E0DF325BE5F79CD6767742C3192E607E424EB4549542BE1BBC53E6174E2' : true,
+ '119279403CB18340E5AB664A679280DFA9628F4B98A91B4835BAD2C1463286BB66646A8C' : true,
+ '14F108AD9DFA64E289E71CCFA8AD7D5E3921C115C15D0ECA5CCB5BC4F07D21D8050B566A' : true,
+ '155EF5117AA2C1150E927E66FE3B84C3B38FECEC0B148AA686C3D00F01ECC8848E8085EB' : true,
+ '15ACA5C2922D79BCE87FCB67ED02CF36E7B4F69D61EC9069DB7E90A7401A3CF47D4FE8EE' : true,
+ '15B298A354704048703A375582C45AFA0048F8D37B153F6EA2798C323EF4F318A5624A9E' : true,
+ '15EE9F5AA08528DF6BDD34A3A056D8307F8A77836BDC6D068F8B0737FCC5725413068CA4' : true,
+ '160A1613C17FF01D887EE3D9E71261CCF88015D3F98479E1DA553D24FD42BA3F43886AEF' : true,
+ '173574AF7B611CEBF4F93CE2EE40F9A2925A8F8D2C6D04E0665F596AFF22D863E8256F3F' : true,
+ '1802B00127036A191B323B83DE9AA985D6BF7994F42BE5FA29DA0BD7587B591F47A44F22' : true,
+ '1898C0D6E93AFCF9B0F50CF74B014417FAB7EE36972662FB2DB02AF6BF03FDE87C4B2F9B' : true,
+ '18AE695D15CAB917673267D597B260C04BA7B9DDD68788E12FF852E1A024204BF286A8F6' : true,
+ '1AD00CB9A6E68A3B6E95860C5B8CD8195A4D0E8B5FDCFDF64E7299A36C060DB222CA78E4' : true,
+ '1B2E00CA2606903DADFE6F1568D36BB367650DF17E8E7E5B8240A4F4564BCFE23D69C6F0' : true,
+ '1BD75F76734CC0DC98CA442BCC0F78DD31E2C52CE1089BEFFDDADB26DD7C782EBC4037BD' : true,
+ '1C4BE2C62DB9AC3114F4400769CB1F4011C5B5F75552B011669C2E9717DE6D9BFF5FA810' : true,
+ '1D3554048578B03F42424DBF20730A3F02FAF3E291435468607857694DF5E45B68851868' : true,
+ '1D6496AF2D821A300BA0620D76BC53AA7FBB6ACD7E0AB438DAAF6FD50210D007C6C0829C' : true,
+ '1E240EA0F876D785A3F5F8A1493D2EBAFD1ED1E2021B0B9F73E8EB75CE23436BBCC746EB' : true,
+ '1E42950233926BB95FC07FDAD6B24BFCCCAB0EA04C2301D6697BDD379FCD12EB24E3949D' : true,
+ '1E74C3863C0C35C53EC27FEF3CAA3CD9209900B63D955728140CD13622D8C687A4EB0085' : true,
+ '200B4A7A88A7A942868A5F74567B880593E6AB220303B52328DCDA569EBAE4D1D1CCFB65' : true,
+ '206BD68B4A8F48ABE488090DE5651A500CFD83DBAE44B9A0C8F676F3B570650B94B69DBF' : true,
+ '2124A681C1D8F219AF4998E39DFE0BF46A174570A916FBE84453EED3D070A1D8DA442829' : true,
+ '21BC82AB49C4133B4BB22B5C6B909C198BAF4C9B1DF02A92F7DA128EB91BACF498604B6F' : true,
+ '21D84C822B990933A2EB14248D8E5FE84054DA6F1C3F4074ACED0FECCDDB79D153FB901D' : true,
+ '21EFB85040393F756F27FEE3EA5870EBA59C9B10EC7357515ABB660C4D94F73B9E6E9272' : true,
+ '222DA601EA7C0AF7F06C56433F7776D3FEB8C432DCF9769ACEAE3DD8908FFD288665647D' : true,
+ '224D8F8AFCF735C2BB5734907B8B22163E2BF7F2031B96F38CE6C4D8A85D3E2D58476A0F' : true,
+ '246DABD2F2EA4A66AE5BBCAE50AD6E56F9DD19266B2043F1FE4B3DCB0190AFF11F31A69D' : true,
+ '2477D9A891D13BFA882DC2FFF8CD3393D8C5388AB7301B1B6ED47AE645253A6F9F1A2761' : true,
+ '252AC6C5896839F9557202165EA39ED23C71D70E35A5DAA8B2E3812DC3677417F5990DF3' : true,
+ '255BA669B87BF8780DC18FA6EAE47063FA0882595F9CA6A11ECCBEAF65C764C0CCC311D0' : true,
+ '257ABA832EB6A20BDAFEF5020F08D7AD81968B3AEF1CDC70F5FA3269C292A3635BD123D3' : true,
+ '259DCF5EB3259D95B93F00865F47943D43F9B110D5BAFD48225231B0D0082B372FEF9A54' : true,
+ '266D2C1998B6706838505419EC9034600B77BEBBCB7AA24705DECC0FBD6A02FC7ABD9B52' : true,
+ '27DE36FE72B70003009DF4F01E6C0424DE3F40BD5093D39B6C60F6DABC076201008976C9' : true,
+ '27EC3947CDDA5AAFE29A016521A94CBB4D2378EC919539B5007F758F033B211EC54D8BCF' : true,
+ '2A5D003739469475397B11A6F29341E13F85F2BB4A62B0B58BE1614ABB0D4631B4BEF8BA' : true,
+ '2A954ECA79B2874573D92D90BAF99FB6A43489159A520F0D93D032CCAF37E7FE20A8B419' : true,
+ '2B508718392D3BFFC3917F2D7DC08A97B19DD096DCD4E3E0FD676885505A672C438D4E9C' : true,
+ '2B7020568682A018C807531228702172F17F6FB631DC99E3A3C87FFE1CF1811088D96033' : true,
+ '2C20269DCB1A4A0085B5B75AAEC201378C96BAEBDD2B070748EE303266A0F3986E7CAE58' : true,
+ '2C6F17A39562012065D2076EFCB83F6DB1EAC3E5B82476E9D50B1EC67D2CC11E12E0B491' : true,
+ '2C8C175EB154AB9317B5365ADBD1C6F2A073E5C5BD43610D864C21130A855857CC9CEA46' : true,
+ '2C8F9F661D1890B147269D8E86828CA96252DC40F71143A22FDE9EF7348E064251B18118' : true,
+ '2CC2B0D5D622C52E901EF4633F0FBB324A058FDFD761DB21B0C2EE48579BE27F42A4DA1C' : true,
+ '2DBBE525D3D165823AB70EFAE6EBE2E1B3EAC44776C9C81CEAF29D95B6CCA0081B67EC9D' : true,
+ '2E03FDC5F5D72B9464C1BE8931F1169B96995C7711E8E52DF9E34BECEC67D3CBF1B6C4D2' : true,
+ '30C908DDD73E63A4092814C74EB97E2CCFE4313DBA05B8A7C30063995A9EB7C247AD8FD5' : true,
+ '30C9E71E6BE614EB65B216692031674D3BC0380B33C3F6A60C86152293D9DFF54B81C004' : true,
+ '31853C62949763B9AAFD894EAF6FE0CF1F4914F7D874951DDDAE02C0BEFD3A2D82755185' : true,
+ '324A4BBBC863699BBE749AC6DD1D4624AD7E1C28B064EF8F6003402014C3D0E3370EB58A' : true,
+ '3327D16CFC9185FC8C7E98FA854EF305E70715F6F728365B5190E271DEE4C65EBEEACAF3' : true,
+ '33B784F55F27D76827DE14DE122AED6F0747220199CE74B97CB03D79B264A2C855E933FF' : true,
+ '343339FC6D033A8FA25385443270DEC45E5A168867BFFF00987D0B1DC2AB466C4264F956' : true,
+ '34FCB8D036DB9E14B3C2F2DB8FE494C7379A197B418545350CA60369F33C2EAF474F2079' : true,
+ '354895364A545A72968EE064CCEF2C8CC90D1BEA883DA7D117BE3B79F4210E1A5894A72D' : true,
+ '370971C4AFEB7501AE636C3016BFD1E5A399F76F0CBF4C9DA55E4AC24E8960984B2905B6' : true,
+ '3741491B18569A26F5ADC266FB40A54C4313BB96F1D5869BC14E6A92F6CFF63469878237' : true,
+ '3785445332451F20F0F395E125C4434EF48B11BFDEABBE94542071E641DE6BBE882B40B9' : true,
+ '37A56ED4B1258497B7FD56157AF9A200B435D4E1119D1C6690A749EBB394BD637BA782B7' : true,
+ '3916AAB96A41E11469DF9E6C3B72DCB6879F4BEE05DF98583BE360D633E70D3FFE9871AF' : true,
+ '3AB2DE229A209349F9EDC8D28AE7680D36863563FD5128C7BEA6F005CFE9B43668086CCE' : true,
+ '3AE550B039BEC7463633A1FE823E8D943CBB5DE0FCD6397C0588E56697BD462ABDF95C76' : true,
+ '3B0AE4BB416A84B39D2C575E6542BE478E1032E9245944F84791983EC9E829CB1059B4D3' : true,
+ '3C4C25CC0A19CAEE6AEB55160086725F23E833233E7D0CC92B7C4279AC19C2F474D604CA' : true,
+ '3D4129CB1EAA1174CD5DB062AFB0435BDDE1D2A901802E1D875E84B3807E4BB1FD994134' : true,
+ '3E455215095192E1B75D379FB187298AB1BC968BD4F49D622AA89A81F2150152A41D829C' : true,
+ '3E80175BADD77C104BF941B0CF1642B000EA522C8A9C06AA3ECCE0B4FA6CDC21D92E8099' : true,
+ '3F459639E25087F7BBFE980C3C2098E62AC8D58B57CEBF2F49AFF2FC768F511462907A41' : true,
+ '400125068D21436A0E43009CE743F3D5F9CD0E2CDA7624C18FBDF0F0ABB645B8F7FED57A' : true,
+ '410352DC0FF7501B16F0028EBA6F45C5DAC9024F54D8F6DF94935FB1732638CA6AD77C13' : true,
+ '41B807F7A8D109EEB49A8E704DFC1B787A74410FB0CD5C972A364B71BF031D88A6510E9E' : true,
+ '4265CABE019A9A4CA98C4149CDC0D57F293621028B20ED02F566C532D1D6ED909F45002F' : true,
+ '42769768CFA6B43824AAA11BF267DECA4178AB4CBFCE7B4102ACDAC4933E6FF50DCF715C' : true,
+ '4281A0E21CE35510DE558942659622E6E0B4322EB2F6A568B654538448184A5036874384' : true,
+ '429BD669C6D445AD2E81511D355A89624F555CE20DCD3364E0DC7C41EFDD40F50356C122' : true,
+ '45E1A572C5A93664409EF5E45884678C6B2F34AD8958BE62FDB06B5CCEBB9DD94F4E39F3' : true,
+ '45F750114EC5ADBD53688663EC7B6AE1C09AB0C8AD7114714ED5E21A5A276ADCD5E7EFCB' : true,
+ '468C210EAB92214659DBA6DB0061DE265A5A4DAF7861267C4B1F1E67586BAE6ED4FEB93F' : true,
+ '48D11E627801C26E4369A42CEE130AB564902AD7277AF3E32CD8CC1DC79DE1FD7F8069EA' : true,
+ '4963AE27F4D5953DD8DB2486B89C0753D3C063F219ED073E34AD5D750B327629FFD59AF2' : true,
+ '497904B0EB8719AC47B0BC11519B74D0D1EB23A46D17D68FD92564C2F1F1601764D8E349' : true,
+ '49EFA6A1F0DE8EA76AEE5B7D1E5FC4463E42A18706BD0C9CCF594750D2E4D6AB0048FDC4' : true,
+ '4B1C568CA0E8C79E1EF5EE32939965FE4C95A9902ABE0777CED18D6ACCC3372D2748381E' : true,
+ '4B6771BE33B90DB64B3A400187F08B1F7AC5FFF8DCBC5583176877073BF751735E9BD358' : true,
+ '4B798DD41D0392AA51EE04E5906F474954F9C163759F19045121A319F64C2D0555B7E073' : true,
+ '4BE2C99196650CF40E5A9392A00AFEB28CF427FD790C3AD166068DE81E57EFBB932272D4' : true,
+ '4C5641E50DBB2BE8CAA3ED1808AD43390483ED3399AC3608058722EDBC5E4600E3BEF9D7' : true,
+ '4D56677ECCE6457259B74F511172E169C0DB578157E9EE82B5917DF0DD6D82EE9039C4E2' : true,
+ '4FEBF1F070C280635D589FDA123CA9C4E392512F0ACFF505DFF6DE067F7537E165EA574B' : true,
+ '50193E2FE8B6F4055449F3AEC98B3E1947AFB915CDA26D82467B97FA42914468726138DD' : true,
+ '5186E81FBCB1C371B51810DB5FDCF62078E9DD0650624DB9CB36B50767F209B843BE15B3' : true,
+ '556EBEF54C1D7C0360C43418BC9649C1245C97DF7514E7CF2DF8BE72AE957B9E04741E85' : true,
+ '565FAA80611217F66721E62B6D61568E8025EFF46E70C8D472246584FE403B8A8D6ADBF5' : true,
+ '58EB470764D62CBAE29B96552B9700B56A6F2A8B6E2615088DF59CD24C402418AE42A3F1' : true,
+ '59736628512B98B410FF7D06FA22D6C8A0F8DB3F0BF417693B282EB74A6AD86DF9D448A3' : true,
+ '5A11B922850289E1C3F22CE14EC101844B421F7515F6AE8A6ECEF97F6982A400A4D9224E' : true,
+ '5B6F532CBB8188FA6C042C325DA56B967CA04FD8064C1CAA32A37AA94375038E8DF8DDC0' : true,
+ '5B9EFD3B6035EA688E52FE1319144AA36B81446A5CDDF474A0F800FFBE69FD0DB6287516' : true,
+ '5C48DCF74272EC56946D1CCC713580756631BF9EF74F9EB6C9D5A60CBA6ABED1F7BDEF7B' : true,
+ '5E397BDDF8BAEC82E9AC62BA0C54002BCA3AFBCF1240364B44B216208880483919937CF7' : true,
+ '5E809E845A0E650B1702F355182A3ED7786A74AC76AB147F9C6A3050BA9EA87EFE9ACE3C' : true,
+ '5F944A7322B8F7D131EC5939F78EFE6E9FC796E8F8524F863AE1496D381242105F1B78F5' : true,
+ '60847C5ACEDB0CD4CBA7E9FE02C6A9C0101DFA3FD50BCBBB9BB5600C1955A41AF4733A04' : true,
+ '649CEF2E44FCC68F5207D051738FCB3DDA40188B9189A3EDEEAEDA97FE2F9DF5B7D18A41' : true,
+ '65295911BB8F5166890D47824002C5AFC4674DDC6CE2967FF9C92E072EF8E8A7FBD6A131' : true,
+ '6558AB15AD576C1EA8A7B569ACBFFFEBE5DF743CB601C49B9843DCAB8CE86A81109FE48E' : true,
+ '67AC0D773011DED143AE7B737190BCA9ED8DC8386C4886AEEE079158AAC3BFE658E394B4' : true,
+ '67CB9DC013248A829BB2171ED11BECD4D23209AD23D314232174E40D7F9D62139786633A' : true,
+ '689B17C654E0E0E099551642F75A86D8027268293E5F5D17AAA4B3C3E6361E1F92575EAA' : true,
+ '6960ECBE8C94D76E6F2EC4782F55F08397226AAE4A7A64A59BD16787F27F841C0A001FD0' : true,
+ '6C397DA40E5559B23FD641B11250DE435F3B8CF2F810B37D78B4CEEC1919C37334B9C774' : true,
+ '6CC9A76E47F10CE3533B784C4DC26AC5B72FFF92D2CE43DE0A8D4C548C503726A81E2B93' : true,
+ '6D38C49B22244CA3A8B3A09345E157FA89C32E6B524E4D65388B9ECEDC637134ED4193A3' : true,
+ '70B57C4881953E80DC289BBAEF1EE4854072BA31FEC351438480F62E6CB95508461EAB2F' : true,
+ '711F0E21E7AAEA323A6623D3AB50D66996974CD6B663A7184526B1D648AD815CF51E801A' : true,
+ '71AA6AAF1FA5C0D50E90D40BF6AADFCC55C86F7414AC8BDD6814F4D86AF15F3710E104D0' : true,
+ '71E265FBCD7B0B845BE3BCD76320C598CFF810FB2C4FFC0156BFE1E1FABCB418C68D31C5' : true,
+ '72E44A87E369408077EABCE3F4FFF0E15F43E5B1BFF8788CAC1CC7CA4A9AC6222BCC34C6' : true,
+ '733A747AECBBA396A6C2E4E2C89BC0C3AEC5FB3FC8E1BFC4E54F03075A9AE800B7F7B6FA' : true,
+ '739DD35FC63C95FEC6ED89E58208DD897FB9E2C995C97A939F9E81A07AEA9B4D70463496' : true,
+ '74014A91B108C458CE47CDF0DD11530885A408C09C193E5D51587DCDD61330FD8CDE37BF' : true,
+ '747B820343F0009E6BB3EC47BF85A5934463C531D7CCC1006794612BB656D3BF8257846F' : true,
+ '74A82C81432B35609B78056B58F36582CFF360F524CB20F1FEAD89006F7F586A285B2D5B' : true,
+ '770D19B121FD00429C3E0CA5DD0B028E25019019CFFBD9991CB76825748D945F30939542' : true,
+ '774AF42C9DB027B747B515E4C762F0FCDF646DCB7B0FD3A96AEE88C64E2D676711FF9D5F' : true,
+ '782A02DFDB2E14D5A75F0ADFB68E9C5D4F65566336DB6598581D584A596C87934D5F2AB4' : true,
+ '78A5FB104BE4632ED26BFBF2B6C24B8EEC0C3716EA9EDFADD35DFBD55608E60A05D3CBF3' : true,
+ '79E4A9840D7D3A96D7C04FE2434C892EA8985D3A65E5E5C4B2D7D66D40C6DD2FB19C5436' : true,
+ '7A79544D07923B5BFF41F00EC739A298C060ED44CBD881BD0EF86C0BA287DDCF8167478C' : true,
+ '7BB508999A8C18BF85277D0EAEDAB2AB24BA6D6C8A5B5837A48DB5FAE919EA675C94D217' : true,
+ '7C62FF749D31535E684AD578AA1EBF239F744E9F2B4DBAEC0F312C50B6563B8E2D93C311' : true,
+ '7CA50FF85B9A7D6D30AE545AE342A28A59AF82799186C7B47507CBCF035746EB04DDB716' : true,
+ '7D86908F5BF1F240C0F73D62B5A4A93B72997913EC9B0DAE65D1B6D7B24A76A3AEC2EE16' : true,
+ '7E234E5BA7A5B425E90007741162AED67F8AB0CFD051876A66F3360F47C88D8CD335FC74' : true,
+ '7F667A71D3EB6978209A51149D83DA20BE36A4562FB2EE05DBB3D32323ADF445084ED656' : true,
+ '803ABC22C1E6FB8D9B3B274A321B9A0147BEABC922EAE80E78783462A79F45C254FDE68B' : true,
+ '8135B9FBFB12CA186936EBAE6978A1F1DCBB9EB7194BC47205C111752986835B53CAE4F8' : true,
+ '81D6ED354F1F26D031D040DD8AE5810DE0925E18C7765E22DABD9427529DA6AF4E066428' : true,
+ '8212F789E10B9160A4B6229F9468119268ED18B309CD5291C0D3357C1D1141BF883866B1' : true,
+ '824AD493004D66B6A32CA77B3536CF0B687EC17E0602E3CD3F7DFBD7E28D57A0199A3F44' : true,
+ '8292BA5BEFCD8A6FA63D55F984F6D6B7F9B5B632455F9CBEEC575F80DCE96E2CC7B278B7' : true,
+ '84901D95304956FC4181F045D776C46B439E525F5A6A47C32CEBC45C63ED39317CE5F4DF' : true,
+ '852FF4764CD5426CCB5E7DF717E835BD4EFCED9C6BDD0C985CA3C7D253063C5BE6FC620C' : true,
+ '85CA765A1BD16822DCA22312CAC680345BCDCDCC66F6DCE4441FE37D5CC3134C46F47038' : true,
+ '86386D5E49636C855CDB6DDC94B7D0F7ACED5F6553FD25CE015F1F7A483B6A749F6178C6' : true,
+ '86420509BCA79DEC1DF32E0EBAD81DD01D8259CA2127C3CBC16CD932F62C65298CA88712' : true,
+ '86ACDE2BC56DC3D98C2888D38D16131ECE6A64A309E42FBBD9851C453E6409EAE87D60F1' : true,
+ '86EF8E319D9F8569A2A41A127168BA1B90DECE77F8C825340E62EBD635E1BE20CF7327DD' : true,
+ '8714AB83C4041BF193C750E2D721EBEF30779E9315022E94856A3FF8BCF815B082F9AEFD' : true,
+ '879055F2CE31153C33D927C876E37DE13070F8833E4AA6803E09A646AE3F7D8AE1FD1654' : true,
+ '87CE0B7B2A0E4900E158719B37A893720563B8630D62D75ABBC8AB1E4BDFB5A899B24D43' : true,
+ '882C8C52B8A23CF3F7BB03EAAEAC420B74207441729CDD92EC7931D823108DC28192E2BB' : true,
+ '8949548CC8689A8329ECDC067321AB97A60F34C8626C81F68BF77DA9F667588A903F7D36' : true,
+ '8956AA4D441E59D805A1886DEAC828B26372C49DA9FFF051B8B5C7D4E5AAE30384024B9C' : true,
+ '8BCA525F7553D02C6F630D8F882E1CD78EB03FC3CF7BB292866268B751223DB5103405CB' : true,
+ '8CCADC0B22CEF5BE72AC411A11A8D81291C6D6EE3E8AC86384E548C299295C756C817B81' : true,
+ '8CD79FEBC7B8144C5478A7903BA935671F55E8839BAC30728BE7108EDE7B0BB0D3298224' : true,
+ '8D26FF2F316D5929DDE636A7E2CE6425720FC15DDC27D456D098FABF3CDD78D31EF5A8DA' : true,
+ '8D639B56C114E4EE9A128586119082A3D2441AA8C203AECAA96E501F124D52B68FE4C375' : true,
+ '8D7251DBA03ACF2077DFF265065EDFEFC8C25F169EF85074D5BEE8CDA2D43CAEE75FD257' : true,
+ '8EADB501AA4D81E48C1DD1E1140095193679CA35668772304D30A5FB873B0FA77BB70D54' : true,
+ '8F5D770627C4983C5B9378E7D77D9BCC7E784A101C8265CC2DE1F16D47B440CAD90A1945' : true,
+ '8F91E7EEE3FCDA86CAFCDC70EDB7B70C8250BED5A214433A66377CBC10EF83F669DA3A67' : true,
+ '911B3F6ECD9EABEE07FE1F71D2B36127E19FE30E8B84609E809B170D72A8C5BA6E1409BD' : true,
+ '91DE0625ABDAFD32170CBB25172A84672796BAE63F1801E277261BA0D77770028F20EEE4' : true,
+ '91F4035520A1F8632C62DEACFB611C8E21FCBD8E7F6CAF051BD1B343ECA8E76147F20F8A' : true,
+ '9265588BA21A317273685CB4A57A0748E621F3354379059A4B68309D8A2F74221587EC79' : true,
+ '932A3EF6FD23690D7120D42B47992BA6CBA1C5F8B0E35EB8B94512D3F934A2E90610D336' : true,
+ '937F901CED846717A4655F9BCB3002978781C25A96BDC2FB4C65064FF9390B26048A0E01' : true,
+ '93C28E117BD4F30319BD2875134A454AAB48F333DB04ABB9C072DA5B0CC1D057F0369B46' : true,
+ '93EB36130BC154F13E7505E5E01CD4375F4E1FCF31B7913B850B54F6E5FF501A2B6FC6CF' : true,
+ '93F1AD340B2BE7A85460E2738CA49431705D2B4565C7047A540694A79AF7ABB842BDC161' : true,
+ '9414777E3E5EFD8F30BD41B0CFE7D03075E0ABB6138512271C04F85FDDDE38E4B7242EFE' : true,
+ '96897D61D1552B27E25A39B42A6C446F8EFDCABC93E61E925D4D1DED181A4320A467A139' : true,
+ '9760E8575FD35047E5430C94368AB06290AEA26985FF14804C434952ECE9608477AF556F' : true,
+ '978FC66B3B3E40857724750B76BB55F8B5D303BF8682E152919D83F184ED05F1DCE5370C' : true,
+ '9A771918ED96CFDF1BB70EF58DB9882ECF74BFFF9B86815B08335440363E87B6B6F0BF73' : true,
+ '9AAEF722F533FB4EEC0A249DC63D7D255E997CA5945AAB75FFD14804A974BF2AE1DFE7E1' : true,
+ '9B340D1A315B97462698BCA6136A71969E6CEB179185A29EC6060CA53E1974AF94AF59D4' : true,
+ '9D666ACCFFD5F543B4BF8C16D12BA8998939576E178DF705780FCC5EC84F84F6253A4893' : true,
+ '9DFBF9ACED893322F428488325235BE0A69A91FD057F136A42630BB1760D2D51120C1650' : true,
+ '9E80FF78010C2EC136BDFE96906E08F34ABDEEEC950D359C89AEC752A12C5B29F6D6AA0C' : true,
+ '9F6C1F0F07AC1921F915BBD5C72CD82AF5C27CF5FFF3029ACF1A1A4BEC7EE1964C77D784' : true,
+ '9FDDDBABFF8EFF45215FF06C9D8FFE2B9656CD7B57969895D0E141466806FBB8C6110687' : true,
+ 'A10B44B3CA10D8006E9D0FD80F920AD1B80186D1EB9C86A54104CF3054F34C52B7E558C6' : true,
+ 'A208E4B33EEFDE084B60D0BF7952498D8CC4307BC60755E7B22DD9F7FEA245936C7CF288' : true,
+ 'A2339B4C747873D46CE7C1F38DCB5CE985371CA6E550143DCE2803471BDE3A09E8F8770F' : true,
+ 'A26F53B7EE40DB4A68E7FA18D9104B7269BD8CF49CD300FB592E1793CA556AF3ECAA35FB' : true,
+ 'A33D88FE161BDDF95C9F1A7FD8C89008A3E31E20B2E46A328520472D0CDE9523E7260C6D' : true,
+ 'A37D2C27E4A7F3AA5F75D4C49264026AB6AF5BE5F878A00114C3D7FEF8C775C34CCD17B6' : true,
+ 'A3EC750F2E88DFFA48014E0B5C486FFB37F76DE6077C90C5B13E931AB74110B4F2E49A27' : true,
+ 'A66B6090239B3F2DBB986FD6A7190D46E0AB059420725493056062023670F7CD2EFC6666' : true,
+ 'A771FD26FC3CE540F19906EBC1936DE9E619D25B380B7B13FDA33E8A58CD82D8A88E0515' : true,
+ 'A7F2E41606411150306B9CE3B49CB0C9E12DFB4B41D7D9C32B30514BAC1D81D8385E2D46' : true,
+ 'A80D6F3978B9436D77426D985ACC23CAD6DAA8208D09D2154D24B52FCB346EB258B28A58' : true,
+ 'A8EDDEEB938866D82FC3BD1DBE45BE4D7639C71847E151B5C7EA01C758FBF12ABA298F7A' : true,
+ 'A923759BBA49366E31C2DBF2E766BA87317A2AD07F2B335EF5A1C34E4B57E8B7D8F1FCA6' : true,
+ 'A981C0B73A9250BC91A521FF3D47879FCB658264EA8CDA186E1752FB52C397367EA387BE' : true,
+ 'AA088FF6F97BB7F2B1A71E9BEAEABD79CF9E876DD3EBFC422697A3B5A37AA076A9062348' : true,
+ 'AA8E5DD9F8DB0A58B78D26876C823555409D4BD917B55C27B69B64CB9822440DCD09B889' : true,
+ 'AABFBF6497DA981D6FC6083A957033CA394FF6850B06BE52E51856CC10E180E882B385CC' : true,
+ 'AB57A65B7D428219B5D85826285EFDFFB12E13634586A46F1AB2606837582DC4ACFD9497' : true,
+ 'ABAB8D2DB740E5973D2FF2A63BDA6A05C18211328A92B3B23809B9B5E2740A07FB12EB5E' : true,
+ 'ABBFEAE36B29A6CCA6783599EFAD2B802F173F7DE99667AFA57AF80AA2D1B12FAC830338' : true,
+ 'ACB694A59C17E0D791529BB19706A6E4D4DE20D05E66FC53FE1A50882C78DB2852CAE474' : true,
+ 'AD8E0F9E016BA0C574D50CD368654F1ECFDEFE102FDA05BBE4C78D2E4423589005B2571D' : true,
+ 'AFB8336E7CDDC60264AD58FC0D4F7BCFBC7B3C6FEF26B9F7AB10D7A1F6B67C5ED2A12D3D' : true,
+ 'B001EE14D9AF291894768EF169332A846E3A55A4190C195C93843CC0DB722E313061F0B1' : true,
+ 'B147BC1857D118A0782DEC71E82A9573204285DCF7EB764195578E136BD4B7D1E98E46A5' : true,
+ 'B39C25B1C32E32538015309D4D02773E6782AAE0EDEEE21A5839D3C0CD14680A4F60142A' : true,
+ 'B3A53E77216DAC4AC0C9FBD5413DCA0658119F0E128287EA50FDD987456F4F78DCFAD6D4' : true,
+ 'B44ADBE85916461E5AD86EDA064352622964B686135B5DFDDD3253A89BBC24D74B08C64D' : true,
+ 'B465220A7CADDF41B7D544D5ADFA9A75BC9219DDC98E14BF1A781F6E280B04C27F902712' : true,
+ 'B4819E89AC1724FD2A4285271D0C2B5D20CB594FB4EDD895763FD5254E959A6674C6EEB2' : true,
+ 'B5E83436C910445848706D2E83D4B805039EEDB80BE7A03C6953893B20D2D9323A4C2AFD' : true,
+ 'B75274E292B48093F275E4CCD7F2EA263BC49F48F8F373A09C1EBDF85BB1C365C7D811B3' : true,
+ 'B774CD487C5F9A0D3BF3FE66F41B3DFA5B4E0EC28EBD8292A51782241281AD9FEEDD4E4C' : true,
+ 'B7B0D1EC1A033ECEA91511CCB16FB2AEE3D73606996CDFEF61FA04C335E98EA96104264A' : true,
+ 'B8089AF003CC1B0DC86C0B76A1756423A0A1AB90C9FC847B3B1261E8977D5FD32261D3CC' : true,
+ 'B816334C4C4CF2D8D34D06B4A65B4003838E30F77FDD14AA385ED145009C0E2236494FAA' : true,
+ 'B8D312034E8C0C5A47C9B6C59E5B97FD0560A2C738FF98D1172A94FE45FB8A47D665371E' : true,
+ 'BA21EA20D6DDDB8FC1578B40ADA1FCFC801D62D07B449D5C5C035C98EA61FA443C2A58FE' : true,
+ 'BA926442161FCBA116481AF6405C59870456F23D1E9C43AECB0D807F1C0647551A05F456' : true,
+ 'BC6C5133A7E9D366635415721B2192935922A1E15AEA163521F898396A4646B0441B0FA9' : true,
+ 'BD8ACE34A8AE6148E85EC87A1CE8CCBFD2EDF88B41B6FE01461D6E2834EC7C8F6C77721E' : true,
+ 'BDD6F58A7C3CC4A6F934CCC38961F6B2CABB51672400588E6419F1D40878D0403AA20264' : true,
+ 'BE395ABE078AB1121725CC1D46343CB2DE990CED99E0431F60EDC3937E7CD5BF0ED9E5FA' : true,
+ 'BF6059A35BBAF6A77642DA6F1A7B50CF5D989CDB159611365165641B560FDBEA2AC23EF1' : true,
+ 'BFB5E77D3DEA6F1DF08A50BC8C1CFA1DE4554333CA390E128B8BF81D90B70F4002D1D6E9' : true,
+ 'C1623E23C582739C03594B2BE977497F2AB628485E78FBF3AD9E7910DD6BDF99722C96E5' : true,
+ 'C1D43E07AEEBECFD7589E67EA84CEBCD76B76096DD145629AC7585D37063C1BC47861C8B' : true,
+ 'C1D951C084B86A75E82FD7D65F7EAC460B972C9EA6E7CC58D93B20BF71EC412E7209FABF' : true,
+ 'C22A59ABCF152F4CF7E631A316AE840C9158C5EF987301A8903CFDAB03D72DA1D88909C9' : true,
+ 'C2DBAB8E9652C5EEAEF25500896D55953913853E45C439A2DA718CDFB6F3E033E04FEE71' : true,
+ 'C45D0E48B6AC28304E0ABCF938168757D8A6332CE0036FB185F6634F7D6A066526322827' : true,
+ 'C463AB44201C36E437C05F279D0F6F6E97E2E99636A547554F838FBA38B82E74F89A830A' : true,
+ 'C4D7F0B2A3C57D6167F004CD43D3BA5890DEDE9E4C4E9F6FD88617579DD391BC65A68964' : true,
+ 'C570C4A2ED53780CC810538164CBD01D23E594945195F2414803B4D564D2A3A3F5D88B8C' : true,
+ 'C5A1B7FF73DDD6D7343218DFFC3CAD8806083F593F15A104A069A46BA903D006B7970991' : true,
+ 'C5DFB849CA051355EE2DBA1AC33EB028D69B561148F01C77C54578C10926DF5B856976AD' : true,
+ 'C5E67BBF06D04F43EDC47A658AFB6B19339B6B1450249B557A01877284D9E02FC3D2D8E9' : true,
+ 'C69F6D5CB379B00389CBF03FA4C09F8AEF2DACCBEABB682D32CE4ABD6CB90025236C07BC' : true,
+ 'C7BD11D6918A3582C53666017C6F4779634C3B0230CF1B78B4569FECF2C04A8652EFEF0E' : true,
+ 'C86E97F335A729144782892391A6BEC84A3F8D6BDC0E1ECFCD72E377DEF2D7FF92C19BC7' : true,
+ 'C91962D0DA7E1020FCA4CD0380872DF551A44C28F313E3F9CB5E7C0A1E0E0DD2843758AE' : true,
+ 'C9982777281E3D0E153C8400B88503E656E0FAC03B8F18235518E5D311CAE8C24331AB66' : true,
+ 'CA3DD368F1035CD032FAB82B59E85ADB97817950D81C9670CC34D809CF794431367EF474' : true,
+ 'CB17E431673EE209FE455793F30AFA1C4EB6D578499B1CCF5F581EAD56BE3D9B6744A5E5' : true,
+ 'CBBDC3682DB3CB1859D32952E8C66489C9321DE6B5A82666CF6971A18A56F2D3A8675602' : true,
+ 'CC4DAEFB306BD838FE50EB86614BD2269C615C4D4D85103A5326C24DBAEAE4A2D2D5CC97' : true,
+ 'CD3B3D625B09B80936879E122F7164BA67EB337B684CEB0EC2B0760AB488278CDD9597DD' : true,
+ 'CD68B6A7C7C4CE75E01D4F5744619209132D0D45534B6997CDB2D5C339E25576609B5CC6' : true,
+ 'CD996CDB2AC296155ABF879EAEA5EE93EE29D6EA98E632C6E527E0906F0280688BDF44DC' : true,
+ 'CDF439F3B51850D73EA4C591A03E214BE1A45B141A21DA1A79F41A42A961D669CD0634C1' : true,
+ 'CE78335C5978016E18EAB936A0B92E23AE5083ED7CF45CBC8F61C621FE685D794221156E' : true,
+ 'CF8F3B62A3CACA711BA3E1CB4857351F5D003860F002ED829DEAA41868F788186D62127F' : true,
+ 'CFF4270DD4EDDC6516496D3DDABF6EDE3A44735AE581901F248661461E3B9CC45FF53A1B' : true,
+ 'D2EDEE7992F78272180BFED98BEC13D8A7F8390BA57705096FD36941D42E7198C6D4D9D5' : true,
+ 'D35376E3CE58C5B0F29FF42A05F0A1F2211165CA379FBB5ED801E31C430A62AAC109BCB4' : true,
+ 'D3D9BDAE9FAC6724B3C81B52E1B9A9BD4A65D5F41DEF39B8B8904A4AD3648133CFC7A1D1' : true,
+ 'D3F3A616C0FA6B1D59B12D964D0E112E74F8A3C3EFE7B390064B83903C21646020E5DFCE' : true,
+ 'D474DE575C39B2D39C8583C5C065498A5FB7EE0633E259DBAD0C4C9AE6D38F1A61C7DC25' : true,
+ 'D480656824F9892228DBF5A49A178F14016897E1A0B8F2C3B134665C20A727B7A158E28F' : true,
+ 'D59788DA6416E71D664AA6EA37FC7ADCEC93DE083C93D933A986B3D5CDE25ACB2FEECF8E' : true,
+ 'D5BEFFB5EE826CF0E2578EA7E5346F03D904080A4929C838E9F185ECF7A22DEF99342407' : true,
+ 'D5E98140C51869FC462C8975620FAA7807E032E020B72C3F192F0628A2593A19A70F069E' : true,
+ 'D63981C6527E9669FCFCCA66ED05F296B51C067CEE2B0C3DF855AB2D92F4FE39D4E70F0E' : true,
+ 'D6A5C3ED5DDD3E00C13D87921F1D3FE4B31EB1B740E36C8402DADC37D44DF5D4674952F9' : true,
+ 'D6ED3CCAE2660FAF10430D779B0409BF85B5FF679B0C79961FC86E4422004613DB179284' : true,
+ 'D7343DEF1D270928E131025B132BDDF7B172B1A56D95F91FE50287E14D37EA6A4463768A' : true,
+ 'D87E32EF69F8BF72031D4082E8A775AF42EFDDE6BFF35ED0BAE6ACDD204C50AE86C4F4FA' : true,
+ 'DA26B6E6C7C2F7B79E4659B3577718653E84D3BCC544C0F6FA19435C851F3F2FCBA8E814' : true,
+ 'DB233DF969FA4BB9958044735E7D4183273EE12457FDC4F90C55E82B56167F62F532E547' : true,
+ 'DBC8F2272EB1EA6A29235DFE563E33DFC8EC8C879269CB4BAB39E98D7E5767F31495739D' : true,
+ 'DC32C3A76D2557C768099DEA2DA9A2D18782C6C304353BCFD29692D2593E7D44D934FF11' : true,
+ 'DC6D6FAF897CDD17332FB5BA9035E9CE7F88CD7223F3C813818C994614A89C99FA3B5247' : true,
+ 'DD753F56BFBBC5A17A1553C690F9FBCC24A40A1F573643A67F0A4B0749F6A22BF28ABB6B' : true,
+ 'DF0DBC7CC836B77699A1ABF0D20F896A342CD9D3062DA48C346965297F081EBC2EF68FDC' : true,
+ 'DF168A83EA83845DB96501C6A65D193EDBAC3C7AA4254DA1AA5CAAD68468CB88EEDDEEA8' : true,
+ 'DF3C735981E7395081044C34A2CBB37B61573A11DF0ED87ED5926522EAD056D744B32371' : true,
+ 'DFF28073CCF1E66173FCF542E9C57CEE99A69BE61AFE886B4D2B82007CB854FC317E1539' : true,
+ 'E006A1C97DCFC9FC0DC0567596D862139BAAE59F56EE21CB435ABE2593DFA7F040D11DCB' : true,
+ 'E14B5273D71BDB9330E5BDE4096EBEFB216B2A29E62A00CE820146D8244141B92511B279' : true,
+ 'E1C07EA0AABBD4B77B84C228117808A7CDD4EEAE6000AC7F40C3802C171E30148030C072' : true,
+ 'E2D52023ECEEB872E12B5D296FFA43DA9BACF3B664EAC5A17BED08437C72E4ACDA12F7E7' : true,
+ 'E2D8F867F4509435FC5E05FC822295C30446C8BB9A6983C95C8A2E5464687C1115AAB74A' : true,
+ 'E2F8E080D0083F1EC1E9D23F8069AE06C73026E325FE21916B55C4B53A56B13DCAF3D625' : true,
+ 'E60BD2C9CA2D88DB1A710E4B78EB024140E78C1D523D1CD9954FAC1A1AB3BD3CBAA15BFC' : true,
+ 'E77ADCB11F6E061F746C591627C34BC07454535C24A3A758207E3E3ED324F816FB211649' : true,
+ 'E8CC9FB09B40C51F4FBA7421F952857A688B6EB807E8EDA5C7B17C4393D0795F0FAE155F' : true,
+ 'EBB04F1D3A2E372F1DDA6E27D6B680FA18F7C1FCC3090203FD5BAA2F861A754976C8DD25' : true,
+ 'EBF59D290D61F9421F7CC2BA6DE3150928903A635B5280FAE6774C0B6DA7D6BAA64AF2E8' : true,
+ 'EC407D2B765267052CEAF23A4F65F0D8A5EC73D48C34FCBEF1005AEB85843524BBFAB727' : true,
+ 'ED41F58C50C52B9C73E6EE6CEBC2A8261B4B396126276B6491A2686DD70243212D1F1D96' : true,
+ 'EE2931BC327E9AE6E8B5F751B4347190503006091D97D4F5AE39F7CBE7927D7D652D3431' : true,
+ 'EE7A41E0CF757D889280A21A9A7BA157679A4F81FC705DDEC419778DD2EBD875F4C242C6' : true,
+ 'EEFE6169656EF89CC62AF4D72B63EFA29FAD91A6CE6AC6C50047C44EC9D4A50D92D84979' : true,
+ 'EF5AF133EFF1CDBB5102EE12144B96C4A1DB6393916F17E4185509400415C70240B0AE6B' : true,
+ 'F058C503826717AB8FDA0310278E19C2CB44A097857C45FA187ED952086CB9841F2D51B5' : true,
+ 'F096B62FC510D5678E832532E85E2EE52388C9D371CC9E963DFF7D3CA7CEFCD625EC190D' : true,
+ 'F09E639376A595BC1861F19BFBD364DD80BF3DE9A41D768D194B293C85632CDBC8EA8CF7' : true,
+ 'F16A2218C9CDDFCE821D1DB7785CA9A57998A308E14D6585E6C21E153A719FBA5AD34AD9' : true,
+ 'F1BC636A54E0B527F5CDE71AE34D6E4A36B12B49F9819ED74C9EBC380FC6568F5DACB2F7' : true,
+ 'F20598E5964BBE5D55181B55B388E3929078C5A28F9A4325C2A7C73813CDFE13C20F934E' : true,
+ 'F27DE954E4A3220D769FE70BBBB3242B049811056AFE9FD0F5BE01685AACE6A5D1C4454C' : true,
+ 'F37E3A13DC746306741A3C38328CFBA9253F775B0E7797AB645F15915597C39E263631D1' : true,
+ 'F3D752A875FD18ECE17D35B1706EA59C968338F113E36A7BABDD08F7776391A68736582E' : true,
+ 'F4FF97428070FE66168BBED35315819BF44095C238AC73FC4F77BF8F98DF70F8F091BC52' : true,
+ 'F520DA5203862B92768D5CB72D8B93ADA65CB4733D94A5C865A864647C2C01272C89B143' : true,
+ 'F775AB29FB514EB7775EFF053C998EF5DE28F4A4FFE5B92FA3C503D1A349A7F9962A8212' : true,
+ 'F7B661AB03C25C463E2D2CF4A124D854FAA7D9FB31B746F200A85E65797613D816E063B5' : true,
+ 'F8387C7788DF2C16682EC2E2524BB8F95F3AFC0A8B64F686673474DF7EA9A2FEF9FA7A51' : true,
+ 'F8BEC46322C9A846748BB81D1E4A2BF661EF43D77FCAD46151BC98E0C35912AF9FEB6311' : true,
+ 'FB1B5D438A94CD44C676F2434B47E731F18B538D1BE903B6A6F056435B171589CAF36BF2' : true,
+ 'FC11B8D8089330006D23F97EEB521E0270179B868C00A4FA609152223F9F3E32BDE00562' : true,
+ 'FD49BE5B185A25ECF9C354851040E8D4086418E906CEE89C2353B6E27FBD9E7439F76316' : true
+};
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/code/STS.js b/data/extensions/https-everywhere@eff.org/chrome/content/code/STS.js
new file mode 100644
index 0000000..17999aa
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/code/STS.js
@@ -0,0 +1,228 @@
+// http://lists.w3.org/Archives/Public/www-archive/2009Sep/att-0051/draft-hodges-strict-transport-sec-05.plain.html
+
+const STS = {
+
+ enabled: false,
+
+ get db() {
+ delete this.db;
+ return this.initPersistentDB();
+ },
+
+ initPersistentDB: function() {
+ return this.db = new STSDB(STSPersistence);
+ },
+
+ processRequest: function(chan) {
+ if (this.enabled) {
+ var uri = chan.URI;
+ if (uri.schemeIs("https")) {
+ try {
+ this.db.processHeader(uri.asciiHost, chan.getResponseHeader("Strict-Transport-Security"));
+ } catch (e) {}
+ }
+ }
+ },
+
+ isSTSURI: function(uri) {
+ return this.enabled && this.db.matches(uri.asciiHost);
+ },
+
+ enterPrivateBrowsing: function() {
+ try {
+ this.db.save();
+ } catch(e) {}
+
+ this.db = new STSDB(this.db);
+ },
+
+ exitPrivateBrowsing: function() {
+ this.initPersistentDB();
+ },
+
+ eraseDB: function() {
+ this.db.reset();
+ STSPersistence.save(this.db);
+ },
+
+ patchErrorPage: function(docShell, errorURI) {
+ // see #errors-in-secure-transport-establishment
+ if (!this.enabled) return;
+
+ if (!(/^about:certerror?/.test(errorURI.spec) &&
+ this.isSTSURI(docShell.currentURI))
+ ) return;
+
+ Thread.delay(function() {
+ docShell.document.getElementById("expertContent").style.display = "none";
+ }, 100);
+ },
+
+ dispose: function() {
+ this.db.save();
+ }
+};
+
+function STSDB(source) {
+ this._entries = {};
+ if (source && source._entries) { // clone
+ var entries = source._entries;
+ for (var p in entries) {
+ this._entries[p] = entries[p];
+ }
+ } else {
+ if (source && source.load) {
+ this._persistence = source;
+ this.load();
+ }
+ }
+}
+
+STSDB.prototype = {
+ _persistence: null,
+ _dirty: false,
+ _saveTimer: null,
+
+ processHeader: function(host, header) {
+ if (DNS.isIP(host)) return;
+
+ var m = header.match(/^\s*max-age\s*=\s*(\d+)\s*(;\s*includeSubDomains)?/i);
+ if (!m) return;
+ var maxAge = parseInt(m[1]);
+ var includeSubDomains = !!m[2];
+ var expiration = Math.round(Date.now() / 1000) + maxAge;
+ if (host in this._entries) {
+ var e = this._entries[host];
+ if (e.expiration == expiration && e.includeSubDomains == includeSubDomains)
+ return;
+
+ e.expiration = expiration;
+ e.includeSubDomains = includeSubDomains;
+ } else {
+ this.add(new STSEntry(host, expiration, includeSubDomains));
+ }
+ this.saveDeferred();
+ },
+
+ add: function(entry) {
+ this._entries[entry.host] = entry;
+ },
+
+ matches: function(host, asSuperDomain) {
+ if (host in this._entries) {
+ var e = this._entries[host];
+
+ if (e.expiration >= Date.now() / 1000) {
+ if ((!asSuperDomain || e.includeSubDomains))
+ return true;
+ } else {
+ delete this._entries[host];
+ }
+ }
+
+ var dotPos = host.indexOf(".");
+ var lastDotPos = host.lastIndexOf(".");
+
+ if (dotPos == lastDotPos)
+ return false;
+
+ return this.matches(host.substring(dotPos + 1), true);
+ },
+
+ serialize: function() {
+ var lines = [], ee = this._entries;
+ var e;
+ for (var h in ee) {
+ e = ee[h];
+ lines.push([e.host, e.expiration, e.includeSubDomains ? "*" : ""].join(";"));
+ }
+ return lines.join("\n");
+ },
+ restore: function(s) {
+ s.split(/\s+/).forEach(function(line) {
+ if (line) {
+ var args = line.split(";");
+ if (args.length > 1)
+ this.add(new STSEntry(args[0], parseInt(args[1]), !!args[2]));
+ }
+ }, this);
+ },
+
+ load: function() {
+ if (this._persistence) {
+ this._persistence.load(this);
+ this.purgeExpired();
+ }
+ },
+
+ save: function() {
+ if (this._dirty && this._persistence) {
+ this.purgeExpired();
+ this._persistence.save(this);
+ this._dirty = false;
+ }
+ },
+
+ saveDeferred: function() {
+ if (this._dirty || !this._persistence) return;
+ this._dirty = true;
+ if (!this._timer) this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+ this._timer.initWithCallback(this, 10000, Ci.nsITimer.TYPE_ONE_SHOT);
+ },
+ notify: function(timer) {
+ this.save();
+ },
+
+ purgeExpired: function() {
+ var now = Math.round(Date.now() / 1000);
+ for (var h in this._entries) {
+ if (this._entries[h].expiration < now) delete this._entries[h];
+ }
+ },
+
+ reset: function() {
+ this._entries = {};
+ this._dirty = false;
+ }
+};
+
+function STSEntry(host, expiration, includeSubDomains) {
+ this.host = host;
+ this.expiration = expiration;
+ if (includeSubDomains) this.includeSubDomains = includeSubDomains;
+}
+
+STSEntry.prototype = {
+ includeSubDomains: false
+};
+
+
+const STSPersistence = {
+ get _file() {
+ delete this._file;
+ var f = Cc["@mozilla.org/file/directory_service;1"].getService(
+ Ci.nsIProperties).get("ProfD", Ci.nsIFile);
+ f.append("NoScriptSTS.db");
+ return this._file = f;
+ },
+ load: function(db) {
+ var f = this._file;
+ try {
+ if (f.exists()) db.restore(IO.readFile(f));
+ } catch (e) {
+ dump("STS: Error loading db from " + f.path + "!" + e + "\n");
+ return false;
+ }
+ return true;
+ },
+ save: function(db) {
+ var f = this._file;
+ try {
+ IO.safeWriteFile(f, db.serialize());
+ } catch(e) {
+ dump("STS: Error saving db to " + f.path + "!" + e + "\n");
+ return false;
+ }
+ return true;
+ }
+};
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/code/Thread.js b/data/extensions/https-everywhere@eff.org/chrome/content/code/Thread.js
new file mode 100644
index 0000000..8c9daf6
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/code/Thread.js
@@ -0,0 +1,100 @@
+
+var Thread = {
+
+ hostRunning: true,
+ activeLoops: 0,
+ _timers: [],
+
+ spin: function(ctrl) {
+ ctrl.startTime = ctrl.startTime || Date.now();
+ ctrl.timeout = false;
+ this.activeLoops++;
+ this._spinInternal(ctrl);
+ this.activeLoops--;
+ ctrl.elapsed = Date.now() - ctrl.startTime;
+ return ctrl.timeout;
+ },
+
+ _spinInternal: function(ctrl) {
+ var t = ctrl.startTime;
+ var maxTime = parseInt(ctrl.maxTime);
+ if (maxTime) {
+ while(ctrl.running && this.hostRunning) {
+ this.yield();
+ if (Date.now() - t > maxTime) {
+ ctrl.timeout = true;
+ ctrl.running = false;
+ break;
+ }
+ }
+ } else while(ctrl.running && this.hostRunning) this.yield();
+ },
+
+ yield: function() {
+ this.current.processNextEvent(true);
+ },
+
+ yieldAll: function() {
+ var t = this.current;
+ while(t.hasPendingEvents()) t.processNextEvent(false);
+ },
+
+ get current() {
+ delete this.current;
+ var obj = "@mozilla.org/thread-manager;1" in Cc
+ ? Cc["@mozilla.org/thread-manager;1"].getService()
+ : Cc["@mozilla.org/thread;1"].createInstance(Ci.nsIThread);
+ this.__defineGetter__("current", function() { return obj.currentThread; });
+ return this.current;
+ },
+
+ get currentQueue() {
+ delete this.currentQueue;
+ var eqs = null;
+ const CTRID = "@mozilla.org/event-queue-service;1";
+ if (CTRID in Cc) {
+ const IFace = Ci.nsIEventQueueService;
+ eqs = Cc[CTRID].getService(IFace);
+ }
+ this.__defineGetter__("currentQueue", eqs
+ ? function() { return eqs.getSpecialEventQueue(IFace.CURRENT_THREAD_EVENT_QUEUE); }
+ : this.__lookupGetter__("current")
+ );
+ return this.currentQueue;
+ },
+
+ delay: function(callback, time, self, args) {
+ var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+ this._timers.push(timer);
+ timer.initWithCallback({
+ notify: this._delayRunner,
+ context: { callback: callback, args: args || DUMMY_ARRAY, self: self || null }
+ }, time || 1, 0);
+ },
+
+ dispatch: function(runnable) {
+ this.current.dispatch(runnable, Ci.nsIEventTarget.DISPATCH_NORMAL);
+ },
+
+ asap: function(callback, self, args) {
+ this.current.dispatch({
+ run: function() {
+ callback.apply(self, args || DUMMY_ARRAY);
+ }
+ }, Ci.nsIEventTarget.DISPATCH_NORMAL);
+ },
+
+ _delayRunner: function(timer) {
+ var ctx = this.context;
+ try {
+ ctx.callback.apply(ctx.self, ctx.args);
+ } finally {
+ this.context = null;
+ var tt = Thread._timers;
+ var pos = tt.indexOf(timer);
+ if (pos > -1) tt.splice(pos, 1);
+ timer.cancel();
+ }
+ }
+
+};
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/code/X509ChainWhitelist.js b/data/extensions/https-everywhere@eff.org/chrome/content/code/X509ChainWhitelist.js
new file mode 100644
index 0000000..b32b6e4
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/code/X509ChainWhitelist.js
@@ -0,0 +1,1007 @@
+
+// These are SHA256 fingerprints for the most common chains observed by the
+// Decentralized SSL Observatory. These should not be resubmitted.
+// This file is automatically generated by utils/mk_client_whitelist.py
+
+const X509ChainWhitelist = {
+ '000AA4E99FE86D84F762DFB2DC29323D0614B95AA335A270AF204EBA2F2240AF' : true,
+ '00487384DE9545F7F6D6709574920DB9743F0DDC4D5E1518EC00ACCCC6F9866F' : true,
+ '0077DFC8E3CFE0E4398F208CDCB1BC5A7A78BEEF101ED256315FCB9833283B58' : true,
+ '012AAE6B27B392684695FA22F87C8DD3F60CDAB564EE4D4D58DF98575D99153B' : true,
+ '01FC275FB7BB83082EA2C546876545030D74F68355AF2B0CCB1972993B393E58' : true,
+ '0261C3970364E15EC2BB646934FE28F8FCE6E1D5E0B99C7539DF636ED03A9DF0' : true,
+ '027017BAD8EC764424A5DB3B647AD769E78F1653A92F800FAF21212C4DB6CEF8' : true,
+ '034AA8D4F147FC9E93CC18EB5BC06F28FE3DF4923CA61A9CAE92F4E3E078C5F3' : true,
+ '03985CA59706D4A023A5CE0B2E4F870EA465A8E3803CEB2AD859FC86D3569852' : true,
+ '04376F22DBF0B17201EB6871797B1D31FC00EBC4743317793B9C5A5BEA8CECF4' : true,
+ '046C78CE6601C4D88EAC305EE65068225CED3988A6BEC42E50B57B1979742245' : true,
+ '04AEEFBC8685B2668E25C23D77C6D63B95C7C0BA1B8ABBF434F5EAA66BC3E7F4' : true,
+ '052592AA10AFA8D750861F47C540D3A0653A87138ED7427BFD02C9D197D3EF8B' : true,
+ '0544DC1E0D529429A1C86E848D1C78B8511CC1A2128405D276FD864B452890EF' : true,
+ '055C88BD28194042771FF813973E086A30710231DB219FF377B79FA075E7F2AD' : true,
+ '05CB56F00C8DA64EEF10F2305EF696AF839CF8DD541910D760772AC86811FDAB' : true,
+ '05CE45708C3882B0DB81A4504FBE064C1ACD7DABDD071A7F263744FAAF040CF5' : true,
+ '05F70EA23C890F1C382FB250E40DFFD3488C271006DB6B10DC96BF34B6F74420' : true,
+ '06808645F29D708E4C31AC40FA00000733238E10A56D2067AA62803C9736E923' : true,
+ '0699966F623E746BF97DB3B6BBBEB83BCF2E8CAE89D907A49A731951B158216A' : true,
+ '06B35EEE47D7E55F278C5DB13FF137B269B6EF91B58FEB4B2E70E7CC1DB757D2' : true,
+ '07CF2A06F1718D6E476B98C2B42E370A35FAFE4C1F41CF7A1DE115CDB6222FAC' : true,
+ '07E7123B20A807889C384460FFCE4A7F53593A5C872B0E8FD45795D71CD0F9FE' : true,
+ '07FC57E4C188422B53059AD4839F467B9269E4EABBF902C99B30E25DEC5EB1B7' : true,
+ '0834241C7C2B598E20698047C331B173BCA189B96E528FA1993AFAAE3F7D51F6' : true,
+ '087FAD2F33E4D28A13CCFDE11F270188E01AE0EED615D2F433DA4EF05CA6BD4C' : true,
+ '089979504BECAC25640130E65E562AA3E3B5D49EE148FEF6A2B77A2A1CF5FC06' : true,
+ '08BD4BE042F6DA7D627143ED6B2BACE65615683C3C272123AC55105DE4BD723A' : true,
+ '08E5080C1D69F2C11524050C9C0EFDAEBFE68A27FD30EC04AAF4DE2D590F22EB' : true,
+ '09250AF23BC74D92973DD48812D5ED28CE1F5C110EE5F7CA791D9CFDE04A131C' : true,
+ '096800FDAFA82029B3B5E3947E0EAB6FB1F1D6958DE04E9256969F99F7518C57' : true,
+ '0A122B87C038CAEA46E8944009B11C2168E47F4DACAA9D3BBFB92CB5F5E1BCDE' : true,
+ '0A36586C8EEE28E5ECA1F542691D12B3CE7815CDCF722CDF7074AA71413C2550' : true,
+ '0A6A1FECBADAF7F1B473305A71E454F6AA8C1B0F40941FF4660B814BFF4984B3' : true,
+ '0A903D7CCFBB18FFEC8E3AB05FC7E592C1E7509D0EC2DBD9A2C05236BA9FD7C9' : true,
+ '0A91A9CAC951DA1739ABB2F29D16A6F5FAA9F49AC87516AB59CA77150D282528' : true,
+ '0AA5730256323B66DBE88E3056AA3F45E52BE5E2B87C1C9DBC1986CEAF97B5D9' : true,
+ '0B2D2C539D3D922820B6D08E159E6763D22AE797B2C32F8202B632BB93588588' : true,
+ '0B39ADF22CBA98C15754A7A899C5B96871337D2178EB3EBF0B5D5F88332EA971' : true,
+ '0B901F548AE4E0F25EF38010E311945FB198E497F203A88FE7C44970F7ECDC40' : true,
+ '0C114EDF67FB7C09C532297D79A5743EE5F8576A8EBE3DF69A728B8CFC0A167C' : true,
+ '0C7E90EF8BCD379CB001FD07530718DCC0A33E9D7D1D333F505F0143BC6A8FD6' : true,
+ '0CA932C2E0929B9B6C0A8822D3F094F671522419835049CAEAC51755D1F44777' : true,
+ '0D4F42B386775FF404B84D58859BC5AB029F1F9CC6B7AFFF32B838F8B8C71F3E' : true,
+ '0D8FC5F202A5668F7F3EA7F6A73521E0C7FEB5DBF6E58BA68AB7C7E01F4C532C' : true,
+ '0D91DE20988EA155526570498A1A6289FEC55994A5BA888C9134765F2A0B0580' : true,
+ '0E3AE0C9BEDFCFB38239DC4214A3AF3E6386720E2E5F8A85EEB52BD152E4DF09' : true,
+ '0EEAAD4FE6818F1D723A5567CD0A6569D45E346E2DA2896222A7F3367F4AE8C7' : true,
+ '0EF8FA5AAD4BACDB842959378F18935855B027B0BADDCBDEADC9CC958C4C603B' : true,
+ '0F39AF5CA9615B05CBC12DE3C94A8C4FBA71CA8CEF541952315A9D0658DB5B28' : true,
+ '0F7DE9806919EBD5EE47188428BF7FE13495E4684ADBB5BA980BB15D4D0B0C22' : true,
+ '0F8F66953B0F42560CDD573A013D3FB809D9747210E58F28F4878CDA5A8B8AD2' : true,
+ '0F97235268233245499D6C1319DF1BCA3AAAFB13CF9B06EB294FCA328022E82C' : true,
+ '0F9E066578F4AFB0ACBDC408CB25B7D7200BC5CB7FC4DA6D32532D827EA5B232' : true,
+ '0FA392F6EABCE0F4DA14C7B5237B21BEEE6BDA55832A8A6090CAEBB53AC8D77B' : true,
+ '1049EFDE8BD0E7D94AE05D50D326ABCE41E79B0572F86FDF1F7387738262F09A' : true,
+ '10552D044AD79FBF1AF5357998DAB9B1FFD66D7B53C8107FC2280148D66475E3' : true,
+ '10E82776E55D0C2D58F6598E615CF38AA14161D1EAD97C4A09182FE1D44E695B' : true,
+ '10FD669D6DA882678AEAFB35A5F8A0963C2E2B3084883EA515C8956FEC4207ED' : true,
+ '114ED15D4B557A16DDE1D01CB4074215CE6773C180FEF60F08267CEAFB670D5E' : true,
+ '116A5D5F3E99CFE5F72A4AFAC8699CC225C130F4B8520CDB350A1262D9585973' : true,
+ '118FF53B6BEB35CBFE6592D45BE082BA1228D1817E46B2CC14B8855FCC5C9D59' : true,
+ '11EC553AB76EED159FE553B52E7475FA71A0FF3F4B3038CF91BC7138F50B0A7E' : true,
+ '11F7A939F33BDF6270E16C747C0B0918902CD4501AF1843D9EA4445A2E708C58' : true,
+ '1243C75D0F805DA54E780D0D9C55247B1ABB31FC09EB65A7017695945F2A0D4A' : true,
+ '124CE9CD70225896BB3C9DF372E0457CABCEE8585D1BCB8E16D0E6D95B94AF2F' : true,
+ '124E430E0E0B103B580A0436D7CF436F6ECE55908279FA8EBDF475AED08A9CE9' : true,
+ '12826065A034136FFC2258AA1A65F9E550A582B4017E396077917C775D42E553' : true,
+ '1363B86EDA0BFAF10F1141CBE7569647F2FFB370F539694288101128A38261B8' : true,
+ '137E64BF679E2CD24F034125EC926D48F34C7404CFD6B61B23BA9E91E55D3560' : true,
+ '13ECB3394571030912CDF82DDAFA05B242398929BD3ACE1598B79DBF28B701F8' : true,
+ '142A33AB96C13ED7C7B8782D764F374B5A8F9C4E33B4DFE9B7750E878E7C5D0D' : true,
+ '14587E25D8BF0150F429924144E88AC551C1F77CB5DC84F6CDDE7079014ED2EE' : true,
+ '14E443C709A20C11205371C5BC54C20CCD53AC434750EBC91C45B30DD0D8B53A' : true,
+ '14F5D6BA3842E708E3AADC26B8A9CD89FE9CF2BEF46398369521839733A4504F' : true,
+ '150F5BC3D839579BD7DD1254A6C3C3AFE3485D7DED21C3B8123BA6875886A91A' : true,
+ '154C4C43AAF5F838B7B9BE748FF671521BDF0ECF3D749EB85487F9C315239778' : true,
+ '15F46CDF488A5BAD54DBA0F2E2F825F956F8ECF9E3AF294551E88F62A8A0CECD' : true,
+ '16BE849F33D16B22C495B9793329BE704AD9C681C2A963C71FDB303D526E09B3' : true,
+ '17A0318A02B4E7EB14792644E1E28966257748F8162A53AF4E49697A4707C9F7' : true,
+ '17BE5D468B1EA071C36079A4843B8A1E69B9FCAFFA0565FB54B10A02D78B7FA8' : true,
+ '17D0A909CE750C728FBD0F33589A3EBFDA452D00C757A18557DB4697289287B6' : true,
+ '17E110287D04C595DAE0C73090051A1F30F165A37429CD78C1F8FC1754549D41' : true,
+ '17EC9E8F98C207F4CA7FD0680193A54DC33BC97CB364669442F5B7492D36839E' : true,
+ '17FD21D68D53F369EEC1E22EFCC3B79B255EB8E1031D147F6461291C4D980037' : true,
+ '183AE55CFEE1CAC5CCBC1C58D813DED429DF750E023362FB8BEDCB27A9F94559' : true,
+ '186DC5DF9C693C311857A94BF9B2810BDD02F22DAD527D2BFBC0CDF24BCE26FD' : true,
+ '1882C2D8D817DD1078933D244E379CFC5BA8EAAE302BCF9FA22636B08FAC86CE' : true,
+ '188F5D081FD0D98429D1747FFBFEAB39733EA7C2B61C8BF6B0ED62F71264C619' : true,
+ '1974EFA39EBF5C2D3B53D5089EF28F6545D5B4937DB660385AF579A28FD17A3F' : true,
+ '19778EECDA512FBEFDD9AD0507A1F828AE67C35594C20831D1D531B79F8B2F99' : true,
+ '19AD483D37D656F9D7844F14C53281FDD56683C0C8FB2A8F3F77DE7C810C1CFC' : true,
+ '19C76F18839C90F94AB9E4CD3ABC4C15E0A8DA9B8705E7DD872962CF8409DAF2' : true,
+ '1A5C89F300E3A9835759D6588CE3361993E336D76EF4B2F64F1DFC4D913BC6F3' : true,
+ '1AA7EB7CB182FF1BA09FCDFD088DE1F25F8551DAE53CE2C16D4D72D1B6091CA5' : true,
+ '1ADFE710199AE62734EAD27EEE6D6A4EC4D6FF19D6978A7CFBDCABA69C1617E1' : true,
+ '1B5827F9E4B66B4895AB47A0395BB1E135D15F7A23712147C5D382C1AD805ED5' : true,
+ '1B8AC4A31C75996D44252AED8CCF639282DF3A180900C660804483597238D8BF' : true,
+ '1BAF1A75711BC2EF2C4EB8C2BEA4B5B1B183E95ACCB247DB89B3098C324870C2' : true,
+ '1C1BD271327C7721AFDE3C5BE6FA98B132F2EE1911BDF05F0649121349A4537F' : true,
+ '1C1DAB84FAA0FC35AAA8A54760840F8A48EB449B338D7CF3902397514F4D1CD7' : true,
+ '1C363FBCE719D6567E55DE267E6662A454494FA085180F23FE84139E9E83527C' : true,
+ '1C573E491ECF04E3240144B2A63D8DDB457367055B90F5947CEFB55174A6B959' : true,
+ '1C923C0DC4E99E8F807E44A5499EAC4BC48022C63A3EB4CE819D556349FB57BA' : true,
+ '1D4D6D7E6B04F507E28EEA37367012166A6E4AFD02D2F325129A70F76894512E' : true,
+ '1D602FC8C0A6E38288593AF300D73F04B3A5AF89F5B08A0DAC3D935A9B69D7B9' : true,
+ '1E15FDE9774DDD452B000A3FD8118DAE63D16F8EAC19D26806BB08A70677F42F' : true,
+ '1E294231C72B07AAA6E2FE3B18BA14F1095F82718B42AF1DEE071D011740550E' : true,
+ '1E5D810BCB8DA3AF393761C59CC88D22669ECB7D4F926760BE1EC6CD83E60765' : true,
+ '1E5DD6CDAA3AAB8BB891B8D7B4E99AF2EBB7F08719F1D3B3C7B8694962EE8668' : true,
+ '1E84A8F15A3EB4B7921D7462C1FFF8DDC182E4E0682EB48C42FB3645BA43A6E2' : true,
+ '1EC6CF08000A6583160FEDE1C117794E75CA5533B666D04FAB138D8F12A4ABC1' : true,
+ '1F1A125828C6F4A21A9D035C28E5493FACE0F4D7DE6B6F2DD5B9FD5D426B6FC7' : true,
+ '1F3C4550EEA0B9B8F4608632610548B64126E8929450D285DBF906752241CEF3' : true,
+ '1F4C963A9BA39CE44E46F135EFEAD5B30D6A0A3A43545E18CBE59DE452A6468B' : true,
+ '1F6AF055216D53382D7D42AE6893552B4C04C0D6CE31A2A71B7FD24F7A607A67' : true,
+ '1FB6F7F8DD4B392D4BEAA5E707AAF882D2AA83C5E9720C58B616F8DDDFFA6F77' : true,
+ '206A33714BD518CEFF68A6904E19B0837230BCADEADEA6E056EE3745774BE3EB' : true,
+ '20714569334D93E90D2200B253E447A249EC53311A379538BFACDCEE457D9656' : true,
+ '20BE732FDB6D751C0991700E7C9D401093135652D25B1A29D3387E21D60B776B' : true,
+ '20F2E0109442ED3DB805D939B1FCC9F4C8E17414F748FDE98883C9EFA504397E' : true,
+ '20FD7A6E1659C35B1870F698D182820EADD8E02ABE97A9FCD691681B4A6493E6' : true,
+ '215C6D97B01A9EA11CDCB7D4D62EF74D31231F99CA59F3D21104097AD5D52868' : true,
+ '22BA6A5C28A505A68F7C025447822720E4772BC380FD9EA58EA71C32682CF0FC' : true,
+ '22DD516BE482B2A7F3C5EE268E8110EB9814E86E4102654C3CF5705743BCF870' : true,
+ '22E6BB3D9964F458D462BAF404323775B20EEF02F174CDBB442D4381DB98C61D' : true,
+ '23223C3601CC5682B21E4D4C236BB85C9098082EE3942070E33CC791CDFAD31A' : true,
+ '23980A7B935B10CA69315CDA05E61B4ABAE7876724C0E0C3CC7BE9748E41ACCC' : true,
+ '243D9193A5D38C9F2C21409EA470757D3903F8C418709E12C47F01C4EC08E5D5' : true,
+ '24540FC5876A301AF83E2494013ED0B4F7B1312D7238EDDFA1DB0E7736082856' : true,
+ '24789DF7D8F1D393F224621E436675778CAFD595AF6988D2995F28553F28B629' : true,
+ '24AEFDF5AA4C36F89987C960EA14B8A90CB2670CCCC66957652A21E0231D2E4E' : true,
+ '25531D59643B0F5E1CEE67B9CE42B0332FCF9688659F62D990C77CB8C1349E10' : true,
+ '258296CAC41A779D819E37CB4B120D2270F55AD8BDA24747C572165BE31849D2' : true,
+ '25B87ACDCD18628D9B64EB9F6366C970B2FE922B39EBB7E3DD1354899260B180' : true,
+ '2601092E7F1A7841A9E65C6D24D0BBC0CFE986404E6DAFF628E2C2D70667EB59' : true,
+ '2635178113FBBCC75EABC09C497D411C994AD0170CF9DF999A4FF5C16872CDBB' : true,
+ '2643995B1EC6D06457AB936E18B5A5721CEDDCC82F4E116C36EEC5096BB04DC4' : true,
+ '2677470F2FBD067904B7014B88988BB94F72403C014240B9843AE5A5FA21661D' : true,
+ '26B163AB60042EB690FF4549F6086019E19A99A3B69332AD1FE85D9C46491AA9' : true,
+ '26D184F574A19836878B10B209825413B48BB1C92195AB69F6B01D359FD4D07E' : true,
+ '2710EBB98F6790081E34A1961D7716533511A1746616DDBAB9A3D64ED32B1875' : true,
+ '271B4C5B8689BD69CCA837BC080C554DBEE0B20C5B1C505F68544AEC29588277' : true,
+ '2774F85336B9446490224280339F361F69E44891C5D8F078F03FEC5BC7C37437' : true,
+ '27C6EFE085FD0EF2DD467630B0A650BD3624BB4065F811F5F99CA976B4C0B871' : true,
+ '28002E2FB259DA7341B69C144F4EC6B5B12CB9A981C34387044926957CF9152C' : true,
+ '28082C3B3FB30995C3ED4D971AF00E3114C75B9FA47540DEA79E120E01C03562' : true,
+ '28445F7C648AB6025EB469E9C5FD10C6C8D0D21B6A20F078854EFF406C55D3F7' : true,
+ '287821696D43B83F1EA4A3AF5F6E5695F86D770148341106757B98DACB5C979F' : true,
+ '287AC69E23A84ED6C79668FD778A1C5F89D93D9E85B1F84110731B3EF007852D' : true,
+ '288B79B657E95C6E9FF6FF795A3E36528FDD26538925F67411B0F1F715DC9905' : true,
+ '2895D775D2F7F4D7BFF504B3C204939766B2C2734BC607B154CB1B2E52D76012' : true,
+ '28B2F8B5E2ED8681AE3D47EBB733718E32FF81FD736E97EEE68E12A6CFD3C9D6' : true,
+ '29AE4E3FA75E6A40E5C2D8BB9446BC39D672780F4CD6334CA2527FFEC0FBBFD3' : true,
+ '2A00C2E13F83FE2640D9DA1B802219AED52B811CCD54F7632622FB05531CB829' : true,
+ '2A227A780950EC49D49437E4FBD2306EC1D213A25343B752F116B3C4203C641A' : true,
+ '2A2EE56590084C2B144125731B45BDF927C357840E997888F52EF90AD6361EA5' : true,
+ '2AE917E3AB4B867883088BCFFED53EBEF9F87988C77AE47FE325547B181931A1' : true,
+ '2B372D2A09743CB535C71949D24612C108A95D542D5235B443C116426F4EC740' : true,
+ '2B5FC256FE24DB51001FBB200C80DEDE29EF2CCA290DEDA0EA7FA5627A8400E6' : true,
+ '2B804DA0656D06DB6CFF31AF9EE7A41E9621F5062C855A3FA3E69208C6BED1BB' : true,
+ '2B96B9494AB9EF09B7D4ACC0F7C7C8B27BB23772D8203F98A635285335B476FA' : true,
+ '2BB158B54FA26B5A7FDA92096D214B5AB548D13D4CD0D275B967703750B03097' : true,
+ '2BDDDA7C2F05123A014AFE1044AE6AD3B1AA14F0BEAE4FDE812BE52DA271F992' : true,
+ '2C27A3FBE2D833ED7FA00DE8A00EB1E16F40043D68C21C6FAA72A34DD839A5EB' : true,
+ '2C43EC0374BC603A1B191B88ADBCD5C1A0409120427995C2684A1590C7AB1432' : true,
+ '2C6E83BE981FD0EB0ECE7D8977D665C1B7665DFEE4C0F7DBDF5138FEC3974EBB' : true,
+ '2D75CD1232720CFFABA233953EB8CFD860C23034BD9CF969E8D104485B251ECE' : true,
+ '2D978BE3F44F069B366DB5D8E3B1FE4B02775498DE8D17EA68B423259B681FDD' : true,
+ '2DBAF94C053FCCFA1EC09CBB22F54DAFF2DB4ABE1B3C61CFF1BEBC31260F4821' : true,
+ '2E23B68E6E803E74BA36D9C9006F96D8BAC39DB4CAEEBF1C12C6CC01CFDFAD6D' : true,
+ '2E50DDF50FA4B9220202816F9B79405227BA4F803E61FD96D6BC95A0263E49EC' : true,
+ '2E6193577D9F6627E5D23883970975541C6807F1DD1F48971EECF07C204C16BD' : true,
+ '2E726E5D6C08B18944773DECBBBA88F95E25D586248B145354596BA8DB31DDC1' : true,
+ '2F0D2656CFB3D34F4775E89AD96E2AA7D3A1FCDE399BCB2E03AA2BA0A035946B' : true,
+ '2F36C6E796C7C4047152AD68B781475E3FA3AA785DE5CC277DA2DA20F35AD52C' : true,
+ '2FE442C9741D5351A016B9796E3021A01BAC6867A567ABBD1C7EB08DD359DF94' : true,
+ '30354519FFD4794257A7EBEDB0D47DEC9A547B4E7213199000F41EB65C233EF7' : true,
+ '304039981650BCAEA6BAC7B1FF2E03A9BFBC8AF4C37F37E66D59D327776EAE77' : true,
+ '305B4CDDF744AA543DA713E7E60C19ED5537D49ED2252330B46B7E664C4E588C' : true,
+ '30AF2F588C872B174436F3B68ED432C0495D651C84A04787CC8C13D6D61DF63B' : true,
+ '3102A33CF44D88924253BC149D22198D046E6571E79D0C6CFE106F8A725364FC' : true,
+ '3141118408E436FF8489E07BACF80B260A33E842C5BEC83C763B6AE73701A76A' : true,
+ '31C4E7F6630486BF42150967E951D3DA5ED8D382AA596FD571231CA96E0F352E' : true,
+ '31F411310C7FCAAF8CC265F557CF93BF32E5E277589E932442A3A840E141809D' : true,
+ '32CFE4F78C2B8737E9A31F4E0A2513535FE242D02F1DD83C04ADA77839CC4442' : true,
+ '32D398E73D053561EC78257EB01F0945C2A38D9F80674F6F2B4B10BA35A2B4E4' : true,
+ '32FA61C84B195BCADA9A65448CD3C8CA66B1DFE252CF97D46567ACEB59BD2D83' : true,
+ '330457913F88C2037F663003C36F0B6B2B3071AD972C9A4DA54998A7CEB8B148' : true,
+ '331C02F8B180F4E4F15DFAC71D1F03F3ACA9438FEE138AC2A60264BCA35DA54A' : true,
+ '3379517964657D6F875971C1ED6218D9F890BEFC7390CA654C79A666D1989A18' : true,
+ '3386FCF2133229E0BB6481DD2149E9D87540B5277E3FC3C3DFAE50A8D81D0653' : true,
+ '339C59871E132711D25988F0DDB86E0EE5D34B119972C0A5E3C3B556BC293D74' : true,
+ '33AD12326DC0DE4AD1CCDF7B3F1E0202B8476857E1C911B056F53CC6D4A60187' : true,
+ '34CADA62CE9D32857D65E868355E258447C0111D3F78CDCF4360F5B7B9F7E3E4' : true,
+ '34F904FEE6E8CF59E4FFE90F627D688210910D0176C9B5ACF7DAE8CABA722B63' : true,
+ '357E325CD50420D15B1E6779D32E62FB6029A9710017B14CC23AD41DE08A400B' : true,
+ '35931DC7CBFF8F707BEF6D02988B66FC79B77D05DA0A09F439040F4099A69883' : true,
+ '359D692646482C906B77BC217B7C262E81B6D80441DAC6FC2E317C5A0C1A72DF' : true,
+ '35A88292416784CF9D883274B422DDA092B8692CB98FCC788C9B926987854291' : true,
+ '35C8C522026971801A41CE23438829BBA27D3902953FE183E2E3B84415F6ECEC' : true,
+ '36267B2A60E0B5997DEEE17CDBE6AC7F7D54D279C6AB4F06CD469919F442E6AE' : true,
+ '362BF6E353729E4F8FDA7D87DD726C825E2661DA801BB75B857F4DA622BB9704' : true,
+ '363C229BA74BC61CAD1DEF35B5B808146FB5D1D34E5D37C02E1FE19B5EC6C37A' : true,
+ '366B123FA1EA2FF7FDBCA0422E504C8E0AB62334AC8941D307060F5ACDFB58AA' : true,
+ '3761FB4C3FDF80BD66FB31A506612BE2B98FAC57691A6125227B4787C35C32F6' : true,
+ '379F1BE4B67E89183FCD2AB1C0A3B930DE70D33CAE2C8629819DB4951600A398' : true,
+ '37A8C0FE01BCC73FA73F8A161566E23F12C22BAD0461D7CB9D9386EB7DD63800' : true,
+ '383BB79AFA098696BE4D3605F26A60FDD7C455D31FB03BE8553C3EA348F479F2' : true,
+ '386702317DA5549A08139017D14AC498D7DD4837E0E16F91BCAD37684AA6EB97' : true,
+ '388AF939697463B651AFF01141B625DC877D0FB31CBC5E234A5526BAAB68E660' : true,
+ '392080D12E0D8985A6C35526FCCF9CFF55219D7E62E92BF05863F7CFFC42596D' : true,
+ '39CA68E75049A34F875DEE1CD6929FA61DE4B250B5060D613BA9088810D60B9A' : true,
+ '39EC99D4093CF0A60A947685856F20DBF85966FBCAB4033890361A650294A8A8' : true,
+ '3A9480EEDF0D65938DD92A7FE7E9BE4D797CEB0662CADDA2321D47C04818A57D' : true,
+ '3AFA38F8367A45AAFBA949076A38537CBAE4A0774FC4CC40BE52F944F29F7F19' : true,
+ '3B00662EE3F01FFE2C40842F0F3B76C039ABB785962E371767E89E2AFA311A74' : true,
+ '3B1FDB5890A3C11F7149C13019F3EE43D3D3A8C174E485512E946EDCBBFFFE55' : true,
+ '3B3A1C7A8131E1E6A66039972C1AEF65797E783ACC2C645CF10EEAA5F20BD297' : true,
+ '3C40EF3135CB1E82D0E6518EF75EAEDAC43DE347CB74E2A09CBC0C5A56DB2636' : true,
+ '3C49B9DC9307C6B33E0DBE135836504ACB9F6204B7172A412C28E797E56CA02A' : true,
+ '3C91A39CC52452FB91463E511257D3BFCDCA3A149EBF39978F39E55F20FB061E' : true,
+ '3C96B0CE3855D125998B8DDA63F2A37AA1FC5967949393D7428C1FA97D2542B4' : true,
+ '3CFD92A9ACFC3B9D7BF81B2994D398500413E7B57C711D711F98DB009FD142D4' : true,
+ '3D04D60DD221BA390696E262A7B522815BAD5A03B79D1176931F2AD5435D494F' : true,
+ '3D7A71BB494A12E1F21A1EB9033CBEFCD1FE81F358B131016DAF92C1C06F1A38' : true,
+ '3D81B541D1B04B15AFEF518152CF8DDDB9300EE0A1BADC916FB366FA034120ED' : true,
+ '3D9910368BB2A01AF8277EA5E26F9CFCB045DC63CEC7397EEB2827B16C0344AE' : true,
+ '3DE5855D87575043D52CE7496F7486CBD8177FCB9F8C686B55F5F0EE761B2DFF' : true,
+ '3E09F448ED5A72584FA305F82A25706D2AE756083530B4E18665DA2AE46C1410' : true,
+ '3E18B028DAFB97BD9A036F1743316C8EC963C17066E362328FEA24D6FF8B2A7C' : true,
+ '3E486CEF660870234BD56B008730D8B318B7FBD047B55939D74545B98D8176DC' : true,
+ '3E5558CB92AEDC7E01DB0FBCD0825CC0F51AA7B683ABFD01D1E5E04C8A4D716B' : true,
+ '3E7FC707C590EECFA7E9DBBD270452366C0E2F0ABA7768B3F18E7DE34B3E15BD' : true,
+ '3EA82DE5DF72699D567B865AACE54C72AFF800647415E5E49D4260F422C26DA7' : true,
+ '3EFD44B1F0C8400130C35FE003FA304C2E47FD20612A4D1C83F88723B885CE66' : true,
+ '3FC8022D0C28EBFD45DC1D07E14F9E83F0CAD2E7ECEDBFDB991E01EBF2400F54' : true,
+ '3FC92874F07DB0DEE11CCB2CA7BDF187641DC78ECE4C76E71B2253FBBC17E3FE' : true,
+ '3FCBCC65096D7D731244167CCEAA21757E56D6EFC05A632AB3E062643E5B380F' : true,
+ '402FA5AD0E7932A07356FB849DCC1AEF11649D516ED1C5617C48F3E7F9B02356' : true,
+ '4093A7B65486890D2575D57070237C586DC489B3A68FA913DEF136370F2DDF9F' : true,
+ '40E66AA57071722F0B8E8B59A74998F82E8D5020BDDBB35D0E941851ED11921D' : true,
+ '4147C9CD6ECA16D7C6A8939E15E419220C822956FE754DCB2F08F2C78A99C3DC' : true,
+ '414CB8A3E4E86E2B4E03EB2FE71312CFE17B78945B41597F8E03AF04CFFAECC9' : true,
+ '4196DA17789961AAEB04CEBF7F1F77621F89102F48350D3B95E66E955FA8AA8D' : true,
+ '4247E57738776992C6640ACA48156C9DE580F0A739CAF0A353CDDFE3417F7C46' : true,
+ '4248F09AC0B07BCF41B413A2D8FF50AC42C6943D6F6D20F9C37502FDD2315171' : true,
+ '426334353C51D4E625F2DE937D9AD9FE6769E0F4E1425AF23D7802385103B583' : true,
+ '429DA945C771332087229D2822684175DC050F832EB9F0ED90F868E99B6FBFC1' : true,
+ '42D6DFA920BABBF7876416C3F5B30598040F6A748F22E3C3E0E2D32DEF098AD1' : true,
+ '431F835569D356C0C577FFCF90DDBF9B17E16D7FA9027888B708071B696E818F' : true,
+ '4321F690235447D71149C54E13896C885D07524C80CBA133428E1BD235123234' : true,
+ '43555C20820B179886354E63251A21247292B3B7BA46D8BEE860A0313258136A' : true,
+ '4373B2B85D4FEFE97E79B4C7935AD1762380D97FAE2C64FD61E58593F8BC8C4A' : true,
+ '43CFA30A34E75D16640693DF32B691B40219631AFFFC6A09DA97006AFD2811FC' : true,
+ '44338B3B7D1302BEC14439BFF723B5AF93DC549A7E1E417112C76C1455108EB3' : true,
+ '44CE10B295D3908C5CB40661F3F07EA13B27A31F32041B79D12AB7F5250B4227' : true,
+ '44CE6D5CE40E8F7BE79569A66792B181CA71DF0C80D3CEDA59A151F2E7CD32E3' : true,
+ '4533B5CC20DF3613F517118ED8D5AA328EDE18610AE99E16A5B6AF21EC0FFE17' : true,
+ '45CFA75EF370F3B3C2271E4AA0F99106B3339B6FEFDA5B335CC863F0C6F66323' : true,
+ '4603C35A8304F6057C253381D39404E8B40AE0958B4EB2CEAB7777CD85802C0C' : true,
+ '46236B9468DB40FAF467AFB0C35B517E514251530785695F54440E6730AAE44A' : true,
+ '46584E2D9BFE069862BC6449C85E904AF29A71887DCAEB14C191D75ED0AC1FCF' : true,
+ '46853D3090658137B446AC75E481E4593CFF61E22115C348521D70EF398C05F8' : true,
+ '46C05D7E95263B17CE368AAED872817DB0517CD9F388396CF42568DF88C96C67' : true,
+ '46E74AF8240C97D2E91E118761CA4F74371BF7D2266601BAF6084BB1924B62D6' : true,
+ '475971EE29368BC1FB6B66D497096A1ABA32C66A30C7D554CB11FE848345B46D' : true,
+ '47828F3C65E9FB0113793E5B60E19A44BC9775611C44ACB65481842FEE2FA819' : true,
+ '478D230215F850914D64BD43327923DEC9E52B4F14EF5E7E9122B16F40B2733D' : true,
+ '47A1BDC994354BC3EB242FFC12768EA8633719084BB5A159E30FC4388BED59B7' : true,
+ '47BE050E9E76AE62AED5EFF6EA9F2E0DF1FF0E7A3EE2B6B68D60B3C849E070EA' : true,
+ '47E134C83737EE674C6AC46306C325701EFF7B0A4C887B968593CC1F5FCAAF0D' : true,
+ '480ABF7202B5437D84FC1F475A30A19C18C7F598BDA1375E8AB84829B966D596' : true,
+ '4810562E0CC4EFD265AC19316F353D660806DC54231D65C906C6DB1E86EEDAC2' : true,
+ '486F62E8D5F6323416CF210DDBD26A256AF9AD33F70A2C1CF8915866F74C149D' : true,
+ '48DF42F374FDCD58EB650256F421F6C1A73F663DCB8DE0972DF9421205509F8C' : true,
+ '49AC28CE0DDCDA953E64E7D131DEA9EF57169FF3280EC9FC6DAA88C943EA9E76' : true,
+ '49B7DA13E82D9DEB867193B30E48CD1279A66A6FB44236E1B93AAF62F58EE077' : true,
+ '49CB0BC132E548E6D6A5BCC31C2254016BC2A181755B5B13D1D27218404D1C74' : true,
+ '4A12F9678B1A5B4677054BDA1CB6B41AD8A4F556A184E7E4C33669EDD31EA50D' : true,
+ '4A60AA57F2A0858D4A3A9696C5652432997B73BDDE06880BB3DE7879FE79B87B' : true,
+ '4AE41D7B98B74E61B0D6EED291348B881E5531B4ECEB9940631835EF6A8CC60F' : true,
+ '4AF1D354BDAA3AB076BB6A02BAA3E1BAA2503D21ABE54B54001BCF62C0982721' : true,
+ '4B2851A38CCC082ED3A24F9DCB8C917F572D9F064CEF218D2E07ECBAAF6EDAAB' : true,
+ '4B6B616E1EE80E17D1BB037A2831C3AAD7E6CDE3D89A205D1F7D6E0854F3C21A' : true,
+ '4BF10AC1958BCBEFA06944AC7866E3458EA70E6ED97DBDDF01A84A360C3B71CA' : true,
+ '4C1A5506EA02230980E66C1CA936B268A3C453E997733E44074640CF4653594C' : true,
+ '4C3F647343026A15ADA9E047A8B4527FF88F9D01A2B7AB7241947443F75D5E96' : true,
+ '4C6FC9852280F11829BD4066C38BE6C1FE4E4C053F6126EE03D15EC3D0BD5B15' : true,
+ '4CCB36D30DA2AD2DEFBFA838DE32AE64AC8F6AE138E0A1FA46D1E0CDB688974F' : true,
+ '4CE6DB77F8EF355DF6EC2ABA7A5989DD0F2D0BB228DB5DE69BE7C83E3603C69E' : true,
+ '4CE78AB01352DC6AD84A195DD333207A43CBA0372546FEDEC9E6803DA6375403' : true,
+ '4D26A014A4C4007564C743D9BBF9C2DC9A5A881C05E549DFFDAFCD3814F3966C' : true,
+ '4D53CEABA15DE7DACABA8689C96832B59F66AC55E9E94CB595405004A1A9AF29' : true,
+ '4DC47950ADC2B7FF5A9A57167E343AFDDB27155DE0D031F25149B622E608B8CB' : true,
+ '4DD59EC33898319B54EE610C9A4DA78A87504FB8631FCA5783223F306529FABF' : true,
+ '4DDCB0EAA387111F7C2E0355AFF2C3325514BD9D9A3812295F7506999838B7ED' : true,
+ '4E0E281DBED708FB0AF032A0233F134D3BD309224DD8BE9894E749D1AE9BA37D' : true,
+ '4E5AD8D52C37A505176F9BA95BAF43CB5FD5A7FC4654DC71178ABEA8188E7ED6' : true,
+ '4E88949F1AA84802EB493CA5C6CDA9C6DED49A4DBA0C8453139C89A9CEC2E041' : true,
+ '4ED3C78D58943651EDB04EDDCB696F91F7B33450831CB18ACE714720AF4523EA' : true,
+ '4F212E4C3A8E4EA8F7D258A988D5930F05A8E61E78D86DBF9478DA2DE8F01B54' : true,
+ '509A3662D987A2D5D9CE7943D1878A36DFC4A786CC185CC9DE1D58E15E2EE02A' : true,
+ '50C1358C5AA5556E967E2CCC1397BEA364DE2E7C6704B6950E423AD5D5BBE798' : true,
+ '50D5DCC8D0668D34E90722924EB28C37C803E34156DE8E61DAB296DBD37F5993' : true,
+ '5112E6A8D06852BA07669C1DF31EFA1BA2BE7894C3F0F7B7282FEEBB698F7F4F' : true,
+ '512EFAAE67E525C0DC3D7AF491ABA9FFA1B7439031207D293622E9286F0BB562' : true,
+ '51452CADA5B15129E04773A1BAFC3166F56C59B4CCF905060BA52EB6A877E1E9' : true,
+ '5184A3AD148B610511D8D02CFBCD2993AFC3BBD576721B617FE7CB1DF53C070D' : true,
+ '51ABE9BEDE2D96CA84110007FD6626F0ADF9881A3C74870C119CEDBFF2B4CE54' : true,
+ '51EE14CDF007AFBCE34D598602831B21661F6FD7B6C04B0D34817757B4D007D7' : true,
+ '52B8E665B8191D828F946C041ABC28AC6A5719A4AA21B1C403F7611F11A84F31' : true,
+ '52C584E4DA8D3FD6FD63E83B2EA0FD6D98DB0413776C26122FF0420A3F0F91A0' : true,
+ '52F208427F03726C6DE3F5308C776D690F580EA39DDB01595DFB54364C48377D' : true,
+ '5376577409E17E8F37B2CC6FD486FBD356FF2AD0B5EF520DB7CDAD06C6A6F3E0' : true,
+ '538735DC5CF27D0DACB0FBC4FC24E0598D8838682CBE3DA8C37CDA60F60BE64C' : true,
+ '53C57169154423529775809598828294B218B2D2AFBCD3F2561FD072376CA188' : true,
+ '552771717F5948A7FBF93067CF25E5D1D67A63C8A3DD09EF98603165874E3281' : true,
+ '5545F754EE0194995FACDF3F30F3E6A8B0749DD750B0B5964B16A5D9B21E9FAC' : true,
+ '55E0EF8E07B79720C78F3E2303981BAC4BE4FB417D858E3531716DEA81BB8D67' : true,
+ '56B5B8AD95FC9A853F180196FAF9BF2896A8D2E053474ECA3A19295B1D214AD1' : true,
+ '56B6BEB3100D40CAB0EA4E450188CDDA653F473F3F182578AAB314006E66FA5C' : true,
+ '56CC8586CAB1C99C3EA4C1D35E91FAA568DED02AA74364D08F480A0EEE4E4FF7' : true,
+ '57383F2DCB3A5959514A8C0CB208205EEF70D3A899BEA2AA7D1B6FD13BB23BD8' : true,
+ '57A0B57635F2D75EBC9C3B166E68E35E1CF91BD074AA9D5CBCB3359D93F02859' : true,
+ '585CCB444BDE628F6778320DE64727701AABA22F826C31063082CFC5835742BB' : true,
+ '597C180F976AF183984FD9B1D015D000C55AF0B873FE4A4F8E782D191285BAC1' : true,
+ '5999169B7C3C7ED6E94A194BF0DFF7D07EB7581BE8C82E77B83DE42263F6A673' : true,
+ '59E0DDB8377B568DA0FC1E2B7C482CC6331DA441F85E7F52FA8AE280DA90D051' : true,
+ '59FF0CC641EA56CD3670E81E4BD76A487163C70CCA729E0710D49AD1EAD70634' : true,
+ '5AA16CEF791C27E12F900F07D5FC9D0B3386A1FCCF2F547D08E94AD34BABB775' : true,
+ '5AA7341552FF047164227AEFB41437582F7116D76B854F54920A5D6A9B72271C' : true,
+ '5AEDDAC786E11B696A37E5506BF5CB702A3B803BC8506BBFF720788401D595A2' : true,
+ '5AFD1775AD2CAA741FCF1201AE206C4A1286C0DBF751AC035BAADE571F002927' : true,
+ '5B11479053C46A16C629C58DD5EB40529814B75A6BBDCD6BD6FC6BA9483D9669' : true,
+ '5B1D47E25C53FAFDB2894D342FB536794A99B4D0F4C0BB994DAC22CF9247F166' : true,
+ '5B67A7FC34D1885F7351DC949794160E0DB6E6C193286145DF8E483F21E90B80' : true,
+ '5B9F8603E75E06129C216E4A2DF6FB4EC184CE685F6C229BB85233DFFD2335A6' : true,
+ '5C07B9D0BC6C5C3634102DAF631A330FC02BF579A3421E1B8483E076953FCDF5' : true,
+ '5C2484F4DCA59EC5D77C5935BF71EC473995A9F7D39B0F26D2264A279C6DEC96' : true,
+ '5C25116119EA6FCA1D13D54D4870475E5B3D34B060605E02F9C7521D3EC47441' : true,
+ '5C34509E57E6B30A28891841EFB2A5F0D051493059DD80157C19B2822A97EAF4' : true,
+ '5C95EA9F41391B1D2609E3CBFEDDC0B9B865326B4526176D5305DF2EEF5AED52' : true,
+ '5CDF3C4C27BB3B1BBE8C6AB81EFF3FA995BBDFE662A0BCDED869E462BE748486' : true,
+ '5CE0E2F94DE7BFC370B5C429E1CE1A0635E4F38D55BAF122748D4307F1709DE9' : true,
+ '5CF08039C4F9AC5947E941DB6D681C0CD7971AD6E068262D919060C1A66D5FB2' : true,
+ '5D2112B7777AF1BBA029F1DB3D166086C0379669C01C03FCB1667645F32EAA35' : true,
+ '5D5F5FC12AC675264FB7F2783EF62458304D84B09BF62E19EC1B91243E3E5487' : true,
+ '5D77443F3FFBBAEAB8C88714A8EEE37196F7D9CE89517806EDBF897DE0215763' : true,
+ '5DB16AA171CA274D753222AA4EC17827814F5A69CFE72D092397F048CEEB2370' : true,
+ '5DFF17B36C6CED5E5607FC2A8B6559964A23AB8B08181E1CAC94E3B213767A1B' : true,
+ '5E579D296D274F9A01D1E1A7410A24029948FFA01595E64BD2E492EEFDD1F702' : true,
+ '5EC75158F235F80BBFC25F40D96AB89CC35D8578BAD11410B5D32CC33428A00E' : true,
+ '5F05ACF54EAA38008B650AAA2DBB3722805C793616B1A21B43E1879107254E38' : true,
+ '5F6795C104B707429A3E966D32F847FF1B18497C73A45F6EA5E47378EF1D3823' : true,
+ '5F98F1AC11CB74885CCC871AB7CB1B95989E9E3E7482BDFC32895A65A783AFE9' : true,
+ '5FB819ACDB4D470232F59DBE853A5BC55C3713062ED6F75AD35982304E14B32A' : true,
+ '5FCCA125301032F32C5C915A1AF5191FB7E0ADB6E36AB4210099490CF54C2C27' : true,
+ '5FEFA4F01BA5AA16F36E2A4125C2E0F808B9503355BF09B3189A623B8EA42E69' : true,
+ '5FFD23170DA2D4AF8278447F473A80F69D41889D6C91F3A598E41B4C1170E43E' : true,
+ '60234A884EF08293BDFED2AA0F7A12164317F1453966758A66FEA4AA422E9A14' : true,
+ '6085325DD4C19C14024B66E50D6FB600D161AE12B569A70B9C1EFFECBE9C2A3D' : true,
+ '60B1AE233D6CEE231FA2D0B3D5888FC9842087D2ABB3CBCC6E9C230D974F5D7E' : true,
+ '60B7233177358390EAA910658D1D063B57CC3D5B76F70E521CB81E39DB9AD50C' : true,
+ '60CC6E8C652D1CCBFFA42DAD8158217DFB7F42B9EEF9DBDB795ED372EB2AA728' : true,
+ '613E70A1BE3CA6314EDB7C00B2477990271E0C8DE8210EED56ACD391E8CFF28F' : true,
+ '6167E58071C283AEE1B24B692C593747D5FAD1B3A001B1CF11569E80FDA44152' : true,
+ '61F83ABFF7740C9144959145660E563D682A8D21E20B92AF581237F621A5187C' : true,
+ '623760585A2256D234ACE51A98E31B982EB5E5BA2D3CBD673C747FC832529F60' : true,
+ '624A2686ED8B75686FCCC3FD9DB8284E94981BF30BDD2453817BD653F3BD9CF2' : true,
+ '626042CAC6DE8C95C77C0E732144FCBD63418D72ED04CCB42FCBF260B38B21D5' : true,
+ '62C06D5EC111BEA1222B57F5BF5FA974B5025C3554BCFC2677048DF4A2EC0170' : true,
+ '62C4876E637B0361493822910A5FEBD70113B70407AEE4FDEBF249585FC4A069' : true,
+ '62C9A052080F8EBA5E8FEB9615B5CDDFFF1D74F8467653030CB1BA12337EB5D7' : true,
+ '63448627F20BDD4F11B278941D82DE56AD3A689CC06064D867FF060FCFE29A49' : true,
+ '634783AC64589BF61818D6D57D8C3628FBECF3354AE91725CC1CC3A6B62E4E0E' : true,
+ '63591FA550D322410D6B2617A3B70A23046032A8CB2F96F2CFFF9111D46489BB' : true,
+ '635B65E10638CE83AC12795BB42A235C6DF75DCE35AB6901255D4A3B0DE05FA0' : true,
+ '63C46A097FF0E3D00C6ACAC2029979168DC83ACF453ABD79E9502AEDFC9736A2' : true,
+ '63DBD2E32AFC1025D4AC5CABF8E6E61ED4DF6D0DE50533BFBD6E3918F40E6EEB' : true,
+ '63E6A22E453B17B4EA3E35C6E39EB315DBB77A237B1BBA9BFB2B3BCF675A63B9' : true,
+ '64261C63D988D7AD86D209177AEF7DB6EE3E62151B54C6FADF8F100C2750D0CB' : true,
+ '644E41BA23C44182CD1D12265833CF5D62553B2192496B051118DE945E0B5BBC' : true,
+ '64831454483CA9CA55859BBD324F492638DA8179EAAED19EA3CC8E16FCE7A83B' : true,
+ '65B9EA850436692D74A1A350E112A63BB4F2B9E4B10A602707ADBEFE76B247F2' : true,
+ '65E435C88F831D080BA50F37D0668230281DB9A679D705FBA84820A44D822540' : true,
+ '668B926F5EAA59F351B7ABFCBBE5FA17B547B01C5A7D4AE385736CE8FD13359E' : true,
+ '66E91987E1C56D61C6210022B93C24BBFA83C039C8C13E71A4E949A252792B77' : true,
+ '66E9E8A83F938165FE2D1F3E6669FD46132CFF7A2F99E5D23CC3CEEE0A07EFDA' : true,
+ '66F68579A292313FF975514DFBE38463C59215775C62323FD02302F539E3B252' : true,
+ '671DBED9969959A1ADA0F9DBAAFB7DD35CB71FB06D0337DB178E34BB5CAFA9C1' : true,
+ '676EC356B302BAC4392ABCD0702056E398C3092F6F3C66B61CA17171FB8196A5' : true,
+ '67E6D8DB673E4B9ADC12C134F94EFEBC055068A7B255AC721582D7AE3FCD3D6C' : true,
+ '68EE7C99FB1E2B8F0DA74C5339E58C6A1F7C2697CDE363B2A8A6D8E012D2C773' : true,
+ '692C08B2A888E8B373FCCDB491C531D58002CAC55188368BB037DDA1F2C829F5' : true,
+ '692C7B1D9E68C51DE61E300811DE5521D900BFBE44AA0E5211A4622C51A1193F' : true,
+ '6981222723F6C1FB0E7C14D8181D0799F0657E123C470C759F70A78D995B7102' : true,
+ '69A828B3AAE09B3F1EFBC53DB56353AF2444809A08F188668225B2A0EB520FC3' : true,
+ '69C135C5854B93D0B081254262DAFDB0FB3C0603D45EE6F5E91BD6678CF5A6E9' : true,
+ '69D7A817007EC6958CDE66700AE1372870F1AE4710026D3F93EE1A15E024C880' : true,
+ '69EEB2BDE9BE075A2C6927DCF5DB9E9427FBD153953D3843BE5151A6ECC3D560' : true,
+ '6A14524124841DA5A7C0A27539973C88C77C79EE8C190068EAAA9218CC35AE76' : true,
+ '6A525C84FBFEF83BEA806634766F1530D9C5964DFAE49BD2F678984AF29FB474' : true,
+ '6ABF9C8C111E6353439EF682EDBFECE4F8AF8029D4E9F3F0E638C27A347DBA14' : true,
+ '6AC112C1828538894A1FAC7CECE0ACFEE75658118041513498E880274BD2B7C9' : true,
+ '6B02CD14A3675354A800006220E94D8D4D5F9774D60EC984955FF720D927E529' : true,
+ '6B59DAD53B5D9FAD67626890D678177BE94BBD7C8E7815986BB28C09BD60E9D2' : true,
+ '6BF07AE522AE438A1736D449CDFF0D8F72F7690C120CD9F51FA2CF88160E8980' : true,
+ '6C636B0095B2D2ADC0DA3BEA01B82A14130410220A5692C3FA2F374E07EC03AA' : true,
+ '6CC97CE9EB4776E7E4EE831B97F15D992FDDE766B9AA2233B41770271C0BDD88' : true,
+ '6D13CD353D7F6723CC79620F59D5ADC6FF6FD185B9482C0D3044B69E8B60434B' : true,
+ '6D3BBB6612DF6B07FDB7630F79AE3C8B7609A853AC5E95FA5061E4248BE9CE97' : true,
+ '6DDA1CB95F5505512C2759E9F6ACB12B2F66CDEA160527EFA91D2F1CE057079F' : true,
+ '6DF2BF0E57C2A025F1FFACF32B574A50464D613CA9873BD8DF692B62CB1DFD74' : true,
+ '6DF8AC95B45A03538483369BAEE17EC1610F591F633E29A9A4DFD0C29E28397D' : true,
+ '6E01105B0FBC4CEC9790A2501D4DC5536754CD3B71480AB7C200B7A671A643B5' : true,
+ '6E61AF6B9F05C441F3AE6B3FE2D5A6ECF9885A2B223703D1C9660D14E6102F7F' : true,
+ '6E7E91E395DCD00520BAB2D41630963493456B73BF32E23ACBF4C2BBD5F0A703' : true,
+ '6E8D6125A9037938869D2D9C291AC9A2AC3731A6E7429D9E2037970069B7659C' : true,
+ '6E95E8980B03A9FF276C6A4F68B46DE8D29410A9FCF4285633DA91647BE7E10C' : true,
+ '6F6CA3B04E355CFF85B89EEB861EDD2D91CC874EEFE99A2D9B0A3095653D9E97' : true,
+ '6F8652847DB9289EECB5A58CA15FA522DA5F26A60E0BAFAA1BAAA37B32FBF465' : true,
+ '6FBABED892623FA77A93005871EF0A6374050AE9F3D3A346A8BD4558EE3959C1' : true,
+ '6FCE4CF77E254C2920BE515857DAB1929ECE7638DD8C370C1AF6A374F36517A6' : true,
+ '701E5C167D1D2A47E29F6E0EF64D59D978CA3287D20E3590ABF531EEFDDD885F' : true,
+ '70202315E3423BCD73E6A3CE51D0F541A78350111E683D8BA64AE9271A9C6369' : true,
+ '7066B709F68AFBA83E93FC497B97DAEE440AA3B27F8E6E32DFBB1365C3F2EE68' : true,
+ '70751440BEBC64501417A81F17FDB0FD31052D19DC361383EDE63E647ED1D8DA' : true,
+ '7081C7813097A8602BE2DFE4BF202EF4574BCD4DDF51FE8C7A2F872F93481E83' : true,
+ '709A501B0835742664FB4C650498359C1576F74186B0D12129A6E96A5C09080F' : true,
+ '70EE22590F5CFBBC659A9EA9BCFA0C876694116323562076D6FA6471E79907E9' : true,
+ '71168AF1899C2122E92CE1FAFCB2EE64B9CDE6D14069E7412F492C9078704F26' : true,
+ '713C52C05CB8B1EA3B27FBBE33649956A33D8E1AC4F222EC3B90428E52C28E00' : true,
+ '714F1E26865618BA75AD738AD3B843B14D776EC9B7D617CA4E7C2DBC98C8E7D2' : true,
+ '7180F1CD379E01A81DB181F3A839C48E64734FD493D1013367A7287181C4A7DA' : true,
+ '72FB0C9D7767CD725184EC22406246CC4E130E49E4630E2D5BF248187EA583D0' : true,
+ '72FC451177A264EC01165ACC89684C137EB92467BB44EE64962C5D1AED5F8409' : true,
+ '731D2388EDB673DEAA419BD26B43D6AE7D27EFDFB47B6A1124EB20D30F90965F' : true,
+ '7356E86E8C181E623D168491A780BA7011327CF716B416619FED3C3878A425B5' : true,
+ '73B26EBA4831AC03380E60772E12BE78303E9A6816058678BC432BA8D640B3F6' : true,
+ '745D3184B509466217C4305CF4082681DA91C917D7C176D5C8FB8C9810C1EFF0' : true,
+ '7464C196FA42968ABF359C05DE1A029FA4CC551380CBBE661CCBFBB1C7865E70' : true,
+ '74711F9774C66CEC41DE4FD32197132B13A40A6758A106DC95BCADB9298A6241' : true,
+ '747E80C10894375B82C313C81766E6757B1B28E5BAE75AAB0BDE87A9242E8655' : true,
+ '74C7149B1B6739C22FC0102A7EA2DBCA770432A85F2095812DC7961831F73EC2' : true,
+ '74D4CF230B19F9B9E3C674DB1B1754DEBA59A837534135CEA2A9DA3496876FD2' : true,
+ '74E0485AFE164965FF9F982F0999B980CF05DE73016EB7F6B38B105A5E07564D' : true,
+ '750C7E44BD7AE01B7D2ABEE54139FF35FC53DDE34A4E0802432CB08764E211C5' : true,
+ '7567AE3D698B690FB2349D4468F155CEFE64ED1975B768E791D934332970791B' : true,
+ '7572D3C2860E9D28159C0337E8DC7C693F307AE0F1F02E0C35E091AC1C1571F6' : true,
+ '75B0A587771EFCF6AD7AF92EFBDEFF0F4E5CAF9883AF521B9B13C78D247B5A4E' : true,
+ '75B50B0EBC80D619AC5A04DBDF5C622B1FBEE1F299594B0E4CD6B6363BEFF8CB' : true,
+ '75F12E7E7FEE1F0AE3C22D1B94D33E4A31EC9C3B0B30338AF4EAD52856A11D26' : true,
+ '7607259BFE14402887557E6AC9BB570FD9D3927DA048FF9C7926758ECE32B824' : true,
+ '7633A1503B4C364C9C55BAAE30CC899238244FC16BEEDF7DC22E54CB9B569A6C' : true,
+ '765511648B44C53C9335BA4041B2808D4B9BE5A3223FFB901ED32673D5898A4A' : true,
+ '767EB0B508322CA5B9E37A4A1CE1CC43F5AFEB557D509AD50261F25DA73ED0DE' : true,
+ '76A266265F7454F38CBC307C9FECDBE80081097444B97BCA9C722D93219EA358' : true,
+ '76B1A25306D53B410FE5318EF1D077B29081025ADDD40CA55ED4A0A1EF557E65' : true,
+ '76EBE04192726D45EAEF654FC3DFE992E2297DFDEE303BBE89C8F425269F41E7' : true,
+ '770784FC2B1A52F110194800E972006E868F055C52A8BE467F3AD7BCD7E441CC' : true,
+ '77C5EFEDC19C242BDC746C5EF4A1DF4117918CBE078CF6DD65FC274DB64CFBAD' : true,
+ '77CDA7C1BAC564BA322B350C6CEC0B9E813104332905F2D556603B8F661AC19A' : true,
+ '78C30D03D640DB32D06E482ABA1084A967544E9081BE94CA87CA4FBC2141C6E9' : true,
+ '79244B0AFBB3B26770A470A4F23555757DC25D3856F56D0096D9F06EB47D5889' : true,
+ '792EE0B202E6A45AAA85E918497D9C9F16FEAC99500A7940C0FC812ECC42120C' : true,
+ '79B0B3A8D1BDB11D40FE8B93868460B339CEE667DE3E94C880AD9BB14E50CBFD' : true,
+ '79B893E3487215CD87BE3BB3CD5CE1359CF8385BEA49A5E45BD03624A0DB3D08' : true,
+ '79F9792935CFEB56CBCCF76F92C17E93606B2774C0F3618F2DE9BFE9506AA04F' : true,
+ '7A081DEE8006EF40615953A1EF9BA820BADAA31338157E69660B3EBE7852838C' : true,
+ '7A0F440C38F18E15DE15BBD496D670B48571AC7A71EE56F0F696E26FE1C06C92' : true,
+ '7A898AD8A9DC791DD00EC4F1C6CA3F1AFBF711D2A26E99E6D0740B1B5FCEFA49' : true,
+ '7A938A727247270556F67BCA523A333A2F22573331A6D696E6C559302C9C1912' : true,
+ '7B3234A53D173A266510B9777DBDA7F372E40651E07B910899A0C1063A560787' : true,
+ '7B40E5E9E8A2F63FFF19CE2F4EFEC73C902CD146E75DF866ED274651288DEC80' : true,
+ '7B45E99CAD17290A002ED52128572713BDD96FC1544094FE297EDF28E4D40063' : true,
+ '7B6DCA23E77F3424FAA26C0DB800ACB6E3BBC3DC13A11EE4679049EE3DF03A02' : true,
+ '7C6BB49D3E96F1125169FEB59751BE733ABD4F0D2860EA0A8F1A5C9B14A62968' : true,
+ '7CE1119D84CDCA99D2C1040485C894E22A02106EEEAB39FD20650BFBF7CC5948' : true,
+ '7CEE465792A72473B5B70A88F140AA27C5DAFC6C876AD88D2E45423D9CDC6C06' : true,
+ '7D100CF85EE12F47C6C9755F00CEDCEBBFA513CEC80993AE5E7FAF6F68289C23' : true,
+ '7D3EF8DEBFDDD39FA7CA90EAC62E660639521686926488A315B10FB2A0005F6A' : true,
+ '7D7753734C01837BEC44A0E459A049D96683FF8D0DB78878C3BEC4C9574B412A' : true,
+ '7D817F280F1D664E0C9E717287D6AADB1132D4F3A3E2001B94009119733C9434' : true,
+ '7D886B62A526E2B996C9F715AC5B23D07EDA09AD69D18E8F54F5210166AE0C8D' : true,
+ '7DAB96077DBBA3345EB176EDF7919AF6889938AFD1D9BD32105BD82B0D1CBCA1' : true,
+ '7DBF7C36818F0BBE711267E6192080F75CE8908B48C9E6EB9626DD9B05308A7D' : true,
+ '7DE8C95508E4933243E3EC7D7C222F82A250E1B71C5619C547FCDA51146392FD' : true,
+ '7E0CD7D375698FDB4C4FFDA33ECBEEDCC86ECE5ED8942F85B216B022812A3504' : true,
+ '7E47F4F45DE3FCA19673D070AA99E0DBFD6049A98B94D090B6B2168A1347D6E7' : true,
+ '7E770FF8F54B17E68443C8D43DCF1661C1082C024BF46DC66716D39B7BC6FA80' : true,
+ '7F0F7FB9B5975CD10469ECD29F69E5C11CDE9EC561684535E8A36CBC514D3DBC' : true,
+ '7F3B3BE589085EF5F314845A6F850F9411F0594FAFDDF725D3AD3BB189BBBE99' : true,
+ '7FCD0B25EEE0A63FA151354DC39D42CA58AC10D8ED9EB4E0B215C652C07D4E28' : true,
+ '8035EB81467C64D22C3624A58022AF1B5D0D4047328109CABB74CE6B580A9A8E' : true,
+ '806791E1F1BCA3B3AFECAB7D1EC6FD66C2616C6CF13A3256AF0D53AB0A759BCF' : true,
+ '8126A7034869686473438C4C7C005631DF665491A9CE81D9B3ABAA27D327CF75' : true,
+ '813CF894750BE7FE8A0C8B5003B362D62D400F6F08BC1FCABF247172A63B17E7' : true,
+ '814461D429FB2539D44E02913E03F0698FC1ECFF7894260AD3AA9C2716B99E0B' : true,
+ '81A524F4768E8D164B51E023E9FDC90DFBD9EB3D6111C0DA5328B8743253BE8A' : true,
+ '81C82F1726447A63776BE2F5E36CC6DEDF0C62F3B11C7C8B7CE17E10309C4569' : true,
+ '81F32F8C3E868A588E5F34A64C6FBDB483891716BABC5C59D75391A58D8C6146' : true,
+ '8249977B7E0D31F533255488A5416349A1C6AAA59C330D6274C82364324C3870' : true,
+ '8256476D83180014AF0D76C02D405990926003E2052E205DD66B158E69DAD7AC' : true,
+ '82668C1629CB39A7B5D9DF6BC94349FA113F915999799DDFE31FF1862FACD095' : true,
+ '82C49DF2DF809141CB5FB30EAA8E41A3E510AC7F51CF203FAC2B16F20C96C2E4' : true,
+ '82D1AEF2AFC46271D18C5FE50811DF9A5EAB812156C2FE6F531A34FD529E75A9' : true,
+ '837CFD4C8E9033F38B46225EAF78A12DA6636DAA0CCA197FC964B51092C55634' : true,
+ '83BBDAE22AE7CC2EEC0698B2435650633DEE4E0DCF849789C974976D4D641C33' : true,
+ '83DD8D43E88B8D6ABAEA06F3A3A2455C8F6F79059923A08A8D2AF33233F5A63F' : true,
+ '840B5405310320AE110F3410F585B799CE365AC1076CA0CDCD94CA6867A9166A' : true,
+ '84A8C623C4304D57CE03893ACBF4E51FC9975C58658B89127508E5C33BE992A7' : true,
+ '84F98B7850FF7A169D5642E9EF4401DDEBE465DFD5BE957C9EF18CE9988C11AD' : true,
+ '8524BF9691E1C2AB2BA091218096105A335A0315C8282E59B6E8346B11E36608' : true,
+ '8583DD0B4F3B4EF42A66A8D6E369B1E2FCB8B7C64846B242384DF6B8FA0570BD' : true,
+ '85C4AABFC4B38B9B5D0A4B854DC02527DEC6BA1761B28F5698141AE36ECB15D1' : true,
+ '85DFEE3DF0EC8DFD281A3DE35C80A220A42FC9CFA1EA353349D98FBB58DB6E64' : true,
+ '86154D1D0FD89E4E1FCF72511C74A8B2B0DDF4F38E675B649192ED0C9DAF84CE' : true,
+ '8685E22CF1BE901D8E954A0674DB6EC013D9627DDC9FB81D3EEF752BB410DCB5' : true,
+ '87108514AFAE3DC15C9F52574F918D7FAE18350602652906E289802FC543E61E' : true,
+ '8769B55BC6349F2874697988D13507CC28F9EC6630431A7A9D360046DCBB3190' : true,
+ '8769C6220722FE98F6EA21C5456ED2BFDD9112CBAE15847B239AFB2E6A630DBF' : true,
+ '87C002662AAAB5BE7B6A7CF4B1CE9036E3A2A70A0A3CD80F64005C889ECCDDBE' : true,
+ '87D35135D0372CC692C261453242880BE00159B60C2450AC7D7B84DF963FCF8B' : true,
+ '87D61B9AF0E0A2D9F836AC304E2F5A84C543275820BC4BABBE3B75A0D182DAA0' : true,
+ '8858520A8D4E5C88D777C33963CC7F43E796B555E7FC573681B59DCFAFB43EFA' : true,
+ '887A5D0381838CCC20D204BBCFFDD864AB71C20D2BA06842921BD96BB171A796' : true,
+ '88BDA25A602E57FFD8A0837257CE1618DEA23AFB0051874072E85CD98F740F07' : true,
+ '88EBF5BCAB2CF8C43095EC58E1BD0E375518B5C734CDC394BEB34F3A7B0480EC' : true,
+ '8919E46CD5418E4CBC8FEA766240D5918B48BB28BAE25743EB276B996E6E7B73' : true,
+ '89489486E767E3C410896A44B28109680C653391FA763E7A21ED1FEB13540DFE' : true,
+ '8974A885ADD3112CB168E00C10557410A89955EDFA94CCC4EBA3F5A51759D8E5' : true,
+ '899F08AAF5A4105B9B6CD106464D7634D5B27A444CDBC70264B8CFB56D290DEF' : true,
+ '89CBF98E81A0F82966E19BF3BB997A2E0BCC7C90FB83A2D4627FB311B6FD1D58' : true,
+ '89F5AB7CB2C9A8F6123C4D2F3F4FE378BEEE92B2EF506202BFE847DB058631E8' : true,
+ '8BA43B5CC73958FF059423C2AC018F994F6FE3A7E88C4B4E6E89ADEC692FF1E9' : true,
+ '8BB672CAE5B222514864A8E4FB8C89A774200D7773F2A56347C75D5094514C74' : true,
+ '8BE5E1A7C8736600D204B7C20EDDA49E72107EDA9AA5E03F971FB24FA8F8C686' : true,
+ '8C2DDBA5CA9E4CF79937A5A3AFCA79F371B6F235B37308EB53ADF12C319A7EC9' : true,
+ '8C6DDA18A4CB339717E1321FBFDC9A3ACC52F2FEF6FB453EA389A2B43FFFC63C' : true,
+ '8C7CFA7D4BB49D306857772722769DB1FB9CDC09F565F22A8EC082D956E93694' : true,
+ '8C85C2F6E697880B740C96BF35FAA02B4B2F718DDBC4A8ED6ECF9EBD7FBEC1E4' : true,
+ '8CB93E0ED93C6730B58CC0314B8158A7A92184312C53A7CDABF05B369CC7E730' : true,
+ '8D0CF6F0B227BE9394DA0DADABAB81A44900D104A915645ABF030220F3AE187C' : true,
+ '8D0EC1B68E24C1C390A7DCE081085A14CB27FE8B5CE652A60529E04825F289DC' : true,
+ '8D7E00642EF079DCB1B9DE964075E3FD44C63D7DD6493AA3507D87D0E277CD25' : true,
+ '8E6419A3781E9E9C262AFDF8318332504EEA56B39EF770B9882523D132B85AE9' : true,
+ '8F8515B35B665B69D0DB9661EAE9FF0829B71CF4AFEB3BBF988BEE73985F5D3B' : true,
+ '8F9CE539058EA5E0587C8E79E554DBFD1971FDE7C5A96DD1EF7277AFC2EF70D3' : true,
+ '8FDA31393381A23479C8BFCADEA59DA75A1C390693F72CB7B546C641BC698256' : true,
+ '8FDDF56677555109B03ACCF8F39EAF657767096D71F1652125BBF487FC6BAEFC' : true,
+ '903081B318092837E460229248FA67A70B01EC6DF9C9D279188ACED18F1E6BB8' : true,
+ '905AF56BB5517C973A43C5B576B40C5EB69F00E615BEAA8538D294E40BBA836C' : true,
+ '90859FF52A82829F7DC99392C6AAD9F346F54ED3D468426C26233AD5D189FBC7' : true,
+ '90BDE9F4CB3DD673BDB6C641361BD8B076A985903DF004AF7E74DAD95EF82E50' : true,
+ '90D6AE9953E31E3DA34A67533E444BC924E67CC2C610FA468DB31E59B1A35471' : true,
+ '90FF35B27260290E94BE3E2FD6F62F412A3FF4303E38ACF6315E190A1980A095' : true,
+ '916A17B983FBECECABBDBC4ECA80A330919B2EC1F3F4BE4A54832B3874EEE5AF' : true,
+ '91CD0D276921BD32F4C8616BF2676078C24E39AE1B30943C5263AE0377F41F21' : true,
+ '91CE410FCEA8EC201D33AB8E7419BC60E8EC83509B51D10BBAD728E2B6EAFB1C' : true,
+ '91EE28B14AB2C7571BE6CDE2D75FD4C05C960FB033DA819EDD463D5D3C494591' : true,
+ '92624A843DE27E186FB6C18ADEE88F30E00A984E44BAB93108BFF565AFFD2A15' : true,
+ '927546232861B1DE9D105031E4A2502A170A06D65340705EE3D7ADDD34F9FE0A' : true,
+ '930971709C7B3F9D52B30CD42E61D03BB430A1D8641F685F5A9F730760FC78A5' : true,
+ '9343EA576B49D46887962DA39BEBE09276ED97EBDF47A82AA8CA4F28A04AC789' : true,
+ '936EC5E6437D79832DE6B015C38725C84A4638D73770965D82F3CBA4EC35C0BA' : true,
+ '9394C03EA88D9DCD628AACC140CF1FAAEC364252F318F577380BF2623009DFFF' : true,
+ '93AFEA0BFBF153CA77357087301C0F31B095EF2D5A53F7E2D02F9B13DD6E7325' : true,
+ '93D45B29473CACF1E89444ADB8FCB8C3626C278E2339E897C88C2A51119C1C25' : true,
+ '93DCEAA3D67BD8992097C446EECE4A6A02DCF89EAB0008EFAE7D0C9BE26B7C00' : true,
+ '94C5E69A5644B4BBFF863312752633025D60B905984BC297D103F7B58F8F1CAA' : true,
+ '94CE12FB5F69E4273C8F813ED37ECB954AD667BC81C4E37DD27A40C291DDB12E' : true,
+ '951E14CC4823E3E83E2DD0CE75826B7BDBCD45CB16FCB70A1CFBE6C6BE1157D0' : true,
+ '95EEDB5E6C8B8552E29D7FB0C607EC68AB3D3F88A3FF97F4C70D7BA9D69C8521' : true,
+ '9658D54C28C27DD6E9B79098D7D86C1EA32215492E8AE9DB225E3410EEBC39CE' : true,
+ '96735DA929F88A1A3292D120F963FF675FD13315DECAE2555139CCF71822F408' : true,
+ '96B9BCDC21A4E9187BC7BB7B5BB052A1953140044A59ECFB2F1DB1C0FC648FE6' : true,
+ '96BC0612871BA526E0F8AB96612077A50930AD430147A0BFD37E1BE21E0C64DD' : true,
+ '96DC92A327E33DF81946BB760B8C22FD7F74A2C9592987BA110F7A9D211F47B8' : true,
+ '974149DB587C53796C2752AE8D14C7F3E7C9A1002EECE93420AEDF52B1F48558' : true,
+ '9787EFF64AF68F280E2778414020672F24C44010549900A5A0487F11CADF9A41' : true,
+ '97907F0BB6A5CFB411D9975E742C8DD55AED77AA373C56DD74ABE6B7C9892A60' : true,
+ '97B09B0E6CD2378FA7CED47F365C77266C94B867F8F87B01D8B667D0DB2F5DC8' : true,
+ '98323FED7420A24CE2E1D0A4445B73918FA0C867BF19E2FEA18449B429D935CD' : true,
+ '984E447F3A932B79E9373A9EA9786E0637ADEE21B6EAA6B8127B05F26D7181FF' : true,
+ '98AD6C8A91B962AFCC223C26F0026802B688AE55C204BA0A4ED5BFA5619D979C' : true,
+ '98D9DCCD4C1EF004D7F000B29AC540E935ADC074DAB919F8ABBAC7507FC35EBF' : true,
+ '990477B5471E1BFF7187E419CFAFEDE674FAF3E6325182F9F8C686A2BAB085B5' : true,
+ '99E437DA5156E02DE52D0D95AFDE0FDBAF8F626F4D3BAD2FFFE7F4C75D76BD60' : true,
+ '9AE40265F51732A5A72BFE9B4C3CAA7106EE84D320F7C675C443C91550E5F701' : true,
+ '9B340670FFFA8B98B78247E2A470627E05F1AE05ADA505FDD049350B5A8521EC' : true,
+ '9B573154350FBEDA3CAC21F90DC0E59C9EB0DED7F069650E099F62B0871F3615' : true,
+ '9B80DD5C98B0F0A7AE343DBB896DBCE45DA52EB4E31BE057287A2A738D9CE3D6' : true,
+ '9B98284571E5FBB2A2BE676AE24830A6F0048748FA38D1F11CBCB252505D2E62' : true,
+ '9B9C56A1228EFF3D6520261D3CE06F38597A96199CEE7BFEE71D95F7EA6EB54D' : true,
+ '9BD01B7914B81371F2FBF23E7A0876608CAC69218A0DDB78C2AE45909744E5BE' : true,
+ '9BE0DD4F76D60653F0C3DF854026C8A73C5403B593504B80187730E6562FC67B' : true,
+ '9BF6A4CE27AD782886988DB3FC3AF54CC857946C7C5E32A9A6AB13A9F7504DB1' : true,
+ '9C0F47FE70B9E636409CD37362B052B40B3CF765DFE80E71D999E7EB1AE1D4C2' : true,
+ '9C102F918224790C649D916B43E1CC9EFC4C16ACD141E22E85F199C1C6BE7DA2' : true,
+ '9C109FBEC4A2FC259F1C89666AFC54EC974EF4CC52C858B3C612689CC8A943FF' : true,
+ '9C1C2898E71561BB2B87D8859A5066940BA97950DE95E12ED293822111EC3D35' : true,
+ '9C7F9776163746C45FBC96E2985B57C6AF769E83428F910C3EEF0918BC5CE593' : true,
+ '9CF455322FC12AA2FFE88CCC43388419F61C41ED1AEC560E11D627A009DA62EC' : true,
+ '9D484D53782C2FC0798843979D991B84A180C1A833D717AE002E75F90E954EFB' : true,
+ '9D93BBA3F1A3E4BE5D1146849473DC18A987B0CF48566E506564D4386B29C50F' : true,
+ '9DF287B6058B72D28B1B7E4A46CEC187EC1FF32561A6B681E2F6B6E5A4937F88' : true,
+ '9E2F5DDC11A878B6A7D27F9FECBF10861EF27BACAA208D8EC7ADBE2682FADE95' : true,
+ '9E531CB7619C8C0D5C97E7ED9B20C3A269ACE189AFC5D80DF6D2034BFFD0E804' : true,
+ '9E6937E5BD26C280FA683490204D1347BD8662325524F0BE4B25FC17381923E8' : true,
+ '9E837E2CEACD82AEE4D2CCFDFCCDD0331D305E5B2D123B317E2F3C0376BAC850' : true,
+ '9EA5F3B71232ACCBFFFAD71FCCD08B459DEE53DE93399DCE0A212D0034E9FE6F' : true,
+ '9ED22741CDF43DC2AA238D354F0BD95C28F1B5557ECE9489AABA4CC37CBFC9AF' : true,
+ '9EF5444454DA21B0B7D6110C9B040BDD005EA0BEA27788D00BB3F1C48D9D0F36' : true,
+ '9F7385E656F0E8237CE9A5E9C96A1B3CA17920EE75C112ABE9219C18F77E9E97' : true,
+ '9F9E4DC55925D2944C0ADE2959EED5F6E55A14BC2F6109F8864A8AAD2E4A7997' : true,
+ '9FC08812780624B21DB7596E278F22F0023D27DE99277E37CF07BBBD4B351590' : true,
+ '9FC5DF8E8AECAEAA4939A5BD94A078371135107A7AAA15ED5728C9887FF4DD8B' : true,
+ 'A0142CE676C4FA2524F53E7626D21042BFD8A903AC54F8AB2FB977ABB760D6D5' : true,
+ 'A029D3A07D53CF4D88E75038E45EA719A7A04F1084FA5C327E5AE66B229E7761' : true,
+ 'A03D7CE2FA040738CCFEF1F20872DDC1E321745B2C34095822A51B3BDC07D9F5' : true,
+ 'A03DFE739C80E109658E0B3EB41D9EE1F03EEE48162C4EB97EBC3548760402AF' : true,
+ 'A0AF36C48B0FB8F827459F8AFE6FB82AD1CF7D5D193057AA7BE7DE3EF5E4F69A' : true,
+ 'A0E9635A0A993A3C15F0D7362D4D7C1EC21A50B04AFDEC18685B4A21F69E42B3' : true,
+ 'A1504C131B0FE702B64AA259B901DA2D9B2AE9D85AADE02F1528C1147F98E535' : true,
+ 'A1712F04B99848A73D978552028EB84039AB331DCFCE329E8A7A59F678139F28' : true,
+ 'A1B71E94B84076BBF29645578CA796F299D5FC07CA4C2049D41760F9B53035F2' : true,
+ 'A2152E5BF42DA70683BFF5526B3F9B90045F74B82A034EDDDFD2F8674BD20D7F' : true,
+ 'A21C3F2CE357822C64D1F9C26446235137559939DBE7C7C3E5CDA218376EC1EB' : true,
+ 'A277B893194AE7687EBBCFA344178B3578AA6228D2B430BBE2FC8D5EAEE43135' : true,
+ 'A2E6C7ED88E5F8103D95E02F792372AB66EEDA5AF35CE4884316493325F971E9' : true,
+ 'A3554186EC7CFF6B11D03F042B490700287F9CCE71A4F581B0C5C13C2A0CE643' : true,
+ 'A37B9444FE3BB0FB2EC43F2677926EF458D0ED4F0688FEA6443A5F243F10C2AB' : true,
+ 'A44473407C78C1A951194CB7DBBFBD5010A60A0C82565E02AE1E372975C8D8E4' : true,
+ 'A450EA9215B45056104180FAA52CD6635B94625D0FA383A2000CD8FB0B203E28' : true,
+ 'A45C0F1FB81BDEAED2EF4302BD5AF171F31496B6A8D502B488BC8E3E22D5E992' : true,
+ 'A45C8546DF176BCD32BD7D15FFE732DA2B73EDB38D387108ADABBE4B20066275' : true,
+ 'A4C6A2F0F5175D6C5C1D87E61ECCECB368E6B5374F056F222FEDBD0857B83F2A' : true,
+ 'A4D07A0F8A6A11935F63B66461D06DAFE3D8AAC0E0001B5E842A2232F327137F' : true,
+ 'A5278398DC472DC37141AA3EFCF4953AD7B14AC25D3730D2E99020353CDEEA25' : true,
+ 'A558DE705EC13AE6FF7DF6E6B1BFDB54A7CB7FFAC1499954FB109E6B884CFC03' : true,
+ 'A59F7C5EA7F5C48B71DC6BB678541E4982BBA6FE8E181F5C91DBB9F9FBF49A66' : true,
+ 'A5B9EDB84D5E06BB960BD23A73B0AFC8A0F35C95B782BB54004EEF2430CD3351' : true,
+ 'A6584C2334B3B29B3F7DC858D65AC229F679D8134C75DBD5A6CC1A4B897ABB2D' : true,
+ 'A68F08DECE7FAEC73E7F00AFE4C758B2742EA6BCB9FFC0F3D09C3D3E79E41EBF' : true,
+ 'A6B6702113E87CFB26DA2066CE2151698C68EC71EA906F632FD65DD35B3E0094' : true,
+ 'A6D113CA991875E854CB226297662EE3B083F5D4E15E03D1FBD96AF0FA6691DB' : true,
+ 'A6D1CFE508A9E64AC65FDE0FB8EDB8A808D3083125E2BFA975B4A1F0373FE8B9' : true,
+ 'A718CF6FB0B4672FDB9BA1CDB812CDB98423DD8ACC8991780BE5E0FAEB863FBC' : true,
+ 'A74DA51FDF285B66F86065496D236FADC4D44051DA6400B743DAB15A81FF3B13' : true,
+ 'A7636BE0A08F56D7F05A8D69AF0B7199FA7C05AAC123DCE71AB57C538A4D910A' : true,
+ 'A806A89477E76D5B381113AFAF7D082B543E172A38A1C4B5E23645A81A411E8A' : true,
+ 'A84DC1DB143EEE938A45743268683770BA0FB2EE69A4EB4B131841555CF1E124' : true,
+ 'A8E146E7A32922CB9F5908D8FC85B2928D4BBAF44E8917F370E57C60EC479EBF' : true,
+ 'A9266E0A665A00C7C4360A7CE3FE0B5ADBD6E7E20A32677E43BA30FCFE112E30' : true,
+ 'A93B07A90F55AB3B6BDD56958FD69A808C8DEFA838DB35D323F080A4AB1E4B60' : true,
+ 'A982473B3AABC66BDE83F206E260A07267088862EF71389082A98858BB12C3EB' : true,
+ 'A99953DEB7EA51793C1A353F91A070E4702D42AECC9808E4F14805A755D1866C' : true,
+ 'A9C8BD62DD64EBE49F3DC28459A7756B6D7D6168A9195E8C52D41D2AB9D9CE05' : true,
+ 'A9DAFB7E89AA7141CD52F08D5740F09F388419744351D889C96D2B4C3153A424' : true,
+ 'AA1716CB8EAE12CAD75B01F3A4EC5516140813349BF4041369089A6063625EDB' : true,
+ 'AA55A82D7DDFFAE695312FA5ADFE893D1430057D1D8ECCCD2A9E985CEBAE3989' : true,
+ 'AA9F7FEBC74FE835504EE24501DB2D00409FC761AACAFA92DC8A696388AE843D' : true,
+ 'AAA011E89B2581C1863FB1DA1E41A8FB8EF14ED0817976F16909C68E27F4E70B' : true,
+ 'AAB01A25BB1EE114084DBA1E0B2B8E5C84936196D40CAAA26A16E58FC50E2B93' : true,
+ 'AAD7DA6E17F164E00B0B63A6338330219F40EE683F8E0CA5F6B709F2E13FB3E5' : true,
+ 'AADA8A48FB9966CCB61E4B8C97DB2DE50F0AF34422D74D1A770501AD00C40119' : true,
+ 'AB34CB23DF8A006DD182B01EBBD38DC13785C4DDD433564B5CA7579DEBF3B1AC' : true,
+ 'AB47045D4B45B0821E851EEEF7EA9D6571F9759DAE4F3DB1EF92597BFD2B4FF9' : true,
+ 'ABB5673AF0583FF328D23B1D4F35B33EF6B68DDCDD482BB3BC1DCB43D2A0367D' : true,
+ 'ABB5D30080E3CFE6F83F249F3F8A22C731F318DDF1BAC4D4895B2B7F7A6287E4' : true,
+ 'ABE9809D21AFE6E0FB253DCD55E10C31DBAB32A973EC52DFDA1C15068F89D333' : true,
+ 'AC3D6D1C64348ED7E068376BFDDA866A015317B4AA8A7FC0C16F7E7ED4DA9682' : true,
+ 'ACBD5C965EBDEE4D8D3EDEE2A5FC407A6A3A7AD5E6EC120EF1854C18118953B2' : true,
+ 'AD046A8C4DE2A89F32973F0566452CFD38CE0586998717364C528F5995B5E2F2' : true,
+ 'AD05645C0957254FE67FC48F7BFAFC24D30BEBE233B82D87DAFF3B44EF7314B4' : true,
+ 'AD3FC05D383E384659DA700279CE3C48DAB804AC74DE2B3DD3687F6ED355F99B' : true,
+ 'AD40C15657CEFAB57F6A71035796462F0184B0AAA489E601087DE329F35CD757' : true,
+ 'AD679FC990B740191DF7F88D51947A1F23D79F862160E3C94A22BB1169A7567D' : true,
+ 'AE03E5FDACD94805484DE44DB4BABB96D1D2EED4F0B9CB528CB30210C8005C6A' : true,
+ 'AE176A4F7AAFCDBBDC0B7A69ED5D5AE0A8FD0A5BD37BE887ED0F098239D11CE6' : true,
+ 'AE7960061D5D4739E2A6C0BEC6BE8E98ECE3E97994940C9BF5AB2E1C2C0D9702' : true,
+ 'AE7BAFD9FB7AB3D87D0D58774420B314E46538D2894DC58DF5F5614DFE7F0435' : true,
+ 'AEF7E370874D2001D989B258853C1974A5E45676D3D7595F74662C0B650BFE8D' : true,
+ 'AFEC41B1302FD09F03015FB573960516918EFAE30F68D97D027D45A51C4115B7' : true,
+ 'B06CD6AF9B4156B4379FF3C6C1F8CA182A923527D0DD92905394DB3446A11D5C' : true,
+ 'B09F332B8A115069BAC41865E1F1228DFD8ADCF3A66C1F2EC9DFF41173EE7A85' : true,
+ 'B0FD996D85E74BF51328181823707C4FE5E96C0028C2B3FAC104A96237B63EC6' : true,
+ 'B0FF4F8A6FD3F8FBB19A188351CD4925C951DC2D64633B9E0446F026670A47D1' : true,
+ 'B15FFE5C987B12D7299D96F1DBC1C7E85B0528D1AFAF9C6FE808361F7B0D1D06' : true,
+ 'B183D8E672345AABE24C849B4A13D0BD99C296AAB273ABE88C00CAA229A27154' : true,
+ 'B1991ED1894F821B66AEF2E26E0834CC796FFB43971A79588A44CCBF7E8B3076' : true,
+ 'B1D9B3EE2512A48A8E703E2D2263EEB4B0A3D24963F5165DB3719CD4750D2986' : true,
+ 'B20BEB685F3FB617FC974C4C624ED894EB2F7FA61DE28104C7B9EDA1F52F46FE' : true,
+ 'B295FDC9D7462488EBD4E5FA8E5B062FE5E2D0432C6A02B99F4CAD1F9BE6D0BB' : true,
+ 'B319CB30FD80959806C6836129AF6E1A8A32B8B8D39AF65674532BBCAFA2CF8C' : true,
+ 'B31C07387E56AA457F17CA3D3A4C485683253CF387E6DCE37469B6A8E51CBF29' : true,
+ 'B3251BB9A1B4F219400E69789FB08CA2BBA396C6D2FD3C4B69F4B7E1C0DDB615' : true,
+ 'B3381C627EFBEF5DF3BCC9DB71A9B6E4C0A4F3114F7E7408A356FB33FBA5D20B' : true,
+ 'B36D72C8B1F436DA49520421FC0A2869A9952DA405DA5E29EC3A1919453DD6F5' : true,
+ 'B38D0B1FCAFA3F435FECB2B3A25804FB004BF11DE5CD691C1461A4D76792A4B0' : true,
+ 'B4130785116E5A84BF7B191696B213BA8877228388B18C2DA38DCB9EE14AC8CA' : true,
+ 'B440A043514252DA267A339059C789BB14D1339B7964B0945262D978D9AD021E' : true,
+ 'B5008FE6CBE7E0EC5B158E8C9CE487FB6E5349F47007F3CDD2B1AAA69098FA40' : true,
+ 'B51BFFBF094EBB26247D54321DE8F7CC10B24BE9EA6D9383BF908E765D5D9594' : true,
+ 'B5453C09F38363BC702FCACE4B64A74538B1BE40617640C00150CA9129FCDF52' : true,
+ 'B55BBD123C4262662BC144E0CF4BC9B47059C4BD0A136C075BB9B3E82830799D' : true,
+ 'B56769F28FE8395FCD50E7552BFBC2AA549F30E1092A54921BE76B07A6A800F5' : true,
+ 'B5A9BD7AB128FDCB0DE3C7EAE193904867BAC57822BE195F3060369520403D6A' : true,
+ 'B5C58EAB37201F8A7F3C520FECBB3C016A30960C5931DD7C43ECA217A1E31774' : true,
+ 'B5D38F895E2681F656FEE774C8677D29749C3E5ADD3DAF7A2A91043BF5A4DDA5' : true,
+ 'B5F004A0997E3448A1ABE7DCE45D8BD263AC631D14B05A04CA195E98D665B679' : true,
+ 'B61D7AEFD0BDF0DF2C8C8E68D4E3D92EF45CF9F79AFD9EDC4729D71375916019' : true,
+ 'B633827A97472541F7DFF77C347301FB40604D6076D08FF4244C070FCFC9B731' : true,
+ 'B663B6C8C60A5969BEE4F6844813AAB8945EE2CE2253CFBA67500B991CD8A07F' : true,
+ 'B6CEE930054D71DEE1D167A566B9881B8971F7EB4BC4A34FCFD9DDB3DE311B9C' : true,
+ 'B6FAC01424B5C332C72B6B218DC93AEBE54318DDBFC5BD1277E262FA7831E5B1' : true,
+ 'B70CE73DC10ECA5F97059AFEA5A65F1B1CD45F3137BADD7F3A12DD1D6A468D82' : true,
+ 'B7135730040D8EC88C4228AF1C9482AE97526F30CEED5AA117387D20A61D7159' : true,
+ 'B72D29A0BC3BE16C085CE7AD38D1B7A945DC96F4A6F20F126138FC5202A072C4' : true,
+ 'B745A72DD07E5FED73CFA723D6BC2E98FA62B6E03ED378804EBEF7DCD83725C0' : true,
+ 'B76BD62A287E68C2CC8F8CA7FD5196938DF4C39E6F46DD81A3A37D22B761C158' : true,
+ 'B7E6A641053C86E17A4A328D98700AF4BA3BDD35E5208359AF120C2690F51E3E' : true,
+ 'B7EC03174DAD602E897345B072749AA86CAF05151062989E183C3039DE25569D' : true,
+ 'B839688B9303FEF8860B4FB2EDF19FF2A0BF5306DAC007E8CE074CBA13B39A03' : true,
+ 'B86F85494700264E918D8706B711B9E8C3C12AA776E0B63AF35B73CE56B15BBA' : true,
+ 'B8845702F28C3AF9B35D8B5F1DFFFA014CE411CF592B18395F700CD8B937F3B9' : true,
+ 'B8F0936622984493F4B74D087ACA8438AABAB1111DA258806EA86C23C6F6617E' : true,
+ 'B9772693C35DE8A4B6EDC9457AFC3B4B52ECAFDBF612CEF1A27AE7F7FAB8F79C' : true,
+ 'B9D8E2EC3C47B6130DB45DE0741CDB790E36E4617986AAD5A2BA232B8BD8A85D' : true,
+ 'BA4052C530EB5FDDBBFD98FA9EB99660BC084678009D5AFB2F9996BCA40C354B' : true,
+ 'BAC88F443D9F2F03CC7ABFB27373EF9600AC918E084967BB77E80650B3724266' : true,
+ 'BADED8CA137A9AFC4A0FE344F663C743D1A549D0A8DE663426B90E788868024C' : true,
+ 'BB7E9348A57593802F083CAA99351386DBDF348C83AB35E554BB7BA44FE1FA55' : true,
+ 'BB7F20108F934620F741F678F3D25F7DB4A50A2CD216FBAA1F4773767F645AB9' : true,
+ 'BBAA50F752648522389B89EDD345BF8C41FE10D4593A8A1DF467B2FFA7BF870B' : true,
+ 'BBB99D57C9ECE54B1634DB4BD6211C5167A5EB4DC310340BDE14B1BBCE275937' : true,
+ 'BBEF78F8C05ED5A5C2142C3598696B0674FF3DADFC8156896025A13EC892ECC2' : true,
+ 'BC0B758091A4613FE070BECD6CDC0BF1FE89727C3482DB4A2353CEC027E3AB11' : true,
+ 'BC17CA376A3CA716F41BFA9D3A2CED2B1941431D70543BD600B7596F4EA2E440' : true,
+ 'BC1FE50662610B7D575931031B1EE60479D9D9E3D94048DE6FBD44C88B9FDAF1' : true,
+ 'BC447B8A11DA8F1DE19285AAFB97AF1A26A35157AB8FE1E4AF80AA70B11AB65B' : true,
+ 'BC568DC8C01D8D7595FFCA2A7E000780F15EC24CD38AAF25EDDCE7BCD41E4FAE' : true,
+ 'BC622EDE87E66E364218B38609D792F6906F7CF95EE5EDD1A76BE0C48B8533F3' : true,
+ 'BCE02BE648B8A1EE092574F3D453388649082A1B72E7AFE7ADBA310EFBD38DE6' : true,
+ 'BCE27288DAB9DD76CB73B5754152983F14B11DD0466B1D4F6F55B61E27A3353D' : true,
+ 'BCEAEC2D8B8C18B58BD320D77850EC38285F419ACA8A9E939DAE7DFDF26696D0' : true,
+ 'BDE511A7E1B38D779BD9E758B2EE8F7F2DD5A242D37CA573394808CB01B78FA1' : true,
+ 'BEDF91AB2008A01DA4111518C8065D4BFD9ED614A29CF89A16E94CBCD5F5D17F' : true,
+ 'BF38E5D5BE0CC67C1CFAC96B40DFD91DE065F2DAAE427AA54893FFC5ADC73707' : true,
+ 'BF9B71E2C87C03CF421733610A1BDAB430C041EB20DB75ADBD9ECB3D342072CA' : true,
+ 'BFA0CD61FEFB0FE90D0F9025E67C62A735DC730F13B5D5FBED9B54A3DB882F91' : true,
+ 'BFA5B4A3751715409895D27F7C9F057F2C31EE560DB075008A3BAA21DE838FF3' : true,
+ 'BFE49B659622D1011F4BB655CDA77638665D068FBCAF11C73829D2DE16E43BE4' : true,
+ 'BFEC93327E0A7A92EB67CB3E00D29C97411077E06CFD010BB84A5C0836CD2F1B' : true,
+ 'C0AF523C6E9B52801FCA62602022547B25D8A107CC7008C67C438E1A093FA69B' : true,
+ 'C0DA5CBD6F39A5B707B0E7DD33004811FD6F925DE713C817F3E2719393163E9F' : true,
+ 'C1AF26C31745338DD2E13C1BA98A2E643AAA3271CF1FD5B878E93B1DDA2DB868' : true,
+ 'C1AFF08543BBDC3D2D796884D099D8A7B8D40FBA1F37AA31CEC16EBE2AFF0D0A' : true,
+ 'C27D64BA2F133417986FC42073BCD7DB4668A2FA7D2D217CDE215F25D2BD5E23' : true,
+ 'C284387A9875E45662ACE976D665D6A33C36F3EF2B053AF26C0918DEECBE7CB6' : true,
+ 'C2C65F50563C7E96AFE6602B9A0B68DE74F3C7AE5C00ECDB39B98960BDFE5B91' : true,
+ 'C2CE30C7F0723F2D2B25A18FA209B1CBC66662624FA8CD1EBA96BF051D969625' : true,
+ 'C2E60ADC4803F0F11F83C644D8DAF80DAD4B9D6A67FC108B3C2CE6F2576EB69C' : true,
+ 'C32E558AC4FEACD1690C227683DFC38CD26FEF103953FCEC9CBE0FAB08C176DF' : true,
+ 'C391E32BB11DD8F6F13BF71E0B9CE225364A50006E3F91147EDE39D2AA6E70E0' : true,
+ 'C3C07C187D95222D855EBFDFF827193F71C471BAA3A1B51242BFE963FD4A63F1' : true,
+ 'C3DEDA7A5C280862654DD266D482AF59CD7CE5C09020F8F32EDA0D0FE2345B02' : true,
+ 'C46DC6888470BF64D41C297E1FA082ABB128D4D0EC44DAB62E05E4FF8496B18B' : true,
+ 'C4D51A111115A7D06422BBB16B67ECFC73D636DB08551B27596FEB532D8CC2BA' : true,
+ 'C4F8364FC0A36A73AA0BDA4074FF1490B3AE07A7BEA479385BF28078288F9C3E' : true,
+ 'C520C3FFB5C5107BEF2E8DC44C74803713E13D9BCC99A57C6838BE15ADAAC04A' : true,
+ 'C55B18B5DF187AE68174C086FA4E692C6443B01FF4A19DCA743EC1F6E1B7E332' : true,
+ 'C58F0FF2DF810FAC8EA095F349A2E6D7E0D9C09D6FBE7D45895408530E1C75F4' : true,
+ 'C5B2A636DE1FD6629B4BA41FD1693F261F50577130A05366D298F9CD282E4BA7' : true,
+ 'C5E4575B4442687C80E6F9F290846CE80217AEE8892B9977C5F455BEBE285EDA' : true,
+ 'C610F374CDA9036FCB01F526005ED8561D16A27790491AFB26D56A1BF0716007' : true,
+ 'C6479E02F20A3596203FF184483F1F6A29EF9F95DAD258EF2A84BC6125B299DC' : true,
+ 'C66BA6D7D5EE44E268D2DFE0A00284BA59F2FD86AE8F738E84718A1B4C5927D3' : true,
+ 'C6983038573EE575734E531266D91772390BDF63A276B49E9360C81F8C813EA6' : true,
+ 'C69E1305EEEB633DAB5055D952D0A8FFAF35FE57D0E1896A7BB24EE37F29959B' : true,
+ 'C6A38936450B0D72D5C38EC5BE6FA683D25CBFE604C7415BC5E55E2DEB06A946' : true,
+ 'C71294A0124420512711C918C36F77192D2B45CDF8C99824B4BC862D0B31C3B0' : true,
+ 'C7E74023ADA70B7F3BE9085E1554B8EC7AA20B0E0A38A08B2A05DD377F7177D9' : true,
+ 'C821C2140114FA7DDE92FA497EED3E4B9131919A9EF3D6750013C6CE7FEE0B72' : true,
+ 'C86D8AEC465B23370C4D5086141E9C98935D91524E3CF68BBE62C0AB231EEEBD' : true,
+ 'C8726499B7FA3B32022A21230BC27CC59901DF584C69F33232EE76FD7A554F3D' : true,
+ 'C88BF2F611A7EE5307733DC2950EFF56A96BC832961FF595196EB88EFDDF4932' : true,
+ 'C8B4AB5E690CF9E14D079125CBD13232EACD4FA3F15276D2D7BC48FB84BDC0C3' : true,
+ 'C8CC1B97C420851221D3997B0C0E3A6B87B4D9F86D348917FF90BF710DE79351' : true,
+ 'C950A2AC5B35DEC3F384099AD2E3BA7FDBE79E93362A132380CB5ADD1EC2E94D' : true,
+ 'C9F2002F6542DA1BC5833AF9A11F6F5F144B76539CDB9E1738C7DB37097523D9' : true,
+ 'CA157632863D3E7B499F141741724FA84DBA48AEB51B04A53A9D3DFEA7F70BF1' : true,
+ 'CA362B0DE34C54F91953DDCDE461D54BF30DB252EC07AB6B4C449E45750BACED' : true,
+ 'CA46DA728E76E97AD214DBB6AC9CB1EA2DC87202C88C35E87CE574FC1F2E0438' : true,
+ 'CA846077B68DCA99AE30BAC33929143E856784B64E70098CBC7FF5BBD85C824B' : true,
+ 'CB42AB965E2C1CC7F20BE15F308C2173AE531C532DBBF8A36B292B1E1A891A07' : true,
+ 'CB6C703326037CB5C4456097438DF15387452C0CACD89D9DDAB1475A2111C197' : true,
+ 'CB7FF00DBEDF16D72C8A10151A30595AEEEB9A2317D3F44269966624417141F4' : true,
+ 'CBC3C62B44E2C35250AB62FB2C3993C55F251559259727D5F76A63002148F17A' : true,
+ 'CC1A62E8FD6FCF9A3BE4BAAA64AE2FC0BDEA2C2F34BAEF8F9123D991262DB210' : true,
+ 'CC815184FE74CDD53947DCC9733B1D5E9B9E8F31C8C96154355ABAF389BF7D63' : true,
+ 'CCF6435DDA033106286D7A69A4C8DD727B59C4E334826CDBCF6F66C801580FF4' : true,
+ 'CD35C7ABA0839C0D865DEA4C1DB624F709E5EA041A68DB55842E2C189F38BAC1' : true,
+ 'CD7C028069F371EBE93537094CB57A51CA0CA421B9A7F8C1422D9C454F864FD3' : true,
+ 'CDA01229ED05A3825448BF81C4479F02828C6E02DC3F303ADC153BC0600D1FE3' : true,
+ 'CDE7AA628678D4BCAEF4240A9D09B5BC7BC1A1757010006931949C83DA299B9E' : true,
+ 'CE01F10B612255CCF31E03F308F45E0A091C0FC41A13280F575BAA7F4F7B4A58' : true,
+ 'CE318D567E77FA3E2B87268B09B1FE99484916CDBC7A56B99900CE7BB7B4F967' : true,
+ 'CE34361030AA71334FC8EAC253C91EDDDAD3E2AF0974931325384B9A445CD116' : true,
+ 'CEA9DC1557689CC8AFBC740C095ABE8AA617C19AB92B761EA71F19AB2B3FBA4A' : true,
+ 'CF19B1004488D5D9C882E2C4D0A47789618E0BCD6475F6D9C6B5591C2BF333C9' : true,
+ 'CF3457D98980F7909742C974AE4EEABF2007967D9870705867C18A5B47CEB2B4' : true,
+ 'D010B9708329342E43370125857DBFD443ABC95CF5778898A7343E5F1C61F4E9' : true,
+ 'D0927B6D60E3441E11D75A8FD593A38665AA7D211F691BDA3D0E815EBE303C25' : true,
+ 'D0ADA8B3F0D09BD13AE5877B5E448C18376D129F92DCF2D4F1BB182725A62D3D' : true,
+ 'D0E5727B39200CF1054391FD251191C38F6754C103612F442673BC53F1C1634D' : true,
+ 'D18241A820196F4910694FBB37556273E54236F41FD53B3AF75B6C6430D93B15' : true,
+ 'D1B116326075EB6F65C4F8F8E6742B639DB23B56CD8420F42F8219CE615303C7' : true,
+ 'D1C4E4D1F014FB8F889F45AFA39485BE742F64268C662BB28494855E393ADE96' : true,
+ 'D1C684802932EB8EBBFA0DBD55EFA5345AB3A928653CC222D548CD29D91EEBFE' : true,
+ 'D249C8E95880A20CAEEFADA9A9B8E80386234DBCA6D990E78CE574B430C0E6A2' : true,
+ 'D2D9C57B19EABF7A90BCB421283733EABE5ECC6311B1D05089D4F4251D157E3D' : true,
+ 'D3525FAE9E537DD0A56F0311A27A603C422DB0376928C707A12A1E3785F2BEE7' : true,
+ 'D387A162888C2556F1D3B9A73201A8608A57085E1115214BD2588F315B89776A' : true,
+ 'D41844AFC9E00E17DC87F0ED1AE4A0559C418770A4FD7033E3D9A9997C5E204E' : true,
+ 'D44D1A7D80BD2F9B4A62E11BFEBBB74A5780B0366CB6038CEC9FBC8C8E19439A' : true,
+ 'D44DF644880E56596405F1364D8C3E5301F05ACBF82FD66B671D895288C75360' : true,
+ 'D53C334638CE54CB75DAA15D1AAAAD70081C9A52A2393DFC79E9C3A92D54F4D6' : true,
+ 'D5D9E3A7DAB437D5F8967A307F6BEDD3B2AEFCF59B229BA649C4E549F01668B5' : true,
+ 'D5E62D9B8F9EB17D8BA84646BC72AE6271E24D0C7787D302965A92ABAEDEE2FB' : true,
+ 'D6061064FEC9DF923123EDB3050700BE1532B68D9FC12FAECABB9FA82CE2B887' : true,
+ 'D6200C1744EDDC3BA40857A1089A20F7E86EC3B29FF413CA2BE49C060A79D19C' : true,
+ 'D63DF52A3A887D35ED58C64463BF73252738FDDFD73E0F8B378E318AD3057D36' : true,
+ 'D646154250C7883E951B03FBBE9EF7D3D00E74D60281FC82876A913A23AACB1B' : true,
+ 'D6ADFC439E8E9FAD7C281DF1117E0030BAE78D15E481B7886F54E72DB7DD352A' : true,
+ 'D7266CBBD307F97B7284312CD4C2A5BADA7D4EB123237EFA43E55D8D2F5B16A6' : true,
+ 'D737A5AE5F875A566A4ED4CB025D07D076998270F0D25292661B4CD581B0805C' : true,
+ 'D7632272521683A38E88A18C2CC6AED79B2C5E854483BDB6EE83D82BF41B96CA' : true,
+ 'D77C2904CEF8726B748EE36E43BE65BDBD12FC48E4A4ECA4885537745B0BFD15' : true,
+ 'D77D31A02283F81A4E64F7512C59BD71FF603FED5EC57F24F0A240F04B846999' : true,
+ 'D782121A27D3EFEBF791EFE34D5A81385358DA939F5DEB17530252BFBC8E2F02' : true,
+ 'D78220C9BDCD563F71BD8139B40A495879DAE9FB1968AE3225BD0D04DAF294BF' : true,
+ 'D796DA6F4413295EF05E79C798E92CF8A6AE172A091C862D7176384D520BA2FA' : true,
+ 'D7D1D7F326D3DE85FC1DFA7F45F9D5A3C64473B37143EB09DA66CE56F6258FCE' : true,
+ 'D82602A79F22AF46AD32D0AD123D30464371FFCB7A8AFB8C51A74841463A20FF' : true,
+ 'D86562629BA86C435C0965C4AC302160729F27804FEBA36E211F96CDEFB5DF8E' : true,
+ 'D86996C0C019AAD9DF5531836BC48F54427021AB8E24BA1AD073895574A143FA' : true,
+ 'D8AA8D8A7A48ACCB4C1B7E6C2228B7BFBC297EAFAB1315643744E3EE4DFA7E6C' : true,
+ 'D9065B6D9F7F27507D51170FB465FA6250DF528EC38BB46DAD0311C1DF63ACA1' : true,
+ 'D9259A35701E881FD41A9939C4AB82EDAA83A18D1ABCBBBF8329FC6850A0C6DD' : true,
+ 'D94290750677E2B5ECE7C2DC41AD4618C6995F173EC44DF80B23CC0E333EA654' : true,
+ 'D9FDB29EF83808BC82A97839FB2F22C2D20DAB2E6B67BF5862C8922BB1FA9068' : true,
+ 'DA5D20F1A6CF6CEC3AA7028A6E17D8F2E1A60069E497758B0CC938C08F4E76BC' : true,
+ 'DAA384D0D2A94A18A14E3DDF7A963E59BE41C06B978F3DC8862E1EE6C8E76DD0' : true,
+ 'DACA572539398A22DF7049B23BA3E59DAD6F34A44ED7D5E275457D9F79B880A8' : true,
+ 'DB7B1361B066EC2F777AE104F88A846DC163200AEB05B47D5BFEC91B6F13AC53' : true,
+ 'DB995D854C4EDEF4DB5CCF20B2B30719056F3EDAA0CCF4B9D9C5C898407C5C7A' : true,
+ 'DBBF19EB75C47A8473F59CE4B2A318B493EEFEE4B6719BDF40FAB2E81D9DB2D9' : true,
+ 'DC90A8BEF7B1C62F9E4B3D3345665DBB5D6CB46077F5E7ED0628A5C0E3DFB742' : true,
+ 'DCC87ABAA2524536C43A280BC52710BF117E56EBB39444873F93AEF18519A502' : true,
+ 'DCCFAA33D28DE7243AB2C1514FF36012E967B0C0C6E62E940325CFCE982BFC23' : true,
+ 'DCF5F2D0FD496B041393D2151A3C6366DB5D9E3E6FC5EEAF236CEA93B7E0126D' : true,
+ 'DD5A1FC87107218C43D2C1C73075C5506D6901CE1289F86DC0162E6BBB80B84C' : true,
+ 'DD79B321EF333A6C39D48DB57DC5A138F023A111D56851CD4CBC8EB1BD094893' : true,
+ 'DD7B5992561C1F706A82F7D9318E45DCB1CF508A564263893350E2D3CBC41241' : true,
+ 'DDB4149166CCAC259D826E4E6649B5F59DB8DE3A2ABE0D0CA88F192AC891B331' : true,
+ 'DDC51B2E6531407BA185447AD1A9825344FCD12E93D120D81825613F016DF297' : true,
+ 'DDCA648AB82DF2A942AAD4B384839255D5D98ABEAFB602B2BBA2F4B115072EDC' : true,
+ 'DE65D592D65A64794CCF2911A10DB5DB27C28E6C88BBBF75B75FCBC2CAF5A02A' : true,
+ 'DEC7DC8AB8ED70C1D2FB2875F0F99FA99FB53E6BED70CD47B244ABA2104DA5AD' : true,
+ 'DEEBA70EA985BD2637FA63B79F69B0EEE5D261E95E3699B97855296B23D82C3D' : true,
+ 'DF32CD36F2BAE47DB4BDD2610D77629F44819723F9BA4FCFF6CC7F6E5709FFFD' : true,
+ 'DF4482289B54CB444569A5436AEEBEBFB348D966D2FBC8C5115376F3E5496303' : true,
+ 'DF464344337A60D78868FE886F92848BFF8713D641C9AC5EBA29524842656CCA' : true,
+ 'E0BD7FDC3544BBBF78F401148ADE378A4A85214C0469EDD5EC23C5246A6F5555' : true,
+ 'E0EFCF7FC7033248F1933BE975F931485787F32928E47DABAC84FEC9D7365CFB' : true,
+ 'E0F0A23CA9D564C9EF7CCD977D01D6E6E7EF5ABD585819EE64520CF369967353' : true,
+ 'E18545BD6D070F0C6AFE93153C190792C4921FC90953FAA775E351B1FB1BCC44' : true,
+ 'E25454E967CE89CBD0F51AC02466D60FC091BDDD9CBD3093ABD027B0AC4E8174' : true,
+ 'E26F4C34273553354334DC7A22DC56A781F2491181799287CC91F12871FEB50D' : true,
+ 'E27966B8B9C67C751F9AB8315D0BD1CEE334D96A8C5F60C764070EF8B8FCE61A' : true,
+ 'E2C42D4BD3807D802CE3B9EBC6FACC04E34EF327F4BBEC1C7A48618A1271F5E4' : true,
+ 'E2FBB7B66934E9C420D496089F2C0FB5AFA193A1E6F49BF35A751EE1E1F983DA' : true,
+ 'E2FC1229FE0EDF06A3706DB8DBD2344B61A9364840A3E61E6B29CE49A966AC8F' : true,
+ 'E315468836F77DF6AA146AF392C5DB7262A83AA83FD7CD75771C70D29C3F16CB' : true,
+ 'E35CE61842F1093D8D4AA9923AC66D17F8D1870A03C9CFCA1A27361CE8091CBC' : true,
+ 'E381DF6792973BFE322D23C6CF2A6C24A4ECFC77F43F03D2FC04EE39FAD7C683' : true,
+ 'E3EADC69740DF00FD147B0718CB1063D7E90E172E196C96956920235CF9DB382' : true,
+ 'E3FFE980C209BCBE10F594806CAA472BA2D4702F6E2549AEB86DC52B46DCF773' : true,
+ 'E4A79C0CBC9966A44EC1185DD6E66371FF395D0FAC53C1FD2619B02F6ACC9C6D' : true,
+ 'E4E88DE573C9161962C072B7A9C966BE3070A6027A061DE32630C553C09EB046' : true,
+ 'E4F069C24D7162E3C94AB295EA33C8926BDDF79934CA28D8982A35650EB60B05' : true,
+ 'E50C2EC0BA6891F60BB325C0762AB06271161EFA9E0B2ADD50FF520128092FBF' : true,
+ 'E556C54852E6E0E61097B2A34DDCB87F12EF74CA847CE07C4CAD2348FF41D3E5' : true,
+ 'E5E046397DC23925AB8CAD7CB66E2A12EBD989350CE41F89EED455248A109098' : true,
+ 'E5FB4DB1871BDADEE779D366E7BD007F7A963FBCB00B90EC14C8077477E436AD' : true,
+ 'E68C4E54088AD4A308EC6053041A4A8B04A213347BAE2CE86D3F1587B1518981' : true,
+ 'E692108B3683F3C6362DF92476D62BAE60687035B70B9119F962190C9C215B04' : true,
+ 'E6A029856494D7FE48E048D60E7BDE80D2B6217FF084F64A929056E166F479C2' : true,
+ 'E6A6EDA8D60BE3C0A5A19631D1BC3262EDABEBFCD0144F3D19513C8F6342CD12' : true,
+ 'E6EB9DC7D407B4A2F308B4822E5BEA7428CD4520C59934214831D61E95F2BA34' : true,
+ 'E70FC0431E5B6632A30C04F99A4E0E55C860187A04CCCDA4FDC08E926E94964D' : true,
+ 'E7382549110E59A8E0AEADFBD5D29FFA2350B5FB2923F2095744FBFD8AD54C97' : true,
+ 'E7CF336F6E4E8CC153474F240D9238D41091EBA635F25CDAFCFCFC3AF2A6BA43' : true,
+ 'E7E7A31551051BC4346069C741DF38908FB54470BEA2FAAA789DDED2D627F09D' : true,
+ 'E80FA3BD00D99AF27B013B520D3CEB1A8DF8BE355EC971F08B4AE44FFCE44147' : true,
+ 'E8165BA89FE5F637FA2B3428FCC54E7E92BDDBB80505188C61320FC70E24F86F' : true,
+ 'E83B3C3A3EAA32F6C60BE4D4DA918AA4A5432FF3380D4886C2844D69094EC571' : true,
+ 'E893B898F708775C51A0A60748972C53C4B62787A591B96EFBF8CE28E29E87D8' : true,
+ 'E8AD1B8DA833226A37C21D1608E0DBA8C758EED7A943EDF323ACBB779E227C86' : true,
+ 'E9A176C583F8B5522A9A86B6A4409AFAF614D6A7650A5D6C32E4499319F5280B' : true,
+ 'E9BB3A11B595B1D403FE21DF47A3A4EB4CF43ED49259DA83FB0FAAEC048422D7' : true,
+ 'E9DDA8C162F91A7D746A5567060DD636491C8C1441697B600F56C00FE73AC594' : true,
+ 'EA64F2625FAFE2EC122B493D4754C2B090153F167213AB6F07A87C1D993E5292' : true,
+ 'EA6973A28807C80D7558B7636F875574C9FAD887BACF23B0F686A61C26EDBFA7' : true,
+ 'EA9369F9AEF701B1F9699363254A2AE007F47AA824AECE077B82F1C0B6A69197' : true,
+ 'EB11019A7642C75F4DDC1DC9CF3B469BFB4C44B71C615693C73175F16DCA036C' : true,
+ 'EB5F60FED8FCE35455A15B9A8E9E200FCF1B8B5B278D1511C8C5EE67BD99FB46' : true,
+ 'EBABE928B643E1B9FD6F61D67ACC4BA6A9BFCC95927D31D265F701AC4613B9AE' : true,
+ 'EBB8403BAC78C842A81201893DC86184BE82BC2BFEC8A51748651F938F4051B0' : true,
+ 'EBC9928117D91D999CC375930982E891C5DC4F9E02A3960FE692DAB13D96ADA5' : true,
+ 'EC3097F047F40894368CA744A97CBB177C1122963AFF3D958DDBAC299F793E71' : true,
+ 'EC4FC179A9A40EBCF5F9508C94C0209D9C28ABFB21EE932FE11BC87F2887C490' : true,
+ 'EC810B437C1FF46BD3F0DABC2AE11DBC7ADE12B9889580BCF20C097540C97A7B' : true,
+ 'EC869ABCCE3A1C036F1AFABE5ECD4FDA581D16C0E81E16A2734E6004A55896BC' : true,
+ 'ECA27FBA9090EAD50CEE16362AB7462FBD060DF8B4BE27C107328E49214D6758' : true,
+ 'ECA4B72D4C90C2889F21F4084AE4CB53F5B8EA5D147529B0CF72D3A9093532B4' : true,
+ 'ED310E1BAEB1759D2AEC00BCDE6D9A86DFA33B17563EB5105585F15327831032' : true,
+ 'EDEEFEA60ECD1F9063448654B3D1285B8D340B4AAE455A26C34AF221F6F96F85' : true,
+ 'EE5D710097EAD11639F98940D1F32793ECC114F0408856CCB6536F1EF2366704' : true,
+ 'EE82E118167C83EC466137DE867DF824A5063074FC61CD164D21F26976741A2E' : true,
+ 'EF162B09A3D267BB7B8C79D44D06A7AF21EF260518D0EF3A8CFA1730D7B89231' : true,
+ 'EF55226DCFD0FA606BFD3496633BFCBC146925B2D6685AB4875E142D79233600' : true,
+ 'F010781D39EBF1A76700CA71DB56877685A52CEC2E7250D2C5684AF659887AC8' : true,
+ 'F055D488944F4779BE3F17FBEAD728843701CE6598D01286AA1D525F26AEDAAB' : true,
+ 'F07E7F2A7106743D8C1FF2E201F944E3227363968C5A0AE31112473B93BACC7B' : true,
+ 'F0A9E452CB90B0B6C50FB794AAE7ECBF5E56801A10124C95292B28592FA9B003' : true,
+ 'F0FD8D8E64636B1A1CC2557C50DBADE7A1F0536B905F5FFC06AFEF630AB9A40B' : true,
+ 'F1C66D3A1C4917A59AF8ADC68A0722F7193D345BD978BA00FF669E7948D44F29' : true,
+ 'F1DE4066AF24E5744C9075CFE974CCEAAEC75EF9E6028B48090B1A46CC218C37' : true,
+ 'F205928C933AFF1F1A6411AB779CFAE3FAAF43754AB86735DB52F74DB1DA81D2' : true,
+ 'F233DDE8F7165F2D7AA4E736E6FE1F913570FA7CA3E3C134EFD22D5F303075DE' : true,
+ 'F2835EDF2E61A29F9E62FEF97476165D5FF40E553A2A4F955EDE30C0A5149E12' : true,
+ 'F28F54684E233C9EEC646C6E1336E33684DA3732ECBEEDB2A606E09DD29801FA' : true,
+ 'F2C91876EDB36EAD7E4821C2A6581144F1E5A67B2DEF4A5E4AFDF79F5E1CC4D7' : true,
+ 'F2F7938B7E294F17565B2833CC2E0A657DA80A237814C24B5C0AAAF35C4608F8' : true,
+ 'F3160DD030C118B5D5835743E78CCADD0620E5C08460E0CD1F5D9D437352105B' : true,
+ 'F319741878D155ED3E5DD4955A82B842700A64D86AB782B511F0CB9B25C48AFA' : true,
+ 'F3A6A1A957C3BC86EFB3772C6153D97C33B908124CA58480AD1F62C54CD89013' : true,
+ 'F3B356D9CE5B37D2B690C4EBB2E04A643CB542273C1754D2EC9803D831781737' : true,
+ 'F3D202454336E948C83BCA2342C4D1A0DBB4335E829229BEAE04B4125F0D508E' : true,
+ 'F3F90821BD1454FC7AC92F768D2C9F75B5CD79FF4DD3251F4B9D647D34024F73' : true,
+ 'F456775CCC8DEC02CF2F92A48101E18EBCC9C880D41FA87EBE5E2EAA0E24620D' : true,
+ 'F460158348B017310570CAB302E33DD12FF72526698115EEE8D3DE318383ED9C' : true,
+ 'F47CA7623AEE6A1849B4F3F90818A93AA937A0EFA65D6674EA769BD7EC113BF8' : true,
+ 'F48CB2C1C2551290BA59502BBFCEC7BF137B5176967BB92B38E79D4EAA63B7E0' : true,
+ 'F4AD6AEF9BCAC58CF21EA81D65C3B8C85CBC9BCF6A2807FB0C5CD332C5F9BF49' : true,
+ 'F4C119D9DB2CD569E75B9B1F0884B990575EFD920E8C62177990AE650B7AA274' : true,
+ 'F4EDB536BE8520B583202E17C56768579613187741195347DDB9BCE3AE2D5150' : true,
+ 'F5B52148D7155BEE637459A918CE58D22D4E024FB715325FC1B36DA4C6255357' : true,
+ 'F5DBA16527D871BEFEEAE706C232AD0B76FA1384EFB86A844C7BA46B96917B9D' : true,
+ 'F5EB7AFA398131FF3966EE221B9C8F332BEFCB634D42631E349AC0BCF367E920' : true,
+ 'F5F8E7786E1F61643C7D2805D86031E5C4CC97AE93FC3785FE289FBC44C381E4' : true,
+ 'F66ABF80914FBDBE53F794409F4E0DC895129066609E8B491506FCE246A2EEB8' : true,
+ 'F69B01FAC28E6126F1BA71159D0273519683F2317EA764B4C483B32BB97614B0' : true,
+ 'F6A08E63AF8E62D51930BCE0FA7CF25DD2944512652EFA275E150EDD9C11CF51' : true,
+ 'F6A7FA219283E5B13E256B4E039E4CCD93CB72B84D84086E398D5534ECA42DFE' : true,
+ 'F74D9E23F4CB53775CA60178347F2A029F77579000B21AA08EC62A1C2932348A' : true,
+ 'F754352E819D0C33E6CFC06EECBB4356DB5D8BD1FD2591C7C817CCE662BE2BC4' : true,
+ 'F77AF5088D4EB425ADC0997C059C641EFB5AE2CAC73669EBAEEA378EDA383186' : true,
+ 'F7A57247F89F0C50879598293BB33B7AFF5FB74BCE37BF7B53F8955CEFBB9511' : true,
+ 'F7B593D9277B72E9CF376EAC2BD5535F76CD9FA0FDA3793D7EA6B4D050602E85' : true,
+ 'F7FC63254BF2472575C6D5DEC8DDF02B24B6F1BDCE03D807B159A69820262D4A' : true,
+ 'F805AE1FEDB2D94096F0D341B703ECD4975D773A179555DDC83D424F85578571' : true,
+ 'F823D6220F702D0547375FC4451FE27A91F0CE2AF9DA31552235F96CBBA56326' : true,
+ 'F82E01B697453BD37AD7012E267DC78395DF3DF4BFB0B1657F58256616F9B355' : true,
+ 'F8434B1782EC41F184305BD75BB3C0206721BC6CAD62442377072C06101B70DE' : true,
+ 'F88D1DF97289C9ED7E062D4E4B2B2463F90946DAC91785A6FA02F2599D7FE65C' : true,
+ 'F8E68F837C3E9452994FD6BF08F02D12D087BF6D44137BA37F72E408620F558B' : true,
+ 'F9971BA9EA322BB3FCB85111FED48B9CC1C9788D7BC6985E3CCE4BB7801B0DCC' : true,
+ 'FA14D235A95650A4CFD7A2A4DD80BAF2AF47581E01E412D640F93D6BB79D1C06' : true,
+ 'FADEBB24D23CEE1E8B02430C31A939E14821E9567A25367303F20F74879AB51C' : true,
+ 'FB674F1642EE443BBB827B29FD871CC110D77875884B1B050FC804D2884B2B3A' : true,
+ 'FB6814C66D6DDA2F348BF759398AB81F7795CA223F8AE9C0D82CA295162F68AD' : true,
+ 'FB7EF701469F77B6412100BB2D6399B1A574BB9610186FFFCC0119E14CB2021F' : true,
+ 'FBCC79E05CC135E183F4963C2A206F9DFDBC2DD0D379A743D5FB301741796921' : true,
+ 'FC2DA5A38AD07685CC019C7C388A396159FBAEF9EA491588FC995DBDF52A0B9C' : true,
+ 'FCF4BA663F0032118EADF9D327B65AB502C7A8B336462A397238884E9A28508E' : true,
+ 'FD4E54155D3117D78872DA05046A16FE944315F63C20BF0530F986F5F3797ECF' : true,
+ 'FD87C175594ABB82818D5CFEE506105069ECE5D5A499CFAD2E6376A88BAEB15D' : true,
+ 'FD8B1849A13BBD87D072F9D09506C90C0F29D7CCBD2B6446AD31335348AF9294' : true,
+ 'FDEE85771EF592A9E5F47D08250AFCBC73DCE96A72418B2848AE400F3CF59341' : true,
+ 'FE5DBE234A59B532A12BD552A36DB75AD21EF243C48C61849A0F93AF314C5896' : true,
+ 'FE739A748FB17DAFB6CBA0DA5B2164B8E0435E8DA7FB85E7970BBE731B428631' : true,
+ 'FE9E5DFD73260F732A5F7CE93B82DFA71D84F10D772A845221204A9685089FE7' : true,
+ 'FEB92F19B7394B8BF0FF71AEFD233E262AB656BDD531AD89FBEB9228C5378301' : true,
+ 'FEE5D5CF3F51FDBCD24D5D4E9BA06AFB96BFB558CB5D4249C70066749EEA8FBA' : true,
+ 'FEFEF80071B0D8E2B57D6601BB353A435A425EAA701827370C3585CE09F2CE50' : true,
+ 'FF769AAD90F56FB48D6C6CFCC86E38F9CBC6DB23774342892AFD4680ED3560FB' : true,
+} ;
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/code/sha256.js b/data/extensions/https-everywhere@eff.org/chrome/content/code/sha256.js
new file mode 100644
index 0000000..7e15f1a
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/code/sha256.js
@@ -0,0 +1,249 @@
+/*
+ * A JavaScript implementation of the SHA256 hash function.
+ *
+ * FILE:sha256.js
+ * VERSION:0.8
+ * AUTHOR:Christoph Bichlmeier <informatik@zombiearena.de>
+ *
+ * NOTE: This version is not tested thoroughly!
+ *
+ * Copyright (c) 2003, Christoph Bichlmeier
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * ======================================================================
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* SHA256 logical functions */
+function rotateRight(n,x) {
+ return ((x >>> n) | (x << (32 - n)));
+}
+function choice(x,y,z) {
+ return ((x & y) ^ (~x & z));
+}
+function majority(x,y,z) {
+ return ((x & y) ^ (x & z) ^ (y & z));
+}
+function sha256_Sigma0(x) {
+ return (rotateRight(2, x) ^ rotateRight(13, x) ^ rotateRight(22, x));
+}
+function sha256_Sigma1(x) {
+ return (rotateRight(6, x) ^ rotateRight(11, x) ^ rotateRight(25, x));
+}
+function sha256_sigma0(x) {
+ return (rotateRight(7, x) ^ rotateRight(18, x) ^ (x >>> 3));
+}
+function sha256_sigma1(x) {
+ return (rotateRight(17, x) ^ rotateRight(19, x) ^ (x >>> 10));
+}
+function sha256_expand(W, j) {
+ return (W[j&0x0f] += sha256_sigma1(W[(j+14)&0x0f]) + W[(j+9)&0x0f] +
+ sha256_sigma0(W[(j+1)&0x0f]));
+}
+
+/* Hash constant words K: */
+var K256 = new Array(
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+ );
+
+/* global arrays */
+var ihash, count, buffer;
+var sha256_hex_digits = "0123456789abcdef";
+
+/* Add 32-bit integers with 16-bit operations (bug in some JS-interpreters:
+ overflow) */
+function safe_add(x, y)
+{
+ var lsw = (x & 0xffff) + (y & 0xffff);
+ var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+ return (msw << 16) | (lsw & 0xffff);
+}
+
+/* Initialise the SHA256 computation */
+function sha256_init() {
+ ihash = new Array(8);
+ count = new Array(2);
+ buffer = new Array(64);
+ count[0] = count[1] = 0;
+ ihash[0] = 0x6a09e667;
+ ihash[1] = 0xbb67ae85;
+ ihash[2] = 0x3c6ef372;
+ ihash[3] = 0xa54ff53a;
+ ihash[4] = 0x510e527f;
+ ihash[5] = 0x9b05688c;
+ ihash[6] = 0x1f83d9ab;
+ ihash[7] = 0x5be0cd19;
+}
+
+/* Transform a 512-bit message block */
+function sha256_transform() {
+ var a, b, c, d, e, f, g, h, T1, T2;
+ var W = new Array(16);
+
+ /* Initialize registers with the previous intermediate value */
+ a = ihash[0];
+ b = ihash[1];
+ c = ihash[2];
+ d = ihash[3];
+ e = ihash[4];
+ f = ihash[5];
+ g = ihash[6];
+ h = ihash[7];
+
+ /* make 32-bit words */
+ for(var i=0; i<16; i++)
+ W[i] = ((buffer[(i<<2)+3]) | (buffer[(i<<2)+2] << 8) | (buffer[(i<<2)+1]
+ << 16) | (buffer[i<<2] << 24));
+
+ for(var j=0; j<64; j++) {
+ T1 = h + sha256_Sigma1(e) + choice(e, f, g) + K256[j];
+ if(j < 16) T1 += W[j];
+ else T1 += sha256_expand(W, j);
+ T2 = sha256_Sigma0(a) + majority(a, b, c);
+ h = g;
+ g = f;
+ f = e;
+ e = safe_add(d, T1);
+ d = c;
+ c = b;
+ b = a;
+ a = safe_add(T1, T2);
+ }
+
+ /* Compute the current intermediate hash value */
+ ihash[0] += a;
+ ihash[1] += b;
+ ihash[2] += c;
+ ihash[3] += d;
+ ihash[4] += e;
+ ihash[5] += f;
+ ihash[6] += g;
+ ihash[7] += h;
+}
+
+/* Read the next chunk of data and update the SHA256 computation */
+function sha256_update(data, inputLen) {
+ var i, index, curpos = 0;
+ /* Compute number of bytes mod 64 */
+ index = ((count[0] >> 3) & 0x3f);
+ var remainder = (inputLen & 0x3f);
+
+ /* Update number of bits */
+ if ((count[0] += (inputLen << 3)) < (inputLen << 3)) count[1]++;
+ count[1] += (inputLen >> 29);
+
+ /* Transform as many times as possible */
+ for(i=0; i+63<inputLen; i+=64) {
+ for(var j=index; j<64; j++)
+ buffer[j] = data.charCodeAt(curpos++);
+ sha256_transform();
+ index = 0;
+ }
+
+ /* Buffer remaining input */
+ for(var j=0; j<remainder; j++)
+ buffer[j] = data.charCodeAt(curpos++);
+}
+
+/* Finish the computation by operations such as padding */
+function sha256_final() {
+ var index = ((count[0] >> 3) & 0x3f);
+ buffer[index++] = 0x80;
+ if(index <= 56) {
+ for(var i=index; i<56; i++)
+ buffer[i] = 0;
+ } else {
+ for(var i=index; i<64; i++)
+ buffer[i] = 0;
+ sha256_transform();
+ for(var i=0; i<56; i++)
+ buffer[i] = 0;
+ }
+ buffer[56] = (count[1] >>> 24) & 0xff;
+ buffer[57] = (count[1] >>> 16) & 0xff;
+ buffer[58] = (count[1] >>> 8) & 0xff;
+ buffer[59] = count[1] & 0xff;
+ buffer[60] = (count[0] >>> 24) & 0xff;
+ buffer[61] = (count[0] >>> 16) & 0xff;
+ buffer[62] = (count[0] >>> 8) & 0xff;
+ buffer[63] = count[0] & 0xff;
+ sha256_transform();
+}
+
+/* Split the internal hash values into an array of bytes */
+function sha256_encode_bytes() {
+ var j=0;
+ var output = new Array(32);
+ for(var i=0; i<8; i++) {
+ output[j++] = ((ihash[i] >>> 24) & 0xff);
+ output[j++] = ((ihash[i] >>> 16) & 0xff);
+ output[j++] = ((ihash[i] >>> 8) & 0xff);
+ output[j++] = (ihash[i] & 0xff);
+ }
+ return output;
+}
+
+/* Get the internal hash as a hex string */
+function sha256_encode_hex() {
+ var output = new String();
+ for(var i=0; i<8; i++) {
+ for(var j=28; j>=0; j-=4)
+ output += sha256_hex_digits.charAt((ihash[i] >>> j) & 0x0f);
+ }
+ return output;
+}
+
+/* Main function: returns a hex string representing the SHA256 value of the
+ given data */
+function sha256_digest(data) {
+ sha256_init();
+ sha256_update(data, data.length);
+ sha256_final();
+ return sha256_encode_hex();
+}
+
+/* test if the JS-interpreter is working properly */
+function sha256_self_test()
+{
+ return sha256_digest("message digest") ==
+ "f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650";
+}
+
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/fetch-source.js b/data/extensions/https-everywhere@eff.org/chrome/content/fetch-source.js
new file mode 100644
index 0000000..a0220c8
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/fetch-source.js
@@ -0,0 +1,161 @@
+/* vim: set expandtab tabstop=2 shiftwidth=2 softtabstop=2 foldmethod=marker: */
+
+/**
+ * HTTPS Everywhere Firefox Extension: https://www.eff.org/https-everywhere/
+ *
+ * Licensed under the GPL v3+.
+ *
+ * @copyright Copyright (C) 2010-2013 Mike Perry <mikeperry@fscked.org>
+ * Peter Eckersley <pde@eff.org>
+ * and many others.
+ */
+
+// Define https everywhere variable object that will act as a namespace, so that
+// global namespace pollution is avoided, although technically not required for
+// windows created by add-on.
+// See: https://developer.mozilla.org/en-US/docs/Security_best_practices_in_extensions#Code_wrapping
+if (!httpsEverywhere) { var httpsEverywhere = {}; }
+
+/**
+ * JS Object for fetching the XML source of rulesets.
+ *
+ * @author Pavel Kazakov <nullishzero@gmail.com>
+ */
+httpsEverywhere.fetchSource = {
+ // TODO: look into class constants
+ CC: Components.classes,
+ CI: Components.interfaces,
+
+ // Constants for generating URL from which source will be fetched
+ BASE_SITE: 'https://gitweb.torproject.org/https-everywhere.git/blob_plain/',
+ DIRECTORY: '/src/chrome/content/rules/',
+ HEAD_STRING: 'HEAD',
+
+ /**
+ * Initializes the window to view source.
+ */
+ init: function() {
+ var fs = httpsEverywhere.fetchSource;
+
+ if("arguments" in window && window.arguments.length > 0) {
+ var filename = window.arguments[0].xmlName;
+ var id = window.arguments[0].GITCommitID; //GIT commit ID
+ var URL = fs.getURL(filename, id);
+ var source = fs.getSource(URL, filename, false);
+ } else {
+ // Should never happen
+ throw 'Invalid window arguments.';
+ }
+ },
+
+ /**
+ * Generates a URL that can be used for viewing the ruleset source.
+ *
+ * @param filename name of ruleset to view, such as EFF.xml
+ * @param GITCommitID revision of ruleset
+ *
+ * @return string of URL
+ */
+ getURL: function(filename, GITCommitID) {
+ var fs = httpsEverywhere.fetchSource;
+ return fs.BASE_SITE + GITCommitID + ":" + fs.DIRECTORY + filename;
+ },
+
+ /**
+ * Sends HTTP request to view ruleset source and updates the window with the
+ * ruleset source.
+ *
+ * @param URL HTTP request will be sent to this URL
+ * @param filename used for displaying ruleset source
+ * @param useHead whether send request to latest revision of ruleset
+ */
+ getSource: function(URL, filename, useHead) {
+ var fs = httpsEverywhere.fetchSource;
+ fs.setFilenameText(filename);
+ fs.setPathText(URL);
+
+ var req = fs.CC["@mozilla.org/xmlextras/xmlhttprequest;1"]
+ .createInstance(fs.CI.nsIXMLHttpRequest);
+
+ // Use HTTP GET
+ req.open("GET", URL);
+
+ // Clear User-Agent so request is pseudo-anonymous
+ req.setRequestHeader("User-Agent", "");
+
+ // handle asynchronous request
+ req.onreadystatechange = function(params) {
+ if (req.readyState == 4) {
+
+ // HTTP Request was successful
+ if (req.status == 200) {
+ fs.setSourceText(req.responseText);
+ } else if (!useHead) {
+ // HTTP request was not successful and the request wasn't sent to
+ // get the latest revision. Therefore, if we can't fetch current
+ // revision (this project's revision might newer than lastest, for
+ // example), try to at least display the latest revision.
+ var URL = fs.getURL(filename, fs.HEAD_STRING);
+ fs.getSource(URL, filename, true);
+ } else {
+ // at least we tried...
+ fs.downloadFailed();
+ }
+ }
+ };
+
+ req.send();
+ },
+
+ /**
+ * Handle a download failure of ruleset.
+ */
+ downloadFailed: function() {
+ document.getElementById("source-text").hidden = true;
+ document.getElementById("failure-label").hidden = false;
+ },
+
+
+ /**
+ * Convenience method for setting ruleset source text.
+ *
+ * @param text ruleset source
+ */
+ setSourceText: function(text) {
+ var textBox = document.getElementById("source-text");
+ textBox.value = text;
+ },
+
+ /**
+ * Convenience method for setting filename text.
+ *
+ * @param text file name
+ */
+ setFilenameText: function (text) {
+ var textLabel = document.getElementById("filename-text");
+ textLabel.value = text;
+ },
+
+ /**
+ * Convenience method for setting the path (URL) that was used to fetch
+ * ruleset.
+ *
+ * @param text path text
+ */
+ setPathText: function(text) {
+ var textLabel = document.getElementById("path-text");
+ textLabel.value = text;
+ }
+};
+
+// TODO: Test resizing on mulitple platforms
+// adjust window resizing
+window.onresize = function() {
+ var textBox = document.getElementById("source-text");
+ // TODO: Move to constants
+ textBox.width = window.innerWidth - 100;
+ textBox.height = window.innerHeight - 150;
+};
+
+// hook event for init
+window.addEventListener("load", httpsEverywhere.fetchSource.init, false);
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/fetch-source.xul b/data/extensions/https-everywhere@eff.org/chrome/content/fetch-source.xul
new file mode 100644
index 0000000..caa0048
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/fetch-source.xul
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<!DOCTYPE overlay SYSTEM "chrome://https-everywhere/locale/https-everywhere.dtd">
+
+<dialog id="https-everywhere-fetch-xml"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ xmlns:html="http://www.w3.org/1999/xhtml"
+ title="&https-everywhere.prefs.view_xml_source;"
+ persist="screenX screenY width height"
+ style="height:80%; resize:both;"
+ buttons="accept"
+ height="600"
+ width="650">
+
+
+ <script type="application/x-javascript" src="fetch-source.js"/>
+ <box orient="horizontal">
+ <label id="filename-label" value="&https-everywhere.source.filename;:"/>
+ <label id="filename-text"/>
+ </box>
+ <box orient="horizontal">
+ <label id="path-label" value="URL:"/>
+ <label id="path-text"/>
+ </box>
+ <separator class="thin"/>
+ <textbox id="source-text" multiline="true" readonly="true" value="&https-everywhere.source.downloading;..."/>
+ <label id="failure-label" hidden="true" value="&https-everywhere.source.unable_to_download;"/>
+</dialog>
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/meta-preferences.xul b/data/extensions/https-everywhere@eff.org/chrome/content/meta-preferences.xul
new file mode 100644
index 0000000..3e48010
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/meta-preferences.xul
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://https-everywhere/content/preferences.css" type="text/css"?>
+
+<!DOCTYPE overlay SYSTEM "chrome://https-everywhere/locale/https-everywhere.dtd">
+
+<window id="https-everywhere-meta-prefs"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ xmlns:html="http://www.w3.org/1999/xhtml"
+ title="&https-everywhere.prefs.title;"
+ persist="screenX screenY width height"
+ width="600"
+ height="600">
+ <separator class="thin" />
+ <tabbox flex="1">
+ <tabs>
+ <tab label="HTTPS Everywhere" />
+ <tab label="SSL Observatory" />
+ </tabs>
+ <tabpanels flex="1">
+ <tabpanel flex="1" orient="vertical">
+ <browser src="chrome://https-everywhere/content/preferences.xul" flex="1"/>
+ </tabpanel>
+ <tabpanel flex="1" orient="vertical">
+ <browser src="chrome://https-everywhere/content/observatory-preferences.xul" flex="1"/>
+ </tabpanel>
+ </tabpanels>
+ </tabbox>
+
+</window>
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/observatory-popup.xul b/data/extensions/https-everywhere@eff.org/chrome/content/observatory-popup.xul
new file mode 100644
index 0000000..60da68f
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/observatory-popup.xul
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<!DOCTYPE window SYSTEM "chrome://https-everywhere/locale/ssl-observatory.dtd">
+<window id="ssl-observatory-dialog"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ xmlns:html="http://www.w3.org/1999/xhtml"
+ title="&ssl-observatory.popup.title;"
+ width="500"
+ height="440"
+ align="center"
+ onload="document.getElementById('ask-me-later').focus()"
+ >
+ <script type="application/x-javascript" src="observatory-xul.js" />
+ <image src="chrome://https-everywhere/skin/ssl-observatory-messy.jpg" />
+ <label style="padding:25px;">&ssl-observatory.popup.text;</label>
+
+ <commandgroup>
+ <command id="enable" oncommand="enable_observatory() ; popup_done()" />
+ <command id="nope" oncommand="disable_observatory() ; popup_done()" />
+ <command id="later" oncommand="window.close()" />
+ <command id="more-info"
+ oncommand='popup_done() ;
+ window.open("chrome://https-everywhere/content/observatory-preferences.xul","obsprefs",
+ "chrome, centerscreen")'/>
+ </commandgroup>
+
+ <vbox flex="1">
+ <spacer flex="5" />
+ <separator class="thin"/>
+ <hbox>
+ <spacer flex="2" />
+ <button label="&ssl-observatory.popup.yes;" tabindex="2" accesskey="y"
+ command='enable'/>
+ <spacer flex="1" />
+ <button label="&ssl-observatory.popup.no;" tabindex="3" accesskey="n"
+ command='nope'/>
+ <spacer flex="2" />
+ </hbox>
+ <separator class="thin"/>
+ <spacer flex="10" />
+ <hbox>
+ <spacer flex="2" />
+ <button label="&ssl-observatory.popup.details;" tabindex="4" accesskey="D"
+ command='more-info'/>
+ <spacer flex="1" />
+ <button id="ask-me-later" label="&ssl-observatory.popup.later;"
+ tabindex="1" accesskey="A" command='later'/>
+ <spacer flex="2" />
+ </hbox>
+ <separator class="thin"/>
+ <spacer flex="1" />
+ </vbox>
+
+ <!--
+ <hbox style="padding-top:10px;">
+ <label class="text-link" href="https://www.eff.org/" tabindex="3" value="&ssl-observatory.popup.details;" />
+ <spacer flex="1" />
+ <button label="&ssl-observatory.popup.later;" id="ask-me-later" tabindex="0" style="font-size:0.8em;" accesskey="l"
+ oncommand="doCancel()"/>-
+ </hbox>-->
+</window>
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/observatory-preferences.xul b/data/extensions/https-everywhere@eff.org/chrome/content/observatory-preferences.xul
new file mode 100644
index 0000000..96102d0
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/observatory-preferences.xul
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<!DOCTYPE overlay SYSTEM "chrome://https-everywhere/locale/ssl-observatory.dtd">
+
+<dialog id="https-everywhere-prefs"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ xmlns:html="http://www.w3.org/1999/xhtml"
+ buttons="accept"
+ buttonlabelaccept="&ssl-observatory.prefs.done;"
+ title="&ssl-observatory.prefs.title;"
+ width="800"
+ height="768"
+ persist="screenX screenY width height"
+ onload="observatory_prefs_init(document)"
+ ondialogaccept="observatory_prefs_accept()">
+ <script type="application/x-javascript" src="observatory-xul.js" />
+ <vbox flex="1" style="overflow:auto">
+ <spacer flex="1" />
+ <hbox flex="1">
+ <spacer flex="1" />
+ <image id="obs-title-logo"
+ src="chrome://https-everywhere/skin/ssl-observatory-messy.jpg" />
+ <spacer flex="1" />
+ </hbox>
+ <spacer flex="2" />
+ <label>&ssl-observatory.prefs.explanation;</label>
+ <separator class="thin" />
+ <label>&ssl-observatory.prefs.explanation2;</label>
+ <separator class="thin" />
+ <commandset>
+ <command id="toggle-enabled" oncommand="toggle_enabled()" />
+ <command id="use-obs-anon" oncommand="set_obs_anon(true)" />
+ <command id="use-obs-nonanon" oncommand="set_obs_anon(false)" />
+ <command id="toggle-alt-roots" oncommand="toggle_alt_roots()" />
+ <command id="toggle-send-asn" oncommand="toggle_send_asn()" />
+ <command id="toggle-priv-dns" oncommand="toggle_priv_dns()" />
+ <command id="toggle-self-signed" oncommand="toggle_self_signed()" />
+ </commandset>
+ <checkbox label="&ssl-observatory.prefs.use;" id="use-observatory"
+ command="toggle-enabled" style="font-size:1.5em;"/>
+ <separator class="thin"/>
+ <radiogroup style="margin-left:3em;" id="ssl-obs-how">
+ <radio label="&ssl-observatory.prefs.anonymous;"
+ tooltiptext="&ssl-observatory.prefs.anonymous_tooltip;"
+ alt_label="&ssl-observatory.prefs.anonymous_unavailable;"
+ command="use-obs-anon"
+ class="ssl-obs-conf" id="ssl-obs-anon"/>
+ <radio label="&ssl-observatory.prefs.nonanon;"
+ tooltiptext="&ssl-observatory.prefs.nonanon_tooltip;"
+ command="use-obs-nonanon"
+ class="ssl-obs-conf" id="ssl-obs-nonanon"/>
+ </radiogroup>
+ <separator class="thin"/>
+ <tooltip id="asn-tip" noautohide="true">
+ <label>&ssl-observatory.prefs.asn_tooltip;</label>
+ </tooltip>
+ <checkbox label="&ssl-observatory.prefs.asn;" id="send-asn"
+ tooltip="asn-tip" class="ssl-obs-conf"
+ command="toggle-send-asn"/>
+ <spacer flex="2" />
+ <hbox>
+ <spacer flex="1" />
+ <button label="&ssl-observatory.prefs.show;" onclick="show_advanced()"
+ id="show-advanced-button" class="ssl-obs-conf"/>
+ <button label="&ssl-observatory.prefs.hide;" onclick="hide_advanced()"
+ id="hide-advanced-button" hidden="true" />
+ <spacer flex="1" />
+ </hbox>
+ <spacer flex="1" />
+ <vbox flex="2">
+ <tooltip id="alt-roots-tip" noautohide="true">
+ <label>&ssl-observatory.prefs.alt_roots_tooltip;</label>
+ </tooltip>
+ <tooltip id="priv-dns-tip" noautohide="true">
+ <label>&ssl-observatory.prefs.priv_dns_tooltip;</label>
+ </tooltip>
+ <tooltip id="self-signed-tip" noautohide="true">
+ <label>&ssl-observatory.prefs.self_signed_tooltip;</label>
+ </tooltip>
+ <vbox id="observatory-advanced-opts" hidden="true">
+
+ <groupbox hidden="true" tooltip="self-signed-tip">
+ <checkbox label="&ssl-observatory.prefs.self_signed;"
+ class="ssl-obs-conf" id="self-signed"
+ command="toggle-self-signed"/>
+ </groupbox>
+
+ <groupbox hidden="true" tooltip="alt-roots-tip" >
+ <caption hidden="true" label="&ssl-observatory.prefs.adv_priv_opts1;"/>
+ <checkbox label="&ssl-observatory.prefs.alt_roots;"
+ command="toggle-alt-roots" class="ssl-obs-conf"
+ id="alt-roots" />
+ </groupbox>
+ <groupbox hidden="true" tooltip="priv-dns-tip">
+ <caption hidden="true" label="&ssl-observatory.prefs.adv_priv_opts2;"/>
+ <checkbox label="&ssl-observatory.prefs.priv_dns;"
+ class="ssl-obs-conf" id="priv-dns"
+ command="toggle-priv-dns"/>
+ </groupbox>
+ </vbox>
+ </vbox>
+ <spacer flex="5" />
+ </vbox>
+</dialog>
+
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/observatory-warning.xul b/data/extensions/https-everywhere@eff.org/chrome/content/observatory-warning.xul
new file mode 100644
index 0000000..1f64e12
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/observatory-warning.xul
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<!DOCTYPE window SYSTEM "chrome://https-everywhere/locale/ssl-observatory.dtd">
+<window id="ssl-observatory-dialog"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ xmlns:html="http://www.w3.org/1999/xhtml"
+ title="&ssl-observatory.warning.title;"
+ width="600"
+ height="500"
+ align="center"
+ onload="warning_populate(window.arguments[0])"
+ >
+ <script type="application/x-javascript" src="observatory-xul.js" />
+ <image src="chrome://https-everywhere/skin/ssl-observatory-messy.jpg" />
+ <vbox flex="1">
+ <vbox id="warning-container" flex="1">
+ <label style="padding:25px 25px 10px;">&ssl-observatory.warning.text;</label>
+ <spacer flex="1" />
+ </vbox>
+
+ <commandgroup>
+ <command id="showcert" oncommand="show_certs()" />
+ <command id="okay" oncommand='window.close()'
+ />
+ </commandgroup>
+
+ <spacer flex="1" />
+ <label style="padding:5px 25px 0px;">&ssl-observatory.warning.defense;</label>
+ <separator class="thin"/>
+ <hbox>
+ <spacer flex="2" />
+ <button label="&ssl-observatory.warning.showcert;" accesskey="S"
+ id="show-certificate" command='showcert'/>
+ <spacer flex="1" />
+ <button label="&ssl-observatory.warning.okay;" accesskey="I"
+ command='okay'/>
+ <spacer flex="2" />
+ </hbox>
+ <separator class="thin" />
+ </vbox>
+
+ <!--
+ <hbox style="padding-top:10px;">
+ <label class="text-link" href="https://www.eff.org/" tabindex="3" value="&ssl-observatory.popup.details;" />
+ <spacer flex="1" />
+ <button label="&ssl-observatory.popup.later;" id="ask-me-later" tabindex="0" style="font-size:0.8em;" accesskey="l"
+ oncommand="doCancel()"/>-
+ </hbox>-->
+</window>
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/observatory-xul.js b/data/extensions/https-everywhere@eff.org/chrome/content/observatory-xul.js
new file mode 100644
index 0000000..df5e623
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/observatory-xul.js
@@ -0,0 +1,194 @@
+const CC = Components.classes;
+const CI = Components.interfaces;
+VERB=1;
+DBUG=2;
+INFO=3;
+NOTE=4;
+WARN=5;
+
+var ssl_observatory = CC["@eff.org/ssl-observatory;1"]
+ .getService(Components.interfaces.nsISupports)
+ .wrappedJSObject;
+var obsprefs = ssl_observatory.prefs;
+
+const pref_prefix = "extensions.ssl_observatory.";
+
+function observatory_prefs_init(doc) {
+ // Is the Observatory on?
+ var enabled = obsprefs.getBoolPref("extensions.https_everywhere._observatory.enabled");
+ document.getElementById("use-observatory").checked = enabled;
+ set_observatory_configurability(enabled);
+ // Other settings
+ document.getElementById("alt-roots").checked =
+ obsprefs.getBoolPref("extensions.https_everywhere._observatory.alt_roots");
+ document.getElementById("priv-dns").checked =
+ obsprefs.getBoolPref("extensions.https_everywhere._observatory.priv_dns");
+ document.getElementById("self-signed").checked =
+ obsprefs.getBoolPref("extensions.https_everywhere._observatory.self_signed");
+ document.getElementById("send-asn").checked =
+ obsprefs.getBoolPref("extensions.https_everywhere._observatory.send_asn");
+
+ // More complicated: is it anonymised by Tor?
+ var obs_how = doc.getElementById("ssl-obs-how");
+ var anon_radio = document.getElementById("ssl-obs-anon");
+ var nonanon_radio = document.getElementById("ssl-obs-nonanon");
+ var anon = !obsprefs.getBoolPref(
+ "extensions.https_everywhere._observatory.use_custom_proxy");
+
+ // first set the radios to match the current settings variables
+ obs_how.selectedItem = (anon) ? anon_radio : nonanon_radio;
+
+ // But if the user hasn't turned the observatory on,
+ // the default should be the maximally sensible one
+ var torbutton_avail = ssl_observatory.proxy_test_successful;
+ if (!enabled) {
+ set_obs_anon(torbutton_avail);
+ obs_how.selectedItem = (torbutton_avail) ? anon_radio : nonanon_radio;
+ }
+ //scale_title_logo();
+}
+
+// The user has responded to the popup in a final way; don't show it to them
+// again
+function popup_done() {
+ obsprefs.setBoolPref("extensions.https_everywhere._observatory.popup_shown", true);
+ obsprefs.setBoolPref("extensions.https_everywhere._observatory.clean_config", true);
+ window.close();
+}
+
+
+function scale_title_logo() {
+ // The image is naturally 500x207, but if it's shrunk we don't want it
+ // distorted
+ var img = document.getElementById("obs-title-logo");
+ alert("ch is " + img.height);
+ if (img.height != "207")
+ img.width = (500.0/207.0) * img.height;
+}
+
+// grey/ungrey UI elements that control observatory operation
+function set_observatory_configurability(enabled) {
+ // the relevant widgets are tagged with class="ssl-obs-conf"
+ var ui_elements = document.querySelectorAll(".ssl-obs-conf");
+ for (var i =0; i < ui_elements.length; i++)
+ ui_elements[i].disabled = !enabled;
+ // the "use tor" option can't be ungreyed unless tor is available
+ if (ssl_observatory.proxy_test_successful == false) {
+ var tor_opt = document.getElementById("ssl-obs-anon")
+ tor_opt.disabled = true;
+ tor_opt.label = tor_opt.getAttribute("alt_label");
+ }
+ if (!enabled)
+ hide_advanced();
+}
+
+// show/hide advanced options in the preferences dialog
+function show_advanced() {
+ var enabled = obsprefs.getBoolPref("extensions.https_everywhere._observatory.enabled");
+ if (enabled) {
+ var adv_opts_box = document.getElementById("observatory-advanced-opts");
+ recursive_set(adv_opts_box, "hidden", "false");
+ document.getElementById("show-advanced-button").hidden = true;
+ document.getElementById("hide-advanced-button").hidden = false;
+ }
+ //scale_title_logo();
+}
+function hide_advanced() {
+ var adv_opts_box = document.getElementById("observatory-advanced-opts");
+ recursive_set(adv_opts_box, "hidden", "true");
+ document.getElementById("show-advanced-button").hidden = false;
+ document.getElementById("hide-advanced-button").hidden = true;
+}
+
+function recursive_set(node, attrib, value) {
+ node.setAttribute(attrib, value);
+ for (var i=0; i < node.childNodes.length; i++)
+ recursive_set(node.childNodes[i], attrib, value)
+}
+
+
+function set_obs_anon(val) {
+ obsprefs.setBoolPref( "extensions.https_everywhere._observatory.use_custom_proxy", !val);
+}
+
+// called from the popup only
+function enable_observatory() {
+ obsprefs.setBoolPref("extensions.https_everywhere._observatory.enabled", true);
+ var torbutton_avail = ssl_observatory.proxy_test_successful;
+ set_obs_anon(torbutton_avail);
+}
+
+function disable_observatory() {
+ // default but be sure...
+ obsprefs.setBoolPref("extensions.https_everywhere._observatory.enabled", false);
+}
+
+// called from within the prefs window, we have more work to do:
+function toggle_enabled() {
+ var use_obs = document.getElementById("use-observatory").checked;
+ obsprefs.setBoolPref("extensions.https_everywhere._observatory.enabled", use_obs);
+ set_observatory_configurability(use_obs);
+}
+
+function toggle_send_asn() {
+ var send_asn = document.getElementById("send-asn").checked;
+ obsprefs.setBoolPref("extensions.https_everywhere._observatory.send_asn", send_asn);
+ if (send_asn) ssl_observatory.setupASNWatcher()
+ else ssl_observatory.stopASNWatcher();
+}
+
+function toggle_alt_roots() {
+ var alt_roots = document.getElementById("alt-roots").checked;
+ obsprefs.setBoolPref("extensions.https_everywhere._observatory.alt_roots", alt_roots);
+}
+
+function toggle_priv_dns() {
+ var priv_dns = document.getElementById("priv-dns").checked;
+ obsprefs.setBoolPref("extensions.https_everywhere._observatory.priv_dns", priv_dns);
+}
+
+function toggle_self_signed() {
+ var self_signed = document.getElementById("self-signed").checked;
+ obsprefs.setBoolPref("extensions.https_everywhere._observatory.self_signed", self_signed);
+}
+
+function observatory_prefs_accept() {
+ // This is *horrid*, but
+ // https://developer.mozilla.org/en/working_with_windows_in_chrome_code#Accessing_the_elements_of_the_top-level_document_from_a_child_window
+ var outer = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIWebNavigation)
+ .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
+ .rootTreeItem
+ .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIDOMWindow);
+
+ if (outer) outer.close()
+ else alert("no outer space");
+
+ return true; // https://developer.mozilla.org/en/XUL/dialog#a-ondialogaccept
+ // also close things if there is no out meta prefs window
+}
+
+function warning_populate(warningObj) {
+ // Fill in the SSL Observatory Warning labels...
+ var container = document.getElementById("warning-container");
+ for (var hash in warningObj) {
+ var label=document.createElement("label");
+ label.setAttribute("style","padding:5px 25px 5px;");
+ label.textContent = warningObj[hash].long_desc;
+ container.appendChild(label);
+ //var spacer=document.createElement("spacer");
+ //separator.setAttribute("flex","1");
+ //container.appendChild(spacer);
+ }
+}
+
+function show_certs() {
+ var parent_win = window.arguments[1];
+ var cert = window.arguments[2];
+ if (!parent_win)
+ alert("no parent window trying to show certs");
+ CC["@mozilla.org/nsCertificateDialogs;1"]
+ .getService(CI.nsICertificateDialogs)
+ .viewCert(parent_win, cert);
+}
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/preferences.css b/data/extensions/https-everywhere@eff.org/chrome/content/preferences.css
new file mode 100644
index 0000000..6b35c00
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/preferences.css
@@ -0,0 +1,11 @@
+treechildren::-moz-tree-checkbox { /* css for unchecked cells */
+ list-style-image: url("chrome://https-everywhere/skin/cross.png");
+}
+
+treechildren::-moz-tree-checkbox(checked) { /* css for checked cells */
+ list-style-image: url("chrome://https-everywhere/skin/tick.png");
+}
+
+treechildren::-moz-tree-checkbox(undefined) { /* css for empty cells */
+ list-style-image: url("");
+}
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/preferences.js b/data/extensions/https-everywhere@eff.org/chrome/content/preferences.js
new file mode 100644
index 0000000..557b335
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/preferences.js
@@ -0,0 +1,269 @@
+const CC = Components.classes;
+const CI = Components.interfaces;
+VERB=1;
+DBUG=2;
+INFO=3;
+NOTE=4;
+WARN=5;
+
+https_everywhere = CC["@eff.org/https-everywhere;1"]
+ .getService(Components.interfaces.nsISupports)
+ .wrappedJSObject;
+
+rulesets = [];
+
+const id_prefix = "he_enable";
+const pref_prefix = "extensions.https_everywhere.";
+const GITID = https_everywhere.https_rules.GITCommitID;
+
+// Disable all rules.
+function disable_all() {
+ for (var i in rulesets) {
+ rulesets[i].disable();
+ }
+
+ treeView.treebox.invalidate();
+}
+
+// Reset all rules to their default state.
+function reset_defaults() {
+ https_everywhere.https_rules.resetRulesetsToDefaults()
+ treeView.treebox.invalidate();
+}
+
+function resetSelected() {
+ var start = {};
+ var end = {};
+ var st = document.getElementById('sites_tree');
+ var sel = st.view.selection;
+ var numRanges = sel.getRangeCount();
+
+ for (var t = 0; t < numRanges; t++){
+ sel.getRangeAt(t, start, end);
+ for (var v = start.value; v <= end.value; v++){
+ var rs = treeView.rules[v];
+ rs.clear();
+ }
+ }
+}
+
+function resetSelectedMenu() {
+ var start = {};
+ var end = {};
+ var st = document.getElementById('sites_tree');
+ var sel = st.view.selection;
+ var numRanges = sel.getRangeCount();
+ var menuitem = document.getElementById("revert_menuitem");
+
+ for (var t = 0; t < numRanges; t++){
+ sel.getRangeAt(t, start, end);
+ for (var v = start.value; v <= end.value; v++){
+ var rs = treeView.rules[v];
+ if (rs.active !== rs.on_by_default) {
+ menuitem.disabled = false;
+ return;
+ }
+ }
+ }
+ menuitem.disabled = true;
+}
+
+function toggleSelected() {
+ var start = {};
+ var end = {};
+ var st = document.getElementById('sites_tree');
+ var sel = st.view.selection;
+ var numRanges = sel.getRangeCount();
+ var menuitem = document.getElementById("revert_menuitem");
+
+ for (var t = 0; t < numRanges; t++){
+ sel.getRangeAt(t, start, end);
+ for (var v = start.value; v <= end.value; v++){
+ var rs = treeView.rules[v];
+ rs.toggle();
+ treeView.treebox.invalidateRow(v);
+ }
+ }
+}
+
+
+function viewXMLSource() {
+ var start = {};
+ var end = {};
+ var st = document.getElementById('sites_tree');
+ var sel = st.view.selection;
+ var numRanges = sel.getRangeCount();
+ var menuitem = document.getElementById("revert_menuitem");
+
+ for (var t = 0; t < numRanges; t++){
+ sel.getRangeAt(t, start, end);
+ for (var v = start.value; v <= end.value; v++){
+ var rs = treeView.rules[v];
+
+ //This *should* not violate TorButton's State Control, but someone should double check
+ //this code just in case
+ var aWin = CC['@mozilla.org/appshell/window-mediator;1']
+ .getService(CI.nsIWindowMediator)
+ .getMostRecentWindow('navigator:browser');
+ aWin.openDialog("chrome://https-everywhere/content/fetch-source.xul",
+ rs.xmlName, "chrome,centerscreen",
+ {xmlName: rs.xmlName, GITCommitID: GITID} );
+ }
+ }
+}
+
+function getValue(row, col) {
+ switch (col.id) {
+ case "site_col":
+ return row.name;
+ case "note_col":
+ return row.notes;
+ case "enabled_col":
+ return https_everywhere.https_rules.rulesetsByName[row.name].active;
+ /*var ruleActive = false;
+ try {
+ if(https_everywhere.rule_toggle_prefs.getBoolPref(row.name))
+ ruleActive = true;
+ } catch(e) {
+ ruleActive = https_everywhere.https_rules.rulesetsByName[row.name].active;
+ }
+ return ruleActive;*/
+ default:
+ return;
+ }
+}
+
+function compareRules(a, b, col) {
+ var aval = getValue(a, col).toLowerCase();
+ var bval = getValue(b, col).toLowerCase();
+ var ret = 0;
+ if (aval < bval) {
+ ret = -1;
+ } else if (aval > bval) {
+ ret = 1;
+ } else {
+ ret = 0;
+ }
+ return ret;
+}
+
+function https_prefs_init(doc) {
+ var st = document.getElementById('sites_tree');
+ https_everywhere.https_rules.loadAllRulesets();
+ rulesets = Array.slice(https_everywhere.https_rules.rulesets);
+
+ // GLOBAL VARIABLE!
+ treeView = {
+ rules: rulesets,
+ rowCount: rulesets.length,
+ getCellValue: function(row, col) { // site names
+ if (!this.rules[row]) return;
+ return getValue(this.rules[row], col);
+ },
+ getCellText: function(row, col) { // activation indicator
+ return this.getCellValue(row, col);
+ },
+ setCellValue: function(row, col, val) { // toggle a rule's activation
+ var rule = this.rules[row];
+
+ if (val == "true") {
+ rule.enable();
+ } else {
+ rule.disable();
+ }
+
+ this.treebox.invalidateRow(row);
+ },
+ isEditable: function(row, col) {
+ return (col.id == "enabled_col");
+ },
+ setTree: function(treebox) {
+ this.treebox = treebox;
+ },
+ isContainer: function(row) { return false; },
+ isSeparator: function(row) { return false; },
+ isSorted: function() { return false; },
+ getRowProperties: function(row, props) {},
+ getColumnProperties: function(colid, col, props) {},
+ getCellProperties: function(row, col, props) {
+ if ( (col.id == "enabled_col") && !(this.rules[row]) ) {
+ var atomS = CC["@mozilla.org/atom-service;1"];
+ atomS = atomS.getService(CI.nsIAtomService);
+ // Starting with 22.0a1 there is no |props| available anymore. See:
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=407956. Looking at the
+ // patch the following seems to work, though.
+ if (!props) {
+ return "undefined";
+ }
+ props.AppendElement( atomS.getAtom("undefined") );
+ }
+ },
+ getLevel: function(row) { return 0; },
+ getImageSrc: function(row, col) { return null; },
+ search: function(query) {
+ var new_rules = [];
+ query = query.value.toLowerCase().replace(/^\s+|\s+$/g, "");
+
+ for (var i in rulesets) {
+ var rule_name = rulesets[i].name.toLowerCase();
+ if ( rule_name.indexOf(query) != -1 ) {
+ new_rules.push(rulesets[i]);
+ }
+ }
+
+ this.rules = new_rules;
+ this.rowCount = new_rules.length;
+ this.treebox.invalidate();
+ this.treebox.scrollToRow(rulesets[0]);
+ },
+ cycleHeader: function (col) {
+ var columnName;
+ var order = (col.element.getAttribute("sortDirection") === "ascending" ? -1 : 1);
+
+ var compare = function (a, b) {
+ return compareRules(a, b, col) * order;
+ };
+ rulesets.sort(compare);
+ this.rules.sort(compare);
+
+ var cols = st.getElementsByTagName("treecol");
+ for (var i = 0; i < cols.length; i++) {
+ cols[i].removeAttribute("sortDirection");
+ }
+ col.element.setAttribute("sortDirection", order === 1 ? "ascending" : "descending");
+ this.treebox.invalidate();
+ }
+ };
+
+ st.view = treeView;
+}
+
+function window_opener(uri) {
+ // we don't use window.open, because we need to work around TorButton's state control
+ if(typeof gBrowser == "undefined"){
+ var window = CC["@mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator);
+ var browserWindow = window.getMostRecentWindow("navigator:browser").getBrowser();
+ var newTab = browserWindow.addTab(uri, null, null);
+ browserWindow.selectedTab = newTab;
+
+ }
+ else
+ gBrowser.selectedTab = gBrowser.addTab(uri);
+}
+
+function https_prefs_accept() {
+ // This is *horrid*, but
+ // https://developer.mozilla.org/en/working_with_windows_in_chrome_code#Accessing_the_elements_of_the_top-level_document_from_a_child_window
+ var outer = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIWebNavigation)
+ .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
+ .rootTreeItem
+ .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIDOMWindow);
+
+ if (outer) outer.close();
+ else alert("no outer space");
+
+ return true; // https://developer.mozilla.org/en/XUL/dialog#a-ondialogaccept
+ // also close things if there is no out meta prefs window
+}
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/preferences.xul b/data/extensions/https-everywhere@eff.org/chrome/content/preferences.xul
new file mode 100644
index 0000000..ebde85b
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/preferences.xul
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://https-everywhere/content/preferences.css" type="text/css"?>
+
+<!DOCTYPE overlay SYSTEM "chrome://https-everywhere/locale/https-everywhere.dtd">
+
+<dialog id="https-everywhere-prefs"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ xmlns:html="http://www.w3.org/1999/xhtml"
+ buttons="accept,extra1,extra2"
+ buttonlabelextra1="&https-everywhere.prefs.disable_all;"
+ ondialogextra1="disable_all();"
+ buttonlabelextra2="&https-everywhere.prefs.reset_defaults;"
+ ondialogextra2="reset_defaults();"
+ title="&https-everywhere.prefs.title;"
+ persist="screenX screenY width height"
+ style="height:80%; resize:both;"
+ height="600"
+ width="650"
+ onload="https_prefs_init(document)"
+ ondialogaccept="https_prefs_accept()">
+
+ <script type="application/x-javascript" src="preferences.js"/>
+
+ <popupset>
+ <menupopup id="tree-contextmenu" onpopupshowing="resetSelectedMenu()">
+ <menuitem label="&https-everywhere.prefs.reset_default;" oncommand="resetSelected();" id="revert_menuitem"/>
+ <menuitem label="&https-everywhere.prefs.toggle;" oncommand="toggleSelected();"/>
+ <menuitem label="&https-everywhere.prefs.view_xml_source;" oncommand="viewXMLSource();"/>
+ </menupopup>
+ </popupset>
+
+ <groupbox flex="1">
+ <caption label="&https-everywhere.prefs.list_caption;"
+ align="center"/>
+ <vbox>
+ &https-everywhere.prefs.search;: <textbox id="tree_search" oninput="treeView.search(this);" />
+ </vbox>
+ <tree id="sites_tree" editable="true" flex="1" context="tree-contextmenu">
+ <treecols>
+ <treecol id="enabled_col" type="checkbox" label="&https-everywhere.prefs.enabled;"
+ editable="true" class="sortDirectionIndicator" persist="sortDirection width"/>
+ <splitter class="tree-splitter"/>
+ <treecol id="site_col" label="&https-everywhere.prefs.site;" flex="1" editable="false" class="sortDirectionIndicator" persist="sortDirection width"/>
+ <splitter class="tree-splitter"/>
+ <treecol id="note_col" label="&https-everywhere.prefs.notes;" flex="1" editable="false" class="sortDirectionIndicator" persist="sortDirection width"/>
+ </treecols>
+ <treechildren/>
+ </tree>
+ </groupbox>
+ <separator class="thin"/>
+ <vbox>
+ &https-everywhere.prefs.ruleset_howto;
+ <separator class="thin"/>
+ <label id="ruleset link"
+ value="&https-everywhere.prefs.here_link;"
+ style="color: blue; cursor:hand; text-decoration:underline;"
+ onmouseover="event.target.style.cursor='pointer'"
+ onmouseout="event.target.style.cursor='default'"
+ onclick="window_opener('https://eff.org/https-everywhere/rulesets')"/>.
+ </vbox>
+</dialog>
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/rules/00README b/data/extensions/https-everywhere@eff.org/chrome/content/rules/00README
new file mode 100644
index 0000000..fcd8a77
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/rules/00README
@@ -0,0 +1,17 @@
+<!--
+This directory contains web site rewriting rules for the
+HTTPS Everywhere software, available from
+https://www.eff.org/https-everywhere
+
+These rules were contributed to the project by users and aim to
+enable routine secure access to as many different web sites as
+possible. They are automatically installed together with the
+HTTPS Everywhere software. The presence of these rules does not
+mean that an HTTPS Everywhere user accessed, or intended to
+access, any particular web site.
+
+For information about how to create additional HTTPS Everywhere
+rewriting rules to add support for new sites, please see
+
+https://www.eff.org/https-everywhere/rulesets
+-->
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/ruleset-tests-status.css b/data/extensions/https-everywhere@eff.org/chrome/content/ruleset-tests-status.css
new file mode 100644
index 0000000..30dad18
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/ruleset-tests-status.css
@@ -0,0 +1,14 @@
+#ruleset-tests-status {
+ padding: 20px;
+}
+#wrapper {
+ text-align: center;
+}
+#progess-bar {
+ width: 300px;
+ height: 20px;
+}
+#log {
+ width: 400px;
+ height: 300px;
+}
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/ruleset-tests-status.js b/data/extensions/https-everywhere@eff.org/chrome/content/ruleset-tests-status.js
new file mode 100644
index 0000000..0bee33e
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/ruleset-tests-status.js
@@ -0,0 +1,31 @@
+var HTTPSEverywhere = null;
+
+function updateStatusBar(current_test, total_tests) {
+ var labelText = "Test "+current_test+" of "+total_tests;
+ document.getElementById("progress-bar-label").value = labelText;
+
+ var percent = current_test / total_tests;
+ document.getElementById("progress-bar").value = percent;
+}
+
+function updateLog(msg) {
+ document.getElementById("log").value += msg+'\n';
+}
+
+function cancel() {
+ updateLog("Canceling early ...");
+ HTTPSEverywhere.httpseRulesetTests.cancel = true;
+}
+
+function start() {
+ HTTPSEverywhere = Components.classes["@eff.org/https-everywhere;1"]
+ .getService(Components.interfaces.nsISupports)
+ .wrappedJSObject;
+
+ HTTPSEverywhere.httpseRulesetTests.updateStatusBar = updateStatusBar;
+ HTTPSEverywhere.httpseRulesetTests.updateLog = updateLog;
+ HTTPSEverywhere.httpseRulesetTests.cancel = false;
+
+ updateLog("Starting ruleset tests ...");
+ HTTPSEverywhere.httpseRulesetTests.testRunner();
+}
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/ruleset-tests-status.xul b/data/extensions/https-everywhere@eff.org/chrome/content/ruleset-tests-status.xul
new file mode 100644
index 0000000..0efcd5d
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/ruleset-tests-status.xul
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="ruleset-tests-status.css" type="text/css"?>
+<!DOCTYPE window SYSTEM "chrome://https-everywhere/locale/https-everywhere.dtd">
+<window id="ruleset-tests-status"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ xmlns:html="http://www.w3.org/1999/xhtml"
+ title="&https-everywhere.ruleset-tests.status_title;"
+ >
+
+ <script type="application/x-javascript" src="ruleset-tests-status.js" />
+
+ <commandgroup>
+ <command id="cancel" oncommand="cancel();" />
+ <command id="start" oncommand="start();" />
+ </commandgroup>
+
+ <html:div id="wrapper">
+ <vbox flex="1" style="width:100%">
+ <label id="progress-bar-label" value="Click Start to start the tests"></label>
+
+ <spacer flex="1"/>
+
+ <progressmeter id="progress-bar" mode="determined" value="0" />
+
+ <spacer flex="1"/>
+
+ <textbox id="log" multiline="true" readonly="true" value="" />
+
+ <spacer flex="1"/>
+
+ <button
+ id="cancel-button"
+ label="&https-everywhere.ruleset-tests.status_cancel_button;"
+ command="cancel" />
+
+ <button
+ id="start-button"
+ label="&https-everywhere.ruleset-tests.status_start_button;"
+ command="start" />
+ </vbox>
+ </html:div>
+</window>
+
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/ruleset-tests.js b/data/extensions/https-everywhere@eff.org/chrome/content/ruleset-tests.js
new file mode 100644
index 0000000..1aa94d8
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/ruleset-tests.js
@@ -0,0 +1,155 @@
+// load the HTTPS Everywhere component
+var HTTPSEverywhere = null;
+try {
+ HTTPSEverywhere = Components.classes["@eff.org/https-everywhere;1"]
+ .getService(Components.interfaces.nsISupports)
+ .wrappedJSObject;
+} catch(e) {
+ // HTTPS Everywhere doesn't seem to be installed
+}
+
+// attach testRunner to the HTTPS Everywhere component so that status.js can run it
+if(HTTPSEverywhere) {
+ HTTPSEverywhere.httpseRulesetTests = {
+ testRunner: testRunner
+ };
+}
+
+
+function openStatus() {
+ // make sure mixed content blocking preferences are correct
+ Services.prefs.setBoolPref("security.mixed_content.block_display_content", false);
+ Services.prefs.setBoolPref("security.mixed_content.block_active_content", true);
+
+ // open the status tab
+ var statusTab = gBrowser.addTab('chrome://https-everywhere/content/ruleset-tests-status.xul');
+ gBrowser.selectedTab = statusTab;
+}
+
+function testRunner() {
+ Components.utils.import("resource://gre/modules/PopupNotifications.jsm");
+
+ const numTabs = 6;
+ var finished = false;
+ var output = [];
+ var urls = [];
+ var num = 0;
+
+ for(var target in HTTPSEverywhere.https_rules.targets) {
+ if(!target.indexOf("*") != -1) {
+ urls.push({
+ url: 'https://'+target,
+ target: target,
+ ruleset_names: HTTPSEverywhere.https_rules.targets[target]
+ });
+ }
+ }
+
+ function test() {
+ var i;
+
+ HTTPSEverywhere.httpseRulesetTests.updateStatusBar(num, urls.length);
+
+ // start loading all the tabs
+ window.focus
+ for(i=0; i<numTabs; i++) {
+ newTab(num);
+ }
+ }
+
+ function newTab(number) {
+ num +=1;
+ // start a test in this tab
+ if(urls.length) {
+
+ // open a new tab
+ var tab = gBrowser.addTab(urls[number].url);
+
+ // wait for the page to load
+ var intervalId = window.setTimeout(function(){
+
+ // detect mixed content blocker
+ if(PopupNotifications.getNotification("mixed-content-blocked", gBrowser.getBrowserForTab(tab))) {
+ // build output to log
+ ruleset_xmls = '';
+ for(let i=0; i<urls[number].ruleset_names.length; i++) {
+ ruleset_xmls += urls[number].ruleset_names[i].xmlName + ', ';
+ }
+ if(ruleset_xmls != '')
+ ruleset_xmls = ruleset_xmls.substring(ruleset_xmls.length-2, 2);
+ var output = 'MCB triggered: '+urls[number].url+' ('+ruleset_xmls+')';
+
+ HTTPSEverywhere.httpseRulesetTests.updateLog(output);
+ }
+
+ // close this tab, and open another
+ closeTab(tab);
+
+ }, 10000);
+
+ } else {
+
+ //to run if urls is empty
+ if (!finished) {
+ finished = true;
+ window.setTimeout(function(){
+ gBrowser.removeCurrentTab();
+ }, 10000);
+ }
+ }
+ }
+
+ //closes tab
+ function closeTab(tab) {
+ HTTPSEverywhere.httpseRulesetTests.updateStatusBar(num, urls.length);
+
+ gBrowser.selectedTab = tab;
+ gBrowser.removeCurrentTab();
+
+ // open a new tab, if the tests haven't been canceled
+ if(!HTTPSEverywhere.httpseRulesetTests.cancel) {
+ newTab(num);
+ }
+ }
+
+ //manages write out of output mochilog.txt, which contains sites that trigger mcb
+ function writeout(weburl) {
+
+ //initialize file
+ var file = Components.classes["@mozilla.org/file/directory_service;1"].
+ getService(Components.interfaces.nsIProperties).
+ get("Home", Components.interfaces.nsIFile);
+ writeoutfile = "mochilog.txt";
+ file.append(writeoutfile);
+
+ //create file if it does not already exist
+ if(!file.exists()) {
+ file.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 420);
+ }
+
+ //initialize output stream
+ var stream = Components.classes["@mozilla.org/network/file-output-stream;1"]
+ .createInstance(Components.interfaces.nsIFileOutputStream);
+
+ //permissions are set to append (will not delete existing contents)
+ stream.init(file, 0x02 | 0x08 | 0x10, 0666, 0);
+
+ var content = weburl + "\n";
+
+ //Deal with ascii text and write out
+ var converter = Components.classes["@mozilla.org/intl/converter-output-stream;1"].
+ createInstance(Components.interfaces.nsIConverterOutputStream);
+ converter.init(stream, "UTF-8", 0, 0);
+ converter.writeString(content);
+ converter.close();
+
+ //alternative write out if ascii is not a concern
+ //stream.write(content,content.length);
+ //stream.close();
+
+ }
+ test();
+}
+
+
+
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/toolbar_button.js b/data/extensions/https-everywhere@eff.org/chrome/content/toolbar_button.js
new file mode 100644
index 0000000..0e90a12
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/toolbar_button.js
@@ -0,0 +1,369 @@
+window.addEventListener("load", https_everywhere_load, true);
+window.addEventListener("load", function load(event) {
+ // need to wrap migratePreferences in another callback so that notification
+ // always displays on browser restart
+ window.removeEventListener("load", load, false);
+ gBrowser.addEventListener("DOMContentLoaded", migratePreferences, true);
+}, false);
+
+const CI = Components.interfaces;
+const CC = Components.classes;
+
+// LOG LEVELS ---
+VERB=1;
+DBUG=2;
+INFO=3;
+NOTE=4;
+WARN=5;
+
+HTTPSEverywhere = CC["@eff.org/https-everywhere;1"]
+ .getService(Components.interfaces.nsISupports)
+ .wrappedJSObject;
+
+// avoid polluting global namespace
+// see: https://developer.mozilla.org/en-US/docs/Security_best_practices_in_extensions#Code_wrapping
+if (!httpsEverywhere) { var httpsEverywhere = {}; }
+
+/**
+ * JS Object that acts as a namespace for the toolbar.
+ *
+ * Used to display toolbar hints to new users and change toolbar UI for cases
+ * such as when the toolbar is disabled.
+ */
+httpsEverywhere.toolbarButton = {
+
+ /**
+ * Name of preference for determining whether to show ruleset counter.
+ */
+ COUNTER_PREF: "extensions.https_everywhere.show_counter",
+
+ /**
+ * Used to determine if a hint has been previously shown.
+ * TODO: Probably extraneous, look into removing
+ */
+ hintShown: false,
+
+ /**
+ * Initialize the toolbar button used to hint new users and update UI on
+ * certain events.
+ */
+ init: function() {
+ HTTPSEverywhere.log(DBUG, 'Removing listener for toolbarButton init.');
+ window.removeEventListener('load', httpsEverywhere.toolbarButton.init, false);
+
+ var tb = httpsEverywhere.toolbarButton;
+
+ // make sure icon is proper color during init
+ tb.changeIcon();
+
+ // make sure the checkbox for showing counter is properly set
+ var showCounter = tb.shouldShowCounter();
+ var counterItem = document.getElementById('https-everywhere-counter-item');
+ counterItem.setAttribute('checked', showCounter ? 'true' : 'false');
+
+ // show ruleset counter when a tab is changed
+ tb.updateRulesetsApplied();
+ gBrowser.tabContainer.addEventListener(
+ 'TabSelect',
+ tb.updateRulesetsApplied,
+ false
+ );
+
+ // hook event for when page loads
+ var onPageLoad = function() {
+ // Timeout is used for a number of reasons.
+ // 1) For Performance since we want to defer computation.
+ // 2) Sometimes the page is loaded before all applied rulesets are
+ // calculated; in such a case, a half-second wait works.
+ setTimeout(tb.updateRulesetsApplied, 500);
+ };
+
+ var appcontent = document.getElementById('appcontent');
+ if (appcontent) {
+ appcontent.addEventListener('load', onPageLoad, true);
+ }
+
+ // decide whether to show toolbar hint
+ let hintPref = "extensions.https_everywhere.toolbar_hint_shown";
+ if (!Services.prefs.getPrefType(hintPref)
+ || !Services.prefs.getBoolPref(hintPref)) {
+ // only run once
+ Services.prefs.setBoolPref(hintPref, true);
+ gBrowser.addEventListener("DOMContentLoaded", tb.handleShowHint, true);
+ }
+ },
+
+ /**
+ * Shows toolbar hint if previously not shown.
+ */
+ handleShowHint: function() {
+ var tb = httpsEverywhere.toolbarButton;
+ if (!tb.hintShown){
+ tb.hintShown = true;
+ const faqURL = "https://www.eff.org/https-everywhere/faq";
+ var nBox = gBrowser.getNotificationBox();
+ var strings = document.getElementById('HttpsEverywhereStrings');
+ var msg = strings.getString('https-everywhere.toolbar.hint');
+ var hint = nBox.appendNotification(
+ msg,
+ 'https-everywhere',
+ 'chrome://https-everywhere/skin/https-everywhere-24.png',
+ nBox.PRIORITY_WARNING_MEDIUM,
+ [],
+ function(action) {
+ // see https://developer.mozilla.org/en-US/docs/XUL/Method/appendNotification#Notification_box_events
+ gBrowser.selectedTab = gBrowser.addTab(faqURL);
+ }
+ );
+ }
+ gBrowser.removeEventListener("DOMContentLoaded", tb.handleShowHint, true);
+ },
+
+ /**
+ * Changes HTTPS Everywhere toolbar icon based on whether HTTPS Everywhere
+ * is enabled or disabled.
+ */
+ changeIcon: function() {
+ var enabled = HTTPSEverywhere.prefs.getBoolPref("globalEnabled");
+
+ var toolbarbutton = document.getElementById('https-everywhere-button');
+ if (enabled) {
+ toolbarbutton.setAttribute('status', 'enabled');
+ } else {
+ toolbarbutton.setAttribute('status', 'disabled');
+ }
+ },
+
+ /**
+ * Update the rulesets applied counter for the current tab.
+ */
+ updateRulesetsApplied: function() {
+ var toolbarbutton = document.getElementById('https-everywhere-button');
+ var enabled = HTTPSEverywhere.prefs.getBoolPref("globalEnabled");
+ var showCounter = httpsEverywhere.toolbarButton.shouldShowCounter();
+ if (!enabled || !showCounter) {
+ toolbarbutton.setAttribute('rulesetsApplied', 0);
+ return;
+ }
+
+ var domWin = content.document.defaultView.top;
+ var alist = HTTPSEverywhere.getExpando(domWin,"applicable_rules", null);
+ if (!alist) {
+ return;
+ }
+ // Make sure the list is up to date
+ alist.populate_list();
+
+ var counter = 0;
+ for (var x in alist.active) {
+ if (!(x in alist.breaking)) {
+ ++counter;
+ }
+ }
+ for (var x in alist.moot) {
+ if (!(x in alist.active)) {
+ ++counter;
+ }
+ }
+
+ toolbarbutton.setAttribute('rulesetsApplied', counter);
+ HTTPSEverywhere.log(INFO, 'Setting icon counter to: ' + counter);
+ },
+
+ /**
+ * Gets whether to show the rulesets applied counter.
+ *
+ * @return {boolean}
+ */
+ shouldShowCounter: function() {
+ var tb = httpsEverywhere.toolbarButton;
+ var sp = Services.prefs;
+
+ var prefExists = sp.getPrefType(tb.COUNTER_PREF);
+
+ // the default behavior is to show the rulesets applied counter.
+ // if no preference exists (default) or its enabled, show the counter
+ return !prefExists || sp.getBoolPref(tb.COUNTER_PREF);
+ },
+
+ /**
+ * Toggles the user's preference for displaying the rulesets applied counter
+ * and updates the UI.
+ */
+ toggleShowCounter: function() {
+ var tb = httpsEverywhere.toolbarButton;
+ var sp = Services.prefs;
+
+ var showCounter = tb.shouldShowCounter();
+ sp.setBoolPref(tb.COUNTER_PREF, !showCounter);
+
+ tb.updateRulesetsApplied();
+ }
+
+};
+
+function https_everywhere_load() {
+ window.removeEventListener('load', https_everywhere_load, true);
+ // on first run, put the context menu in the addons bar
+ try {
+ var first_run;
+ try {
+ first_run = Services.prefs.getBoolPref("extensions.https_everywhere.firstrun_context_menu");
+ } catch(e) {
+ Services.prefs.setBoolPref("extensions.https_everywhere.firstrun_context_menu", true);
+ first_run = true;
+ }
+ if(first_run) {
+ Services.prefs.setBoolPref("extensions.https_everywhere.firstrun_context_menu", false);
+ var navbar = document.getElementById("nav-bar");
+ if(navbar.currentSet.indexOf("https-everywhere-button") == -1) {
+ var set = navbar.currentSet+',https-everywhere-button';
+ navbar.setAttribute('currentset', set);
+ navbar.currentSet = set;
+ document.persist('nav-bar', 'currentset');
+ }
+ }
+ } catch(e) { }
+}
+
+function stitch_context_menu() {
+ // the same menu appears both under Tools and via the toolbar button:
+ var menu = document.getElementById("https-everywhere-menu");
+ if (!menu.firstChild) {
+ var popup = document.getElementById("https-everywhere-context");
+ menu.appendChild(popup.cloneNode(true));
+ }
+}
+function stitch_context_menu2() {
+ // the same menu appears both under Tools and via the toolbar button:
+ var menu = document.getElementById("https-everywhere-menu2");
+ if (!menu.firstChild) {
+ var popup = document.getElementById("https-everywhere-context");
+ menu.appendChild(popup.cloneNode(true));
+ }
+}
+
+var rulesetTestsMenuItem = null;
+
+function show_applicable_list(menupopup) {
+ var domWin = content.document.defaultView.top;
+ if (!(domWin instanceof CI.nsIDOMWindow)) {
+ alert(domWin + " is not an nsIDOMWindow");
+ return null;
+ }
+
+ var alist = HTTPSEverywhere.getExpando(domWin,"applicable_rules", null);
+ var weird=false;
+
+ if (!alist) {
+ // This case occurs for error pages and similar. We need a dummy alist
+ // because populate_menu lives in there. Would be good to refactor this
+ // away.
+ alist = new HTTPSEverywhere.ApplicableList(HTTPSEverywhere.log, document, domWin);
+ weird = true;
+ }
+ alist.populate_menu(document, menupopup, weird);
+
+ // should we also show the ruleset tests menu item?
+ if(HTTPSEverywhere.prefs.getBoolPref("show_ruleset_tests")) {
+
+ if(!rulesetTestsMenuItem) {
+ let strings = document.getElementById('HttpsEverywhereStrings');
+ let label = strings.getString('https-everywhere.menu.ruleset-tests');
+
+ rulesetTestsMenuItem = this.document.createElement('menuitem');
+ rulesetTestsMenuItem.setAttribute('command', 'https-everywhere-menuitem-ruleset-tests');
+ rulesetTestsMenuItem.setAttribute('label', label);
+ }
+
+ if(!menupopup.contains(rulesetTestsMenuItem))
+ menupopup.appendChild(rulesetTestsMenuItem);
+ }
+
+}
+
+function toggle_rule(rule_id) {
+ // toggle the rule state
+ HTTPSEverywhere.https_rules.rulesetsByID[rule_id].toggle();
+ var domWin = content.document.defaultView.top;
+ /*if (domWin instanceof CI.nsIDOMWindow) {
+ var alist = HTTPSEverywhere.getExpando(domWin,"applicable_rules", null);
+ if (alist) alist.empty();
+ }*/
+ reload_window();
+}
+
+function reload_window() {
+ var domWin = content.document.defaultView.top;
+ if (!(domWin instanceof CI.nsIDOMWindow)) {
+ HTTPSEverywhere.log(WARN, domWin + " is not an nsIDOMWindow");
+ return null;
+ }
+ try {
+ var webNav = domWin.QueryInterface(CI.nsIInterfaceRequestor)
+ .getInterface(CI.nsIWebNavigation)
+ .QueryInterface(CI.nsIDocShell);
+ } catch(e) {
+ HTTPSEverywhere.log(WARN,"failed to get webNav");
+ return null;
+ }
+ // This choice of flags comes from NoScript's quickReload function; not sure
+ // if it's optimal
+ webNav.reload(webNav.LOAD_FLAGS_CHARSET_CHANGE);
+}
+
+function toggleEnabledState(){
+ HTTPSEverywhere.toggleEnabledState();
+ reload_window();
+
+ // Change icon depending on enabled state
+ httpsEverywhere.toolbarButton.changeIcon();
+}
+
+function open_in_tab(url) {
+ var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Components.interfaces.nsIWindowMediator);
+ var recentWindow = wm.getMostRecentWindow("navigator:browser");
+ recentWindow.delayedOpenTab(url, null, null, null, null);
+}
+
+// hook event for showing hint
+HTTPSEverywhere.log(DBUG, 'Adding listener for toolbarButton init.');
+window.addEventListener("load", httpsEverywhere.toolbarButton.init, false);
+
+function migratePreferences() {
+ gBrowser.removeEventListener("DOMContentLoaded", migratePreferences, true);
+ let prefs_version = HTTPSEverywhere.prefs.getIntPref("prefs_version");
+
+ // first migration loses saved prefs
+ if(prefs_version == 0) {
+ try {
+ // upgrades will have old rules as preferences, such as the EFF rule
+ let upgrade = false;
+ let childList = HTTPSEverywhere.prefs.getChildList("", {});
+ for(let i=0; i<childList.length; i++) {
+ if(childList[i] == 'EFF') {
+ upgrade = true;
+ break;
+ }
+ }
+
+ if(upgrade) {
+ let nBox = gBrowser.getNotificationBox();
+ let strings = document.getElementById('HttpsEverywhereStrings');
+ let msg = strings.getString('https-everywhere.migration.notification0');
+ nBox.appendNotification(
+ msg,
+ 'https-everywhere-migration0',
+ 'chrome://https-everywhere/skin/https-everywhere-24.png',
+ nBox.PRIORITY_WARNING_MEDIUM
+ );
+ }
+ } catch(e) {
+ HTTPSEverywhere.log(WARN, "Migration from prefs_version 0 error: "+e);
+ }
+
+ HTTPSEverywhere.prefs.setIntPref("prefs_version", prefs_version+1);
+ }
+}
+
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/toolbar_button.xul b/data/extensions/https-everywhere@eff.org/chrome/content/toolbar_button.xul
new file mode 100644
index 0000000..c3cbed0
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/toolbar_button.xul
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://https-everywhere/skin/https-everywhere.css" type="text/css"?>
+
+<!DOCTYPE overlay SYSTEM "chrome://https-everywhere/locale/https-everywhere.dtd">
+
+<!-- helpful docs at
+ https://developer.mozilla.org/en/XUL/PopupGuide/PopupEvents -->
+
+<overlay id="https-everywhere-button-overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script type="application/x-javascript" src="chrome://https-everywhere/content/toolbar_button.js"/>
+ <script type="application/x-javascript" src="chrome://https-everywhere/content/ruleset-tests.js"/>
+
+ <stringbundleset id="stringbundleset">
+ <stringbundle id="HttpsEverywhereStrings"
+ src="chrome://https-everywhere/locale/https-everywhere.properties" />
+ </stringbundleset>
+
+ <!-- this works in Firefox, we need a Seamonkey version too... -->
+ <menupopup id="menu_ToolsPopup" onpopupshowing="stitch_context_menu()">
+ <menu id="https-everywhere-menu" label="&https-everywhere.about.ext_name;">
+ <!-- "https-everywhere-context" below gets .cloneNode()ed in here -->
+ </menu>
+ </menupopup>
+
+ <menupopup id="toolsPopup" onpopupshowing="stitch_context_menu2()">
+ <menu id="https-everywhere-menu2" label="&https-everywhere.about.ext_name;">
+ <!-- "https-everywhere-context" below gets .cloneNode()ed in here -->
+ </menu>
+ </menupopup>
+
+ <toolbarpalette id="BrowserToolbarPalette">
+ <toolbarbutton
+ id="https-everywhere-button"
+ tooltiptext="&https-everywhere.about.ext_name;"
+ label="HTTPS"
+ context="https-everywhere-context-menu"
+ oncontextmenu="this.open = true;"
+ oncommand="this.open = true;"
+ buttonstyle="pictures"
+ type="menu"
+ rulesetsApplied="0">
+
+ <menupopup id="https-everywhere-context" onpopupshowing="show_applicable_list(this)">
+ <!-- entries will be written here by ApplicableList.populate_menu() -->
+ <menuseparator />
+ <menuitem type="checkbox" id="https-everywhere-counter-item" label="&https-everywhere.menu.showCounter;"
+ oncommand="httpsEverywhere.toolbarButton.toggleShowCounter()" />
+ <menuseparator />
+ <menuitem label="&https-everywhere.menu.observatory;" command="https-everywhere-menuitem-observatory" />
+ <menuitem label="&https-everywhere.menu.about;" command="https-everywhere-menuitem-about" />
+ </menupopup>
+ </toolbarbutton>
+ </toolbarpalette>
+ <commandset>
+ <command id="https-everywhere-menuitem-globalEnableToggle"
+ oncommand="toggleEnabledState();" />
+ <command id="https-everywhere-menuitem-preferences"
+ oncommand="HTTPSEverywhere.chrome_opener('chrome://https-everywhere/content/preferences.xul', 'chrome,centerscreen,resizable=yes');" />
+ <command id="https-everywhere-menuitem-about"
+ oncommand="HTTPSEverywhere.chrome_opener('chrome://https-everywhere/content/about.xul');" />
+ <command id="https-everywhere-menuitem-observatory"
+ oncommand="HTTPSEverywhere.chrome_opener('chrome://https-everywhere/content/observatory-preferences.xul', 'chrome,centerscreen,resizable=yes');" />
+ <command id="https-everywhere-menuitem-donate-eff"
+ oncommand="open_in_tab('https://www.eff.org/donate');" />
+ <command id="https-everywhere-menuitem-donate-tor"
+ oncommand="open_in_tab('https://www.torproject.org/donate');" />
+ <command id="https-everywhere-menuitem-ruleset-tests"
+ oncommand="openStatus();" />
+ </commandset>
+</overlay>
+
diff --git a/data/extensions/https-everywhere@eff.org/chrome/content/toolbar_button_binding.xml b/data/extensions/https-everywhere@eff.org/chrome/content/toolbar_button_binding.xml
new file mode 100644
index 0000000..1981b3a
--- /dev/null
+++ b/data/extensions/https-everywhere@eff.org/chrome/content/toolbar_button_binding.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+<!--
+Toolbar button needs to be extended to show a counter for the number of
+rulesets applied, and this can be done using XBL.
+
+See: https://developer.mozilla.org/en-US/docs/XBL
+-->
+<bindings xmlns="http://www.mozilla.org/xbl"
+ xmlns:xbl="http://www.mozilla.org/xbl"
+ xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <binding id="https-everywhere-binding">
+ <content>
+ <!-- ruleset counter (rscounter) and rulesets applied (rsapplied) -->
+ <xul:stack id="rscounter">
+ <xul:label id="rsapplied" xbl:inherits="value=rulesetsApplied" />
+ </xul:stack>
+
+ <!--
+ Https everywhere toolbar button is already defined; just use its settings.
+ TODO: Look into any issues with oncommand/oncontext.
+ -->
+ <xul:toolbarbutton
+ class="https-everywhere-button toolbarbutton-1 chromeclass-toolbar-additional"
+ flex="1"
+ allowevents="true"
+ xbl:inherits="type,crop,image,label,accesskey,command,align,dir,pack,orient,wrap">
+
+ <children includes="menupopup" />
+ </xul:toolbarbutton>
+ </content>
+ </binding>
+</bindings>