| 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 = domain.split("").reverse().join(""); | 
 |   99   addSuffix(rules.domain, reverse, CUSTOM_RULE_PRIORITY); | 
 |  100 } | 
 |  101 exports.onWhitelistEntryAdded = onWhitelistEntryAdded; | 
 |  102  | 
 |  103 function onWhitelistEntryRemoved(domain) | 
 |  104 { | 
 |  105   let reverse = domain.split("").reverse().join(""); | 
 |  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 |