| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 /* |  | 
| 2  * This file is part of the Adblock Plus extension, |  | 
| 3  * Copyright (C) 2006-2012 Eyeo GmbH |  | 
| 4  * |  | 
| 5  * Adblock Plus is free software: you can redistribute it and/or modify |  | 
| 6  * it under the terms of the GNU General Public License version 3 as |  | 
| 7  * published by the Free Software Foundation. |  | 
| 8  * |  | 
| 9  * Adblock Plus is distributed in the hope that it will be useful, |  | 
| 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of |  | 
| 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | 
| 12  * GNU General Public License for more details. |  | 
| 13  * |  | 
| 14  * You should have received a copy of the GNU General Public License |  | 
| 15  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. |  | 
| 16  */ |  | 
| 17 |  | 
| 18 // |  | 
| 19 // This file has been generated automatically from Adblock Plus for Firefox |  | 
| 20 // source code. DO NOT MODIFY, change the original source code instead. |  | 
| 21 // |  | 
| 22 // Relevant repositories: |  | 
| 23 // * https://hg.adblockplus.org/adblockplus/ |  | 
| 24 // * https://hg.adblockplus.org/jshydra/ |  | 
| 25 // |  | 
| 26 |  | 
| 27 require.scopes["filterNotifier"] = (function() |  | 
| 28 { |  | 
| 29   var exports = {}; |  | 
| 30   var listeners = []; |  | 
| 31   var FilterNotifier = exports.FilterNotifier = |  | 
| 32   { |  | 
| 33     addListener: function(listener) |  | 
| 34     { |  | 
| 35       if (listeners.indexOf(listener) >= 0) |  | 
| 36       { |  | 
| 37         return; |  | 
| 38       } |  | 
| 39       listeners.push(listener); |  | 
| 40     }, |  | 
| 41     removeListener: function(listener) |  | 
| 42     { |  | 
| 43       var index = listeners.indexOf(listener); |  | 
| 44       if (index >= 0) |  | 
| 45       { |  | 
| 46         listeners.splice(index, 1); |  | 
| 47       } |  | 
| 48     }, |  | 
| 49     triggerListeners: function(action, item, param1, param2, param3) |  | 
| 50     { |  | 
| 51       for (var _loopIndex0 = 0; _loopIndex0 < listeners.length; ++_loopIndex0) |  | 
| 52       { |  | 
| 53         var listener = listeners[_loopIndex0]; |  | 
| 54         listener(action, item, param1, param2, param3); |  | 
| 55       } |  | 
| 56     } |  | 
| 57   }; |  | 
| 58   return exports; |  | 
| 59 })(); |  | 
| 60 require.scopes["filterClasses"] = (function() |  | 
| 61 { |  | 
| 62   var exports = {}; |  | 
| 63   var FilterNotifier = require("filterNotifier").FilterNotifier; |  | 
| 64 |  | 
| 65   function Filter(text) |  | 
| 66   { |  | 
| 67     this.text = text; |  | 
| 68     this.subscriptions = []; |  | 
| 69   } |  | 
| 70   exports.Filter = Filter; |  | 
| 71   Filter.prototype = |  | 
| 72   { |  | 
| 73     text: null, |  | 
| 74     subscriptions: null, |  | 
| 75     serialize: function(buffer) |  | 
| 76     { |  | 
| 77       buffer.push("[Filter]"); |  | 
| 78       buffer.push("text=" + this.text); |  | 
| 79     }, |  | 
| 80     toString: function() |  | 
| 81     { |  | 
| 82       return this.text; |  | 
| 83     } |  | 
| 84   }; |  | 
| 85   Filter.knownFilters = |  | 
| 86   { |  | 
| 87     __proto__: null |  | 
| 88   }; |  | 
| 89   Filter.elemhideRegExp = /^([^\/\*\|\@"!]*?)#(\@)?(?:([\w\-]+|\*)((?:\([\w\-]+(
      ?:[$^*]?=[^\(\)"]*)?\))*)|#([^{}]+))$/; |  | 
| 90   Filter.regexpRegExp = /^(@@)?\/.*\/(?:\$~?[\w\-]+(?:=[^,\s]+)?(?:,~?[\w\-]+(?:
      =[^,\s]+)?)*)?$/; |  | 
| 91   Filter.optionsRegExp = /\$(~?[\w\-]+(?:=[^,\s]+)?(?:,~?[\w\-]+(?:=[^,\s]+)?)*)
      $/; |  | 
| 92   Filter.fromText = function(text) |  | 
| 93   { |  | 
| 94     if (text in Filter.knownFilters) |  | 
| 95     { |  | 
| 96       return Filter.knownFilters[text]; |  | 
| 97     } |  | 
| 98     var ret; |  | 
| 99     var match = text.indexOf("#") >= 0 ? Filter.elemhideRegExp.exec(text) : null
      ; |  | 
| 100     if (match) |  | 
| 101     { |  | 
| 102       ret = ElemHideBase.fromText(text, match[1], match[2], match[3], match[4], 
      match[5]); |  | 
| 103     } |  | 
| 104     else if (text[0] == "!") |  | 
| 105     { |  | 
| 106       ret = new CommentFilter(text); |  | 
| 107     } |  | 
| 108     else |  | 
| 109     { |  | 
| 110       ret = RegExpFilter.fromText(text); |  | 
| 111     } |  | 
| 112     Filter.knownFilters[ret.text] = ret; |  | 
| 113     return ret; |  | 
| 114   }; |  | 
| 115   Filter.fromObject = function(obj) |  | 
| 116   { |  | 
| 117     var ret = Filter.fromText(obj.text); |  | 
| 118     if (ret instanceof ActiveFilter) |  | 
| 119     { |  | 
| 120       if ("disabled" in obj) |  | 
| 121       { |  | 
| 122         ret._disabled = obj.disabled == "true"; |  | 
| 123       } |  | 
| 124       if ("hitCount" in obj) |  | 
| 125       { |  | 
| 126         ret._hitCount = parseInt(obj.hitCount) || 0; |  | 
| 127       } |  | 
| 128       if ("lastHit" in obj) |  | 
| 129       { |  | 
| 130         ret._lastHit = parseInt(obj.lastHit) || 0; |  | 
| 131       } |  | 
| 132     } |  | 
| 133     return ret; |  | 
| 134   }; |  | 
| 135   Filter.normalize = function(text) |  | 
| 136   { |  | 
| 137     if (!text) |  | 
| 138     { |  | 
| 139       return text; |  | 
| 140     } |  | 
| 141     text = text.replace(/[^\S ]/g, ""); |  | 
| 142     if (/^\s*!/.test(text)) |  | 
| 143     { |  | 
| 144       return text.replace(/^\s+/, "").replace(/\s+$/, ""); |  | 
| 145     } |  | 
| 146     else if (Filter.elemhideRegExp.test(text)) |  | 
| 147     { |  | 
| 148       var _tempVar1 = /^(.*?)(#\@?#?)(.*)$/.exec(text); |  | 
| 149       var domain = _tempVar1[1]; |  | 
| 150       var separator = _tempVar1[2]; |  | 
| 151       var selector = _tempVar1[3]; |  | 
| 152       return domain.replace(/\s/g, "") + separator + selector.replace(/^\s+/, ""
      ).replace(/\s+$/, ""); |  | 
| 153     } |  | 
| 154     else |  | 
| 155     { |  | 
| 156       return text.replace(/\s/g, ""); |  | 
| 157     } |  | 
| 158   }; |  | 
| 159 |  | 
| 160   function InvalidFilter(text, reason) |  | 
| 161   { |  | 
| 162     Filter.call(this, text); |  | 
| 163     this.reason = reason; |  | 
| 164   } |  | 
| 165   exports.InvalidFilter = InvalidFilter; |  | 
| 166   InvalidFilter.prototype = |  | 
| 167   { |  | 
| 168     __proto__: Filter.prototype, |  | 
| 169     reason: null, |  | 
| 170     serialize: function(buffer){} |  | 
| 171   }; |  | 
| 172 |  | 
| 173   function CommentFilter(text) |  | 
| 174   { |  | 
| 175     Filter.call(this, text); |  | 
| 176   } |  | 
| 177   exports.CommentFilter = CommentFilter; |  | 
| 178   CommentFilter.prototype = |  | 
| 179   { |  | 
| 180     __proto__: Filter.prototype, |  | 
| 181     serialize: function(buffer){} |  | 
| 182   }; |  | 
| 183 |  | 
| 184   function ActiveFilter(text, domains) |  | 
| 185   { |  | 
| 186     Filter.call(this, text); |  | 
| 187     this.domainSource = domains; |  | 
| 188   } |  | 
| 189   exports.ActiveFilter = ActiveFilter; |  | 
| 190   ActiveFilter.prototype = |  | 
| 191   { |  | 
| 192     __proto__: Filter.prototype, |  | 
| 193     _disabled: false, |  | 
| 194     _hitCount: 0, |  | 
| 195     _lastHit: 0, |  | 
| 196     get disabled() |  | 
| 197     { |  | 
| 198       return this._disabled; |  | 
| 199     }, |  | 
| 200     set disabled(value) |  | 
| 201     { |  | 
| 202       if (value != this._disabled) |  | 
| 203       { |  | 
| 204         var oldValue = this._disabled; |  | 
| 205         this._disabled = value; |  | 
| 206         FilterNotifier.triggerListeners("filter.disabled", this, value, oldValue
      ); |  | 
| 207       } |  | 
| 208       return this._disabled; |  | 
| 209     }, |  | 
| 210     get hitCount() |  | 
| 211     { |  | 
| 212       return this._hitCount; |  | 
| 213     }, |  | 
| 214     set hitCount(value) |  | 
| 215     { |  | 
| 216       if (value != this._hitCount) |  | 
| 217       { |  | 
| 218         var oldValue = this._hitCount; |  | 
| 219         this._hitCount = value; |  | 
| 220         FilterNotifier.triggerListeners("filter.hitCount", this, value, oldValue
      ); |  | 
| 221       } |  | 
| 222       return this._hitCount; |  | 
| 223     }, |  | 
| 224     get lastHit() |  | 
| 225     { |  | 
| 226       return this._lastHit; |  | 
| 227     }, |  | 
| 228     set lastHit(value) |  | 
| 229     { |  | 
| 230       if (value != this._lastHit) |  | 
| 231       { |  | 
| 232         var oldValue = this._lastHit; |  | 
| 233         this._lastHit = value; |  | 
| 234         FilterNotifier.triggerListeners("filter.lastHit", this, value, oldValue)
      ; |  | 
| 235       } |  | 
| 236       return this._lastHit; |  | 
| 237     }, |  | 
| 238     domainSource: null, |  | 
| 239     domainSeparator: null, |  | 
| 240     ignoreTrailingDot: true, |  | 
| 241     get domains() |  | 
| 242     { |  | 
| 243       var domains = null; |  | 
| 244       if (this.domainSource) |  | 
| 245       { |  | 
| 246         var list = this.domainSource.split(this.domainSeparator); |  | 
| 247         if (list.length == 1 && list[0][0] != "~") |  | 
| 248         { |  | 
| 249           domains = |  | 
| 250           { |  | 
| 251             __proto__: null, |  | 
| 252             "": false |  | 
| 253           }; |  | 
| 254           if (this.ignoreTrailingDot) |  | 
| 255           { |  | 
| 256             list[0] = list[0].replace(/\.+$/, ""); |  | 
| 257           } |  | 
| 258           domains[list[0]] = true; |  | 
| 259         } |  | 
| 260         else |  | 
| 261         { |  | 
| 262           var hasIncludes = false; |  | 
| 263           for (var i = 0; i < list.length; i++) |  | 
| 264           { |  | 
| 265             var domain = list[i]; |  | 
| 266             if (this.ignoreTrailingDot) |  | 
| 267             { |  | 
| 268               domain = domain.replace(/\.+$/, ""); |  | 
| 269             } |  | 
| 270             if (domain == "") |  | 
| 271             { |  | 
| 272               continue; |  | 
| 273             } |  | 
| 274             var include; |  | 
| 275             if (domain[0] == "~") |  | 
| 276             { |  | 
| 277               include = false; |  | 
| 278               domain = domain.substr(1); |  | 
| 279             } |  | 
| 280             else |  | 
| 281             { |  | 
| 282               include = true; |  | 
| 283               hasIncludes = true; |  | 
| 284             } |  | 
| 285             if (!domains) |  | 
| 286             { |  | 
| 287               domains = |  | 
| 288               { |  | 
| 289                 __proto__: null |  | 
| 290               }; |  | 
| 291             } |  | 
| 292             domains[domain] = include; |  | 
| 293           } |  | 
| 294           domains[""] = !hasIncludes; |  | 
| 295         } |  | 
| 296         delete this.domainSource; |  | 
| 297       } |  | 
| 298       this.__defineGetter__("domains", function() |  | 
| 299       { |  | 
| 300         return domains; |  | 
| 301       }); |  | 
| 302       return this.domains; |  | 
| 303     }, |  | 
| 304     isActiveOnDomain: function(docDomain) |  | 
| 305     { |  | 
| 306       if (!this.domains) |  | 
| 307       { |  | 
| 308         return true; |  | 
| 309       } |  | 
| 310       if (!docDomain) |  | 
| 311       { |  | 
| 312         return this.domains[""]; |  | 
| 313       } |  | 
| 314       if (this.ignoreTrailingDot) |  | 
| 315       { |  | 
| 316         docDomain = docDomain.replace(/\.+$/, ""); |  | 
| 317       } |  | 
| 318       docDomain = docDomain.toUpperCase(); |  | 
| 319       while (true) |  | 
| 320       { |  | 
| 321         if (docDomain in this.domains) |  | 
| 322         { |  | 
| 323           return this.domains[docDomain]; |  | 
| 324         } |  | 
| 325         var nextDot = docDomain.indexOf("."); |  | 
| 326         if (nextDot < 0) |  | 
| 327         { |  | 
| 328           break; |  | 
| 329         } |  | 
| 330         docDomain = docDomain.substr(nextDot + 1); |  | 
| 331       } |  | 
| 332       return this.domains[""]; |  | 
| 333     }, |  | 
| 334     isActiveOnlyOnDomain: function(docDomain) |  | 
| 335     { |  | 
| 336       if (!docDomain || !this.domains || this.domains[""]) |  | 
| 337       { |  | 
| 338         return false; |  | 
| 339       } |  | 
| 340       if (this.ignoreTrailingDot) |  | 
| 341       { |  | 
| 342         docDomain = docDomain.replace(/\.+$/, ""); |  | 
| 343       } |  | 
| 344       docDomain = docDomain.toUpperCase(); |  | 
| 345       for (var domain in this.domains) |  | 
| 346       { |  | 
| 347         if (this.domains[domain] && domain != docDomain && (domain.length <= doc
      Domain.length || domain.indexOf("." + docDomain) != domain.length - docDomain.le
      ngth - 1)) |  | 
| 348         { |  | 
| 349           return false; |  | 
| 350         } |  | 
| 351       } |  | 
| 352       return true; |  | 
| 353     }, |  | 
| 354     serialize: function(buffer) |  | 
| 355     { |  | 
| 356       if (this._disabled || this._hitCount || this._lastHit) |  | 
| 357       { |  | 
| 358         Filter.prototype.serialize.call(this, buffer); |  | 
| 359         if (this._disabled) |  | 
| 360         { |  | 
| 361           buffer.push("disabled=true"); |  | 
| 362         } |  | 
| 363         if (this._hitCount) |  | 
| 364         { |  | 
| 365           buffer.push("hitCount=" + this._hitCount); |  | 
| 366         } |  | 
| 367         if (this._lastHit) |  | 
| 368         { |  | 
| 369           buffer.push("lastHit=" + this._lastHit); |  | 
| 370         } |  | 
| 371       } |  | 
| 372     } |  | 
| 373   }; |  | 
| 374 |  | 
| 375   function RegExpFilter(text, regexpSource, contentType, matchCase, domains, thi
      rdParty) |  | 
| 376   { |  | 
| 377     ActiveFilter.call(this, text, domains); |  | 
| 378     if (contentType != null) |  | 
| 379     { |  | 
| 380       this.contentType = contentType; |  | 
| 381     } |  | 
| 382     if (matchCase) |  | 
| 383     { |  | 
| 384       this.matchCase = matchCase; |  | 
| 385     } |  | 
| 386     if (thirdParty != null) |  | 
| 387     { |  | 
| 388       this.thirdParty = thirdParty; |  | 
| 389     } |  | 
| 390     if (regexpSource.length >= 2 && regexpSource[0] == "/" && regexpSource[regex
      pSource.length - 1] == "/") |  | 
| 391     { |  | 
| 392       var regexp = new RegExp(regexpSource.substr(1, regexpSource.length - 2), t
      his.matchCase ? "" : "i"); |  | 
| 393       this.__defineGetter__("regexp", function() |  | 
| 394       { |  | 
| 395         return regexp; |  | 
| 396       }); |  | 
| 397     } |  | 
| 398     else |  | 
| 399     { |  | 
| 400       this.regexpSource = regexpSource; |  | 
| 401     } |  | 
| 402   } |  | 
| 403   exports.RegExpFilter = RegExpFilter; |  | 
| 404   RegExpFilter.prototype = |  | 
| 405   { |  | 
| 406     __proto__: ActiveFilter.prototype, |  | 
| 407     length: 1, |  | 
| 408     domainSeparator: "|", |  | 
| 409     regexpSource: null, |  | 
| 410     get regexp() |  | 
| 411     { |  | 
| 412       var source = this.regexpSource.replace(/\*+/g, "*"); |  | 
| 413       if (source[0] == "*") |  | 
| 414       { |  | 
| 415         source = source.substr(1); |  | 
| 416       } |  | 
| 417       var pos = source.length - 1; |  | 
| 418       if (pos >= 0 && source[pos] == "*") |  | 
| 419       { |  | 
| 420         source = source.substr(0, pos); |  | 
| 421       } |  | 
| 422       source = source.replace(/\^\|$/, "^").replace(/\W/g, "\\$&").replace(/\\\*
      /g, ".*").replace(/\\\^/g, "(?:[\\x00-\\x24\\x26-\\x2C\\x2F\\x3A-\\x40\\x5B-\\x5
      E\\x60\\x7B-\\x80]|$)").replace(/^\\\|\\\|/, "^[\\w\\-]+:\\/+(?!\\/)(?:[^.\\/]+\
      \.)*?").replace(/^\\\|/, "^").replace(/\\\|$/, "$"); |  | 
| 423       var regexp = new RegExp(source, this.matchCase ? "" : "i"); |  | 
| 424       delete this.regexpSource; |  | 
| 425       this.__defineGetter__("regexp", function() |  | 
| 426       { |  | 
| 427         return regexp; |  | 
| 428       }); |  | 
| 429       return this.regexp; |  | 
| 430     }, |  | 
| 431     contentType: 2147483647, |  | 
| 432     matchCase: false, |  | 
| 433     thirdParty: null, |  | 
| 434     matches: function(location, contentType, docDomain, thirdParty) |  | 
| 435     { |  | 
| 436       if (this.regexp.test(location) && (RegExpFilter.typeMap[contentType] & thi
      s.contentType) != 0 && (this.thirdParty == null || this.thirdParty == thirdParty
      ) && this.isActiveOnDomain(docDomain)) |  | 
| 437       { |  | 
| 438         return true; |  | 
| 439       } |  | 
| 440       return false; |  | 
| 441     } |  | 
| 442   }; |  | 
| 443   RegExpFilter.prototype.__defineGetter__("0", function() |  | 
| 444   { |  | 
| 445     return this; |  | 
| 446   }); |  | 
| 447   RegExpFilter.fromText = function(text) |  | 
| 448   { |  | 
| 449     var blocking = true; |  | 
| 450     var origText = text; |  | 
| 451     if (text.indexOf("@@") == 0) |  | 
| 452     { |  | 
| 453       blocking = false; |  | 
| 454       text = text.substr(2); |  | 
| 455     } |  | 
| 456     var contentType = null; |  | 
| 457     var matchCase = null; |  | 
| 458     var domains = null; |  | 
| 459     var siteKeys = null; |  | 
| 460     var thirdParty = null; |  | 
| 461     var collapse = null; |  | 
| 462     var options; |  | 
| 463     var match = text.indexOf("$") >= 0 ? Filter.optionsRegExp.exec(text) : null; |  | 
| 464     if (match) |  | 
| 465     { |  | 
| 466       options = match[1].toUpperCase().split(","); |  | 
| 467       text = match.input.substr(0, match.index); |  | 
| 468       for (var _loopIndex2 = 0; _loopIndex2 < options.length; ++_loopIndex2) |  | 
| 469       { |  | 
| 470         var option = options[_loopIndex2]; |  | 
| 471         var value = null; |  | 
| 472         var separatorIndex = option.indexOf("="); |  | 
| 473         if (separatorIndex >= 0) |  | 
| 474         { |  | 
| 475           value = option.substr(separatorIndex + 1); |  | 
| 476           option = option.substr(0, separatorIndex); |  | 
| 477         } |  | 
| 478         option = option.replace(/-/, "_"); |  | 
| 479         if (option in RegExpFilter.typeMap) |  | 
| 480         { |  | 
| 481           if (contentType == null) |  | 
| 482           { |  | 
| 483             contentType = 0; |  | 
| 484           } |  | 
| 485           contentType |= RegExpFilter.typeMap[option]; |  | 
| 486         } |  | 
| 487         else if (option[0] == "~" && option.substr(1) in RegExpFilter.typeMap) |  | 
| 488         { |  | 
| 489           if (contentType == null) |  | 
| 490           { |  | 
| 491             contentType = RegExpFilter.prototype.contentType; |  | 
| 492           } |  | 
| 493           contentType &= ~RegExpFilter.typeMap[option.substr(1)]; |  | 
| 494         } |  | 
| 495         else if (option == "MATCH_CASE") |  | 
| 496         { |  | 
| 497           matchCase = true; |  | 
| 498         } |  | 
| 499         else if (option == "DOMAIN" && typeof value != "undefined") |  | 
| 500         { |  | 
| 501           domains = value; |  | 
| 502         } |  | 
| 503         else if (option == "THIRD_PARTY") |  | 
| 504         { |  | 
| 505           thirdParty = true; |  | 
| 506         } |  | 
| 507         else if (option == "~THIRD_PARTY") |  | 
| 508         { |  | 
| 509           thirdParty = false; |  | 
| 510         } |  | 
| 511         else if (option == "COLLAPSE") |  | 
| 512         { |  | 
| 513           collapse = true; |  | 
| 514         } |  | 
| 515         else if (option == "~COLLAPSE") |  | 
| 516         { |  | 
| 517           collapse = false; |  | 
| 518         } |  | 
| 519         else if (option == "SITEKEY" && typeof value != "undefined") |  | 
| 520         { |  | 
| 521           siteKeys = value.split(/\|/); |  | 
| 522         } |  | 
| 523       } |  | 
| 524     } |  | 
| 525     if (!blocking && (contentType == null || contentType & RegExpFilter.typeMap.
      DOCUMENT) && (!options || options.indexOf("DOCUMENT") < 0) && !/^\|?[\w\-]+:/.te
      st(text)) |  | 
| 526     { |  | 
| 527       if (contentType == null) |  | 
| 528       { |  | 
| 529         contentType = RegExpFilter.prototype.contentType; |  | 
| 530       } |  | 
| 531       contentType &= ~RegExpFilter.typeMap.DOCUMENT; |  | 
| 532     } |  | 
| 533     if (!blocking && siteKeys) |  | 
| 534     { |  | 
| 535       contentType = RegExpFilter.typeMap.DOCUMENT; |  | 
| 536     } |  | 
| 537     try |  | 
| 538     { |  | 
| 539       if (blocking) |  | 
| 540       { |  | 
| 541         return new BlockingFilter(origText, text, contentType, matchCase, domain
      s, thirdParty, collapse); |  | 
| 542       } |  | 
| 543       else |  | 
| 544       { |  | 
| 545         return new WhitelistFilter(origText, text, contentType, matchCase, domai
      ns, thirdParty, siteKeys); |  | 
| 546       } |  | 
| 547     } |  | 
| 548     catch (e) |  | 
| 549     { |  | 
| 550       return new InvalidFilter(text, e); |  | 
| 551     } |  | 
| 552   }; |  | 
| 553   RegExpFilter.typeMap = |  | 
| 554   { |  | 
| 555     OTHER: 1, |  | 
| 556     SCRIPT: 2, |  | 
| 557     IMAGE: 4, |  | 
| 558     STYLESHEET: 8, |  | 
| 559     OBJECT: 16, |  | 
| 560     SUBDOCUMENT: 32, |  | 
| 561     DOCUMENT: 64, |  | 
| 562     XBL: 1, |  | 
| 563     PING: 1, |  | 
| 564     XMLHTTPREQUEST: 2048, |  | 
| 565     OBJECT_SUBREQUEST: 4096, |  | 
| 566     DTD: 1, |  | 
| 567     MEDIA: 16384, |  | 
| 568     FONT: 32768, |  | 
| 569     BACKGROUND: 4, |  | 
| 570     POPUP: 268435456, |  | 
| 571     DONOTTRACK: 536870912, |  | 
| 572     ELEMHIDE: 1073741824 |  | 
| 573   }; |  | 
| 574   RegExpFilter.prototype.contentType &= ~ (RegExpFilter.typeMap.ELEMHIDE | RegEx
      pFilter.typeMap.DONOTTRACK | RegExpFilter.typeMap.POPUP); |  | 
| 575 |  | 
| 576   function BlockingFilter(text, regexpSource, contentType, matchCase, domains, t
      hirdParty, collapse) |  | 
| 577   { |  | 
| 578     RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains,
       thirdParty); |  | 
| 579     this.collapse = collapse; |  | 
| 580   } |  | 
| 581   exports.BlockingFilter = BlockingFilter; |  | 
| 582   BlockingFilter.prototype = |  | 
| 583   { |  | 
| 584     __proto__: RegExpFilter.prototype, |  | 
| 585     collapse: null |  | 
| 586   }; |  | 
| 587 |  | 
| 588   function WhitelistFilter(text, regexpSource, contentType, matchCase, domains, 
      thirdParty, siteKeys) |  | 
| 589   { |  | 
| 590     RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains,
       thirdParty); |  | 
| 591     if (siteKeys != null) |  | 
| 592     { |  | 
| 593       this.siteKeys = siteKeys; |  | 
| 594     } |  | 
| 595   } |  | 
| 596   exports.WhitelistFilter = WhitelistFilter; |  | 
| 597   WhitelistFilter.prototype = |  | 
| 598   { |  | 
| 599     __proto__: RegExpFilter.prototype, |  | 
| 600     siteKeys: null |  | 
| 601   }; |  | 
| 602 |  | 
| 603   function ElemHideBase(text, domains, selector) |  | 
| 604   { |  | 
| 605     ActiveFilter.call(this, text, domains ? domains.toUpperCase() : null); |  | 
| 606     if (domains) |  | 
| 607     { |  | 
| 608       this.selectorDomain = domains.replace(/,~[^,]+/g, "").replace(/^~[^,]+,?/,
       "").toLowerCase(); |  | 
| 609     } |  | 
| 610     this.selector = selector; |  | 
| 611   } |  | 
| 612   exports.ElemHideBase = ElemHideBase; |  | 
| 613   ElemHideBase.prototype = |  | 
| 614   { |  | 
| 615     __proto__: ActiveFilter.prototype, |  | 
| 616     domainSeparator: ",", |  | 
| 617     ignoreTrailingDot: false, |  | 
| 618     selectorDomain: null, |  | 
| 619     selector: null |  | 
| 620   }; |  | 
| 621   ElemHideBase.fromText = function(text, domain, isException, tagName, attrRules
      , selector) |  | 
| 622   { |  | 
| 623     if (!selector) |  | 
| 624     { |  | 
| 625       if (tagName == "*") |  | 
| 626       { |  | 
| 627         tagName = ""; |  | 
| 628       } |  | 
| 629       var id = null; |  | 
| 630       var additional = ""; |  | 
| 631       if (attrRules) |  | 
| 632       { |  | 
| 633         attrRules = attrRules.match(/\([\w\-]+(?:[$^*]?=[^\(\)"]*)?\)/g); |  | 
| 634         for (var _loopIndex3 = 0; _loopIndex3 < attrRules.length; ++_loopIndex3) |  | 
| 635         { |  | 
| 636           var rule = attrRules[_loopIndex3]; |  | 
| 637           rule = rule.substr(1, rule.length - 2); |  | 
| 638           var separatorPos = rule.indexOf("="); |  | 
| 639           if (separatorPos > 0) |  | 
| 640           { |  | 
| 641             rule = rule.replace(/=/, "=\"") + "\""; |  | 
| 642             additional += "[" + rule + "]"; |  | 
| 643           } |  | 
| 644           else |  | 
| 645           { |  | 
| 646             if (id) |  | 
| 647             { |  | 
| 648               var Utils = require("utils").Utils; |  | 
| 649               return new InvalidFilter(text, Utils.getString("filter_elemhide_du
      plicate_id")); |  | 
| 650             } |  | 
| 651             else |  | 
| 652             { |  | 
| 653               id = rule; |  | 
| 654             } |  | 
| 655           } |  | 
| 656         } |  | 
| 657       } |  | 
| 658       if (id) |  | 
| 659       { |  | 
| 660         selector = tagName + "." + id + additional + "," + tagName + "#" + id + 
      additional; |  | 
| 661       } |  | 
| 662       else if (tagName || additional) |  | 
| 663       { |  | 
| 664         selector = tagName + additional; |  | 
| 665       } |  | 
| 666       else |  | 
| 667       { |  | 
| 668         var Utils = require("utils").Utils; |  | 
| 669         return new InvalidFilter(text, Utils.getString("filter_elemhide_nocriter
      ia")); |  | 
| 670       } |  | 
| 671     } |  | 
| 672     if (isException) |  | 
| 673     { |  | 
| 674       return new ElemHideException(text, domain, selector); |  | 
| 675     } |  | 
| 676     else |  | 
| 677     { |  | 
| 678       return new ElemHideFilter(text, domain, selector); |  | 
| 679     } |  | 
| 680   }; |  | 
| 681 |  | 
| 682   function ElemHideFilter(text, domains, selector) |  | 
| 683   { |  | 
| 684     ElemHideBase.call(this, text, domains, selector); |  | 
| 685   } |  | 
| 686   exports.ElemHideFilter = ElemHideFilter; |  | 
| 687   ElemHideFilter.prototype = |  | 
| 688   { |  | 
| 689     __proto__: ElemHideBase.prototype |  | 
| 690   }; |  | 
| 691 |  | 
| 692   function ElemHideException(text, domains, selector) |  | 
| 693   { |  | 
| 694     ElemHideBase.call(this, text, domains, selector); |  | 
| 695   } |  | 
| 696   exports.ElemHideException = ElemHideException; |  | 
| 697   ElemHideException.prototype = |  | 
| 698   { |  | 
| 699     __proto__: ElemHideBase.prototype |  | 
| 700   }; |  | 
| 701   return exports; |  | 
| 702 })(); |  | 
| 703 require.scopes["subscriptionClasses"] = (function() |  | 
| 704 { |  | 
| 705   var exports = {}; |  | 
| 706   var _tempVar4 = require("filterClasses"); |  | 
| 707   var ActiveFilter = _tempVar4.ActiveFilter; |  | 
| 708   var BlockingFilter = _tempVar4.BlockingFilter; |  | 
| 709   var WhitelistFilter = _tempVar4.WhitelistFilter; |  | 
| 710   var ElemHideBase = _tempVar4.ElemHideBase; |  | 
| 711   var FilterNotifier = require("filterNotifier").FilterNotifier; |  | 
| 712 |  | 
| 713   function Subscription(url, title) |  | 
| 714   { |  | 
| 715     this.url = url; |  | 
| 716     this.filters = []; |  | 
| 717     if (title) |  | 
| 718     { |  | 
| 719       this._title = title; |  | 
| 720     } |  | 
| 721     else |  | 
| 722     { |  | 
| 723       var Utils = require("utils").Utils; |  | 
| 724       this._title = Utils.getString("newGroup_title"); |  | 
| 725     } |  | 
| 726     Subscription.knownSubscriptions[url] = this; |  | 
| 727   } |  | 
| 728   exports.Subscription = Subscription; |  | 
| 729   Subscription.prototype = |  | 
| 730   { |  | 
| 731     url: null, |  | 
| 732     filters: null, |  | 
| 733     _title: null, |  | 
| 734     _fixedTitle: false, |  | 
| 735     _disabled: false, |  | 
| 736     get title() |  | 
| 737     { |  | 
| 738       return this._title; |  | 
| 739     }, |  | 
| 740     set title(value) |  | 
| 741     { |  | 
| 742       if (value != this._title) |  | 
| 743       { |  | 
| 744         var oldValue = this._title; |  | 
| 745         this._title = value; |  | 
| 746         FilterNotifier.triggerListeners("subscription.title", this, value, oldVa
      lue); |  | 
| 747       } |  | 
| 748       return this._title; |  | 
| 749     }, |  | 
| 750     get fixedTitle() |  | 
| 751     { |  | 
| 752       return this._fixedTitle; |  | 
| 753     }, |  | 
| 754     set fixedTitle(value) |  | 
| 755     { |  | 
| 756       if (value != this._fixedTitle) |  | 
| 757       { |  | 
| 758         var oldValue = this._fixedTitle; |  | 
| 759         this._fixedTitle = value; |  | 
| 760         FilterNotifier.triggerListeners("subscription.fixedTitle", this, value, 
      oldValue); |  | 
| 761       } |  | 
| 762       return this._fixedTitle; |  | 
| 763     }, |  | 
| 764     get disabled() |  | 
| 765     { |  | 
| 766       return this._disabled; |  | 
| 767     }, |  | 
| 768     set disabled(value) |  | 
| 769     { |  | 
| 770       if (value != this._disabled) |  | 
| 771       { |  | 
| 772         var oldValue = this._disabled; |  | 
| 773         this._disabled = value; |  | 
| 774         FilterNotifier.triggerListeners("subscription.disabled", this, value, ol
      dValue); |  | 
| 775       } |  | 
| 776       return this._disabled; |  | 
| 777     }, |  | 
| 778     serialize: function(buffer) |  | 
| 779     { |  | 
| 780       buffer.push("[Subscription]"); |  | 
| 781       buffer.push("url=" + this.url); |  | 
| 782       buffer.push("title=" + this._title); |  | 
| 783       if (this._fixedTitle) |  | 
| 784       { |  | 
| 785         buffer.push("fixedTitle=true"); |  | 
| 786       } |  | 
| 787       if (this._disabled) |  | 
| 788       { |  | 
| 789         buffer.push("disabled=true"); |  | 
| 790       } |  | 
| 791     }, |  | 
| 792     serializeFilters: function(buffer) |  | 
| 793     { |  | 
| 794       for (var _loopIndex5 = 0; _loopIndex5 < this.filters.length; ++_loopIndex5
      ) |  | 
| 795       { |  | 
| 796         var filter = this.filters[_loopIndex5]; |  | 
| 797         buffer.push(filter.text.replace(/\[/g, "\\[")); |  | 
| 798       } |  | 
| 799     }, |  | 
| 800     toString: function() |  | 
| 801     { |  | 
| 802       var buffer = []; |  | 
| 803       this.serialize(buffer); |  | 
| 804       return buffer.join("\n"); |  | 
| 805     } |  | 
| 806   }; |  | 
| 807   Subscription.knownSubscriptions = |  | 
| 808   { |  | 
| 809     __proto__: null |  | 
| 810   }; |  | 
| 811   Subscription.fromURL = function(url) |  | 
| 812   { |  | 
| 813     if (url in Subscription.knownSubscriptions) |  | 
| 814     { |  | 
| 815       return Subscription.knownSubscriptions[url]; |  | 
| 816     } |  | 
| 817     try |  | 
| 818     { |  | 
| 819       url = Services.io.newURI(url, null, null).spec; |  | 
| 820       return new DownloadableSubscription(url, null); |  | 
| 821     } |  | 
| 822     catch (e) |  | 
| 823     { |  | 
| 824       return new SpecialSubscription(url); |  | 
| 825     } |  | 
| 826   }; |  | 
| 827   Subscription.fromObject = function(obj) |  | 
| 828   { |  | 
| 829     var result; |  | 
| 830     try |  | 
| 831     { |  | 
| 832       obj.url = Services.io.newURI(obj.url, null, null).spec; |  | 
| 833       result = new DownloadableSubscription(obj.url, obj.title); |  | 
| 834       if ("nextURL" in obj) |  | 
| 835       { |  | 
| 836         result.nextURL = obj.nextURL; |  | 
| 837       } |  | 
| 838       if ("downloadStatus" in obj) |  | 
| 839       { |  | 
| 840         result._downloadStatus = obj.downloadStatus; |  | 
| 841       } |  | 
| 842       if ("lastModified" in obj) |  | 
| 843       { |  | 
| 844         result.lastModified = obj.lastModified; |  | 
| 845       } |  | 
| 846       if ("lastSuccess" in obj) |  | 
| 847       { |  | 
| 848         result.lastSuccess = parseInt(obj.lastSuccess) || 0; |  | 
| 849       } |  | 
| 850       if ("lastCheck" in obj) |  | 
| 851       { |  | 
| 852         result._lastCheck = parseInt(obj.lastCheck) || 0; |  | 
| 853       } |  | 
| 854       if ("expires" in obj) |  | 
| 855       { |  | 
| 856         result.expires = parseInt(obj.expires) || 0; |  | 
| 857       } |  | 
| 858       if ("softExpiration" in obj) |  | 
| 859       { |  | 
| 860         result.softExpiration = parseInt(obj.softExpiration) || 0; |  | 
| 861       } |  | 
| 862       if ("errors" in obj) |  | 
| 863       { |  | 
| 864         result._errors = parseInt(obj.errors) || 0; |  | 
| 865       } |  | 
| 866       if ("requiredVersion" in obj) |  | 
| 867       { |  | 
| 868         var addonVersion = require("info").addonVersion; |  | 
| 869         result.requiredVersion = obj.requiredVersion; |  | 
| 870         if (Services.vc.compare(result.requiredVersion, addonVersion) > 0) |  | 
| 871         { |  | 
| 872           result.upgradeRequired = true; |  | 
| 873         } |  | 
| 874       } |  | 
| 875       if ("alternativeLocations" in obj) |  | 
| 876       { |  | 
| 877         result.alternativeLocations = obj.alternativeLocations; |  | 
| 878       } |  | 
| 879       if ("homepage" in obj) |  | 
| 880       { |  | 
| 881         result._homepage = obj.homepage; |  | 
| 882       } |  | 
| 883       if ("lastDownload" in obj) |  | 
| 884       { |  | 
| 885         result._lastDownload = parseInt(obj.lastDownload) || 0; |  | 
| 886       } |  | 
| 887     } |  | 
| 888     catch (e) |  | 
| 889     { |  | 
| 890       if (!("title" in obj)) |  | 
| 891       { |  | 
| 892         if (obj.url == "~wl~") |  | 
| 893         { |  | 
| 894           obj.defaults = "whitelist"; |  | 
| 895         } |  | 
| 896         else if (obj.url == "~fl~") |  | 
| 897         { |  | 
| 898           obj.defaults = "blocking"; |  | 
| 899         } |  | 
| 900         else if (obj.url == "~eh~") |  | 
| 901         { |  | 
| 902           obj.defaults = "elemhide"; |  | 
| 903         } |  | 
| 904         if ("defaults" in obj) |  | 
| 905         { |  | 
| 906           var Utils = require("utils").Utils; |  | 
| 907           obj.title = Utils.getString(obj.defaults + "Group_title"); |  | 
| 908         } |  | 
| 909       } |  | 
| 910       result = new SpecialSubscription(obj.url, obj.title); |  | 
| 911       if ("defaults" in obj) |  | 
| 912       { |  | 
| 913         result.defaults = obj.defaults.split(" "); |  | 
| 914       } |  | 
| 915     } |  | 
| 916     if ("fixedTitle" in obj) |  | 
| 917     { |  | 
| 918       result._fixedTitle = obj.fixedTitle == "true"; |  | 
| 919     } |  | 
| 920     if ("disabled" in obj) |  | 
| 921     { |  | 
| 922       result._disabled = obj.disabled == "true"; |  | 
| 923     } |  | 
| 924     return result; |  | 
| 925   }; |  | 
| 926 |  | 
| 927   function SpecialSubscription(url, title) |  | 
| 928   { |  | 
| 929     Subscription.call(this, url, title); |  | 
| 930   } |  | 
| 931   exports.SpecialSubscription = SpecialSubscription; |  | 
| 932   SpecialSubscription.prototype = |  | 
| 933   { |  | 
| 934     __proto__: Subscription.prototype, |  | 
| 935     defaults: null, |  | 
| 936     isDefaultFor: function(filter) |  | 
| 937     { |  | 
| 938       if (this.defaults && this.defaults.length) |  | 
| 939       { |  | 
| 940         for (var _loopIndex6 = 0; _loopIndex6 < this.defaults.length; ++_loopInd
      ex6) |  | 
| 941         { |  | 
| 942           var type = this.defaults[_loopIndex6]; |  | 
| 943           if (filter instanceof SpecialSubscription.defaultsMap[type]) |  | 
| 944           { |  | 
| 945             return true; |  | 
| 946           } |  | 
| 947           if (!(filter instanceof ActiveFilter) && type == "blacklist") |  | 
| 948           { |  | 
| 949             return true; |  | 
| 950           } |  | 
| 951         } |  | 
| 952       } |  | 
| 953       return false; |  | 
| 954     }, |  | 
| 955     serialize: function(buffer) |  | 
| 956     { |  | 
| 957       Subscription.prototype.serialize.call(this, buffer); |  | 
| 958       if (this.defaults && this.defaults.length) |  | 
| 959       { |  | 
| 960         buffer.push("defaults=" + this.defaults.filter(function(type) |  | 
| 961         { |  | 
| 962           return type in SpecialSubscription.defaultsMap; |  | 
| 963         }).join(" ")); |  | 
| 964       } |  | 
| 965       if (this._lastDownload) |  | 
| 966       { |  | 
| 967         buffer.push("lastDownload=" + this._lastDownload); |  | 
| 968       } |  | 
| 969     } |  | 
| 970   }; |  | 
| 971   SpecialSubscription.defaultsMap = |  | 
| 972   { |  | 
| 973     __proto__: null, |  | 
| 974     "whitelist": WhitelistFilter, |  | 
| 975     "blocking": BlockingFilter, |  | 
| 976     "elemhide": ElemHideBase |  | 
| 977   }; |  | 
| 978   SpecialSubscription.create = function(title) |  | 
| 979   { |  | 
| 980     var url; |  | 
| 981     do |  | 
| 982     { |  | 
| 983       url = "~user~" + Math.round(Math.random() * 1000000); |  | 
| 984     } |  | 
| 985     while (url in Subscription.knownSubscriptions); |  | 
| 986     return new SpecialSubscription(url, title); |  | 
| 987   }; |  | 
| 988   SpecialSubscription.createForFilter = function(filter) |  | 
| 989   { |  | 
| 990     var subscription = SpecialSubscription.create(); |  | 
| 991     subscription.filters.push(filter); |  | 
| 992     for (var type in SpecialSubscription.defaultsMap) |  | 
| 993     { |  | 
| 994       if (filter instanceof SpecialSubscription.defaultsMap[type]) |  | 
| 995       { |  | 
| 996         subscription.defaults = [type]; |  | 
| 997       } |  | 
| 998     } |  | 
| 999     if (!subscription.defaults) |  | 
| 1000     { |  | 
| 1001       subscription.defaults = ["blocking"]; |  | 
| 1002     } |  | 
| 1003     var Utils = require("utils").Utils; |  | 
| 1004     subscription.title = Utils.getString(subscription.defaults[0] + "Group_title
      "); |  | 
| 1005     return subscription; |  | 
| 1006   }; |  | 
| 1007 |  | 
| 1008   function RegularSubscription(url, title) |  | 
| 1009   { |  | 
| 1010     Subscription.call(this, url, title || url); |  | 
| 1011   } |  | 
| 1012   exports.RegularSubscription = RegularSubscription; |  | 
| 1013   RegularSubscription.prototype = |  | 
| 1014   { |  | 
| 1015     __proto__: Subscription.prototype, |  | 
| 1016     _homepage: null, |  | 
| 1017     _lastDownload: 0, |  | 
| 1018     get homepage() |  | 
| 1019     { |  | 
| 1020       return this._homepage; |  | 
| 1021     }, |  | 
| 1022     set homepage(value) |  | 
| 1023     { |  | 
| 1024       if (value != this._homepage) |  | 
| 1025       { |  | 
| 1026         var oldValue = this._homepage; |  | 
| 1027         this._homepage = value; |  | 
| 1028         FilterNotifier.triggerListeners("subscription.homepage", this, value, ol
      dValue); |  | 
| 1029       } |  | 
| 1030       return this._homepage; |  | 
| 1031     }, |  | 
| 1032     get lastDownload() |  | 
| 1033     { |  | 
| 1034       return this._lastDownload; |  | 
| 1035     }, |  | 
| 1036     set lastDownload(value) |  | 
| 1037     { |  | 
| 1038       if (value != this._lastDownload) |  | 
| 1039       { |  | 
| 1040         var oldValue = this._lastDownload; |  | 
| 1041         this._lastDownload = value; |  | 
| 1042         FilterNotifier.triggerListeners("subscription.lastDownload", this, value
      , oldValue); |  | 
| 1043       } |  | 
| 1044       return this._lastDownload; |  | 
| 1045     }, |  | 
| 1046     serialize: function(buffer) |  | 
| 1047     { |  | 
| 1048       Subscription.prototype.serialize.call(this, buffer); |  | 
| 1049       if (this._homepage) |  | 
| 1050       { |  | 
| 1051         buffer.push("homepage=" + this._homepage); |  | 
| 1052       } |  | 
| 1053       if (this._lastDownload) |  | 
| 1054       { |  | 
| 1055         buffer.push("lastDownload=" + this._lastDownload); |  | 
| 1056       } |  | 
| 1057     } |  | 
| 1058   }; |  | 
| 1059 |  | 
| 1060   function ExternalSubscription(url, title) |  | 
| 1061   { |  | 
| 1062     RegularSubscription.call(this, url, title); |  | 
| 1063   } |  | 
| 1064   exports.ExternalSubscription = ExternalSubscription; |  | 
| 1065   ExternalSubscription.prototype = |  | 
| 1066   { |  | 
| 1067     __proto__: RegularSubscription.prototype, |  | 
| 1068     serialize: function(buffer) |  | 
| 1069     { |  | 
| 1070       throw new Error("Unexpected call, external subscriptions should not be ser
      ialized"); |  | 
| 1071     } |  | 
| 1072   }; |  | 
| 1073 |  | 
| 1074   function DownloadableSubscription(url, title) |  | 
| 1075   { |  | 
| 1076     RegularSubscription.call(this, url, title); |  | 
| 1077   } |  | 
| 1078   exports.DownloadableSubscription = DownloadableSubscription; |  | 
| 1079   DownloadableSubscription.prototype = |  | 
| 1080   { |  | 
| 1081     __proto__: RegularSubscription.prototype, |  | 
| 1082     _downloadStatus: null, |  | 
| 1083     _lastCheck: 0, |  | 
| 1084     _errors: 0, |  | 
| 1085     nextURL: null, |  | 
| 1086     get downloadStatus() |  | 
| 1087     { |  | 
| 1088       return this._downloadStatus; |  | 
| 1089     }, |  | 
| 1090     set downloadStatus(value) |  | 
| 1091     { |  | 
| 1092       var oldValue = this._downloadStatus; |  | 
| 1093       this._downloadStatus = value; |  | 
| 1094       FilterNotifier.triggerListeners("subscription.downloadStatus", this, value
      , oldValue); |  | 
| 1095       return this._downloadStatus; |  | 
| 1096     }, |  | 
| 1097     lastModified: null, |  | 
| 1098     lastSuccess: 0, |  | 
| 1099     get lastCheck() |  | 
| 1100     { |  | 
| 1101       return this._lastCheck; |  | 
| 1102     }, |  | 
| 1103     set lastCheck(value) |  | 
| 1104     { |  | 
| 1105       if (value != this._lastCheck) |  | 
| 1106       { |  | 
| 1107         var oldValue = this._lastCheck; |  | 
| 1108         this._lastCheck = value; |  | 
| 1109         FilterNotifier.triggerListeners("subscription.lastCheck", this, value, o
      ldValue); |  | 
| 1110       } |  | 
| 1111       return this._lastCheck; |  | 
| 1112     }, |  | 
| 1113     expires: 0, |  | 
| 1114     softExpiration: 0, |  | 
| 1115     get errors() |  | 
| 1116     { |  | 
| 1117       return this._errors; |  | 
| 1118     }, |  | 
| 1119     set errors(value) |  | 
| 1120     { |  | 
| 1121       if (value != this._errors) |  | 
| 1122       { |  | 
| 1123         var oldValue = this._errors; |  | 
| 1124         this._errors = value; |  | 
| 1125         FilterNotifier.triggerListeners("subscription.errors", this, value, oldV
      alue); |  | 
| 1126       } |  | 
| 1127       return this._errors; |  | 
| 1128     }, |  | 
| 1129     requiredVersion: null, |  | 
| 1130     upgradeRequired: false, |  | 
| 1131     alternativeLocations: null, |  | 
| 1132     serialize: function(buffer) |  | 
| 1133     { |  | 
| 1134       RegularSubscription.prototype.serialize.call(this, buffer); |  | 
| 1135       if (this.nextURL) |  | 
| 1136       { |  | 
| 1137         buffer.push("nextURL=" + this.nextURL); |  | 
| 1138       } |  | 
| 1139       if (this.downloadStatus) |  | 
| 1140       { |  | 
| 1141         buffer.push("downloadStatus=" + this.downloadStatus); |  | 
| 1142       } |  | 
| 1143       if (this.lastModified) |  | 
| 1144       { |  | 
| 1145         buffer.push("lastModified=" + this.lastModified); |  | 
| 1146       } |  | 
| 1147       if (this.lastSuccess) |  | 
| 1148       { |  | 
| 1149         buffer.push("lastSuccess=" + this.lastSuccess); |  | 
| 1150       } |  | 
| 1151       if (this.lastCheck) |  | 
| 1152       { |  | 
| 1153         buffer.push("lastCheck=" + this.lastCheck); |  | 
| 1154       } |  | 
| 1155       if (this.expires) |  | 
| 1156       { |  | 
| 1157         buffer.push("expires=" + this.expires); |  | 
| 1158       } |  | 
| 1159       if (this.softExpiration) |  | 
| 1160       { |  | 
| 1161         buffer.push("softExpiration=" + this.softExpiration); |  | 
| 1162       } |  | 
| 1163       if (this.errors) |  | 
| 1164       { |  | 
| 1165         buffer.push("errors=" + this.errors); |  | 
| 1166       } |  | 
| 1167       if (this.requiredVersion) |  | 
| 1168       { |  | 
| 1169         buffer.push("requiredVersion=" + this.requiredVersion); |  | 
| 1170       } |  | 
| 1171       if (this.alternativeLocations) |  | 
| 1172       { |  | 
| 1173         buffer.push("alternativeLocations=" + this.alternativeLocations); |  | 
| 1174       } |  | 
| 1175     } |  | 
| 1176   }; |  | 
| 1177   return exports; |  | 
| 1178 })(); |  | 
| 1179 require.scopes["filterStorage"] = (function() |  | 
| 1180 { |  | 
| 1181   var exports = {}; |  | 
| 1182   var IO = require("io").IO; |  | 
| 1183   var Prefs = require("prefs").Prefs; |  | 
| 1184   var _tempVar7 = require("filterClasses"); |  | 
| 1185   var Filter = _tempVar7.Filter; |  | 
| 1186   var ActiveFilter = _tempVar7.ActiveFilter; |  | 
| 1187   var _tempVar8 = require("subscriptionClasses"); |  | 
| 1188   var Subscription = _tempVar8.Subscription; |  | 
| 1189   var SpecialSubscription = _tempVar8.SpecialSubscription; |  | 
| 1190   var ExternalSubscription = _tempVar8.ExternalSubscription; |  | 
| 1191   var FilterNotifier = require("filterNotifier").FilterNotifier; |  | 
| 1192   var formatVersion = 4; |  | 
| 1193   var FilterStorage = exports.FilterStorage = |  | 
| 1194   { |  | 
| 1195     get formatVersion() |  | 
| 1196     { |  | 
| 1197       return formatVersion; |  | 
| 1198     }, |  | 
| 1199     get sourceFile() |  | 
| 1200     { |  | 
| 1201       var file = null; |  | 
| 1202       if (Prefs.patternsfile) |  | 
| 1203       { |  | 
| 1204         file = IO.resolveFilePath(Prefs.patternsfile); |  | 
| 1205       } |  | 
| 1206       if (!file) |  | 
| 1207       { |  | 
| 1208         file = IO.resolveFilePath(Prefs.data_directory); |  | 
| 1209         if (file) |  | 
| 1210         { |  | 
| 1211           file.append("patterns.ini"); |  | 
| 1212         } |  | 
| 1213       } |  | 
| 1214       if (!file) |  | 
| 1215       { |  | 
| 1216         try |  | 
| 1217         { |  | 
| 1218           file = IO.resolveFilePath(Services.prefs.getDefaultBranch("extensions.
      adblockplus.").getCharPref("data_directory")); |  | 
| 1219           if (file) |  | 
| 1220           { |  | 
| 1221             file.append("patterns.ini"); |  | 
| 1222           } |  | 
| 1223         } |  | 
| 1224         catch (e){} |  | 
| 1225       } |  | 
| 1226       if (!file) |  | 
| 1227       { |  | 
| 1228         Cu.reportError("Adblock Plus: Failed to resolve filter file location fro
      m extensions.adblockplus.patternsfile preference"); |  | 
| 1229       } |  | 
| 1230       this.__defineGetter__("sourceFile", function() |  | 
| 1231       { |  | 
| 1232         return file; |  | 
| 1233       }); |  | 
| 1234       return this.sourceFile; |  | 
| 1235     }, |  | 
| 1236     fileProperties: |  | 
| 1237     { |  | 
| 1238       __proto__: null |  | 
| 1239     }, |  | 
| 1240     subscriptions: [], |  | 
| 1241     knownSubscriptions: |  | 
| 1242     { |  | 
| 1243       __proto__: null |  | 
| 1244     }, |  | 
| 1245     getGroupForFilter: function(filter) |  | 
| 1246     { |  | 
| 1247       var generalSubscription = null; |  | 
| 1248       for (var _loopIndex9 = 0; _loopIndex9 < FilterStorage.subscriptions.length
      ; ++_loopIndex9) |  | 
| 1249       { |  | 
| 1250         var subscription = FilterStorage.subscriptions[_loopIndex9]; |  | 
| 1251         if (subscription instanceof SpecialSubscription && !subscription.disable
      d) |  | 
| 1252         { |  | 
| 1253           if (subscription.isDefaultFor(filter)) |  | 
| 1254           { |  | 
| 1255             return subscription; |  | 
| 1256           } |  | 
| 1257           if (!generalSubscription && (!subscription.defaults || !subscription.d
      efaults.length)) |  | 
| 1258           { |  | 
| 1259             generalSubscription = subscription; |  | 
| 1260           } |  | 
| 1261         } |  | 
| 1262       } |  | 
| 1263       return generalSubscription; |  | 
| 1264     }, |  | 
| 1265     addSubscription: function(subscription, silent) |  | 
| 1266     { |  | 
| 1267       if (subscription.url in FilterStorage.knownSubscriptions) |  | 
| 1268       { |  | 
| 1269         return; |  | 
| 1270       } |  | 
| 1271       FilterStorage.subscriptions.push(subscription); |  | 
| 1272       FilterStorage.knownSubscriptions[subscription.url] = subscription; |  | 
| 1273       addSubscriptionFilters(subscription); |  | 
| 1274       if (!silent) |  | 
| 1275       { |  | 
| 1276         FilterNotifier.triggerListeners("subscription.added", subscription); |  | 
| 1277       } |  | 
| 1278     }, |  | 
| 1279     removeSubscription: function(subscription, silent) |  | 
| 1280     { |  | 
| 1281       for (var i = 0; i < FilterStorage.subscriptions.length; i++) |  | 
| 1282       { |  | 
| 1283         if (FilterStorage.subscriptions[i].url == subscription.url) |  | 
| 1284         { |  | 
| 1285           removeSubscriptionFilters(subscription); |  | 
| 1286           FilterStorage.subscriptions.splice(i--, 1); |  | 
| 1287           delete FilterStorage.knownSubscriptions[subscription.url]; |  | 
| 1288           if (!silent) |  | 
| 1289           { |  | 
| 1290             FilterNotifier.triggerListeners("subscription.removed", subscription
      ); |  | 
| 1291           } |  | 
| 1292           return; |  | 
| 1293         } |  | 
| 1294       } |  | 
| 1295     }, |  | 
| 1296     moveSubscription: function(subscription, insertBefore) |  | 
| 1297     { |  | 
| 1298       var currentPos = FilterStorage.subscriptions.indexOf(subscription); |  | 
| 1299       if (currentPos < 0) |  | 
| 1300       { |  | 
| 1301         return; |  | 
| 1302       } |  | 
| 1303       var newPos = insertBefore ? FilterStorage.subscriptions.indexOf(insertBefo
      re) : -1; |  | 
| 1304       if (newPos < 0) |  | 
| 1305       { |  | 
| 1306         newPos = FilterStorage.subscriptions.length; |  | 
| 1307       } |  | 
| 1308       if (currentPos < newPos) |  | 
| 1309       { |  | 
| 1310         newPos--; |  | 
| 1311       } |  | 
| 1312       if (currentPos == newPos) |  | 
| 1313       { |  | 
| 1314         return; |  | 
| 1315       } |  | 
| 1316       FilterStorage.subscriptions.splice(currentPos, 1); |  | 
| 1317       FilterStorage.subscriptions.splice(newPos, 0, subscription); |  | 
| 1318       FilterNotifier.triggerListeners("subscription.moved", subscription); |  | 
| 1319     }, |  | 
| 1320     updateSubscriptionFilters: function(subscription, filters) |  | 
| 1321     { |  | 
| 1322       removeSubscriptionFilters(subscription); |  | 
| 1323       subscription.oldFilters = subscription.filters; |  | 
| 1324       subscription.filters = filters; |  | 
| 1325       addSubscriptionFilters(subscription); |  | 
| 1326       FilterNotifier.triggerListeners("subscription.updated", subscription); |  | 
| 1327       delete subscription.oldFilters; |  | 
| 1328     }, |  | 
| 1329     addFilter: function(filter, subscription, position, silent) |  | 
| 1330     { |  | 
| 1331       if (!subscription) |  | 
| 1332       { |  | 
| 1333         if (filter.subscriptions.some(function(s) |  | 
| 1334         { |  | 
| 1335           return s instanceof SpecialSubscription && !s.disabled; |  | 
| 1336         })) |  | 
| 1337         { |  | 
| 1338           return; |  | 
| 1339         } |  | 
| 1340         subscription = FilterStorage.getGroupForFilter(filter); |  | 
| 1341       } |  | 
| 1342       if (!subscription) |  | 
| 1343       { |  | 
| 1344         subscription = SpecialSubscription.createForFilter(filter); |  | 
| 1345         this.addSubscription(subscription); |  | 
| 1346         return; |  | 
| 1347       } |  | 
| 1348       if (typeof position == "undefined") |  | 
| 1349       { |  | 
| 1350         position = subscription.filters.length; |  | 
| 1351       } |  | 
| 1352       if (filter.subscriptions.indexOf(subscription) < 0) |  | 
| 1353       { |  | 
| 1354         filter.subscriptions.push(subscription); |  | 
| 1355       } |  | 
| 1356       subscription.filters.splice(position, 0, filter); |  | 
| 1357       if (!silent) |  | 
| 1358       { |  | 
| 1359         FilterNotifier.triggerListeners("filter.added", filter, subscription, po
      sition); |  | 
| 1360       } |  | 
| 1361     }, |  | 
| 1362     removeFilter: function(filter, subscription, position) |  | 
| 1363     { |  | 
| 1364       var subscriptions = subscription ? [subscription] : filter.subscriptions.s
      lice(); |  | 
| 1365       for (var i = 0; i < subscriptions.length; i++) |  | 
| 1366       { |  | 
| 1367         var subscription = subscriptions[i]; |  | 
| 1368         if (subscription instanceof SpecialSubscription) |  | 
| 1369         { |  | 
| 1370           var positions = []; |  | 
| 1371           if (typeof position == "undefined") |  | 
| 1372           { |  | 
| 1373             var index = -1; |  | 
| 1374             do |  | 
| 1375             { |  | 
| 1376               index = subscription.filters.indexOf(filter, index + 1); |  | 
| 1377               if (index >= 0) |  | 
| 1378               { |  | 
| 1379                 positions.push(index); |  | 
| 1380               } |  | 
| 1381             } |  | 
| 1382             while (index >= 0); |  | 
| 1383           } |  | 
| 1384           else |  | 
| 1385           { |  | 
| 1386             positions.push(position); |  | 
| 1387           } |  | 
| 1388           for (var j = positions.length - 1; j >= 0; j--) |  | 
| 1389           { |  | 
| 1390             var position = positions[j]; |  | 
| 1391             if (subscription.filters[position] == filter) |  | 
| 1392             { |  | 
| 1393               subscription.filters.splice(position, 1); |  | 
| 1394               if (subscription.filters.indexOf(filter) < 0) |  | 
| 1395               { |  | 
| 1396                 var index = filter.subscriptions.indexOf(subscription); |  | 
| 1397                 if (index >= 0) |  | 
| 1398                 { |  | 
| 1399                   filter.subscriptions.splice(index, 1); |  | 
| 1400                 } |  | 
| 1401               } |  | 
| 1402               FilterNotifier.triggerListeners("filter.removed", filter, subscrip
      tion, position); |  | 
| 1403             } |  | 
| 1404           } |  | 
| 1405         } |  | 
| 1406       } |  | 
| 1407     }, |  | 
| 1408     moveFilter: function(filter, subscription, oldPosition, newPosition) |  | 
| 1409     { |  | 
| 1410       if (!(subscription instanceof SpecialSubscription) || subscription.filters
      [oldPosition] != filter) |  | 
| 1411       { |  | 
| 1412         return; |  | 
| 1413       } |  | 
| 1414       newPosition = Math.min(Math.max(newPosition, 0), subscription.filters.leng
      th - 1); |  | 
| 1415       if (oldPosition == newPosition) |  | 
| 1416       { |  | 
| 1417         return; |  | 
| 1418       } |  | 
| 1419       subscription.filters.splice(oldPosition, 1); |  | 
| 1420       subscription.filters.splice(newPosition, 0, filter); |  | 
| 1421       FilterNotifier.triggerListeners("filter.moved", filter, subscription, oldP
      osition, newPosition); |  | 
| 1422     }, |  | 
| 1423     increaseHitCount: function(filter, wnd) |  | 
| 1424     { |  | 
| 1425       if (!Prefs.savestats || PrivateBrowsing.enabledForWindow(wnd) || PrivateBr
      owsing.enabled || !(filter instanceof ActiveFilter)) |  | 
| 1426       { |  | 
| 1427         return; |  | 
| 1428       } |  | 
| 1429       filter.hitCount++; |  | 
| 1430       filter.lastHit = Date.now(); |  | 
| 1431     }, |  | 
| 1432     resetHitCounts: function(filters) |  | 
| 1433     { |  | 
| 1434       if (!filters) |  | 
| 1435       { |  | 
| 1436         filters = []; |  | 
| 1437         for (var text in Filter.knownFilters) |  | 
| 1438         { |  | 
| 1439           filters.push(Filter.knownFilters[text]); |  | 
| 1440         } |  | 
| 1441       } |  | 
| 1442       for (var _loopIndex10 = 0; _loopIndex10 < filters.length; ++_loopIndex10) |  | 
| 1443       { |  | 
| 1444         var filter = filters[_loopIndex10]; |  | 
| 1445         filter.hitCount = 0; |  | 
| 1446         filter.lastHit = 0; |  | 
| 1447       } |  | 
| 1448     }, |  | 
| 1449     _loading: false, |  | 
| 1450     loadFromDisk: function(sourceFile) |  | 
| 1451     { |  | 
| 1452       if (this._loading) |  | 
| 1453       { |  | 
| 1454         return; |  | 
| 1455       } |  | 
| 1456       var readFile = function(sourceFile, backupIndex) |  | 
| 1457       { |  | 
| 1458         var parser = new INIParser(); |  | 
| 1459         IO.readFromFile(sourceFile, true, parser, function(e) |  | 
| 1460         { |  | 
| 1461           if (!e && parser.subscriptions.length == 0) |  | 
| 1462           { |  | 
| 1463             e = new Error("No data in the file"); |  | 
| 1464           } |  | 
| 1465           if (e) |  | 
| 1466           { |  | 
| 1467             Cu.reportError(e); |  | 
| 1468           } |  | 
| 1469           if (e && !explicitFile) |  | 
| 1470           { |  | 
| 1471             sourceFile = this.sourceFile; |  | 
| 1472             if (sourceFile) |  | 
| 1473             { |  | 
| 1474               var _tempVar11 = /^(.*)(\.\w+)$/.exec(sourceFile.leafName) || [nul
      l, sourceFile.leafName, ""]; |  | 
| 1475               var part1 = _tempVar11[1]; |  | 
| 1476               var part2 = _tempVar11[2]; |  | 
| 1477               sourceFile = sourceFile.clone(); |  | 
| 1478               sourceFile.leafName = part1 + "-backup" + ++backupIndex + part2; |  | 
| 1479               IO.statFile(sourceFile, function(e, statData) |  | 
| 1480               { |  | 
| 1481                 if (!e && statData.exists) |  | 
| 1482                 { |  | 
| 1483                   readFile(sourceFile, backupIndex); |  | 
| 1484                 } |  | 
| 1485                 else |  | 
| 1486                 { |  | 
| 1487                   doneReading(parser); |  | 
| 1488                 } |  | 
| 1489               }); |  | 
| 1490               return; |  | 
| 1491             } |  | 
| 1492           } |  | 
| 1493           doneReading(parser); |  | 
| 1494         }.bind(this), "FilterStorageRead"); |  | 
| 1495       }.bind(this); |  | 
| 1496       var doneReading = function(parser) |  | 
| 1497       { |  | 
| 1498         var specialMap = |  | 
| 1499         { |  | 
| 1500           "~il~": true, |  | 
| 1501           "~wl~": true, |  | 
| 1502           "~fl~": true, |  | 
| 1503           "~eh~": true |  | 
| 1504         }; |  | 
| 1505         var knownSubscriptions = |  | 
| 1506         { |  | 
| 1507           __proto__: null |  | 
| 1508         }; |  | 
| 1509         for (var i = 0; i < parser.subscriptions.length; i++) |  | 
| 1510         { |  | 
| 1511           var subscription = parser.subscriptions[i]; |  | 
| 1512           if (subscription instanceof SpecialSubscription && subscription.filter
      s.length == 0 && subscription.url in specialMap) |  | 
| 1513           { |  | 
| 1514             parser.subscriptions.splice(i--, 1); |  | 
| 1515           } |  | 
| 1516           else |  | 
| 1517           { |  | 
| 1518             knownSubscriptions[subscription.url] = subscription; |  | 
| 1519           } |  | 
| 1520         } |  | 
| 1521         this.fileProperties = parser.fileProperties; |  | 
| 1522         this.subscriptions = parser.subscriptions; |  | 
| 1523         this.knownSubscriptions = knownSubscriptions; |  | 
| 1524         Filter.knownFilters = parser.knownFilters; |  | 
| 1525         Subscription.knownSubscriptions = parser.knownSubscriptions; |  | 
| 1526         if (parser.userFilters) |  | 
| 1527         { |  | 
| 1528           for (var i = 0; i < parser.userFilters.length; i++) |  | 
| 1529           { |  | 
| 1530             var filter = Filter.fromText(parser.userFilters[i]); |  | 
| 1531             this.addFilter(filter, null, undefined, true); |  | 
| 1532           } |  | 
| 1533         } |  | 
| 1534         this._loading = false; |  | 
| 1535         FilterNotifier.triggerListeners("load"); |  | 
| 1536         if (sourceFile != this.sourceFile) |  | 
| 1537         { |  | 
| 1538           this.saveToDisk(); |  | 
| 1539         } |  | 
| 1540       }.bind(this); |  | 
| 1541       var startRead = function(file) |  | 
| 1542       { |  | 
| 1543         this._loading = true; |  | 
| 1544         readFile(file, 0); |  | 
| 1545       }.bind(this); |  | 
| 1546       var explicitFile; |  | 
| 1547       if (sourceFile) |  | 
| 1548       { |  | 
| 1549         explicitFile = true; |  | 
| 1550         startRead(sourceFile); |  | 
| 1551       } |  | 
| 1552       else |  | 
| 1553       { |  | 
| 1554         explicitFile = false; |  | 
| 1555         sourceFile = FilterStorage.sourceFile; |  | 
| 1556         var callback = function(e, statData) |  | 
| 1557         { |  | 
| 1558           if (e || !statData.exists) |  | 
| 1559           { |  | 
| 1560             var addonRoot = require("info").addonRoot; |  | 
| 1561             sourceFile = Services.io.newURI(addonRoot + "defaults/patterns.ini",
       null, null); |  | 
| 1562           } |  | 
| 1563           startRead(sourceFile); |  | 
| 1564         }; |  | 
| 1565         if (sourceFile) |  | 
| 1566         { |  | 
| 1567           IO.statFile(sourceFile, callback); |  | 
| 1568         } |  | 
| 1569         else |  | 
| 1570         { |  | 
| 1571           callback(true); |  | 
| 1572         } |  | 
| 1573       } |  | 
| 1574     }, |  | 
| 1575     _generateFilterData: function(subscriptions) |  | 
| 1576     { |  | 
| 1577       var _generatorResult12 = []; |  | 
| 1578       _generatorResult12.push("# Adblock Plus preferences"); |  | 
| 1579       _generatorResult12.push("version=" + formatVersion); |  | 
| 1580       var saved = |  | 
| 1581       { |  | 
| 1582         __proto__: null |  | 
| 1583       }; |  | 
| 1584       var buf = []; |  | 
| 1585       for (var i = 0; i < subscriptions.length; i++) |  | 
| 1586       { |  | 
| 1587         var subscription = subscriptions[i]; |  | 
| 1588         for (var j = 0; j < subscription.filters.length; j++) |  | 
| 1589         { |  | 
| 1590           var filter = subscription.filters[j]; |  | 
| 1591           if (!(filter.text in saved)) |  | 
| 1592           { |  | 
| 1593             filter.serialize(buf); |  | 
| 1594             saved[filter.text] = filter; |  | 
| 1595             for (var k = 0; k < buf.length; k++) |  | 
| 1596             { |  | 
| 1597               _generatorResult12.push(buf[k]); |  | 
| 1598             } |  | 
| 1599             buf.splice(0); |  | 
| 1600           } |  | 
| 1601         } |  | 
| 1602       } |  | 
| 1603       for (var i = 0; i < subscriptions.length; i++) |  | 
| 1604       { |  | 
| 1605         var subscription = subscriptions[i]; |  | 
| 1606         _generatorResult12.push(""); |  | 
| 1607         subscription.serialize(buf); |  | 
| 1608         if (subscription.filters.length) |  | 
| 1609         { |  | 
| 1610           buf.push("", "[Subscription filters]"); |  | 
| 1611           subscription.serializeFilters(buf); |  | 
| 1612         } |  | 
| 1613         for (var k = 0; k < buf.length; k++) |  | 
| 1614         { |  | 
| 1615           _generatorResult12.push(buf[k]); |  | 
| 1616         } |  | 
| 1617         buf.splice(0); |  | 
| 1618       } |  | 
| 1619       return _generatorResult12; |  | 
| 1620     }, |  | 
| 1621     _saving: false, |  | 
| 1622     _needsSave: false, |  | 
| 1623     saveToDisk: function(targetFile) |  | 
| 1624     { |  | 
| 1625       var explicitFile = true; |  | 
| 1626       if (!targetFile) |  | 
| 1627       { |  | 
| 1628         targetFile = FilterStorage.sourceFile; |  | 
| 1629         explicitFile = false; |  | 
| 1630       } |  | 
| 1631       if (!targetFile) |  | 
| 1632       { |  | 
| 1633         return; |  | 
| 1634       } |  | 
| 1635       if (!explicitFile && this._saving) |  | 
| 1636       { |  | 
| 1637         this._needsSave = true; |  | 
| 1638         return; |  | 
| 1639       } |  | 
| 1640       try |  | 
| 1641       { |  | 
| 1642         targetFile.parent.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRE
      CTORY); |  | 
| 1643       } |  | 
| 1644       catch (e){} |  | 
| 1645       var writeFilters = function() |  | 
| 1646       { |  | 
| 1647         IO.writeToFile(targetFile, true, this._generateFilterData(subscriptions)
      , function(e) |  | 
| 1648         { |  | 
| 1649           if (!explicitFile) |  | 
| 1650           { |  | 
| 1651             this._saving = false; |  | 
| 1652           } |  | 
| 1653           if (e) |  | 
| 1654           { |  | 
| 1655             Cu.reportError(e); |  | 
| 1656           } |  | 
| 1657           if (!explicitFile && this._needsSave) |  | 
| 1658           { |  | 
| 1659             this._needsSave = false; |  | 
| 1660             this.saveToDisk(); |  | 
| 1661           } |  | 
| 1662           else |  | 
| 1663           { |  | 
| 1664             FilterNotifier.triggerListeners("save"); |  | 
| 1665           } |  | 
| 1666         }.bind(this), "FilterStorageWrite"); |  | 
| 1667       }.bind(this); |  | 
| 1668       var checkBackupRequired = function(callbackNotRequired, callbackRequired) |  | 
| 1669       { |  | 
| 1670         if (explicitFile || Prefs.patternsbackups <= 0) |  | 
| 1671         { |  | 
| 1672           callbackNotRequired(); |  | 
| 1673         } |  | 
| 1674         else |  | 
| 1675         { |  | 
| 1676           IO.statFile(targetFile, function(e, statData) |  | 
| 1677           { |  | 
| 1678             if (e || !statData.exists) |  | 
| 1679             { |  | 
| 1680               callbackNotRequired(); |  | 
| 1681             } |  | 
| 1682             else |  | 
| 1683             { |  | 
| 1684               var _tempVar13 = /^(.*)(\.\w+)$/.exec(targetFile.leafName) || [nul
      l, targetFile.leafName, ""]; |  | 
| 1685               var part1 = _tempVar13[1]; |  | 
| 1686               var part2 = _tempVar13[2]; |  | 
| 1687               var newestBackup = targetFile.clone(); |  | 
| 1688               newestBackup.leafName = part1 + "-backup1" + part2; |  | 
| 1689               IO.statFile(newestBackup, function(e, statData) |  | 
| 1690               { |  | 
| 1691                 if (!e && (!statData.exists || (Date.now() - statData.lastModifi
      ed) / 3600000 >= Prefs.patternsbackupinterval)) |  | 
| 1692                 { |  | 
| 1693                   callbackRequired(part1, part2); |  | 
| 1694                 } |  | 
| 1695                 else |  | 
| 1696                 { |  | 
| 1697                   callbackNotRequired(); |  | 
| 1698                 } |  | 
| 1699               }); |  | 
| 1700             } |  | 
| 1701           }); |  | 
| 1702         } |  | 
| 1703       }.bind(this); |  | 
| 1704       var removeLastBackup = function(part1, part2) |  | 
| 1705       { |  | 
| 1706         var file = targetFile.clone(); |  | 
| 1707         file.leafName = part1 + "-backup" + Prefs.patternsbackups + part2; |  | 
| 1708         IO.removeFile(file, function(e) |  | 
| 1709         { |  | 
| 1710           return renameBackup(part1, part2, Prefs.patternsbackups - 1); |  | 
| 1711         }); |  | 
| 1712       }.bind(this); |  | 
| 1713       var renameBackup = function(part1, part2, index) |  | 
| 1714       { |  | 
| 1715         if (index > 0) |  | 
| 1716         { |  | 
| 1717           var fromFile = targetFile.clone(); |  | 
| 1718           fromFile.leafName = part1 + "-backup" + index + part2; |  | 
| 1719           var toName = part1 + "-backup" + (index + 1) + part2; |  | 
| 1720           IO.renameFile(fromFile, toName, function(e) |  | 
| 1721           { |  | 
| 1722             return renameBackup(part1, part2, index - 1); |  | 
| 1723           }); |  | 
| 1724         } |  | 
| 1725         else |  | 
| 1726         { |  | 
| 1727           var toFile = targetFile.clone(); |  | 
| 1728           toFile.leafName = part1 + "-backup" + (index + 1) + part2; |  | 
| 1729           IO.copyFile(targetFile, toFile, writeFilters); |  | 
| 1730         } |  | 
| 1731       }.bind(this); |  | 
| 1732       var subscriptions = this.subscriptions.filter(function(s) |  | 
| 1733       { |  | 
| 1734         return !(s instanceof ExternalSubscription); |  | 
| 1735       }); |  | 
| 1736       if (!explicitFile) |  | 
| 1737       { |  | 
| 1738         this._saving = true; |  | 
| 1739       } |  | 
| 1740       checkBackupRequired(writeFilters, removeLastBackup); |  | 
| 1741     }, |  | 
| 1742     getBackupFiles: function() |  | 
| 1743     { |  | 
| 1744       var result = []; |  | 
| 1745       var _tempVar14 = /^(.*)(\.\w+)$/.exec(FilterStorage.sourceFile.leafName) |
      | [null, FilterStorage.sourceFile.leafName, ""]; |  | 
| 1746       var part1 = _tempVar14[1]; |  | 
| 1747       var part2 = _tempVar14[2]; |  | 
| 1748       for (var i = 1;; i++) |  | 
| 1749       { |  | 
| 1750         var file = FilterStorage.sourceFile.clone(); |  | 
| 1751         file.leafName = part1 + "-backup" + i + part2; |  | 
| 1752         if (file.exists()) |  | 
| 1753         { |  | 
| 1754           result.push(file); |  | 
| 1755         } |  | 
| 1756         else |  | 
| 1757         { |  | 
| 1758           break; |  | 
| 1759         } |  | 
| 1760       } |  | 
| 1761       return result; |  | 
| 1762     } |  | 
| 1763   }; |  | 
| 1764 |  | 
| 1765   function addSubscriptionFilters(subscription) |  | 
| 1766   { |  | 
| 1767     if (!(subscription.url in FilterStorage.knownSubscriptions)) |  | 
| 1768     { |  | 
| 1769       return; |  | 
| 1770     } |  | 
| 1771     for (var _loopIndex15 = 0; _loopIndex15 < subscription.filters.length; ++_lo
      opIndex15) |  | 
| 1772     { |  | 
| 1773       var filter = subscription.filters[_loopIndex15]; |  | 
| 1774       filter.subscriptions.push(subscription); |  | 
| 1775     } |  | 
| 1776   } |  | 
| 1777 |  | 
| 1778   function removeSubscriptionFilters(subscription) |  | 
| 1779   { |  | 
| 1780     if (!(subscription.url in FilterStorage.knownSubscriptions)) |  | 
| 1781     { |  | 
| 1782       return; |  | 
| 1783     } |  | 
| 1784     for (var _loopIndex16 = 0; _loopIndex16 < subscription.filters.length; ++_lo
      opIndex16) |  | 
| 1785     { |  | 
| 1786       var filter = subscription.filters[_loopIndex16]; |  | 
| 1787       var i = filter.subscriptions.indexOf(subscription); |  | 
| 1788       if (i >= 0) |  | 
| 1789       { |  | 
| 1790         filter.subscriptions.splice(i, 1); |  | 
| 1791       } |  | 
| 1792     } |  | 
| 1793   } |  | 
| 1794   var PrivateBrowsing = exports.PrivateBrowsing = |  | 
| 1795   { |  | 
| 1796     enabled: false, |  | 
| 1797     enabledForWindow: function(wnd) |  | 
| 1798     { |  | 
| 1799       try |  | 
| 1800       { |  | 
| 1801         return wnd.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIL
      oadContext).usePrivateBrowsing; |  | 
| 1802       } |  | 
| 1803       catch (e) |  | 
| 1804       { |  | 
| 1805         if (e.result != Cr.NS_NOINTERFACE) |  | 
| 1806         { |  | 
| 1807           Cu.reportError(e); |  | 
| 1808         } |  | 
| 1809         return false; |  | 
| 1810       } |  | 
| 1811     }, |  | 
| 1812     init: function() |  | 
| 1813     { |  | 
| 1814       if ("@mozilla.org/privatebrowsing;1" in Cc) |  | 
| 1815       { |  | 
| 1816         try |  | 
| 1817         { |  | 
| 1818           this.enabled = Cc["@mozilla.org/privatebrowsing;1"].getService(Ci.nsIP
      rivateBrowsingService).privateBrowsingEnabled; |  | 
| 1819           Services.obs.addObserver(this, "private-browsing", true); |  | 
| 1820           onShutdown.add(function() |  | 
| 1821           { |  | 
| 1822             Services.obs.removeObserver(this, "private-browsing"); |  | 
| 1823           }.bind(this)); |  | 
| 1824         } |  | 
| 1825         catch (e) |  | 
| 1826         { |  | 
| 1827           Cu.reportError(e); |  | 
| 1828         } |  | 
| 1829       } |  | 
| 1830     }, |  | 
| 1831     observe: function(subject, topic, data) |  | 
| 1832     { |  | 
| 1833       if (topic == "private-browsing") |  | 
| 1834       { |  | 
| 1835         if (data == "enter") |  | 
| 1836         { |  | 
| 1837           this.enabled = true; |  | 
| 1838         } |  | 
| 1839         else if (data == "exit") |  | 
| 1840         { |  | 
| 1841           this.enabled = false; |  | 
| 1842         } |  | 
| 1843       } |  | 
| 1844     }, |  | 
| 1845     QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference, Ci.nsIOb
      server]) |  | 
| 1846   }; |  | 
| 1847   PrivateBrowsing.init(); |  | 
| 1848 |  | 
| 1849   function INIParser() |  | 
| 1850   { |  | 
| 1851     this.fileProperties = this.curObj = {}; |  | 
| 1852     this.subscriptions = []; |  | 
| 1853     this.knownFilters = |  | 
| 1854     { |  | 
| 1855       __proto__: null |  | 
| 1856     }; |  | 
| 1857     this.knownSubscriptions = |  | 
| 1858     { |  | 
| 1859       __proto__: null |  | 
| 1860     }; |  | 
| 1861   } |  | 
| 1862   INIParser.prototype = |  | 
| 1863   { |  | 
| 1864     subscriptions: null, |  | 
| 1865     knownFilters: null, |  | 
| 1866     knownSubscrptions: null, |  | 
| 1867     wantObj: true, |  | 
| 1868     fileProperties: null, |  | 
| 1869     curObj: null, |  | 
| 1870     curSection: null, |  | 
| 1871     userFilters: null, |  | 
| 1872     process: function(val) |  | 
| 1873     { |  | 
| 1874       var origKnownFilters = Filter.knownFilters; |  | 
| 1875       Filter.knownFilters = this.knownFilters; |  | 
| 1876       var origKnownSubscriptions = Subscription.knownSubscriptions; |  | 
| 1877       Subscription.knownSubscriptions = this.knownSubscriptions; |  | 
| 1878       var match; |  | 
| 1879       try |  | 
| 1880       { |  | 
| 1881         if (this.wantObj === true && (match = /^(\w+)=(.*)$/.exec(val))) |  | 
| 1882         { |  | 
| 1883           this.curObj[match[1]] = match[2]; |  | 
| 1884         } |  | 
| 1885         else if (val === null || (match = /^\s*\[(.+)\]\s*$/.exec(val))) |  | 
| 1886         { |  | 
| 1887           if (this.curObj) |  | 
| 1888           { |  | 
| 1889             switch (this.curSection) |  | 
| 1890             { |  | 
| 1891             case "filter": |  | 
| 1892             case "pattern": |  | 
| 1893               if ("text" in this.curObj) |  | 
| 1894               { |  | 
| 1895                 Filter.fromObject(this.curObj); |  | 
| 1896               } |  | 
| 1897               break; |  | 
| 1898             case "subscription": |  | 
| 1899               var subscription = Subscription.fromObject(this.curObj); |  | 
| 1900               if (subscription) |  | 
| 1901               { |  | 
| 1902                 this.subscriptions.push(subscription); |  | 
| 1903               } |  | 
| 1904               break; |  | 
| 1905             case "subscription filters": |  | 
| 1906             case "subscription patterns": |  | 
| 1907               if (this.subscriptions.length) |  | 
| 1908               { |  | 
| 1909                 var subscription = this.subscriptions[this.subscriptions.length 
      - 1]; |  | 
| 1910                 for (var _loopIndex17 = 0; _loopIndex17 < this.curObj.length; ++
      _loopIndex17) |  | 
| 1911                 { |  | 
| 1912                   var text = this.curObj[_loopIndex17]; |  | 
| 1913                   var filter = Filter.fromText(text); |  | 
| 1914                   subscription.filters.push(filter); |  | 
| 1915                   filter.subscriptions.push(subscription); |  | 
| 1916                 } |  | 
| 1917               } |  | 
| 1918               break; |  | 
| 1919             case "user patterns": |  | 
| 1920               this.userFilters = this.curObj; |  | 
| 1921               break; |  | 
| 1922             } |  | 
| 1923           } |  | 
| 1924           if (val === null) |  | 
| 1925           { |  | 
| 1926             return; |  | 
| 1927           } |  | 
| 1928           this.curSection = match[1].toLowerCase(); |  | 
| 1929           switch (this.curSection) |  | 
| 1930           { |  | 
| 1931           case "filter": |  | 
| 1932           case "pattern": |  | 
| 1933           case "subscription": |  | 
| 1934             this.wantObj = true; |  | 
| 1935             this.curObj = {}; |  | 
| 1936             break; |  | 
| 1937           case "subscription filters": |  | 
| 1938           case "subscription patterns": |  | 
| 1939           case "user patterns": |  | 
| 1940             this.wantObj = false; |  | 
| 1941             this.curObj = []; |  | 
| 1942             break; |  | 
| 1943           default: |  | 
| 1944             this.wantObj = undefined; |  | 
| 1945             this.curObj = null; |  | 
| 1946           } |  | 
| 1947         } |  | 
| 1948         else if (this.wantObj === false && val) |  | 
| 1949         { |  | 
| 1950           this.curObj.push(val.replace(/\\\[/g, "[")); |  | 
| 1951         } |  | 
| 1952       } |  | 
| 1953       finally |  | 
| 1954       { |  | 
| 1955         Filter.knownFilters = origKnownFilters; |  | 
| 1956         Subscription.knownSubscriptions = origKnownSubscriptions; |  | 
| 1957       } |  | 
| 1958     } |  | 
| 1959   }; |  | 
| 1960   return exports; |  | 
| 1961 })(); |  | 
| 1962 require.scopes["elemHide"] = (function() |  | 
| 1963 { |  | 
| 1964   var exports = {}; |  | 
| 1965   var Utils = require("utils").Utils; |  | 
| 1966   var IO = require("io").IO; |  | 
| 1967   var Prefs = require("prefs").Prefs; |  | 
| 1968   var ElemHideException = require("filterClasses").ElemHideException; |  | 
| 1969   var FilterNotifier = require("filterNotifier").FilterNotifier; |  | 
| 1970   var AboutHandler = require("elemHideHitRegistration").AboutHandler; |  | 
| 1971   var filterByKey = |  | 
| 1972   { |  | 
| 1973     __proto__: null |  | 
| 1974   }; |  | 
| 1975   var keyByFilter = |  | 
| 1976   { |  | 
| 1977     __proto__: null |  | 
| 1978   }; |  | 
| 1979   var knownExceptions = |  | 
| 1980   { |  | 
| 1981     __proto__: null |  | 
| 1982   }; |  | 
| 1983   var exceptions = |  | 
| 1984   { |  | 
| 1985     __proto__: null |  | 
| 1986   }; |  | 
| 1987   var styleURL = null; |  | 
| 1988   var ElemHide = exports.ElemHide = |  | 
| 1989   { |  | 
| 1990     isDirty: false, |  | 
| 1991     applied: false, |  | 
| 1992     init: function() |  | 
| 1993     { |  | 
| 1994       Prefs.addListener(function(name) |  | 
| 1995       { |  | 
| 1996         if (name == "enabled") |  | 
| 1997         { |  | 
| 1998           ElemHide.apply(); |  | 
| 1999         } |  | 
| 2000       }); |  | 
| 2001       onShutdown.add(function() |  | 
| 2002       { |  | 
| 2003         ElemHide.unapply(); |  | 
| 2004       }); |  | 
| 2005       var styleFile = IO.resolveFilePath(Prefs.data_directory); |  | 
| 2006       styleFile.append("elemhide.css"); |  | 
| 2007       styleURL = Services.io.newFileURI(styleFile).QueryInterface(Ci.nsIFileURL)
      ; |  | 
| 2008     }, |  | 
| 2009     clear: function() |  | 
| 2010     { |  | 
| 2011       filterByKey = |  | 
| 2012       { |  | 
| 2013         __proto__: null |  | 
| 2014       }; |  | 
| 2015       keyByFilter = |  | 
| 2016       { |  | 
| 2017         __proto__: null |  | 
| 2018       }; |  | 
| 2019       knownExceptions = |  | 
| 2020       { |  | 
| 2021         __proto__: null |  | 
| 2022       }; |  | 
| 2023       exceptions = |  | 
| 2024       { |  | 
| 2025         __proto__: null |  | 
| 2026       }; |  | 
| 2027       ElemHide.isDirty = false; |  | 
| 2028       ElemHide.unapply(); |  | 
| 2029     }, |  | 
| 2030     add: function(filter) |  | 
| 2031     { |  | 
| 2032       if (filter instanceof ElemHideException) |  | 
| 2033       { |  | 
| 2034         if (filter.text in knownExceptions) |  | 
| 2035         { |  | 
| 2036           return; |  | 
| 2037         } |  | 
| 2038         var selector = filter.selector; |  | 
| 2039         if (!(selector in exceptions)) |  | 
| 2040         { |  | 
| 2041           exceptions[selector] = []; |  | 
| 2042         } |  | 
| 2043         exceptions[selector].push(filter); |  | 
| 2044         knownExceptions[filter.text] = true; |  | 
| 2045       } |  | 
| 2046       else |  | 
| 2047       { |  | 
| 2048         if (filter.text in keyByFilter) |  | 
| 2049         { |  | 
| 2050           return; |  | 
| 2051         } |  | 
| 2052         var key; |  | 
| 2053         do |  | 
| 2054         { |  | 
| 2055           key = Math.random().toFixed(15).substr(5); |  | 
| 2056         } |  | 
| 2057         while (key in filterByKey); |  | 
| 2058         filterByKey[key] = filter; |  | 
| 2059         keyByFilter[filter.text] = key; |  | 
| 2060         ElemHide.isDirty = true; |  | 
| 2061       } |  | 
| 2062     }, |  | 
| 2063     remove: function(filter) |  | 
| 2064     { |  | 
| 2065       if (filter instanceof ElemHideException) |  | 
| 2066       { |  | 
| 2067         if (!(filter.text in knownExceptions)) |  | 
| 2068         { |  | 
| 2069           return; |  | 
| 2070         } |  | 
| 2071         var list = exceptions[filter.selector]; |  | 
| 2072         var index = list.indexOf(filter); |  | 
| 2073         if (index >= 0) |  | 
| 2074         { |  | 
| 2075           list.splice(index, 1); |  | 
| 2076         } |  | 
| 2077         delete knownExceptions[filter.text]; |  | 
| 2078       } |  | 
| 2079       else |  | 
| 2080       { |  | 
| 2081         if (!(filter.text in keyByFilter)) |  | 
| 2082         { |  | 
| 2083           return; |  | 
| 2084         } |  | 
| 2085         var key = keyByFilter[filter.text]; |  | 
| 2086         delete filterByKey[key]; |  | 
| 2087         delete keyByFilter[filter.text]; |  | 
| 2088         ElemHide.isDirty = true; |  | 
| 2089       } |  | 
| 2090     }, |  | 
| 2091     getException: function(filter, docDomain) |  | 
| 2092     { |  | 
| 2093       var selector = filter.selector; |  | 
| 2094       if (!(filter.selector in exceptions)) |  | 
| 2095       { |  | 
| 2096         return null; |  | 
| 2097       } |  | 
| 2098       var list = exceptions[filter.selector]; |  | 
| 2099       for (var i = list.length - 1; i >= 0; i--) |  | 
| 2100       { |  | 
| 2101         if (list[i].isActiveOnDomain(docDomain)) |  | 
| 2102         { |  | 
| 2103           return list[i]; |  | 
| 2104         } |  | 
| 2105       } |  | 
| 2106       return null; |  | 
| 2107     }, |  | 
| 2108     _applying: false, |  | 
| 2109     _needsApply: false, |  | 
| 2110     apply: function() |  | 
| 2111     { |  | 
| 2112       if (this._applying) |  | 
| 2113       { |  | 
| 2114         this._needsApply = true; |  | 
| 2115         return; |  | 
| 2116       } |  | 
| 2117       if (!ElemHide.isDirty || !Prefs.enabled) |  | 
| 2118       { |  | 
| 2119         if (Prefs.enabled && !ElemHide.applied) |  | 
| 2120         { |  | 
| 2121           try |  | 
| 2122           { |  | 
| 2123             Utils.styleService.loadAndRegisterSheet(styleURL, Ci.nsIStyleSheetSe
      rvice.USER_SHEET); |  | 
| 2124             ElemHide.applied = true; |  | 
| 2125           } |  | 
| 2126           catch (e) |  | 
| 2127           { |  | 
| 2128             Cu.reportError(e); |  | 
| 2129           } |  | 
| 2130         } |  | 
| 2131         else if (!Prefs.enabled && ElemHide.applied) |  | 
| 2132         { |  | 
| 2133           ElemHide.unapply(); |  | 
| 2134         } |  | 
| 2135         return; |  | 
| 2136       } |  | 
| 2137       IO.writeToFile(styleURL.file, false, this._generateCSSContent(), function(
      e) |  | 
| 2138       { |  | 
| 2139         this._applying = false; |  | 
| 2140         if (e && e.result == Cr.NS_ERROR_NOT_AVAILABLE) |  | 
| 2141         { |  | 
| 2142           IO.removeFile(styleURL.file, function(e2){}); |  | 
| 2143         } |  | 
| 2144         else if (e) |  | 
| 2145         { |  | 
| 2146           Cu.reportError(e); |  | 
| 2147         } |  | 
| 2148         if (this._needsApply) |  | 
| 2149         { |  | 
| 2150           this._needsApply = false; |  | 
| 2151           this.apply(); |  | 
| 2152         } |  | 
| 2153         else if (!e || e.result == Cr.NS_ERROR_NOT_AVAILABLE) |  | 
| 2154         { |  | 
| 2155           ElemHide.isDirty = false; |  | 
| 2156           ElemHide.unapply(); |  | 
| 2157           if (!e) |  | 
| 2158           { |  | 
| 2159             try |  | 
| 2160             { |  | 
| 2161               Utils.styleService.loadAndRegisterSheet(styleURL, Ci.nsIStyleSheet
      Service.USER_SHEET); |  | 
| 2162               ElemHide.applied = true; |  | 
| 2163             } |  | 
| 2164             catch (e) |  | 
| 2165             { |  | 
| 2166               Cu.reportError(e); |  | 
| 2167             } |  | 
| 2168           } |  | 
| 2169           FilterNotifier.triggerListeners("elemhideupdate"); |  | 
| 2170         } |  | 
| 2171       }.bind(this), "ElemHideWrite"); |  | 
| 2172       this._applying = true; |  | 
| 2173     }, |  | 
| 2174     _generateCSSContent: function() |  | 
| 2175     { |  | 
| 2176       var _generatorResult12 = []; |  | 
| 2177       var domains = |  | 
| 2178       { |  | 
| 2179         __proto__: null |  | 
| 2180       }; |  | 
| 2181       var hasFilters = false; |  | 
| 2182       for (var key in filterByKey) |  | 
| 2183       { |  | 
| 2184         var filter = filterByKey[key]; |  | 
| 2185         var domain = filter.selectorDomain || ""; |  | 
| 2186         var list; |  | 
| 2187         if (domain in domains) |  | 
| 2188         { |  | 
| 2189           list = domains[domain]; |  | 
| 2190         } |  | 
| 2191         else |  | 
| 2192         { |  | 
| 2193           list = |  | 
| 2194           { |  | 
| 2195             __proto__: null |  | 
| 2196           }; |  | 
| 2197           domains[domain] = list; |  | 
| 2198         } |  | 
| 2199         list[filter.selector] = key; |  | 
| 2200         hasFilters = true; |  | 
| 2201       } |  | 
| 2202       if (!hasFilters) |  | 
| 2203       { |  | 
| 2204         throw Cr.NS_ERROR_NOT_AVAILABLE; |  | 
| 2205       } |  | 
| 2206 |  | 
| 2207       function escapeChar(match) |  | 
| 2208       { |  | 
| 2209         return "\\" + match.charCodeAt(0).toString(16) + " "; |  | 
| 2210       } |  | 
| 2211       var cssTemplate = "-moz-binding: url(about:" + AboutHandler.aboutPrefix + 
      "?%ID%#dummy) !important;"; |  | 
| 2212       for (var domain in domains) |  | 
| 2213       { |  | 
| 2214         var rules = []; |  | 
| 2215         var list = domains[domain]; |  | 
| 2216         if (domain) |  | 
| 2217         { |  | 
| 2218           _generatorResult12.push(("@-moz-document domain(\"" + domain.split(","
      ).join("\"),domain(\"") + "\"){").replace(/[^\x01-\x7F]/g, escapeChar)); |  | 
| 2219         } |  | 
| 2220         else |  | 
| 2221         { |  | 
| 2222           _generatorResult12.push("@-moz-document url-prefix(\"http://\"),url-pr
      efix(\"https://\")," + "url-prefix(\"mailbox://\"),url-prefix(\"imap://\")," + "
      url-prefix(\"news://\"),url-prefix(\"snews://\"){"); |  | 
| 2223         } |  | 
| 2224         for (var selector in list) |  | 
| 2225         { |  | 
| 2226           _generatorResult12.push(selector.replace(/[^\x01-\x7F]/g, escapeChar) 
      + "{" + cssTemplate.replace("%ID%", list[selector]) + "}"); |  | 
| 2227         } |  | 
| 2228         _generatorResult12.push("}"); |  | 
| 2229       } |  | 
| 2230       return _generatorResult12; |  | 
| 2231     }, |  | 
| 2232     unapply: function() |  | 
| 2233     { |  | 
| 2234       if (ElemHide.applied) |  | 
| 2235       { |  | 
| 2236         try |  | 
| 2237         { |  | 
| 2238           Utils.styleService.unregisterSheet(styleURL, Ci.nsIStyleSheetService.U
      SER_SHEET); |  | 
| 2239         } |  | 
| 2240         catch (e) |  | 
| 2241         { |  | 
| 2242           Cu.reportError(e); |  | 
| 2243         } |  | 
| 2244         ElemHide.applied = false; |  | 
| 2245       } |  | 
| 2246     }, |  | 
| 2247     get styleURL() |  | 
| 2248     { |  | 
| 2249       return ElemHide.applied ? styleURL.spec : null; |  | 
| 2250     }, |  | 
| 2251     getFilterByKey: function(key) |  | 
| 2252     { |  | 
| 2253       return key in filterByKey ? filterByKey[key] : null; |  | 
| 2254     }, |  | 
| 2255     getSelectorsForDomain: function(domain, specificOnly) |  | 
| 2256     { |  | 
| 2257       var result = []; |  | 
| 2258       for (var key in filterByKey) |  | 
| 2259       { |  | 
| 2260         var filter = filterByKey[key]; |  | 
| 2261         if (specificOnly && (!filter.domains || filter.domains[""])) |  | 
| 2262         { |  | 
| 2263           continue; |  | 
| 2264         } |  | 
| 2265         if (filter.isActiveOnDomain(domain) && !this.getException(filter, domain
      )) |  | 
| 2266         { |  | 
| 2267           result.push(filter.selector); |  | 
| 2268         } |  | 
| 2269       } |  | 
| 2270       return result; |  | 
| 2271     } |  | 
| 2272   }; |  | 
| 2273   return exports; |  | 
| 2274 })(); |  | 
| 2275 require.scopes["matcher"] = (function() |  | 
| 2276 { |  | 
| 2277   var exports = {}; |  | 
| 2278   var _tempVar18 = require("filterClasses"); |  | 
| 2279   var Filter = _tempVar18.Filter; |  | 
| 2280   var RegExpFilter = _tempVar18.RegExpFilter; |  | 
| 2281   var WhitelistFilter = _tempVar18.WhitelistFilter; |  | 
| 2282 |  | 
| 2283   function Matcher() |  | 
| 2284   { |  | 
| 2285     this.clear(); |  | 
| 2286   } |  | 
| 2287   exports.Matcher = Matcher; |  | 
| 2288   Matcher.prototype = |  | 
| 2289   { |  | 
| 2290     filterByKeyword: null, |  | 
| 2291     keywordByFilter: null, |  | 
| 2292     clear: function() |  | 
| 2293     { |  | 
| 2294       this.filterByKeyword = |  | 
| 2295       { |  | 
| 2296         __proto__: null |  | 
| 2297       }; |  | 
| 2298       this.keywordByFilter = |  | 
| 2299       { |  | 
| 2300         __proto__: null |  | 
| 2301       }; |  | 
| 2302     }, |  | 
| 2303     add: function(filter) |  | 
| 2304     { |  | 
| 2305       if (filter.text in this.keywordByFilter) |  | 
| 2306       { |  | 
| 2307         return; |  | 
| 2308       } |  | 
| 2309       var keyword = this.findKeyword(filter); |  | 
| 2310       var oldEntry = this.filterByKeyword[keyword]; |  | 
| 2311       if (typeof oldEntry == "undefined") |  | 
| 2312       { |  | 
| 2313         this.filterByKeyword[keyword] = filter; |  | 
| 2314       } |  | 
| 2315       else if (oldEntry.length == 1) |  | 
| 2316       { |  | 
| 2317         this.filterByKeyword[keyword] = [oldEntry, filter]; |  | 
| 2318       } |  | 
| 2319       else |  | 
| 2320       { |  | 
| 2321         oldEntry.push(filter); |  | 
| 2322       } |  | 
| 2323       this.keywordByFilter[filter.text] = keyword; |  | 
| 2324     }, |  | 
| 2325     remove: function(filter) |  | 
| 2326     { |  | 
| 2327       if (!(filter.text in this.keywordByFilter)) |  | 
| 2328       { |  | 
| 2329         return; |  | 
| 2330       } |  | 
| 2331       var keyword = this.keywordByFilter[filter.text]; |  | 
| 2332       var list = this.filterByKeyword[keyword]; |  | 
| 2333       if (list.length <= 1) |  | 
| 2334       { |  | 
| 2335         delete this.filterByKeyword[keyword]; |  | 
| 2336       } |  | 
| 2337       else |  | 
| 2338       { |  | 
| 2339         var index = list.indexOf(filter); |  | 
| 2340         if (index >= 0) |  | 
| 2341         { |  | 
| 2342           list.splice(index, 1); |  | 
| 2343           if (list.length == 1) |  | 
| 2344           { |  | 
| 2345             this.filterByKeyword[keyword] = list[0]; |  | 
| 2346           } |  | 
| 2347         } |  | 
| 2348       } |  | 
| 2349       delete this.keywordByFilter[filter.text]; |  | 
| 2350     }, |  | 
| 2351     findKeyword: function(filter) |  | 
| 2352     { |  | 
| 2353       var result = ""; |  | 
| 2354       var text = filter.text; |  | 
| 2355       if (Filter.regexpRegExp.test(text)) |  | 
| 2356       { |  | 
| 2357         return result; |  | 
| 2358       } |  | 
| 2359       var match = Filter.optionsRegExp.exec(text); |  | 
| 2360       if (match) |  | 
| 2361       { |  | 
| 2362         text = match.input.substr(0, match.index); |  | 
| 2363       } |  | 
| 2364       if (text.substr(0, 2) == "@@") |  | 
| 2365       { |  | 
| 2366         text = text.substr(2); |  | 
| 2367       } |  | 
| 2368       var candidates = text.toLowerCase().match(/[^a-z0-9%*][a-z0-9%]{3,}(?=[^a-
      z0-9%*])/g); |  | 
| 2369       if (!candidates) |  | 
| 2370       { |  | 
| 2371         return result; |  | 
| 2372       } |  | 
| 2373       var hash = this.filterByKeyword; |  | 
| 2374       var resultCount = 16777215; |  | 
| 2375       var resultLength = 0; |  | 
| 2376       for (var i = 0, l = candidates.length; i < l; i++) |  | 
| 2377       { |  | 
| 2378         var candidate = candidates[i].substr(1); |  | 
| 2379         var count = candidate in hash ? hash[candidate].length : 0; |  | 
| 2380         if (count < resultCount || count == resultCount && candidate.length > re
      sultLength) |  | 
| 2381         { |  | 
| 2382           result = candidate; |  | 
| 2383           resultCount = count; |  | 
| 2384           resultLength = candidate.length; |  | 
| 2385         } |  | 
| 2386       } |  | 
| 2387       return result; |  | 
| 2388     }, |  | 
| 2389     hasFilter: function(filter) |  | 
| 2390     { |  | 
| 2391       return filter.text in this.keywordByFilter; |  | 
| 2392     }, |  | 
| 2393     getKeywordForFilter: function(filter) |  | 
| 2394     { |  | 
| 2395       if (filter.text in this.keywordByFilter) |  | 
| 2396       { |  | 
| 2397         return this.keywordByFilter[filter.text]; |  | 
| 2398       } |  | 
| 2399       else |  | 
| 2400       { |  | 
| 2401         return null; |  | 
| 2402       } |  | 
| 2403     }, |  | 
| 2404     _checkEntryMatch: function(keyword, location, contentType, docDomain, thirdP
      arty) |  | 
| 2405     { |  | 
| 2406       var list = this.filterByKeyword[keyword]; |  | 
| 2407       for (var i = 0; i < list.length; i++) |  | 
| 2408       { |  | 
| 2409         var filter = list[i]; |  | 
| 2410         if (filter.matches(location, contentType, docDomain, thirdParty)) |  | 
| 2411         { |  | 
| 2412           return filter; |  | 
| 2413         } |  | 
| 2414       } |  | 
| 2415       return null; |  | 
| 2416     }, |  | 
| 2417     matchesAny: function(location, contentType, docDomain, thirdParty) |  | 
| 2418     { |  | 
| 2419       var candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g); |  | 
| 2420       if (candidates === null) |  | 
| 2421       { |  | 
| 2422         candidates = []; |  | 
| 2423       } |  | 
| 2424       candidates.push(""); |  | 
| 2425       for (var i = 0, l = candidates.length; i < l; i++) |  | 
| 2426       { |  | 
| 2427         var substr = candidates[i]; |  | 
| 2428         if (substr in this.filterByKeyword) |  | 
| 2429         { |  | 
| 2430           var result = this._checkEntryMatch(substr, location, contentType, docD
      omain, thirdParty); |  | 
| 2431           if (result) |  | 
| 2432           { |  | 
| 2433             return result; |  | 
| 2434           } |  | 
| 2435         } |  | 
| 2436       } |  | 
| 2437       return null; |  | 
| 2438     } |  | 
| 2439   }; |  | 
| 2440 |  | 
| 2441   function CombinedMatcher() |  | 
| 2442   { |  | 
| 2443     this.blacklist = new Matcher(); |  | 
| 2444     this.whitelist = new Matcher(); |  | 
| 2445     this.keys = |  | 
| 2446     { |  | 
| 2447       __proto__: null |  | 
| 2448     }; |  | 
| 2449     this.resultCache = |  | 
| 2450     { |  | 
| 2451       __proto__: null |  | 
| 2452     }; |  | 
| 2453   } |  | 
| 2454   exports.CombinedMatcher = CombinedMatcher; |  | 
| 2455   CombinedMatcher.maxCacheEntries = 1000; |  | 
| 2456   CombinedMatcher.prototype = |  | 
| 2457   { |  | 
| 2458     blacklist: null, |  | 
| 2459     whitelist: null, |  | 
| 2460     keys: null, |  | 
| 2461     resultCache: null, |  | 
| 2462     cacheEntries: 0, |  | 
| 2463     clear: function() |  | 
| 2464     { |  | 
| 2465       this.blacklist.clear(); |  | 
| 2466       this.whitelist.clear(); |  | 
| 2467       this.keys = |  | 
| 2468       { |  | 
| 2469         __proto__: null |  | 
| 2470       }; |  | 
| 2471       this.resultCache = |  | 
| 2472       { |  | 
| 2473         __proto__: null |  | 
| 2474       }; |  | 
| 2475       this.cacheEntries = 0; |  | 
| 2476     }, |  | 
| 2477     add: function(filter) |  | 
| 2478     { |  | 
| 2479       if (filter instanceof WhitelistFilter) |  | 
| 2480       { |  | 
| 2481         if (filter.siteKeys) |  | 
| 2482         { |  | 
| 2483           for (var i = 0; i < filter.siteKeys.length; i++) |  | 
| 2484           { |  | 
| 2485             this.keys[filter.siteKeys[i]] = filter.text; |  | 
| 2486           } |  | 
| 2487         } |  | 
| 2488         else |  | 
| 2489         { |  | 
| 2490           this.whitelist.add(filter); |  | 
| 2491         } |  | 
| 2492       } |  | 
| 2493       else |  | 
| 2494       { |  | 
| 2495         this.blacklist.add(filter); |  | 
| 2496       } |  | 
| 2497       if (this.cacheEntries > 0) |  | 
| 2498       { |  | 
| 2499         this.resultCache = |  | 
| 2500         { |  | 
| 2501           __proto__: null |  | 
| 2502         }; |  | 
| 2503         this.cacheEntries = 0; |  | 
| 2504       } |  | 
| 2505     }, |  | 
| 2506     remove: function(filter) |  | 
| 2507     { |  | 
| 2508       if (filter instanceof WhitelistFilter) |  | 
| 2509       { |  | 
| 2510         if (filter.siteKeys) |  | 
| 2511         { |  | 
| 2512           for (var i = 0; i < filter.siteKeys.length; i++) |  | 
| 2513           { |  | 
| 2514             delete this.keys[filter.siteKeys[i]]; |  | 
| 2515           } |  | 
| 2516         } |  | 
| 2517         else |  | 
| 2518         { |  | 
| 2519           this.whitelist.remove(filter); |  | 
| 2520         } |  | 
| 2521       } |  | 
| 2522       else |  | 
| 2523       { |  | 
| 2524         this.blacklist.remove(filter); |  | 
| 2525       } |  | 
| 2526       if (this.cacheEntries > 0) |  | 
| 2527       { |  | 
| 2528         this.resultCache = |  | 
| 2529         { |  | 
| 2530           __proto__: null |  | 
| 2531         }; |  | 
| 2532         this.cacheEntries = 0; |  | 
| 2533       } |  | 
| 2534     }, |  | 
| 2535     findKeyword: function(filter) |  | 
| 2536     { |  | 
| 2537       if (filter instanceof WhitelistFilter) |  | 
| 2538       { |  | 
| 2539         return this.whitelist.findKeyword(filter); |  | 
| 2540       } |  | 
| 2541       else |  | 
| 2542       { |  | 
| 2543         return this.blacklist.findKeyword(filter); |  | 
| 2544       } |  | 
| 2545     }, |  | 
| 2546     hasFilter: function(filter) |  | 
| 2547     { |  | 
| 2548       if (filter instanceof WhitelistFilter) |  | 
| 2549       { |  | 
| 2550         return this.whitelist.hasFilter(filter); |  | 
| 2551       } |  | 
| 2552       else |  | 
| 2553       { |  | 
| 2554         return this.blacklist.hasFilter(filter); |  | 
| 2555       } |  | 
| 2556     }, |  | 
| 2557     getKeywordForFilter: function(filter) |  | 
| 2558     { |  | 
| 2559       if (filter instanceof WhitelistFilter) |  | 
| 2560       { |  | 
| 2561         return this.whitelist.getKeywordForFilter(filter); |  | 
| 2562       } |  | 
| 2563       else |  | 
| 2564       { |  | 
| 2565         return this.blacklist.getKeywordForFilter(filter); |  | 
| 2566       } |  | 
| 2567     }, |  | 
| 2568     isSlowFilter: function(filter) |  | 
| 2569     { |  | 
| 2570       var matcher = filter instanceof WhitelistFilter ? this.whitelist : this.bl
      acklist; |  | 
| 2571       if (matcher.hasFilter(filter)) |  | 
| 2572       { |  | 
| 2573         return !matcher.getKeywordForFilter(filter); |  | 
| 2574       } |  | 
| 2575       else |  | 
| 2576       { |  | 
| 2577         return !matcher.findKeyword(filter); |  | 
| 2578       } |  | 
| 2579     }, |  | 
| 2580     matchesAnyInternal: function(location, contentType, docDomain, thirdParty) |  | 
| 2581     { |  | 
| 2582       var candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g); |  | 
| 2583       if (candidates === null) |  | 
| 2584       { |  | 
| 2585         candidates = []; |  | 
| 2586       } |  | 
| 2587       candidates.push(""); |  | 
| 2588       var blacklistHit = null; |  | 
| 2589       for (var i = 0, l = candidates.length; i < l; i++) |  | 
| 2590       { |  | 
| 2591         var substr = candidates[i]; |  | 
| 2592         if (substr in this.whitelist.filterByKeyword) |  | 
| 2593         { |  | 
| 2594           var result = this.whitelist._checkEntryMatch(substr, location, content
      Type, docDomain, thirdParty); |  | 
| 2595           if (result) |  | 
| 2596           { |  | 
| 2597             return result; |  | 
| 2598           } |  | 
| 2599         } |  | 
| 2600         if (substr in this.blacklist.filterByKeyword && blacklistHit === null) |  | 
| 2601         { |  | 
| 2602           blacklistHit = this.blacklist._checkEntryMatch(substr, location, conte
      ntType, docDomain, thirdParty); |  | 
| 2603         } |  | 
| 2604       } |  | 
| 2605       return blacklistHit; |  | 
| 2606     }, |  | 
| 2607     matchesAny: function(location, contentType, docDomain, thirdParty) |  | 
| 2608     { |  | 
| 2609       var key = location + " " + contentType + " " + docDomain + " " + thirdPart
      y; |  | 
| 2610       if (key in this.resultCache) |  | 
| 2611       { |  | 
| 2612         return this.resultCache[key]; |  | 
| 2613       } |  | 
| 2614       var result = this.matchesAnyInternal(location, contentType, docDomain, thi
      rdParty); |  | 
| 2615       if (this.cacheEntries >= CombinedMatcher.maxCacheEntries) |  | 
| 2616       { |  | 
| 2617         this.resultCache = |  | 
| 2618         { |  | 
| 2619           __proto__: null |  | 
| 2620         }; |  | 
| 2621         this.cacheEntries = 0; |  | 
| 2622       } |  | 
| 2623       this.resultCache[key] = result; |  | 
| 2624       this.cacheEntries++; |  | 
| 2625       return result; |  | 
| 2626     }, |  | 
| 2627     matchesByKey: function(location, key, docDomain) |  | 
| 2628     { |  | 
| 2629       key = key.toUpperCase(); |  | 
| 2630       if (key in this.keys) |  | 
| 2631       { |  | 
| 2632         var filter = Filter.knownFilters[this.keys[key]]; |  | 
| 2633         if (filter && filter.matches(location, "DOCUMENT", docDomain, false)) |  | 
| 2634         { |  | 
| 2635           return filter; |  | 
| 2636         } |  | 
| 2637         else |  | 
| 2638         { |  | 
| 2639           return null; |  | 
| 2640         } |  | 
| 2641       } |  | 
| 2642       else |  | 
| 2643       { |  | 
| 2644         return null; |  | 
| 2645       } |  | 
| 2646     } |  | 
| 2647   }; |  | 
| 2648   var defaultMatcher = exports.defaultMatcher = new CombinedMatcher(); |  | 
| 2649   return exports; |  | 
| 2650 })(); |  | 
| 2651 require.scopes["filterListener"] = (function() |  | 
| 2652 { |  | 
| 2653   var exports = {}; |  | 
| 2654   var FilterStorage = require("filterStorage").FilterStorage; |  | 
| 2655   var FilterNotifier = require("filterNotifier").FilterNotifier; |  | 
| 2656   var ElemHide = require("elemHide").ElemHide; |  | 
| 2657   var defaultMatcher = require("matcher").defaultMatcher; |  | 
| 2658   var _tempVar19 = require("filterClasses"); |  | 
| 2659   var ActiveFilter = _tempVar19.ActiveFilter; |  | 
| 2660   var RegExpFilter = _tempVar19.RegExpFilter; |  | 
| 2661   var ElemHideBase = _tempVar19.ElemHideBase; |  | 
| 2662   var Prefs = require("prefs").Prefs; |  | 
| 2663   var batchMode = false; |  | 
| 2664   var isDirty = 0; |  | 
| 2665   var FilterListener = exports.FilterListener = |  | 
| 2666   { |  | 
| 2667     get batchMode() |  | 
| 2668     { |  | 
| 2669       return batchMode; |  | 
| 2670     }, |  | 
| 2671     set batchMode(value) |  | 
| 2672     { |  | 
| 2673       batchMode = value; |  | 
| 2674       flushElemHide(); |  | 
| 2675     }, |  | 
| 2676     setDirty: function(factor) |  | 
| 2677     { |  | 
| 2678       if (factor == 0 && isDirty > 0) |  | 
| 2679       { |  | 
| 2680         isDirty = 1; |  | 
| 2681       } |  | 
| 2682       else |  | 
| 2683       { |  | 
| 2684         isDirty += factor; |  | 
| 2685       } |  | 
| 2686       if (isDirty >= 1) |  | 
| 2687       { |  | 
| 2688         FilterStorage.saveToDisk(); |  | 
| 2689       } |  | 
| 2690     } |  | 
| 2691   }; |  | 
| 2692   var HistoryPurgeObserver = |  | 
| 2693   { |  | 
| 2694     observe: function(subject, topic, data) |  | 
| 2695     { |  | 
| 2696       if (topic == "browser:purge-session-history" && Prefs.clearStatsOnHistoryP
      urge) |  | 
| 2697       { |  | 
| 2698         FilterStorage.resetHitCounts(); |  | 
| 2699         FilterListener.setDirty(0); |  | 
| 2700         Prefs.recentReports = []; |  | 
| 2701       } |  | 
| 2702     }, |  | 
| 2703     QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference, Ci.nsIOb
      server]) |  | 
| 2704   }; |  | 
| 2705 |  | 
| 2706   function init() |  | 
| 2707   { |  | 
| 2708     FilterNotifier.addListener(function(action, item, newValue, oldValue) |  | 
| 2709     { |  | 
| 2710       var match = /^(\w+)\.(.*)/.exec(action); |  | 
| 2711       if (match && match[1] == "filter") |  | 
| 2712       { |  | 
| 2713         onFilterChange(match[2], item, newValue, oldValue); |  | 
| 2714       } |  | 
| 2715       else if (match && match[1] == "subscription") |  | 
| 2716       { |  | 
| 2717         onSubscriptionChange(match[2], item, newValue, oldValue); |  | 
| 2718       } |  | 
| 2719       else |  | 
| 2720       { |  | 
| 2721         onGenericChange(action, item); |  | 
| 2722       } |  | 
| 2723     }); |  | 
| 2724     var application = require("info").application; |  | 
| 2725     if (application == "chrome") |  | 
| 2726     { |  | 
| 2727       flushElemHide = function(){}; |  | 
| 2728     } |  | 
| 2729     else |  | 
| 2730     { |  | 
| 2731       ElemHide.init(); |  | 
| 2732     } |  | 
| 2733     FilterStorage.loadFromDisk(); |  | 
| 2734     Services.obs.addObserver(HistoryPurgeObserver, "browser:purge-session-histor
      y", true); |  | 
| 2735     onShutdown.add(function() |  | 
| 2736     { |  | 
| 2737       Services.obs.removeObserver(HistoryPurgeObserver, "browser:purge-session-h
      istory"); |  | 
| 2738     }); |  | 
| 2739   } |  | 
| 2740   init(); |  | 
| 2741 |  | 
| 2742   function flushElemHide() |  | 
| 2743   { |  | 
| 2744     if (!batchMode && ElemHide.isDirty) |  | 
| 2745     { |  | 
| 2746       ElemHide.apply(); |  | 
| 2747     } |  | 
| 2748   } |  | 
| 2749 |  | 
| 2750   function addFilter(filter) |  | 
| 2751   { |  | 
| 2752     if (!(filter instanceof ActiveFilter) || filter.disabled) |  | 
| 2753     { |  | 
| 2754       return; |  | 
| 2755     } |  | 
| 2756     var hasEnabled = false; |  | 
| 2757     for (var i = 0; i < filter.subscriptions.length; i++) |  | 
| 2758     { |  | 
| 2759       if (!filter.subscriptions[i].disabled) |  | 
| 2760       { |  | 
| 2761         hasEnabled = true; |  | 
| 2762       } |  | 
| 2763     } |  | 
| 2764     if (!hasEnabled) |  | 
| 2765     { |  | 
| 2766       return; |  | 
| 2767     } |  | 
| 2768     if (filter instanceof RegExpFilter) |  | 
| 2769     { |  | 
| 2770       defaultMatcher.add(filter); |  | 
| 2771     } |  | 
| 2772     else if (filter instanceof ElemHideBase) |  | 
| 2773     { |  | 
| 2774       ElemHide.add(filter); |  | 
| 2775     } |  | 
| 2776   } |  | 
| 2777 |  | 
| 2778   function removeFilter(filter) |  | 
| 2779   { |  | 
| 2780     if (!(filter instanceof ActiveFilter)) |  | 
| 2781     { |  | 
| 2782       return; |  | 
| 2783     } |  | 
| 2784     if (!filter.disabled) |  | 
| 2785     { |  | 
| 2786       var hasEnabled = false; |  | 
| 2787       for (var i = 0; i < filter.subscriptions.length; i++) |  | 
| 2788       { |  | 
| 2789         if (!filter.subscriptions[i].disabled) |  | 
| 2790         { |  | 
| 2791           hasEnabled = true; |  | 
| 2792         } |  | 
| 2793       } |  | 
| 2794       if (hasEnabled) |  | 
| 2795       { |  | 
| 2796         return; |  | 
| 2797       } |  | 
| 2798     } |  | 
| 2799     if (filter instanceof RegExpFilter) |  | 
| 2800     { |  | 
| 2801       defaultMatcher.remove(filter); |  | 
| 2802     } |  | 
| 2803     else if (filter instanceof ElemHideBase) |  | 
| 2804     { |  | 
| 2805       ElemHide.remove(filter); |  | 
| 2806     } |  | 
| 2807   } |  | 
| 2808 |  | 
| 2809   function onSubscriptionChange(action, subscription, newValue, oldValue) |  | 
| 2810   { |  | 
| 2811     FilterListener.setDirty(1); |  | 
| 2812     if (action != "added" && action != "removed" && action != "disabled" && acti
      on != "updated") |  | 
| 2813     { |  | 
| 2814       return; |  | 
| 2815     } |  | 
| 2816     if (action != "removed" && !(subscription.url in FilterStorage.knownSubscrip
      tions)) |  | 
| 2817     { |  | 
| 2818       return; |  | 
| 2819     } |  | 
| 2820     if ((action == "added" || action == "removed" || action == "updated") && sub
      scription.disabled) |  | 
| 2821     { |  | 
| 2822       return; |  | 
| 2823     } |  | 
| 2824     if (action == "added" || action == "removed" || action == "disabled") |  | 
| 2825     { |  | 
| 2826       var method = action == "added" || action == "disabled" && newValue == fals
      e ? addFilter : removeFilter; |  | 
| 2827       if (subscription.filters) |  | 
| 2828       { |  | 
| 2829         subscription.filters.forEach(method); |  | 
| 2830       } |  | 
| 2831     } |  | 
| 2832     else if (action == "updated") |  | 
| 2833     { |  | 
| 2834       subscription.oldFilters.forEach(removeFilter); |  | 
| 2835       subscription.filters.forEach(addFilter); |  | 
| 2836     } |  | 
| 2837     flushElemHide(); |  | 
| 2838   } |  | 
| 2839 |  | 
| 2840   function onFilterChange(action, filter, newValue, oldValue) |  | 
| 2841   { |  | 
| 2842     if (action == "hitCount" || action == "lastHit") |  | 
| 2843     { |  | 
| 2844       FilterListener.setDirty(0.002); |  | 
| 2845     } |  | 
| 2846     else |  | 
| 2847     { |  | 
| 2848       FilterListener.setDirty(1); |  | 
| 2849     } |  | 
| 2850     if (action != "added" && action != "removed" && action != "disabled") |  | 
| 2851     { |  | 
| 2852       return; |  | 
| 2853     } |  | 
| 2854     if ((action == "added" || action == "removed") && filter.disabled) |  | 
| 2855     { |  | 
| 2856       return; |  | 
| 2857     } |  | 
| 2858     if (action == "added" || action == "disabled" && newValue == false) |  | 
| 2859     { |  | 
| 2860       addFilter(filter); |  | 
| 2861     } |  | 
| 2862     else |  | 
| 2863     { |  | 
| 2864       removeFilter(filter); |  | 
| 2865     } |  | 
| 2866     flushElemHide(); |  | 
| 2867   } |  | 
| 2868 |  | 
| 2869   function onGenericChange(action) |  | 
| 2870   { |  | 
| 2871     if (action == "load") |  | 
| 2872     { |  | 
| 2873       isDirty = 0; |  | 
| 2874       defaultMatcher.clear(); |  | 
| 2875       ElemHide.clear(); |  | 
| 2876       for (var _loopIndex20 = 0; _loopIndex20 < FilterStorage.subscriptions.leng
      th; ++_loopIndex20) |  | 
| 2877       { |  | 
| 2878         var subscription = FilterStorage.subscriptions[_loopIndex20]; |  | 
| 2879         if (!subscription.disabled) |  | 
| 2880         { |  | 
| 2881           subscription.filters.forEach(addFilter); |  | 
| 2882         } |  | 
| 2883       } |  | 
| 2884       flushElemHide(); |  | 
| 2885     } |  | 
| 2886     else if (action == "save") |  | 
| 2887     { |  | 
| 2888       isDirty = 0; |  | 
| 2889     } |  | 
| 2890   } |  | 
| 2891   return exports; |  | 
| 2892 })(); |  | 
| 2893 require.scopes["synchronizer"] = (function() |  | 
| 2894 { |  | 
| 2895   var exports = {}; |  | 
| 2896   var Utils = require("utils").Utils; |  | 
| 2897   var FilterStorage = require("filterStorage").FilterStorage; |  | 
| 2898   var FilterNotifier = require("filterNotifier").FilterNotifier; |  | 
| 2899   var Prefs = require("prefs").Prefs; |  | 
| 2900   var _tempVar21 = require("filterClasses"); |  | 
| 2901   var Filter = _tempVar21.Filter; |  | 
| 2902   var CommentFilter = _tempVar21.CommentFilter; |  | 
| 2903   var _tempVar22 = require("subscriptionClasses"); |  | 
| 2904   var Subscription = _tempVar22.Subscription; |  | 
| 2905   var DownloadableSubscription = _tempVar22.DownloadableSubscription; |  | 
| 2906   var MILLISECONDS_IN_SECOND = 1000; |  | 
| 2907   var SECONDS_IN_MINUTE = 60; |  | 
| 2908   var SECONDS_IN_HOUR = 60 * SECONDS_IN_MINUTE; |  | 
| 2909   var SECONDS_IN_DAY = 24 * SECONDS_IN_HOUR; |  | 
| 2910   var INITIAL_DELAY = 6 * SECONDS_IN_MINUTE; |  | 
| 2911   var CHECK_INTERVAL = SECONDS_IN_HOUR; |  | 
| 2912   var MIN_EXPIRATION_INTERVAL = 1 * SECONDS_IN_DAY; |  | 
| 2913   var MAX_EXPIRATION_INTERVAL = 14 * SECONDS_IN_DAY; |  | 
| 2914   var MAX_ABSENSE_INTERVAL = 1 * SECONDS_IN_DAY; |  | 
| 2915   var timer = null; |  | 
| 2916   var executing = |  | 
| 2917   { |  | 
| 2918     __proto__: null |  | 
| 2919   }; |  | 
| 2920   var Synchronizer = exports.Synchronizer = |  | 
| 2921   { |  | 
| 2922     init: function() |  | 
| 2923     { |  | 
| 2924       var callback = function() |  | 
| 2925       { |  | 
| 2926         timer.delay = CHECK_INTERVAL * MILLISECONDS_IN_SECOND; |  | 
| 2927         checkSubscriptions(); |  | 
| 2928       }; |  | 
| 2929       timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); |  | 
| 2930       timer.initWithCallback(callback, INITIAL_DELAY * MILLISECONDS_IN_SECOND, C
      i.nsITimer.TYPE_REPEATING_SLACK); |  | 
| 2931       onShutdown.add(function() |  | 
| 2932       { |  | 
| 2933         timer.cancel(); |  | 
| 2934       }); |  | 
| 2935     }, |  | 
| 2936     isExecuting: function(url) |  | 
| 2937     { |  | 
| 2938       return url in executing; |  | 
| 2939     }, |  | 
| 2940     execute: function(subscription, manual, forceDownload) |  | 
| 2941     { |  | 
| 2942       Utils.runAsync(this.executeInternal, this, subscription, manual, forceDown
      load); |  | 
| 2943     }, |  | 
| 2944     executeInternal: function(subscription, manual, forceDownload) |  | 
| 2945     { |  | 
| 2946       var url = subscription.url; |  | 
| 2947       if (url in executing) |  | 
| 2948       { |  | 
| 2949         return; |  | 
| 2950       } |  | 
| 2951       var newURL = subscription.nextURL; |  | 
| 2952       var hadTemporaryRedirect = false; |  | 
| 2953       subscription.nextURL = null; |  | 
| 2954       var loadFrom = newURL; |  | 
| 2955       var isBaseLocation = true; |  | 
| 2956       if (!loadFrom) |  | 
| 2957       { |  | 
| 2958         loadFrom = url; |  | 
| 2959       } |  | 
| 2960       if (loadFrom == url) |  | 
| 2961       { |  | 
| 2962         if (subscription.alternativeLocations) |  | 
| 2963         { |  | 
| 2964           var options = [ |  | 
| 2965             [1, url] |  | 
| 2966           ]; |  | 
| 2967           var totalWeight = 1; |  | 
| 2968           for (var _loopIndex23 = 0; _loopIndex23 < subscription.alternativeLoca
      tions.split(",").length; ++_loopIndex23) |  | 
| 2969           { |  | 
| 2970             var alternative = subscription.alternativeLocations.split(",")[_loop
      Index23]; |  | 
| 2971             if (!/^https?:\/\//.test(alternative)) |  | 
| 2972             { |  | 
| 2973               continue; |  | 
| 2974             } |  | 
| 2975             var weight = 1; |  | 
| 2976             var match = /;q=([\d\.]+)$/.exec(alternative); |  | 
| 2977             if (match) |  | 
| 2978             { |  | 
| 2979               weight = parseFloat(match[1]); |  | 
| 2980               if (isNaN(weight) || !isFinite(weight) || weight < 0) |  | 
| 2981               { |  | 
| 2982                 weight = 1; |  | 
| 2983               } |  | 
| 2984               if (weight > 10) |  | 
| 2985               { |  | 
| 2986                 weight = 10; |  | 
| 2987               } |  | 
| 2988               alternative = alternative.substr(0, match.index); |  | 
| 2989             } |  | 
| 2990             options.push([weight, alternative]); |  | 
| 2991             totalWeight += weight; |  | 
| 2992           } |  | 
| 2993           var choice = Math.random() * totalWeight; |  | 
| 2994           for (var _loopIndex24 = 0; _loopIndex24 < options.length; ++_loopIndex
      24) |  | 
| 2995           { |  | 
| 2996             var _tempVar25 = options[_loopIndex24]; |  | 
| 2997             var weight = _tempVar25[0]; |  | 
| 2998             var alternative = _tempVar25[1]; |  | 
| 2999             choice -= weight; |  | 
| 3000             if (choice < 0) |  | 
| 3001             { |  | 
| 3002               loadFrom = alternative; |  | 
| 3003               break; |  | 
| 3004             } |  | 
| 3005           } |  | 
| 3006           isBaseLocation = loadFrom == url; |  | 
| 3007         } |  | 
| 3008       } |  | 
| 3009       else |  | 
| 3010       { |  | 
| 3011         forceDownload = true; |  | 
| 3012       } |  | 
| 3013       var addonVersion = require("info").addonVersion; |  | 
| 3014       loadFrom = loadFrom.replace(/%VERSION%/, "ABP" + addonVersion); |  | 
| 3015       var request = null; |  | 
| 3016 |  | 
| 3017       function errorCallback(error) |  | 
| 3018       { |  | 
| 3019         var channelStatus = -1; |  | 
| 3020         try |  | 
| 3021         { |  | 
| 3022           channelStatus = request.channel.status; |  | 
| 3023         } |  | 
| 3024         catch (e){} |  | 
| 3025         var responseStatus = ""; |  | 
| 3026         try |  | 
| 3027         { |  | 
| 3028           responseStatus = request.channel.QueryInterface(Ci.nsIHttpChannel).res
      ponseStatus; |  | 
| 3029         } |  | 
| 3030         catch (e){} |  | 
| 3031         setError(subscription, error, channelStatus, responseStatus, loadFrom, i
      sBaseLocation, manual); |  | 
| 3032       } |  | 
| 3033       try |  | 
| 3034       { |  | 
| 3035         request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(C
      i.nsIXMLHttpRequest); |  | 
| 3036         request.mozBackgroundRequest = true; |  | 
| 3037         request.open("GET", loadFrom); |  | 
| 3038       } |  | 
| 3039       catch (e) |  | 
| 3040       { |  | 
| 3041         errorCallback("synchronize_invalid_url"); |  | 
| 3042         return; |  | 
| 3043       } |  | 
| 3044       try |  | 
| 3045       { |  | 
| 3046         request.overrideMimeType("text/plain"); |  | 
| 3047         request.channel.loadFlags = request.channel.loadFlags | request.channel.
      INHIBIT_CACHING | request.channel.VALIDATE_ALWAYS; |  | 
| 3048         if (request.channel instanceof Ci.nsIHttpChannel) |  | 
| 3049         { |  | 
| 3050           request.channel.redirectionLimit = 5; |  | 
| 3051         } |  | 
| 3052         var oldNotifications = request.channel.notificationCallbacks; |  | 
| 3053         var oldEventSink = null; |  | 
| 3054         request.channel.notificationCallbacks = |  | 
| 3055         { |  | 
| 3056           QueryInterface: XPCOMUtils.generateQI([Ci.nsIInterfaceRequestor, Ci.ns
      IChannelEventSink]), |  | 
| 3057           getInterface: function(iid) |  | 
| 3058           { |  | 
| 3059             if (iid.equals(Ci.nsIChannelEventSink)) |  | 
| 3060             { |  | 
| 3061               try |  | 
| 3062               { |  | 
| 3063                 oldEventSink = oldNotifications.QueryInterface(iid); |  | 
| 3064               } |  | 
| 3065               catch (e){} |  | 
| 3066               return this; |  | 
| 3067             } |  | 
| 3068             if (oldNotifications) |  | 
| 3069             { |  | 
| 3070               return oldNotifications.QueryInterface(iid); |  | 
| 3071             } |  | 
| 3072             else |  | 
| 3073             { |  | 
| 3074               throw Cr.NS_ERROR_NO_INTERFACE; |  | 
| 3075             } |  | 
| 3076           }, |  | 
| 3077           asyncOnChannelRedirect: function(oldChannel, newChannel, flags, callba
      ck) |  | 
| 3078           { |  | 
| 3079             if (isBaseLocation && !hadTemporaryRedirect && oldChannel instanceof
       Ci.nsIHttpChannel) |  | 
| 3080             { |  | 
| 3081               try |  | 
| 3082               { |  | 
| 3083                 subscription.alternativeLocations = oldChannel.getResponseHeader
      ("X-Alternative-Locations"); |  | 
| 3084               } |  | 
| 3085               catch (e) |  | 
| 3086               { |  | 
| 3087                 subscription.alternativeLocations = null; |  | 
| 3088               } |  | 
| 3089             } |  | 
| 3090             if (flags & Ci.nsIChannelEventSink.REDIRECT_TEMPORARY) |  | 
| 3091             { |  | 
| 3092               hadTemporaryRedirect = true; |  | 
| 3093             } |  | 
| 3094             else if (!hadTemporaryRedirect) |  | 
| 3095             { |  | 
| 3096               newURL = newChannel.URI.spec; |  | 
| 3097             } |  | 
| 3098             if (oldEventSink) |  | 
| 3099             { |  | 
| 3100               oldEventSink.asyncOnChannelRedirect(oldChannel, newChannel, flags,
       callback); |  | 
| 3101             } |  | 
| 3102             else |  | 
| 3103             { |  | 
| 3104               callback.onRedirectVerifyCallback(Cr.NS_OK); |  | 
| 3105             } |  | 
| 3106           } |  | 
| 3107         }; |  | 
| 3108       } |  | 
| 3109       catch (e) |  | 
| 3110       { |  | 
| 3111         Cu.reportError(e); |  | 
| 3112       } |  | 
| 3113       if (subscription.lastModified && !forceDownload) |  | 
| 3114       { |  | 
| 3115         request.setRequestHeader("If-Modified-Since", subscription.lastModified)
      ; |  | 
| 3116       } |  | 
| 3117       request.addEventListener("error", function(ev) |  | 
| 3118       { |  | 
| 3119         if (onShutdown.done) |  | 
| 3120         { |  | 
| 3121           return; |  | 
| 3122         } |  | 
| 3123         delete executing[url]; |  | 
| 3124         try |  | 
| 3125         { |  | 
| 3126           request.channel.notificationCallbacks = null; |  | 
| 3127         } |  | 
| 3128         catch (e){} |  | 
| 3129         errorCallback("synchronize_connection_error"); |  | 
| 3130       }, false); |  | 
| 3131       request.addEventListener("load", function(ev) |  | 
| 3132       { |  | 
| 3133         if (onShutdown.done) |  | 
| 3134         { |  | 
| 3135           return; |  | 
| 3136         } |  | 
| 3137         delete executing[url]; |  | 
| 3138         try |  | 
| 3139         { |  | 
| 3140           request.channel.notificationCallbacks = null; |  | 
| 3141         } |  | 
| 3142         catch (e){} |  | 
| 3143         if (request.status && request.status != 200 && request.status != 304) |  | 
| 3144         { |  | 
| 3145           errorCallback("synchronize_connection_error"); |  | 
| 3146           return; |  | 
| 3147         } |  | 
| 3148         var newFilters = null; |  | 
| 3149         if (request.status != 304) |  | 
| 3150         { |  | 
| 3151           newFilters = readFilters(subscription, request.responseText, errorCall
      back); |  | 
| 3152           if (!newFilters) |  | 
| 3153           { |  | 
| 3154             return; |  | 
| 3155           } |  | 
| 3156           subscription.lastModified = request.getResponseHeader("Last-Modified")
      ; |  | 
| 3157         } |  | 
| 3158         if (isBaseLocation && !hadTemporaryRedirect) |  | 
| 3159         { |  | 
| 3160           subscription.alternativeLocations = request.getResponseHeader("X-Alter
      native-Locations"); |  | 
| 3161         } |  | 
| 3162         subscription.lastSuccess = subscription.lastDownload = Math.round(Date.n
      ow() / MILLISECONDS_IN_SECOND); |  | 
| 3163         subscription.downloadStatus = "synchronize_ok"; |  | 
| 3164         subscription.errors = 0; |  | 
| 3165         var now = Math.round(((new Date(request.getResponseHeader("Date"))).getT
      ime() || Date.now()) / MILLISECONDS_IN_SECOND); |  | 
| 3166         var expires = Math.round((new Date(request.getResponseHeader("Expires"))
      ).getTime() / MILLISECONDS_IN_SECOND) || 0; |  | 
| 3167         var expirationInterval = expires ? expires - now : 0; |  | 
| 3168         for (var _loopIndex26 = 0; _loopIndex26 < (newFilters || subscription.fi
      lters).length; ++_loopIndex26) |  | 
| 3169         { |  | 
| 3170           var filter = (newFilters || subscription.filters)[_loopIndex26]; |  | 
| 3171           if (!(filter instanceof CommentFilter)) |  | 
| 3172           { |  | 
| 3173             continue; |  | 
| 3174           } |  | 
| 3175           var match = /\bExpires\s*(?::|after)\s*(\d+)\s*(h)?/i.exec(filter.text
      ); |  | 
| 3176           if (match) |  | 
| 3177           { |  | 
| 3178             var interval = parseInt(match[1], 10); |  | 
| 3179             if (match[2]) |  | 
| 3180             { |  | 
| 3181               interval *= SECONDS_IN_HOUR; |  | 
| 3182             } |  | 
| 3183             else |  | 
| 3184             { |  | 
| 3185               interval *= SECONDS_IN_DAY; |  | 
| 3186             } |  | 
| 3187             if (interval > expirationInterval) |  | 
| 3188             { |  | 
| 3189               expirationInterval = interval; |  | 
| 3190             } |  | 
| 3191           } |  | 
| 3192         } |  | 
| 3193         expirationInterval = Math.min(Math.max(expirationInterval, MIN_EXPIRATIO
      N_INTERVAL), MAX_EXPIRATION_INTERVAL); |  | 
| 3194         subscription.expires = subscription.lastDownload + expirationInterval * 
      2; |  | 
| 3195         subscription.softExpiration = subscription.lastDownload + Math.round(exp
      irationInterval * (Math.random() * 0.4 + 0.8)); |  | 
| 3196         if (newFilters) |  | 
| 3197         { |  | 
| 3198           var fixedTitle = false; |  | 
| 3199           for (var i = 0; i < newFilters.length; i++) |  | 
| 3200           { |  | 
| 3201             var filter = newFilters[i]; |  | 
| 3202             if (!(filter instanceof CommentFilter)) |  | 
| 3203             { |  | 
| 3204               continue; |  | 
| 3205             } |  | 
| 3206             var match = /^!\s*(\w+)\s*:\s*(.*)/.exec(filter.text); |  | 
| 3207             if (match) |  | 
| 3208             { |  | 
| 3209               var keyword = match[1].toLowerCase(); |  | 
| 3210               var value = match[2]; |  | 
| 3211               var known = true; |  | 
| 3212               if (keyword == "redirect") |  | 
| 3213               { |  | 
| 3214                 if (isBaseLocation && value != url) |  | 
| 3215                 { |  | 
| 3216                   subscription.nextURL = value; |  | 
| 3217                 } |  | 
| 3218               } |  | 
| 3219               else if (keyword == "homepage") |  | 
| 3220               { |  | 
| 3221                 var uri = Utils.makeURI(value); |  | 
| 3222                 if (uri && (uri.scheme == "http" || uri.scheme == "https")) |  | 
| 3223                 { |  | 
| 3224                   subscription.homepage = uri.spec; |  | 
| 3225                 } |  | 
| 3226               } |  | 
| 3227               else if (keyword == "title") |  | 
| 3228               { |  | 
| 3229                 if (value) |  | 
| 3230                 { |  | 
| 3231                   subscription.title = value; |  | 
| 3232                   fixedTitle = true; |  | 
| 3233                 } |  | 
| 3234               } |  | 
| 3235               else |  | 
| 3236               { |  | 
| 3237                 known = false; |  | 
| 3238               } |  | 
| 3239               if (known) |  | 
| 3240               { |  | 
| 3241                 newFilters.splice(i--, 1); |  | 
| 3242               } |  | 
| 3243             } |  | 
| 3244           } |  | 
| 3245           subscription.fixedTitle = fixedTitle; |  | 
| 3246         } |  | 
| 3247         if (isBaseLocation && newURL && newURL != url) |  | 
| 3248         { |  | 
| 3249           var listed = subscription.url in FilterStorage.knownSubscriptions; |  | 
| 3250           if (listed) |  | 
| 3251           { |  | 
| 3252             FilterStorage.removeSubscription(subscription); |  | 
| 3253           } |  | 
| 3254           url = newURL; |  | 
| 3255           var newSubscription = Subscription.fromURL(url); |  | 
| 3256           for (var key in newSubscription) |  | 
| 3257           { |  | 
| 3258             delete newSubscription[key]; |  | 
| 3259           } |  | 
| 3260           for (var key in subscription) |  | 
| 3261           { |  | 
| 3262             newSubscription[key] = subscription[key]; |  | 
| 3263           } |  | 
| 3264           delete Subscription.knownSubscriptions[subscription.url]; |  | 
| 3265           newSubscription.oldSubscription = subscription; |  | 
| 3266           subscription = newSubscription; |  | 
| 3267           subscription.url = url; |  | 
| 3268           if (!(subscription.url in FilterStorage.knownSubscriptions) && listed) |  | 
| 3269           { |  | 
| 3270             FilterStorage.addSubscription(subscription); |  | 
| 3271           } |  | 
| 3272         } |  | 
| 3273         if (newFilters) |  | 
| 3274         { |  | 
| 3275           FilterStorage.updateSubscriptionFilters(subscription, newFilters); |  | 
| 3276         } |  | 
| 3277         delete subscription.oldSubscription; |  | 
| 3278       }, false); |  | 
| 3279       executing[url] = true; |  | 
| 3280       FilterNotifier.triggerListeners("subscription.downloadStatus", subscriptio
      n); |  | 
| 3281       try |  | 
| 3282       { |  | 
| 3283         request.send(null); |  | 
| 3284       } |  | 
| 3285       catch (e) |  | 
| 3286       { |  | 
| 3287         delete executing[url]; |  | 
| 3288         errorCallback("synchronize_connection_error"); |  | 
| 3289         return; |  | 
| 3290       } |  | 
| 3291     } |  | 
| 3292   }; |  | 
| 3293   Synchronizer.init(); |  | 
| 3294 |  | 
| 3295   function checkSubscriptions() |  | 
| 3296   { |  | 
| 3297     if (!Prefs.subscriptions_autoupdate) |  | 
| 3298     { |  | 
| 3299       return; |  | 
| 3300     } |  | 
| 3301     var time = Math.round(Date.now() / MILLISECONDS_IN_SECOND); |  | 
| 3302     for (var _loopIndex27 = 0; _loopIndex27 < FilterStorage.subscriptions.length
      ; ++_loopIndex27) |  | 
| 3303     { |  | 
| 3304       var subscription = FilterStorage.subscriptions[_loopIndex27]; |  | 
| 3305       if (!(subscription instanceof DownloadableSubscription)) |  | 
| 3306       { |  | 
| 3307         continue; |  | 
| 3308       } |  | 
| 3309       if (subscription.lastCheck && time - subscription.lastCheck > MAX_ABSENSE_
      INTERVAL) |  | 
| 3310       { |  | 
| 3311         subscription.softExpiration += time - subscription.lastCheck; |  | 
| 3312       } |  | 
| 3313       subscription.lastCheck = time; |  | 
| 3314       if (subscription.expires - time > MAX_EXPIRATION_INTERVAL) |  | 
| 3315       { |  | 
| 3316         subscription.expires = time + MAX_EXPIRATION_INTERVAL; |  | 
| 3317       } |  | 
| 3318       if (subscription.softExpiration - time > MAX_EXPIRATION_INTERVAL) |  | 
| 3319       { |  | 
| 3320         subscription.softExpiration = time + MAX_EXPIRATION_INTERVAL; |  | 
| 3321       } |  | 
| 3322       if (subscription.softExpiration > time && subscription.expires > time) |  | 
| 3323       { |  | 
| 3324         continue; |  | 
| 3325       } |  | 
| 3326       if (time - subscription.lastDownload >= MIN_EXPIRATION_INTERVAL) |  | 
| 3327       { |  | 
| 3328         Synchronizer.execute(subscription, false); |  | 
| 3329       } |  | 
| 3330     } |  | 
| 3331   } |  | 
| 3332 |  | 
| 3333   function readFilters(subscription, text, errorCallback) |  | 
| 3334   { |  | 
| 3335     var lines = text.split(/[\r\n]+/); |  | 
| 3336     var match = /\[Adblock(?:\s*Plus\s*([\d\.]+)?)?\]/i.exec(lines[0]); |  | 
| 3337     if (!match) |  | 
| 3338     { |  | 
| 3339       errorCallback("synchronize_invalid_data"); |  | 
| 3340       return null; |  | 
| 3341     } |  | 
| 3342     var minVersion = match[1]; |  | 
| 3343     for (var i = 0; i < lines.length; i++) |  | 
| 3344     { |  | 
| 3345       var match = /!\s*checksum[\s\-:]+([\w\+\/]+)/i.exec(lines[i]); |  | 
| 3346       if (match) |  | 
| 3347       { |  | 
| 3348         lines.splice(i, 1); |  | 
| 3349         var checksum = Utils.generateChecksum(lines); |  | 
| 3350         if (checksum && checksum != match[1]) |  | 
| 3351         { |  | 
| 3352           errorCallback("synchronize_checksum_mismatch"); |  | 
| 3353           return null; |  | 
| 3354         } |  | 
| 3355         break; |  | 
| 3356       } |  | 
| 3357     } |  | 
| 3358     delete subscription.requiredVersion; |  | 
| 3359     delete subscription.upgradeRequired; |  | 
| 3360     if (minVersion) |  | 
| 3361     { |  | 
| 3362       var addonVersion = require("info").addonVersion; |  | 
| 3363       subscription.requiredVersion = minVersion; |  | 
| 3364       if (Services.vc.compare(minVersion, addonVersion) > 0) |  | 
| 3365       { |  | 
| 3366         subscription.upgradeRequired = true; |  | 
| 3367       } |  | 
| 3368     } |  | 
| 3369     lines.shift(); |  | 
| 3370     var result = []; |  | 
| 3371     for (var _loopIndex28 = 0; _loopIndex28 < lines.length; ++_loopIndex28) |  | 
| 3372     { |  | 
| 3373       var line = lines[_loopIndex28]; |  | 
| 3374       line = Filter.normalize(line); |  | 
| 3375       if (line) |  | 
| 3376       { |  | 
| 3377         result.push(Filter.fromText(line)); |  | 
| 3378       } |  | 
| 3379     } |  | 
| 3380     return result; |  | 
| 3381   } |  | 
| 3382 |  | 
| 3383   function setError(subscription, error, channelStatus, responseStatus, download
      URL, isBaseLocation, manual) |  | 
| 3384   { |  | 
| 3385     if (!isBaseLocation) |  | 
| 3386     { |  | 
| 3387       subscription.alternativeLocations = null; |  | 
| 3388     } |  | 
| 3389     try |  | 
| 3390     { |  | 
| 3391       Cu.reportError("Adblock Plus: Downloading filter subscription " + subscrip
      tion.title + " failed (" + Utils.getString(error) + ")\n" + "Download address: "
       + downloadURL + "\n" + "Channel status: " + channelStatus + "\n" + "Server resp
      onse: " + responseStatus); |  | 
| 3392     } |  | 
| 3393     catch (e){} |  | 
| 3394     subscription.lastDownload = Math.round(Date.now() / MILLISECONDS_IN_SECOND); |  | 
| 3395     subscription.downloadStatus = error; |  | 
| 3396     if (!manual) |  | 
| 3397     { |  | 
| 3398       if (error == "synchronize_checksum_mismatch") |  | 
| 3399       { |  | 
| 3400         subscription.errors = 0; |  | 
| 3401       } |  | 
| 3402       else |  | 
| 3403       { |  | 
| 3404         subscription.errors++; |  | 
| 3405       } |  | 
| 3406       if (subscription.errors >= Prefs.subscriptions_fallbackerrors && /^https?:
      \/\//i.test(subscription.url)) |  | 
| 3407       { |  | 
| 3408         subscription.errors = 0; |  | 
| 3409         var fallbackURL = Prefs.subscriptions_fallbackurl; |  | 
| 3410         var addonVersion = require("info").addonVersion; |  | 
| 3411         fallbackURL = fallbackURL.replace(/%VERSION%/g, encodeURIComponent(addon
      Version)); |  | 
| 3412         fallbackURL = fallbackURL.replace(/%SUBSCRIPTION%/g, encodeURIComponent(
      subscription.url)); |  | 
| 3413         fallbackURL = fallbackURL.replace(/%URL%/g, encodeURIComponent(downloadU
      RL)); |  | 
| 3414         fallbackURL = fallbackURL.replace(/%ERROR%/g, encodeURIComponent(error))
      ; |  | 
| 3415         fallbackURL = fallbackURL.replace(/%CHANNELSTATUS%/g, encodeURIComponent
      (channelStatus)); |  | 
| 3416         fallbackURL = fallbackURL.replace(/%RESPONSESTATUS%/g, encodeURIComponen
      t(responseStatus)); |  | 
| 3417         var request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstan
      ce(Ci.nsIXMLHttpRequest); |  | 
| 3418         request.mozBackgroundRequest = true; |  | 
| 3419         request.open("GET", fallbackURL); |  | 
| 3420         request.overrideMimeType("text/plain"); |  | 
| 3421         request.channel.loadFlags = request.channel.loadFlags | request.channel.
      INHIBIT_CACHING | request.channel.VALIDATE_ALWAYS; |  | 
| 3422         request.addEventListener("load", function(ev) |  | 
| 3423         { |  | 
| 3424           if (onShutdown.done) |  | 
| 3425           { |  | 
| 3426             return; |  | 
| 3427           } |  | 
| 3428           if (!(subscription.url in FilterStorage.knownSubscriptions)) |  | 
| 3429           { |  | 
| 3430             return; |  | 
| 3431           } |  | 
| 3432           var match = /^(\d+)(?:\s+(\S+))?$/.exec(request.responseText); |  | 
| 3433           if (match && match[1] == "301" && match[2]) |  | 
| 3434           { |  | 
| 3435             subscription.nextURL = match[2]; |  | 
| 3436           } |  | 
| 3437           else if (match && match[1] == "410") |  | 
| 3438           { |  | 
| 3439             var data = "[Adblock]\n" + subscription.filters.map(function(f) |  | 
| 3440             { |  | 
| 3441               return f.text; |  | 
| 3442             }).join("\n"); |  | 
| 3443             var url = "data:text/plain," + encodeURIComponent(data); |  | 
| 3444             var newSubscription = Subscription.fromURL(url); |  | 
| 3445             newSubscription.title = subscription.title; |  | 
| 3446             newSubscription.disabled = subscription.disabled; |  | 
| 3447             FilterStorage.removeSubscription(subscription); |  | 
| 3448             FilterStorage.addSubscription(newSubscription); |  | 
| 3449             Synchronizer.execute(newSubscription); |  | 
| 3450           } |  | 
| 3451         }, false); |  | 
| 3452         request.send(null); |  | 
| 3453       } |  | 
| 3454     } |  | 
| 3455   } |  | 
| 3456   return exports; |  | 
| 3457 })(); |  | 
| OLD | NEW | 
|---|