| Left: | ||
| Right: |
| OLD | NEW |
|---|---|
| 1 /* This Source Code Form is subject to the terms of the Mozilla Public | 1 /* This Source Code Form is subject to the terms of the Mozilla Public |
| 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file, | 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
| 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ | 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| 4 | 4 |
| 5 Cu.import("resource://gre/modules/Services.jsm"); | 5 Cu.import("resource://gre/modules/Services.jsm"); |
| 6 Cu.import("resource://gre/modules/FileUtils.jsm"); | 6 Cu.import("resource://gre/modules/FileUtils.jsm"); |
| 7 | 7 |
| 8 let {Prefs} = require("prefs"); | 8 let {Prefs} = require("prefs"); |
| 9 | 9 |
| 10 let RULES_VERSION = 2; | 10 let RULES_VERSION = 2; |
| 11 | 11 |
| 12 let CUSTOM_RULE_PRIORITY = 0x7FFFFFFF; | |
| 13 | |
| 12 let rules = {expressions: []}; | 14 let rules = {expressions: []}; |
| 13 | 15 |
| 14 loadRules(); | 16 loadRules(); |
| 15 | 17 |
| 16 // Make first attempt to update rules after five minutes | 18 // Make first attempt to update rules after five minutes |
| 17 let updateTimer = null; | 19 let updateTimer = null; |
| 18 updateTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); | 20 updateTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); |
| 19 updateTimer.initWithCallback(onTimer, 1000 * 60 * 5, Ci.nsITimer.TYPE_REPEATING_ SLACK); | 21 updateTimer.initWithCallback(onTimer, 1000 * 60 * 5, Ci.nsITimer.TYPE_REPEATING_ SLACK); |
| 20 onShutdown.add(function() updateTimer.cancel()); | 22 onShutdown.add(function() updateTimer.cancel()); |
| 21 | 23 |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 39 request.addEventListener("load", function() | 41 request.addEventListener("load", function() |
| 40 { | 42 { |
| 41 try | 43 try |
| 42 { | 44 { |
| 43 // Remove comments from the file if any | 45 // Remove comments from the file if any |
| 44 let data = JSON.parse(request.responseText.replace(/^\s*\/\/.*/mg, "")); | 46 let data = JSON.parse(request.responseText.replace(/^\s*\/\/.*/mg, "")); |
| 45 if (ignoreVersion || data.version == RULES_VERSION) | 47 if (ignoreVersion || data.version == RULES_VERSION) |
| 46 { | 48 { |
| 47 rules = data; | 49 rules = data; |
| 48 callback(true); | 50 callback(true); |
| 51 | |
| 52 // Add user-defined rules after calling the callback - if the callback | |
| 53 // saves the rules then the custom rules won't be included. | |
| 54 addCustomRules(); | |
| 49 } | 55 } |
| 50 else | 56 else |
| 51 callback(false); | 57 callback(false); |
| 52 } | 58 } |
| 53 catch (e) | 59 catch (e) |
| 54 { | 60 { |
| 55 Cu.reportError(e); | 61 Cu.reportError(e); |
| 56 callback(false); | 62 callback(false); |
| 57 } | 63 } |
| 58 }, false); | 64 }, false); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 74 } | 80 } |
| 75 | 81 |
| 76 function getRuleFile() | 82 function getRuleFile() |
| 77 { | 83 { |
| 78 let result = FileUtils.getFile("ProfD", ["url-fixer-rules.json"]); | 84 let result = FileUtils.getFile("ProfD", ["url-fixer-rules.json"]); |
| 79 | 85 |
| 80 getRuleFile = function() result; | 86 getRuleFile = function() result; |
| 81 return getRuleFile(); | 87 return getRuleFile(); |
| 82 } | 88 } |
| 83 | 89 |
| 90 function addCustomRules() | |
| 91 { | |
| 92 for (let domain in Prefs.whitelist) | |
| 93 onWhitelistEntryAdded(domain); | |
| 94 } | |
| 95 | |
| 96 function onWhitelistEntryAdded(domain) | |
| 97 { | |
| 98 let reverse = Array.prototype.slice.call(domain).reverse().join(""); | |
|
Thomas Greiner
2012/09/26 15:59:35
also in onWhitelistEntryAdded function
| |
| 99 addSuffix(rules.domain, reverse, CUSTOM_RULE_PRIORITY); | |
| 100 } | |
| 101 exports.onWhitelistEntryAdded = onWhitelistEntryAdded; | |
| 102 | |
| 103 function onWhitelistEntryRemoved(domain) | |
| 104 { | |
| 105 let reverse = Array.prototype.slice.call(domain).reverse().join(""); | |
|
Thomas Greiner
2012/09/26 15:49:13
It looks less confusing if you do it this way:
le
Wladimir Palant
2012/09/27 14:55:06
domain is a string - string.slice() returns anothe
| |
| 106 removeSuffix(rules.domain, reverse, CUSTOM_RULE_PRIORITY); | |
| 107 } | |
| 108 exports.onWhitelistEntryRemoved = onWhitelistEntryRemoved; | |
| 109 | |
| 110 function addSuffix(tree, suffix, priority) | |
| 111 { | |
| 112 if (suffix.length == 0) | |
| 113 { | |
| 114 // We are at the last character, just put our priority here | |
| 115 tree[""] = " " + priority; | |
| 116 return; | |
| 117 } | |
| 118 | |
| 119 let c = suffix[0]; | |
| 120 if (c in tree) | |
| 121 { | |
| 122 let existing = tree[c]; | |
| 123 if (typeof existing == "string") | |
| 124 { | |
| 125 // Single choice for this suffix, maybe the same entry? | |
| 126 if (existing.substr(0, suffix.length - 1) == suffix.substr(1) && existing[ suffix.length - 1] == " ") | |
| 127 { | |
| 128 // Same entry, simply replace it by new priority | |
| 129 tree[c] = suffix.substr(1) + " " + priority; | |
| 130 } | |
| 131 else | |
| 132 { | |
| 133 // Different entry, need to add a new branching point and go deeper | |
| 134 if (existing[0] == " ") | |
| 135 tree[c] = {"": existing}; | |
| 136 else | |
| 137 { | |
| 138 tree[c] = {}; | |
| 139 tree[c][existing[0]] = existing.substr(1); | |
| 140 } | |
| 141 addSuffix(tree[c], suffix.substr(1), priority); | |
| 142 } | |
| 143 } | |
| 144 else | |
| 145 { | |
| 146 // Multiple choices for this suffix - go deeper | |
| 147 addSuffix(existing, suffix.substr(1), priority); | |
| 148 } | |
| 149 } | |
| 150 else | |
| 151 { | |
| 152 // No existing entry yet, just add ours | |
| 153 tree[c] = suffix.substr(1) + " " + priority; | |
| 154 } | |
| 155 } | |
| 156 | |
| 157 function removeSuffix(tree, suffix, priority) | |
| 158 { | |
| 159 if (suffix.length == 0) | |
| 160 { | |
| 161 // We are at the last character, check whether there is an entry with | |
| 162 // matching priority | |
| 163 if ("" in tree && tree[""] == " " + priority) | |
| 164 delete tree[""]; | |
| 165 return; | |
| 166 } | |
| 167 | |
| 168 let c = suffix[0]; | |
| 169 if (!(c in tree)) | |
| 170 return; | |
| 171 | |
| 172 if (typeof tree[c] == "string") | |
| 173 { | |
| 174 // Single entry - check whether it is the right one | |
| 175 if (tree[c] == suffix.substr(1) + " " + priority) | |
| 176 delete tree[c]; | |
| 177 } | |
| 178 else | |
| 179 { | |
| 180 // Multiple entries, need to go deeper | |
| 181 removeSuffix(tree[c], suffix.substr(1), priority); | |
| 182 } | |
| 183 } | |
| 184 | |
| 84 function onTimer() | 185 function onTimer() |
| 85 { | 186 { |
| 86 // Next check in 1 hour | 187 // Next check in 1 hour |
| 87 updateTimer.delay = 1000 * 60 * 60; | 188 updateTimer.delay = 1000 * 60 * 60; |
| 88 | 189 |
| 89 // Only download rules every three days | 190 // Only download rules every three days |
| 90 let nextUpdate = Prefs.lastRuleUpdate + 60 * 60 * 24 * 3; | 191 let nextUpdate = Prefs.lastRuleUpdate + 60 * 60 * 24 * 3; |
| 91 if (nextUpdate > Date.now() / 1000) | 192 if (nextUpdate > Date.now() / 1000) |
| 92 return; | 193 return; |
| 93 | 194 |
| 94 loadRulesFrom("http://urlfixer.org/download/rules.json?version=" + RULES_VERSI ON, false, function(success) | 195 loadRulesFrom("http://urlfixer.org/download/rules.json?version=" + RULES_VERSI ON, false, function(success) |
| 95 { | 196 { |
| 96 if (success) | 197 if (success) |
| 97 { | 198 { |
| 98 rules.timestamp = Date.now(); | 199 rules.timestamp = Date.now(); |
| 99 | 200 |
| 100 var dynRules = require("updateRules").updateRules(); | |
| 101 for(var i in dynRules) | |
| 102 { | |
| 103 rules[i] = dynRules[i]; | |
| 104 } | |
| 105 | |
| 106 try | 201 try |
| 107 { | 202 { |
| 108 // Save the rules to file. | 203 // Save the rules to file. |
| 109 let rulesText = JSON.stringify(rules); | 204 let rulesText = JSON.stringify(rules); |
| 110 let fileStream = FileUtils.openSafeFileOutputStream(getRuleFile()); | 205 let fileStream = FileUtils.openSafeFileOutputStream(getRuleFile()); |
| 111 let stream = Cc["@mozilla.org/intl/converter-output-stream;1"].createIns tance(Ci.nsIConverterOutputStream); | 206 let stream = Cc["@mozilla.org/intl/converter-output-stream;1"].createIns tance(Ci.nsIConverterOutputStream); |
| 112 stream.init(fileStream, "UTF-8", 16384, Ci.nsIConverterInputStream.DEFAU LT_REPLACEMENT_CHARACTER); | 207 stream.init(fileStream, "UTF-8", 16384, Ci.nsIConverterInputStream.DEFAU LT_REPLACEMENT_CHARACTER); |
| 113 stream.writeString(rulesText); | 208 stream.writeString(rulesText); |
| 114 stream.flush(); | 209 stream.flush(); |
| 115 FileUtils.closeSafeFileOutputStream(fileStream); | 210 FileUtils.closeSafeFileOutputStream(fileStream); |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 143 let customRules = Prefs.custom_replace; | 238 let customRules = Prefs.custom_replace; |
| 144 for (let searchString in customRules) | 239 for (let searchString in customRules) |
| 145 { | 240 { |
| 146 let replacement = customRules[searchString]; | 241 let replacement = customRules[searchString]; |
| 147 searchString = searchString.toLowerCase(); | 242 searchString = searchString.toLowerCase(); |
| 148 if (/^re:+/.test(searchString)) | 243 if (/^re:+/.test(searchString)) |
| 149 domain = domain.replace(new RegExp(RegExp.rightContext, "g"), replacement) ; | 244 domain = domain.replace(new RegExp(RegExp.rightContext, "g"), replacement) ; |
| 150 else | 245 else |
| 151 domain = domain.replace(searchString, replacement); | 246 domain = domain.replace(searchString, replacement); |
| 152 } | 247 } |
| 153 | |
| 154 // Apply user's whitelist | |
| 155 let whitelist = Prefs.whitelist; | |
| 156 if (whitelist.hasOwnProperty(domain) || /^www\./.test(domain) && whitelist.has OwnProperty(domain.substr(4))) | |
| 157 { | |
| 158 return domain; | |
| 159 } | |
| 160 | 248 |
| 161 // Now apply our rules on the domain name | 249 // Now apply our rules on the domain name |
| 162 for (let i = 0, l = rules.expressions.length; i < l; i++) | 250 for (let i = 0, l = rules.expressions.length; i < l; i++) |
| 163 domain = applyExpression(domain, rules.expressions[i]); | 251 domain = applyExpression(domain, rules.expressions[i]); |
| 164 | 252 |
| 165 // Find similar known domains, test domains without the www. prefix | 253 // Find similar known domains, test domains without the www. prefix |
| 166 if (domain.substr(0, 4) == "www.") | 254 if (domain.substr(0, 4) == "www.") |
| 167 domain = "www." + getBestMatch(domain.substr(4), rules.domain, 1, "."); | 255 domain = "www." + getBestMatch(domain.substr(4), rules.domain, 1, "."); |
| 168 else | 256 else |
| 169 domain = getBestMatch(domain, rules.domain, 1, "."); | 257 domain = getBestMatch(domain, rules.domain, 1, "."); |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 312 bestSuggestionDistance = distance; | 400 bestSuggestionDistance = distance; |
| 313 bestSuggestionMatched = matchedLen; | 401 bestSuggestionMatched = matchedLen; |
| 314 bestSuggestionPriority = priority; | 402 bestSuggestionPriority = priority; |
| 315 } | 403 } |
| 316 } | 404 } |
| 317 if (bestSuggestion) | 405 if (bestSuggestion) |
| 318 return input.substr(0, input.length - bestSuggestionMatched) + bestSuggestio n; | 406 return input.substr(0, input.length - bestSuggestionMatched) + bestSuggestio n; |
| 319 else | 407 else |
| 320 return input; | 408 return input; |
| 321 } | 409 } |
| OLD | NEW |