-
Notifications
You must be signed in to change notification settings - Fork 310
/
storage.js
210 lines (193 loc) · 6.08 KB
/
storage.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
/* global require, exports */
/**
* This file is part of Adguard Browser Extension (https://github.com/AdguardTeam/AdguardBrowserExtension).
*
* Adguard Browser Extension is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Adguard Browser Extension 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Adguard Browser Extension. If not, see <http://www.gnu.org/licenses/>.
*/
var Log = require('../../lib/utils/log').Log;
var FS = require('../../lib/utils/file-storage').FS;
var FilterRuleBuilder = require('../../lib/filter/rules/filter-rule-builder').FilterRuleBuilder;
/**
* This class manages file storage for filters.
*/
var FilterStorage = exports.FilterStorage = {
FILE_PATH: "filters.ini",
CSS_FILE_PATH: 'elementsHide.css',
_loading: false,
_cssSaving: false,
/**
* Saves filter rules to file
*
* @param filterId Filter identifier
* @param filterRules Filter rules
* @param callback Called when save operation is finished
*/
saveFilterRules: function (filterId, filterRules, callback) {
var filePath = FilterStorage._getFilePath(filterId);
FS.writeToFile(filePath, filterRules, function (e) {
if (e) {
Log.error("Error write filters to file {0} cause: {1}", filePath, e);
}
if (callback) {
callback();
}
});
},
/**
* Loads filter from the file storage
*
* @param filterId Filter identifier
* @param callback Called when file content has been loaded
*/
loadFilterRules: function (filterId, callback) {
var filePath = FilterStorage._getFilePath(filterId);
FS.readFromFile(filePath, function (e, rules) {
if (e) {
Log.error("Error while reading rules from file {0} cause: {1}", filePath, e);
}
callback(rules);
}.bind(this));
},
/**
* Saves CSS stylesheet to file.
*
* This method is used in Firefox extension only.
* If user has enabled "Send statistics for ad filters usage" option we change the way of applying CSS rules.
* In this case we register browser-wide stylesheet using StyleService.registerSheet.
* We should save it to file before registering the stylesheet.
*
* @param cssRules CSS file content
* @param callback Called when operation is finished
*/
saveStyleSheetToDisk: function (cssRules, callback) {
if (this._cssSaving) {
return;
}
this._cssSaving = true;
var filePath = FilterStorage.CSS_FILE_PATH;
FS.writeToFile(filePath, cssRules, function (e) {
if (e && e.error) {
Log.error("Error write css styleSheet to file {0} cause: {1}", filePath, e);
return;
} else {
callback();
}
this._cssSaving = false;
}.bind(this));
},
/**
* Gets CSS file URI
*
* This method is used in Firefox extension only.
* If user has enabled "Send statistics for ad filters usage" option we change the way of applying CSS rules.
* In this case we register browser-wide stylesheet using StyleService.registerSheet.
* We should save it to file before registering the stylesheet.
*
* @returns CSS file URI
*/
getInjectCssFileURI: function () {
if (!this.injectCssUrl) {
this.injectCssUrl = FS.getFileInAdguardDirUri(this.CSS_FILE_PATH);
}
return this.injectCssUrl;
},
_getFilePath: function (filterId) {
return "filterrules_" + filterId + ".txt";
}
};
/**
* Parser for filter files
*
* @constructor
*/
var FilterParser = function () {
this.currentSection = null;
this.currentFilter = null;
this.currentRules = null;
this.antiBannerFilters = [];
};
FilterParser.Sections = {
FILTER_START: "[FILTER]",
FILTER_END: "[/FILTER]",
RULES_START: "[RULES]",
RULES_END: "[/RULES]"
};
/**
* Parses filter metadata
* @param obj
* @returns {{filterId: number}}
*/
FilterParser.fromObject = function (obj) {
var antiBannerFilter = {
filterId: obj.filterId - 0
};
antiBannerFilter.version = "0.0.0.0";
if ("version" in obj) {
antiBannerFilter.version = obj.version;
}
if ("lastUpdateTime" in obj) {
antiBannerFilter.lastUpdateTime = obj.lastUpdateTime - 0;
}
if ("lastCheckTime" in obj) {
antiBannerFilter.lastCheckTime = obj.lastCheckTime - 0;
}
antiBannerFilter.disabled = (obj.disabled == "true");
return antiBannerFilter;
};
FilterParser.prototype = {
process: function (line) {
switch (line) {
case FilterParser.Sections.FILTER_START:
this.currentFilter = Object.create(null);
this.currentSection = FilterParser.Sections.FILTER_START;
break;
case FilterParser.Sections.RULES_START:
this.currentRules = [];
this.currentSection = FilterParser.Sections.RULES_START;
break;
case FilterParser.Sections.FILTER_END:
if (this.currentFilter) {
var antiBannerFilter = FilterParser.fromObject(this.currentFilter);
if (antiBannerFilter !== null) {
antiBannerFilter.filterRules = this.currentRules;
this.antiBannerFilters.push(antiBannerFilter);
}
}
this.currentFilter = null;
this.currentRules = null;
this.currentSection = null;
break;
case FilterParser.Sections.RULES_END:
//do nothing
break;
default :
switch (this.currentSection) {
case FilterParser.Sections.FILTER_START:
if (line && this.currentFilter) {
var match = /^(\w+)=(.*)$/.exec(line);
this.currentFilter[match[1]] = match[2];
}
break;
case FilterParser.Sections.RULES_START:
if (line && this.currentRules) {
var rule = FilterRuleBuilder.createRule(line, this.currentFilter.filterId - 0);
if (rule !== null) {
this.currentRules.push(rule);
}
}
break;
}
}
}
};