Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: lib/adblockplus.js

Issue 8483154: Adding ABP core modules to ABP/Opera (Closed)
Patch Set: Created Oct. 11, 2012, 9:35 a.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: lib/adblockplus.js
===================================================================
new file mode 100644
--- /dev/null
+++ b/lib/adblockplus.js
@@ -0,0 +1,3047 @@
+/*
+ * This Source Code is subject to the terms of the Mozilla Public License
+ * version 2.0 (the "License"). You can obtain a copy of the License at
+ * http://mozilla.org/MPL/2.0/.
+ */
+
+//
+// This file has been generated automatically from Adblock Plus for Firefox
+// source code. DO NOT MODIFY, change the original source code instead.
+//
+// Relevant repositories:
+// * https://hg.adblockplus.org/adblockplus/
+// * https://hg.adblockplus.org/jshydra/
+//
+
+require.scopes["filterNotifier"] = (function()
+{
+ var exports = {};
+ var listeners = [];
+ var FilterNotifier = exports.FilterNotifier =
+ {
+ addListener: function(listener)
+ {
+ if (listeners.indexOf(listener) >= 0)
+ {
+ return;
+ }
+ listeners.push(listener);
+ },
+ removeListener: function(listener)
+ {
+ var index = listeners.indexOf(listener);
+ if (index >= 0)
+ {
+ listeners.splice(index, 1);
+ }
+ },
+ triggerListeners: function(action, item, param1, param2, param3)
+ {
+ for (var _loopIndex0 = 0; _loopIndex0 < listeners.length; ++_loopIndex0)
+ {
+ var listener = listeners[_loopIndex0];
+ listener(action, item, param1, param2, param3);
+ }
+ }
+ };
+ return exports;
+})();
+require.scopes["filterClasses"] = (function()
+{
+ var exports = {};
+ var FilterNotifier = require("filterNotifier").FilterNotifier;
+
+ function Filter(text)
+ {
+ this.text = text;
+ this.subscriptions = [];
+ }
+ exports.Filter = Filter;
+ Filter.prototype =
+ {
+ text: null,
+ subscriptions: null,
+ serialize: function(buffer)
+ {
+ buffer.push("[Filter]");
+ buffer.push("text=" + this.text);
+ },
+ toString: function()
+ {
+ return this.text;
+ }
+ };
+ Filter.knownFilters =
+ {
+ __proto__: null
+ };
+ Filter.elemhideRegExp = /^([^\/\*\|\@"!]*?)#(\@)?(?:([\w\-]+|\*)((?:\([\w\-]+(?:[$^*]?=[^\(\)"]*)?\))*)|#([^{}]+))$/;
+ Filter.regexpRegExp = /^(@@)?\/.*\/(?:\$~?[\w\-]+(?:=[^,\s]+)?(?:,~?[\w\-]+(?:=[^,\s]+)?)*)?$/;
+ Filter.optionsRegExp = /\$(~?[\w\-]+(?:=[^,\s]+)?(?:,~?[\w\-]+(?:=[^,\s]+)?)*)$/;
+ Filter.fromText = function(text)
+ {
+ if (text in Filter.knownFilters)
+ {
+ return Filter.knownFilters[text];
+ }
+ var ret;
+ var match = text.indexOf("#") >= 0 ? Filter.elemhideRegExp.exec(text) : null;
+ if (match)
+ {
+ ret = ElemHideBase.fromText(text, match[1], match[2], match[3], match[4], match[5]);
+ }
+ else if (text[0] == "!")
+ {
+ ret = new CommentFilter(text);
+ }
+ else
+ {
+ ret = RegExpFilter.fromText(text);
+ }
+ Filter.knownFilters[ret.text] = ret;
+ return ret;
+ };
+ Filter.fromObject = function(obj)
+ {
+ var ret = Filter.fromText(obj.text);
+ if (ret instanceof ActiveFilter)
+ {
+ if ("disabled" in obj)
+ {
+ ret._disabled = obj.disabled == "true";
+ }
+ if ("hitCount" in obj)
+ {
+ ret._hitCount = parseInt(obj.hitCount) || 0;
+ }
+ if ("lastHit" in obj)
+ {
+ ret._lastHit = parseInt(obj.lastHit) || 0;
+ }
+ }
+ return ret;
+ };
+ Filter.normalize = function(text)
+ {
+ if (!text)
+ {
+ return text;
+ }
+ text = text.replace(/[^\S ]/g, "");
+ if (/^\s*!/.test(text))
+ {
+ return text.replace(/^\s+/, "").replace(/\s+$/, "");
+ }
+ else if (Filter.elemhideRegExp.test(text))
+ {
+ var _tempVar1 = /^(.*?)(#\@?#?)(.*)$/.exec(text);
+ var domain = _tempVar1[1];
+ var separator = _tempVar1[2];
+ var selector = _tempVar1[3];
+ return domain.replace(/\s/g, "") + separator + selector.replace(/^\s+/, "").replace(/\s+$/, "");
+ }
+ else
+ {
+ return text.replace(/\s/g, "");
+ }
+ };
+
+ function InvalidFilter(text, reason)
+ {
+ Filter.call(this, text);
+ this.reason = reason;
+ }
+ exports.InvalidFilter = InvalidFilter;
+ InvalidFilter.prototype =
+ {
+ __proto__: Filter.prototype,
+ reason: null,
+ serialize: function(buffer){}
+ };
+
+ function CommentFilter(text)
+ {
+ Filter.call(this, text);
+ }
+ exports.CommentFilter = CommentFilter;
+ CommentFilter.prototype =
+ {
+ __proto__: Filter.prototype,
+ serialize: function(buffer){}
+ };
+
+ function ActiveFilter(text, domains)
+ {
+ Filter.call(this, text);
+ this.domainSource = domains;
+ }
+ exports.ActiveFilter = ActiveFilter;
+ ActiveFilter.prototype =
+ {
+ __proto__: Filter.prototype,
+ _disabled: false,
+ _hitCount: 0,
+ _lastHit: 0,
+ get disabled()
+ {
+ return this._disabled;
+ },
+ set disabled(value)
+ {
+ if (value != this._disabled)
+ {
+ var oldValue = this._disabled;
+ this._disabled = value;
+ FilterNotifier.triggerListeners("filter.disabled", this, value, oldValue);
+ }
+ return this._disabled;
+ },
+ get hitCount()
+ {
+ return this._hitCount;
+ },
+ set hitCount(value)
+ {
+ if (value != this._hitCount)
+ {
+ var oldValue = this._hitCount;
+ this._hitCount = value;
+ FilterNotifier.triggerListeners("filter.hitCount", this, value, oldValue);
+ }
+ return this._hitCount;
+ },
+ get lastHit()
+ {
+ return this._lastHit;
+ },
+ set lastHit(value)
+ {
+ if (value != this._lastHit)
+ {
+ var oldValue = this._lastHit;
+ this._lastHit = value;
+ FilterNotifier.triggerListeners("filter.lastHit", this, value, oldValue);
+ }
+ return this._lastHit;
+ },
+ domainSource: null,
+ domainSeparator: null,
+ ignoreTrailingDot: true,
+ get domains()
+ {
+ var domains = null;
+ if (this.domainSource)
+ {
+ var list = this.domainSource.split(this.domainSeparator);
+ if (list.length == 1 && list[0][0] != "~")
+ {
+ domains =
+ {
+ __proto__: null,
+ "": false
+ };
+ if (this.ignoreTrailingDot)
+ {
+ list[0] = list[0].replace(/\.+$/, "");
+ }
+ domains[list[0]] = true;
+ }
+ else
+ {
+ var hasIncludes = false;
+ for (var i = 0; i < list.length; i++)
+ {
+ var domain = list[i];
+ if (this.ignoreTrailingDot)
+ {
+ domain = domain.replace(/\.+$/, "");
+ }
+ if (domain == "")
+ {
+ continue;
+ }
+ var include;
+ if (domain[0] == "~")
+ {
+ include = false;
+ domain = domain.substr(1);
+ }
+ else
+ {
+ include = true;
+ hasIncludes = true;
+ }
+ if (!domains)
+ {
+ domains =
+ {
+ __proto__: null
+ };
+ }
+ domains[domain] = include;
+ }
+ domains[""] = !hasIncludes;
+ }
+ delete this.domainSource;
+ }
+ this.__defineGetter__("domains", function()
+ {
+ return domains;
+ });
+ return this.domains;
+ },
+ isActiveOnDomain: function(docDomain)
+ {
+ if (!this.domains)
+ {
+ return true;
+ }
+ if (!docDomain)
+ {
+ return this.domains[""];
+ }
+ if (this.ignoreTrailingDot)
+ {
+ docDomain = docDomain.replace(/\.+$/, "");
+ }
+ docDomain = docDomain.toUpperCase();
+ while (true)
+ {
+ if (docDomain in this.domains)
+ {
+ return this.domains[docDomain];
+ }
+ var nextDot = docDomain.indexOf(".");
+ if (nextDot < 0)
+ {
+ break;
+ }
+ docDomain = docDomain.substr(nextDot + 1);
+ }
+ return this.domains[""];
+ },
+ isActiveOnlyOnDomain: function(docDomain)
+ {
+ if (!docDomain || !this.domains || this.domains[""])
+ {
+ return false;
+ }
+ if (this.ignoreTrailingDot)
+ {
+ docDomain = docDomain.replace(/\.+$/, "");
+ }
+ docDomain = docDomain.toUpperCase();
+ for (var domain in this.domains)
+ {
+ if (this.domains[domain] && domain != docDomain && (domain.length <= docDomain.length || domain.indexOf("." + docDomain) != domain.length - docDomain.length - 1))
+ {
+ return false;
+ }
+ }
+ return true;
+ },
+ serialize: function(buffer)
+ {
+ if (this._disabled || this._hitCount || this._lastHit)
+ {
+ Filter.prototype.serialize.call(this, buffer);
+ if (this._disabled)
+ {
+ buffer.push("disabled=true");
+ }
+ if (this._hitCount)
+ {
+ buffer.push("hitCount=" + this._hitCount);
+ }
+ if (this._lastHit)
+ {
+ buffer.push("lastHit=" + this._lastHit);
+ }
+ }
+ }
+ };
+
+ function RegExpFilter(text, regexpSource, contentType, matchCase, domains, thirdParty)
+ {
+ ActiveFilter.call(this, text, domains);
+ if (contentType != null)
+ {
+ this.contentType = contentType;
+ }
+ if (matchCase)
+ {
+ this.matchCase = matchCase;
+ }
+ if (thirdParty != null)
+ {
+ this.thirdParty = thirdParty;
+ }
+ if (regexpSource.length >= 2 && regexpSource[0] == "/" && regexpSource[regexpSource.length - 1] == "/")
+ {
+ var regexp = new RegExp(regexpSource.substr(1, regexpSource.length - 2), this.matchCase ? "" : "i");
+ this.__defineGetter__("regexp", function()
+ {
+ return regexp;
+ });
+ }
+ else
+ {
+ this.regexpSource = regexpSource;
+ }
+ }
+ exports.RegExpFilter = RegExpFilter;
+ RegExpFilter.prototype =
+ {
+ __proto__: ActiveFilter.prototype,
+ length: 1,
+ domainSeparator: "|",
+ regexpSource: null,
+ get regexp()
+ {
+ var source = this.regexpSource.replace(/\*+/g, "*");
+ if (source[0] == "*")
+ {
+ source = source.substr(1);
+ }
+ var pos = source.length - 1;
+ if (pos >= 0 && source[pos] == "*")
+ {
+ source = source.substr(0, pos);
+ }
+ source = source.replace(/\^\|$/, "^").replace(/\W/g, "\\$&").replace(/\\\*/g, ".*").replace(/\\\^/g, "(?:[\\x00-\\x24\\x26-\\x2C\\x2F\\x3A-\\x40\\x5B-\\x5E\\x60\\x7B-\\x80]|$)").replace(/^\\\|\\\|/, "^[\\w\\-]+:\\/+(?!\\/)(?:[^.\\/]+\\.)*?").replace(/^\\\|/, "^").replace(/\\\|$/, "$");
+ var regexp = new RegExp(source, this.matchCase ? "" : "i");
+ delete this.regexpSource;
+ this.__defineGetter__("regexp", function()
+ {
+ return regexp;
+ });
+ return this.regexp;
+ },
+ contentType: 2147483647,
+ matchCase: false,
+ thirdParty: null,
+ matches: function(location, contentType, docDomain, thirdParty)
+ {
+ if (this.regexp.test(location) && (RegExpFilter.typeMap[contentType] & this.contentType) != 0 && (this.thirdParty == null || this.thirdParty == thirdParty) && this.isActiveOnDomain(docDomain))
+ {
+ return true;
+ }
+ return false;
+ }
+ };
+ RegExpFilter.prototype.__defineGetter__("0", function()
+ {
+ return this;
+ });
+ RegExpFilter.fromText = function(text)
+ {
+ var blocking = true;
+ var origText = text;
+ if (text.indexOf("@@") == 0)
+ {
+ blocking = false;
+ text = text.substr(2);
+ }
+ var contentType = null;
+ var matchCase = null;
+ var domains = null;
+ var siteKeys = null;
+ var thirdParty = null;
+ var collapse = null;
+ var options;
+ var match = text.indexOf("$") >= 0 ? Filter.optionsRegExp.exec(text) : null;
+ if (match)
+ {
+ options = match[1].toUpperCase().split(",");
+ text = match.input.substr(0, match.index);
+ for (var _loopIndex2 = 0; _loopIndex2 < options.length; ++_loopIndex2)
+ {
+ var option = options[_loopIndex2];
+ var value = null;
+ var separatorIndex = option.indexOf("=");
+ if (separatorIndex >= 0)
+ {
+ value = option.substr(separatorIndex + 1);
+ option = option.substr(0, separatorIndex);
+ }
+ option = option.replace(/-/, "_");
+ if (option in RegExpFilter.typeMap)
+ {
+ if (contentType == null)
+ {
+ contentType = 0;
+ }
+ contentType |= RegExpFilter.typeMap[option];
+ }
+ else if (option[0] == "~" && option.substr(1) in RegExpFilter.typeMap)
+ {
+ if (contentType == null)
+ {
+ contentType = RegExpFilter.prototype.contentType;
+ }
+ contentType &= ~RegExpFilter.typeMap[option.substr(1)];
+ }
+ else if (option == "MATCH_CASE")
+ {
+ matchCase = true;
+ }
+ else if (option == "DOMAIN" && typeof value != "undefined")
+ {
+ domains = value;
+ }
+ else if (option == "THIRD_PARTY")
+ {
+ thirdParty = true;
+ }
+ else if (option == "~THIRD_PARTY")
+ {
+ thirdParty = false;
+ }
+ else if (option == "COLLAPSE")
+ {
+ collapse = true;
+ }
+ else if (option == "~COLLAPSE")
+ {
+ collapse = false;
+ }
+ else if (option == "SITEKEY" && typeof value != "undefined")
+ {
+ siteKeys = value.split(/\|/);
+ }
+ }
+ }
+ if (!blocking && (contentType == null || contentType & RegExpFilter.typeMap.DOCUMENT) && (!options || options.indexOf("DOCUMENT") < 0) && !/^\|?[\w\-]+:/.test(text))
+ {
+ if (contentType == null)
+ {
+ contentType = RegExpFilter.prototype.contentType;
+ }
+ contentType &= ~RegExpFilter.typeMap.DOCUMENT;
+ }
+ if (!blocking && siteKeys)
+ {
+ contentType = RegExpFilter.typeMap.DOCUMENT;
+ }
+ try
+ {
+ if (blocking)
+ {
+ return new BlockingFilter(origText, text, contentType, matchCase, domains, thirdParty, collapse);
+ }
+ else
+ {
+ return new WhitelistFilter(origText, text, contentType, matchCase, domains, thirdParty, siteKeys);
+ }
+ }
+ catch (e)
+ {
+ return new InvalidFilter(text, e);
+ }
+ };
+ RegExpFilter.typeMap =
+ {
+ OTHER: 1,
+ SCRIPT: 2,
+ IMAGE: 4,
+ STYLESHEET: 8,
+ OBJECT: 16,
+ SUBDOCUMENT: 32,
+ DOCUMENT: 64,
+ XBL: 1,
+ PING: 1,
+ XMLHTTPREQUEST: 2048,
+ OBJECT_SUBREQUEST: 4096,
+ DTD: 1,
+ MEDIA: 16384,
+ FONT: 32768,
+ BACKGROUND: 4,
+ POPUP: 268435456,
+ DONOTTRACK: 536870912,
+ ELEMHIDE: 1073741824
+ };
+ RegExpFilter.prototype.contentType &= ~ (RegExpFilter.typeMap.ELEMHIDE | RegExpFilter.typeMap.DONOTTRACK | RegExpFilter.typeMap.POPUP);
+
+ function BlockingFilter(text, regexpSource, contentType, matchCase, domains, thirdParty, collapse)
+ {
+ RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, thirdParty);
+ this.collapse = collapse;
+ }
+ exports.BlockingFilter = BlockingFilter;
+ BlockingFilter.prototype =
+ {
+ __proto__: RegExpFilter.prototype,
+ collapse: null
+ };
+
+ function WhitelistFilter(text, regexpSource, contentType, matchCase, domains, thirdParty, siteKeys)
+ {
+ RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, thirdParty);
+ if (siteKeys != null)
+ {
+ this.siteKeys = siteKeys;
+ }
+ }
+ exports.WhitelistFilter = WhitelistFilter;
+ WhitelistFilter.prototype =
+ {
+ __proto__: RegExpFilter.prototype,
+ siteKeys: null
+ };
+
+ function ElemHideBase(text, domains, selector)
+ {
+ ActiveFilter.call(this, text, domains ? domains.toUpperCase() : null);
+ if (domains)
+ {
+ this.selectorDomain = domains.replace(/,~[^,]+/g, "").replace(/^~[^,]+,?/, "").toLowerCase();
+ }
+ this.selector = selector;
+ }
+ exports.ElemHideBase = ElemHideBase;
+ ElemHideBase.prototype =
+ {
+ __proto__: ActiveFilter.prototype,
+ domainSeparator: ",",
+ ignoreTrailingDot: false,
+ selectorDomain: null,
+ selector: null
+ };
+ ElemHideBase.fromText = function(text, domain, isException, tagName, attrRules, selector)
+ {
+ if (!selector)
+ {
+ if (tagName == "*")
+ {
+ tagName = "";
+ }
+ var id = null;
+ var additional = "";
+ if (attrRules)
+ {
+ attrRules = attrRules.match(/\([\w\-]+(?:[$^*]?=[^\(\)"]*)?\)/g);
+ for (var _loopIndex3 = 0; _loopIndex3 < attrRules.length; ++_loopIndex3)
+ {
+ var rule = attrRules[_loopIndex3];
+ rule = rule.substr(1, rule.length - 2);
+ var separatorPos = rule.indexOf("=");
+ if (separatorPos > 0)
+ {
+ rule = rule.replace(/=/, "=\"") + "\"";
+ additional += "[" + rule + "]";
+ }
+ else
+ {
+ if (id)
+ {
+ var Utils = require("utils").Utils;
+ return new InvalidFilter(text, Utils.getString("filter_elemhide_duplicate_id"));
+ }
+ else
+ {
+ id = rule;
+ }
+ }
+ }
+ }
+ if (id)
+ {
+ selector = tagName + "." + id + additional + "," + tagName + "#" + id + additional;
+ }
+ else if (tagName || additional)
+ {
+ selector = tagName + additional;
+ }
+ else
+ {
+ var Utils = require("utils").Utils;
+ return new InvalidFilter(text, Utils.getString("filter_elemhide_nocriteria"));
+ }
+ }
+ if (isException)
+ {
+ return new ElemHideException(text, domain, selector);
+ }
+ else
+ {
+ return new ElemHideFilter(text, domain, selector);
+ }
+ };
+
+ function ElemHideFilter(text, domains, selector)
+ {
+ ElemHideBase.call(this, text, domains, selector);
+ }
+ exports.ElemHideFilter = ElemHideFilter;
+ ElemHideFilter.prototype =
+ {
+ __proto__: ElemHideBase.prototype
+ };
+
+ function ElemHideException(text, domains, selector)
+ {
+ ElemHideBase.call(this, text, domains, selector);
+ }
+ exports.ElemHideException = ElemHideException;
+ ElemHideException.prototype =
+ {
+ __proto__: ElemHideBase.prototype
+ };
+ return exports;
+})();
+require.scopes["subscriptionClasses"] = (function()
+{
+ var exports = {};
+ var _tempVar4 = require("filterClasses");
+ var ActiveFilter = _tempVar4.ActiveFilter;
+ var BlockingFilter = _tempVar4.BlockingFilter;
+ var WhitelistFilter = _tempVar4.WhitelistFilter;
+ var ElemHideBase = _tempVar4.ElemHideBase;
+ var FilterNotifier = require("filterNotifier").FilterNotifier;
+
+ function Subscription(url, title)
+ {
+ this.url = url;
+ this.filters = [];
+ if (title)
+ {
+ this._title = title;
+ }
+ else
+ {
+ var Utils = require("utils").Utils;
+ this._title = Utils.getString("newGroup_title");
+ }
+ Subscription.knownSubscriptions[url] = this;
+ }
+ exports.Subscription = Subscription;
+ Subscription.prototype =
+ {
+ url: null,
+ filters: null,
+ _title: null,
+ _fixedTitle: false,
+ _disabled: false,
+ get title()
+ {
+ return this._title;
+ },
+ set title(value)
+ {
+ if (value != this._title)
+ {
+ var oldValue = this._title;
+ this._title = value;
+ FilterNotifier.triggerListeners("subscription.title", this, value, oldValue);
+ }
+ return this._title;
+ },
+ get fixedTitle()
+ {
+ return this._fixedTitle;
+ },
+ set fixedTitle(value)
+ {
+ if (value != this._fixedTitle)
+ {
+ var oldValue = this._fixedTitle;
+ this._fixedTitle = value;
+ FilterNotifier.triggerListeners("subscription.fixedTitle", this, value, oldValue);
+ }
+ return this._fixedTitle;
+ },
+ get disabled()
+ {
+ return this._disabled;
+ },
+ set disabled(value)
+ {
+ if (value != this._disabled)
+ {
+ var oldValue = this._disabled;
+ this._disabled = value;
+ FilterNotifier.triggerListeners("subscription.disabled", this, value, oldValue);
+ }
+ return this._disabled;
+ },
+ serialize: function(buffer)
+ {
+ buffer.push("[Subscription]");
+ buffer.push("url=" + this.url);
+ buffer.push("title=" + this._title);
+ if (this._fixedTitle)
+ {
+ buffer.push("fixedTitle=true");
+ }
+ if (this._disabled)
+ {
+ buffer.push("disabled=true");
+ }
+ },
+ serializeFilters: function(buffer)
+ {
+ for (var _loopIndex5 = 0; _loopIndex5 < this.filters.length; ++_loopIndex5)
+ {
+ var filter = this.filters[_loopIndex5];
+ buffer.push(filter.text.replace(/\[/g, "\\["));
+ }
+ },
+ toString: function()
+ {
+ var buffer = [];
+ this.serialize(buffer);
+ return buffer.join("\n");
+ }
+ };
+ Subscription.knownSubscriptions =
+ {
+ __proto__: null
+ };
+ Subscription.fromURL = function(url)
+ {
+ if (url in Subscription.knownSubscriptions)
+ {
+ return Subscription.knownSubscriptions[url];
+ }
+ try
+ {
+ url = Services.io.newURI(url, null, null).spec;
+ return new DownloadableSubscription(url, null);
+ }
+ catch (e)
+ {
+ return new SpecialSubscription(url);
+ }
+ };
+ Subscription.fromObject = function(obj)
+ {
+ var result;
+ try
+ {
+ obj.url = Services.io.newURI(obj.url, null, null).spec;
+ result = new DownloadableSubscription(obj.url, obj.title);
+ if ("nextURL" in obj)
+ {
+ result.nextURL = obj.nextURL;
+ }
+ if ("downloadStatus" in obj)
+ {
+ result._downloadStatus = obj.downloadStatus;
+ }
+ if ("lastModified" in obj)
+ {
+ result.lastModified = obj.lastModified;
+ }
+ if ("lastSuccess" in obj)
+ {
+ result.lastSuccess = parseInt(obj.lastSuccess) || 0;
+ }
+ if ("lastCheck" in obj)
+ {
+ result._lastCheck = parseInt(obj.lastCheck) || 0;
+ }
+ if ("expires" in obj)
+ {
+ result.expires = parseInt(obj.expires) || 0;
+ }
+ if ("softExpiration" in obj)
+ {
+ result.softExpiration = parseInt(obj.softExpiration) || 0;
+ }
+ if ("errors" in obj)
+ {
+ result._errors = parseInt(obj.errors) || 0;
+ }
+ if ("requiredVersion" in obj)
+ {
+ var addonVersion = require("info").addonVersion;
+ result.requiredVersion = obj.requiredVersion;
+ if (Services.vc.compare(result.requiredVersion, addonVersion) > 0)
+ {
+ result.upgradeRequired = true;
+ }
+ }
+ if ("alternativeLocations" in obj)
+ {
+ result.alternativeLocations = obj.alternativeLocations;
+ }
+ if ("homepage" in obj)
+ {
+ result._homepage = obj.homepage;
+ }
+ if ("lastDownload" in obj)
+ {
+ result._lastDownload = parseInt(obj.lastDownload) || 0;
+ }
+ }
+ catch (e)
+ {
+ if (!("title" in obj))
+ {
+ if (obj.url == "~wl~")
+ {
+ obj.defaults = "whitelist";
+ }
+ else if (obj.url == "~fl~")
+ {
+ obj.defaults = "blocking";
+ }
+ else if (obj.url == "~eh~")
+ {
+ obj.defaults = "elemhide";
+ }
+ if ("defaults" in obj)
+ {
+ var Utils = require("utils").Utils;
+ obj.title = Utils.getString(obj.defaults + "Group_title");
+ }
+ }
+ result = new SpecialSubscription(obj.url, obj.title);
+ if ("defaults" in obj)
+ {
+ result.defaults = obj.defaults.split(" ");
+ }
+ }
+ if ("fixedTitle" in obj)
+ {
+ result._fixedTitle = obj.fixedTitle == "true";
+ }
+ if ("disabled" in obj)
+ {
+ result._disabled = obj.disabled == "true";
+ }
+ return result;
+ };
+
+ function SpecialSubscription(url, title)
+ {
+ Subscription.call(this, url, title);
+ }
+ exports.SpecialSubscription = SpecialSubscription;
+ SpecialSubscription.prototype =
+ {
+ __proto__: Subscription.prototype,
+ defaults: null,
+ isDefaultFor: function(filter)
+ {
+ if (this.defaults && this.defaults.length)
+ {
+ for (var _loopIndex6 = 0; _loopIndex6 < this.defaults.length; ++_loopIndex6)
+ {
+ var type = this.defaults[_loopIndex6];
+ if (filter instanceof SpecialSubscription.defaultsMap[type])
+ {
+ return true;
+ }
+ if (!(filter instanceof ActiveFilter) && type == "blacklist")
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ },
+ serialize: function(buffer)
+ {
+ Subscription.prototype.serialize.call(this, buffer);
+ if (this.defaults && this.defaults.length)
+ {
+ buffer.push("defaults=" + this.defaults.filter(function(type)
+ {
+ return type in SpecialSubscription.defaultsMap;
+ }).join(" "));
+ }
+ if (this._lastDownload)
+ {
+ buffer.push("lastDownload=" + this._lastDownload);
+ }
+ }
+ };
+ SpecialSubscription.defaultsMap =
+ {
+ __proto__: null,
+ "whitelist": WhitelistFilter,
+ "blocking": BlockingFilter,
+ "elemhide": ElemHideBase
+ };
+ SpecialSubscription.create = function(title)
+ {
+ var url;
+ do
+ {
+ url = "~user~" + Math.round(Math.random() * 1000000);
+ }
+ while (url in Subscription.knownSubscriptions);
+ return new SpecialSubscription(url, title);
+ };
+ SpecialSubscription.createForFilter = function(filter)
+ {
+ var subscription = SpecialSubscription.create();
+ subscription.filters.push(filter);
+ for (var type in SpecialSubscription.defaultsMap)
+ {
+ if (filter instanceof SpecialSubscription.defaultsMap[type])
+ {
+ subscription.defaults = [type];
+ }
+ }
+ if (!subscription.defaults)
+ {
+ subscription.defaults = ["blocking"];
+ }
+ var Utils = require("utils").Utils;
+ subscription.title = Utils.getString(subscription.defaults[0] + "Group_title");
+ return subscription;
+ };
+
+ function RegularSubscription(url, title)
+ {
+ Subscription.call(this, url, title || url);
+ }
+ exports.RegularSubscription = RegularSubscription;
+ RegularSubscription.prototype =
+ {
+ __proto__: Subscription.prototype,
+ _homepage: null,
+ _lastDownload: 0,
+ get homepage()
+ {
+ return this._homepage;
+ },
+ set homepage(value)
+ {
+ if (value != this._homepage)
+ {
+ var oldValue = this._homepage;
+ this._homepage = value;
+ FilterNotifier.triggerListeners("subscription.homepage", this, value, oldValue);
+ }
+ return this._homepage;
+ },
+ get lastDownload()
+ {
+ return this._lastDownload;
+ },
+ set lastDownload(value)
+ {
+ if (value != this._lastDownload)
+ {
+ var oldValue = this._lastDownload;
+ this._lastDownload = value;
+ FilterNotifier.triggerListeners("subscription.lastDownload", this, value, oldValue);
+ }
+ return this._lastDownload;
+ },
+ serialize: function(buffer)
+ {
+ Subscription.prototype.serialize.call(this, buffer);
+ if (this._homepage)
+ {
+ buffer.push("homepage=" + this._homepage);
+ }
+ if (this._lastDownload)
+ {
+ buffer.push("lastDownload=" + this._lastDownload);
+ }
+ }
+ };
+
+ function ExternalSubscription(url, title)
+ {
+ RegularSubscription.call(this, url, title);
+ }
+ exports.ExternalSubscription = ExternalSubscription;
+ ExternalSubscription.prototype =
+ {
+ __proto__: RegularSubscription.prototype,
+ serialize: function(buffer)
+ {
+ throw new Error("Unexpected call, external subscriptions should not be serialized");
+ }
+ };
+
+ function DownloadableSubscription(url, title)
+ {
+ RegularSubscription.call(this, url, title);
+ }
+ exports.DownloadableSubscription = DownloadableSubscription;
+ DownloadableSubscription.prototype =
+ {
+ __proto__: RegularSubscription.prototype,
+ _downloadStatus: null,
+ _lastCheck: 0,
+ _errors: 0,
+ nextURL: null,
+ get downloadStatus()
+ {
+ return this._downloadStatus;
+ },
+ set downloadStatus(value)
+ {
+ var oldValue = this._downloadStatus;
+ this._downloadStatus = value;
+ FilterNotifier.triggerListeners("subscription.downloadStatus", this, value, oldValue);
+ return this._downloadStatus;
+ },
+ lastModified: null,
+ lastSuccess: 0,
+ get lastCheck()
+ {
+ return this._lastCheck;
+ },
+ set lastCheck(value)
+ {
+ if (value != this._lastCheck)
+ {
+ var oldValue = this._lastCheck;
+ this._lastCheck = value;
+ FilterNotifier.triggerListeners("subscription.lastCheck", this, value, oldValue);
+ }
+ return this._lastCheck;
+ },
+ expires: 0,
+ softExpiration: 0,
+ get errors()
+ {
+ return this._errors;
+ },
+ set errors(value)
+ {
+ if (value != this._errors)
+ {
+ var oldValue = this._errors;
+ this._errors = value;
+ FilterNotifier.triggerListeners("subscription.errors", this, value, oldValue);
+ }
+ return this._errors;
+ },
+ requiredVersion: null,
+ upgradeRequired: false,
+ alternativeLocations: null,
+ serialize: function(buffer)
+ {
+ RegularSubscription.prototype.serialize.call(this, buffer);
+ if (this.nextURL)
+ {
+ buffer.push("nextURL=" + this.nextURL);
+ }
+ if (this.downloadStatus)
+ {
+ buffer.push("downloadStatus=" + this.downloadStatus);
+ }
+ if (this.lastModified)
+ {
+ buffer.push("lastModified=" + this.lastModified);
+ }
+ if (this.lastSuccess)
+ {
+ buffer.push("lastSuccess=" + this.lastSuccess);
+ }
+ if (this.lastCheck)
+ {
+ buffer.push("lastCheck=" + this.lastCheck);
+ }
+ if (this.expires)
+ {
+ buffer.push("expires=" + this.expires);
+ }
+ if (this.softExpiration)
+ {
+ buffer.push("softExpiration=" + this.softExpiration);
+ }
+ if (this.errors)
+ {
+ buffer.push("errors=" + this.errors);
+ }
+ if (this.requiredVersion)
+ {
+ buffer.push("requiredVersion=" + this.requiredVersion);
+ }
+ if (this.alternativeLocations)
+ {
+ buffer.push("alternativeLocations=" + this.alternativeLocations);
+ }
+ }
+ };
+ return exports;
+})();
+require.scopes["filterStorage"] = (function()
+{
+ var exports = {};
+ var IO = require("io").IO;
+ var Prefs = require("prefs").Prefs;
+ var _tempVar7 = require("filterClasses");
+ var Filter = _tempVar7.Filter;
+ var ActiveFilter = _tempVar7.ActiveFilter;
+ var _tempVar8 = require("subscriptionClasses");
+ var Subscription = _tempVar8.Subscription;
+ var SpecialSubscription = _tempVar8.SpecialSubscription;
+ var ExternalSubscription = _tempVar8.ExternalSubscription;
+ var FilterNotifier = require("filterNotifier").FilterNotifier;
+ var formatVersion = 4;
+ var FilterStorage = exports.FilterStorage =
+ {
+ get formatVersion()
+ {
+ return formatVersion;
+ },
+ get sourceFile()
+ {
+ var file = null;
+ if (Prefs.patternsfile)
+ {
+ file = IO.resolveFilePath(Prefs.patternsfile);
+ }
+ if (!file)
+ {
+ file = IO.resolveFilePath(Prefs.data_directory);
+ if (file)
+ {
+ file.append("patterns.ini");
+ }
+ }
+ if (!file)
+ {
+ try
+ {
+ file = IO.resolveFilePath(Services.prefs.getDefaultBranch("extensions.adblockplus.").getCharPref("data_directory"));
+ if (file)
+ {
+ file.append("patterns.ini");
+ }
+ }
+ catch (e){}
+ }
+ if (!file)
+ {
+ Cu.reportError("Adblock Plus: Failed to resolve filter file location from extensions.adblockplus.patternsfile preference");
+ }
+ this.__defineGetter__("sourceFile", function()
+ {
+ return file;
+ });
+ return this.sourceFile;
+ },
+ fileProperties:
+ {
+ __proto__: null
+ },
+ subscriptions: [],
+ knownSubscriptions:
+ {
+ __proto__: null
+ },
+ getGroupForFilter: function(filter)
+ {
+ var generalSubscription = null;
+ for (var _loopIndex9 = 0; _loopIndex9 < FilterStorage.subscriptions.length; ++_loopIndex9)
+ {
+ var subscription = FilterStorage.subscriptions[_loopIndex9];
+ if (subscription instanceof SpecialSubscription && !subscription.disabled)
+ {
+ if (subscription.isDefaultFor(filter))
+ {
+ return subscription;
+ }
+ if (!generalSubscription && (!subscription.defaults || !subscription.defaults.length))
+ {
+ generalSubscription = subscription;
+ }
+ }
+ }
+ return generalSubscription;
+ },
+ addSubscription: function(subscription, silent)
+ {
+ if (subscription.url in FilterStorage.knownSubscriptions)
+ {
+ return;
+ }
+ FilterStorage.subscriptions.push(subscription);
+ FilterStorage.knownSubscriptions[subscription.url] = subscription;
+ addSubscriptionFilters(subscription);
+ if (!silent)
+ {
+ FilterNotifier.triggerListeners("subscription.added", subscription);
+ }
+ },
+ removeSubscription: function(subscription, silent)
+ {
+ for (var i = 0; i < FilterStorage.subscriptions.length; i++)
+ {
+ if (FilterStorage.subscriptions[i].url == subscription.url)
+ {
+ removeSubscriptionFilters(subscription);
+ FilterStorage.subscriptions.splice(i--, 1);
+ delete FilterStorage.knownSubscriptions[subscription.url];
+ if (!silent)
+ {
+ FilterNotifier.triggerListeners("subscription.removed", subscription);
+ }
+ return;
+ }
+ }
+ },
+ moveSubscription: function(subscription, insertBefore)
+ {
+ var currentPos = FilterStorage.subscriptions.indexOf(subscription);
+ if (currentPos < 0)
+ {
+ return;
+ }
+ var newPos = insertBefore ? FilterStorage.subscriptions.indexOf(insertBefore) : -1;
+ if (newPos < 0)
+ {
+ newPos = FilterStorage.subscriptions.length;
+ }
+ if (currentPos < newPos)
+ {
+ newPos--;
+ }
+ if (currentPos == newPos)
+ {
+ return;
+ }
+ FilterStorage.subscriptions.splice(currentPos, 1);
+ FilterStorage.subscriptions.splice(newPos, 0, subscription);
+ FilterNotifier.triggerListeners("subscription.moved", subscription);
+ },
+ updateSubscriptionFilters: function(subscription, filters)
+ {
+ removeSubscriptionFilters(subscription);
+ subscription.oldFilters = subscription.filters;
+ subscription.filters = filters;
+ addSubscriptionFilters(subscription);
+ FilterNotifier.triggerListeners("subscription.updated", subscription);
+ delete subscription.oldFilters;
+ },
+ addFilter: function(filter, subscription, position, silent)
+ {
+ if (!subscription)
+ {
+ if (filter.subscriptions.some(function(s)
+ {
+ return s instanceof SpecialSubscription && !s.disabled;
+ }))
+ {
+ return;
+ }
+ subscription = FilterStorage.getGroupForFilter(filter);
+ }
+ if (!subscription)
+ {
+ subscription = SpecialSubscription.createForFilter(filter);
+ this.addSubscription(subscription);
+ return;
+ }
+ if (typeof position == "undefined")
+ {
+ position = subscription.filters.length;
+ }
+ if (filter.subscriptions.indexOf(subscription) < 0)
+ {
+ filter.subscriptions.push(subscription);
+ }
+ subscription.filters.splice(position, 0, filter);
+ if (!silent)
+ {
+ FilterNotifier.triggerListeners("filter.added", filter, subscription, position);
+ }
+ },
+ removeFilter: function(filter, subscription, position)
+ {
+ var subscriptions = subscription ? [subscription] : filter.subscriptions.slice();
+ for (var i = 0; i < subscriptions.length; i++)
+ {
+ var subscription = subscriptions[i];
+ if (subscription instanceof SpecialSubscription)
+ {
+ var positions = [];
+ if (typeof position == "undefined")
+ {
+ var index = -1;
+ do
+ {
+ index = subscription.filters.indexOf(filter, index + 1);
+ if (index >= 0)
+ {
+ positions.push(index);
+ }
+ }
+ while (index >= 0);
+ }
+ else
+ {
+ positions.push(position);
+ }
+ for (var j = positions.length - 1; j >= 0; j--)
+ {
+ var position = positions[j];
+ if (subscription.filters[position] == filter)
+ {
+ subscription.filters.splice(position, 1);
+ if (subscription.filters.indexOf(filter) < 0)
+ {
+ var index = filter.subscriptions.indexOf(subscription);
+ if (index >= 0)
+ {
+ filter.subscriptions.splice(index, 1);
+ }
+ }
+ FilterNotifier.triggerListeners("filter.removed", filter, subscription, position);
+ }
+ }
+ }
+ }
+ },
+ moveFilter: function(filter, subscription, oldPosition, newPosition)
+ {
+ if (!(subscription instanceof SpecialSubscription) || subscription.filters[oldPosition] != filter)
+ {
+ return;
+ }
+ newPosition = Math.min(Math.max(newPosition, 0), subscription.filters.length - 1);
+ if (oldPosition == newPosition)
+ {
+ return;
+ }
+ subscription.filters.splice(oldPosition, 1);
+ subscription.filters.splice(newPosition, 0, filter);
+ FilterNotifier.triggerListeners("filter.moved", filter, subscription, oldPosition, newPosition);
+ },
+ increaseHitCount: function(filter)
+ {
+ if (!Prefs.savestats || PrivateBrowsing.enabled || !(filter instanceof ActiveFilter))
+ {
+ return;
+ }
+ filter.hitCount++;
+ filter.lastHit = Date.now();
+ },
+ resetHitCounts: function(filters)
+ {
+ if (!filters)
+ {
+ filters = [];
+ for (var text in Filter.knownFilters)
+ {
+ filters.push(Filter.knownFilters[text]);
+ }
+ }
+ for (var _loopIndex10 = 0; _loopIndex10 < filters.length; ++_loopIndex10)
+ {
+ var filter = filters[_loopIndex10];
+ filter.hitCount = 0;
+ filter.lastHit = 0;
+ }
+ },
+ _loading: false,
+ loadFromDisk: function(sourceFile)
+ {
+ if (this._loading)
+ {
+ return;
+ }
+ var readFile = function(sourceFile, backupIndex)
+ {
+ var parser = new INIParser();
+ IO.readFromFile(sourceFile, true, parser, function(e)
+ {
+ if (!e && parser.subscriptions.length == 0)
+ {
+ e = new Error("No data in the file");
+ }
+ if (e)
+ {
+ Cu.reportError(e);
+ }
+ if (e && !explicitFile)
+ {
+ sourceFile = this.sourceFile;
+ if (sourceFile)
+ {
+ var _tempVar11 = /^(.*)(\.\w+)$/.exec(sourceFile.leafName) || [null, sourceFile.leafName, ""];
+ var part1 = _tempVar11[1];
+ var part2 = _tempVar11[2];
+ sourceFile = sourceFile.clone();
+ sourceFile.leafName = part1 + "-backup" + ++backupIndex + part2;
+ IO.statFile(sourceFile, function(e, statData)
+ {
+ if (!e && statData.exists)
+ {
+ readFile(sourceFile, backupIndex);
+ }
+ });
+ return;
+ }
+ }
+ var specialMap =
+ {
+ "~il~": true,
+ "~wl~": true,
+ "~fl~": true,
+ "~eh~": true
+ };
+ var knownSubscriptions =
+ {
+ __proto__: null
+ };
+ for (var i = 0; i < parser.subscriptions.length; i++)
+ {
+ var subscription = parser.subscriptions[i];
+ if (subscription instanceof SpecialSubscription && subscription.filters.length == 0 && subscription.url in specialMap)
+ {
+ parser.subscriptions.splice(i--, 1);
+ }
+ else
+ {
+ knownSubscriptions[subscription.url] = subscription;
+ }
+ }
+ this.fileProperties = parser.fileProperties;
+ this.subscriptions = parser.subscriptions;
+ this.knownSubscriptions = knownSubscriptions;
+ Filter.knownFilters = parser.knownFilters;
+ Subscription.knownSubscriptions = parser.knownSubscriptions;
+ if (parser.userFilters)
+ {
+ for (var i = 0; i < parser.userFilters.length; i++)
+ {
+ var filter = Filter.fromText(parser.userFilters[i]);
+ this.addFilter(filter, null, undefined, true);
+ }
+ }
+ this._loading = false;
+ FilterNotifier.triggerListeners("load");
+ if (sourceFile != this.sourceFile)
+ {
+ this.saveToDisk();
+ }
+ }.bind(this), "FilterStorageRead");
+ }.bind(this);
+ var startRead = function(file)
+ {
+ this._loading = true;
+ readFile(file, 0);
+ }.bind(this);
+ var explicitFile;
+ if (sourceFile)
+ {
+ explicitFile = true;
+ startRead(sourceFile);
+ }
+ else
+ {
+ explicitFile = false;
+ sourceFile = FilterStorage.sourceFile;
+ var callback = function(e, statData)
+ {
+ if (e || !statData.exists)
+ {
+ var addonRoot = require("info").addonRoot;
+ sourceFile = Services.io.newURI(addonRoot + "defaults/patterns.ini", null, null);
+ }
+ startRead(sourceFile);
+ };
+ if (sourceFile)
+ {
+ IO.statFile(sourceFile, callback);
+ }
+ else
+ {
+ callback(true);
+ }
+ }
+ },
+ _generateFilterData: function(subscriptions)
+ {
+ var _generatorResult12 = [];
+ _generatorResult12.push("# Adblock Plus preferences");
+ _generatorResult12.push("version=" + formatVersion);
+ var saved =
+ {
+ __proto__: null
+ };
+ var buf = [];
+ for (var i = 0; i < subscriptions.length; i++)
+ {
+ var subscription = subscriptions[i];
+ for (var j = 0; j < subscription.filters.length; j++)
+ {
+ var filter = subscription.filters[j];
+ if (!(filter.text in saved))
+ {
+ filter.serialize(buf);
+ saved[filter.text] = filter;
+ for (var k = 0; k < buf.length; k++)
+ {
+ _generatorResult12.push(buf[k]);
+ }
+ buf.splice(0);
+ }
+ }
+ }
+ for (var i = 0; i < subscriptions.length; i++)
+ {
+ var subscription = subscriptions[i];
+ _generatorResult12.push("");
+ subscription.serialize(buf);
+ if (subscription.filters.length)
+ {
+ buf.push("", "[Subscription filters]");
+ subscription.serializeFilters(buf);
+ }
+ for (var k = 0; k < buf.length; k++)
+ {
+ _generatorResult12.push(buf[k]);
+ }
+ buf.splice(0);
+ }
+ return _generatorResult12;
+ },
+ _saving: false,
+ _needsSave: false,
+ saveToDisk: function(targetFile)
+ {
+ var explicitFile = true;
+ if (!targetFile)
+ {
+ targetFile = FilterStorage.sourceFile;
+ explicitFile = false;
+ }
+ if (!targetFile)
+ {
+ return;
+ }
+ if (!explicitFile && this._saving)
+ {
+ this._needsSave = true;
+ return;
+ }
+ try
+ {
+ targetFile.parent.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
+ }
+ catch (e){}
+ var writeFilters = function()
+ {
+ IO.writeToFile(targetFile, true, this._generateFilterData(subscriptions), function(e)
+ {
+ if (!explicitFile)
+ {
+ this._saving = false;
+ }
+ if (e)
+ {
+ Cu.reportError(e);
+ }
+ if (!explicitFile && this._needsSave)
+ {
+ this._needsSave = false;
+ this.saveToDisk();
+ }
+ else
+ {
+ FilterNotifier.triggerListeners("save");
+ }
+ }.bind(this), "FilterStorageWrite");
+ }.bind(this);
+ var checkBackupRequired = function(callbackNotRequired, callbackRequired)
+ {
+ if (explicitFile || Prefs.patternsbackups <= 0)
+ {
+ callbackNotRequired();
+ }
+ else
+ {
+ IO.statFile(targetFile, function(e, statData)
+ {
+ if (e || !statData.exists)
+ {
+ callbackNotRequired();
+ }
+ else
+ {
+ var _tempVar13 = /^(.*)(\.\w+)$/.exec(targetFile.leafName) || [null, targetFile.leafName, ""];
+ var part1 = _tempVar13[1];
+ var part2 = _tempVar13[2];
+ var newestBackup = targetFile.clone();
+ newestBackup.leafName = part1 + "-backup1" + part2;
+ IO.statFile(newestBackup, function(e, statData)
+ {
+ if (!e && (!statData.exists || (Date.now() - statData.lastModified) / 3600000 >= Prefs.patternsbackupinterval))
+ {
+ callbackRequired(part1, part2);
+ }
+ else
+ {
+ callbackNotRequired();
+ }
+ });
+ }
+ });
+ }
+ }.bind(this);
+ var removeLastBackup = function(part1, part2)
+ {
+ var file = targetFile.clone();
+ file.leafName = part1 + "-backup" + Prefs.patternsbackups + part2;
+ IO.removeFile(file, function(e)
+ {
+ return renameBackup(part1, part2, Prefs.patternsbackups - 1);
+ });
+ }.bind(this);
+ var renameBackup = function(part1, part2, index)
+ {
+ if (index > 0)
+ {
+ var fromFile = targetFile.clone();
+ fromFile.leafName = part1 + "-backup" + index + part2;
+ var toName = part1 + "-backup" + (index + 1) + part2;
+ IO.renameFile(fromFile, toName, function(e)
+ {
+ return renameBackup(part1, part2, index - 1);
+ });
+ }
+ else
+ {
+ var toFile = targetFile.clone();
+ toFile.leafName = part1 + "-backup" + (index + 1) + part2;
+ IO.copyFile(targetFile, toFile, writeFilters);
+ }
+ }.bind(this);
+ var subscriptions = this.subscriptions.filter(function(s)
+ {
+ return !(s instanceof ExternalSubscription);
+ });
+ if (!explicitFile)
+ {
+ this._saving = true;
+ }
+ checkBackupRequired(writeFilters, removeLastBackup);
+ },
+ getBackupFiles: function()
+ {
+ var result = [];
+ var _tempVar14 = /^(.*)(\.\w+)$/.exec(FilterStorage.sourceFile.leafName) || [null, FilterStorage.sourceFile.leafName, ""];
+ var part1 = _tempVar14[1];
+ var part2 = _tempVar14[2];
+ for (var i = 1;; i++)
+ {
+ var file = FilterStorage.sourceFile.clone();
+ file.leafName = part1 + "-backup" + i + part2;
+ if (file.exists())
+ {
+ result.push(file);
+ }
+ else
+ {
+ break;
+ }
+ }
+ return result;
+ }
+ };
+
+ function addSubscriptionFilters(subscription)
+ {
+ if (!(subscription.url in FilterStorage.knownSubscriptions))
+ {
+ return;
+ }
+ for (var _loopIndex15 = 0; _loopIndex15 < subscription.filters.length; ++_loopIndex15)
+ {
+ var filter = subscription.filters[_loopIndex15];
+ filter.subscriptions.push(subscription);
+ }
+ }
+
+ function removeSubscriptionFilters(subscription)
+ {
+ if (!(subscription.url in FilterStorage.knownSubscriptions))
+ {
+ return;
+ }
+ for (var _loopIndex16 = 0; _loopIndex16 < subscription.filters.length; ++_loopIndex16)
+ {
+ var filter = subscription.filters[_loopIndex16];
+ var i = filter.subscriptions.indexOf(subscription);
+ if (i >= 0)
+ {
+ filter.subscriptions.splice(i, 1);
+ }
+ }
+ }
+ var PrivateBrowsing = exports.PrivateBrowsing =
+ {
+ enabled: false,
+ init: function()
+ {
+ if ("@mozilla.org/privatebrowsing;1" in Cc)
+ {
+ try
+ {
+ this.enabled = Cc["@mozilla.org/privatebrowsing;1"].getService(Ci.nsIPrivateBrowsingService).privateBrowsingEnabled;
+ Services.obs.addObserver(this, "private-browsing", true);
+ onShutdown.add(function()
+ {
+ Services.obs.removeObserver(this, "private-browsing");
+ }.bind(this));
+ }
+ catch (e)
+ {
+ Cu.reportError(e);
+ }
+ }
+ },
+ observe: function(subject, topic, data)
+ {
+ if (topic == "private-browsing")
+ {
+ if (data == "enter")
+ {
+ this.enabled = true;
+ }
+ else if (data == "exit")
+ {
+ this.enabled = false;
+ }
+ }
+ },
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference, Ci.nsIObserver])
+ };
+ PrivateBrowsing.init();
+
+ function INIParser()
+ {
+ this.fileProperties = this.curObj = {};
+ this.subscriptions = [];
+ this.knownFilters =
+ {
+ __proto__: null
+ };
+ this.knownSubscriptions =
+ {
+ __proto__: null
+ };
+ }
+ INIParser.prototype =
+ {
+ subscriptions: null,
+ knownFilters: null,
+ knownSubscrptions: null,
+ wantObj: true,
+ fileProperties: null,
+ curObj: null,
+ curSection: null,
+ userFilters: null,
+ process: function(val)
+ {
+ var origKnownFilters = Filter.knownFilters;
+ Filter.knownFilters = this.knownFilters;
+ var origKnownSubscriptions = Subscription.knownSubscriptions;
+ Subscription.knownSubscriptions = this.knownSubscriptions;
+ var match;
+ try
+ {
+ if (this.wantObj === true && (match = /^(\w+)=(.*)$/.exec(val)))
+ {
+ this.curObj[match[1]] = match[2];
+ }
+ else if (val === null || (match = /^\s*\[(.+)\]\s*$/.exec(val)))
+ {
+ if (this.curObj)
+ {
+ switch (this.curSection)
+ {
+ case "filter":
+ case "pattern":
+ if ("text" in this.curObj)
+ {
+ Filter.fromObject(this.curObj);
+ }
+ break;
+ case "subscription":
+ var subscription = Subscription.fromObject(this.curObj);
+ if (subscription)
+ {
+ this.subscriptions.push(subscription);
+ }
+ break;
+ case "subscription filters":
+ case "subscription patterns":
+ if (this.subscriptions.length)
+ {
+ var subscription = this.subscriptions[this.subscriptions.length - 1];
+ for (var _loopIndex17 = 0; _loopIndex17 < this.curObj.length; ++_loopIndex17)
+ {
+ var text = this.curObj[_loopIndex17];
+ var filter = Filter.fromText(text);
+ subscription.filters.push(filter);
+ filter.subscriptions.push(subscription);
+ }
+ }
+ break;
+ case "user patterns":
+ this.userFilters = this.curObj;
+ break;
+ }
+ }
+ if (val === null)
+ {
+ return;
+ }
+ this.curSection = match[1].toLowerCase();
+ switch (this.curSection)
+ {
+ case "filter":
+ case "pattern":
+ case "subscription":
+ this.wantObj = true;
+ this.curObj = {};
+ break;
+ case "subscription filters":
+ case "subscription patterns":
+ case "user patterns":
+ this.wantObj = false;
+ this.curObj = [];
+ break;
+ default:
+ this.wantObj = undefined;
+ this.curObj = null;
+ }
+ }
+ else if (this.wantObj === false && val)
+ {
+ this.curObj.push(val.replace(/\\\[/g, "["));
+ }
+ }
+ finally
+ {
+ Filter.knownFilters = origKnownFilters;
+ Subscription.knownSubscriptions = origKnownSubscriptions;
+ }
+ }
+ };
+ return exports;
+})();
+require.scopes["elemHide"] = (function()
+{
+ var exports = {};
+ var Utils = require("utils").Utils;
+ var IO = require("io").IO;
+ var Prefs = require("prefs").Prefs;
+ var ElemHideException = require("filterClasses").ElemHideException;
+ var FilterNotifier = require("filterNotifier").FilterNotifier;
+ var AboutHandler = require("elemHideHitRegistration").AboutHandler;
+ var filterByKey =
+ {
+ __proto__: null
+ };
+ var keyByFilter =
+ {
+ __proto__: null
+ };
+ var knownExceptions =
+ {
+ __proto__: null
+ };
+ var exceptions =
+ {
+ __proto__: null
+ };
+ var styleURL = null;
+ var ElemHide = exports.ElemHide =
+ {
+ isDirty: false,
+ applied: false,
+ init: function()
+ {
+ Prefs.addListener(function(name)
+ {
+ if (name == "enabled")
+ {
+ ElemHide.apply();
+ }
+ });
+ onShutdown.add(function()
+ {
+ ElemHide.unapply();
+ });
+ var styleFile = IO.resolveFilePath(Prefs.data_directory);
+ styleFile.append("elemhide.css");
+ styleURL = Services.io.newFileURI(styleFile).QueryInterface(Ci.nsIFileURL);
+ },
+ clear: function()
+ {
+ filterByKey =
+ {
+ __proto__: null
+ };
+ keyByFilter =
+ {
+ __proto__: null
+ };
+ knownExceptions =
+ {
+ __proto__: null
+ };
+ exceptions =
+ {
+ __proto__: null
+ };
+ ElemHide.isDirty = false;
+ ElemHide.unapply();
+ },
+ add: function(filter)
+ {
+ if (filter instanceof ElemHideException)
+ {
+ if (filter.text in knownExceptions)
+ {
+ return;
+ }
+ var selector = filter.selector;
+ if (!(selector in exceptions))
+ {
+ exceptions[selector] = [];
+ }
+ exceptions[selector].push(filter);
+ knownExceptions[filter.text] = true;
+ }
+ else
+ {
+ if (filter.text in keyByFilter)
+ {
+ return;
+ }
+ var key;
+ do
+ {
+ key = Math.random().toFixed(15).substr(5);
+ }
+ while (key in filterByKey);
+ filterByKey[key] = filter;
+ keyByFilter[filter.text] = key;
+ ElemHide.isDirty = true;
+ }
+ },
+ remove: function(filter)
+ {
+ if (filter instanceof ElemHideException)
+ {
+ if (!(filter.text in knownExceptions))
+ {
+ return;
+ }
+ var list = exceptions[filter.selector];
+ var index = list.indexOf(filter);
+ if (index >= 0)
+ {
+ list.splice(index, 1);
+ }
+ delete knownExceptions[filter.text];
+ }
+ else
+ {
+ if (!(filter.text in keyByFilter))
+ {
+ return;
+ }
+ var key = keyByFilter[filter.text];
+ delete filterByKey[key];
+ delete keyByFilter[filter.text];
+ ElemHide.isDirty = true;
+ }
+ },
+ getException: function(filter, docDomain)
+ {
+ var selector = filter.selector;
+ if (!(filter.selector in exceptions))
+ {
+ return null;
+ }
+ var list = exceptions[filter.selector];
+ for (var i = list.length - 1; i >= 0; i--)
+ {
+ if (list[i].isActiveOnDomain(docDomain))
+ {
+ return list[i];
+ }
+ }
+ return null;
+ },
+ _applying: false,
+ _needsApply: false,
+ apply: function()
+ {
+ if (this._applying)
+ {
+ this._needsApply = true;
+ return;
+ }
+ if (!ElemHide.isDirty || !Prefs.enabled)
+ {
+ if (Prefs.enabled && !ElemHide.applied)
+ {
+ try
+ {
+ Utils.styleService.loadAndRegisterSheet(styleURL, Ci.nsIStyleSheetService.USER_SHEET);
+ ElemHide.applied = true;
+ }
+ catch (e)
+ {
+ Cu.reportError(e);
+ }
+ }
+ else if (!Prefs.enabled && ElemHide.applied)
+ {
+ ElemHide.unapply();
+ }
+ return;
+ }
+ IO.writeToFile(styleURL.file, false, this._generateCSSContent(), function(e)
+ {
+ this._applying = false;
+ if (e && e.result == Cr.NS_ERROR_NOT_AVAILABLE)
+ {
+ IO.removeFile(styleURL.file, function(e2){});
+ }
+ else if (e)
+ {
+ Cu.reportError(e);
+ }
+ if (this._needsApply)
+ {
+ this._needsApply = false;
+ this.apply();
+ }
+ else if (!e || e.result == Cr.NS_ERROR_NOT_AVAILABLE)
+ {
+ ElemHide.isDirty = false;
+ ElemHide.unapply();
+ if (!e)
+ {
+ try
+ {
+ Utils.styleService.loadAndRegisterSheet(styleURL, Ci.nsIStyleSheetService.USER_SHEET);
+ ElemHide.applied = true;
+ }
+ catch (e)
+ {
+ Cu.reportError(e);
+ }
+ }
+ FilterNotifier.triggerListeners("elemhideupdate");
+ }
+ }.bind(this), "ElemHideWrite");
+ this._applying = true;
+ },
+ _generateCSSContent: function()
+ {
+ var _generatorResult12 = [];
+ var domains =
+ {
+ __proto__: null
+ };
+ var hasFilters = false;
+ for (var key in filterByKey)
+ {
+ var filter = filterByKey[key];
+ var domain = filter.selectorDomain || "";
+ var list;
+ if (domain in domains)
+ {
+ list = domains[domain];
+ }
+ else
+ {
+ list =
+ {
+ __proto__: null
+ };
+ domains[domain] = list;
+ }
+ list[filter.selector] = key;
+ hasFilters = true;
+ }
+ if (!hasFilters)
+ {
+ throw Cr.NS_ERROR_NOT_AVAILABLE;
+ }
+
+ function escapeChar(match)
+ {
+ return "\\" + match.charCodeAt(0).toString(16) + " ";
+ }
+ var cssTemplate = "-moz-binding: url(about:" + AboutHandler.aboutPrefix + "?%ID%#dummy) !important;";
+ for (var domain in domains)
+ {
+ var rules = [];
+ var list = domains[domain];
+ if (domain)
+ {
+ _generatorResult12.push(("@-moz-document domain(\"" + domain.split(",").join("\"),domain(\"") + "\"){").replace(/[^\x01-\x7F]/g, escapeChar));
+ }
+ else
+ {
+ _generatorResult12.push("@-moz-document url-prefix(\"http://\"),url-prefix(\"https://\"),url-prefix(\"mailbox://\"),url-prefix(\"imap://\"),url-prefix(\"news://\"),url-prefix(\"snews://\"){");
+ }
+ for (var selector in list)
+ {
+ _generatorResult12.push(selector.replace(/[^\x01-\x7F]/g, escapeChar) + "{" + cssTemplate.replace("%ID%", list[selector]) + "}");
+ }
+ _generatorResult12.push("}");
+ }
+ return _generatorResult12;
+ },
+ unapply: function()
+ {
+ if (ElemHide.applied)
+ {
+ try
+ {
+ Utils.styleService.unregisterSheet(styleURL, Ci.nsIStyleSheetService.USER_SHEET);
+ }
+ catch (e)
+ {
+ Cu.reportError(e);
+ }
+ ElemHide.applied = false;
+ }
+ },
+ get styleURL()
+ {
+ return ElemHide.applied ? styleURL.spec : null;
+ },
+ getFilterByKey: function(key)
+ {
+ return key in filterByKey ? filterByKey[key] : null;
+ },
+ getSelectorsForDomain: function(domain, specificOnly)
+ {
+ var result = [];
+ for (var key in filterByKey)
+ {
+ var filter = filterByKey[key];
+ if (specificOnly && (!filter.domains || filter.domains[""]))
+ {
+ continue;
+ }
+ if (filter.isActiveOnDomain(domain) && !this.getException(filter, domain))
+ {
+ result.push(filter.selector);
+ }
+ }
+ return result;
+ }
+ };
+ return exports;
+})();
+require.scopes["filterListener"] = (function()
+{
+ var exports = {};
+ var FilterStorage = require("filterStorage").FilterStorage;
+ var FilterNotifier = require("filterNotifier").FilterNotifier;
+ var ElemHide = require("elemHide").ElemHide;
+ var defaultMatcher = require("matcher").defaultMatcher;
+ var _tempVar18 = require("filterClasses");
+ var ActiveFilter = _tempVar18.ActiveFilter;
+ var RegExpFilter = _tempVar18.RegExpFilter;
+ var ElemHideBase = _tempVar18.ElemHideBase;
+ var Prefs = require("prefs").Prefs;
+ var batchMode = false;
+ var isDirty = 0;
+ var FilterListener = exports.FilterListener =
+ {
+ get batchMode()
+ {
+ return batchMode;
+ },
+ set batchMode(value)
+ {
+ batchMode = value;
+ flushElemHide();
+ },
+ setDirty: function(factor)
+ {
+ if (factor == 0 && isDirty > 0)
+ {
+ isDirty = 1;
+ }
+ else
+ {
+ isDirty += factor;
+ }
+ if (isDirty >= 1)
+ {
+ FilterStorage.saveToDisk();
+ }
+ }
+ };
+ var HistoryPurgeObserver =
+ {
+ observe: function(subject, topic, data)
+ {
+ if (topic == "browser:purge-session-history" && Prefs.clearStatsOnHistoryPurge)
+ {
+ FilterStorage.resetHitCounts();
+ FilterListener.setDirty(0);
+ Prefs.recentReports = [];
+ }
+ },
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference, Ci.nsIObserver])
+ };
+
+ function init()
+ {
+ FilterNotifier.addListener(function(action, item, newValue, oldValue)
+ {
+ var match = /^(\w+)\.(.*)/.exec(action);
+ if (match && match[1] == "filter")
+ {
+ onFilterChange(match[2], item, newValue, oldValue);
+ }
+ else if (match && match[1] == "subscription")
+ {
+ onSubscriptionChange(match[2], item, newValue, oldValue);
+ }
+ else
+ {
+ onGenericChange(action, item);
+ }
+ });
+ var application = require("info").application;
+ if (application == "chrome" || application == "opera")
+ {
+ flushElemHide = function(){};
+ }
+ else
+ {
+ ElemHide.init();
+ }
+ FilterStorage.loadFromDisk();
+ Services.obs.addObserver(HistoryPurgeObserver, "browser:purge-session-history", true);
+ onShutdown.add(function()
+ {
+ Services.obs.removeObserver(HistoryPurgeObserver, "browser:purge-session-history");
+ });
+ }
+ init();
+
+ function flushElemHide()
+ {
+ if (!batchMode && ElemHide.isDirty)
+ {
+ ElemHide.apply();
+ }
+ }
+
+ function addFilter(filter)
+ {
+ if (!(filter instanceof ActiveFilter) || filter.disabled)
+ {
+ return;
+ }
+ var hasEnabled = false;
+ for (var i = 0; i < filter.subscriptions.length; i++)
+ {
+ if (!filter.subscriptions[i].disabled)
+ {
+ hasEnabled = true;
+ }
+ }
+ if (!hasEnabled)
+ {
+ return;
+ }
+ if (filter instanceof RegExpFilter)
+ {
+ defaultMatcher.add(filter);
+ }
+ else if (filter instanceof ElemHideBase)
+ {
+ ElemHide.add(filter);
+ }
+ }
+
+ function removeFilter(filter)
+ {
+ if (!(filter instanceof ActiveFilter))
+ {
+ return;
+ }
+ if (!filter.disabled)
+ {
+ var hasEnabled = false;
+ for (var i = 0; i < filter.subscriptions.length; i++)
+ {
+ if (!filter.subscriptions[i].disabled)
+ {
+ hasEnabled = true;
+ }
+ }
+ if (hasEnabled)
+ {
+ return;
+ }
+ }
+ if (filter instanceof RegExpFilter)
+ {
+ defaultMatcher.remove(filter);
+ }
+ else if (filter instanceof ElemHideBase)
+ {
+ ElemHide.remove(filter);
+ }
+ }
+
+ function onSubscriptionChange(action, subscription, newValue, oldValue)
+ {
+ FilterListener.setDirty(1);
+ if (action != "added" && action != "removed" && action != "disabled" && action != "updated")
+ {
+ return;
+ }
+ if (action != "removed" && !(subscription.url in FilterStorage.knownSubscriptions))
+ {
+ return;
+ }
+ if ((action == "added" || action == "removed" || action == "updated") && subscription.disabled)
+ {
+ return;
+ }
+ if (action == "added" || action == "removed" || action == "disabled")
+ {
+ var method = action == "added" || action == "disabled" && newValue == false ? addFilter : removeFilter;
+ if (subscription.filters)
+ {
+ subscription.filters.forEach(method);
+ }
+ }
+ else if (action == "updated")
+ {
+ subscription.oldFilters.forEach(removeFilter);
+ subscription.filters.forEach(addFilter);
+ }
+ flushElemHide();
+ }
+
+ function onFilterChange(action, filter, newValue, oldValue)
+ {
+ if (action == "hitCount" || action == "lastHit")
+ {
+ FilterListener.setDirty(0.002);
+ }
+ else
+ {
+ FilterListener.setDirty(1);
+ }
+ if (action != "added" && action != "removed" && action != "disabled")
+ {
+ return;
+ }
+ if ((action == "added" || action == "removed") && filter.disabled)
+ {
+ return;
+ }
+ if (action == "added" || action == "disabled" && newValue == false)
+ {
+ addFilter(filter);
+ }
+ else
+ {
+ removeFilter(filter);
+ }
+ flushElemHide();
+ }
+
+ function onGenericChange(action)
+ {
+ if (action == "load")
+ {
+ isDirty = 0;
+ defaultMatcher.clear();
+ ElemHide.clear();
+ for (var _loopIndex19 = 0; _loopIndex19 < FilterStorage.subscriptions.length; ++_loopIndex19)
+ {
+ var subscription = FilterStorage.subscriptions[_loopIndex19];
+ if (!subscription.disabled)
+ {
+ subscription.filters.forEach(addFilter);
+ }
+ }
+ flushElemHide();
+ }
+ else if (action == "save")
+ {
+ isDirty = 0;
+ }
+ }
+ return exports;
+})();
+require.scopes["synchronizer"] = (function()
+{
+ var exports = {};
+ var Utils = require("utils").Utils;
+ var FilterStorage = require("filterStorage").FilterStorage;
+ var FilterNotifier = require("filterNotifier").FilterNotifier;
+ var Prefs = require("prefs").Prefs;
+ var _tempVar20 = require("filterClasses");
+ var Filter = _tempVar20.Filter;
+ var CommentFilter = _tempVar20.CommentFilter;
+ var _tempVar21 = require("subscriptionClasses");
+ var Subscription = _tempVar21.Subscription;
+ var DownloadableSubscription = _tempVar21.DownloadableSubscription;
+ var MILLISECONDS_IN_SECOND = 1000;
+ var SECONDS_IN_MINUTE = 60;
+ var SECONDS_IN_HOUR = 60 * SECONDS_IN_MINUTE;
+ var SECONDS_IN_DAY = 24 * SECONDS_IN_HOUR;
+ var INITIAL_DELAY = 6 * SECONDS_IN_MINUTE;
+ var CHECK_INTERVAL = SECONDS_IN_HOUR;
+ var MIN_EXPIRATION_INTERVAL = 1 * SECONDS_IN_DAY;
+ var MAX_EXPIRATION_INTERVAL = 14 * SECONDS_IN_DAY;
+ var MAX_ABSENSE_INTERVAL = 1 * SECONDS_IN_DAY;
+ var timer = null;
+ var executing =
+ {
+ __proto__: null
+ };
+ var Synchronizer = exports.Synchronizer =
+ {
+ init: function()
+ {
+ var callback = function()
+ {
+ timer.delay = CHECK_INTERVAL * MILLISECONDS_IN_SECOND;
+ checkSubscriptions();
+ };
+ timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+ timer.initWithCallback(callback, INITIAL_DELAY * MILLISECONDS_IN_SECOND, Ci.nsITimer.TYPE_REPEATING_SLACK);
+ onShutdown.add(function()
+ {
+ timer.cancel();
+ });
+ },
+ isExecuting: function(url)
+ {
+ return url in executing;
+ },
+ execute: function(subscription, manual, forceDownload)
+ {
+ Utils.runAsync(this.executeInternal, this, subscription, manual, forceDownload);
+ },
+ executeInternal: function(subscription, manual, forceDownload)
+ {
+ var url = subscription.url;
+ if (url in executing)
+ {
+ return;
+ }
+ var newURL = subscription.nextURL;
+ var hadTemporaryRedirect = false;
+ subscription.nextURL = null;
+ var loadFrom = newURL;
+ var isBaseLocation = true;
+ if (!loadFrom)
+ {
+ loadFrom = url;
+ }
+ if (loadFrom == url)
+ {
+ if (subscription.alternativeLocations)
+ {
+ var options = [
+ [1, url]
+ ];
+ var totalWeight = 1;
+ for (var _loopIndex22 = 0; _loopIndex22 < subscription.alternativeLocations.split(",").length; ++_loopIndex22)
+ {
+ var alternative = subscription.alternativeLocations.split(",")[_loopIndex22];
+ if (!/^https?:\/\//.test(alternative))
+ {
+ continue;
+ }
+ var weight = 1;
+ var match = /;q=([\d\.]+)$/.exec(alternative);
+ if (match)
+ {
+ weight = parseFloat(match[1]);
+ if (isNaN(weight) || !isFinite(weight) || weight < 0)
+ {
+ weight = 1;
+ }
+ if (weight > 10)
+ {
+ weight = 10;
+ }
+ alternative = alternative.substr(0, match.index);
+ }
+ options.push([weight, alternative]);
+ totalWeight += weight;
+ }
+ var choice = Math.random() * totalWeight;
+ for (var _loopIndex23 = 0; _loopIndex23 < options.length; ++_loopIndex23)
+ {
+ var _tempVar24 = options[_loopIndex23];
+ var weight = _tempVar24[0];
+ var alternative = _tempVar24[1];
+ choice -= weight;
+ if (choice < 0)
+ {
+ loadFrom = alternative;
+ break;
+ }
+ }
+ isBaseLocation = loadFrom == url;
+ }
+ }
+ else
+ {
+ forceDownload = true;
+ }
+ var addonVersion = require("info").addonVersion;
+ loadFrom = loadFrom.replace(/%VERSION%/, "ABP" + addonVersion);
+ var request = null;
+
+ function errorCallback(error)
+ {
+ var channelStatus = -1;
+ try
+ {
+ channelStatus = request.channel.status;
+ }
+ catch (e){}
+ var responseStatus = "";
+ try
+ {
+ responseStatus = request.channel.QueryInterface(Ci.nsIHttpChannel).responseStatus;
+ }
+ catch (e){}
+ setError(subscription, error, channelStatus, responseStatus, loadFrom, isBaseLocation, manual);
+ }
+ try
+ {
+ request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
+ request.mozBackgroundRequest = true;
+ request.open("GET", loadFrom);
+ }
+ catch (e)
+ {
+ errorCallback("synchronize_invalid_url");
+ return;
+ }
+ try
+ {
+ request.overrideMimeType("text/plain");
+ request.channel.loadFlags = request.channel.loadFlags | request.channel.INHIBIT_CACHING | request.channel.VALIDATE_ALWAYS;
+ if (request.channel instanceof Ci.nsIHttpChannel)
+ {
+ request.channel.redirectionLimit = 5;
+ }
+ var oldNotifications = request.channel.notificationCallbacks;
+ var oldEventSink = null;
+ request.channel.notificationCallbacks =
+ {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIInterfaceRequestor, Ci.nsIChannelEventSink]),
+ getInterface: function(iid)
+ {
+ if (iid.equals(Ci.nsIChannelEventSink))
+ {
+ try
+ {
+ oldEventSink = oldNotifications.QueryInterface(iid);
+ }
+ catch (e){}
+ return this;
+ }
+ if (oldNotifications)
+ {
+ return oldNotifications.QueryInterface(iid);
+ }
+ else
+ {
+ throw Cr.NS_ERROR_NO_INTERFACE;
+ }
+ },
+ asyncOnChannelRedirect: function(oldChannel, newChannel, flags, callback)
+ {
+ if (isBaseLocation && !hadTemporaryRedirect && oldChannel instanceof Ci.nsIHttpChannel)
+ {
+ try
+ {
+ subscription.alternativeLocations = oldChannel.getResponseHeader("X-Alternative-Locations");
+ }
+ catch (e)
+ {
+ subscription.alternativeLocations = null;
+ }
+ }
+ if (flags & Ci.nsIChannelEventSink.REDIRECT_TEMPORARY)
+ {
+ hadTemporaryRedirect = true;
+ }
+ else if (!hadTemporaryRedirect)
+ {
+ newURL = newChannel.URI.spec;
+ }
+ if (oldEventSink)
+ {
+ oldEventSink.asyncOnChannelRedirect(oldChannel, newChannel, flags, callback);
+ }
+ else
+ {
+ callback.onRedirectVerifyCallback(Cr.NS_OK);
+ }
+ }
+ };
+ }
+ catch (e)
+ {
+ Cu.reportError(e);
+ }
+ if (subscription.lastModified && !forceDownload)
+ {
+ request.setRequestHeader("If-Modified-Since", subscription.lastModified);
+ }
+ request.addEventListener("error", function(ev)
+ {
+ if (onShutdown.done)
+ {
+ return;
+ }
+ delete executing[url];
+ try
+ {
+ request.channel.notificationCallbacks = null;
+ }
+ catch (e){}
+ errorCallback("synchronize_connection_error");
+ }, false);
+ request.addEventListener("load", function(ev)
+ {
+ if (onShutdown.done)
+ {
+ return;
+ }
+ delete executing[url];
+ try
+ {
+ request.channel.notificationCallbacks = null;
+ }
+ catch (e){}
+ if (request.status && request.status != 200 && request.status != 304)
+ {
+ errorCallback("synchronize_connection_error");
+ return;
+ }
+ var newFilters = null;
+ if (request.status != 304)
+ {
+ newFilters = readFilters(subscription, request.responseText, errorCallback);
+ if (!newFilters)
+ {
+ return;
+ }
+ subscription.lastModified = request.getResponseHeader("Last-Modified");
+ }
+ if (isBaseLocation && !hadTemporaryRedirect)
+ {
+ subscription.alternativeLocations = request.getResponseHeader("X-Alternative-Locations");
+ }
+ subscription.lastSuccess = subscription.lastDownload = Math.round(Date.now() / MILLISECONDS_IN_SECOND);
+ subscription.downloadStatus = "synchronize_ok";
+ subscription.errors = 0;
+ var now = Math.round(((new Date(request.getResponseHeader("Date"))).getTime() || Date.now()) / MILLISECONDS_IN_SECOND);
+ var expires = Math.round((new Date(request.getResponseHeader("Expires"))).getTime() / MILLISECONDS_IN_SECOND) || 0;
+ var expirationInterval = expires ? expires - now : 0;
+ for (var _loopIndex25 = 0; _loopIndex25 < (newFilters || subscription.filters).length; ++_loopIndex25)
+ {
+ var filter = (newFilters || subscription.filters)[_loopIndex25];
+ if (!(filter instanceof CommentFilter))
+ {
+ continue;
+ }
+ var match = /\bExpires\s*(?::|after)\s*(\d+)\s*(h)?/i.exec(filter.text);
+ if (match)
+ {
+ var interval = parseInt(match[1], 10);
+ if (match[2])
+ {
+ interval *= SECONDS_IN_HOUR;
+ }
+ else
+ {
+ interval *= SECONDS_IN_DAY;
+ }
+ if (interval > expirationInterval)
+ {
+ expirationInterval = interval;
+ }
+ }
+ }
+ expirationInterval = Math.min(Math.max(expirationInterval, MIN_EXPIRATION_INTERVAL), MAX_EXPIRATION_INTERVAL);
+ subscription.expires = subscription.lastDownload + expirationInterval * 2;
+ subscription.softExpiration = subscription.lastDownload + Math.round(expirationInterval * (Math.random() * 0.4 + 0.8));
+ if (newFilters)
+ {
+ var fixedTitle = false;
+ for (var i = 0; i < newFilters.length; i++)
+ {
+ var filter = newFilters[i];
+ if (!(filter instanceof CommentFilter))
+ {
+ continue;
+ }
+ var match = /^!\s*(\w+)\s*:\s*(.*)/.exec(filter.text);
+ if (match)
+ {
+ var keyword = match[1].toLowerCase();
+ var value = match[2];
+ var known = true;
+ if (keyword == "redirect")
+ {
+ if (isBaseLocation && value != url)
+ {
+ subscription.nextURL = value;
+ }
+ }
+ else if (keyword == "homepage")
+ {
+ var uri = Utils.makeURI(value);
+ if (uri && (uri.scheme == "http" || uri.scheme == "https"))
+ {
+ subscription.homepage = uri.spec;
+ }
+ }
+ else if (keyword == "title")
+ {
+ if (value)
+ {
+ subscription.title = value;
+ fixedTitle = true;
+ }
+ }
+ else
+ {
+ known = false;
+ }
+ if (known)
+ {
+ newFilters.splice(i--, 1);
+ }
+ }
+ }
+ subscription.fixedTitle = fixedTitle;
+ }
+ if (isBaseLocation && newURL && newURL != url)
+ {
+ var listed = subscription.url in FilterStorage.knownSubscriptions;
+ if (listed)
+ {
+ FilterStorage.removeSubscription(subscription);
+ }
+ url = newURL;
+ var newSubscription = Subscription.fromURL(url);
+ for (var key in newSubscription)
+ {
+ delete newSubscription[key];
+ }
+ for (var key in subscription)
+ {
+ newSubscription[key] = subscription[key];
+ }
+ delete Subscription.knownSubscriptions[subscription.url];
+ newSubscription.oldSubscription = subscription;
+ subscription = newSubscription;
+ subscription.url = url;
+ if (!(subscription.url in FilterStorage.knownSubscriptions) && listed)
+ {
+ FilterStorage.addSubscription(subscription);
+ }
+ }
+ if (newFilters)
+ {
+ FilterStorage.updateSubscriptionFilters(subscription, newFilters);
+ }
+ delete subscription.oldSubscription;
+ }, false);
+ executing[url] = true;
+ FilterNotifier.triggerListeners("subscription.downloadStatus", subscription);
+ try
+ {
+ request.send(null);
+ }
+ catch (e)
+ {
+ delete executing[url];
+ errorCallback("synchronize_connection_error");
+ return;
+ }
+ }
+ };
+ Synchronizer.init();
+
+ function checkSubscriptions()
+ {
+ if (!Prefs.subscriptions_autoupdate)
+ {
+ return;
+ }
+ var time = Math.round(Date.now() / MILLISECONDS_IN_SECOND);
+ for (var _loopIndex26 = 0; _loopIndex26 < FilterStorage.subscriptions.length; ++_loopIndex26)
+ {
+ var subscription = FilterStorage.subscriptions[_loopIndex26];
+ if (!(subscription instanceof DownloadableSubscription))
+ {
+ continue;
+ }
+ if (subscription.lastCheck && time - subscription.lastCheck > MAX_ABSENSE_INTERVAL)
+ {
+ subscription.softExpiration += time - subscription.lastCheck;
+ }
+ subscription.lastCheck = time;
+ if (subscription.expires - time > MAX_EXPIRATION_INTERVAL)
+ {
+ subscription.expires = time + MAX_EXPIRATION_INTERVAL;
+ }
+ if (subscription.softExpiration - time > MAX_EXPIRATION_INTERVAL)
+ {
+ subscription.softExpiration = time + MAX_EXPIRATION_INTERVAL;
+ }
+ if (subscription.softExpiration > time && subscription.expires > time)
+ {
+ continue;
+ }
+ if (time - subscription.lastDownload >= MIN_EXPIRATION_INTERVAL)
+ {
+ Synchronizer.execute(subscription, false);
+ }
+ }
+ }
+
+ function readFilters(subscription, text, errorCallback)
+ {
+ var lines = text.split(/[\r\n]+/);
+ var match = /\[Adblock(?:\s*Plus\s*([\d\.]+)?)?\]/i.exec(lines[0]);
+ if (!match)
+ {
+ errorCallback("synchronize_invalid_data");
+ return null;
+ }
+ var minVersion = match[1];
+ for (var i = 0; i < lines.length; i++)
+ {
+ var match = /!\s*checksum[\s\-:]+([\w\+\/]+)/i.exec(lines[i]);
+ if (match)
+ {
+ lines.splice(i, 1);
+ var checksum = Utils.generateChecksum(lines);
+ if (checksum && checksum != match[1])
+ {
+ errorCallback("synchronize_checksum_mismatch");
+ return null;
+ }
+ break;
+ }
+ }
+ delete subscription.requiredVersion;
+ delete subscription.upgradeRequired;
+ if (minVersion)
+ {
+ var addonVersion = require("info").addonVersion;
+ subscription.requiredVersion = minVersion;
+ if (Services.vc.compare(minVersion, addonVersion) > 0)
+ {
+ subscription.upgradeRequired = true;
+ }
+ }
+ lines.shift();
+ var result = [];
+ for (var _loopIndex27 = 0; _loopIndex27 < lines.length; ++_loopIndex27)
+ {
+ var line = lines[_loopIndex27];
+ line = Filter.normalize(line);
+ if (line)
+ {
+ result.push(Filter.fromText(line));
+ }
+ }
+ return result;
+ }
+
+ function setError(subscription, error, channelStatus, responseStatus, downloadURL, isBaseLocation, manual)
+ {
+ if (!isBaseLocation)
+ {
+ subscription.alternativeLocations = null;
+ }
+ try
+ {
+ Cu.reportError("Adblock Plus: Downloading filter subscription " + subscription.title + " failed (" + Utils.getString(error) + ")\n" + "Download address: " + downloadURL + "\n" + "Channel status: " + channelStatus + "\n" + "Server response: " + responseStatus);
+ }
+ catch (e){}
+ subscription.lastDownload = Math.round(Date.now() / MILLISECONDS_IN_SECOND);
+ subscription.downloadStatus = error;
+ if (!manual)
+ {
+ if (error == "synchronize_checksum_mismatch")
+ {
+ subscription.errors = 0;
+ }
+ else
+ {
+ subscription.errors++;
+ }
+ if (subscription.errors >= Prefs.subscriptions_fallbackerrors && /^https?:\/\//i.test(subscription.url))
+ {
+ subscription.errors = 0;
+ var fallbackURL = Prefs.subscriptions_fallbackurl;
+ var addonVersion = require("info").addonVersion;
+ fallbackURL = fallbackURL.replace(/%VERSION%/g, encodeURIComponent(addonVersion));
+ fallbackURL = fallbackURL.replace(/%SUBSCRIPTION%/g, encodeURIComponent(subscription.url));
+ fallbackURL = fallbackURL.replace(/%URL%/g, encodeURIComponent(downloadURL));
+ fallbackURL = fallbackURL.replace(/%ERROR%/g, encodeURIComponent(error));
+ fallbackURL = fallbackURL.replace(/%CHANNELSTATUS%/g, encodeURIComponent(channelStatus));
+ fallbackURL = fallbackURL.replace(/%RESPONSESTATUS%/g, encodeURIComponent(responseStatus));
+ var request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
+ request.mozBackgroundRequest = true;
+ request.open("GET", fallbackURL);
+ request.overrideMimeType("text/plain");
+ request.channel.loadFlags = request.channel.loadFlags | request.channel.INHIBIT_CACHING | request.channel.VALIDATE_ALWAYS;
+ request.addEventListener("load", function(ev)
+ {
+ if (onShutdown.done)
+ {
+ return;
+ }
+ if (!(subscription.url in FilterStorage.knownSubscriptions))
+ {
+ return;
+ }
+ var match = /^(\d+)(?:\s+(\S+))?$/.exec(request.responseText);
+ if (match && match[1] == "301" && match[2])
+ {
+ subscription.nextURL = match[2];
+ }
+ else if (match && match[1] == "410")
+ {
+ var data = "[Adblock]\n" + subscription.filters.map(function(f)
+ {
+ return f.text;
+ }).join("\n");
+ var url = "data:text/plain," + encodeURIComponent(data);
+ var newSubscription = Subscription.fromURL(url);
+ newSubscription.title = subscription.title;
+ newSubscription.disabled = subscription.disabled;
+ FilterStorage.removeSubscription(subscription);
+ FilterStorage.addSubscription(newSubscription);
+ Synchronizer.execute(newSubscription);
+ }
+ }, false);
+ request.send(null);
+ }
+ }
+ }
+ return exports;
+})();

Powered by Google App Engine
This is Rietveld