| Index: lib/filterStorage.js |
| =================================================================== |
| deleted file mode 100644 |
| --- a/lib/filterStorage.js |
| +++ /dev/null |
| @@ -1,800 +0,0 @@ |
| -/* |
| - * This file is part of Adblock Plus <https://adblockplus.org/>, |
| - * Copyright (C) 2006-2016 Eyeo GmbH |
| - * |
| - * Adblock Plus is free software: you can redistribute it and/or modify |
| - * it under the terms of the GNU General Public License version 3 as |
| - * published by the Free Software Foundation. |
| - * |
| - * Adblock Plus 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 Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
| - */ |
| - |
| -/** |
| - * @fileOverview FilterStorage class responsible for managing user's subscriptions and filters. |
| - */ |
| - |
| -Cu.import("resource://gre/modules/Services.jsm"); |
| -Cu.import("resource://gre/modules/FileUtils.jsm"); |
| -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
| - |
| -let {IO} = require("io"); |
| -let {Prefs} = require("prefs"); |
| -let {Filter, ActiveFilter} = require("filterClasses"); |
| -let {Subscription, SpecialSubscription, ExternalSubscription} = require("subscriptionClasses"); |
| -let {FilterNotifier} = require("filterNotifier"); |
| -let {Utils} = require("utils"); |
| - |
| -/** |
| - * Version number of the filter storage file format. |
| - * @type Integer |
| - */ |
| -let formatVersion = 4; |
| - |
| -/** |
| - * This class reads user's filters from disk, manages them in memory and writes them back. |
| - * @class |
| - */ |
| -let FilterStorage = exports.FilterStorage = |
| -{ |
| - /** |
| - * Version number of the patterns.ini format used. |
| - * @type Integer |
| - */ |
| - get formatVersion() |
| - { |
| - return formatVersion; |
| - }, |
| - |
| - /** |
| - * File that the filter list has been loaded from and should be saved to |
| - * @type nsIFile |
| - */ |
| - get sourceFile() |
| - { |
| - let file = null; |
| - if (Prefs.patternsfile) |
| - { |
| - // Override in place, use it instead of placing the file in the regular data dir |
| - file = IO.resolveFilePath(Prefs.patternsfile); |
| - } |
| - if (!file) |
| - { |
| - // Place the file in the data dir |
| - file = IO.resolveFilePath(Prefs.data_directory); |
| - if (file) |
| - file.append("patterns.ini"); |
| - } |
| - if (!file) |
| - { |
| - // Data directory pref misconfigured? Try the default value |
| - 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"); |
| - |
| - // Property is configurable because of the test suite. |
| - Object.defineProperty(this, "sourceFile", {value: file, configurable: true}); |
| - return file; |
| - }, |
| - |
| - /** |
| - * Will be set to true if no patterns.ini file exists. |
| - * @type Boolean |
| - */ |
| - firstRun: false, |
| - |
| - /** |
| - * Map of properties listed in the filter storage file before the sections |
| - * start. Right now this should be only the format version. |
| - */ |
| - fileProperties: Object.create(null), |
| - |
| - /** |
| - * List of filter subscriptions containing all filters |
| - * @type Subscription[] |
| - */ |
| - subscriptions: [], |
| - |
| - /** |
| - * Map of subscriptions already on the list, by their URL/identifier |
| - * @type Object |
| - */ |
| - knownSubscriptions: Object.create(null), |
| - |
| - /** |
| - * Finds the filter group that a filter should be added to by default. Will |
| - * return null if this group doesn't exist yet. |
| - */ |
| - getGroupForFilter: function(/**Filter*/ filter) /**SpecialSubscription*/ |
| - { |
| - let generalSubscription = null; |
| - for (let subscription of FilterStorage.subscriptions) |
| - { |
| - if (subscription instanceof SpecialSubscription && !subscription.disabled) |
| - { |
| - // Always prefer specialized subscriptions |
| - if (subscription.isDefaultFor(filter)) |
| - return subscription; |
| - |
| - // If this is a general subscription - store it as fallback |
| - if (!generalSubscription && (!subscription.defaults || !subscription.defaults.length)) |
| - generalSubscription = subscription; |
| - } |
| - } |
| - return generalSubscription; |
| - }, |
| - |
| - /** |
| - * Adds a filter subscription to the list |
| - * @param {Subscription} subscription filter subscription to be added |
| - * @param {Boolean} silent if true, no listeners will be triggered (to be used when filter list is reloaded) |
| - */ |
| - 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); |
| - }, |
| - |
| - /** |
| - * Removes a filter subscription from the list |
| - * @param {Subscription} subscription filter subscription to be removed |
| - * @param {Boolean} silent if true, no listeners will be triggered (to be used when filter list is reloaded) |
| - */ |
| - removeSubscription: function(subscription, silent) |
| - { |
| - for (let 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; |
| - } |
| - } |
| - }, |
| - |
| - /** |
| - * Moves a subscription in the list to a new position. |
| - * @param {Subscription} subscription filter subscription to be moved |
| - * @param {Subscription} [insertBefore] filter subscription to insert before |
| - * (if omitted the subscription will be put at the end of the list) |
| - */ |
| - moveSubscription: function(subscription, insertBefore) |
| - { |
| - let currentPos = FilterStorage.subscriptions.indexOf(subscription); |
| - if (currentPos < 0) |
| - return; |
| - |
| - let 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); |
| - }, |
| - |
| - /** |
| - * Replaces the list of filters in a subscription by a new list |
| - * @param {Subscription} subscription filter subscription to be updated |
| - * @param {Filter[]} filters new filter list |
| - */ |
| - updateSubscriptionFilters: function(subscription, filters) |
| - { |
| - removeSubscriptionFilters(subscription); |
| - subscription.oldFilters = subscription.filters; |
| - subscription.filters = filters; |
| - addSubscriptionFilters(subscription); |
| - FilterNotifier.triggerListeners("subscription.updated", subscription); |
| - delete subscription.oldFilters; |
| - }, |
| - |
| - /** |
| - * Adds a user-defined filter to the list |
| - * @param {Filter} filter |
| - * @param {SpecialSubscription} [subscription] particular group that the filter should be added to |
| - * @param {Integer} [position] position within the subscription at which the filter should be added |
| - * @param {Boolean} silent if true, no listeners will be triggered (to be used when filter list is reloaded) |
| - */ |
| - addFilter: function(filter, subscription, position, silent) |
| - { |
| - if (!subscription) |
| - { |
| - if (filter.subscriptions.some(s => s instanceof SpecialSubscription && !s.disabled)) |
| - return; // No need to add |
| - subscription = FilterStorage.getGroupForFilter(filter); |
| - } |
| - if (!subscription) |
| - { |
| - // No group for this filter exists, create one |
| - 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); |
| - }, |
| - |
| - /** |
| - * Removes a user-defined filter from the list |
| - * @param {Filter} filter |
| - * @param {SpecialSubscription} [subscription] a particular filter group that |
| - * the filter should be removed from (if ommited will be removed from all subscriptions) |
| - * @param {Integer} [position] position inside the filter group at which the |
| - * filter should be removed (if ommited all instances will be removed) |
| - */ |
| - removeFilter: function(filter, subscription, position) |
| - { |
| - let subscriptions = (subscription ? [subscription] : filter.subscriptions.slice()); |
| - for (let i = 0; i < subscriptions.length; i++) |
| - { |
| - let subscription = subscriptions[i]; |
| - if (subscription instanceof SpecialSubscription) |
| - { |
| - let positions = []; |
| - if (typeof position == "undefined") |
| - { |
| - let index = -1; |
| - do |
| - { |
| - index = subscription.filters.indexOf(filter, index + 1); |
| - if (index >= 0) |
| - positions.push(index); |
| - } while (index >= 0); |
| - } |
| - else |
| - positions.push(position); |
| - |
| - for (let j = positions.length - 1; j >= 0; j--) |
| - { |
| - let position = positions[j]; |
| - if (subscription.filters[position] == filter) |
| - { |
| - subscription.filters.splice(position, 1); |
| - if (subscription.filters.indexOf(filter) < 0) |
| - { |
| - let index = filter.subscriptions.indexOf(subscription); |
| - if (index >= 0) |
| - filter.subscriptions.splice(index, 1); |
| - } |
| - FilterNotifier.triggerListeners("filter.removed", filter, subscription, position); |
| - } |
| - } |
| - } |
| - } |
| - }, |
| - |
| - /** |
| - * Moves a user-defined filter to a new position |
| - * @param {Filter} filter |
| - * @param {SpecialSubscription} subscription filter group where the filter is located |
| - * @param {Integer} oldPosition current position of the filter |
| - * @param {Integer} newPosition new position of the filter |
| - */ |
| - 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); |
| - }, |
| - |
| - /** |
| - * Increases the hit count for a filter by one |
| - * @param {Filter} filter |
| - */ |
| - increaseHitCount: function(filter) |
| - { |
| - if (!Prefs.savestats || !(filter instanceof ActiveFilter)) |
| - return; |
| - |
| - filter.hitCount++; |
| - filter.lastHit = Date.now(); |
| - }, |
| - |
| - /** |
| - * Resets hit count for some filters |
| - * @param {Filter[]} filters filters to be reset, if null all filters will be reset |
| - */ |
| - resetHitCounts: function(filters) |
| - { |
| - if (!filters) |
| - { |
| - filters = []; |
| - for (let text in Filter.knownFilters) |
| - filters.push(Filter.knownFilters[text]); |
| - } |
| - for (let filter of filters) |
| - { |
| - filter.hitCount = 0; |
| - filter.lastHit = 0; |
| - } |
| - }, |
| - |
| - _loading: false, |
| - |
| - /** |
| - * Loads all subscriptions from the disk |
| - * @param {nsIFile} [sourceFile] File to read from |
| - */ |
| - loadFromDisk: function(sourceFile) |
| - { |
| - if (this._loading) |
| - return; |
| - |
| - this._loading = true; |
| - |
| - let readFile = function(sourceFile, backupIndex) |
| - { |
| - let parser = new INIParser(); |
| - IO.readFromFile(sourceFile, parser, function(e) |
| - { |
| - if (!e && parser.subscriptions.length == 0) |
| - { |
| - // No filter subscriptions in the file, this isn't right. |
| - e = new Error("No data in the file"); |
| - } |
| - |
| - if (e) |
| - Cu.reportError(e); |
| - |
| - if (e && !explicitFile) |
| - { |
| - // Attempt to load a backup |
| - sourceFile = this.sourceFile; |
| - if (sourceFile) |
| - { |
| - let [, part1, part2] = /^(.*)(\.\w+)$/.exec(sourceFile.leafName) || [null, sourceFile.leafName, ""]; |
| - |
| - sourceFile = sourceFile.clone(); |
| - sourceFile.leafName = part1 + "-backup" + (++backupIndex) + part2; |
| - |
| - IO.statFile(sourceFile, function(e, statData) |
| - { |
| - if (!e && statData.exists) |
| - readFile(sourceFile, backupIndex); |
| - else |
| - doneReading(parser); |
| - }); |
| - return; |
| - } |
| - } |
| - doneReading(parser); |
| - }.bind(this)); |
| - }.bind(this); |
| - |
| - var doneReading = function(parser) |
| - { |
| - // Old special groups might have been converted, remove them if they are empty |
| - let specialMap = {"~il~": true, "~wl~": true, "~fl~": true, "~eh~": true}; |
| - let knownSubscriptions = Object.create(null); |
| - for (let i = 0; i < parser.subscriptions.length; i++) |
| - { |
| - let 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 (let i = 0; i < parser.userFilters.length; i++) |
| - { |
| - let 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); |
| - |
| - let explicitFile; |
| - if (sourceFile) |
| - { |
| - explicitFile = true; |
| - readFile(sourceFile, 0); |
| - } |
| - else |
| - { |
| - explicitFile = false; |
| - sourceFile = FilterStorage.sourceFile; |
| - |
| - let callback = function(e, statData) |
| - { |
| - if (e || !statData.exists) |
| - { |
| - this.firstRun = true; |
| - this._loading = false; |
| - FilterNotifier.triggerListeners("load"); |
| - } |
| - else |
| - readFile(sourceFile, 0); |
| - }.bind(this); |
| - |
| - if (sourceFile) |
| - IO.statFile(sourceFile, callback); |
| - else |
| - callback(true); |
| - } |
| - }, |
| - |
| - _generateFilterData: function*(subscriptions) |
| - { |
| - yield "# Adblock Plus preferences"; |
| - yield "version=" + formatVersion; |
| - |
| - let saved = Object.create(null); |
| - let buf = []; |
| - |
| - // Save filter data |
| - for (let i = 0; i < subscriptions.length; i++) |
| - { |
| - let subscription = subscriptions[i]; |
| - for (let j = 0; j < subscription.filters.length; j++) |
| - { |
| - let filter = subscription.filters[j]; |
| - if (!(filter.text in saved)) |
| - { |
| - filter.serialize(buf); |
| - saved[filter.text] = filter; |
| - for (let k = 0; k < buf.length; k++) |
| - yield buf[k]; |
| - buf.splice(0); |
| - } |
| - } |
| - } |
| - |
| - // Save subscriptions |
| - for (let i = 0; i < subscriptions.length; i++) |
| - { |
| - let subscription = subscriptions[i]; |
| - |
| - yield ""; |
| - |
| - subscription.serialize(buf); |
| - if (subscription.filters.length) |
| - { |
| - buf.push("", "[Subscription filters]") |
| - subscription.serializeFilters(buf); |
| - } |
| - for (let k = 0; k < buf.length; k++) |
| - yield buf[k]; |
| - buf.splice(0); |
| - } |
| - }, |
| - |
| - /** |
| - * Will be set to true if saveToDisk() is running (reentrance protection). |
| - * @type Boolean |
| - */ |
| - _saving: false, |
| - |
| - /** |
| - * Will be set to true if a saveToDisk() call arrives while saveToDisk() is |
| - * already running (delayed execution). |
| - * @type Boolean |
| - */ |
| - _needsSave: false, |
| - |
| - /** |
| - * Saves all subscriptions back to disk |
| - * @param {nsIFile} [targetFile] File to be written |
| - */ |
| - saveToDisk: function(targetFile) |
| - { |
| - let explicitFile = true; |
| - if (!targetFile) |
| - { |
| - targetFile = FilterStorage.sourceFile; |
| - explicitFile = false; |
| - } |
| - if (!targetFile) |
| - return; |
| - |
| - if (!explicitFile && this._saving) |
| - { |
| - this._needsSave = true; |
| - return; |
| - } |
| - |
| - // Make sure the file's parent directory exists |
| - try { |
| - targetFile.parent.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); |
| - } catch (e) {} |
| - |
| - let writeFilters = function() |
| - { |
| - IO.writeToFile(targetFile, 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)); |
| - }.bind(this); |
| - |
| - let checkBackupRequired = function(callbackNotRequired, callbackRequired) |
| - { |
| - if (explicitFile || Prefs.patternsbackups <= 0) |
| - callbackNotRequired(); |
| - else |
| - { |
| - IO.statFile(targetFile, function(e, statData) |
| - { |
| - if (e || !statData.exists) |
| - callbackNotRequired(); |
| - else |
| - { |
| - let [, part1, part2] = /^(.*)(\.\w+)$/.exec(targetFile.leafName) || [null, targetFile.leafName, ""]; |
| - let 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); |
| - |
| - let removeLastBackup = function(part1, part2) |
| - { |
| - let file = targetFile.clone(); |
| - file.leafName = part1 + "-backup" + Prefs.patternsbackups + part2; |
| - IO.removeFile(file, (e) => renameBackup(part1, part2, Prefs.patternsbackups - 1)); |
| - }.bind(this); |
| - |
| - let renameBackup = function(part1, part2, index) |
| - { |
| - if (index > 0) |
| - { |
| - let fromFile = targetFile.clone(); |
| - fromFile.leafName = part1 + "-backup" + index + part2; |
| - |
| - let toName = part1 + "-backup" + (index + 1) + part2; |
| - |
| - IO.renameFile(fromFile, toName, (e) => renameBackup(part1, part2, index - 1)); |
| - } |
| - else |
| - { |
| - let toFile = targetFile.clone(); |
| - toFile.leafName = part1 + "-backup" + (index + 1) + part2; |
| - |
| - IO.copyFile(targetFile, toFile, writeFilters); |
| - } |
| - }.bind(this); |
| - |
| - // Do not persist external subscriptions |
| - let subscriptions = this.subscriptions.filter((s) => !(s instanceof ExternalSubscription)); |
| - if (!explicitFile) |
| - this._saving = true; |
| - |
| - checkBackupRequired(writeFilters, removeLastBackup); |
| - }, |
| - |
| - /** |
| - * Returns the list of existing backup files. |
| - */ |
| - getBackupFiles: function() /**nsIFile[]*/ |
| - { |
| - // TODO: This method should be asynchronous |
| - let result = []; |
| - |
| - let [, part1, part2] = /^(.*)(\.\w+)$/.exec(FilterStorage.sourceFile.leafName) || [null, FilterStorage.sourceFile.leafName, ""]; |
| - for (let i = 1; ; i++) |
| - { |
| - let file = FilterStorage.sourceFile.clone(); |
| - file.leafName = part1 + "-backup" + i + part2; |
| - if (file.exists()) |
| - result.push(file); |
| - else |
| - break; |
| - } |
| - return result; |
| - } |
| -}; |
| - |
| -/** |
| - * Joins subscription's filters to the subscription without any notifications. |
| - * @param {Subscription} subscription filter subscription that should be connected to its filters |
| - */ |
| -function addSubscriptionFilters(subscription) |
| -{ |
| - if (!(subscription.url in FilterStorage.knownSubscriptions)) |
| - return; |
| - |
| - for (let filter of subscription.filters) |
| - filter.subscriptions.push(subscription); |
| -} |
| - |
| -/** |
| - * Removes subscription's filters from the subscription without any notifications. |
| - * @param {Subscription} subscription filter subscription to be removed |
| - */ |
| -function removeSubscriptionFilters(subscription) |
| -{ |
| - if (!(subscription.url in FilterStorage.knownSubscriptions)) |
| - return; |
| - |
| - for (let filter of subscription.filters) |
| - { |
| - let i = filter.subscriptions.indexOf(subscription); |
| - if (i >= 0) |
| - filter.subscriptions.splice(i, 1); |
| - } |
| -} |
| - |
| -/** |
| - * IO.readFromFile() listener to parse filter data. |
| - * @constructor |
| - */ |
| -function INIParser() |
| -{ |
| - this.fileProperties = this.curObj = {}; |
| - this.subscriptions = []; |
| - this.knownFilters = Object.create(null); |
| - this.knownSubscriptions = Object.create(null); |
| -} |
| -INIParser.prototype = |
| -{ |
| - linesProcessed: 0, |
| - subscriptions: null, |
| - knownFilters: null, |
| - knownSubscriptions : null, |
| - wantObj: true, |
| - fileProperties: null, |
| - curObj: null, |
| - curSection: null, |
| - userFilters: null, |
| - |
| - process: function(val) |
| - { |
| - let origKnownFilters = Filter.knownFilters; |
| - Filter.knownFilters = this.knownFilters; |
| - let origKnownSubscriptions = Subscription.knownSubscriptions; |
| - Subscription.knownSubscriptions = this.knownSubscriptions; |
| - let 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) |
| - { |
| - // Process current object before going to next section |
| - switch (this.curSection) |
| - { |
| - case "filter": |
| - case "pattern": |
| - if ("text" in this.curObj) |
| - Filter.fromObject(this.curObj); |
| - break; |
| - case "subscription": |
| - let subscription = Subscription.fromObject(this.curObj); |
| - if (subscription) |
| - this.subscriptions.push(subscription); |
| - break; |
| - case "subscription filters": |
| - case "subscription patterns": |
| - if (this.subscriptions.length) |
| - { |
| - let subscription = this.subscriptions[this.subscriptions.length - 1]; |
| - for (let text of this.curObj) |
| - { |
| - let 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; |
| - } |
| - |
| - // Allow events to be processed every now and then. |
| - // Note: IO.readFromFile() will deal with the potential reentrance here. |
| - this.linesProcessed++; |
| - if (this.linesProcessed % 1000 == 0) |
| - Utils.yield(); |
| - } |
| -}; |