summaryrefslogtreecommitdiff
path: root/data/extensions/https-everywhere-eff@eff.org/chrome/content
diff options
context:
space:
mode:
Diffstat (limited to 'data/extensions/https-everywhere-eff@eff.org/chrome/content')
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/about.js14
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/about.xul72
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/code/AndroidUI.jsm236
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/code/ApplicableList.js269
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/code/ChannelReplacement.js389
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/code/Cookie.js150
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/code/HTTPS.js318
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/code/HTTPSRules.js776
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/code/IOUtil.js265
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/code/NSS.js496
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/code/Root-CAs.js348
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/code/Thread.js100
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/code/X509ChainWhitelist.js1007
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/code/commonOCSP.json289
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/code/sha256.js249
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/fetch-source.js161
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/fetch-source.xul29
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/meta-preferences.xul30
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/observatory-popup.xul61
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/observatory-preferences.xul114
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/observatory-warning.xul49
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/observatory-xul.js201
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/preferences.css11
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/preferences.js278
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/preferences.xul62
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/ruleset-tests-status.css14
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/ruleset-tests-status.js31
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/ruleset-tests-status.xul44
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/ruleset-tests.js189
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/toolbar_button.js433
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/toolbar_button.xul82
-rw-r--r--data/extensions/https-everywhere-eff@eff.org/chrome/content/toolbar_button_binding.xml33
32 files changed, 6800 insertions, 0 deletions
diff --git a/data/extensions/https-everywhere-eff@eff.org/chrome/content/about.js b/data/extensions/https-everywhere-eff@eff.org/chrome/content/about.js
new file mode 100644
index 0000000..7a37815
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@eff.org/chrome/content/about.js
@@ -0,0 +1,14 @@
+const CC = Components.classes;
+
+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);
+}
diff --git a/data/extensions/https-everywhere-eff@eff.org/chrome/content/about.xul b/data/extensions/https-everywhere-eff@eff.org/chrome/content/about.xul
new file mode 100644
index 0000000..e788261
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@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/about.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>
+
+ <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')"/>
+ &https-everywhere.about.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>
+
+ <groupbox>
+ <caption label="&https-everywhere.about.version;" />
+ <label>5.1.1</label>
+ </groupbox>
+
+ <groupbox>
+ <caption label="&https-everywhere.about.created_by;" />
+ <label>Mike Perry, Peter Eckersley, and Yan Zhu</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>
+ </vbox>
+</dialog>
diff --git a/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/AndroidUI.jsm b/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/AndroidUI.jsm
new file mode 100644
index 0000000..1a4936d
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/AndroidUI.jsm
@@ -0,0 +1,236 @@
+const CC = Components.classes;
+const CI = Components.interfaces;
+const CU = Components.utils;
+
+var HTTPSEverywhere = CC["@eff.org/https-everywhere;1"]
+ .getService(CI.nsISupports).wrappedJSObject;
+
+CU.import("resource://gre/modules/Prompt.jsm");
+
+var menuId;
+var urlbarId;
+var aWindow = getWindow();
+
+
+/*
+ * Setup/Teardown for the UI
+ */
+
+function loadIntoWindow() {
+ if (!aWindow) {
+ return;
+ }
+ var enabled = HTTPSEverywhere.prefs.getBoolPref("globalEnabled");
+ addToggleItemToMenu(enabled);
+ if (enabled) {
+ urlbarId = aWindow.NativeWindow.pageactions.add(urlbarOptions);
+ } else if (urlbarId) {
+ aWindow.NativeWindow.pageactions.remove(urlbarId);
+ }
+
+ // When navigating away from a page, we want to clear the applicable list for
+ // that page. There are a few different APIs to do this, but this is the one
+ // that work on mobile. We trigger on pagehide rather than pageshow because we
+ // want to capture subresources during load.
+ var BrowserApp = aWindow.BrowserApp;
+ BrowserApp.deck.addEventListener("pagehide", function(evt) {
+ var browser = BrowserApp.getBrowserForDocument(evt.target);
+ HTTPSEverywhere.resetApplicableList(browser);
+ }, true);
+}
+
+function unloadFromWindow() {
+ if (!aWindow) {
+ return;
+ }
+ aWindow.NativeWindow.menu.remove(menuId);
+ aWindow.NativeWindow.pageactions.remove(urlbarId);
+}
+
+
+/*
+ * Add a menu item to toggle HTTPS Everywhere
+ */
+
+function addToggleItemToMenu(enabled) {
+ if (menuId) { aWindow.NativeWindow.menu.remove(menuId); }
+ var menuLabel = enabled ? "HTTPS Everywhere on" : "HTTPS Everywhere off";
+ menuId = aWindow.NativeWindow.menu.add(menuLabel, null, function() {
+ popupToggleMenu(aWindow, enabled);
+ });
+}
+
+function popupToggleMenu(aWindow, enabled) {
+ var buttons = [
+ {
+ label: "Yes",
+ callback: function() {
+ toggleEnabledState();
+ var msg = enabled ? "HTTPS Everywhere disabled!" : "HTTPS Everywhere enabled!";
+ aWindow.NativeWindow.toast.show(msg, "short");
+ return true;
+ }
+ }, {
+ label: "No",
+ callback: function() { return false; }
+ }
+ ];
+ var newState = enabled ? "off?" : "on?";
+ aWindow.NativeWindow.doorhanger.show("Would you like to turn HTTPS Everywhere "+newState,
+ "doorhanger-toggle", buttons);
+}
+
+
+/*
+ * The HTTPS Everywhere icon in the URL bar shows a popup of rules that the
+ * user can activate/deactivate. On long click, reset all rules to defaults.
+ */
+
+var popupInfo = {
+ rules: [],
+ ruleItems: [],
+ ruleStatus: [],
+ alist: null,
+ getApplicableList: function() {
+ var browser = aWindow.BrowserApp.selectedBrowser;
+ return HTTPSEverywhere.getApplicableListForBrowser(browser);
+ },
+ fill: function() {
+ this.clear();
+ this.alist = this.getApplicableList();
+ HTTPSEverywhere.log(4,"applicable list active: "+JSON.stringify(this.alist.active));
+ HTTPSEverywhere.log(4,"applicable list inactive: "+JSON.stringify(this.alist.inactive));
+ for (var rule in this.alist.all) {
+ if (this.alist.active.hasOwnProperty(rule)) {
+ // active rules are checked and toggleable
+ this.ruleItems.push({ label: rule, selected: true });
+ this.ruleStatus.push(true);
+ this.rules.push(this.alist.active[rule]);
+ } else if (this.alist.moot.hasOwnProperty(rule)) {
+ // moot rules are checked and toggleable too
+ this.ruleItems.push({ label: rule, selected: true });
+ this.ruleStatus.push(true);
+ this.rules.push(this.alist.moot[rule]);
+ } else if (this.alist.inactive.hasOwnProperty(rule)) {
+ // inactive rules are unchecked and toggleable
+ this.ruleItems.push({ label: rule });
+ this.ruleStatus.push(false);
+ this.rules.push(this.alist.inactive[rule]);
+ } else if (this.alist.breaking.hasOwnProperty(rule)) {
+ // breaking rules are get a unicode clockwise arrow next to them
+ var ruleLabel = "\u21B7"+rule;
+ var isSelected = this.alist.breaking[rule].active;
+ this.ruleItems.push({ label: ruleLabel, selected: isSelected });
+ this.ruleStatus.push(isSelected);
+ this.rules.push(this.alist.breaking[rule]);
+ }
+ }
+ },
+ clear: function() {
+ this.rules = [];
+ this.ruleItems = [];
+ this.ruleStatus = [];
+ this.alist = {};
+ }
+};
+
+var urlbarOptions = {
+
+ title: "HTTPS Everywhere",
+
+ icon: "chrome://https-everywhere/skin/https-everywhere-128.png",
+
+ clickCallback: function() {
+ popupInfo.fill();
+ rulesPrompt.setMultiChoiceItems(popupInfo.ruleItems);
+ rulesPrompt.show(function(data) {
+ var db = data.button;
+ if (db === -1) { return null; } // user didn't click the accept button
+ if (popupInfo.rules.length !== db.length) {
+ // Why does db sometimes have an extra entry that doesn't correspond
+ // to any of the ruleItems? No idea, but let's log it.
+ HTTPSEverywhere.log(5,"Got length mismatch between popupInfo.ruleItems and data.button");
+ HTTPSEverywhere.log(4,"Applicable rules: "+JSON.stringify(popupInfo.rules));
+ HTTPSEverywhere.log(4, "data.button: "+JSON.stringify(db));
+ }
+ for (var i=0; i<popupInfo.rules.length; i++) {
+ if (popupInfo.ruleStatus[i] !== db[i]) {
+ HTTPSEverywhere.log(4, "toggling: "+JSON.stringify(popupInfo.rules[i]));
+ popupInfo.rules[i].toggle();
+ }
+ }
+ reloadTab();
+ return null;
+ });
+ },
+
+ longClickCallback: function() { popupResetDefaultsMenu(aWindow); }
+};
+
+var rulesPrompt = new Prompt({
+ window: aWindow,
+ title: "Enable/disable rules",
+ buttons: ["Apply changes"]
+});
+
+function popupResetDefaultsMenu(aWindow) {
+ var buttons = [
+ {
+ label: "Yes",
+ callback: function() {
+ resetToDefaults();
+ var msg = "Default rules reset.";
+ aWindow.NativeWindow.toast.show(msg, "short");
+ return true;
+ }
+ }, {
+ label: "No",
+ callback: function() { return false; }
+ }
+ ];
+ aWindow.NativeWindow.doorhanger.show("Reset all HTTPS Everywhere rules to defaults?",
+ "doorhanger-reset", buttons);
+}
+
+
+/*
+ * Some useful utils
+ */
+
+function reloadTab() {
+ // There seems to be no API to do this directly?
+ aWindow.BrowserApp.selectedTab.window.location.reload();
+}
+
+function toggleEnabledState(){
+ HTTPSEverywhere.toggleEnabledState();
+ loadIntoWindow();
+ reloadTab();
+}
+
+function resetToDefaults() {
+ HTTPSEverywhere.https_rules.resetRulesetsToDefaults();
+ reloadTab();
+}
+
+function getWindow() {
+ return CC['@mozilla.org/appshell/window-mediator;1']
+ .getService(CI.nsIWindowMediator)
+ .getMostRecentWindow('navigator:browser');
+}
+
+
+/*
+ * Here's the external API to this UI module
+ */
+
+var AndroidUI = {
+ init: function() {
+ loadIntoWindow();
+ },
+ shutdown: function() {
+ unloadFromWindow();
+ }
+};
+
+var EXPORTED_SYMBOLS = ["AndroidUI"];
diff --git a/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/ApplicableList.js b/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/ApplicableList.js
new file mode 100644
index 0000000..11b9c42
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/ApplicableList.js
@@ -0,0 +1,269 @@
+// 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)
+
+var serial_number = 0;
+
+function ApplicableList(logger, uri) {
+ this.log = logger;
+ this.uri = uri.clone();
+ if (!this.uri) {
+ this.log(WARN,"NULL CLONING URI " + doc);
+ if (uri) {
+ this.log(WARN,"NULL CLONING URI " + uri.spec);
+ }
+ }
+ this.home = uri.spec; // what doc we're housekeeping for
+ 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.uri.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.uri.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.uri.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;
+ }
+ // This label just describes the fact that the items underneath it enable
+ // and disable rules.
+ var label = document.createElement('menuitem');
+ label.setAttribute('label', strings.getString('https-everywhere.menu.enableDisable'));
+ label.setAttribute('disabled', 'true');
+ label.setAttribute('class', 'menuitem-non-iconic');
+ label.setAttribute('style', 'color:#000000;');
+ 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 browser = wm.getMostRecentWindow("navigator:browser").gBrowser.selectedBrowser;
+ var location = browser.currentURI.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.getElementById("https-everywhere-menuitem-rule-toggle-template").cloneNode();
+ command.setAttribute('id', JSON.stringify(rule.id)+'-command');
+ command.setAttribute('data-id', JSON.stringify(rule.id));
+ command.setAttribute('label', rule.name);
+ 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('type', 'checkbox');
+ 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@eff.org/chrome/content/code/ChannelReplacement.js b/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/ChannelReplacement.js
new file mode 100644
index 0000000..ca70939
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/ChannelReplacement.js
@@ -0,0 +1,389 @@
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+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: XPCOMUtils.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: XPCOMUtils.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: XPCOMUtils.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: XPCOMUtils.generateQI([Ci.nsISimpleEnumerator]),
+ getNext: function() { return null; },
+ hasMoreElements: function() { return false; }
+ }
+};
diff --git a/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/Cookie.js b/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/Cookie.js
new file mode 100644
index 0000000..f9134bc
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/Cookie.js
@@ -0,0 +1,150 @@
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+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: XPCOMUtils.generateQI([Ci.nsICookie, Ci.nsICookie2])
+
+};
diff --git a/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/HTTPS.js b/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/HTTPS.js
new file mode 100644
index 0000000..c5834dd
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/HTTPS.js
@@ -0,0 +1,318 @@
+INCLUDE('Cookie');
+
+var securityService = CC['@mozilla.org/ssservice;1']
+ .getService(CI.nsISiteSecurityService);
+
+// 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,
+
+ /**
+ * Given a channel and a list of potentially applicable rules,
+ * redirect or abort a request if appropriate.
+ *
+ * @param {RuleSet[]} applicable_list A list of potentially applicable rules
+ * (i.e. those that match on a hostname basis).
+ * @param {nsIChannel} channel The channel to be manipulated.
+ * @param {boolean} httpNowhereEnabled Whether to abort non-https requests.
+ * @returns {boolean} True if the request was redirected; false if it was
+ * untouched or aborted.
+ */
+ replaceChannel: function(applicable_list, channel, httpNowhereEnabled) {
+ var blob = HTTPSRules.rewrittenURI(applicable_list, channel.URI.clone());
+ var isSTS = securityService.isSecureURI(
+ CI.nsISiteSecurityService.HEADER_HSTS, channel.URI, 0);
+ if (blob === null) {
+ // Abort insecure requests if HTTP Nowhere is on
+ if (httpNowhereEnabled && channel.URI.schemeIs("http") && !isSTS) {
+ IOUtil.abort(channel);
+ }
+ return false; // no rewrite
+ }
+ var uri = blob.newuri;
+ if (!uri) this.log(WARN, "OH NO BAD ARGH\nARGH");
+
+ // Abort downgrading if HTTP Nowhere is on
+ if (httpNowhereEnabled && uri.schemeIs("http")) {
+ IOUtil.abort(channel);
+ }
+
+ 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;
+ if (httpNowhereEnabled && channel.URI.schemeIs("http")) {
+ IOUtil.abort(channel);
+ }
+ 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);
+ }
+ 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.host + " " + 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@eff.org/chrome/content/code/HTTPSRules.js b/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/HTTPSRules.js
new file mode 100644
index 0000000..f100a79
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/HTTPSRules.js
@@ -0,0 +1,776 @@
+// 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) {
+ // we rewrote the uri
+ this.log(DBUG, "Rewrote " + urispec + " -> " + returl + " using " + this.xmlName + ": " + this.rules[i].from_c + " -> " + this.rules[i].to);
+ 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) {
+ if (!file.exists())
+ return 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 data;
+ },
+
+ write: function(file, data) {
+ //if (!file.exists())
+ // return null;
+ this.log(DBUG, "Opening " + file.path + " for writing");
+ var fstream = CC["@mozilla.org/network/file-output-stream;1"]
+ .createInstance(CI.nsIFileOutputStream);
+ fstream.init(file, -1, -1, 0);
+
+ var retval = fstream.write(data, data.length);
+ this.log(DBUG, "Got retval " + retval);
+ fstream.close();
+ return data;
+ },
+
+ rulesetFromFile: function(file, rule_store, ruleset_id) {
+ if ((rule_store.targets == null) && (rule_store.targets != {}))
+ this.log(WARN, "TARGETS IS NULL");
+ var data = this.read(file);
+ if (!data) return null;
+ 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");
+
+ 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.rulesetFromFile(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(DBUG, "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) {
+ 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]);
+ },
+
+ // 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.queryForRuleset.params.id = ruleset_id;
+
+ try {
+ if (this.queryForRuleset.executeStep()) {
+ 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(DBUG, "For target " + target + ", found no ids in DB");
+ }
+ return output;
+ },
+
+ /**
+ * Return a list of rulesets that declare targets matching a given hostname.
+ * The returned rulesets include those that are disabled for various reasons.
+ * This function is only defined for fully-qualified hostnames. Wildcards and
+ * cookie-style domain attributes with a leading dot are not permitted.
+ * @param host {string}
+ * @return {Array.<RuleSet>}
+ */
+ potentiallyApplicableRulesets: function(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];
+ if (tmp.length === 0) {
+ this.log(WARN,"Malformed host passed to potentiallyApplicableRulesets: " + host);
+ return null;
+ }
+ 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;
+ },
+
+ /**
+ * If a cookie's domain attribute has a leading dot to indicate it should be
+ * sent for all subdomains (".example.com"), return the actual host part (the
+ * part after the dot).
+ *
+ * @param cookieDomain {string} A cookie domain to strip a leading dot from.
+ * @return {string} a fully qualified hostname.
+ */
+ hostFromCookieDomain: function(cookieDomain) {
+ if (cookieDomain.length > 0 && cookieDomain[0] == ".") {
+ return cookieDomain.slice(1);
+ } else {
+ return cookieDomain;
+ }
+ },
+
+ /**
+ * Check to see if the Cookie object c meets any of our cookierule citeria
+ * for being marked as secure.
+ *
+ * @param applicable_list {ApplicableList} an ApplicableList for record keeping
+ * @param c {nsICookie2} The cookie we might secure.
+ * @param known_https {boolean} True if the cookie appeared in an HTTPS request and
+ * so we know it is okay to mark it secure (assuming a cookierule matches it.
+ * TODO(jsha): Double-check that the code calling this actually does that.
+ * @return {boolean} True if the cookie in question should have the 'secure'
+ * flag set to true.
+ */
+ shouldSecureCookie: function(applicable_list, c, known_https) {
+ this.log(DBUG," rawhost: " + c.rawHost + " name: " + c.name + " host" + c.host);
+ var i,j;
+ // potentiallyApplicableRulesets is defined on hostnames not cookie-style
+ // "domain" attributes, so we strip a leading dot before calling.
+ var rs = this.potentiallyApplicableRulesets(this.hostFromCookieDomain(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 && 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;
+ },
+
+ /**
+ * 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. In particular, if cookies are set from Javascript (as
+ * opposed to HTTP/HTTPS responses), we don't know what page context that
+ * Javascript ran in.
+
+ * 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.
+ *
+ * @param domain {string} The cookie's 'domain' attribute.
+ * @return {boolean} True if it's safe to secure a cookie on that domain.
+ */
+ safeToSecureCookie: function(domain) {
+ 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(DBUG, "Testing securecookie applicability with " + test_uri);
+ // potentiallyApplicableRulesets is defined on hostnames not cookie-style
+ // "domain" attributes, so we strip a leading dot before calling.
+ var rs = this.potentiallyApplicableRulesets(this.hostFromCookieDomain(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(DBUG, "Safe to secure cookie for " + test_uri + ": " + rewrite);
+ return true;
+ }
+ }
+ this.log(DBUG, "Unsafe to secure cookie for " + test_uri);
+ return false;
+ }
+};
diff --git a/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/IOUtil.js b/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/IOUtil.js
new file mode 100644
index 0000000..f3a5bee
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/IOUtil.js
@@ -0,0 +1,265 @@
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+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: XPCOMUtils.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(Components.results.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@eff.org/chrome/content/code/NSS.js b/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/NSS.js
new file mode 100644
index 0000000..878b90f
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/NSS.js
@@ -0,0 +1,496 @@
+// 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() {
+
+}
+
+// Alias to reduce the number of spurious warnings from amo-validator.
+let tcypes = ctypes;
+
+NSS.initialize = function(nssPath) {
+ var sharedLib;
+
+ try {
+ sharedLib = tcypes.open(nssPath);
+ } catch (e) {
+ Components.utils.import("resource://gre/modules/Services.jsm");
+ var nssFile = Services.dirsvc.get("GreD", Ci.nsILocalFile);
+ nssFile.append(tcypes.libraryName("nss3"));
+ sharedLib = tcypes.open(nssFile.path);
+ }
+
+ NSS.types = new Object();
+
+ NSS.types.CERTDistNames = tcypes.StructType("CERTDistNames");
+
+ NSS.types.SECItem = tcypes.StructType("SECItem",
+ [{'type' : tcypes.int},
+ {'data' : tcypes.unsigned_char.ptr},
+ {'len' : tcypes.uint32_t}]);
+
+ NSS.types.PLArenaPool = tcypes.StructType("PLArenaPool");
+
+ NSS.types.CERTCertificateList = tcypes.StructType("CERTCertificateList",
+ [{'certs' : NSS.types.SECItem.ptr},
+ {'len' : tcypes.int},
+ {'arena' : NSS.types.PLArenaPool.ptr}]),
+
+ NSS.types.CERTAVA = tcypes.StructType("CERTAVA",
+ [{'type' : NSS.types.SECItem},
+ {'value' : NSS.types.SECItem}]);
+
+ NSS.types.CERTRDN = tcypes.StructType("CERTRDN",
+ [{'avas' : NSS.types.CERTAVA.ptr.ptr}]);
+
+ NSS.types.SECAlgorithmID = tcypes.StructType("SECAlgorithmID",
+ [{'algorithm' : NSS.types.SECItem},
+ {'parameters' : NSS.types.SECItem}]);
+
+ NSS.types.CERTSignedData = tcypes.StructType("CERTSignedData",
+ [{'data' : NSS.types.SECItem},
+ {'signatureAlgorithm' : NSS.types.SECAlgorithmID},
+ {'signature' : NSS.types.SECItem}]);
+
+ NSS.types.CERTOKDomainName = tcypes.StructType("CERTOKDomainName");
+
+ NSS.types.NSSCertificateStr = tcypes.StructType("NSSCertificateStr");
+
+ NSS.types.CERTAuthKeyID = tcypes.StructType("CERTAuthKeyID");
+
+ NSS.types.CERTName = tcypes.StructType("CERTName",
+ [{'arena' : tcypes.voidptr_t},
+ {'rdns' : NSS.types.CERTRDN.ptr.ptr}]);
+
+ NSS.types.CERTValidity = tcypes.StructType("CERTValidity",
+ [{'arena' : tcypes.voidptr_t},
+ {'notBefore' : NSS.types.SECItem},
+ {'notAfter' : NSS.types.SECItem}]);
+
+ NSS.types.CERTCertExtension = tcypes.StructType("CERTCertExtension",
+ [{'id' : NSS.types.SECItem},
+ {'critical' : NSS.types.SECItem},
+ {'value' : NSS.types.SECItem}]);
+
+ NSS.types.CERTCertDBHandle = tcypes.StructType("CERTCertDBHandle");
+
+ NSS.types.PK11SlotInfo = tcypes.StructType("PK11SlotInfo");
+
+ NSS.types.PK11SlotListElement = tcypes.StructType("PK11SlotListElement",
+ [{'next' : tcypes.StructType("PK11SlotListElement").ptr},
+ {'prev' : tcypes.StructType("PK11SlotListElement").ptr},
+ {'slot' : NSS.types.PK11SlotInfo.ptr},
+ {'refCount' : tcypes.int}]),
+
+ NSS.types.PK11SlotList = tcypes.StructType("PK11SlotList",
+ [{'head' : NSS.types.PK11SlotListElement.ptr},
+ {'tail' : NSS.types.PK11SlotListElement.ptr},
+ {'lock' : tcypes.StructType("PZLock").ptr}]),
+
+ NSS.types.SECKEYPrivateKey = tcypes.StructType("SECKEYPrivateKey",
+ [{'arena' : NSS.types.PLArenaPool.ptr},
+ {'keyType' : tcypes.int},
+ {'pkcs11Slot' : NSS.types.PK11SlotInfo.ptr},
+ {'pkcs11ID' : tcypes.unsigned_long},
+ {'pkcs11IsTemp' : tcypes.int},
+ {'wincx' : tcypes.voidptr_t},
+ {'staticflags' : tcypes.int32_t}]);
+
+ NSS.types.SECKEYPublicKey = tcypes.StructType("SECKEYPublicKey");
+
+ NSS.types.CERTSubjectPublicKeyInfo = tcypes.StructType("CERTSubjectPublicKeyInfo",
+ [{'arena' : NSS.types.PLArenaPool.ptr},
+ {'algorithm' : NSS.types.SECAlgorithmID},
+ {'subjectPublicKey' : NSS.types.SECItem}]);
+
+ NSS.types.CERTCertificateRequest = tcypes.StructType("CERTCertificateRequest");
+
+ NSS.types.SEC_ASN1Template = tcypes.StructType("SEC_ASN1Template",
+ [{'kind' : tcypes.unsigned_long},
+ {'offset' : tcypes.unsigned_long},
+ {'sub' : tcypes.voidptr_t},
+ {'size' : tcypes.unsigned_int}]);
+
+ NSS.types.PK11RSAGenParams = tcypes.StructType("PK11RSAGenParams",
+ [{'keySizeInBits' : tcypes.int},
+ {'pe' : tcypes.unsigned_long}]);
+
+ NSS.types.CERTCertTrust = tcypes.StructType("CERTCertTrust",
+ [{'sslFlags' : tcypes.uint32_t},
+ {'emailFlags' : tcypes.uint32_t},
+ {'objectSigningFlags' : tcypes.uint32_t}]);
+
+ NSS.types.CERTSubjectList = tcypes.StructType("CERTSubjectList");
+
+ NSS.types.CERTGeneralName = tcypes.StructType("CERTGeneralName");
+
+ NSS.types.CERTCertificate = tcypes.StructType("CERTCertificate",
+ [{'arena' : NSS.types.PLArenaPool.ptr},
+ {'subjectName' : tcypes.char.ptr},
+ {'issuerName' : tcypes.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' : tcypes.char.ptr},
+ {'dbhandle' : NSS.types.CERTCertDBHandle.ptr},
+ {'subjectKeyID' : NSS.types.SECItem},
+ {'keyIDGenerated' : tcypes.int},
+ {'keyUsage' : tcypes.unsigned_int},
+ {'rawKeyUsage' : tcypes.unsigned_int},
+ {'keyUsagePresent' : tcypes.int},
+ {'nsCertType' : tcypes.uint32_t},
+ {'keepSession' : tcypes.int},
+ {'timeOK' : tcypes.int},
+ {'domainOK' : NSS.types.CERTOKDomainName.ptr},
+ {'isperm' : tcypes.int},
+ {'istemp' : tcypes.int},
+ {'nickname' : tcypes.char.ptr},
+ {'dbnickname' : tcypes.char.ptr},
+ {'nssCertificate' : NSS.types.NSSCertificateStr.ptr},
+ {'trust' : NSS.types.CERTCertTrust.ptr},
+ {'referenceCount' : tcypes.int},
+ {'subjectList' : NSS.types.CERTSubjectList.ptr},
+ {'authKeyID' : NSS.types.CERTAuthKeyID.ptr},
+ {'isRoot' : tcypes.int},
+ {'options' : tcypes.voidptr_t},
+ {'series' : tcypes.int},
+ {'slot' : NSS.types.PK11SlotInfo.ptr},
+ {'pkcs11ID' : tcypes.unsigned_long},
+ {'ownSlot' : tcypes.int}]);
+
+ NSS.types.CERTBasicConstraints = tcypes.StructType("CERTBasicConstraints",
+ [{'isCA': tcypes.int},
+ {'pathLenConstraint' : tcypes.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 : tcypes.ArrayType(tcypes.char),
+ ubuffer : tcypes.ArrayType(tcypes.unsigned_char),
+
+ // CERT_CertificateTemplate : sharedLib.declare("CERT_CertificateTemplate",
+ // NSS.types.SEC_ASN1Template),
+
+ NSS_Get_CERT_CertificateTemplate : sharedLib.declare("NSS_Get_CERT_CertificateTemplate",
+ tcypes.default_abi,
+ NSS.types.SEC_ASN1Template.ptr),
+
+ PK11_HashBuf : sharedLib.declare("PK11_HashBuf",
+ tcypes.default_abi,
+ tcypes.int,
+ tcypes.int,
+ tcypes.unsigned_char.ptr,
+ tcypes.unsigned_char.ptr,
+ tcypes.int32_t),
+
+ CERT_GetDefaultCertDB : sharedLib.declare("CERT_GetDefaultCertDB",
+ tcypes.default_abi,
+ NSS.types.CERTCertDBHandle.ptr),
+
+ CERT_ChangeCertTrust : sharedLib.declare("CERT_ChangeCertTrust",
+ tcypes.default_abi,
+ tcypes.int32_t,
+ NSS.types.CERTCertDBHandle.ptr,
+ NSS.types.CERTCertificate.ptr,
+ NSS.types.CERTCertTrust.ptr),
+
+ CERT_FindCertByNickname : sharedLib.declare("CERT_FindCertByNickname",
+ tcypes.default_abi,
+ NSS.types.CERTCertificate.ptr,
+ NSS.types.CERTCertDBHandle.ptr,
+ tcypes.char.ptr),
+
+ CERT_FindCertByDERCert : sharedLib.declare("CERT_FindCertByDERCert",
+ tcypes.default_abi,
+ NSS.types.CERTCertificate.ptr,
+ NSS.types.CERTCertDBHandle.ptr,
+ NSS.types.SECItem.ptr),
+
+ CERT_VerifyCertNow : sharedLib.declare("CERT_VerifyCertNow",
+ tcypes.default_abi,
+ tcypes.int,
+ NSS.types.CERTCertDBHandle.ptr,
+ NSS.types.CERTCertificate.ptr,
+ tcypes.int,
+ tcypes.int,
+ tcypes.voidptr_t),
+
+ CERT_CertChainFromCert : sharedLib.declare("CERT_CertChainFromCert",
+ tcypes.default_abi,
+ NSS.types.CERTCertificateList.ptr,
+ NSS.types.CERTCertificate.ptr,
+ tcypes.int,
+ tcypes.int),
+
+ PK11_FindKeyByAnyCert : sharedLib.declare("PK11_FindKeyByAnyCert",
+ tcypes.default_abi,
+ NSS.types.SECKEYPrivateKey.ptr,
+ NSS.types.CERTCertificate.ptr,
+ tcypes.voidptr_t),
+
+ PK11_GetInternalKeySlot : sharedLib.declare("PK11_GetInternalKeySlot",
+ tcypes.default_abi,
+ NSS.types.PK11SlotInfo.ptr),
+
+ PK11_GetAllSlotsForCert : sharedLib.declare("PK11_GetAllSlotsForCert",
+ tcypes.default_abi,
+ NSS.types.PK11SlotList.ptr,
+ NSS.types.CERTCertificate.ptr,
+ tcypes.voidptr_t),
+
+ PK11_GetTokenName : sharedLib.declare("PK11_GetTokenName",
+ tcypes.default_abi,
+ tcypes.char.ptr,
+ NSS.types.PK11SlotInfo.ptr),
+
+ PK11_GenerateKeyPair : sharedLib.declare("PK11_GenerateKeyPair",
+ tcypes.default_abi,
+ NSS.types.SECKEYPrivateKey.ptr,
+ NSS.types.PK11SlotInfo.ptr,
+ tcypes.int,
+ NSS.types.PK11RSAGenParams.ptr,
+ NSS.types.SECKEYPublicKey.ptr.ptr,
+ tcypes.int,
+ tcypes.int,
+ tcypes.voidptr_t),
+
+ PK11_SetPrivateKeyNickname : sharedLib.declare("PK11_SetPrivateKeyNickname",
+ tcypes.default_abi,
+ tcypes.int,
+ NSS.types.SECKEYPrivateKey.ptr,
+ tcypes.char.ptr),
+
+ SEC_ASN1EncodeItem : sharedLib.declare("SEC_ASN1EncodeItem",
+ tcypes.default_abi,
+ NSS.types.SECItem.ptr,
+ NSS.types.PLArenaPool.ptr,
+ NSS.types.SECItem.ptr,
+ tcypes.voidptr_t,
+ NSS.types.SEC_ASN1Template.ptr),
+
+ SEC_DerSignData : sharedLib.declare("SEC_DerSignData",
+ tcypes.default_abi,
+ tcypes.int,
+ NSS.types.PLArenaPool.ptr,
+ NSS.types.SECItem.ptr,
+ tcypes.unsigned_char.ptr,
+ tcypes.int,
+ NSS.types.SECKEYPrivateKey.ptr,
+ tcypes.int),
+
+ SEC_GetSignatureAlgorithmOidTag : sharedLib.declare("SEC_GetSignatureAlgorithmOidTag",
+ tcypes.default_abi,
+ tcypes.int,
+ tcypes.int,
+ tcypes.int),
+
+ SECOID_SetAlgorithmID : sharedLib.declare("SECOID_SetAlgorithmID",
+ tcypes.default_abi,
+ tcypes.int,
+ NSS.types.PLArenaPool.ptr,
+ NSS.types.SECAlgorithmID.ptr,
+ tcypes.int,
+ NSS.types.SECItem.ptr),
+
+
+ CERT_Hexify : sharedLib.declare("CERT_Hexify",
+ tcypes.default_abi,
+ tcypes.char.ptr,
+ NSS.types.SECItem.ptr,
+ tcypes.int),
+
+ CERT_AsciiToName : sharedLib.declare("CERT_AsciiToName",
+ tcypes.default_abi,
+ NSS.types.CERTName.ptr,
+ tcypes.char.ptr),
+
+ SECKEY_CreateSubjectPublicKeyInfo : sharedLib.declare("SECKEY_CreateSubjectPublicKeyInfo",
+ tcypes.default_abi,
+ NSS.types.CERTSubjectPublicKeyInfo.ptr,
+ NSS.types.SECKEYPublicKey.ptr),
+
+ CERT_CreateCertificateRequest : sharedLib.declare("CERT_CreateCertificateRequest",
+ tcypes.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",
+ tcypes.default_abi,
+ NSS.types.CERTCertificate.ptr,
+ tcypes.uint32_t,
+ NSS.types.CERTName.ptr,
+ NSS.types.CERTValidity.ptr,
+ NSS.types.CERTCertificateRequest.ptr),
+
+ CERT_DestroyCertificate : sharedLib.declare("CERT_DestroyCertificate",
+ tcypes.default_abi,
+ tcypes.int,
+ NSS.types.CERTCertificate.ptr),
+
+ CERT_DestroyCertificateList : sharedLib.declare("CERT_DestroyCertificateList",
+ tcypes.default_abi,
+ tcypes.int,
+ NSS.types.CERTCertificateList.ptr),
+
+ CERT_NewTempCertificate : sharedLib.declare("CERT_NewTempCertificate",
+ tcypes.default_abi,
+ NSS.types.CERTCertificate.ptr,
+ NSS.types.CERTCertDBHandle.ptr,
+ NSS.types.SECItem.ptr,
+ tcypes.char.ptr,
+ tcypes.int,
+ tcypes.int),
+
+ CERT_CreateValidity : sharedLib.declare("CERT_CreateValidity",
+ tcypes.default_abi,
+ NSS.types.CERTValidity.ptr,
+ tcypes.int64_t,
+ tcypes.int64_t),
+
+ CERT_CertListFromCert : sharedLib.declare("CERT_CertListFromCert",
+ tcypes.default_abi,
+ NSS.types.CERTCertificateList.ptr,
+ NSS.types.CERTCertificate.ptr),
+
+ CERT_StartCertExtensions : sharedLib.declare("CERT_StartCertExtensions",
+ tcypes.default_abi,
+ tcypes.voidptr_t,
+ NSS.types.CERTCertificate.ptr),
+
+ CERT_AddExtension : sharedLib.declare("CERT_AddExtension",
+ tcypes.default_abi,
+ tcypes.int,
+ tcypes.voidptr_t,
+ tcypes.int,
+ NSS.types.SECItem.ptr,
+ tcypes.int,
+ tcypes.int),
+
+
+ CERT_EncodeBasicConstraintValue : sharedLib.declare("CERT_EncodeBasicConstraintValue",
+ tcypes.default_abi,
+ tcypes.int,
+ NSS.types.PLArenaPool.ptr,
+ NSS.types.CERTBasicConstraints.ptr,
+ NSS.types.SECItem.ptr),
+
+ CERT_EncodeAndAddBitStrExtension : sharedLib.declare("CERT_EncodeAndAddBitStrExtension",
+ tcypes.default_abi,
+ tcypes.int,
+ tcypes.voidptr_t,
+ tcypes.int,
+ NSS.types.SECItem.ptr,
+ tcypes.int),
+
+ CERT_EncodeAltNameExtension : sharedLib.declare("CERT_EncodeAltNameExtension",
+ tcypes.default_abi,
+ tcypes.int,
+ NSS.types.PLArenaPool.ptr,
+ NSS.types.CERTGeneralName.ptr,
+ NSS.types.SECItem.ptr),
+
+ CERT_FinishExtensions : sharedLib.declare("CERT_FinishExtensions",
+ tcypes.default_abi,
+ tcypes.int,
+ tcypes.voidptr_t),
+
+ CERT_ImportCerts : sharedLib.declare("CERT_ImportCerts",
+ tcypes.default_abi,
+ tcypes.int,
+ NSS.types.CERTCertDBHandle.ptr,
+ tcypes.int,
+ tcypes.int,
+ NSS.types.SECItem.ptr.ptr,
+ NSS.types.CERTCertificate.ptr.ptr.ptr,
+ tcypes.int,
+ tcypes.int,
+ tcypes.char.ptr),
+
+ PORT_NewArena : sharedLib.declare("PORT_NewArena",
+ tcypes.default_abi,
+ NSS.types.PLArenaPool.ptr,
+ tcypes.uint32_t),
+
+ PORT_ArenaZAlloc : sharedLib.declare("PORT_ArenaZAlloc",
+ tcypes.default_abi,
+ tcypes.voidptr_t,
+ NSS.types.PLArenaPool.ptr,
+ tcypes.int),
+
+ PORT_FreeArena : sharedLib.declare("PORT_FreeArena",
+ tcypes.default_abi,
+ tcypes.void_t,
+ NSS.types.PLArenaPool.ptr,
+ tcypes.int),
+
+ CERT_GetCommonName : sharedLib.declare("CERT_GetCommonName",
+ tcypes.default_abi,
+ tcypes.char.ptr,
+ NSS.types.CERTName.ptr),
+
+ CERT_GetOrgUnitName : sharedLib.declare("CERT_GetOrgUnitName",
+ tcypes.default_abi,
+ tcypes.char.ptr,
+ NSS.types.CERTName.ptr),
+
+ CERT_GetCertificateNames : sharedLib.declare("CERT_GetCertificateNames",
+ tcypes.default_abi,
+ NSS.types.CERTGeneralName.ptr,
+ NSS.types.CERTCertificate.ptr,
+ NSS.types.PLArenaPool.ptr),
+
+ CERT_DecodeDERCertificate : sharedLib.declare("__CERT_DecodeDERCertificate",
+ tcypes.default_abi,
+ NSS.types.CERTCertificate.ptr,
+ NSS.types.SECItem.ptr,
+ tcypes.int,
+ tcypes.char.ptr),
+
+ CERT_FindCertExtension : sharedLib.declare("CERT_FindCertExtension",
+ tcypes.default_abi,
+ tcypes.int,
+ NSS.types.CERTCertificate.ptr,
+ tcypes.int,
+ NSS.types.SECItem.ptr),
+ };
+
+};
diff --git a/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/Root-CAs.js b/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/Root-CAs.js
new file mode 100644
index 0000000..15372bc
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@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
+
+var 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@eff.org/chrome/content/code/Thread.js b/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/Thread.js
new file mode 100644
index 0000000..8c9daf6
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@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@eff.org/chrome/content/code/X509ChainWhitelist.js b/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/X509ChainWhitelist.js
new file mode 100644
index 0000000..e208d15
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@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,
+ '002F83BE1562B658A7BA747EEE36FFBA25A7D6C66E263B2901184058802D9A43' : true,
+ '006014E5A5190652C3475AA099483A273989F403FDB282AAD77DB72397C274A8' : true,
+ '013470D100AFBBA6D4E03735C1D924EFA6E25E66F781E9DBB6155EF713336307' : true,
+ '0147A7B139D599058A43CDE86602DA56375CC78C2C15AC512953E3C98592D4D2' : true,
+ '016BBB29A76DA59A20C5E9909D8D0A9CD25824D7462BD51B022D61B503569936' : true,
+ '018BCB77EB89BD658CFB6388F57F22E40942E08FD6BF3A26DE05A2F992F6E5A2' : true,
+ '01B1568F4757D7222D2E2AB9FA13E7EBBEE1B5D622CB6FA3DC45D552C2086B4C' : true,
+ '01E42F89ABE23F6B00E5A35240F35DF38A861FADA04A0B07B6DA9FFA4B57075C' : true,
+ '01FC275FB7BB83082EA2C546876545030D74F68355AF2B0CCB1972993B393E58' : true,
+ '020E3FCA9BCBC32FF8E96460F1666CF889EAC42A586CCC76B46BBE85AAEAA450' : true,
+ '02748B445F904F6C04BB42BB810B11B77BDE047350F3181DF40C3BA79D4DC89F' : true,
+ '028CD123ABEA12F150435947299419928DC5E80E94E9148841265B64344C3DBC' : true,
+ '028D7A3A5ACA6156AA42F1DAE25BD6116A417EFD8E64B7E6A004B1911CABCAC0' : true,
+ '0299AD4101A95EA006706582B2E55A35DFD2224EB9A8F8AA822D2354BAC4C640' : true,
+ '02E266B8D011CF92708D0DD0D9D840BB8EF54B4A4670BF700AE90EE6F7E445A8' : true,
+ '02FB82CE0C8614F748564CB3D14C2BCDDFCF982D6187EC85E5A33B28E5340CF7' : true,
+ '0333E05678F411BCFDAEFB069DDAC8BE1B3B7E45376AE4C3827771C10A53D294' : true,
+ '0369D2A3E853610AD59F13C199134850D43D07356DD83ED5A3C366DD6326C118' : true,
+ '043B68D81BB683927B40D3DAFC7F89C56F400F859DE68C0EA88AAB1FB1D75A27' : true,
+ '045B734DD0081F9504751492B6059B22BC201018436701D98832E3A9AF050ADE' : true,
+ '0494ED6BB7E16B78F2AEAAC053DAE6B31B52E39F0E10F5E8D95B77ECBA0A0BAC' : true,
+ '04BE558E6D064E92B741B3C551CFE1F38462EF3A08AC56470894D1A80278AD5E' : true,
+ '0508390E2DF4B63477E49A461AE883335BC71F03A24BAA06F46EB0DBF42641EF' : true,
+ '0529FFECC3EB688DEA32684A0348F89876F1BD45FEA23DC8E9A25D524E7B1333' : true,
+ '052AEDFBE22BDAB88C89277692F4510A2605F64112E3024EE508A92B2D0E71CC' : true,
+ '054806D84102E23956A821100183D32EC4B5E8E9DE72912A1F8E6EE53FF9A839' : true,
+ '05546BBD905F23086AF150C0B1E30F0BCA2705B6E0CBDB56092D8E62CFD09D0E' : true,
+ '055C88BD28194042771FF813973E086A30710231DB219FF377B79FA075E7F2AD' : true,
+ '0562EA3C474A2003D2CF45418458B126AC9CBF29151CCA9B6C4A5E7AB0279CAD' : true,
+ '0589AF9C3A578488F4259AB8BBFFB2089D4C678B63D4C40B6A46CE2405346C0D' : true,
+ '06183C90C1DCDC3E9340477D37DC231361321A9960C1948E92D1A175A1500A08' : true,
+ '06354AFD85075A5BDE2D84F8408B185CCFD354C2D75988D8FC67948AA6F60562' : true,
+ '06808645F29D708E4C31AC40FA00000733238E10A56D2067AA62803C9736E923' : true,
+ '0698D7B65AF15F9A903D8D364BB7DBC1B238DACA79505B8BCE8D44AEAAB5709D' : true,
+ '06D7D04035F29672F6921CF0BB432541AE7579AA2591ABFA9155639DBEFFD2F5' : true,
+ '073B1FDF3C2009FD1E4201F3490526B49F66CD11D683A70A8D5B8A9E6E4EBF64' : true,
+ '0742E85FE9C68350E070039897F5B790BDA92D92229D74BA9C6906D958A5C510' : true,
+ '077495BFAEEBF5E62CEA015EDCE70CE78AF13C813920FD9D4AB72C999F60D4DC' : true,
+ '0780AB0F9801F169F4E7DE6F6F40F9575707D4561E4EFEBBADE71279825E0CE6' : true,
+ '07B61AF096B72D71AF801B9C7EB9F76C42CC20A7192C78DF1336611644289BE5' : true,
+ '07C228652318F79E189338C3704D4E6329632563103B494C5116C53343A073FA' : true,
+ '07CF2A06F1718D6E476B98C2B42E370A35FAFE4C1F41CF7A1DE115CDB6222FAC' : true,
+ '07D5A15EAED5AE2CA304FFCAD864791055797B0252F925AE9177B686461E2C17' : true,
+ '081B43CA6CFFA952AF4C08D1335449BCA854BE5CE2C555783A0900A7867E6120' : true,
+ '08522737DBEF2F7400033E866B61B3F9E19066EC71294DC9CE2138231921AFAB' : true,
+ '08DC876F1AE5A29F9E8B6CA628966C6FAFD1E474C3207A78792D4AA4D5C7EF9C' : true,
+ '093314E52E8CC862C2C0C8A1C57DB5CA4BED8824A3DC7C40B8675DAE1781DC05' : true,
+ '095FB0FC3CC67539621E292205E758437D94D3B651714049E6F99130BD5ADB6D' : true,
+ '0B0F28E1CE5038D9C7CD8FA557669A9E78FA0BC4BE9DBFB0BE6C96462E2CC065' : true,
+ '0B1C1033250F6DED11E4C0A7E43138AD3D52F5661FEC896519BEBCBEFDC16E41' : true,
+ '0B1D9276FF6C18184DDF7409CB6C0916D24320DEC0505096AC79C0D3FFA9C1CD' : true,
+ '0BA75006139D075BF8CD7D94B460A850F46509B23AD572CD1A1E23134F59431F' : true,
+ '0C2154A365A0DE7DC5BD0AE6EE05A8E06EE782AC5C41F1D3823E2F95C61E0D2C' : true,
+ '0C5B47050FC50334C9C440D6121486F466BB1D2444232ADCC21BC143CB1A79D8' : true,
+ '0DAB05854E84AABD75D30CE09246103436A4C41E931374E16CC374596C8DBB94' : true,
+ '0DB35F56EEAE4C5580F3231EA19F4DBB0FD46DE1BF85F4CCF40103E012CDDA4B' : true,
+ '0E3BD8F8BC06B326EF672A487855F0E9752EF7D4A2A913A41374088B6215EA44' : true,
+ '0E49A9594364BFD4E6943DB24A2F77FA125596414D46F46AFCF070A1645AAC48' : true,
+ '0E7CFF7FA1B013E7EFA9407E167C8255BCB1976C2CB3144C00C39B6DFB8CE21B' : true,
+ '0E8071ED091D6F502E2649CEF26818C0D1DE8F752632B670395E916F1BE748FE' : true,
+ '0ECB53FDA2349AB6008BBC0E5CD361EEC5B6BD769281800FF4B1C9764A925277' : true,
+ '0EF8FA5AAD4BACDB842959378F18935855B027B0BADDCBDEADC9CC958C4C603B' : true,
+ '0F01342B195E54DA8265E4B3928A2692F6CF05F41CB85152A8122FE6E914C67B' : true,
+ '0F0B2EAF8B0C4FBF1A47C048E13196C163ED9D8628AFA4AA264A4624B1CBCF3D' : true,
+ '0F7391E841B068E145E12DBF6CC16DF16410083111E5F093302BA163AD4EF39F' : true,
+ '0F820CFB486D8564C83E968049AD119FD838B2CD21C0B342A0D9B5D22C445C25' : true,
+ '0FBBC11F4627D5AA5F7A7847E0F8DE298021E175EC69ECA90A62740A71DC9B1F' : true,
+ '0FEC8F0781CB9193F4996B43806C6D2C539847FBBC0C28146B64FC35617BAB99' : true,
+ '105993C03E3F5C7E94D5A78242FCD6D0C7B7E5104295F8275752D7C6908428B8' : true,
+ '1089E7487C08428CAACCCDBA18B8982049B6A915FBA4598E953395B4493CC358' : true,
+ '10B8161FF4FC64020AD40EA57306CFC5010BF9682B18DEEF2544DD4D5DF0466E' : true,
+ '10E65A16F0DEE4B2499EBD5C96CD416BD2713C73A422F3BDBA81899C736437C5' : true,
+ '1134E778B42A8DBD01C547E9676F5294D4B16297DB8F6A512394F77B21F22052' : true,
+ '116A5D5F3E99CFE5F72A4AFAC8699CC225C130F4B8520CDB350A1262D9585973' : true,
+ '118FF53B6BEB35CBFE6592D45BE082BA1228D1817E46B2CC14B8855FCC5C9D59' : true,
+ '11D4CF9A8FEC8EB2ADC4EA3B4E7036BB041BDCF45B5563A38F409CC8F6E531C1' : true,
+ '11F7A939F33BDF6270E16C747C0B0918902CD4501AF1843D9EA4445A2E708C58' : true,
+ '1243C75D0F805DA54E780D0D9C55247B1ABB31FC09EB65A7017695945F2A0D4A' : true,
+ '1260F631D1FBC3640BE637469748889E23A2EA907F33F78286408AB56F450A66' : true,
+ '12826065A034136FFC2258AA1A65F9E550A582B4017E396077917C775D42E553' : true,
+ '12F18371A507D5861569D0AEA4A8E66E551FFE7F312721E9122243EE006D8C46' : true,
+ '1306A4D21476D28D3E2F7D6E4385686E1BCB6D7EEBB1A5217346A6E5855DF944' : true,
+ '130753A8008BBCA6A0DD9037C6C7DA2D149BA8978C5E5444AE1B8C98F3C3DB60' : true,
+ '130F0A3C4B9E9132D1676B4EBBAB2B17AFD2AF39E291C983A696D8BF0DD379BD' : true,
+ '142BA9FFCEF5D09FF3DE4BBF8110156D52FEF1C8C707E4B916692D7DDB335A6D' : true,
+ '1491DCCE9B3E3F5EEA92C26671244EB7203C30F539EF5B6131459F389A0D2CD8' : true,
+ '14CF0BEC6B8811A81FF5AD015C62BC85AF172E86B7504D40E9F27F0E0A6F9BDC' : true,
+ '14D5F704481C18BA8A23559A9E49942C499BA8011926C09F4D721D92ACA5F20E' : true,
+ '150B877BB614A98F2186C3B0978D190C77A605146A6A569036728F544520CDC8' : true,
+ '154C4C43AAF5F838B7B9BE748FF671521BDF0ECF3D749EB85487F9C315239778' : true,
+ '15DDBE5ABC768035989DD30C6A2BC696AA7E5AB2ADDF1F3AA8FEEA35D319B47E' : true,
+ '15ECBA98523C315922CFC13469827BC118123E02D1ADF24C3BF8305769869181' : true,
+ '161AAA4D4A25BB68199DBE8BDDA1E8FBC52E9C7B299EC5BFAA7B36040B3916E5' : true,
+ '163227E6A01ADF06502730FF25F39D8F52B79F9AE61D5AA2876980A21985A211' : true,
+ '1632D9CADAB9444AAC7BBF6389BA59C12CD866725786D9284BF9B205E2586A28' : true,
+ '1713C91C21F442044156AAD0A65E96A4C0020B2F765492A1431C6ABC3AF67D96' : true,
+ '1715E347E92C85ADCEFCA2ED0C4B56DF7D7A3FA9C834B1F2DFA7CE115DC8DBC4' : true,
+ '171F671393FB5CF2856957CB6925964B3C328E79EAF083DB15DE3D52233D6268' : true,
+ '1765ACDC57A9EEDE87E6573443C7EBC42B17E012FE153D6D7158402D5CF9365C' : true,
+ '1882C2D8D817DD1078933D244E379CFC5BA8EAAE302BCF9FA22636B08FAC86CE' : true,
+ '18C1218D9ED6A609650AADB754644377914C34E7C35F305D12861D7C28BDBB80' : true,
+ '18D46E40DC2A1F815A02742F6AAB8CCCB80BABB108B349D2E875762F7D80B2CC' : true,
+ '197B67187392F9D4653EC70C8BB277DD7DA843E62BA1A47B0BD95B89CB2C1735' : true,
+ '1985D79429E03A4B25EF4195F04D0D6E770B36E8AB4369232CF3A1C1E40886D3' : true,
+ '198719FE25A84786A0C2BD4053E93940AF864498D6071994E09A5335B675A73D' : true,
+ '19EA658B0817FBEDC5742659375F2BE78A5C76532A516F4687C6033562FAE9D5' : true,
+ '1A30713C34D901235DF30605AFB82AF55EE4D3940B86E60B50692145013AFBB5' : true,
+ '1A483DB77B1FD7D997B7044556C59DD6893641CC7F92178D5346394C2E522ACC' : true,
+ '1A86C1C38DC645A40F8DF9EDC584DC4175CC30F133737BEE3D19530929708509' : true,
+ '1AA2692979DFDFEFD4854EC9EAB4CC323BE159529C3E85799E2C3C51350FB9C2' : true,
+ '1AC37940540C25A5A2E2CC1DFF939F3FAE61C194894FD82F5861AC98E1D1ACE6' : true,
+ '1B53976D26A5F691CEFCF098279AAEADDE2651B698FC3F7088F5C2A5B9CB2C5A' : true,
+ '1BCC11E5459BEF3D48BCCFB10F57B0D640EC74C4BFAA3F0AA221B777170A5B6D' : true,
+ '1BDD0D8B130AB4FE89DB814276912F04405F2D202CE9DA8B89C4420740517437' : true,
+ '1D16AA433A5042924AE1BB07FC1B53E8549BB93D0F3E40723DE9CF95720D593A' : true,
+ '1D2A6A876B8C8A835206E337529E6C222E272D4AB79E2224E23A5B6414039D50' : true,
+ '1D9D0031DF904A27E15FB3AF4E004B0A7350788FFEE1C7FC17F0E6118C678AEC' : true,
+ '1DA6DEBFCC0A4BADEB9672E523C95F42B2D16B168759F75FD03EFBD2CD482032' : true,
+ '1DB7BCE9E799B17DD372C52C9BAA4B213F041B697880932F8AA93D8B609DBBEE' : true,
+ '1E07BA293C78E14CDFC629A797E8046A33F21981334BF6BFF9B4DD2D3C148CF4' : true,
+ '1E51AC35C0CF103BB39F51DBC7096C53D1F3A255DC15A473B5882CC03C266198' : true,
+ '1E5D810BCB8DA3AF393761C59CC88D22669ECB7D4F926760BE1EC6CD83E60765' : true,
+ '1EE116E4B79A340456A72C49C1EDDD86786C97258ABEB9966108A9E01AB3836B' : true,
+ '1F4C963A9BA39CE44E46F135EFEAD5B30D6A0A3A43545E18CBE59DE452A6468B' : true,
+ '200F113FB8BE9CD93DCF38AF69F714D686AE4D227572F482F774574A5CCFA6DB' : true,
+ '2088FE71BC64663BEA0FB04CF93E3053228D41914681A3F17DA61CA996D453AF' : true,
+ '20BFFF5C6EF0AB849F78A1259C766EFF0FE4652DF02731E4F8408B1E27897932' : true,
+ '20C2806DEA7B729E29F7B7BB8B2653B8D71805605AD46394473D1B1F81103664' : true,
+ '20C6290C0D7F1DC37BE540410CE80976FDC523C201D3BAF204454EF851F721E9' : true,
+ '20E0911E2A528C3DC143646F9369D844E82CDA53C48549125DD690ED1047D8FF' : true,
+ '20F5CF34D9A134A8920507B12EB84CB24C2F09152FE9B78FDADF57D892BE79E1' : true,
+ '2128E4E9D372E50A94E43591AAA7C8B6BCDD8BF303C0B22F923B1DCD596E79B6' : true,
+ '2156D89DFDE0B0676EBDE6CC82DF46DA81467DF96F9B8DC4A8B62F71DDA5DF95' : true,
+ '215D8B74267F138F2936F74E6B2029CD8991DD6AAA1CC001ADF88B0202F637F9' : true,
+ '21B2E2C095E47F4762069BA39AAD86802201AC4ED5B6DDBC20D1C7863AE511ED' : true,
+ '21C612A4E2CD066893391249E3C4DF22613E9DA5FF37690E3F806AA708B0401F' : true,
+ '21CA97793B165187383669364CEFC96F19BAF3F8987F7260CC46F3852721BA5C' : true,
+ '21D70F62B14A3B2175742DB9F3C49999B67C15D0FF8ACA95B0C6A5393E043FA1' : true,
+ '223264A2EEB01CD24524FB9273B38688A0AA8E3A2E7D63ECB76012B060039760' : true,
+ '2234133DD7FCAE5D199EB31E1ED8A798554B29A355A895066FA6AE445386D9ED' : true,
+ '225C19F21F4CC5241C15ACC6007060605DDF10817681F676CB8BD1B72014D52E' : true,
+ '23980A7B935B10CA69315CDA05E61B4ABAE7876724C0E0C3CC7BE9748E41ACCC' : true,
+ '23B4591985CFCEFE811945510306C145B21FCE6B79686DC5D245DA69DD6D4128' : true,
+ '240968FE922EFB9937AF8923AA4F0478D7F679937B9FA9BC1A2B1DF18994B9F8' : true,
+ '244EE1B87977A42E7CA64725F7DD82F337A432744853EFA58C9F386DD4E0283D' : true,
+ '2518D06777FE96E9D7D1B0D531149A5862177805443AC9D271BBCFEC660ACFC2' : true,
+ '257335B1AD2B1D562552738ECA1C534A6331FD83B95C91A1EB3B6C2A44650BA9' : true,
+ '261DD192486C36B9BF5DC0C4140F670FDD2BC62EA80C64123D827B5F32E0190B' : true,
+ '2635178113FBBCC75EABC09C497D411C994AD0170CF9DF999A4FF5C16872CDBB' : true,
+ '2677470F2FBD067904B7014B88988BB94F72403C014240B9843AE5A5FA21661D' : true,
+ '26A15E073F71406D8AFF4A4A623F956FA8E3ED70F0C04CB4B28031EA103DB975' : true,
+ '26D106DF3FE6E9C99924142C9DA27551E012C72C71FDE6EDD3CF4B5C87D59A26' : true,
+ '2741D5D511257BAB37E2DD48559D3FE3998CB3A5BA4FC1EA9C8656D5694D7BFD' : true,
+ '274C93C8441ED469C7B7E01B5A4DB6D9923C3947C87CA4B71D09F34D13F37D47' : true,
+ '27560906A3548AB767BA0992FD2F93575AD11AB83AED3354B6267C3F3228C858' : true,
+ '27893DE92514608F647A44E85314B90F983BD7E6BCD6CE9BE428FA52EEE34DD9' : true,
+ '27B5CA8FBD760D881A9769019B0EC43CDADA9AAC3900861E1E14EE9348736FB9' : true,
+ '27E83ECCF1CAB639F44A2B74BF9A3D463B18BE6D600C1186C336421DF0A8B752' : true,
+ '28445F7C648AB6025EB469E9C5FD10C6C8D0D21B6A20F078854EFF406C55D3F7' : true,
+ '2855C813E2F7369732C35656DD791928668591AC6AB3F9C73061B80AA7713920' : true,
+ '286C62823B119606F33D5761CF39C86D4DFBC1531AC399969455CA227344D5C7' : true,
+ '28B49BD8083286E1E01C3B94D6358697FE6827CCE71D7C1D0892941B49D83416' : true,
+ '28C725A83ABDD4F961356B2B5583C1F165094C5BC820CF15A4FE18086272107E' : true,
+ '28F5AFFD30157F1A5DE7CB914129A6BCA4BD8EBC41A61841E1033C512F78E68B' : true,
+ '290DE5FFD5BBBE1A557D3DABD01F3CF8FA5FDCFED4A919F4B73CF80B6CA2E4DF' : true,
+ '296C5D3A18B056644774C03385700A24690EB9CD1114CD9E643E4813B69363ED' : true,
+ '29E0C5434734C0FC43246F066EFA19F533AD59E3A713F97455F8C338F1C3638C' : true,
+ '2A1E01990593F5DE1C300ED5ACD94B694DECF9DE34BF2836A764910F82BE664B' : true,
+ '2AC8168217387601B753D08652B1FE2CD14E8A7C9A7DE7DF74A8300C976FBED2' : true,
+ '2AE917E3AB4B867883088BCFFED53EBEF9F87988C77AE47FE325547B181931A1' : true,
+ '2B1B6843B33770E84785D0FACA5AA6EAB6C480AFA07E95F7A282534BEB69B065' : true,
+ '2BE6A67777765CE8EB868416D68CA6AEA8C57D31523F4A683957DF560C152066' : true,
+ '2C01A7027A6FCCB3EF0B70F134229605465295EE1249F5A582D04CD82689BFC9' : true,
+ '2C43EC0374BC603A1B191B88ADBCD5C1A0409120427995C2684A1590C7AB1432' : true,
+ '2CAB9683916ADE98D778D3394221D8D07E07353E546771D507232A26FA577902' : true,
+ '2CB02C933CD41CDB146CA0256A99AE53D9320BAFBDDE82EB24891AF68BC6E19B' : true,
+ '2CD5E37B2C388FECDF839EE16998A0F0850B5A6BB39AA5A507AE676622001CB0' : true,
+ '2CDCECA60D7F0E4700411340E6CBFE1B3C8FAFA9081E219462D25A14B61F9AB5' : true,
+ '2CF8647F049667F93FC50EBEED00FE30965114437763C339393FA19E306E9CD5' : true,
+ '2DBAF94C053FCCFA1EC09CBB22F54DAFF2DB4ABE1B3C61CFF1BEBC31260F4821' : true,
+ '2DE3B602EC7847028D2EA59A8E241EDE63CEFAE7456802CAFFFAA8433CE9D885' : true,
+ '2DEC053F97460AAAFB67EAB8C769B34049E9D44286F199A8D776D2FBC4A8A41C' : true,
+ '2E40BCD87CC3A1033F406FD9FB81C5F405BDFC21283B22CE396562EC17CDDF02' : true,
+ '2E936472C0CBE755C72128EECCF5BB8AE91AF188CB2F3277B205E27904A9EF20' : true,
+ '2E9AA94F913F869B027272668BCA46D5076503EB9550737482C337950749E946' : true,
+ '2F3A46F3C2FC1EBB5FB46B3135B7B4ED88CB515C2DB9A508716102340AC3583B' : true,
+ '2F56C46CCFDB3A3F0192313C4801F02FFB1738F328CCF0F33F44C0731D340DD5' : true,
+ '2FB44A33A5795F520D20CB4ABC4AE4E239FC193CC2E3D3A85056685ABDA9E0A5' : true,
+ '2FEC6D75CCD95ADD4DB327257B4E73A880CC462E1760267970030576C46E0077' : true,
+ '300B5DFEFE98F5280E47725FE63D7A0967CA022E4CF3531023A3969867677C6E' : true,
+ '30354519FFD4794257A7EBEDB0D47DEC9A547B4E7213199000F41EB65C233EF7' : true,
+ '305B4CDDF744AA543DA713E7E60C19ED5537D49ED2252330B46B7E664C4E588C' : true,
+ '305D58D32D2FBAA00A386E3BCCE2202522B78C6B10E3D83C6A7402706ADEB4F6' : true,
+ '30664111831B947406CEAFC2E660230B307F401DD060852E0E5281C95D9F526E' : true,
+ '3074E85BD8520085B6E6AE099964DEF737BF95AF53A0A8F3C5F4B4D714CA2824' : true,
+ '308F0B0CF08358D501CB807667A31FEE7FDBF7539E1AE74945DD9245AB9F2CF6' : true,
+ '309DBF5FE6C52E6C7143E63BA07B9FE59D4ED38944409ECBECBDD74ACDE4E78E' : true,
+ '30E358967DCBDB42F759C5380FE945EF7142DD37D820E199AEA23DBA51EF541F' : true,
+ '311F6B428C4994F2677A56588DA04B704926D737669A76B1B3C8504EECCE4A61' : true,
+ '317B7685779DAFF1AD898FA790781D54D3EDC11621D1EAA3F4A9BA3262462557' : true,
+ '3264E084FB98F560090992151EFBCB41AA84EAE0C3D8378127A974DF81473E9E' : true,
+ '326F94C0B20B06F11A54904E31BCAB0C1A4DEC790BA2D1947E0E11F9B7210F58' : true,
+ '32707DD6FF2DAE577C4097176D936DE4E46E5CF428B0831D12574128BBFF6309' : true,
+ '32D398E73D053561EC78257EB01F0945C2A38D9F80674F6F2B4B10BA35A2B4E4' : true,
+ '32ED76AE2E09C58605B9C2BF6A27080DB8C7EEB70889BCCCEA72104C7F33F95D' : true,
+ '33512B5F197ED2B530575C71046268C4E2F5724B645B8DF1C689EC535C0FC791' : true,
+ '3361788E20F935BE971D4A9B9F49BCF9951C7B30E8E1B00E18130777401E634D' : true,
+ '3379517964657D6F875971C1ED6218D9F890BEFC7390CA654C79A666D1989A18' : true,
+ '33AF2CA60F79D526019EDEA838ADAD51FE541F589F09B0C69A0AA288363D3C72' : true,
+ '33E0C503F4B4CE3AB1851ABE4630DDCCA720DBE3634CF7A5203ACEAC15031F12' : true,
+ '34535CB0A54193C144158D23C5A7F6F0F448FDD8EB9C21542A1203BB66BB8144' : true,
+ '34B1CD29AECA7639010C4082C4609B8EC6EFC5DF272CC90D2650D01ADEEA8A53' : true,
+ '350123506BA002EA62350E82CFEC1DA7BF24B405C4160EF1BF4C445F7DC31757' : true,
+ '3551069D5774095145A9731885485CE10FBF3FB46144F33A4E48C03CF2E475E0' : true,
+ '359BA4063DD43F04725A67F7E425EC48A593838AC97328374F83A31FFBB1EBF7' : true,
+ '36267B2A60E0B5997DEEE17CDBE6AC7F7D54D279C6AB4F06CD469919F442E6AE' : true,
+ '366B123FA1EA2FF7FDBCA0422E504C8E0AB62334AC8941D307060F5ACDFB58AA' : true,
+ '36E58C6DDB5038020FC61F17D2728311DEA600AD9FBFBEBAE2EFBB7B5071D884' : true,
+ '3757DF53FF77E5BF111290CE7F03B821455E2D1D7B70033F649D7B60ED8D602B' : true,
+ '375A5FEFE06518B0BFD2CE02034E185A44118CA92BEC6FE2D5809762C89E8C67' : true,
+ '376690DCA49A37377D699141D59A549953B2A0B730729BC6FF8BFDA67433F763' : true,
+ '37DFE2D5440429C8D48258C7E68500C526C81FA4606E45B6611E68C6AF2917B1' : true,
+ '381FB3EE49812423C2F3CA943350617377D0E36E0D7FAE21159F648DA79FD32F' : true,
+ '383BD359B34DEAADBEF73CF41B93362BB3C59688EFCE1E8403C50C5783F1C50E' : true,
+ '38BDD8D544DD1094861968FB021D7E27BC2A9D0031AA914F3398C377A4B5F9EB' : true,
+ '38C737C9B8240CCA0A28FD58D0C0C697B8D1DDDCF895D3F3256D1DAC8C08F513' : true,
+ '38D12483160C6E3AC330EDC1DE173382B4C2AD79A298155181CCBC9A10CF6495' : true,
+ '3917E4EF55DFBA1A48DF46B693E2E72D708B7B6146C8686C5B3F94FF8B3704FC' : true,
+ '392944F5A1C82284C698C6BB512CB5ABA48445376D54BDDF0A53C66B832D1BB2' : true,
+ '3958BB2CE60148D4CDAE6266E4E04A6356E00B693621A4E9E05FC78C9709EF33' : true,
+ '39863EF0FA91E0729FB834D4F99A376FE60A015301FBDC91EF818346489EA0E3' : true,
+ '39BF13F759A9161866C6DC6898A5E6D71FDDAEB9EC5925FFED274FA8E5FE34D4' : true,
+ '3A260A20CB6DC9BCEE25A21284C2304A9744F494B37359F5F0AFB46A1D0DABA6' : true,
+ '3A2AC86801E185B3B8A189C42AF1574721D452DA425CEDEC6FA0CCD44894BBF2' : true,
+ '3ACDE8B9E6B1100535007AC7316F4587DEA84EE0DF1B344DECEFFA952AEEDF96' : true,
+ '3B00662EE3F01FFE2C40842F0F3B76C039ABB785962E371767E89E2AFA311A74' : true,
+ '3B209B5718F54F113C557AB8D670B1501B05A16B92E6E16BC97D026087B90C3E' : true,
+ '3B98E076AAEB1E46BA5DAFF4914C9E279EFDB41A348AD849756FC33CB6A4881D' : true,
+ '3BB4AB8E09B6EFC71B2B292A489372337E48085BCC4C08431D090D63C8920C78' : true,
+ '3BD39467620E6ABD6EDEECDB96477E54E67F1F63377B977E1C9E2371F0911922' : true,
+ '3C49B9DC9307C6B33E0DBE135836504ACB9F6204B7172A412C28E797E56CA02A' : true,
+ '3C96E89F8B86936DC4FFF044FF1AE0F5C26BBB357356C47EB977C5E5620EE434' : true,
+ '3C9AD3DFF4DB327C01C03D00389A76E5E699D4C4707E23221DA6C61F949AD532' : true,
+ '3D1C44AA234496D76A6BAC3434418253903B3C5019FF91F78348AC7C14E39CB6' : true,
+ '3D666AC8FDB8483D6006C9E22E5E9539E27B322D5BCD0AF264DC8878F9476DB0' : true,
+ '3D76435F7EA7583AD6F474333B7F8AC6368ACB53FAF4AFF9E8644765025ED427' : true,
+ '3DB253A22F1FBD071CBAB9E97294CD6534BC74430123B82198F7A29ECF800D64' : true,
+ '3E08AEB4D01EEE9C19968EDE2D5FEE0E974E6B7FD65769E767C28CCDADD85D46' : true,
+ '3E09F448ED5A72584FA305F82A25706D2AE756083530B4E18665DA2AE46C1410' : true,
+ '3E0C00CF982CC013733E0AEA478B7329E28EE2A7627E7BE5A53630744F024765' : true,
+ '3E5558CB92AEDC7E01DB0FBCD0825CC0F51AA7B683ABFD01D1E5E04C8A4D716B' : true,
+ '3E5CFCFEB58445BB4A2C7D31BECCD7D28302E69396E3BA6F7DD8FE5AA11DFFD2' : true,
+ '3EE396E9C7E97016AFACE8285C152EC6781728AFFD747291AAA596D573C6ED5E' : true,
+ '3EFF635571ED85551721F01985D1B2C62613C2B7DE25C8DAF17A8767ECFCC39F' : true,
+ '3F1F9323436BD390A2355115CC333592B4B5AE3F3BA2755D342CD863371EAB1E' : true,
+ '3F933B11C350C08B98993CBD045F11249CB355ADAA8FC405B9B3AAB0CBC72F7C' : true,
+ '3FA41F7E559B84FA6918FAD6709B5026B05A1C1AC589049A4D5F05F3A6B7D65B' : true,
+ '3FC8022D0C28EBFD45DC1D07E14F9E83F0CAD2E7ECEDBFDB991E01EBF2400F54' : true,
+ '3FC92874F07DB0DEE11CCB2CA7BDF187641DC78ECE4C76E71B2253FBBC17E3FE' : true,
+ '3FCBCC65096D7D731244167CCEAA21757E56D6EFC05A632AB3E062643E5B380F' : true,
+ '3FE67F5B06535FC13DE42FBF82AB1238C7C899491A460D62CD2FC08DC87DCB73' : true,
+ '4007AA6804EBD54CF48E514FC8BE08DE5BBBE5E6536D678DAC71DE0C05D05B07' : true,
+ '40812953C19613BA9042911FFFEAEE1C00A952E5D97D358B6603AB7DB69C867C' : true,
+ '41717287E2E15F9E79F144B822458F9DBD930C194668167C06B87128E9C21042' : true,
+ '41748175B1E9E26507156E326B06719603CCC2E54D9D1FAE0F6881012101F692' : true,
+ '4181BB2178C564FEA4F0F5C87337921A1DB4C1CB1264B1E2168FFAF334C7DA55' : true,
+ '41A4B72E197905E02DA1199B4B9D2B20CA9B1502151A14FE19D8470FCDF60E0C' : true,
+ '41CD7602C418FD0831F1F207DD50A19A0A03679113F8508F43DE863AFD32FF45' : true,
+ '420E1CF047C7A0FEA28411C545C2E0AAC2AB31DE5BBD13F63022C0193E03DF9D' : true,
+ '422E906DC5CFDA0E2B9711F05E3A36299B9298E7D23392C3ECB11C4173F9DCEF' : true,
+ '42A2B7BAFC9E81A94112C062E15EC8017861988A458D8C52A686702633559BEF' : true,
+ '42D891E625A2FE563C10EC705A036928A9EED088915D480F5DDEDBC4BB35A557' : true,
+ '43555C20820B179886354E63251A21247292B3B7BA46D8BEE860A0313258136A' : true,
+ '440D00F6A763CEAF241756BFC150BABBB724D3AD48D6739ADEBC84004E24FB7A' : true,
+ '448771ECDB6FF9B0B1A817E6C23048CAC06987EE2A6FCB6B84A6F0A75D7DAA6E' : true,
+ '44C748D62020862C698F3A1BE86A0261BEEF4337B6E28B3597F7FA0E4A01E49A' : true,
+ '450608B6DCC297A7FC00DACC4455E165091B8A4B56873B61C4ACD495A32AA2B7' : true,
+ '452F8C17E67135B1FF58F58BC411FA165E80838C8705B1F6BAF1C90F287BBDC9' : true,
+ '45C9985056B6629C3B4566E54648AE5DC504ACDA5569CE68023C39D9E554A217' : true,
+ '45CEF64AA866F2A2A72E13722374190F8EEDFE984F022C3B23B492A073741EBD' : true,
+ '45D1C3C1E96982C752313C9059D4D6291BC0652ED7B266E25F67738E4D74915E' : true,
+ '45EFC525BACC3D6E5AF98E1BFA4A60582231A423EE2E52D5760C184E66241DA5' : true,
+ '4603C35A8304F6057C253381D39404E8B40AE0958B4EB2CEAB7777CD85802C0C' : true,
+ '460D4CA817FB242D2263900689B3CBA7261A390B018391C7E1716991BE8ECAA0' : true,
+ '46236B9468DB40FAF467AFB0C35B517E514251530785695F54440E6730AAE44A' : true,
+ '464CC49DD9D781670D5B24D203D45F2CD011F63C8775862C2D7FAF4B23C64EEC' : true,
+ '46601DC361A7306BA942625822C757F0702F63A009A5B0FA96CDB92CFDD07FB9' : true,
+ '46CF8D35D0A439E7E4BF019F73EBC9636C9C3DCCDBBB4B707A21BC4B36F3EB22' : true,
+ '46E74AF8240C97D2E91E118761CA4F74371BF7D2266601BAF6084BB1924B62D6' : true,
+ '47F4235DE4F1BBD02682F65A8B465D04721124582B6DEAFDAC164A699F56F419' : true,
+ '4800E67D74EEC480EF1C5E3B2CF779C940C3177A5713BD1E1B8CB445DCA65345' : true,
+ '48544D794B99D6942B8C3B2CF051782C2F6CE051860BECDE2736C2CD6A429893' : true,
+ '48DF42F374FDCD58EB650256F421F6C1A73F663DCB8DE0972DF9421205509F8C' : true,
+ '48E8ED415FD8EFB4407D0C67F3A4EBF15286569D29D566DEFA8B7AD8F135A5CD' : true,
+ '49558145AB82E7F795C2E45402260F1AD1ED43D4DF145CF2577BA1615CD00843' : true,
+ '4A12F9678B1A5B4677054BDA1CB6B41AD8A4F556A184E7E4C33669EDD31EA50D' : true,
+ '4A25089DCED84BE3DB1816DA1A2619E2D39D037A7561AB7859949D1401BB6C39' : true,
+ '4A69353F89397B7FBF7B34B298BBA87342EE33C9F5B75660195F8B308FC892E9' : true,
+ '4A80A015BEC13BF13BF90A093212BC7E939DF1F5F535730273342AE942769A2A' : true,
+ '4A978057E01B2F443BFC218B48E7D00D2542DBA58ABD2609ECE7E152A8F86292' : true,
+ '4AF86DB451BCBBB3BD8BB3D5982DBF4451CD96394540DE9FE6210E69F7C2F8D3' : true,
+ '4B14ADF4E6015B7F5E4EBBEAE635E5FCA547B1885B9386DFD76A25B8D2A2A63C' : true,
+ '4B29F275C3803C8B4E50951895FE2A4C94442F4A7D14922D54EADBCAAABF4056' : true,
+ '4B50DC7F1BFC4867D02B551EBF66F63645DD5BC27681BA715154809449F381E4' : true,
+ '4BA4EDD1EF23CC54D0287D277BD59A3EA14C6E7B37C508155E0EF9A01D048318' : true,
+ '4C31265DEE511FAEF9E6B7543D920AB1884D164D630380446406C4C4EFCFC6AD' : true,
+ '4C71A0F5907EDCF7950980BCC1B7B6E00141C1FDD4A50D445BB43E1E054B59C5' : true,
+ '4D112C44F7DBE6E0A55667E639E192515C54B00CE5E964EF696B13AA049BA656' : true,
+ '4D26A014A4C4007564C743D9BBF9C2DC9A5A881C05E549DFFDAFCD3814F3966C' : true,
+ '4D2E2CCFE3A068F7C89D22E4EA6F738F99D3E62287FC8B9C8787D78A7EA77B30' : true,
+ '4D3CD85A0580A0298BECD2FA69BB246CA91261145CA03370847FEDD2BA707CB1' : true,
+ '4D6CCD149A9BF9FA30CD78345F827ADB4A51553FCCDE1811FA39872E293EFE59' : true,
+ '4D934EEB8A02C8031AB9A12A52416AAEEDB4B2EE58FDAA767FAAE917AAF8B645' : true,
+ '4DC761701AB68524A6BACAD94CAF1D8480229B66D8B9B9C0CDA3D3B233A6B785' : true,
+ '4E49086BA0B8B96D1C31415D8A1464F19B93CF45B46D04AE4C21672279ECEFFB' : true,
+ '4E5AD8D52C37A505176F9BA95BAF43CB5FD5A7FC4654DC71178ABEA8188E7ED6' : true,
+ '4EEC544B64210519ACB153834E7AFE21867AA949946FEB78CE5A254D12A0934A' : true,
+ '4EF7A69DC3625A39A416CCF7F607228D8A715D7419781218E4B827B83A504CCF' : true,
+ '505707224B14F1FFF2F5937865DE662C85B0C21D090C59658E24B53CA635EFEA' : true,
+ '50CC4D1AE164F66EC09AA6B7D5931074094FA1BB6788AFF3525D7711449CEA81' : true,
+ '50DB534A27B601C2268FB45FC5F496F4457DC030EBCDFD6221A85B1D6F612837' : true,
+ '513B3B0E023E7013AD1D77E77AFDAC7D99627F8EE3C8FB291064D6D56C3CDFE4' : true,
+ '518B663FE089FF3E12F169F8EB5DE2EDC6635A11F14B7FD4207B307BDF2DAED5' : true,
+ '51951278BE011B8562F6F9F629855BCFC7F28856755EA274F29109E2489CCAC4' : true,
+ '51D06F5BD10CCE82EF993587A687822C99C3D8F3DD2F04408E99A5388C07333B' : true,
+ '51F3918557C9F6EED321444D170BB23E4A558FDDE7B966D11FC6B426C51D1676' : true,
+ '51F5AC607BCB1882F792585357C63B23D08267F717AAC5BE2AF557123EB19446' : true,
+ '52064B1A1610B2374CC7319E51B4ABFAD46FA995B9447DF18ECBFC68382A9ACF' : true,
+ '5208CCACD74C6B569607B3AAB6639B318FD5CEB9E3A3C763F11D6C4BD603ED5A' : true,
+ '526D901BB36A96CF7AEA36490FE1A58EE0970BCD409CDA3E8659D8DDDD59560C' : true,
+ '527E1D8CBE4936132EB16202101509A3A0535CEF78476DD9317AE7A31C097327' : true,
+ '528F9666D1C35F9AB6C5E9E6496B0618C6A3F5C37D6808E0601A8F2829A352F5' : true,
+ '52AFEFBC93919093868483354CF11C747FB38F946CDEFDCFA6E5117FB0F5039B' : true,
+ '52E62F52537E672C499E0902B25BC800C87BD8C45BAB7B9683811A7D09C4559F' : true,
+ '533D8997AAFFA435583E114FAF33F105F8CB1B87020DC86F5DA948808EE81AB4' : true,
+ '5376577409E17E8F37B2CC6FD486FBD356FF2AD0B5EF520DB7CDAD06C6A6F3E0' : true,
+ '53CB6E4A76F1BDA96200BC21FA943685A88C33EC1A4510F4073BF54644475390' : true,
+ '5401D639B63C7A3075C6C5B61F64AD5246B8E06895EA510AA9D7C1418C3E06F4' : true,
+ '550C98DA3C1CCC2DB49A389D57397C73C4304F4A4B65A1EE1A300EBBFAB97478' : true,
+ '55360AB9E4626C6A5CABE53D4DC3FFE3339671F040B96E93C3B8ACB6CB1AD4D1' : true,
+ '557AE25211574C66868033236E50981E6DD3AAC09C9A7916CE3A26D03420E774' : true,
+ '55DB7B0ADB76D9C23CFF1CE64083074EAEFFB1F83642E1AEC2A7FBD365A9E962' : true,
+ '5603628307C37436A0A6FD92B580DEDE34FE08652C3E73010745E471230A5B36' : true,
+ '563A36F203C4A0D86BC2ADC38B1006499E3CD3D651B5C97AA848494CBC5582AC' : true,
+ '56A2C00BEDBCD3A014C22A89A1E887CB0F9A2095FED90ECF196F6719EFA35A5E' : true,
+ '56B6BEB3100D40CAB0EA4E450188CDDA653F473F3F182578AAB314006E66FA5C' : true,
+ '5747EF64E7C857584498831611D042B568A3FFFBA79F476ED22F4D07E5239266' : true,
+ '57A0A93A8193B5CC90AEED1D0B92696C9516F2C3A6FAF86F7BB8126B5A691311' : true,
+ '57A0B57635F2D75EBC9C3B166E68E35E1CF91BD074AA9D5CBCB3359D93F02859' : true,
+ '57B2958E7031793509E2EB58DE05C460E0791C4F78A43244640F7926FA3BD7D6' : true,
+ '581247229E9E4F0D67498BD22646654479F5E0E21C96DF47CF84EC94218EFAA6' : true,
+ '585568A4010D0650BF0F0C2F78402F25FBF6D0B8C82879E5B475708DA6617E35' : true,
+ '5878388C3C9B65DD3896113A5E88AC085793C21BE84ED1583D7939DF87D09D7A' : true,
+ '58B590F006C3B293A57D41FF491EDACB580EBBF8AB20A91D6F8F0ACC3D3C19EC' : true,
+ '58C1439E2FF88E70D837218AA52270706EBA8C66B587805DC54AB12215416A05' : true,
+ '590F7D88D52E1E705632486F4CB869B519331ABADB9B139951F8705F33E42C55' : true,
+ '59148BECF90A7738D4915EE2C70C38F7789A26131E0FDC0240A76CA7153EAC00' : true,
+ '5A4A8137AC418073C8912C4393D72D833960641E7343C43A2382861389B433D3' : true,
+ '5A53389620711EDF33A7992A0ACD5EDA7D1AB729D6513ADFA26AA03C8A38675E' : true,
+ '5AA7341552FF047164227AEFB41437582F7116D76B854F54920A5D6A9B72271C' : true,
+ '5B3B3DEBC9899E074F2AFFE1A660013CDFD66E4F70948B72AAA20DF84433A80C' : true,
+ '5C1BDEA6E4051D2FE99D2502AC86707BD008636200DBEE30816399996D796DD0' : true,
+ '5C3F4C823A953A561E8D0787CE7AD8FAC7434EF57CDEFA4520C18A5667C82003' : true,
+ '5C568C32C672A2B3F7242D5CEAA2718B08CED5BDA028B84224D605079DBD0DD7' : true,
+ '5CDDF1DF7B5333F1B4C0FAA66297AD72ACA5258C5E9FDE4B9ACD9EAE832C7A02' : true,
+ '5CF1D1896FCEF8E0B72BF6E617D8210ACE7DC6393E38FD4BD4C68E2EFE2EDC03' : true,
+ '5D0D6A8831205E33D40CA0CA2B8F396D05735A8D91B97DAFA61FBCB60ACC2BB1' : true,
+ '5D133D3BC732EFC05E4C91931F8ACEC74F9BE1FFEC30F8C5E38616D2AF7BB20D' : true,
+ '5D8DBE824180E72B5972E68A8373AC984757EAD57281A973B44B18C36DF6724B' : true,
+ '5E03C9E7A51C7F8539BB4B25ABC9ED0CDB47B48D6A07B0C051D38939AAF91782' : true,
+ '5E650BBA8E8037D6BBEE78A730F740DDDCDD7EC828120AD912F4BBD72794070C' : true,
+ '5EA032BC171418766EB1B1F71A7868FAB9DA3C484A487BB1FE062566DF166002' : true,
+ '5F05ACF54EAA38008B650AAA2DBB3722805C793616B1A21B43E1879107254E38' : true,
+ '5FB6ECAF5FD5CA42241B12521D7BB6F06B7D804C60C84D7BBA7B7A7543FE754E' : true,
+ '5FEA0DFD20247FA12D63859439FF9F4D5D0207D6E1134820CAA9CFE4A1B08FEF' : true,
+ '60B7C0E860123DF4BD6CD8EAC6560CAE6E9CE12DEA9B119B2FB90C57DB328EDE' : true,
+ '60BDF27D143EA5E065460D76C87F245DF44D9C1D5D818C62832A3B83B9973824' : true,
+ '60E9F3B150DCF1BD90562DEDD083FD783E2CA9A982C08BCA2C455F50BF977B98' : true,
+ '6129C7157898F2D29FDF04A78AC6730FFB248F7467858C9F3441A5D4D6B88C8D' : true,
+ '613E70A1BE3CA6314EDB7C00B2477990271E0C8DE8210EED56ACD391E8CFF28F' : true,
+ '618F1FA3F38C857898847A865AE73D87B0071C8DCFD4EBB7E80828B11862151A' : true,
+ '61BA185CD2FAB39562813CDCDDFCD75184A1572E2B2B87667728C2EE8596AC65' : true,
+ '61C0C838E39FD9CB6B924046875626383C616DC9E106BFB5573C5CD2DF7C8738' : true,
+ '61FDD344421DEEB7314FAA2A6C1A5CD97720CB90B48C801EC4AE74C7D88F1E39' : true,
+ '62210E1578BEBACCA159EED5A0EEE3192B7FA0C17FA2556A686E28B251D80C60' : true,
+ '626042CAC6DE8C95C77C0E732144FCBD63418D72ED04CCB42FCBF260B38B21D5' : true,
+ '626D3DAAE3451C750616F520086766043D22C2E2C34F483D6C7EB06E76ABF206' : true,
+ '62AD913E74BC37FCF69CB86718E13A47FDF1440C2B18A4241D3EEE7831456160' : true,
+ '62B59DE2632C2A03669FF060A2C2047B9A95F49050C64B6BF5A782806AC10E99' : true,
+ '62C9A052080F8EBA5E8FEB9615B5CDDFFF1D74F8467653030CB1BA12337EB5D7' : true,
+ '63448627F20BDD4F11B278941D82DE56AD3A689CC06064D867FF060FCFE29A49' : true,
+ '6345E8D1EC10F5092710B275C7E48D8CD6C5D1885994B18DBDFCB2E5AFB9793B' : true,
+ '63A4A98B9778705A9CD9A0F1A40827B0A6C86E2A520DEFFB1AD8F815D760D992' : true,
+ '63B7D2C03D1507A80B8617E50895472A3C9E47CA34E8756069378DCEF952CFD3' : true,
+ '63E6A22E453B17B4EA3E35C6E39EB315DBB77A237B1BBA9BFB2B3BCF675A63B9' : true,
+ '640AD0B7F4803223887EAE106DDD628BED925569AB309C01E1C8B640FF05B2B5' : true,
+ '644685FCA2BDCE4C6D4AA3876174676CB961619414083ADA90FE2443CF929D32' : true,
+ '64831454483CA9CA55859BBD324F492638DA8179EAAED19EA3CC8E16FCE7A83B' : true,
+ '6489A71D718B44D5479D3C5AA2CEE70A2E6738AF25F0288B2BFFEF833280C0C5' : true,
+ '648B6539CC321D112EE1762198FAC01AFC8B598E29317833ACFA9C02307F5E72' : true,
+ '64D1D9522071A54B43A6C43A759223AEA7AE209FEAB423EA24E3E95FD83BDFCC' : true,
+ '64E4359CB75DDA1A17413906C2881931CCBA16E52A52F13F16E65A752C2097A4' : true,
+ '651F8FBEC4C5909A0FDC3B8E8D557574FAF01B33981B5B725311B57DEBB47B24' : true,
+ '6581498408FD7D10902F7D56704A23B3278D6EE675FBA214F305D43C1B620CE9' : true,
+ '65ACF48C5CF24783794CB8D5AFC30737273D3DDF93F62EF803EDCD05650D775F' : true,
+ '66795B4CC33E5CF75F1467F1D97528306D8CFD78DCA8D838A11D5A4E6D3F374F' : true,
+ '6688912D47D0A49A3BF7EBA09AFCEA36E0D4DDF4BB571B383C134B763B17DF7A' : true,
+ '668B926F5EAA59F351B7ABFCBBE5FA17B547B01C5A7D4AE385736CE8FD13359E' : true,
+ '66B10F427AD63DB6544E9E20191BDE4F827A7C96F1DB17E01E0B254D67BE282E' : true,
+ '66D67EC6407BBAA2F4A0EAF49D81F223332DEAADC96292827CD749DB07A82C02' : true,
+ '6750705DF61157E112906D9D3BD36F21696B0DFEC5D6E1CF728A443D76912C57' : true,
+ '67DBD139B060C071667F2A45E06C7E159117263D593C95138066C7BA3AD20DF0' : true,
+ '67F7903A02481CD91A864899AE21E1D8C7E7D3FFEA34021EDB6F29C3DC9FE9CC' : true,
+ '6860622481E0AB0EAD93B771290792279985D4989D072D5C1E376F451FFB1360' : true,
+ '686E60A6CA7744B42193C83E73617621EBE2C59C438B7A32FEA9D7DD14F2072F' : true,
+ '688CBCC96F65054917A6D042282C3E33BC4B2F7A7F3C2AA0EFA97F31F2FEF21F' : true,
+ '68F575FF9F2EE5CBBE2975DB80B0D2E8582B2B5A1624A70EE6470FD562D59E93' : true,
+ '692C0A28DE13EBB75674023CC105A5F663CF5C67153225EF1193209E985CB1D4' : true,
+ '69643C10B6E53A5667D8BAF683B1D566BB54B001E0588D7B791E648EA5681BBB' : true,
+ '69CE183BD9B04AD76F8FEBE25095D92D95888AA7D8735400158CD60B836FCF05' : true,
+ '6A7D32C4F099C8D7ECA61CECDFCE82C5D241F33F6A02B3A00D89802D4689DCBC' : true,
+ '6AC112C1828538894A1FAC7CECE0ACFEE75658118041513498E880274BD2B7C9' : true,
+ '6AD39077DC61A2347F25E34A809107D3F11E18B1E197A88A9A39F5FDBB0A3861' : true,
+ '6AEEBBFBD6A2EB3C41164F87A2491C293A66DB518999827273FDEA3F1892ADAD' : true,
+ '6B02CD14A3675354A800006220E94D8D4D5F9774D60EC984955FF720D927E529' : true,
+ '6B16CAD6D99596442162EEE7113248C0C77EBA7DBE1D3BDC044AB9802337D2CE' : true,
+ '6B8153379F9AD865DAA48C0B805430D7B62D6624C4AA9389FBD770A366439995' : true,
+ '6BC4B8F5756C6E11852DEAF28C2208733B463931BC5413937F897D4735CC2F01' : true,
+ '6BF2234F99577BEF099F5A651C125E660A765202F83A7FF24C82FFC87F87C3FB' : true,
+ '6CF13EB678D9631F8E425073339FF5B4FC020969732BBE54ED0D3087FA774303' : true,
+ '6D1FC10BB256C71CF8A543B99AE433A55FD8EA467FB11EBAF9ABB24C923B4DBF' : true,
+ '6D2E55B7B10EC7E3F82F060350C9BB7DAEED8B6ACB8E79B4B088D9B711A9CC6E' : true,
+ '6D4210568EBEADBB8782B6345952223B49407EEF3F8FEAFAE6D14DDB9DCFE710' : true,
+ '6D53AA3328CC9AC46F2872113922BC105CC4A5C2B3EB7F45C331A93BBE4ADE3E' : true,
+ '6DB177AE67C272A729818F26A5DC8A327236919BDF09E43961204BD9538CB09F' : true,
+ '6DC90241CFAD3946A0A53940327E950D8D7248FA5896CFEFB60F543000A0B165' : true,
+ '6EAC221C01F1C4E158E51B8AA15965260D186BDF22A579C9CE8D89E787A36FB3' : true,
+ '6FCE4CF77E254C2920BE515857DAB1929ECE7638DD8C370C1AF6A374F36517A6' : true,
+ '701E5C167D1D2A47E29F6E0EF64D59D978CA3287D20E3590ABF531EEFDDD885F' : true,
+ '704172C04EB3CE46ADA086772ABDD4DEE208909ABA10D59D1815E9533107CE5C' : true,
+ '707966CCAEC5908E84C5AE646566426234491D2F78CC00BA7C7B9E5F009924B0' : true,
+ '70A137BA9CBC1043B06D08AF2800FC09F4D3334ACDC0915124CDC834A77564A1' : true,
+ '70DF998D006A8684F543CF929F8223770479451AC680070169CF11B6B409CBD5' : true,
+ '711280787458F0E54B0C9294A54270FA83E8CAB29E212ADAF665D7F6345C4DF9' : true,
+ '71CBA0C7ADFA0E0688BBE75D856278A477C4041C6F0895AB384BAD02B9D951BA' : true,
+ '71F2DAF17AC798022DF73260BCDA153082CE08952CAED20A66A588B46E83000A' : true,
+ '721728072AA0815DC7EC109C8737500ECAD862B2003518851C323664A749BB7C' : true,
+ '722368B696E375C97556E68FA5D53C3BA7CDCA15B13B72DB9E49090EE7C9C163' : true,
+ '7225F14A44AC70458F5C98BD93C0A381A68899F718AF8300C897612E65461827' : true,
+ '72950D958C6C1FFDAED4C597635776C7EC60B32CC683D03AF405B023C686FEC0' : true,
+ '72F3DB1BB2B0B3D65683F62D927E20C95303A00E8C845E0088E4DACD4F3B19FE' : true,
+ '730C9CFC51120B6E5C66F07772ECB96F2933EB184A397BAF90453D2BB43BB600' : true,
+ '7334856F73A23C5F0A60FD1EB2DD14EDB444B1B8B62516FFFC38589D1200B09D' : true,
+ '73A621FFE0ABD75757F5C92C8EF20E63EC8F4A279A450BACC7E4FA9D75E0EE5A' : true,
+ '73C4C95F998FC60D5EAE1283F28C36C63697C481E6B321EE7DC46DAE585B0E11' : true,
+ '73D889F527C021A7BB8B363C2467F7499145D97DB7B6E0207D6CB12DFA550903' : true,
+ '74395721FEE13356EFDE73462CBBFB2A471B4C95563BCDB979DA57B786D16A88' : true,
+ '74711F9774C66CEC41DE4FD32197132B13A40A6758A106DC95BCADB9298A6241' : true,
+ '74A9F7B27B38326F64792AAF791E5A5969071CD05C8ECB1E068035AF9AEAF482' : true,
+ '757071EF34F3CA907D7D29C6420EC14B6953F433FA03F2049636F55265E456B0' : true,
+ '7572D3C2860E9D28159C0337E8DC7C693F307AE0F1F02E0C35E091AC1C1571F6' : true,
+ '75893F8249D9326D2316BFA87F7DE3062EA1E00116C921C6876AFF322B636664' : true,
+ '75A9264209E9CFFCF8C4D74F1988A6AD0F509269A5DDA3DAEFC0068EDBE6AB26' : true,
+ '760650CA663BAF50AB023FB340DC4316998A7E66FE226C3A66E7D31CAACC9330' : true,
+ '76180E9A156833EF0B8FA7D3C83404086F9F1141580FEB3710AE5B93B2E819C1' : true,
+ '7621A0521A873D9B899C1F5BB52AF07870D8C98B5FF0797383C26A7D151789F6' : true,
+ '7644E55E75802D6FF784B75B8D77DCFADDADA23DA2FBF95836FA3CB975C6B982' : true,
+ '76498ECB08242DC8AB6DE47C0EF0F87127C2809D2C1E1B8216D6297ED7D791D0' : true,
+ '76D1EE820C99B447CE9277881319CD5B5D2BDE8182D5AE5EED8326244CDA6621' : true,
+ '770784FC2B1A52F110194800E972006E868F055C52A8BE467F3AD7BCD7E441CC' : true,
+ '77C5EFEDC19C242BDC746C5EF4A1DF4117918CBE078CF6DD65FC274DB64CFBAD' : true,
+ '780AD07FBA71E98848DABAE3B6B94B292E5959CCC36769683E0213E78B759DEB' : true,
+ '7871679EEF661F72EE1CCD043F1B7C597E8F23196B653B42634C37F2B6619B00' : true,
+ '7889B1659DAF073B50A3FED9BDD6CA3F3F69E90E22C9EAC126E2F915C476984D' : true,
+ '78E4E5B9DC94A09084EF738F43D30114F90F95DDC550D6BC2ED203D722323EE3' : true,
+ '78EA89695196A279F7B44D8F1AA15080C91C3BB240F1D1878A88F2B27228D430' : true,
+ '79244B0AFBB3B26770A470A4F23555757DC25D3856F56D0096D9F06EB47D5889' : true,
+ '792EE0B202E6A45AAA85E918497D9C9F16FEAC99500A7940C0FC812ECC42120C' : true,
+ '79506C5663C38F43902B55BE2FFABE0757A806105C2A18473770E9DEE5322E40' : true,
+ '7A081DEE8006EF40615953A1EF9BA820BADAA31338157E69660B3EBE7852838C' : true,
+ '7A95B01B834A4CFF097B69C8D84488E0843D9C51A8045BF5AF6AC2CEAB65B079' : true,
+ '7AE7C2EA08D84EB5EE0F978D061FC9D6DDFB57C1382D5215977205894898E0EF' : true,
+ '7B90E5B537B13743AC7B5B9F3EA28B3F5F5E95A6D9F4AA0904DE22858F38C780' : true,
+ '7BA22815A242ED9FF3AA2FFD5F121935346190B63E61E0EE4EFC6EAAF76BA6F6' : true,
+ '7C63B78CCB8DE59051349EFBA4A9E34EB627F65855F3C754312DCFCDBFDC270C' : true,
+ '7C99FBE3E1BF4CE4683186F8BC44BEA34B07919C1542ACDE9420CD75BBF3F388' : true,
+ '7D08B399CE7B4D7A6DAD696C24FD870D577ED45A8081D3E1BF34577B6DEC77B9' : true,
+ '7D3EF8DEBFDDD39FA7CA90EAC62E660639521686926488A315B10FB2A0005F6A' : true,
+ '7D7CB9E4195E89426B889E09DD6EF0018B702EEA4C8E1C5C39DDB538E20CF150' : true,
+ '7D817F280F1D664E0C9E717287D6AADB1132D4F3A3E2001B94009119733C9434' : true,
+ '7DDD5D1914FD375229088F2E7E2CCC9F557B2E86956356D21E4FAC6B5D5B7EC2' : true,
+ '7DFD6433613550E46711F591EB0B0790233460AB951DCCB4B60B61C91C359B83' : true,
+ '7E01E1EBA9D9E46D3DEBEC868180199AE64DB3BC878F66066E91CB4C060B55D0' : true,
+ '7E0AB095FE17F430AAE0B4AB7490366DF97BADF13AC223D96AF0913D6919BE7D' : true,
+ '7E723113D07305D5E9843032E474637331F1567CF33EDD8316059148AA2E3ED8' : true,
+ '7EAF183A91E8DA3866531C499039CEF3AEC4F214BEE293F268A28616B67D0474' : true,
+ '7F1566D05D1E3A90A9D5D551AEF51D2F1827FC9E82922F2BB32A08CDC5BDEC7F' : true,
+ '7F7453584CDB1B6048A5508FD8FE1FB7009FB225E754CA38FDFFC28206BD2640' : true,
+ '802B6D5941983A1F76B514028EDEAC33214B4F27AA490345BCE94DF9B1494516' : true,
+ '806791E1F1BCA3B3AFECAB7D1EC6FD66C2616C6CF13A3256AF0D53AB0A759BCF' : true,
+ '80BB61C435AE010A1BBBC72F9CDD1BA74CCFFAEE4C74E07446ABED3DA2685427' : true,
+ '80BCFC1145A7F287ABB29FD26F6FF09F2F9299D43DBFC2214B15BC346D1A7EE5' : true,
+ '810C819EF5A6F077751EDAD2FD0E77BDDC9567EA2C27ACDBE677BB3FBE3E4E4A' : true,
+ '8117437E2D53CBAF96B03A772D719EA4783D32C4401D6C590BA9F941C52E54FF' : true,
+ '8133AEBBA592FF513EB1EA61723A0CEF57A583CDE66794FA9DE2FC0A8F573B54' : true,
+ '8179173BEEC9E5175036B790F2CED009213A8FF7D62CDED95DE000BE2B03B068' : true,
+ '8253A0516BAE8FA0D24AB03D7E4AF8898FD1EB8333D2925CE515FC3DB6ABC5CC' : true,
+ '826F129EED33C26A96D2FA3EA71B7897E065E2A68280A77C03E948C9EAD80945' : true,
+ '829124925C3F7AB9329A17C8329D55F04DE8C98994845083D9293F2546CFEED3' : true,
+ '82D1AEF2AFC46271D18C5FE50811DF9A5EAB812156C2FE6F531A34FD529E75A9' : true,
+ '82F25208D7357EE223C6715E802CD0F8D019E3004DEFD76A90BFAB18D2DF07CE' : true,
+ '836E748E62C7EF083DEC6A11521F79E4F2EFA40CE0EFCDBE43CF3228F905CE14' : true,
+ '844B51F620215D6845EB82700563692BDD5EE144D097D24FFA8D99C8FB5FCF28' : true,
+ '848E7A1C6E45D88BF111E43067FCF92F6F17BEE0B52C99381668797B108FE80A' : true,
+ '84A093B67AC79FA09CC2E40B54BE4027DE363B86EDF64B623BC346188B877ACF' : true,
+ '84A8C623C4304D57CE03893ACBF4E51FC9975C58658B89127508E5C33BE992A7' : true,
+ '84B91F7D19D03A64195173E28A98C6A24AD166106B5AC14B36A404C45608B2D6' : true,
+ '8540F78EF676D50879CFF30B3CAFCDCDB1287CE9472D0E39AD221AC0B049BF5C' : true,
+ '8544A63131F49B49F2802FA5FFB5BB62D726E1A5972F668781040E2342770042' : true,
+ '8565CBCC3E3484929C4C2D7408530788E83FF8CE2B8502125176AA2F89D3C350' : true,
+ '856D54922C6DB9C5747A1EE5ADB099907C63E0BB928B1D00BEFBF81E6B0E83A6' : true,
+ '857EB3AE3D76F7A86260D7DF2583D65053D7DBC30558CF41078A51A841A15408' : true,
+ '85CFBF3F71BABAFF31DBBAE3EE6615A269748572AACEC462E501B017A4B58C2F' : true,
+ '8620FBF8F4B3D858B8AE9A6EF3423068026CEAD38ED1B70B12E65A66EBE62845' : true,
+ '8632291EE6C74182159207F88A43B60EDD3715D9B23CB51B878C7DFA413AEBAC' : true,
+ '878C8800E459A4D4B9989B0DB92C628E8A13574E71B3324E50484F70555B840C' : true,
+ '878F9A1345B5F3F76831E0AA2CEC43E51FD88455FD70FF0C671DDB8D8646BECF' : true,
+ '87C002662AAAB5BE7B6A7CF4B1CE9036E3A2A70A0A3CD80F64005C889ECCDDBE' : true,
+ '8858520A8D4E5C88D777C33963CC7F43E796B555E7FC573681B59DCFAFB43EFA' : true,
+ '88A9F13EF3721A05CD57C6E13E4B2D6F699C00312E92C24E04D86990177BFD3D' : true,
+ '88C3951EA08F6218D53C848FD0745408A54B8588AD3728B9634AFF9280055838' : true,
+ '88D68B8F6C5B10D7E9413E6B62A450E74806DA84C0EB558EE9E98E2BDEDD16E7' : true,
+ '891419933107B0EC0222BF502DB271240F352C825D2E32776842C40D13C2F8C1' : true,
+ '8998929C795E1C1A4D769B9E0FB886892FBA9D8F1542DD894E15E12530424BCC' : true,
+ '8A0A728D550D96C56A17DA2A0A97A6A9CAF22D5AEC3BA7A6434C51FDBF698785' : true,
+ '8A0D973D9BC8BA74619B1D55816F7931E1114D8A72901D7AA3966A89D96A0AD3' : true,
+ '8AA440E22415685F4A009BA8F14D9B8251614D78159C926A712542B0E9FCA143' : true,
+ '8ADE74E6435437386C63E8C22DBF3BF0533A4B49E6668F5F15824AB58AF721D0' : true,
+ '8B1225A29F8C7203B6154A99814B028517B03B3D4B5A3E25239EC91650206C0D' : true,
+ '8B41B56DC76B41CBEF93FD4F1F74525CF5B11723140CB81A7DD29AA3D95703BD' : true,
+ '8B52AE402628DBFA70BFCE1B172D676422D5E720F7E3AE2E7B195D4FB4E3F285' : true,
+ '8B83806B610FF233FDE11E892A0023140E5CAD1500847E29F5E5C6CC21BF33C5' : true,
+ '8BD1BB8CD29EBAEB36A58AFE2BA070CBB92EC003064B71AEC49E812E39C2874E' : true,
+ '8BD3D0A64D73FCD8450DF0224F56F2B44F88D2B89B94EBBA3B5CB7E905DFCB74' : true,
+ '8BF51CFA32BD64F3D54AF63295B5F890FF439D7FDF854D43F25F4D72E396021F' : true,
+ '8C2DDBA5CA9E4CF79937A5A3AFCA79F371B6F235B37308EB53ADF12C319A7EC9' : true,
+ '8C4AA99089DE2B772FA47DE3D9901FE175AA49A46B9D056BD8211B53848276AF' : true,
+ '8C6DDA18A4CB339717E1321FBFDC9A3ACC52F2FEF6FB453EA389A2B43FFFC63C' : true,
+ '8C742B891F670721F4F8E1D4DADEC74C9E9256E0C7D132578973823FE27C3A33' : true,
+ '8C959CC99EA9E228577582BB36DBC373836E4D91CDD4FA3C89B20A289B11CD23' : true,
+ '8D0394524B030A612B174B7F2FA75A535F6DE732E9317A394BA9286CD3F42F18' : true,
+ '8D0CF6F0B227BE9394DA0DADABAB81A44900D104A915645ABF030220F3AE187C' : true,
+ '8D1EBA5F6A209614B68AF63D583392DF844036E8BE335440D0740396366FFC4C' : true,
+ '8D2E6A0020C2C53A264A392C371146ACBC83A8966438387CA289807BB5583C15' : true,
+ '8DD64FF5EE29EAEA20DFFB1B446F1441CD291260939D41C7784AF872CDD60FAD' : true,
+ '8E8FBD2654D291051FC080C47960747B4191C58D85765C77CAC1C239FF3DDD1C' : true,
+ '8EB48C6A21AF524F446D3F9F4BBB78C5CCA368441B9858FA87DD6664D603AC2F' : true,
+ '8F31ABA69837A432E88579184085B0AE867412379E04666EF880DE539CB03257' : true,
+ '8F8515B35B665B69D0DB9661EAE9FF0829B71CF4AFEB3BBF988BEE73985F5D3B' : true,
+ '8F9608587BFDD90423D96C82A5338A09203663970E435AF25EE4079922B60E21' : true,
+ '8FA478A1DE3999FD32313D519AB1BF7DA3C485C1EC90176E34F82CA74EE170B6' : true,
+ '8FA49556B9E8C97F768F94A3D2653ED2E3E927D31EC7A916D0744BFF07B5E685' : true,
+ '90C2F31A64343BA4CBEEAC90A43FCBDB46932CC21CC58095FB6D6CDA7B33F362' : true,
+ '91490F346E9CE34F77126105D7CB01AD7C58E0891B398289095613F1D1162F6C' : true,
+ '91728081A414570C9CFDDB6A7F70CE56010D44F4E165762B73F4B05436D85351' : true,
+ '918B02B75417DE289310E10FC77AF7041D1F380F02939D64F063776F121AD61E' : true,
+ '91EE28B14AB2C7571BE6CDE2D75FD4C05C960FB033DA819EDD463D5D3C494591' : true,
+ '92059CF4A0175D14DDA7D7EC71DFC76A7A91A75F4B9BD886E5595413920885FC' : true,
+ '922D7192C60ECCB0A2367C8E7897C8289C2CD7010B98CF82A964ACA2B56D8BF7' : true,
+ '9244CDCD0DED69F9AECD82846D0467062DDA89CD32D8174CD69F9DE602AED97E' : true,
+ '9295435D6B38A570B2F537814147422BC442A7E39E1AA307550DDEF0AB93C3DC' : true,
+ '92E91A15A0542407788FCD78EF9287724B2B25A27F703C9FBF2F5BEE709A68F3' : true,
+ '92FD30739B92B5509945785B19CA286449968DDF5EF7B8F44C6C8556711DD3B5' : true,
+ '93671EC41A75DADCAD2454D2D9951DA643ADD6C899C6F4EDF6E8806217949732' : true,
+ '9386153F7472D5A4E3218FC3353ECF45BE32905B7FDA3D7882C4FFE6CF966AA3' : true,
+ '93DCEAA3D67BD8992097C446EECE4A6A02DCF89EAB0008EFAE7D0C9BE26B7C00' : true,
+ '9446A5F64DFA26478AFBF6D0F3A0773ACDD46F1A4F7691A72BF24A58A411B340' : true,
+ '94CE12FB5F69E4273C8F813ED37ECB954AD667BC81C4E37DD27A40C291DDB12E' : true,
+ '951A1AEC1EFF82FA3366E4569838AC37BCE65385B88CF81B0D96B6A552258690' : true,
+ '956DE14452F6966BDC2C3CFE4874878D446083AE81BCD83C705B8E757FA0A390' : true,
+ '95A4DD514D4B5F9B29118B3CE20FD8D4996F40424D7D64BF678A252262608C70' : true,
+ '95A80082CCA2E52DFF16CA0E49B9FFE32F7ECB93770D20913605BBD47A2C65A6' : true,
+ '9658D54C28C27DD6E9B79098D7D86C1EA32215492E8AE9DB225E3410EEBC39CE' : true,
+ '9668363E5A4509F63E66C774CC7374E8D7654D0D63E833131665F65BB0116D90' : true,
+ '96B78900F165A1CA3843F3036950C7A5CB299CFA98F7A1BA6950AADB5DC1459A' : true,
+ '96ED7F4947B39E44EDCEEA05043F9B286C35BFA932C02D88A00B5338BE7829D5' : true,
+ '973CA0AA2F294AE5068B75F5562CDBD51AE5ABD2E25C8F20CE38572587589799' : true,
+ '976ECEBA965B747F498F8E4D26E3BABEFC48A6DD2645210168D7D82BB97C15C5' : true,
+ '977C77EDC0AE3D98F2FE87B8C309DACC9306DC575D2D8FC358973DC716EAD715' : true,
+ '9787C483E07B0D1A0251A93D9F86495C6E39D25375C395E9939145D6C1E818D6' : true,
+ '979F95AFF9D71DE4B8ECE178862627DE62E0E24E5ABDA2E8A20E5177E8F428D2' : true,
+ '983120089E357F1255EAA175207B7DB3462CC8481C2D4F8150B5C4FB93E274C7' : true,
+ '9874E435B3A12419DA88FE7AE98EEFA9DE47D098DC95AA6204B499202AB1A0CB' : true,
+ '995FB24A5192D81E32B762C20EA1298A1C67820CC360914FCCE1613A12CEF526' : true,
+ '99A4816C0BCDE615242EF4FCB3CD6E84EC60952E9F97E248424080DAD5D0629F' : true,
+ '99BD9F4C25AF74058C9E443467C9FBA76EB37661CBEF5A1E1244D8077200A250' : true,
+ '99DDDA7A8D6D222C3111DDF5E85A45261AE9A7CAE2972567996A7729D0FD6E68' : true,
+ '99E2609E0CDCFD36015CC659568D5C5B01CE4F7FA0C5671738D525FD8C518B44' : true,
+ '99E437DA5156E02DE52D0D95AFDE0FDBAF8F626F4D3BAD2FFFE7F4C75D76BD60' : true,
+ '9A01E5759613554A5FAEB7E8889F18EEE16568073CCEDEFA0485F01969535C43' : true,
+ '9A36248A6C3142FB6AE62E262E0F519CD609A0207BCB6891443BD5AA5C02AEDF' : true,
+ '9A9B087A4581C1FE71B3F4D7C041E93D4EC1093B01AF3ED96548AB93254EF65A' : true,
+ '9AC79E2916EDA1EB936B7FC6779F139ACC665C33F143340C5CE540B69F2E9F18' : true,
+ '9ADA51307C3FA225DB6F8E1FA3A218E477F775FA3D3DBE839232E3C385310902' : true,
+ '9AF3A66EB67ED022E3F99B1E810BA8C0A110F83F0BF250914AA5F1F0989B2196' : true,
+ '9B128E182D224AE31F63FA92892A8A322AE42BF2D4723D62F5A6744973C82F6C' : true,
+ '9B37ABC1012C67357E1B828C3F70EF7584EA128D20968DA23969B0BE939CB83B' : true,
+ '9B80DD5C98B0F0A7AE343DBB896DBCE45DA52EB4E31BE057287A2A738D9CE3D6' : true,
+ '9B8B430BCC7FFDD28FA85A1B18690D76DE8F18DE340656F63BD1472816A3C83E' : true,
+ '9B8E5BB6E9E655E4547D6782EE9018C8BE585F7BF89555A920C9157DCC15D0C1' : true,
+ '9BAE8B30BBFA182D0BC3DCE5BADF78381980EE69F15884A0B93F291EA09A7EB9' : true,
+ '9BEB9D4CF88A648ACC9CFFA48A687370D76E9F8188AB3BD638D9BFABD2D6AB24' : true,
+ '9C0F47FE70B9E636409CD37362B052B40B3CF765DFE80E71D999E7EB1AE1D4C2' : true,
+ '9C5435D416BDB4EAE642E2A66B8382BC848B362E3937069725DEFD9282772612' : true,
+ '9C7DCBE2DF8C0BC947A09C39B1B6CD2EE137D366554F8CB46AFD80C5FA9C3B81' : true,
+ '9CFB4802809B54253FD655390678454D0AFFE4E5B0239AF6E4D5CFD90FEF6931' : true,
+ '9D28BF964F6C820DD26D42FFC18689C1D2FD43F4C4DA9B35F11CEB8FA24F2073' : true,
+ '9D98952A99B9FF1B2B7A86D21F50E311B3147CD9475830A856A4C63798B05630' : true,
+ '9E418F784C18C79930946ED9BC408D8E2F694BE1E3DBAE4BB20917F8E1B277A7' : true,
+ '9E492AEE3B5838FF2E4BDA9FF98D73B48CA846FBD2AEEDA19FB885A489F58DF1' : true,
+ '9EBA1808D31F89FD26CA580E6FD37B15D0261A807154FBAF11A7DA4B0C9A5E06' : true,
+ '9FB66B76C9B0AB6ED5DA3188A3DC6FCBC369AB273DCA99468C1EE4604A1E9E99' : true,
+ 'A0212D4EE874832A0202ECD1349ED750083B1D238DB6E30120702BE1256F53D8' : true,
+ 'A03D7CE2FA040738CCFEF1F20872DDC1E321745B2C34095822A51B3BDC07D9F5' : true,
+ 'A03F32B0A7677B8D7102BCE24F121EE6CC503FF173C43CDD6B914BC69D954ACA' : true,
+ 'A06E313693C42005CB7B7AE33A96E3ABD66E05A57012B6294671FBBEF4A84AAC' : true,
+ 'A08110BB7D0D5F694D791F82071E44B4C968D4990C73A402B25E0E0ACA5EA6E7' : true,
+ 'A0B4E9AFEFA1B8966355614B201506B13CC213060D2661264491601F7FAD8269' : true,
+ 'A0B9ADCD27CD63E8842BAE80188453C09DEC27270C32748A4EC2508372AD36A5' : true,
+ 'A13EAF82F0814BE5FA12BFB4D2FFBB75FC6375DF19E16B8490D140CFEB54AEE3' : true,
+ 'A1504C131B0FE702B64AA259B901DA2D9B2AE9D85AADE02F1528C1147F98E535' : true,
+ 'A15455BAF823A9C2A7B971C6F11D799D4C6E5B59D274150AE67294035C94ADC0' : true,
+ 'A15BB49CD56693B9881AD43F6366FD2966AF816643BB107E8A249E07227F67EA' : true,
+ 'A16BC03AE3E35E7C39B45D339A22BEB39CEC134D6B9CCA289E873F91A384DCBF' : true,
+ 'A19514A23AD3729EF69553D8293E9693528EC67609464D4EA0A96CEF8E9C3E05' : true,
+ 'A219A198FA5CE79A2ADBC1EAB8BE34F086699B9A16F88DD2F823325F7481FA8D' : true,
+ 'A277B893194AE7687EBBCFA344178B3578AA6228D2B430BBE2FC8D5EAEE43135' : true,
+ 'A278FEDD023B6A1BE29917353E38320B8D8EBED9ADB0F88A8D00434D9B1A0851' : true,
+ 'A28337D306B9F107098D473AF3F34D8C14DCCBF62D725D5F8EEAE11BAAC558B0' : true,
+ 'A29725F7446E6A2AD03DF0B7D77B72F9CF0249733B42F48DA80AE41C6B206C49' : true,
+ 'A2C85895E192F69BFF3BD6CE420B8C84A6FC87B3A999F84701F0230887DD3344' : true,
+ 'A300C56C8CB909C4F6ABAD6A7FCACC5E621BE17D5209717912B3F3BF2F7D6CAF' : true,
+ 'A32A8197E25FF03AC02B1548EC597DC93B2F3376E971B143538542A6A2212AA1' : true,
+ 'A32C868E44827044CE85B05E7E694717A5D3A7F8B9D28C41B7770DCD84F81218' : true,
+ 'A334A1C1BCBBE82C131CA48858CC1D56495D2CE2B598E5C6E81672D7E9FF9FC7' : true,
+ 'A33C924A4181FC26CCE183DF2C30AD332CF6D6A94626E2B6455CEF77560438F4' : true,
+ 'A35426EFDAE7DC04D5F7926E254D5CEA23D4CAC5371D577ADA3A4AF828766F1F' : true,
+ 'A369DC916C6CA5851F181C38EAAFA733310F462384651762FDA4B2CFBFFF07D6' : true,
+ 'A37B9444FE3BB0FB2EC43F2677926EF458D0ED4F0688FEA6443A5F243F10C2AB' : true,
+ 'A41920689CEE150BF8CDA57D32B36D32985FE08AD4F0E52D150D1CE5C7096810' : true,
+ 'A42FFF1190531FF187F05767CF5029A8CD637C72A8AFD222118463200A27FB84' : true,
+ 'A432841B8E8CE4F3B7992A740AB014B3D78ACD930DA113753E8D2E2E34A5358C' : true,
+ 'A46D4265BD5168CB36068465327371B2B9E2ACFBA66E368A8B90CF77A251ED09' : true,
+ 'A61D1D1BF3A48836E418525F674E32CB457F4C74ECF525BC18A3035A26DB1CBE' : true,
+ 'A6436C7837EB4F0FD89A1F3ECE954BCDC0D76E3817AD0289B64A22B78B071D7E' : true,
+ 'A686BB3EA8129BEA261D5B99357BDD2BC22DE15F0140AFA2D7CA3ADBCB64DE14' : true,
+ 'A696B059AC99AA5CAF081FE9DE0F113EF0032A9F799A92663985EA5939B6F30B' : true,
+ 'A6B23EA2BFF90B8406D914D1D5B5B11D84F759C88B9AFAF64B77B2DCE08D28F4' : true,
+ 'A7636BE0A08F56D7F05A8D69AF0B7199FA7C05AAC123DCE71AB57C538A4D910A' : true,
+ 'A828D902865C9F63FCD670F5752ADB8F8D95C6DD434F33962466496EB8D6BB3C' : true,
+ 'A82D480B6360B97B8FA507BD461FA4E2D6B73BDF171723C707FDBFD7C9C2C144' : true,
+ 'A84DC1DB143EEE938A45743268683770BA0FB2EE69A4EB4B131841555CF1E124' : true,
+ 'A8FFD3DCAC35478A6187DB3E317D7A9BA8D9823BDDA70440B8FCD5D83F49B836' : true,
+ 'A90478E1DFC0653194083700E5101CB3B58FF56E9E68ECF36E1D970522A60681' : true,
+ 'A9869713F6E5332E3F4902E82E81EACF34994042C411A28C8AAC116131EE90E9' : true,
+ 'A9913780644EF0A55C80B8BBFFA76A7453DF7F9FC04E9BB09FB9434240D03961' : true,
+ 'A9C3D776062E86182D7BFAD9005B716E1189EBD051D477078341EBA83F602DC7' : true,
+ 'AA0F48D748A88A3DF4392B0AF891FB99981D3D66D213B261AF14863E44F66870' : true,
+ 'AA33D12B28CCA921C5DAB6E8055B0F162ED6B6B9F92D85F93749619165B1D3A2' : true,
+ 'AA4FC2B4CCD9E52767C35AA8321783EDF85CD1F2F631BE5606C9B35C88486D54' : true,
+ 'AA6A6EB3A263EC4DD20257BAD1C1A94F80FD17E51BB03DF1BF0332AF48FDA5EF' : true,
+ 'AA70F6E381B7B7BE508E8D5EB062186FB323FE00A75B264F43B771B731FE96AB' : true,
+ 'AAA0B610FC8267716C7703C164E8E8A47B0DB68F821405F83AFBF5F4D7BB5219' : true,
+ 'AB33CA8B659481B0120C5A227487E4F99D28106362B530D054FD812F7278CA51' : true,
+ 'AB3975DCF7B531638F8E8EE570E416890F6E1FA4DFB66CD2EA62E81F6CB19383' : true,
+ 'ABEAC0745A8B282D5BB1DB3044B94C07D11F414A514894CCE62C067DF99382A5' : true,
+ 'ABF22A6F97015839A27CBED234E40E5BC875A95E81F4485ABC66FF6D35E38E2C' : true,
+ 'AC1199A88C3BB6564557B6BA422B776E8032D9457EE1099D0BD3E53DC44F73F5' : true,
+ 'AC33C7B064D8FD9A0E5A00BC70581133E949AA0E61209B55010E310791339D4A' : true,
+ 'AC3DBED034C44698984D68EA44B0B3D74C0DE3B7615C3240A71C1709958DC3BF' : true,
+ 'AC72106DE06D4C1A17E641546E6DC5C53A1F48FCED34B9BD09368429F828CD70' : true,
+ 'ACD1D0DF8BE51A80520D345BB16B04745BCBB48B01D936B018FFDA71981F817C' : true,
+ 'AD0C2E82F0B607A9B4D0571DF0302FF442E2B99ECE91C18E22C416B46B67E4F7' : true,
+ 'AD56E6AD659C808689220F5959DECE86001E37EEB88F452E2111BBAD634B4AFC' : true,
+ 'AD5A935C6684CDB2459FA1D67250E8F9B6A6CB6455BC628750F9633FCF6EBF62' : true,
+ 'AE3359DA4CEE82D978C3C7B4954AD6E0A80E53D1CEDB3A6262996F9CA0B77D83' : true,
+ 'AE51B75FD36BE0B6CF478F2441E57E91C216179A93BC05E35983D5FCD582CA91' : true,
+ 'AE7D10798CDAEF50F7599FB03394DE7DED48C3054CE987479DB018E789E3718C' : true,
+ 'AEA0E3A8AC6F70B681BDEFB28D9F156116F80230149D8E5C9DE76E9062EC015B' : true,
+ 'AEDE30ABFD76FFEFF77B437F8862FF677913239CB0DE0360FF93EDA6B515F731' : true,
+ 'AF6F25BC29AA257FB80826165B3AA5BECB2CEF777817998D0619544F02FAF897' : true,
+ 'AFBAAD26120F25FACFB7E1ABAD16A58455814B1A46DA986FCD04330A88DC1502' : true,
+ 'AFDCE2C9BDE084811D64F5408E8AF94945CFB9F7FC69C9A27C8EE39102858DD3' : true,
+ 'AFE6418D301202651844A84CC8B19A56C479D627DE922366E532643D995470A9' : true,
+ 'B040095E5483E488179D07D81A9C14C6CE026480DBA570A6D16D75A7414D7499' : true,
+ 'B05633EABB92254800392A31FA1627F077F2C91B29D82CF1EB1D507EC7D44038' : true,
+ 'B0A3CC901A3D58371289521F9345843F7ADEA438660729BE9B7B520DDB0BB965' : true,
+ 'B145A895F26B09540185848A600F7F58C0B03740C17B61A1B43BDC652740B80B' : true,
+ 'B19BEC326EB5F611BA8CE10410932955840A0818BFD2C1C690BC1C06C63A686F' : true,
+ 'B1B58B7EEBC1947CB840FC4C2713D0DDB23DEBC75E58DB15610AB4EA9A1DE1C3' : true,
+ 'B1BEE5F876D9695E23EBE9D0BF32D0DB4D05096C004A073487C5B3FA26719FCB' : true,
+ 'B1D9B3EE2512A48A8E703E2D2263EEB4B0A3D24963F5165DB3719CD4750D2986' : true,
+ 'B1EA0EB5DC9C9766C903870A4E9DD90C92C8780189ACCADDD9012E1D9911591B' : true,
+ 'B2618AD6AE584F2CDCEC050ECB0FCE8E5BF0E9E978AFE692E4A1BCB8B7D03044' : true,
+ 'B278FB3D58DC99E1CA192EEC63A0F34F9EB8294A23EF98C73F7C5F52A5C86FE4' : true,
+ 'B295FDC9D7462488EBD4E5FA8E5B062FE5E2D0432C6A02B99F4CAD1F9BE6D0BB' : true,
+ 'B29A6DB4686379EB52C1D8F249A74FA55A1DD9F2162B0B3E0683912C1E942437' : true,
+ 'B2CB5A2A69339A575A4198D5B76822E6A0F90871A45C8348F2A060CEE67EC98D' : true,
+ 'B31C07387E56AA457F17CA3D3A4C485683253CF387E6DCE37469B6A8E51CBF29' : true,
+ 'B3251BB9A1B4F219400E69789FB08CA2BBA396C6D2FD3C4B69F4B7E1C0DDB615' : true,
+ 'B33419AF991DF06128CC6A1EF6CAD190F68C1903CFB16B5346D0653C9C5139CA' : true,
+ 'B3381C627EFBEF5DF3BCC9DB71A9B6E4C0A4F3114F7E7408A356FB33FBA5D20B' : true,
+ 'B36D72C8B1F436DA49520421FC0A2869A9952DA405DA5E29EC3A1919453DD6F5' : true,
+ 'B38307BF753F924511125E6FE9542C79A8541FCC780FF6905BA237A4C7FCBB13' : true,
+ 'B3B278DD571DDC491FD26D3B0942C78EC4A1AE3D9A5D07C1E317CE901E6B8979' : true,
+ 'B4130785116E5A84BF7B191696B213BA8877228388B18C2DA38DCB9EE14AC8CA' : true,
+ 'B458C6F566E833CA5856703868BF09531CCC61D32AAB1BE65808DEEEC56EEF25' : true,
+ 'B478303C0A26FF8A262C29BA3A9683FFC4CF075735E637F6A958640C5EC33669' : true,
+ 'B49A2871E348639F681896FB62D6535C945182A3524297258EE2E356D6D5B3A0' : true,
+ 'B4C49BF02ECA8D4E0648B386A408C377ED9A9E8E3DFEAC1D7904D3D14C5E2F76' : true,
+ 'B4C5319F6F6A80B60C2A5A715FB1444F974024960339D49E0301E7F5A530595B' : true,
+ 'B50AADEEA7AEA0CC344AFC4BDC81C75292E1F52374DC4E405CA9376CBA5594BF' : true,
+ 'B54B1776D34DF92E8E090FBF0C927D9852E6F18F98E6F306AE0369229A4AE2E6' : true,
+ 'B5A37CEF1BF2C02B97F06094BA1FC88C650D4F46C43091914D5BC9CC1836A0D1' : true,
+ 'B5E58034813A6D2A70A162E5C9469EA7D31FE15F7478564E5698A388F201A646' : true,
+ 'B5F50267B0042B154B8529FCD98F5E01C986F7D23628B49B63011A3C90398CEC' : true,
+ 'B613D69F10DE096E664C3B4AA083E0BC9F50A98D0F9B682C496FDABB2E4AC9D2' : true,
+ 'B663B6C8C60A5969BEE4F6844813AAB8945EE2CE2253CFBA67500B991CD8A07F' : true,
+ 'B6B0AB34677500F9A39F33BFB229A8B211E9A75506BC0D4E894DA99804B40603' : true,
+ 'B72804ECFF97803B8A40A2FEB3686B4CC1918E9605AA9EA4775441E762D73687' : true,
+ 'B75601AB7AE44FB2C77FF1E9C6FBC4B4D9ECB548009BF40C46CDDBBA8C0FE493' : true,
+ 'B7EC03174DAD602E897345B072749AA86CAF05151062989E183C3039DE25569D' : true,
+ 'B8845702F28C3AF9B35D8B5F1DFFFA014CE411CF592B18395F700CD8B937F3B9' : true,
+ 'B89D04CAFB7A2D049F425329570E4582ACDFC0B92F54A8709716A3001377887B' : true,
+ 'B902076C4F3E4FC9D45AE90E5AF637247D3A4566DBA2D6DAB15364828CF7BCD3' : true,
+ 'B93093DB93D5FE8D16B007F9E40D627BB7B78D617879EC6C4F8528F4B21BDD6F' : true,
+ 'B9891F4ABEA7FE5802FA2C07E596905422C39B16E36612B37FFABB81F49A0BCA' : true,
+ 'B9B8984BD73419077A912955DEF673CCB572907E2C494256D627DCCAF86226A0' : true,
+ 'B9EF83009F5C8B4C3A0C1B8EB263B4AADA87D4D2263887F8AFCA40FD4A7F78CE' : true,
+ 'B9F8D7E05743BCE5E58CA2A0CDE89E7E1A9397417F75813B492785D72D4F8510' : true,
+ 'BA43FBF51015CAA4D822D17A43F4DFB32561617B62E711D921112F12B76F9E43' : true,
+ 'BA5BE146EA09B76F106B28AC62830E5240D1B7DC43BAD171EECC9998B1718E28' : true,
+ 'BA8089CC9A0F25A27251DAD14E47714A331C35ACCE2EDFCC51CD73EFA83E2EB4' : true,
+ 'BAFBC5503CBB29FE4D094BB0B0D04B22852E9120DD54D34D9247A4E570FD458B' : true,
+ 'BB3C208314AFEC26DCB183A0E4DA2C1169F9CC435F1EDB38C349AD97B2C3F6B9' : true,
+ 'BB998A2EEB4ED3C4251EB69296AE91EAE7360B0CBAF690FD250C38A710ACB38A' : true,
+ 'BC0C5DBC1020476F067127D89E5C9A2AA88F141312919D7C0BF1B964D4820FF7' : true,
+ 'BC86367AF49A238438C89460780C94DE2C1E49021437B3DFC590A63F46332888' : true,
+ 'BC9B66EC1AF4106896624836D64B109922DA4163B83288E2131FD9A012CC95AC' : true,
+ 'BCCC1893C98C4BD177A414C7B3D5EBD74893F964FB9A62B96B48A84F1FE64B53' : true,
+ 'BCEAEC2D8B8C18B58BD320D77850EC38285F419ACA8A9E939DAE7DFDF26696D0' : true,
+ 'BD273332A459B8980589FD5B8D03967EA78809CFB4F77AF25F578EA77CE9C785' : true,
+ 'BD4309D792EBF40F5962B65405970EC2ACC7ED1109A1F5FEB486C84327FF6D46' : true,
+ 'BDB42DE005453117D2B60263504B9B58E9AB64B57A7385279CA0323D7246F02A' : true,
+ 'BE6E70EB169369668EF9523107E95867B1B9C0320C750180303720B35CF09798' : true,
+ 'BED1A9D1A4414F4D465F04F9D8C8EC331F89388E19419D0371D0D177FA60287C' : true,
+ 'BEEA29655F2F0DE938C7460012B5265BDF623C09F11529CDC33A4B6BEAF96616' : true,
+ 'BEEB38B82A906102D7CD92E5FD98661DAB5D3C9B7DCA9DE3533565EA9607C5EA' : true,
+ 'BF61A5AF1BAF57E17B092D5A833B4C9A392BDC7529676D4C7248816F00CDA5EB' : true,
+ 'BF7EAFFAA2647F47D816A83ADD1D7579F0CDDA690CBA00F75BC6ABD564987346' : true,
+ 'C0144D1B67F2AB403DD08B73E5F1772F050E9713D8F2FD98BE999FCEE51D2792' : true,
+ 'C03976BCBA4A9A4ADD099CE8F878A6DFF9B066179EC7DCF932EC4AA737FE415A' : true,
+ 'C0AB8B4E884A20E51AB9325567115F185D18654803E08E2C2C6A4632D7ACC2D0' : true,
+ 'C0CDB9DCBD1FC873712C871C230C327A9E53E6D78FBD0E5CE1ABED5DA0D1C7D2' : true,
+ 'C1726BABAC393C02850032B1C43B095C3805E1DEB1FBB2CD8C76E533AFA80484' : true,
+ 'C1EB50953EE0D16410A5DDFD97F5C05060B39F2902807F139EF6B015D0C66729' : true,
+ 'C2118D84846AAB7DE521B0379672EC639CFD745D82E3D504EF68CA723725C5F6' : true,
+ 'C2295D7C0FD4FC4DC7681FAF3CE851F6B416405554781C77FC8212DA169C258D' : true,
+ 'C2C9A263D5F88D7064870FD13AB8633A10CD97E8281F0ECC49C2C1C3F54327A6' : true,
+ 'C31135D0EE5E0B74D6A39E1FC67E9DB5CEAAE9F1D15338359CE02643C198634F' : true,
+ 'C33DB47CE54F64CE33394E20A96D122EFB6F8DAB2584CF26120D8A8C5C380245' : true,
+ 'C34069193CBFC866E03EB745416B50B25BBCAA00B5DE50D1D62D3365749CEDE4' : true,
+ 'C34CDEA10E72069587970C7033095864B6F069B6637C6263A1E7A7A5187923BB' : true,
+ 'C391E32BB11DD8F6F13BF71E0B9CE225364A50006E3F91147EDE39D2AA6E70E0' : true,
+ 'C3DCE474FB44F22E6497A1FCE2C45DEE167853134C6F1C21C13F1707B0BC7FBC' : true,
+ 'C4BDB4AF6E9CEE6017D3FB7ADD286E4B6348088E14D994CF698095DC86C939EB' : true,
+ 'C51ADC8D1B7014B4B9DB3EE230C67BF6F164956C390D41E5F8415977D9D9491E' : true,
+ 'C58563CE93B0DF900E0681376244F32977F577D130320226D3BD9CF82863402E' : true,
+ 'C58F0FF2DF810FAC8EA095F349A2E6D7E0D9C09D6FBE7D45895408530E1C75F4' : true,
+ 'C591A346116A065185360B973A875B0329B48D924E15BE8D4FC4C0B849182732' : true,
+ 'C689F3B9238DB156A7D563E76DF45FCA607B4B5F6CD62BDDC1AD1AC720E67952' : true,
+ 'C6B197D2663DD850504C900569A800D914A5C99FD7E0DC7C2424A063B6C42CE5' : true,
+ 'C6D78C940B53FE313A3DB674498E62C0B10E4C63B2D5E2A84D437BEE64A3F4F1' : true,
+ 'C6F63ACDAA452E008A1DCC711CAD36D00AFE55F958F2CC82A139BB53E27D11EB' : true,
+ 'C6F893D20A417841D7584A029E6E6A2A44B044D858ADFBAD4B11F35B7199309A' : true,
+ 'C700D31BDB3076006337BC249FF7CDFDFBB8A3677F206CB475E7807FE6FBE286' : true,
+ 'C71294A0124420512711C918C36F77192D2B45CDF8C99824B4BC862D0B31C3B0' : true,
+ 'C74B4D9C0A7CB22F6F7B60BD4CEF94A34820E3A0419CA5CCA3CF187612693FAD' : true,
+ 'C77AF2D81D578D009F9859CDEFD2E19A5B3DFA98FCE909C353E235D650DB514F' : true,
+ 'C82AE26EBA1954BC778047DF9684F330C424E9FF778033485305AE0C87E57D68' : true,
+ 'C84E5F64496198370D4E53DD6FD1828388E878759375F498A8670C035275D6C1' : true,
+ 'C936FEC68191D7AF75334834906C8CFB18F91FD53BDE7C2F0B2ACF8100ED3855' : true,
+ 'C9462B9099A574DBBB9E2BB9B87C4AEA825DA388EE8153AB74414555420AA6DC' : true,
+ 'C959CD326D9F3AA21FDEDD42A5AF0B7A2FAA5E9B92907654F29F1ACDC691DBE6' : true,
+ 'C9D7767021698AB5CFE3F43AB281F424E1515A52A0868C8752018CB292DE3190' : true,
+ 'CA157632863D3E7B499F141741724FA84DBA48AEB51B04A53A9D3DFEA7F70BF1' : true,
+ 'CA353A661EFF3C6EA9C66AA7585C19EDCD1C00085C06BB9B0DA2DA78C84D8CB2' : true,
+ 'CA400A13D999554CB3EE03F1F12F7E578ED5C52CBCAF9748124E3402052F921E' : true,
+ 'CA46DA728E76E97AD214DBB6AC9CB1EA2DC87202C88C35E87CE574FC1F2E0438' : true,
+ 'CA529AC5A7489D57CEC2D6BA5881213C5A163409BD6946558DACFE899A977009' : true,
+ 'CA846077B68DCA99AE30BAC33929143E856784B64E70098CBC7FF5BBD85C824B' : true,
+ 'CAAF21212D1AFB10BA4844150A49541967BC1C9879801E43064429A632DFD941' : true,
+ 'CAB896F9E8F1D4C0BBF05F4A48DEC534FB7A2E9E21D3C3B36F72D50131917243' : true,
+ 'CAF98B60B1CE36971AD2DA67A18E72E53345EFCA16382827BD1C2022D009E751' : true,
+ 'CB133229997821E418467CC3A72F77A7B9E31CC62B41032D6A82577B7AF1C6A2' : true,
+ 'CC2E477D4A2640BCF70F232C040954DFC4878E536A4B03E788173E673A2D31FD' : true,
+ 'CC8E9439ED527517579A913E8489CA704B4370AE09A823D36431063C53609C82' : true,
+ 'CC99A37B34F4914C3E3B8B8D6236CE0E8F92DC77CEBEB09D50C6004D51C8D4CC' : true,
+ 'CCE21382C4DDCED2E4101F6FC5A1B8B76166EC8ECE79DBAA58F3339508B48CBF' : true,
+ 'CD35C7ABA0839C0D865DEA4C1DB624F709E5EA041A68DB55842E2C189F38BAC1' : true,
+ 'CDB02DBACBAD381EB4F6854E84372DAD1FD76462ACBC26A9DC86164E81E75C85' : true,
+ 'CDEA4B65584E4EA2889F73E5907E95849BC6A2CA76B17EAD2B1FC7368193B550' : true,
+ 'CED6501D3B06CDB7033EE79351EC3080BBC2993D0991AB91325DFC0550689AA7' : true,
+ 'CEDFCE64CD03E3F512AC1CB6EE68C26F7C48C6753E8708E3A7D5AC867BA3ADC6' : true,
+ 'CF099A3A9DBE3D79F3E420A47A8447A50A2F87ACF2874CA86D49F271B82A68C5' : true,
+ 'CF19B1004488D5D9C882E2C4D0A47789618E0BCD6475F6D9C6B5591C2BF333C9' : true,
+ 'CF2A79710CABB0EB440EE621B37934C249C50612DB4FF926EDDE5B8A30686BED' : true,
+ 'CF44B5D052E8869D4632230291A81F3EBB7F681276D371161609BC23E40C8636' : true,
+ 'CFE1E4D56E0D95E238F3317CC981740011F0D3E4DE08ECD27313F83378F150BA' : true,
+ 'CFF31BD8AB9FBB4681C17AA4135E67D402345E32CA8DC9D566537CA530F27B7D' : true,
+ 'D03547E78303C9FBD70A38BEAFE87AA9F266A92275D818D1A8758DCB9D08DAE0' : true,
+ 'D07441504C544C3C3374E4314A2FB91266585AE94460B2FBE5CD4292556CA20D' : true,
+ 'D0DA9A42796D063B8246DC549D1CDD1D64B0AEF50E7094F0A29F243B51012DC7' : true,
+ 'D0F94901C782E50EA3A7B7300F6D9A113E45B5DA8944E956CE6629AF9C4C92B2' : true,
+ 'D103ECB2B7F74BEFD44109C1CA30EA92D9016C0F9347F1DF3E5467C3AC20221B' : true,
+ 'D10DFC97304D163140768E2D1698B1A0A3AF8331C4941F928622AB80091A3273' : true,
+ 'D1C4E4D1F014FB8F889F45AFA39485BE742F64268C662BB28494855E393ADE96' : true,
+ 'D207EED2218BA7CF564AD049677741A526B9ECB5BBB23CAF2B817A3B0085F004' : true,
+ 'D277E65331EFA2A6668143F8BC5334AF870208332990F977BD7F3588689F4686' : true,
+ 'D2785F7C48F180342D70978EEABFFC424D33A495A07D04F32C08B771BC4E43A4' : true,
+ 'D39BD0C1656F99A47DA9D2957E2D7A49FC9EDD92CC6BE729C29299ECECFC42E7' : true,
+ 'D3D5C3556B8724C6601E217415EA7E89740A9F1B2523D6421ED2BD2E3044145C' : true,
+ 'D44DF644880E56596405F1364D8C3E5301F05ACBF82FD66B671D895288C75360' : true,
+ 'D462D57028E10CB7A7C87ADA83EBD7FE9B4DA384D2971BD7A708816C4EA8711F' : true,
+ 'D46D29E4176A93E3DCD80BA5861A87E84FB7866B784488A977E7E4E4076DD2BD' : true,
+ 'D4CB5B06AF9ABEBF5639377BF36B289CA95A3205A84537D36B4506DF51430669' : true,
+ 'D52C9B39197E2769C185EC17A56A6E7890CDB1D0B18D15F65FA3B52E94DE94F7' : true,
+ 'D5846E29C203E6EAFF8D474085653A1F9E2E123C4E9E8C1172D1CB62474789E4' : true,
+ 'D5B0165C0F4C8F14A2E0C2310AE4A51B6EA08D2FD9790DFD49BCF3FD78AD5198' : true,
+ 'D5EDEAF240AD74C81017160821DE0FF6470839A2F8AB998D84E7392E90280D0D' : true,
+ 'D60AFE53C8CF92DC2D9E8DD1E4003246A16A692A1F619426CE43EEE621319BCE' : true,
+ 'D652650A3DE79A5C0DFEC1925007DA094925533D13F14094722A80F936FC9A8B' : true,
+ 'D666DA4D49E47B079AD7864678B4807D5CA035B3FDA103926CEFD053F50E5F2B' : true,
+ 'D7198C80471105D95103DB11B6BD2F6CDC8E7A7E67DB8329F1FA75C5F5D5E8CE' : true,
+ 'D7632272521683A38E88A18C2CC6AED79B2C5E854483BDB6EE83D82BF41B96CA' : true,
+ 'D780EB94814F0CE1AD1A2F8A1EFD6170C019F0B446E726C7C874C0730E59FF1C' : true,
+ 'D80A44887D03596492FC8CBFEA9878F46AFFEF1E077645169B129C419D3E8C6E' : true,
+ 'D83D1AED881CB22ED4E92AABA18DC390D6931CCF74591C64C236C662EFCDF557' : true,
+ 'D844DEE1597B654C0E645C787DB52F6EA5C855C6C35626BD7787E71E873CAF8F' : true,
+ 'D86562629BA86C435C0965C4AC302160729F27804FEBA36E211F96CDEFB5DF8E' : true,
+ 'D8B8F53177C1E04D93746C8460A7296707654094814772BFAD31F79C03802240' : true,
+ 'D904379306D37F489337D71508E1CA3FE9FDC8188286D24265D3437BC069EA15' : true,
+ 'D9E191EC52F4ECE1E0C43968EAD53E421ED62A7A7DBC0C39ECB2B8FF7962F01C' : true,
+ 'D9FDB29EF83808BC82A97839FB2F22C2D20DAB2E6B67BF5862C8922BB1FA9068' : true,
+ 'DA0D9391992825F7A10312F7E85568086F18DB901838A303E721E58239158EA0' : true,
+ 'DA29D8725034D89C221F415CC5282F82A6502E1EAF416DFA41507BC662C90258' : true,
+ 'DA5D20F1A6CF6CEC3AA7028A6E17D8F2E1A60069E497758B0CC938C08F4E76BC' : true,
+ 'DAA384D0D2A94A18A14E3DDF7A963E59BE41C06B978F3DC8862E1EE6C8E76DD0' : true,
+ 'DAA9CED5BA817CED9942DB9CFAD0210505937A9DB2214298E0BEB831BFC8A31B' : true,
+ 'DAFB1BB231A0D93B70726F2D3D8D8C8C54EFFCD901BB415C7A85AF02D09AA2A4' : true,
+ 'DB301590A7DE580916559C6DE948B95A3F7FC50A7AB8678BC365595A4DCE4E4B' : true,
+ 'DB7B1361B066EC2F777AE104F88A846DC163200AEB05B47D5BFEC91B6F13AC53' : true,
+ 'DB995D854C4EDEF4DB5CCF20B2B30719056F3EDAA0CCF4B9D9C5C898407C5C7A' : true,
+ 'DBB0C3CC436B5E592960BE7E8836AE58D8D632D435365ED2EA3CFAA86681E272' : true,
+ 'DBBF2D4498ED91C779C81FED5E96F9B5210CE86EA463712268BCAF098FE2E285' : true,
+ 'DBCB7851A6EC87DF3B603CDC26C5A9F958C8AE75485E1649A7CEF218B4E4D5BE' : true,
+ 'DC2FCD6AEAEE45D7E82C443FD3F76EDE1C88CE43E5FCEC3B4DEC9F12AF34BAA8' : true,
+ 'DC8D710118FF258F27ED436F585756252FDB30F42DBB58B23B8CD3B2140E13B8' : true,
+ 'DCA17501D12F98C84EE99DF4BC8EFC1FFFA9B65E2BC5A92B20C9296EC61C96CA' : true,
+ 'DCDE97B03688D8CB9F603AEF4D97110A38679F8EE01975E4B0B55855E4A8DD05' : true,
+ 'DCF33FB3953551E4B5F06060A7EC211432C30FEF86FA7B45EE76A8F9F3473C86' : true,
+ 'DD10B2E1AFF8298CC67F58955608C74ECE657F1DEEC77D6C465C1C7D2C8D26D9' : true,
+ 'DD55F1E1BEBA4CF9F582CBEEF4A35E1C1DE36750A3403489C1C98955FCE9950E' : true,
+ 'DD64C7D9E60AE6748B449ACE8CF9C21B5551BC6427EDDCE1D77B7C7720FD21E4' : true,
+ 'DE327172F9BCDA3DBD4E6EEFC759F3EE88FBC635BAD34D76E360541420CDC8BC' : true,
+ 'DE411E4537133A4D436E0D730AE192277792AA1D0584E60B1CECCDC736F53407' : true,
+ 'DEA472B5BED8DA9F6F5539F8DC66FB5340010F7316FB28055E14EA76E03BBE41' : true,
+ 'DEC7DC8AB8ED70C1D2FB2875F0F99FA99FB53E6BED70CD47B244ABA2104DA5AD' : true,
+ 'DEF20D4F0C0D98AE8C9786C364182CCD8990A834C96C1F0989AAE9ECAF33720F' : true,
+ 'DF0525A7807F3709BAD2DEC2ECC569A1D473F97F0C382C932DF726C79926DA0E' : true,
+ 'DF4482289B54CB444569A5436AEEBEBFB348D966D2FBC8C5115376F3E5496303' : true,
+ 'DF533C33DB800394971D608B89269426D3A2F58B76F190229C0573985E4F7CB8' : true,
+ 'DF7FBA4917800A850600F3E7BD4DD0A717F2649060B300F5AF3B1F490BD26536' : true,
+ 'DFE29EDC6A77622D4963EAF8CEEAD0ED5DE393DD069425FE30175AD008D609DE' : true,
+ 'E01A5251FAC16C537237EE4249874187E3BE3AF9B0F1D472E6C69E6C8B8832ED' : true,
+ 'E09CD94E0A501BB4D25D5BBB02CCAE95A24D0BAF8CABADEC9D55A74B7D2C5BD8' : true,
+ 'E0D7FA4702E25E7F51F94DD0D12C39A352DF48DE10A5249AE2687CBC15020CB3' : true,
+ 'E1117A0AB7E1A80334C1C56891A4306CB553C100424773BB0F10C7574CF44ED5' : true,
+ 'E113CDDD84A81BB13795798E245E5D1B3CA1650D6A59AC34777577AB764DFC69' : true,
+ 'E1176E46C4FA7841D94FC724013E3D192E7B414933F92CD50EA36C51617A2C60' : true,
+ 'E1595A9AA15B24610100AEB57ED619460CA1D976B769B856398EADA5A01F952B' : true,
+ 'E1A55E7ABA746B4A053359D13C91DCD7415F2CEECB7E87292DFD697213986946' : true,
+ 'E1A583C63BCEBAC1136939B65CBD0E6DBD7493EA45910275D56E0E2DE209D2BF' : true,
+ 'E1C97EFF3C246073604F341DBB3CEC9683EB6692463D85C1D23FA5269D9F3FFD' : true,
+ 'E26F4C34273553354334DC7A22DC56A781F2491181799287CC91F12871FEB50D' : true,
+ 'E276249DEAEA8F9B735592C3355A2E3822F67A5979A3CCA988F98EBEEB2A8309' : true,
+ 'E276DC254DCFC8C0F2752221EE5D59EC0C86E714522A6600DB67A05E22E01740' : true,
+ 'E27966B8B9C67C751F9AB8315D0BD1CEE334D96A8C5F60C764070EF8B8FCE61A' : true,
+ 'E297439120E6E2701069440EC321BA98A5CFF9EA3F407FF16185671E466B87F0' : true,
+ 'E2D55EAADCF87AD1BD50E53B7168CCC08561F0172004C1EC4DC13D8166D1A313' : true,
+ 'E30234ADF36D445F582C956B26E63BB76FF13FE90048CE1F37B40285BAE6529D' : true,
+ 'E32ECC9EEA662085C10C003A5C910D77A6DCC1E99BD187576EFDD1BFA84591C4' : true,
+ 'E37314E72C7304D32336940ABB576DBD7BE3190CD9A5E8F87413CEEB7579D502' : true,
+ 'E381DF6792973BFE322D23C6CF2A6C24A4ECFC77F43F03D2FC04EE39FAD7C683' : true,
+ 'E40B4275F6249EF4CDDE56EBB983AF4DE4C9A811B4095F8E9F700FA18C951759' : true,
+ 'E43EB6A898FEB796E084C684078E8683417373F468EB087D4130EC6BD7A8510A' : true,
+ 'E469E3D28BF6AB0280F989BA50C11FF4D9EE608BAD2282219A5C4E60C0AD348E' : true,
+ 'E4D680D0579075DCA20740BD4EF6AA4CEFD5542727071005774421A247941B8D' : true,
+ 'E4F069C24D7162E3C94AB295EA33C8926BDDF79934CA28D8982A35650EB60B05' : true,
+ 'E692108B3683F3C6362DF92476D62BAE60687035B70B9119F962190C9C215B04' : true,
+ 'E696A05D698717888181DFB7B903B380E42454076BA429EC8AB0FB58206AB166' : true,
+ 'E756F7776AE92525EABD29B4CE8963EDE748438DE24393263F2118D77CC77C74' : true,
+ 'E7EB8B4D5DE598BED2B9C817AB7D42F1EC99F16640B8C673AF2152D42F5344C4' : true,
+ 'E7F4465713E093B4F7D970C89ED3A5E745457B80A974523648F07C6AAFCDC86C' : true,
+ 'EA64F2625FAFE2EC122B493D4754C2B090153F167213AB6F07A87C1D993E5292' : true,
+ 'EA7AD4DE86B47BEC726BFE21172676F92E0C0BB86888417916CB3123086E84A1' : true,
+ 'EAA0454F2BBEED65A2FC7AAB8F308982387BDF33E6B56A1F3203F70F2981083A' : true,
+ 'EB11019A7642C75F4DDC1DC9CF3B469BFB4C44B71C615693C73175F16DCA036C' : true,
+ 'EB17EADBF0EA09B71BADD853CED1E5170C3A2D9FDE4F5C4A0EEC93E44C4B442C' : true,
+ 'EB59182D7ACE742ED7D7AEE751763EF9F09EDF68D1DDF765E80BE40A53AD0E10' : true,
+ 'EB6D34EFBF063DCACDFB823734B9788D9FB5E22A48372B7EA8AAFED8046652E1' : true,
+ 'EB98F744424597BB5AF5F209D20D161DB2682089271EC2662BE177D36A737FBA' : true,
+ 'EBABE928B643E1B9FD6F61D67ACC4BA6A9BFCC95927D31D265F701AC4613B9AE' : true,
+ 'EBD2581C1B0224FBDA489A642503CF3D3306751C336A66EB1816989900DA52BE' : true,
+ 'EC3A708B75908F8EA0660EF8A9C14B07DAB3AECB71E96E87EB06BB317790A118' : true,
+ 'EC521C3B04AF772AF812B63555A7C24BDA282C06EC619E1766CC346780EC6E04' : true,
+ 'EC869ABCCE3A1C036F1AFABE5ECD4FDA581D16C0E81E16A2734E6004A55896BC' : true,
+ 'ECA7333D185C924CBADF8CD96EEFA90F63B12225555B3C72631C841AA37BA917' : true,
+ 'ECB0646FEF13F818B1ACD2A8AFE448F3B39EC0EF6F623175931C48DC386EAF73' : true,
+ 'ED4D737C0BBE1DC2CD305D8A912D1C1D923C1C4325401D66349541F754233B53' : true,
+ 'ED918BDFDFCB9E4E679BC7C1938F9CE412AA85500BA3531FC550AD5213D5BDC7' : true,
+ 'EDD929C40001C1ACDABD51797B63D689A0B80434FA323B4F7AD213AB8A530B8C' : true,
+ 'EE5B8C42532363A48222B1493803B14EC2C98366CD0C5BA4126F468BA19C559D' : true,
+ 'EE5D710097EAD11639F98940D1F32793ECC114F0408856CCB6536F1EF2366704' : true,
+ 'EF0EE2FBF54D87B6AC02AEB88050155A27E1A60A5A8C4AC46FF24B529D912B04' : true,
+ 'F09ECA7EC8BF7B582C42AEB4A0733A0D40FDFD28CEA2C70DA1BBCF1FF85E29FF' : true,
+ 'F0BF33EE5C1D9A83A7BBDCDE95426DCD201D1C071CF1FB58CA4FE3776996A99F' : true,
+ 'F0EDB0C989C20672BAFC51FA2710F3841BA5793BE379FC212D7ACC3AD4743455' : true,
+ 'F1147FBF98A54E12693453EC571CE8B86C05D7FDF3995D775DFF135E10B9C520' : true,
+ 'F11BB294EAD89BC4AAB21DD82BA85FFA6573215720E347D687D6D5D89EE33EEF' : true,
+ 'F153813F6CD126543E985CEFA06C8B978FE5D4825C189F58944DC0DE17D5A0E9' : true,
+ 'F15E12419E936A907F201FD9D6D3DE2E01E5F8465AC4D8EDDCE1E58262183223' : true,
+ 'F1B73AEECC6698895051EE69179C3897A1DC398C2D72DDD720A29F9C9520457C' : true,
+ 'F205928C933AFF1F1A6411AB779CFAE3FAAF43754AB86735DB52F74DB1DA81D2' : true,
+ 'F20CBF1FC073F7E7DEBC38DFE2042E2CDC5D82898773D6283C680A3BC966BC02' : true,
+ 'F22F96FB88C9D96104167D95B3AD8B5888C92680B0AD13DC785FD5AD3E19EDB7' : true,
+ 'F234FBFD807A0302CBF855175C73ABF27C94915B95135E3146C0ED73662DE3F5' : true,
+ 'F28C56AA368BC4F8DA6B77CF3F8D2A7EF4994BBDE7DF85AA40FF740DC004750B' : true,
+ 'F2C91876EDB36EAD7E4821C2A6581144F1E5A67B2DEF4A5E4AFDF79F5E1CC4D7' : true,
+ 'F35B9D7C54418022E6FD4FDFE88C3261FD138329A11C013AD640145D40BE934A' : true,
+ 'F3926080B8F8289E7DCC479153999D4F459951765A0A22977F056D8249BF5FF5' : true,
+ 'F3CA880E8CF918E29D956A8306A2A0EB9CF76E82135F60A9885033E22B7874E8' : true,
+ 'F3D480D69675A57DC2061544BF7F52B631BB02716680C0E5605413C9B2A6183F' : true,
+ 'F402A9D58A73C40B396B5CE756EDFCA68257AC6D8DE80AA8217F16C97512C51B' : true,
+ 'F49BADFFBB2D2836A995A12E44ECF62E584F1B8D0740E0EDC7610C0C6765CDAA' : true,
+ 'F513DC8D7F8B425FCF55E74BDCF2675EF2ABF98523E5226CF8A2391B0A36A919' : true,
+ 'F55617B92584757BB516B19BFCBDA9B4A71237075487651831CD9C5F9C6F5F29' : true,
+ 'F5B19B2D5D880A4C1ADECA3D760FCB7E75FC2137B2EC99F3EEE034ADF788BADB' : true,
+ 'F5CACF11F3673BFE76BC638692B907E7E1407AD77F3C8943CF4F4BF22A2D5137' : true,
+ 'F5D715B6BE56D1A677ECBF7C26B4D79716F5EC2D2E2EC323ABDFE3442F40BD31' : true,
+ 'F5E43F516D61A0329F78A2560454B8346732A9420C172AC9983C0BEFFD8DEA0A' : true,
+ 'F5FAC17F4DDD973352CBCD311E21AE81EEFA06150CE85B8C32126D7F1661EDA0' : true,
+ 'F605AA2BD611765748A88F933BCBCEC70272F6C6A1A4AC614C2D02D17DAC6CEC' : true,
+ 'F6620F848AB3CFC1695D2AF5399FD8FDD8F2FEC43F73F2924DF78C1A26C22653' : true,
+ 'F6B9B7A36ADF7095D44420CCDCE4A739926841BC695ED40E78856D8F71D41257' : true,
+ 'F74D9E23F4CB53775CA60178347F2A029F77579000B21AA08EC62A1C2932348A' : true,
+ 'F754352E819D0C33E6CFC06EECBB4356DB5D8BD1FD2591C7C817CCE662BE2BC4' : true,
+ 'F7FC63254BF2472575C6D5DEC8DDF02B24B6F1BDCE03D807B159A69820262D4A' : true,
+ 'F805AE1FEDB2D94096F0D341B703ECD4975D773A179555DDC83D424F85578571' : true,
+ 'F94C306978496ED2183DC7591DA0240B513527293E5D522CF7089530E4C58D29' : true,
+ 'F961BA44302F5AF5DC4045A7E3989D4B77AD4BDD53DE92A45F39FE56947293BF' : true,
+ 'F9E220AC82D672997DC20E9EE89BF0713BC4153FB5F2EBC8D9AC9EE35A6E494D' : true,
+ 'FA0E3BFAEEA2FBC6A9E4A33EB6F289EF6C35228008ABAD3878AC4B2C8E87F957' : true,
+ 'FA1B8F32DE3B7F4ACA8FEF5414B5D985FE3705D0E3371D4FE4AF46698B68B01B' : true,
+ 'FA500D7B8D9BED2323488F83C9A6093C012143DEE3E453C1F75738625571E708' : true,
+ 'FA616BE68A75F14CA6331BD5BFDBE3840CE34CC3C3C98E3C8C3E10F027389F2F' : true,
+ 'FA75601E87823F0B02F8764B29377F4EBB02A179051297597E93FB4B1F5FCAD5' : true,
+ 'FAEDB6948B44BBBEB18CC3DE18788AD31CE938A2BA36BD84765BF47728C415E9' : true,
+ 'FB067C05D337FC01FC0721FA712A9E1A4FFDE059A35F3B494D36FFE241107465' : true,
+ 'FB1DF67EE132C7163167839175485C179E82024AD59EF806AF9D968A97F2ACA2' : true,
+ 'FB3A5B27D3488E28ABA3F303A726C2F0440133025981816FEDF798E45B9B1751' : true,
+ 'FB52A9B5EB7A494C06FB5CE4BB4505F32D6C666931AF2A018E6066244802A00D' : true,
+ 'FB7EF701469F77B6412100BB2D6399B1A574BB9610186FFFCC0119E14CB2021F' : true,
+ 'FB81BF294DB8EDE0C4DFFB7F5528EB3EB406FE435A6D62E6894482D8B42CCC48' : true,
+ 'FBCC79E05CC135E183F4963C2A206F9DFDBC2DD0D379A743D5FB301741796921' : true,
+ 'FBF769E6019DEA2724DB5768974B5D32E8A91F8045707B4F50552FE1D3BEAE4E' : true,
+ 'FC072A7AD4E6E41680493AF4BEB98215D4D2F7CE040C95004BB3A1621A9DD513' : true,
+ 'FCA9C3A036EA797D58CA26F793C98A9952E59D37C35E352B67A30D4F8F49FC7D' : true,
+ 'FCABE5BABEB2D2785BBA66B5D465FAF9F9A8E74E77AC1161273F49F4261F17B3' : true,
+ 'FCC12514DEB82E09AFF7A8B73DAC3CF80683D447101F048804D0B1100169D87E' : true,
+ 'FCF4BA663F0032118EADF9D327B65AB502C7A8B336462A397238884E9A28508E' : true,
+ 'FDB416F216D943190D8CADA2EB8F138F77A99CB1BC1334246697D37D8C04AB38' : true,
+ 'FE4A5357D197340536C61A1493D6EB64732D628B4435BCF43A1D52BCC5BF4CFD' : true,
+ 'FEE9BBCB25431C59C14C72C963CEDF437D795B6BEFE79EBF262B7054B0E583A1' : true,
+ 'FEFEF80071B0D8E2B57D6601BB353A435A425EAA701827370C3585CE09F2CE50' : true,
+ 'FF7B4EA9730875FF721ACEB86B327F7A6FB57A203B061CC3A4048E1D68F828B9' : true,
+ 'FF8C4E466EBCD5BD1A16F83E6096501479D74D077F84F2EDEA264781DFD82270' : true,
+ 'FFAE947BA6D3D7E8D31D04F02EEEE60601B0200ACDEBCB12AA5D617F650D5FD0' : true,
+ 'FFFB09720CCEF3A610BCB81EEF5FCD614C1602D4968A9DE8400C05256AEDC1ED' : true,
+} ;
diff --git a/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/commonOCSP.json b/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/commonOCSP.json
new file mode 100644
index 0000000..106916d
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/commonOCSP.json
@@ -0,0 +1,289 @@
+[
+"https://safebrowsing-cache.google.com/",
+"http://ocsp.pca.dfn.de/OCSP-Server/OCSP",
+"http://ocsp.digicert.com",
+"http://ocsp.verisign.com",
+"http://ocsp.comodoca.com",
+"http://clients1.google.com/ocsp",
+"http://ocsp.usertrust.com",
+"http://ocsp.disa.mil",
+"http://ocsp.quovadisglobal.com",
+"http://ocsp.nsn0.rcvs.nit.disa.mil",
+"http://ocsp.camerfirma.com",
+"http://ocsp.thawte.com",
+"http://ocsp.serverpass.telesec.de/ocspr",
+"http://ocsp.certum.pl",
+"http://ocsp.certisign.com.br",
+"http://ocsp.entrust.net",
+"http://telstra-ocsp.pki.telstra.com.au/ocsp",
+"http://ocsp.a-trust.at/ocsp",
+"http://ocsp.godaddy.com",
+"https://ocspaces.trustdst.com",
+"http://ocsp.identrust.com",
+"http://ocsp.pki.auth.gr",
+"http://ocsp2.globalsign.com/gsorganizationvalg2",
+"http://ocsp.starfieldtech.com",
+"http://ocsp.pki.bayern.de:8080",
+"http://ocsp.netsolssl.com",
+"http://ocsp.europki.org:8026",
+"http://ocsp.starfieldtech.com",
+"http://ocsp.treas.gov",
+"http://ocsp.trust-provider.com",
+"http://ocsp.rcsc.lt/ocspresponder.rcsc",
+"http://ocsp.globessl.com",
+"http://ocsp1.wosign.com/ca1",
+"http://gtssl-ocsp.geotrust.com",
+"http://ocsp.turktrust.com.tr",
+"http://ocsp.quovadisoffshore.com",
+"http://eva.orc.com",
+"http://ocsp.incosolutions.com/ocsp",
+"http://validator.wellsfargo.com",
+"http://jjedsocsp1.jnj.com",
+"http://ocsp.cybertrust.ne.jp/OcspServer",
+"http://ocsp.digsigtrust.com",
+"http://ocsp.trust.teliasonera.com",
+"http://ocsp.harica.gr",
+"http://ocsp.pki-services.siemens.com",
+"http://sd.symcd.com",
+"http://ocsp.catcert.cat",
+"http://ocsp.certificateservices.eads.com",
+"http://dc/ocsp",
+"http://ocsp.wosign.com/ca",
+"http://ocsp.swissdigicert.ch/rubin",
+"http://ocsp.unimelb.edu.au/ocsp",
+"http://ocsp.gandi.net",
+"http://ca.multistructure.co.id/ocsp",
+"http://ocsp.buypass.no/ocsp/BPOcsp",
+"http://rapidssl-ocsp.geotrust.com",
+"http://ocsp.tcclass3-II.trustcenter.de",
+"http://ocsp2.globalsign.com/gsalphasha2g2",
+"http://ldap.takata-petri.com:2560",
+"http://ocsp.dpwn.net",
+"http://ocsp.certyfikatyssl.pl",
+"https://ocsp.quovadisoffshore.com",
+"http://ocsp.swissdigicert.ch/smaragd",
+"http://sureseries-ocsp.cybertrust.ne.jp/OcspServer",
+"http://wongtaisin.ms.local/ocsp",
+"http://nsc.vrm.lt/OCSP/ocspresponder.nsc",
+"http://ocsp.webspace-forum.de",
+"http://ocsp.luxtrust.lu",
+"https://ca.e-szigno.hu/aocsp",
+"http://ocsp.trustsign.com.br",
+"http://ocspape.cert.fnmt.es/ocspape/OcspResponder",
+"http://telstra-ocsp.pki.telstra.com.au/ocsp",
+"http://ocsp.tcclass2.trustcenter.de",
+"http://ocsp.inmeta.net/ejbca/publicweb/status/ocsp",
+"http://igc.auf.org/ocsp",
+"http://ocsp.certification.tn",
+"http://ocsp.globaltrust.eu",
+"http://ocsp.e-tugra.com/status/ocsp",
+"http://ocsp.bezeq.com",
+"http://ocsp.nsn0.rcvs.gds.disa.mil",
+"http://certinfo-ocsp.ubs.com:53417",
+"http://ocsp.tbs-x509.com",
+"http://ocsp.ll.mit.edu",
+"http://pki.utg.ua/ocsp",
+"http://ocsp.accv.es",
+"http://crl.itsumo.pl/ocsphttp://corppki/ocsp",
+"http://tr-dc-r2.telering.biz/ocsp",
+"http://ocsp.eme.lv/responder.eme",
+"http://ocsp2.globalsign.com/gsalphag2",
+"http://ocsp.ssl.com",
+"http://ocsp.certificadodigital.com.br/serasa_cd2006",
+"http://la-email.corp.valueclick.com/ocsp",
+"http://ocsp.startssl.com/sub/class3/server/ca",
+"http://acbridge.ds.commun.test.fc2consortium.org:8080/ejbca/publicweb/status/ocsp",
+"http://remote.hirschmann.nl/ocsp",
+"http://ocsp1jca.defence.gov.sg",
+"http://ocsp02.telesec.de/ocspr",
+"http://certs.vonagenetworks.net/ocsp/vonsca",
+"http://ca-ocsp.disig.sk",
+"http://www.isscorp.com/PKI/ra/ocsp",
+"http://ocsp.digi-sign.com",
+"http://ocsp.certificadodigital.com.br/serasarfbv1",
+"http://certificates.medsigroup.ru/ocsp",
+"http://ocsp.bee.vimpelcom.ru/ocsp",
+"http://cert1.cert.internal.loc1.gathowin.net/ocsp",
+"http://ocsp-ext.pki.wellsfargo.com",
+"http://ocsp.innossl.com",
+"http://ocsp.pcf.pl/ocsp",
+"http://nts15.etoncollege.org.uk/ocsp",
+"http://ocsp.dreamhost.com",
+"http://ocspISAca.cert.fnmt.es/ocspISAca/OcspResponder",
+"http://bt1svl0a.bpa.bouyguestelecom.fr/ocsp",
+"http://ocsp.co.vectis.local/ocsp",
+"http://localhost:8080/ejbca/publicweb/status/ocsp",
+"http://ocsp.siteblindadocerts.com",
+"http://corpcert.app.corpintra.net/ocsp",
+"http://ocsp.nlss.com",
+"http://ocsp.bobo-rousselin.com",
+"http://cert.bioscomputers.com/ocsp",
+"http://ocsp.lienvietpostbank.com.vn/ocsp",
+"http://sslocsp.twca.com.tw",
+"http://ocsp.mdais.co.il",
+"http://pki.sana-bb.de/ocsp",
+"http://ocsp.wisekey.com",
+"https://ocsp.rcsc.lt/ocspresponder.rcsc",
+"http://ocsp.startssl.com/sub/class2/server/ca",
+"http://ocsp-cpki.telekom.de/ocsp",
+"http://ocsp2.ssc.lt:2560",
+"http://ocsp.it.point/RMGRCA/http://ocsp.extranet.royalmail.com/RMGRCA",
+"http://eca.ocspts.identrust.com",
+"http://ocsp.vkb-bank.com/ocsp",
+"http://pki.automobiletechnologies.com/ocsp",
+"http://ocsp.g4s.no/ocsp",
+"http://vpn.ozero.com/ocsp",
+"http://ocsp.village-roadshow.com/ocsp",
+"http://ocsp.groupensia.com/ocsp",
+"http://pki.rosautoprom.ru/ocsp",
+"http://ogbl-ocsp2.ogbl.lan/ocsp",
+"http://ocsp.southernco.com/ocsp",
+"http://ocsp.swiss.signdemo.com",
+"http://ocsp.itexcellence.rs/ocsp",
+"http://www.cepsa.com/pki/ocsp",
+"https://ocspaces.identrust.com",
+"http://ocsp.dtica.eu",
+"http://www.tys.org/aia",
+"http://ocsp2.globalsign.com/gsextendvalg2",
+"http://caors.wiltshire.ac.uk/ocsp",
+"http://ocsp1.ssp-strong-id.net/SSP-CA-A1",
+"http://cert.econgas.com/ocsp",
+"http://ocsp.wienerberger.net/ocsp",
+"http://ocsp.pki.wayport.net:2560",
+"http://pkib.mallesons.com/ocsp",
+"http://ocsp.ovh.com",
+"http://ocsp.certificadodigital.com.br/serasacdv1",
+"http://pkiva.indra.es",
+"http://itcert.stanford.edu/ocsp",
+"http://certenroll.bogdanov-associates.com/ocsp",
+"http://srv-pki/ocsp",
+"http://ocsp.godaddy.com",
+"http://ocsp.pki.slb.com/ocsp",
+"http://ocsp.swisssign.net",
+"http://cert.naftogaz.com/ocsp",
+"http://ocsp.uk.deloitte.com",
+"http://ocsp.comodoca3.com",
+"http://ocsp.exzumin.de/ocsp",
+"http://ocsp.msocsp.com",
+"http://cdp2.nis.rs/ocsp",
+"http://corptestcert.app.corpintra.net/ocsp",
+"http://ocsp.comodoca2.com",
+"http://ocsp.ersca.com",
+"http://ocsp.xth.cc",
+"http://ocsp1.ssp-strong-id.net/VA-SSP-CA-B2",
+"http://ocsp.vnpt-ca.vn/responder",
+"http://ocspts.identrust.com",
+"http://ocsp2.globalsign.com/gsdomainvalg2",
+"http://pkiva.bde.es",
+"http://certs.mapservices.fr/ocsp",
+"http://ino.inosoft.de/ocsp",
+"http://rootca.poclabs.net/ocsp",
+"http://pki.rtc-leasing.ru/ocsp",
+"http://ocsp.startssl.com/ca",
+"http://ocsp.ca.vodafone.com/ocsp",
+"http://ocsp.cs.auscert.org.au",
+"http://ocsp.tcclass2-II.trustcenter.de",
+"http://www.er76.ru/ocsp",
+"http://ocsp.walgreens.com/ocsp",
+"http://www.pki.nosc.us/ocsp",
+"http://test_pki1/ocsp",
+"http://ocsp.mytrc.net/ocsp",
+"http://certs.ankalagon.ru/ocsp",
+"http://www.ocsp.gpo.gov",
+"http://ocsp.bayanca.ir",
+"http://va.pfizer.com:1025",
+"http://certificates.dnv.com/ocsp",
+"http://ocsp.orapharma.com/ocsp",
+"http://ocsp.seattlecca.org/ocsp",
+"http://backbone.cnsd.interno.it/ocsp",
+"http://nyppki02/ocsp",
+"http://ocsp2.globalsign.com/gsorganizationvalsha2g2",
+"http://gtssl2-ocsp.geotrust.com",
+"http://ocsp.tcuniversal-I.trustcenter.de",
+"http://ocsp.register.com",
+"http://ocsp.ncdc.gov.sa",
+"http://pki.life.com.by/ocsp",
+"http://ocsp.sgssl.net",
+"http://pki.gmprint.local/ocsp",
+"http://pki.solitdev.com/ocsp",
+"http://ocsp.dics.ua/ocsp",
+"http://ocsp.pre.swissdigicert.ch/rubin",
+"http://ocsp.affirmtrust.com/commev",
+"http://aia.gdir.vt.ru/ocsp",
+"http://ocsp.averius.nl/ocsp",
+"http://ocsp.bechtel.com/ocsp",
+"http://ac.ds.commun.test.fc2consortium.org:8080/ejbca/publicweb/status/ocsp",
+"http://cert-services.e-control.at/OCSP?ca=EControl_IntermediateCA",
+"http://nfiocsp.managed.entrust.com",
+"http://cert.bernards.com/ocsp",
+"http://bhca2.baker-hostetler.com/ocsp",
+"http://pki.suva.ch/ocsp",
+"http://EVSecure-ocsp.verisign.com",
+"http://ocsp.go",
+"http://pki.wabag.com/ocsp",
+"http://ocsp.startssl.com/sub/class4/server/ca",
+"http://nfi2.eva.orc.com",
+"http://onsite-ocsp.verisign.com",
+"http://ocspsslv3.kamusm.gov.tr",
+"http://ocsp.pki.belgium.be",
+"https://www.isscorp.com/PKI/ra/ocsp",
+"http://ocsp.statoil.com:3502",
+"http://pki-ocsp.allscriptscloud.com/ocsp",
+"http://swoop-pki.swoopin.com/ocsp",
+"http://kzatpki0002.okioc.com/ocsp",
+"http://ocsp.policia.es",
+"http://ocsp.startssl.com/sub/class1/client/ca",
+"http://dc01/ocsp",
+"http://ocsp2.pki.wayfair.com/ocsp",
+"http://10.1.101.2/publicweb/status/ocsp",
+"http://ocsp.bt.com/ocsp",
+"http://ocsp.sanofi-aventis.com/ocsp",
+"http://dc-01.raise.group",
+"http://ocsp.spar-ics.eu/ocsp",
+"http://ocsp.vodokanal.spb.ru/ocsp",
+"http://socsp.turktrust.com.tr",
+"http://ocsp.thermocolor.com/ocsp",
+"http://ocsp.lisec-sw.com",
+"http://ocsp.csctrustedsecure.com",
+"http://houpki2.nov.com/ocsp",
+"http://ocsp.bwinservices.com/ocsp",
+"http://ocsp2.globalsign.com/gsextendvalsha2g2",
+"http://ocsp.tcclass3.trustcenter.de",
+"http://ocsp-b.pki.wayport.net:2560",
+"http://devdc01.dev.gatesfoundation.org/ocsp",
+"http://certsrv1.dc1.thomson-webcast.net/ocsp",
+"http://relay.systemshouse.ru/ocsp",
+"http://gold-root-g2.ocsp.swisssign.net",
+"http://pecs1.unisys.com/ocsp",
+"http://ocsp.europeanssl.eu",
+"http://gw.idsaas.de/ocsp",
+"http://ocsp.tcs.terena.org",
+"http://ocsp.trendmicro.com/tmca",
+"http://ocsp-ent.pki.wellsfargo.com",
+"http://www.meridian-capital.kz/ocsp",
+"http://ca.x-any.com/ocsp",
+"http://crl.inditex.com/ocsp",
+"http://ocsp.firmaprofesional.com",
+"http://ocsp2.globalsign.com/gsdomainvalsha2g2",
+"http://exchange.cdl.cz/ocsp",
+"http://pkicvs.cisco.com/pki/ocsp",
+"http://ocsp.affirmtrust.com/premev",
+"http://ocsp.icewarp.com",
+"http://ocsp.ferbritas.pt/ocsp",
+"http://cert.energokaskad.com/ocsp",
+"http://ocsp.utn.com.ua:2560",
+"http://ocsp.affirmtrust.com/ntwkev",
+"http://ocsp.omniroot.com/baltimoreroot",
+"http://ocsp.shamusclan.com",
+"http://ocsp.wurthnet.com/ocsp",
+"http://ocsp.pkic.es/ocsp",
+"http://ocsp.strixchomutov.cz",
+"http://sha2ocsp.dnsalias.com/responder",
+"http://ocsp-test.ncdc.gov.sa",
+"http://ocsp.sysadmins.lv",
+"http://cert.incoma.ru/ocsp",
+"http://ocsp.north-winds.org",
+"http://iis1.eeza.csic.es/ocsp",
+"http://pki.winextreme.org/ocsp",
+"http://ocsp.startssl.com/sub/class1/server/ca",
+"http://pki.eduuni.local/ocsp"]
diff --git a/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/sha256.js b/data/extensions/https-everywhere-eff@eff.org/chrome/content/code/sha256.js
new file mode 100644
index 0000000..7e15f1a
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@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@eff.org/chrome/content/fetch-source.js b/data/extensions/https-everywhere-eff@eff.org/chrome/content/fetch-source.js
new file mode 100644
index 0000000..80c32c4
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@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/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 + fs.DIRECTORY + filename + "?h=" + GITCommitID;
+ },
+
+ /**
+ * 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.addEventListener("resize", function() {
+ var textBox = document.getElementById("source-text");
+ // TODO: Move to constants
+ textBox.width = window.innerWidth - 100;
+ textBox.height = window.innerHeight - 150;
+}, false);
+
+// hook event for init
+window.addEventListener("load", httpsEverywhere.fetchSource.init, false);
diff --git a/data/extensions/https-everywhere-eff@eff.org/chrome/content/fetch-source.xul b/data/extensions/https-everywhere-eff@eff.org/chrome/content/fetch-source.xul
new file mode 100644
index 0000000..caa0048
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@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@eff.org/chrome/content/meta-preferences.xul b/data/extensions/https-everywhere-eff@eff.org/chrome/content/meta-preferences.xul
new file mode 100644
index 0000000..3e48010
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@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@eff.org/chrome/content/observatory-popup.xul b/data/extensions/https-everywhere-eff@eff.org/chrome/content/observatory-popup.xul
new file mode 100644
index 0000000..60da68f
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@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@eff.org/chrome/content/observatory-preferences.xul b/data/extensions/https-everywhere-eff@eff.org/chrome/content/observatory-preferences.xul
new file mode 100644
index 0000000..e686107
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@eff.org/chrome/content/observatory-preferences.xul
@@ -0,0 +1,114 @@
+<?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-show-cert-warning" oncommand="toggle_show_cert_warning()" />
+ <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"/>
+ <separator class="thin"/>
+ <tooltip id="cert-warning-tip" noautohide="true">
+ <label>&ssl-observatory.prefs.show_cert_warning_tooltip;</label>
+ </tooltip>
+ <checkbox label="&ssl-observatory.prefs.show_cert_warning;" id="show-cert-warning"
+ tooltip="cert-warning-tip" class="ssl-obs-conf"
+ command="toggle-show-cert-warning"/>
+ <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@eff.org/chrome/content/observatory-warning.xul b/data/extensions/https-everywhere-eff@eff.org/chrome/content/observatory-warning.xul
new file mode 100644
index 0000000..1f64e12
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@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@eff.org/chrome/content/observatory-xul.js b/data/extensions/https-everywhere-eff@eff.org/chrome/content/observatory-xul.js
new file mode 100644
index 0000000..1d9169e
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@eff.org/chrome/content/observatory-xul.js
@@ -0,0 +1,201 @@
+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");
+ document.getElementById("show-cert-warning").checked =
+ obsprefs.getBoolPref("extensions.https_everywhere._observatory.show_cert_warning");
+
+ // 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_show_cert_warning() {
+ var show_cert_warning = document.getElementById("show-cert-warning").checked;
+ obsprefs.setBoolPref("extensions.https_everywhere._observatory.show_cert_warning", show_cert_warning);
+}
+
+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@eff.org/chrome/content/preferences.css b/data/extensions/https-everywhere-eff@eff.org/chrome/content/preferences.css
new file mode 100644
index 0000000..6b35c00
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@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@eff.org/chrome/content/preferences.js b/data/extensions/https-everywhere-eff@eff.org/chrome/content/preferences.js
new file mode 100644
index 0000000..4a61f0a
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@eff.org/chrome/content/preferences.js
@@ -0,0 +1,278 @@
+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');
+ // Note: It takes several seconds to load all the rulesets, during which time
+ // Firefox is unresponsive. There are too many rulesets to reasonably browse
+ // in this view anyhow. Should start with an empty window and only show
+ // rulesets that match a search term the user types in.
+ https_everywhere.https_rules.loadAllRulesets();
+ rulesets = Array.slice(https_everywhere.https_rules.rulesets);
+ // Sort the rulesets by name to avoid revealing which subset of rulesets has
+ // been visited, per https://trac.torproject.org/projects/tor/ticket/11655.
+ rulesets.sort(function(a, b) {
+ return a.name < b.name ? -1 : 1;
+ });
+
+ // 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@eff.org/chrome/content/preferences.xul b/data/extensions/https-everywhere-eff@eff.org/chrome/content/preferences.xul
new file mode 100644
index 0000000..da722b3
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@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://www.eff.org/https-everywhere/rulesets')"/>.
+ </vbox>
+</dialog>
diff --git a/data/extensions/https-everywhere-eff@eff.org/chrome/content/ruleset-tests-status.css b/data/extensions/https-everywhere-eff@eff.org/chrome/content/ruleset-tests-status.css
new file mode 100644
index 0000000..30dad18
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@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@eff.org/chrome/content/ruleset-tests-status.js b/data/extensions/https-everywhere-eff@eff.org/chrome/content/ruleset-tests-status.js
new file mode 100644
index 0000000..0bee33e
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@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@eff.org/chrome/content/ruleset-tests-status.xul b/data/extensions/https-everywhere-eff@eff.org/chrome/content/ruleset-tests-status.xul
new file mode 100644
index 0000000..0efcd5d
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@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@eff.org/chrome/content/ruleset-tests.js b/data/extensions/https-everywhere-eff@eff.org/chrome/content/ruleset-tests.js
new file mode 100644
index 0000000..f4eda10
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@eff.org/chrome/content/ruleset-tests.js
@@ -0,0 +1,189 @@
+// 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;
+}
+
+// FIXME use a class rather than global state
+var left_star = new RegExp(/^\*\./); // *.example.com
+var accepted_test_targets = {}
+
+function addTestTarget(urls, target, ruleset_ids) {
+ // Add one target and associated metadata to the list of
+ // URLs to be tested, performing housekeeping along the way
+ var active_ids = [];
+ if (target in accepted_test_targets) return;
+
+ for (var n = 0; n < ruleset_ids.length; n++) {
+ var rs_id = ruleset_ids[n];
+ var rs = HTTPSEverywhere.https_rules.rulesetsByID[rs_id];
+ if (rs.active) { active_ids.push(rs_id) };
+ }
+ // Some rulesets that might rewrite this target, let's test them
+ if (active_ids.length > 0) {
+ urls.push({
+ url: 'http://'+target,
+ target: target,
+ ruleset_ids: active_ids
+ });
+ }
+}
+
+function testRunner() {
+ Components.utils.import("resource://gre/modules/PopupNotifications.jsm");
+
+ const numTabs = 6;
+ var finished = false;
+ var output = [];
+ var urls = [];
+ var num = 0;
+ var targets_to_ids = HTTPSEverywhere.https_rules.targets;
+ var ruleset_ids;
+ accepted_test_targets = {}; // reset each time
+
+ // we need every ruleset loaded from DB to check if it's active
+ HTTPSEverywhere.https_rules.loadAllRulesets();
+
+ for(var target in targets_to_ids) {
+ ruleset_ids = targets_to_ids[target];
+ if(target.indexOf("*") == -1) {
+ addTestTarget(urls, target, ruleset_ids);
+ } else {
+ // target is like *.example.wildcard.com, or www.example.*
+ // let's see what we can do...
+ var t = target.replace(left_star, "www.");
+ if (t.indexOf("*") == -1) {
+ addTestTarget(urls, t, ruleset_ids);
+ }
+ }
+ }
+
+ 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_ids.length; i++) {
+ ruleset_xmls += urls[number].ruleset_ids[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@eff.org/chrome/content/toolbar_button.js b/data/extensions/https-everywhere-eff@eff.org/chrome/content/toolbar_button.js
new file mode 100644
index 0000000..2d4b406
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@eff.org/chrome/content/toolbar_button.js
@@ -0,0 +1,433 @@
+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);
+ if (gBrowser) {
+ gBrowser.addEventListener("DOMContentLoaded",
+ migratePreferences.bind(null, gBrowser),
+ true);
+ }
+}, false);
+
+const CI = Components.interfaces;
+const CC = Components.classes;
+
+// LOG LEVELS ---
+let VERB=1;
+let DBUG=2;
+let INFO=3;
+let NOTE=4;
+let WARN=5;
+
+let 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",
+
+ /**
+ * Name of preference for whether HTTP Nowhere is on.
+ */
+ HTTP_NOWHERE_PREF: "extensions.https_everywhere.http_nowhere.enabled",
+
+ /**
+ * 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 the checkbox for showing counter is properly set
+ var showCounter = tb.shouldShowCounter();
+ var counterItem = document.getElementById('https-everywhere-counter-item');
+ if (counterItem) {
+ counterItem.setAttribute('checked', showCounter ? 'true' : 'false');
+ }
+
+ // make sure UI for HTTP Nowhere mode is properly set
+ var httpNowhereItem = document.getElementById('http-nowhere-item');
+ var showHttpNowhere = tb.shouldShowHttpNowhere();
+ var toolbarbutton = document.getElementById('https-everywhere-button');
+ if (httpNowhereItem) {
+ httpNowhereItem.setAttribute('checked', showHttpNowhere ? 'true' : 'false');
+ }
+ if (toolbarbutton) {
+ toolbarbutton.setAttribute('http_nowhere',
+ showHttpNowhere ? 'true' : 'false');
+ }
+
+ // make sure UI is set depending on whether HTTPS-E is enabled
+ toggleEnabledUI();
+
+ // show ruleset counter when a tab is changed
+ tb.updateRulesetsApplied();
+
+ // There is no gBrowser object on Android. Instead Android uses the
+ // window.BrowserApp object:
+ // https://developer.mozilla.org/en-US/Add-ons/Firefox_for_Android/API/BrowserApp
+ if (gBrowser) {
+ gBrowser.tabContainer.addEventListener(
+ 'TabSelect',
+ tb.updateRulesetsApplied,
+ false
+ );
+
+ // add listener for top-level location change across all tabs
+ let httpseProgressListener = {
+ onLocationChange: function(aBrowser, aWebProgress, aReq, aLoc) {
+ HTTPSEverywhere.log(DBUG, "Got on location change!");
+ HTTPSEverywhere.resetApplicableList(aBrowser);
+ },
+ onStateChange: function(aBrowser, aWebProgress, aReq, aFlags, aStatus) {
+ if ((gBrowser.selectedBrowser === aBrowser) &&
+ (aFlags & CI.nsIWebProgressListener.STATE_STOP) &&
+ aWebProgress.isTopLevel) {
+ HTTPSEverywhere.log(DBUG, "Got on state change");
+ tb.updateRulesetsApplied();
+ }
+ }
+ };
+ gBrowser.addTabsProgressListener(httpseProgressListener);
+ }
+
+ // 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 unavailable on Android, see above.
+ if (gBrowser) {
+ gBrowser.addEventListener("DOMContentLoaded",
+ tb.handleShowHint.bind(null, gBrowser),
+ true);
+ }
+ }
+ },
+
+ /**
+ * Shows toolbar hint if previously not shown.
+ */
+ handleShowHint: function(gBrowser) {
+ 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);
+ },
+
+ selectedBrowser: function() {
+ // gBrowser is unavailable on Android, see above.
+ if (window.gBrowser) {
+ return window.gBrowser.selectedBrowser;
+ } else if (window.BrowserApp) {
+ return window.BrowserApp.selectedBrowser;
+ }
+ },
+
+ /**
+ * Update the rulesets applied counter for the current tab.
+ */
+ updateRulesetsApplied: function() {
+ var toolbarbutton = document.getElementById('https-everywhere-button');
+ if (!toolbarbutton) {
+ return;
+ }
+
+ var enabled = HTTPSEverywhere.prefs.getBoolPref("globalEnabled");
+ var showCounter = httpsEverywhere.toolbarButton.shouldShowCounter();
+ if (!enabled || !showCounter) {
+ toolbarbutton.setAttribute('rulesetsApplied', 0);
+ return;
+ }
+
+ var browser = httpsEverywhere.toolbarButton.selectedBrowser();
+ if (!browser) {
+ return;
+ }
+
+ var alist = HTTPSEverywhere.getExpando(browser,"applicable_rules");
+ 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);
+ },
+
+ /**
+ * Gets whether to show HTTP Nowhere UI.
+ *
+ * @return {boolean}
+ */
+ shouldShowHttpNowhere: function() {
+ var tb = httpsEverywhere.toolbarButton;
+ var sp = Services.prefs;
+ return sp.getBoolPref(tb.HTTP_NOWHERE_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();
+ },
+
+ /**
+ * Toggles whether HTTP Nowhere mode is active, updates the toolbar icon.
+ */
+ toggleHttpNowhere: function() {
+ HTTPSEverywhere.toggleHttpNowhere();
+ var tb = httpsEverywhere.toolbarButton;
+ var showHttpNowhere = tb.shouldShowHttpNowhere();
+
+ // Change icon color to red if HTTP nowhere is enabled
+ var toolbarbutton = document.getElementById('https-everywhere-button');
+ toolbarbutton.setAttribute('http_nowhere',
+ showHttpNowhere ? 'true' : 'false');
+ reload_window();
+ },
+
+ /**
+ * Resets all rules to their default state.
+ */
+ resetToDefaults: function() {
+ HTTPSEverywhere.https_rules.resetRulesetsToDefaults()
+ }
+};
+
+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 browser = httpsEverywhere.toolbarButton.selectedBrowser();
+ if (!browser) {
+ HTTPSEverywhere.log(WARN, "No browser for applicable list");
+ return;
+ }
+
+ var alist = HTTPSEverywhere.getExpando(browser,"applicable_rules");
+ 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, browser.currentURI);
+ 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();
+ reload_window();
+}
+
+function reload_window() {
+ var browser = httpsEverywhere.toolbarButton.selectedBrowser();
+ if (browser) {
+ browser.reload();
+ }
+}
+
+function toggleEnabledState(){
+ HTTPSEverywhere.toggleEnabledState();
+ reload_window();
+ toggleEnabledUI();
+}
+
+function toggleEnabledUI() {
+ // Add/remove menu items depending on whether HTTPS-E is enabled
+ var items = document.querySelectorAll(".hide-on-disable");
+ var enabled = HTTPSEverywhere.prefs.getBoolPref("globalEnabled");
+ for (let i = 0; i < items.length; i++) {
+ items[i].hidden = !enabled;
+ }
+
+ // Change icon depending on enabled state
+ var toolbarbutton = document.getElementById('https-everywhere-button');
+ if (toolbarbutton) {
+ toolbarbutton.setAttribute('status', enabled ? 'enabled' : 'disabled');
+ }
+}
+
+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) {
+ 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@eff.org/chrome/content/toolbar_button.xul b/data/extensions/https-everywhere-eff@eff.org/chrome/content/toolbar_button.xul
new file mode 100644
index 0000000..6ba0810
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@eff.org/chrome/content/toolbar_button.xul
@@ -0,0 +1,82 @@
+<?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-everywhere.about.ext_name;"
+ 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 class="hide-on-disable"/>
+ <menuitem label="&https-everywhere.prefs.reset_defaults;"
+ command="https-everywhere-menuitem-resetToDefaults" class="hide-on-disable"/>
+ <menuitem label="&https-everywhere.menu.viewAllRules;"
+ command="https-everywhere-menuitem-viewAllRules" class="hide-on-disable" />
+ <menuitem type="checkbox" id="http-nowhere-item" label="&https-everywhere.menu.blockHttpRequests;"
+ oncommand="httpsEverywhere.toolbarButton.toggleHttpNowhere()" class="hide-on-disable"/>
+ <menuseparator class="hide-on-disable"/>
+ <menuitem type="checkbox" id="https-everywhere-counter-item" label="&https-everywhere.menu.showCounter;"
+ oncommand="httpsEverywhere.toolbarButton.toggleShowCounter()" class="hide-on-disable"/>
+ <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-rule-toggle-template"
+ oncommand="toggle_rule(event.target.attributes['data-id'].value)" />
+ <command id="https-everywhere-menuitem-resetToDefaults"
+ oncommand="httpsEverywhere.toolbarButton.resetToDefaults()" />
+ <command id="https-everywhere-menuitem-globalEnableToggle"
+ oncommand="toggleEnabledState();" />
+ <command id="https-everywhere-menuitem-viewAllRules"
+ oncommand="open_in_tab('https://www.eff.org/https-everywhere/atlas/');" />
+ <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@eff.org/chrome/content/toolbar_button_binding.xml b/data/extensions/https-everywhere-eff@eff.org/chrome/content/toolbar_button_binding.xml
new file mode 100644
index 0000000..1981b3a
--- /dev/null
+++ b/data/extensions/https-everywhere-eff@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>