Index: assets/js/FilterStorage.jsm |
=================================================================== |
new file mode 100755 |
--- /dev/null |
+++ b/assets/js/FilterStorage.jsm |
@@ -0,0 +1,544 @@ |
+/* |
+ * 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 source code |
+// |
+ |
+(function (_patchFunc11) { |
+ const formatVersion = 4; |
+ var FilterStorage = { |
+ get formatVersion() { |
+ return formatVersion; |
+ }, |
+ get sourceFile() { |
+ var file = null; |
+ if (Prefs.patternsfile) { |
+ file = Utils.resolveFilePath(Prefs.patternsfile); |
+ } |
+ if (!file) { |
+ file = Utils.resolveFilePath(Prefs.data_directory); |
+ if (file) |
+ file.append("patterns.ini"); |
+ } |
+ if (!file) { |
+ try { |
+ file = Utils.resolveFilePath(Prefs.defaultBranch.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 _loopIndex0 = 0; |
+ _loopIndex0 < FilterStorage.subscriptions.length; ++ _loopIndex0) { |
+ var subscription = FilterStorage.subscriptions[_loopIndex0]; |
+ if (subscription instanceof SpecialSubscription) { |
+ 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; |
+ if (subscription instanceof SpecialSubscription && !subscription.filters.length && subscription.disabled) |
+ subscription.disabled = false; |
+ } |
+ , |
+ addFilter: function (filter, subscription, position, silent) { |
+ if (!subscription) { |
+ if (filter.subscriptions.some(function (s) { |
+ return s instanceof SpecialSubscription; |
+ })) |
+ 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 || Prefs.privateBrowsing || !(filter instanceof ActiveFilter)) |
+ return ; |
+ filter.hitCount++; |
+ filter.lastHit = Date.now(); |
+ } |
+ , |
+ resetHitCounts: function (filters) { |
+ if (!filters) { |
+ filters = []; |
+ for (var _loopIndex2 = 0; |
+ _loopIndex2 < Filter.knownFilters.length; ++ _loopIndex2) { |
+ var filter = Filter.knownFilters[_loopIndex2]; |
+ filters.push(filter); |
+ } |
+ } |
+ for (var _loopIndex1 = 0; |
+ _loopIndex1 < filters.length; ++ _loopIndex1) { |
+ var filter = filters[_loopIndex1]; |
+ filter.hitCount = 0; |
+ filter.lastHit = 0; |
+ } |
+ } |
+ , |
+ loadFromDisk: function (sourceFile, silent) { |
+ if (!silent) { |
+ Filter.knownFilters = { |
+ __proto__: null |
+ }; |
+ Subscription.knownSubscriptions = { |
+ __proto__: null |
+ }; |
+ } |
+ var explicitFile = true; |
+ if (!sourceFile) { |
+ sourceFile = FilterStorage.sourceFile; |
+ explicitFile = false; |
+ if (!sourceFile || !sourceFile.exists()) { |
+ var patternsURL = Utils.ioService.newURI("chrome://adblockplus-defaults/content/patterns.ini", null, null); |
+ patternsURL = Utils.chromeRegistry.convertChromeURL(patternsURL); |
+ if (patternsURL instanceof Ci.nsIFileURL) |
+ sourceFile = patternsURL.file; |
+ } |
+ } |
+ var userFilters = null; |
+ var backup = 0; |
+ while (true) { |
+ FilterStorage.subscriptions = []; |
+ FilterStorage.knownSubscriptions = { |
+ __proto__: null |
+ }; |
+ try { |
+ if (sourceFile && sourceFile.exists()) { |
+ var fileStream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream); |
+ fileStream.init(sourceFile, 1, 292, 0); |
+ var stream = Cc["@mozilla.org/intl/converter-input-stream;1"].createInstance(Ci.nsIConverterInputStream); |
+ stream.init(fileStream, "UTF-8", 16384, 0); |
+ stream = stream.QueryInterface(Ci.nsIUnicharLineInputStream); |
+ userFilters = parseIniFile(stream); |
+ stream.close(); |
+ if (!FilterStorage.subscriptions.length) { |
+ throw new Error("No data in the file"); |
+ } |
+ } |
+ break; |
+ } |
+ catch (e){ |
+ Cu.reportError("Adblock Plus: Failed to read filters from file " + sourceFile.path); |
+ Cu.reportError(e); |
+ } |
+ if (explicitFile) |
+ break; |
+ sourceFile = FilterStorage.sourceFile; |
+ if (!sourceFile) |
+ break; |
+ var part1 = sourceFile.leafName; |
+ var part2 = ""; |
+ if (/^(.*)(\.\w+)$/.test(part1)) { |
+ part1 = RegExp["$1"]; |
+ part2 = RegExp["$2"]; |
+ } |
+ sourceFile = sourceFile.clone(); |
+ sourceFile.leafName = part1 + "-backup" + (++ backup) + part2; |
+ } |
+ for (var _loopIndex3 = 0; |
+ _loopIndex3 < ["~il~", "~wl~", "~fl~", "~eh~"].length; ++ _loopIndex3) { |
+ var specialSubscription = ["~il~", "~wl~", "~fl~", "~eh~"][_loopIndex3]; |
+ if (specialSubscription in FilterStorage.knownSubscriptions) { |
+ var subscription = Subscription.fromURL(specialSubscription); |
+ if (subscription.filters.length == 0) |
+ FilterStorage.removeSubscription(subscription, true); |
+ } |
+ } |
+ if (userFilters) { |
+ for (var _loopIndex4 = 0; |
+ _loopIndex4 < userFilters.length; ++ _loopIndex4) { |
+ var filter = userFilters[_loopIndex4]; |
+ filter = Filter.fromText(filter); |
+ if (filter) |
+ FilterStorage.addFilter(filter, null, undefined, true); |
+ } |
+ } |
+ if (!silent) |
+ FilterNotifier.triggerListeners("load"); |
+ } |
+ , |
+ saveToDisk: function (targetFile) { |
+ var explicitFile = true; |
+ if (!targetFile) { |
+ targetFile = FilterStorage.sourceFile; |
+ explicitFile = false; |
+ } |
+ if (!targetFile) |
+ return ; |
+ try { |
+ targetFile.normalize(); |
+ } |
+ catch (e){} |
+ try { |
+ targetFile.parent.create(Ci.nsIFile.DIRECTORY_TYPE, 493); |
+ } |
+ catch (e){} |
+ var tempFile = targetFile.clone(); |
+ tempFile.leafName += "-temp"; |
+ var fileStream, stream; |
+ try { |
+ fileStream = Cc["@mozilla.org/network/safe-file-output-stream;1"].createInstance(Ci.nsIFileOutputStream); |
+ fileStream.init(tempFile, 2 | 8 | 32, 420, 0); |
+ stream = Cc["@mozilla.org/intl/converter-output-stream;1"].createInstance(Ci.nsIConverterOutputStream); |
+ stream.init(fileStream, "UTF-8", 16384, Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER); |
+ } |
+ catch (e){ |
+ Cu.reportError(e); |
+ return ; |
+ } |
+ const maxBufLength = 1024; |
+ var buf = ["# Adblock Plus preferences", "version=" + formatVersion]; |
+ var lineBreak = Utils.getLineBreak(); |
+ function writeBuffer() { |
+ stream.writeString(buf.join(lineBreak) + lineBreak); |
+ buf.splice(0, buf.length); |
+ } |
+ var saved = { |
+ __proto__: null |
+ }; |
+ for (var _loopIndex5 = 0; |
+ _loopIndex5 < FilterStorage.subscriptions.length; ++ _loopIndex5) { |
+ var subscription = FilterStorage.subscriptions[_loopIndex5]; |
+ if (subscription instanceof ExternalSubscription) |
+ continue; |
+ for (var _loopIndex7 = 0; |
+ _loopIndex7 < subscription.filters.length; ++ _loopIndex7) { |
+ var filter = subscription.filters[_loopIndex7]; |
+ if (!(filter.text in saved)) { |
+ filter.serialize(buf); |
+ saved[filter.text] = filter; |
+ if (buf.length > maxBufLength) |
+ writeBuffer(); |
+ } |
+ } |
+ } |
+ for (var _loopIndex6 = 0; |
+ _loopIndex6 < FilterStorage.subscriptions.length; ++ _loopIndex6) { |
+ var subscription = FilterStorage.subscriptions[_loopIndex6]; |
+ if (subscription instanceof ExternalSubscription) |
+ continue; |
+ buf.push(""); |
+ subscription.serialize(buf); |
+ if (subscription.filters.length) { |
+ buf.push("", "[Subscription filters]"); |
+ subscription.serializeFilters(buf); |
+ } |
+ if (buf.length > maxBufLength) |
+ writeBuffer(); |
+ } |
+ try { |
+ stream.writeString(buf.join(lineBreak) + lineBreak); |
+ stream.flush(); |
+ fileStream.QueryInterface(Ci.nsISafeOutputStream).finish(); |
+ } |
+ catch (e){ |
+ Cu.reportError(e); |
+ return ; |
+ } |
+ if (!explicitFile && targetFile.exists()) { |
+ var part1 = targetFile.leafName; |
+ var part2 = ""; |
+ if (/^(.*)(\.\w+)$/.test(part1)) { |
+ part1 = RegExp["$1"]; |
+ part2 = RegExp["$2"]; |
+ } |
+ var doBackup = (Prefs.patternsbackups > 0); |
+ if (doBackup) { |
+ var lastBackup = targetFile.clone(); |
+ lastBackup.leafName = part1 + "-backup1" + part2; |
+ if (lastBackup.exists() && (Date.now() - lastBackup.lastModifiedTime) / 3600000 < Prefs.patternsbackupinterval) |
+ doBackup = false; |
+ } |
+ if (doBackup) { |
+ var backupFile = targetFile.clone(); |
+ backupFile.leafName = part1 + "-backup" + Prefs.patternsbackups + part2; |
+ try { |
+ backupFile.remove(false); |
+ } |
+ catch (e){} |
+ for (var i = Prefs.patternsbackups - 1; |
+ i >= 0; i--) { |
+ backupFile.leafName = part1 + (i > 0 ? "-backup" + i : "") + part2; |
+ try { |
+ backupFile.moveTo(backupFile.parent, part1 + "-backup" + (i + 1) + part2); |
+ } |
+ catch (e){} |
+ } |
+ } |
+ } |
+ else |
+ if (targetFile.exists()) |
+ targetFile.remove(false); |
+ tempFile.moveTo(targetFile.parent, targetFile.leafName); |
+ if (!explicitFile) |
+ FilterNotifier.triggerListeners("save"); |
+ } |
+ , |
+ getBackupFiles: function () { |
+ var result = []; |
+ var part1 = FilterStorage.sourceFile.leafName; |
+ var part2 = ""; |
+ if (/^(.*)(\.\w+)$/.test(part1)) { |
+ part1 = RegExp["$1"]; |
+ part2 = RegExp["$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 _loopIndex8 = 0; |
+ _loopIndex8 < subscription.filters.length; ++ _loopIndex8) { |
+ var filter = subscription.filters[_loopIndex8]; |
+ filter.subscriptions.push(subscription); |
+ } |
+ } |
+ function removeSubscriptionFilters(subscription) { |
+ if (!(subscription.url in FilterStorage.knownSubscriptions)) |
+ return ; |
+ for (var _loopIndex9 = 0; |
+ _loopIndex9 < subscription.filters.length; ++ _loopIndex9) { |
+ var filter = subscription.filters[_loopIndex9]; |
+ var i = filter.subscriptions.indexOf(subscription); |
+ if (i >= 0) |
+ filter.subscriptions.splice(i, 1); |
+ } |
+ } |
+ function parseIniFile(stream) { |
+ var wantObj = true; |
+ FilterStorage.fileProperties = { |
+ |
+ }; |
+ var curObj = FilterStorage.fileProperties; |
+ var curSection = null; |
+ var line = { |
+ |
+ }; |
+ var haveMore = true; |
+ var userFilters = null; |
+ while (true) { |
+ if (haveMore) |
+ haveMore = stream.readLine(line); |
+ else |
+ line.value = "[end]"; |
+ var val = line.value; |
+ if (wantObj === true && /^(\w+)=(.*)$/.test(val)) |
+ curObj[RegExp["$1"]] = RegExp["$2"]; |
+ else |
+ if (/^\s*\[(.+)\]\s*$/.test(val)) { |
+ var newSection = RegExp["$1"].toLowerCase(); |
+ if (curObj) { |
+ switch (curSection) { |
+ case "filter": ; |
+ case "pattern": { |
+ if ("text" in curObj) |
+ Filter.fromObject(curObj); |
+ break; |
+ } |
+ case "subscription": { |
+ var subscription = Subscription.fromObject(curObj); |
+ if (subscription) |
+ FilterStorage.addSubscription(subscription, true); |
+ break; |
+ } |
+ case "subscription filters": ; |
+ case "subscription patterns": { |
+ if (FilterStorage.subscriptions.length) { |
+ var subscription = FilterStorage.subscriptions[FilterStorage.subscriptions.length - 1]; |
+ for (var _loopIndex10 = 0; |
+ _loopIndex10 < curObj.length; ++ _loopIndex10) { |
+ var text = curObj[_loopIndex10]; |
+ var filter = Filter.fromText(text); |
+ if (filter) { |
+ subscription.filters.push(filter); |
+ filter.subscriptions.push(subscription); |
+ } |
+ } |
+ } |
+ break; |
+ } |
+ case "user patterns": { |
+ userFilters = curObj; |
+ break; |
+ } |
+ } |
+ } |
+ if (newSection == "end") |
+ break; |
+ curSection = newSection; |
+ switch (curSection) { |
+ case "filter": ; |
+ case "pattern": ; |
+ case "subscription": { |
+ wantObj = true; |
+ curObj = { |
+ |
+ }; |
+ break; |
+ } |
+ case "subscription filters": ; |
+ case "subscription patterns": ; |
+ case "user patterns": { |
+ wantObj = false; |
+ curObj = []; |
+ break; |
+ } |
+ default: { |
+ wantObj = undefined; |
+ curObj = null; |
+ } |
+ } |
+ } |
+ else |
+ if (wantObj === false && val) |
+ curObj.push(val.replace(/\\\[/g, "[")); |
+ } |
+ return userFilters; |
+ } |
+ if (typeof _patchFunc11 != "undefined") |
+ eval("(" + _patchFunc11.toString() + ")()"); |
+ window.FilterStorage = FilterStorage; |
+} |
+)(window.FilterStoragePatch); |