[Pkg-mozext-commits] [noscript] 05/11: New upstream version 5.0.8.1

David Prévot taffit at moszumanska.debian.org
Sat Aug 5 18:02:52 UTC 2017


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch master
in repository noscript.

commit 2b572cd8af0470681f87f5708ca8783bfdfb35d2
Author: David Prévot <david at tilapin.org>
Date:   Sat Aug 5 11:36:03 2017 -0400

    New upstream version 5.0.8.1
---
 META-INF/manifest.mf                               |   22 +-
 META-INF/mozilla.rsa                               |  Bin 4196 -> 4196 bytes
 META-INF/mozilla.sf                                |    4 +-
 chrome/noscript.jar!/content/noscript/ABE.g        |    7 +-
 chrome/noscript.jar!/content/noscript/ABE.js       |  102 +-
 chrome/noscript.jar!/content/noscript/ABELexer.js  |  726 ++---
 chrome/noscript.jar!/content/noscript/ABEParser.js |    6 +-
 .../noscript.jar!/content/noscript/FrameScript.jsm |    2 +-
 .../content/noscript/InjectionChecker.js           | 3444 ++++++++++----------
 .../content/noscript/MSEInterception.js            |    2 +-
 chrome/noscript.jar!/content/noscript/Main.js      |  364 +--
 chrome/noscript.jar!/content/noscript/MainChild.js |   36 +-
 .../noscript.jar!/content/noscript/MainParent.js   |   26 +-
 chrome/noscript.jar!/content/noscript/Policy.js    |   14 +-
 .../content/noscript/RequestWatchdog.js            |   22 +-
 chrome/noscript.jar!/content/noscript/Thread.js    |    2 +-
 chrome/noscript.jar!/content/noscript/UISync.jsm   |   68 +-
 chrome/noscript.jar!/content/noscript/WebExt.js    |   50 +
 .../content/noscript/WebGLInterception.js          |    2 +-
 chrome/noscript.jar!/content/noscript/about.xul    |   12 +-
 chrome/noscript.jar!/content/noscript/e10sIPC.js   |    1 +
 .../noscript.jar!/content/noscript/e10sParent.js   |    7 +
 .../content/noscript/noscriptOverlay.js            |   65 +-
 .../content/noscript/noscriptOverlay.xul           |    2 +-
 .../locale/bg-BG/noscript/noscript.dtd             |    2 +-
 .../locale/ca-AD/noscript/noscript.dtd             |    2 +-
 .../locale/cs-CZ/noscript/noscript.dtd             |    2 +-
 .../locale/cy-GB/noscript/noscript.dtd             |    2 +-
 .../noscript.jar!/locale/da/noscript/noscript.dtd  |    2 +-
 .../noscript.jar!/locale/de/noscript/noscript.dtd  |   12 +-
 .../locale/de/noscript/noscript.properties         |   14 +-
 .../noscript.jar!/locale/el/noscript/noscript.dtd  |    2 +-
 .../locale/en-GB/noscript/noscript.dtd             |    2 +-
 .../locale/en-US/noscript/noscript.dtd             |    2 +-
 .../noscript.jar!/locale/eo/noscript/noscript.dtd  |    2 +-
 .../locale/es-AR/noscript/noscript.dtd             |    2 +-
 .../locale/es-CL/noscript/noscript.dtd             |    2 +-
 .../locale/es-ES/noscript/noscript.dtd             |    2 +-
 .../locale/et-EE/noscript/noscript.dtd             |    2 +-
 .../noscript.jar!/locale/eu/noscript/noscript.dtd  |    2 +-
 .../locale/fa-IR/noscript/noscript.dtd             |    2 +-
 .../noscript.jar!/locale/fi/noscript/noscript.dtd  |    2 +-
 .../noscript.jar!/locale/fr/noscript/noscript.dtd  |    2 +-
 .../locale/gl-ES/noscript/noscript.dtd             |    2 +-
 .../locale/he-IL/noscript/noscript.dtd             |    2 +-
 .../locale/hr-HR/noscript/noscript.dtd             |    2 +-
 .../noscript.jar!/locale/hsb/noscript/noscript.dtd |    2 +-
 .../locale/hu-HU/noscript/noscript.dtd             |    2 +-
 .../locale/id-ID/noscript/noscript.dtd             |    2 +-
 .../noscript.jar!/locale/it/noscript/noscript.dtd  |    2 +-
 .../locale/ja-JP/noscript/noscript.dtd             |    2 +-
 .../locale/kk-KZ/noscript/noscript.dtd             |    2 +-
 .../locale/km-KH/noscript/noscript.dtd             |    2 +-
 .../locale/ko-KR/noscript/noscript.dtd             |    2 +-
 .../noscript.jar!/locale/lt/noscript/noscript.dtd  |    2 +-
 .../locale/mk-MK/noscript/noscript.dtd             |    2 +-
 .../locale/ms-MY/noscript/noscript.dtd             |    2 +-
 .../locale/nb-NO/noscript/noscript.dtd             |    2 +-
 .../noscript.jar!/locale/nl/noscript/noscript.dtd  |    6 +-
 .../locale/nl/noscript/noscript.properties         |   18 +-
 .../noscript.jar!/locale/pl/noscript/noscript.dtd  |    2 +-
 .../locale/pt-BR/noscript/noscript.dtd             |    2 +-
 .../locale/pt-PT/noscript/noscript.dtd             |    2 +-
 .../noscript.jar!/locale/ro/noscript/noscript.dtd  |    2 +-
 .../locale/sk-SK/noscript/noscript.dtd             |    2 +-
 .../locale/sl-SI/noscript/noscript.dtd             |    2 +-
 .../locale/sr-RS/noscript/noscript.dtd             |    2 +-
 .../locale/sv-SE/noscript/noscript.dtd             |    2 +-
 .../locale/te-IN/noscript/noscript.dtd             |    2 +-
 .../noscript.jar!/locale/th/noscript/noscript.dtd  |    2 +-
 .../locale/tr/noscript/about.properties            |   14 +-
 .../noscript.jar!/locale/tr/noscript/noscript.dtd  |  172 +-
 .../locale/tr/noscript/noscript.properties         |  112 +-
 .../noscript.jar!/locale/vi/noscript/noscript.dtd  |    2 +-
 .../locale/zh-CN/noscript/noscript.dtd             |    2 +-
 .../locale/zh-TW/noscript/noscript.dtd             |    2 +-
 defaults/preferences/noscript.js                   |    7 +-
 install.rdf                                        |   22 +-
 webextension/background.js                         |   70 +
 webextension/manifest.json                         |   15 +
 80 files changed, 2886 insertions(+), 2652 deletions(-)

diff --git a/META-INF/manifest.mf b/META-INF/manifest.mf
index 6b2d0ef..23a7483 100644
--- a/META-INF/manifest.mf
+++ b/META-INF/manifest.mf
@@ -2,8 +2,8 @@ Manifest-Version: 1.0
 
 Name: install.rdf
 Digest-Algorithms: MD5 SHA1
-MD5-Digest: caNgYy9PWJ5F6YSpQYgCSw==
-SHA1-Digest: 4A+hj6hQjUmfIPay9kjH0CaaNb0=
+MD5-Digest: lVvLO2aI7uSHlqRyKu1r/Q==
+SHA1-Digest: wZdNfcW09flTIAKTuy/HAAFeZ4E=
 
 Name: chrome.manifest
 Digest-Algorithms: MD5 SHA1
@@ -27,8 +27,8 @@ SHA1-Digest: 624YpFdNjCFbDE7kLhN+vbF9hgM=
 
 Name: chrome/noscript.jar
 Digest-Algorithms: MD5 SHA1
-MD5-Digest: Dwrbo1WkkwjjUAjPUMThxQ==
-SHA1-Digest: jGl8Aj3+UymudSLA4t036vit2J8=
+MD5-Digest: L7rk1WghDL50vZDdMJQbxA==
+SHA1-Digest: IoFGE5nm/ZKJCx1nszPCOWkIzBI=
 
 Name: components/noscriptService.js
 Digest-Algorithms: MD5 SHA1
@@ -37,6 +37,16 @@ SHA1-Digest: CST2HsndXBM/v2zddWR+BmatjQc=
 
 Name: defaults/preferences/noscript.js
 Digest-Algorithms: MD5 SHA1
-MD5-Digest: 977lodArig1fSazzM7sM5Q==
-SHA1-Digest: Qq1OAv0a7ny/GBMLB6sDy4m2HSA=
+MD5-Digest: 3yV/nDojJnVmeY9iN7AIuQ==
+SHA1-Digest: fd1EJ8c2cgXcI90q/A/GB8ltqqo=
+
+Name: webextension/background.js
+Digest-Algorithms: MD5 SHA1
+MD5-Digest: jGrIPCJYL7AeKRiDAm4dUg==
+SHA1-Digest: wVxE8Pl4vQarPR3kbtPE53w077E=
+
+Name: webextension/manifest.json
+Digest-Algorithms: MD5 SHA1
+MD5-Digest: 2h5QeobYFUtfVOGAIlN4SA==
+SHA1-Digest: KIdo2Ytov7HDjqhoUmOJ/Ghg7xs=
 
diff --git a/META-INF/mozilla.rsa b/META-INF/mozilla.rsa
index 4328729..39e512c 100644
Binary files a/META-INF/mozilla.rsa and b/META-INF/mozilla.rsa differ
diff --git a/META-INF/mozilla.sf b/META-INF/mozilla.sf
index 76603dc..ce90b10 100644
--- a/META-INF/mozilla.sf
+++ b/META-INF/mozilla.sf
@@ -1,4 +1,4 @@
 Signature-Version: 1.0
-MD5-Digest-Manifest: KoYmjTGhdTAD4z7GNShXvw==
-SHA1-Digest-Manifest: opzx9k7FFshsRPlSFms476LOtLU=
+MD5-Digest-Manifest: O7S4akQjenJ1qD3va4JVBg==
+SHA1-Digest-Manifest: 3AOlSGmqlieLUT55pSHcRuskbG8=
 
diff --git a/chrome/noscript.jar!/content/noscript/ABE.g b/chrome/noscript.jar!/content/noscript/ABE.g
index 30e8267..bd9e4a3 100644
--- a/chrome/noscript.jar!/content/noscript/ABE.g
+++ b/chrome/noscript.jar!/content/noscript/ABE.g
@@ -24,7 +24,7 @@ oresource: resource | 'SELF' | 'SELF+' | 'SELF++' ;
 resource  : REGEXP | GLOB | URI | LOCATION ;
 action    : A_DENY | A_LOGOUT | A_SANDBOX  | A_ACCEPT ;
 
-T_SITE    : 'Site' ;
+T_SITE    : ('Site' | 'Request') ;
 T_FROM    : ('f' | 'F') 'rom' ;
 A_DENY    : 'Deny' ;
 A_LOGOUT  : 'Logout' | 'Anon' 'ymize'? ;
@@ -43,8 +43,9 @@ REGEXP    : '^' ~'\n'+ ;
 ALL       : 'ALL' ;
 SUB       : 'SUB' ;
 INC       : 'INC' 'LUSION'? ;
-INC_TYPE   : 'OTHER' | 'SCRIPT' | 'IMAGE' | 'CSS' | 'OBJ' | 'SUBDOC' | 'XBL' | 'PING' | 'XHR' | 'OBJSUB' | 'DTD' | 'FONT' | 'MEDIA' ;
-HTTPVERB  : 'A'..'Z' 'A'..'Z'+ ;
+HTTPVERB  : 'GET' | 'POST' | 'PUT' | 'HEAD' | 'PATCH' | 'DELETE' | 'TRACE' | 'OPTIONS';
+INC_TYPE  : 'A'..'Z' ('A'..'Z' | 'A'..'Z' '_' 'A'..'Z')+ ;
+
 
 COMMA     : ',' ;
 LPAR      : '(' ;
diff --git a/chrome/noscript.jar!/content/noscript/ABE.js b/chrome/noscript.jar!/content/noscript/ABE.js
index 28b438b..6697761 100644
--- a/chrome/noscript.jar!/content/noscript/ABE.js
+++ b/chrome/noscript.jar!/content/noscript/ABE.js
@@ -152,7 +152,7 @@ var ABE = {
     const channel = req.channel;
     const loadFlags = channel.loadFlags;
 
-    var browserReq =  req.originURI.schemeIs("chrome") && !req.external;
+    var browserReq = req.originURI.schemeIs("chrome") && !req.external;
 
     if (browserReq &&
         (
@@ -425,11 +425,46 @@ var ABE = {
   setSandboxed(channel, sandboxed = true) {
     ABE.reqData(channel).sandboxed = sandboxed;
   },
-  sandbox: function(docShell, sandboxed) {
-    docShell.allowJavascript = docShell.allowPlugins =
-        docShell.allowMetaRedirects= docShell.allowSubframes = !sandboxed;
-  },
 
+  get cspHeaderValue() {
+    delete this.cspHeaderValue;
+    let prefs = ABEStorage.prefs;
+    let delim;
+    try {
+      delim = prefs.getCharPref("cspHeaderDelim") || "ABE";
+    } catch (e) {
+      delim = `ABE${Math.random().toString().replace(".", "-")}`;
+      prefs.setCharPref("cspHeaderDelim", delim);
+    }
+    let value = `${delim}; child-src 'self'; object-src 'none'; script-src 'none'; ${delim};`;
+    return (this.cspHeaderValue = value);
+  },
+  enforceSandbox(channel, enforcing) {
+    const CSP = "Content-Security-Policy";
+    let value = this.cspHeaderValue;
+    try {
+      let currentPolicy = channel.getResponseHeader(CSP);
+      if (currentPolicy.includes(value)) {
+        if (enforcing) {
+          return true;
+        }
+        channel.setResponseHeader(CSP, currentPolicy.replace(value, ''), false);
+        return false;
+      }
+    } catch (e) {}
+    if (enforcing) {
+       try {
+         channel.setResponseHeader(CSP, value, true);
+         return true;
+       }catch(e) {
+         Cu.reportError(e);
+       }
+    }
+    return false;
+  },
+  handleSandbox(channel) {
+    this.enforceSandbox(channel, this.isSandboxed(channel));
+  },
 
   updateRedirectChain: function(oldChannel, newChannel) {
     this._handleDownloadRedirection(oldChannel, newChannel);
@@ -548,11 +583,7 @@ var ABEActions = {
   },
 
   sandbox: function(req) {
-    ABE.reqData(req).sandboxed = true;
-    if (req.isDoc) {
-      var docShell = DOM.getDocShellForWindow(req.window);
-      if (docShell) ABE.sandbox(docShell);
-    }
+    ABE.setSandboxed(req.channel);
     return ABERes.DONE;
   }
 }
@@ -803,22 +834,41 @@ ABEPredicate.prototype = {
   get _inclusionTypesMap() {
     delete this.__proto__._inclusionTypesMap;
     const CP = Ci.nsIContentPolicy;
-    return this.__proto__._inclusionTypesMap =
-    {
-      "OTHER": CP.TYPE_OTHER,
-      "FONT": CP.TYPE_FONT,
-      "SCRIPT": CP.TYPE_SCRIPT,
-      "IMAGE": [CP.TYPE_IMAGE, CP.TYPE_IMAGESET],
-      "CSS": CP.TYPE_STYLESHEET,
-      "OBJ": [CP.TYPE_OBJECT, CP.TYPE_OBJECT_SUBREQUEST],
-      "MEDIA": CP.TYPE_MEDIA,
-      "SUBDOC": CP.TYPE_SUBDOCUMENT,
-      "XBL": CP.TYPE_XBL,
-      "PING": CP.TYPE_PING,
-      "XHR": CP.TYPE_XMLHTTPREQUEST,
-      "OBJSUB": CP.TYPE_OBJECT_SUBREQUEST,
-      "DTD": CP.TYPE_DTD
+    let map = {
+      CSS: CP.TYPE_STYLESHEET,
+      DOCUMENT: CP.TYPE_DOCUMENT, // placeholder, should never happen for inclusions
+      DTD: CP.TYPE_DTD,
+      FONT: CP.TYPE_FONT,
+      IMAGE: [CP.TYPE_IMAGE, CP.TYPE_IMAGESET],
+      MEDIA: CP.TYPE_MEDIA,
+      OBJ: [CP.TYPE_OBJECT, CP.TYPE_OBJECT_SUBREQUEST],
+      OBJSUB: CP.TYPE_OBJECT_SUBREQUEST,
+      OTHER: [CP.TYPE_OTHER],
+      SCRIPT: CP.TYPE_SCRIPT,
+      SUBDOC: CP.TYPE_SUBDOCUMENT,
+      UNKNOWN: CP.TYPE_OTHER,
+      XHR: [CP.TYPE_XMLHTTPREQUEST, CP.TYPE_FETCH],
     };
+    let mappedTypes = new Set();
+    for (let k in map) {
+      let v = map[k];
+      if (Array.isArray(v)) {
+        for (let t of v) mappedTypes.add(t);
+      } else {
+        mappedTypes.add(v);
+      }
+    }
+
+    let cpTypes = Object.keys(CP).filter(k => k.startsWith("TYPE_") && !k.startsWith("TYPE_INTERNAL_"));
+    for (let key of cpTypes) {
+      let name = key.substring(5);
+      if (!(name in map)) {
+        let type = CP[key];
+        map[name] = type;
+        if (!mappedTypes.has(type)) map.OTHER.push(type);
+      }
+    }
+    return (this.__proto__._inclusionTypesMap = map);
   },
 
   _methodFilter: function(m) {
@@ -1105,7 +1155,7 @@ ABERequest.prototype = Lang.memoize({
 
   type: function() {
     try {
-      return this.early ? this.channel.type : PolicyState.extract(this.channel).contentType;
+      return this.early ? this.channel.type : this.channel.loadInfo.externalContentPolicyType;
     } catch(e) {
       ABE.log("Error retrieving type of " + this.destination + ": " + e); // should happen for favicons only
     }
diff --git a/chrome/noscript.jar!/content/noscript/ABELexer.js b/chrome/noscript.jar!/content/noscript/ABELexer.js
index 49fdd74..e4f811e 100644
--- a/chrome/noscript.jar!/content/noscript/ABELexer.js
+++ b/chrome/noscript.jar!/content/noscript/ABELexer.js
@@ -1,4 +1,4 @@
-// $ANTLR 3.1.1 ABE.g 2011-03-21 12:45:42
+// $ANTLR 3.1.1 ABE.g 2017-07-26 00:44:40
 
 var ABELexer = function(input, state) {
 // alternate constructor @todo
@@ -11,8 +11,8 @@ var ABELexer = function(input, state) {
     (function(){
     }).call(this);
 
-    this.dfa7 = new ABELexer.DFA7(this);
-    this.dfa10 = new ABELexer.DFA10(this);
+    this.dfa8 = new ABELexer.DFA8(this);
+    this.dfa11 = new ABELexer.DFA11(this);
     ABELexer.superclass.constructor.call(this, input, state);
 
 
@@ -149,9 +149,41 @@ org.antlr.lang.augmentObject(ABELexer.prototype, {
         try {
             var _type = this.T_SITE;
             var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
-            // ABE.g:27:11: ( 'Site' )
-            // ABE.g:27:13: 'Site'
-            this.match("Site"); 
+            // ABE.g:27:11: ( ( 'Site' | 'Request' ) )
+            // ABE.g:27:13: ( 'Site' | 'Request' )
+            // ABE.g:27:13: ( 'Site' | 'Request' )
+            var alt1=2;
+            var LA1_0 = this.input.LA(1);
+
+            if ( (LA1_0=='S') ) {
+                alt1=1;
+            }
+            else if ( (LA1_0=='R') ) {
+                alt1=2;
+            }
+            else {
+                var nvae =
+                    new org.antlr.runtime.NoViableAltException("", 1, 0, this.input);
+
+                throw nvae;
+            }
+            switch (alt1) {
+                case 1 :
+                    // ABE.g:27:14: 'Site'
+                    this.match("Site"); 
+
+
+
+                    break;
+                case 2 :
+                    // ABE.g:27:23: 'Request'
+                    this.match("Request"); 
+
+
+
+                    break;
+
+            }
 
 
 
@@ -219,22 +251,22 @@ org.antlr.lang.augmentObject(ABELexer.prototype, {
             var _type = this.A_LOGOUT;
             var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
             // ABE.g:30:11: ( 'Logout' | 'Anon' ( 'ymize' )? )
-            var alt2=2;
-            var LA2_0 = this.input.LA(1);
+            var alt3=2;
+            var LA3_0 = this.input.LA(1);
 
-            if ( (LA2_0=='L') ) {
-                alt2=1;
+            if ( (LA3_0=='L') ) {
+                alt3=1;
             }
-            else if ( (LA2_0=='A') ) {
-                alt2=2;
+            else if ( (LA3_0=='A') ) {
+                alt3=2;
             }
             else {
                 var nvae =
-                    new org.antlr.runtime.NoViableAltException("", 2, 0, this.input);
+                    new org.antlr.runtime.NoViableAltException("", 3, 0, this.input);
 
                 throw nvae;
             }
-            switch (alt2) {
+            switch (alt3) {
                 case 1 :
                     // ABE.g:30:13: 'Logout'
                     this.match("Logout"); 
@@ -247,13 +279,13 @@ org.antlr.lang.augmentObject(ABELexer.prototype, {
                     this.match("Anon"); 
 
                     // ABE.g:30:31: ( 'ymize' )?
-                    var alt1=2;
-                    var LA1_0 = this.input.LA(1);
+                    var alt2=2;
+                    var LA2_0 = this.input.LA(1);
 
-                    if ( (LA1_0=='y') ) {
-                        alt1=1;
+                    if ( (LA2_0=='y') ) {
+                        alt2=1;
                     }
-                    switch (alt1) {
+                    switch (alt2) {
                         case 1 :
                             // ABE.g:30:31: 'ymize'
                             this.match("ymize"); 
@@ -392,18 +424,18 @@ org.antlr.lang.augmentObject(ABELexer.prototype, {
             // ABE.g:39:13: URI_START ( URI_PART )+
             this.mURI_START(); 
             // ABE.g:39:23: ( URI_PART )+
-            var cnt3=0;
-            loop3:
+            var cnt4=0;
+            loop4:
             do {
-                var alt3=2;
-                var LA3_0 = this.input.LA(1);
+                var alt4=2;
+                var LA4_0 = this.input.LA(1);
 
-                if ( (LA3_0=='#'||(LA3_0>='%' && LA3_0<='&')||(LA3_0>=',' && LA3_0<=';')||LA3_0=='='||(LA3_0>='?' && LA3_0<='[')||LA3_0==']'||LA3_0=='_'||(LA3_0>='a' && LA3_0<='z')||LA3_0=='~') ) {
-                    alt3=1;
+                if ( (LA4_0=='#'||(LA4_0>='%' && LA4_0<='&')||(LA4_0>=',' && LA4_0<=';')||LA4_0=='='||(LA4_0>='?' && LA4_0<='[')||LA4_0==']'||LA4_0=='_'||(LA4_0>='a' && LA4_0<='z')||LA4_0=='~') ) {
+                    alt4=1;
                 }
 
 
-                switch (alt3) {
+                switch (alt4) {
                 case 1 :
                     // ABE.g:39:23: URI_PART
                     this.mURI_PART(); 
@@ -412,13 +444,13 @@ org.antlr.lang.augmentObject(ABELexer.prototype, {
                     break;
 
                 default :
-                    if ( cnt3 >= 1 ) {
-                        break loop3;
+                    if ( cnt4 >= 1 ) {
+                        break loop4;
                     }
-                        var eee = new org.antlr.runtime.EarlyExitException(3, this.input);
+                        var eee = new org.antlr.runtime.EarlyExitException(4, this.input);
                         throw eee;
                 }
-                cnt3++;
+                cnt4++;
             } while (true);
 
 
@@ -449,17 +481,17 @@ org.antlr.lang.augmentObject(ABELexer.prototype, {
                 throw mse;}
 
             // ABE.g:40:37: ( URI_PART | '*' )*
-            loop4:
+            loop5:
             do {
-                var alt4=2;
-                var LA4_0 = this.input.LA(1);
+                var alt5=2;
+                var LA5_0 = this.input.LA(1);
 
-                if ( (LA4_0=='#'||(LA4_0>='%' && LA4_0<='&')||LA4_0=='*'||(LA4_0>=',' && LA4_0<=';')||LA4_0=='='||(LA4_0>='?' && LA4_0<='[')||LA4_0==']'||LA4_0=='_'||(LA4_0>='a' && LA4_0<='z')||LA4_0=='~') ) {
-                    alt4=1;
+                if ( (LA5_0=='#'||(LA5_0>='%' && LA5_0<='&')||LA5_0=='*'||(LA5_0>=',' && LA5_0<=';')||LA5_0=='='||(LA5_0>='?' && LA5_0<='[')||LA5_0==']'||LA5_0=='_'||(LA5_0>='a' && LA5_0<='z')||LA5_0=='~') ) {
+                    alt5=1;
                 }
 
 
-                switch (alt4) {
+                switch (alt5) {
                 case 1 :
                     // ABE.g:
                     if ( this.input.LA(1)=='#'||(this.input.LA(1)>='%' && this.input.LA(1)<='&')||this.input.LA(1)=='*'||(this.input.LA(1)>=',' && this.input.LA(1)<=';')||this.input.LA(1)=='='||(this.input.LA(1)>='?' && this.input.LA(1)<='[')||this.input.LA(1)==']'||this.input.LA(1)=='_'||(this.input.LA(1)>='a' && this.input.LA(1)<='z')||this.input.LA(1)=='~' ) {
@@ -476,7 +508,7 @@ org.antlr.lang.augmentObject(ABELexer.prototype, {
                     break;
 
                 default :
-                    break loop4;
+                    break loop5;
                 }
             } while (true);
 
@@ -500,18 +532,18 @@ org.antlr.lang.augmentObject(ABELexer.prototype, {
             // ABE.g:41:13: '^' (~ '\\n' )+
             this.match('^'); 
             // ABE.g:41:17: (~ '\\n' )+
-            var cnt5=0;
-            loop5:
+            var cnt6=0;
+            loop6:
             do {
-                var alt5=2;
-                var LA5_0 = this.input.LA(1);
+                var alt6=2;
+                var LA6_0 = this.input.LA(1);
 
-                if ( ((LA5_0>='\u0000' && LA5_0<='\t')||(LA5_0>='\u000B' && LA5_0<='\uFFFF')) ) {
-                    alt5=1;
+                if ( ((LA6_0>='\u0000' && LA6_0<='\t')||(LA6_0>='\u000B' && LA6_0<='\uFFFF')) ) {
+                    alt6=1;
                 }
 
 
-                switch (alt5) {
+                switch (alt6) {
                 case 1 :
                     // ABE.g:41:17: ~ '\\n'
                     if ( (this.input.LA(1)>='\u0000' && this.input.LA(1)<='\t')||(this.input.LA(1)>='\u000B' && this.input.LA(1)<='\uFFFF') ) {
@@ -528,13 +560,13 @@ org.antlr.lang.augmentObject(ABELexer.prototype, {
                     break;
 
                 default :
-                    if ( cnt5 >= 1 ) {
-                        break loop5;
+                    if ( cnt6 >= 1 ) {
+                        break loop6;
                     }
-                        var eee = new org.antlr.runtime.EarlyExitException(5, this.input);
+                        var eee = new org.antlr.runtime.EarlyExitException(6, this.input);
                         throw eee;
                 }
-                cnt5++;
+                cnt6++;
             } while (true);
 
 
@@ -598,13 +630,13 @@ org.antlr.lang.augmentObject(ABELexer.prototype, {
             this.match("INC"); 
 
             // ABE.g:45:19: ( 'LUSION' )?
-            var alt6=2;
-            var LA6_0 = this.input.LA(1);
+            var alt7=2;
+            var LA7_0 = this.input.LA(1);
 
-            if ( (LA6_0=='L') ) {
-                alt6=1;
+            if ( (LA7_0=='L') ) {
+                alt7=1;
             }
-            switch (alt6) {
+            switch (alt7) {
                 case 1 :
                     // ABE.g:45:19: 'LUSION'
                     this.match("LUSION"); 
@@ -626,102 +658,67 @@ org.antlr.lang.augmentObject(ABELexer.prototype, {
     },
     // $ANTLR end "INC",
 
-    // $ANTLR start INC_TYPE
-    mINC_TYPE: function()  {
+    // $ANTLR start HTTPVERB
+    mHTTPVERB: function()  {
         try {
-            var _type = this.INC_TYPE;
+            var _type = this.HTTPVERB;
             var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
-            // ABE.g:46:12: ( 'OTHER' | 'SCRIPT' | 'IMAGE' | 'CSS' | 'OBJ' | 'SUBDOC' | 'XBL' | 'PING' | 'XHR' | 'OBJSUB' | 'DTD' | 'FONT' | 'MEDIA' )
-            var alt7=13;
-            alt7 = this.dfa7.predict(this.input);
-            switch (alt7) {
+            // ABE.g:46:11: ( 'GET' | 'POST' | 'PUT' | 'HEAD' | 'PATCH' | 'DELETE' | 'TRACE' | 'OPTIONS' )
+            var alt8=8;
+            alt8 = this.dfa8.predict(this.input);
+            switch (alt8) {
                 case 1 :
-                    // ABE.g:46:14: 'OTHER'
-                    this.match("OTHER"); 
+                    // ABE.g:46:13: 'GET'
+                    this.match("GET"); 
 
 
 
                     break;
                 case 2 :
-                    // ABE.g:46:24: 'SCRIPT'
-                    this.match("SCRIPT"); 
+                    // ABE.g:46:21: 'POST'
+                    this.match("POST"); 
 
 
 
                     break;
                 case 3 :
-                    // ABE.g:46:35: 'IMAGE'
-                    this.match("IMAGE"); 
+                    // ABE.g:46:30: 'PUT'
+                    this.match("PUT"); 
 
 
 
                     break;
                 case 4 :
-                    // ABE.g:46:45: 'CSS'
-                    this.match("CSS"); 
+                    // ABE.g:46:38: 'HEAD'
+                    this.match("HEAD"); 
 
 
 
                     break;
                 case 5 :
-                    // ABE.g:46:53: 'OBJ'
-                    this.match("OBJ"); 
+                    // ABE.g:46:47: 'PATCH'
+                    this.match("PATCH"); 
 
 
 
                     break;
                 case 6 :
-                    // ABE.g:46:61: 'SUBDOC'
-                    this.match("SUBDOC"); 
+                    // ABE.g:46:57: 'DELETE'
+                    this.match("DELETE"); 
 
 
 
                     break;
                 case 7 :
-                    // ABE.g:46:72: 'XBL'
-                    this.match("XBL"); 
+                    // ABE.g:46:68: 'TRACE'
+                    this.match("TRACE"); 
 
 
 
                     break;
                 case 8 :
-                    // ABE.g:46:80: 'PING'
-                    this.match("PING"); 
-
-
-
-                    break;
-                case 9 :
-                    // ABE.g:46:89: 'XHR'
-                    this.match("XHR"); 
-
-
-
-                    break;
-                case 10 :
-                    // ABE.g:46:97: 'OBJSUB'
-                    this.match("OBJSUB"); 
-
-
-
-                    break;
-                case 11 :
-                    // ABE.g:46:108: 'DTD'
-                    this.match("DTD"); 
-
-
-
-                    break;
-                case 12 :
-                    // ABE.g:46:116: 'FONT'
-                    this.match("FONT"); 
-
-
-
-                    break;
-                case 13 :
-                    // ABE.g:46:125: 'MEDIA'
-                    this.match("MEDIA"); 
+                    // ABE.g:46:78: 'OPTIONS'
+                    this.match("OPTIONS"); 
 
 
 
@@ -734,44 +731,61 @@ org.antlr.lang.augmentObject(ABELexer.prototype, {
         finally {
         }
     },
-    // $ANTLR end "INC_TYPE",
+    // $ANTLR end "HTTPVERB",
 
-    // $ANTLR start HTTPVERB
-    mHTTPVERB: function()  {
+    // $ANTLR start INC_TYPE
+    mINC_TYPE: function()  {
         try {
-            var _type = this.HTTPVERB;
+            var _type = this.INC_TYPE;
             var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
-            // ABE.g:47:11: ( 'A' .. 'Z' ( 'A' .. 'Z' )+ )
-            // ABE.g:47:13: 'A' .. 'Z' ( 'A' .. 'Z' )+
+            // ABE.g:47:11: ( 'A' .. 'Z' ( 'A' .. 'Z' | 'A' .. 'Z' '_' 'A' .. 'Z' )+ )
+            // ABE.g:47:13: 'A' .. 'Z' ( 'A' .. 'Z' | 'A' .. 'Z' '_' 'A' .. 'Z' )+
             this.matchRange('A','Z'); 
-            // ABE.g:47:22: ( 'A' .. 'Z' )+
-            var cnt8=0;
-            loop8:
+            // ABE.g:47:22: ( 'A' .. 'Z' | 'A' .. 'Z' '_' 'A' .. 'Z' )+
+            var cnt9=0;
+            loop9:
             do {
-                var alt8=2;
-                var LA8_0 = this.input.LA(1);
+                var alt9=3;
+                var LA9_0 = this.input.LA(1);
+
+                if ( ((LA9_0>='A' && LA9_0<='Z')) ) {
+                    var LA9_2 = this.input.LA(2);
+
+                    if ( (LA9_2=='_') ) {
+                        alt9=2;
+                    }
+
+                    else {
+                        alt9=1;
+                    }
 
-                if ( ((LA8_0>='A' && LA8_0<='Z')) ) {
-                    alt8=1;
                 }
 
 
-                switch (alt8) {
+                switch (alt9) {
                 case 1 :
-                    // ABE.g:47:22: 'A' .. 'Z'
+                    // ABE.g:47:23: 'A' .. 'Z'
+                    this.matchRange('A','Z'); 
+
+
+                    break;
+                case 2 :
+                    // ABE.g:47:34: 'A' .. 'Z' '_' 'A' .. 'Z'
+                    this.matchRange('A','Z'); 
+                    this.match('_'); 
                     this.matchRange('A','Z'); 
 
 
                     break;
 
                 default :
-                    if ( cnt8 >= 1 ) {
-                        break loop8;
+                    if ( cnt9 >= 1 ) {
+                        break loop9;
                     }
-                        var eee = new org.antlr.runtime.EarlyExitException(8, this.input);
+                        var eee = new org.antlr.runtime.EarlyExitException(9, this.input);
                         throw eee;
                 }
-                cnt8++;
+                cnt9++;
             } while (true);
 
 
@@ -783,15 +797,15 @@ org.antlr.lang.augmentObject(ABELexer.prototype, {
         finally {
         }
     },
-    // $ANTLR end "HTTPVERB",
+    // $ANTLR end "INC_TYPE",
 
     // $ANTLR start COMMA
     mCOMMA: function()  {
         try {
             var _type = this.COMMA;
             var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
-            // ABE.g:49:11: ( ',' )
-            // ABE.g:49:13: ','
+            // ABE.g:50:11: ( ',' )
+            // ABE.g:50:13: ','
             this.match(','); 
 
 
@@ -809,8 +823,8 @@ org.antlr.lang.augmentObject(ABELexer.prototype, {
         try {
             var _type = this.LPAR;
             var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
-            // ABE.g:50:11: ( '(' )
-            // ABE.g:50:13: '('
+            // ABE.g:51:11: ( '(' )
+            // ABE.g:51:13: '('
             this.match('('); 
 
 
@@ -828,8 +842,8 @@ org.antlr.lang.augmentObject(ABELexer.prototype, {
         try {
             var _type = this.RPAR;
             var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
-            // ABE.g:51:11: ( ')' )
-            // ABE.g:51:13: ')'
+            // ABE.g:52:11: ( ')' )
+            // ABE.g:52:13: ')'
             this.match(')'); 
 
 
@@ -847,8 +861,8 @@ org.antlr.lang.augmentObject(ABELexer.prototype, {
         try {
             var _type = this.WS;
             var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
-            // ABE.g:53:11: ( ( ' ' | '\\r' | '\\t' | '\\u000C' | '\\n' ) )
-            // ABE.g:53:14: ( ' ' | '\\r' | '\\t' | '\\u000C' | '\\n' )
+            // ABE.g:54:11: ( ( ' ' | '\\r' | '\\t' | '\\u000C' | '\\n' ) )
+            // ABE.g:54:14: ( ' ' | '\\r' | '\\t' | '\\u000C' | '\\n' )
             if ( (this.input.LA(1)>='\t' && this.input.LA(1)<='\n')||(this.input.LA(1)>='\f' && this.input.LA(1)<='\r')||this.input.LA(1)==' ' ) {
                 this.input.consume();
 
@@ -875,23 +889,23 @@ org.antlr.lang.augmentObject(ABELexer.prototype, {
         try {
             var _type = this.COMMENT;
             var _channel = org.antlr.runtime.BaseRecognizer.DEFAULT_TOKEN_CHANNEL;
-            // ABE.g:54:9: ( '#' (~ '\\n' )* )
-            // ABE.g:54:11: '#' (~ '\\n' )*
+            // ABE.g:55:9: ( '#' (~ '\\n' )* )
+            // ABE.g:55:11: '#' (~ '\\n' )*
             this.match('#'); 
-            // ABE.g:54:15: (~ '\\n' )*
-            loop9:
+            // ABE.g:55:15: (~ '\\n' )*
+            loop10:
             do {
-                var alt9=2;
-                var LA9_0 = this.input.LA(1);
+                var alt10=2;
+                var LA10_0 = this.input.LA(1);
 
-                if ( ((LA9_0>='\u0000' && LA9_0<='\t')||(LA9_0>='\u000B' && LA9_0<='\uFFFF')) ) {
-                    alt9=1;
+                if ( ((LA10_0>='\u0000' && LA10_0<='\t')||(LA10_0>='\u000B' && LA10_0<='\uFFFF')) ) {
+                    alt10=1;
                 }
 
 
-                switch (alt9) {
+                switch (alt10) {
                 case 1 :
-                    // ABE.g:54:15: ~ '\\n'
+                    // ABE.g:55:15: ~ '\\n'
                     if ( (this.input.LA(1)>='\u0000' && this.input.LA(1)<='\t')||(this.input.LA(1)>='\u000B' && this.input.LA(1)<='\uFFFF') ) {
                         this.input.consume();
 
@@ -906,7 +920,7 @@ org.antlr.lang.augmentObject(ABELexer.prototype, {
                     break;
 
                 default :
-                    break loop9;
+                    break loop10;
                 }
             } while (true);
 
@@ -923,10 +937,10 @@ org.antlr.lang.augmentObject(ABELexer.prototype, {
     // $ANTLR end "COMMENT",
 
     mTokens: function() {
-        // ABE.g:1:8: ( T__28 | T__29 | T__30 | T_SITE | T_FROM | A_DENY | A_LOGOUT | A_SANDBOX | A_ACCEPT | LOCATION | URI | GLOB | REGEXP | ALL | SUB | INC | INC_TYPE | HTTPVERB | COMMA | LPAR | RPAR | WS | COMMENT )
-        var alt10=23;
-        alt10 = this.dfa10.predict(this.input);
-        switch (alt10) {
+        // ABE.g:1:8: ( T__28 | T__29 | T__30 | T_SITE | T_FROM | A_DENY | A_LOGOUT | A_SANDBOX | A_ACCEPT | LOCATION | URI | GLOB | REGEXP | ALL | SUB | INC | HTTPVERB | INC_TYPE | COMMA | LPAR | RPAR | WS | COMMENT )
+        var alt11=23;
+        alt11 = this.dfa11.predict(this.input);
+        switch (alt11) {
             case 1 :
                 // ABE.g:1:10: T__28
                 this.mT__28(); 
@@ -1024,14 +1038,14 @@ org.antlr.lang.augmentObject(ABELexer.prototype, {
 
                 break;
             case 17 :
-                // ABE.g:1:114: INC_TYPE
-                this.mINC_TYPE(); 
+                // ABE.g:1:114: HTTPVERB
+                this.mHTTPVERB(); 
 
 
                 break;
             case 18 :
-                // ABE.g:1:123: HTTPVERB
-                this.mHTTPVERB(); 
+                // ABE.g:1:123: INC_TYPE
+                this.mINC_TYPE(); 
 
 
                 break;
@@ -1073,316 +1087,290 @@ org.antlr.lang.augmentObject(ABELexer.prototype, {
 }, true); // important to pass true to overwrite default implementations
 
 org.antlr.lang.augmentObject(ABELexer, {
-    DFA7_eotS:
-        "\u0010\uffff\u0001\u0012\u0002\uffff",
-    DFA7_eofS:
-        "\u0013\uffff",
-    DFA7_minS:
-        "\u0001\u0043\u0001\u0042\u0001\u0043\u0002\uffff\u0001\u0042\u0005"+
-    "\uffff\u0001\u004a\u0004\uffff\u0001\u0053\u0002\uffff",
-    DFA7_maxS:
-        "\u0001\u0058\u0001\u0054\u0001\u0055\u0002\uffff\u0001\u0048\u0005"+
-    "\uffff\u0001\u004a\u0004\uffff\u0001\u0053\u0002\uffff",
-    DFA7_acceptS:
-        "\u0003\uffff\u0001\u0003\u0001\u0004\u0001\uffff\u0001\u0008\u0001"+
-    "\u000b\u0001\u000c\u0001\u000d\u0001\u0001\u0001\uffff\u0001\u0002\u0001"+
-    "\u0006\u0001\u0007\u0001\u0009\u0001\uffff\u0001\u000a\u0001\u0005",
-    DFA7_specialS:
-        "\u0013\uffff}>",
-    DFA7_transitionS: [
-            "\u0001\u0004\u0001\u0007\u0001\uffff\u0001\u0008\u0002\uffff"+
-            "\u0001\u0003\u0003\uffff\u0001\u0009\u0001\uffff\u0001\u0001"+
-            "\u0001\u0006\u0002\uffff\u0001\u0002\u0004\uffff\u0001\u0005",
-            "\u0001\u000b\u0011\uffff\u0001\u000a",
-            "\u0001\u000c\u0011\uffff\u0001\u000d",
-            "",
-            "",
-            "\u0001\u000e\u0005\uffff\u0001\u000f",
+    DFA8_eotS:
+        "\u000a\uffff",
+    DFA8_eofS:
+        "\u000a\uffff",
+    DFA8_minS:
+        "\u0001\u0044\u0001\uffff\u0001\u0041\u0007\uffff",
+    DFA8_maxS:
+        "\u0001\u0054\u0001\uffff\u0001\u0055\u0007\uffff",
+    DFA8_acceptS:
+        "\u0001\uffff\u0001\u0001\u0001\uffff\u0001\u0004\u0001\u0006\u0001"+
+    "\u0007\u0001\u0008\u0001\u0002\u0001\u0003\u0001\u0005",
+    DFA8_specialS:
+        "\u000a\uffff}>",
+    DFA8_transitionS: [
+            "\u0001\u0004\u0002\uffff\u0001\u0001\u0001\u0003\u0006\uffff"+
+            "\u0001\u0006\u0001\u0002\u0003\uffff\u0001\u0005",
             "",
+            "\u0001\u0009\u000d\uffff\u0001\u0007\u0005\uffff\u0001\u0008",
             "",
             "",
             "",
             "",
-            "\u0001\u0010",
             "",
             "",
-            "",
-            "",
-            "\u0001\u0011",
-            "",
             ""
     ]
 });
 
 org.antlr.lang.augmentObject(ABELexer, {
-    DFA7_eot:
-        org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA7_eotS),
-    DFA7_eof:
-        org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA7_eofS),
-    DFA7_min:
-        org.antlr.runtime.DFA.unpackEncodedStringToUnsignedChars(ABELexer.DFA7_minS),
-    DFA7_max:
-        org.antlr.runtime.DFA.unpackEncodedStringToUnsignedChars(ABELexer.DFA7_maxS),
-    DFA7_accept:
-        org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA7_acceptS),
-    DFA7_special:
-        org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA7_specialS),
-    DFA7_transition: (function() {
+    DFA8_eot:
+        org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA8_eotS),
+    DFA8_eof:
+        org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA8_eofS),
+    DFA8_min:
+        org.antlr.runtime.DFA.unpackEncodedStringToUnsignedChars(ABELexer.DFA8_minS),
+    DFA8_max:
+        org.antlr.runtime.DFA.unpackEncodedStringToUnsignedChars(ABELexer.DFA8_maxS),
+    DFA8_accept:
+        org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA8_acceptS),
+    DFA8_special:
+        org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA8_specialS),
+    DFA8_transition: (function() {
         var a = [],
             i,
-            numStates = ABELexer.DFA7_transitionS.length;
+            numStates = ABELexer.DFA8_transitionS.length;
         for (i=0; i<numStates; i++) {
-            a.push(org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA7_transitionS[i]));
+            a.push(org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA8_transitionS[i]));
         }
         return a;
     })()
 });
 
-ABELexer.DFA7 = function(recognizer) {
+ABELexer.DFA8 = function(recognizer) {
     this.recognizer = recognizer;
-    this.decisionNumber = 7;
-    this.eot = ABELexer.DFA7_eot;
-    this.eof = ABELexer.DFA7_eof;
-    this.min = ABELexer.DFA7_min;
-    this.max = ABELexer.DFA7_max;
-    this.accept = ABELexer.DFA7_accept;
-    this.special = ABELexer.DFA7_special;
-    this.transition = ABELexer.DFA7_transition;
+    this.decisionNumber = 8;
+    this.eot = ABELexer.DFA8_eot;
+    this.eof = ABELexer.DFA8_eof;
+    this.min = ABELexer.DFA8_min;
+    this.max = ABELexer.DFA8_max;
+    this.accept = ABELexer.DFA8_accept;
+    this.special = ABELexer.DFA8_special;
+    this.transition = ABELexer.DFA8_transition;
 };
 
-org.antlr.lang.extend(ABELexer.DFA7, org.antlr.runtime.DFA, {
+org.antlr.lang.extend(ABELexer.DFA8, org.antlr.runtime.DFA, {
     getDescription: function() {
-        return "46:1: INC_TYPE : ( 'OTHER' | 'SCRIPT' | 'IMAGE' | 'CSS' | 'OBJ' | 'SUBDOC' | 'XBL' | 'PING' | 'XHR' | 'OBJSUB' | 'DTD' | 'FONT' | 'MEDIA' );";
+        return "46:1: HTTPVERB : ( 'GET' | 'POST' | 'PUT' | 'HEAD' | 'PATCH' | 'DELETE' | 'TRACE' | 'OPTIONS' );";
     },
     dummy: null
 });
 org.antlr.lang.augmentObject(ABELexer, {
-    DFA10_eotS:
-        "\u0002\uffff\u0001\u0008\u0004\uffff\u0001\u0008\u000e\uffff\u0001"+
-    "\u0010\u0002\uffff\u0002\u0010\u0002\u0032\u0001\uffff\u0001\u0010\u0001"+
-    "\uffff\u0001\u0010\u0001\uffff\u0001\u0010\u0001\uffff\u000b\u0010\u0001"+
-    "\u0042\u0001\u0010\u0001\u0032\u0001\uffff\u0001\u0045\u0001\u0010\u0001"+
-    "\u0047\u0001\u0010\u0001\u0049\u0002\u0010\u0004\u0045\u0002\u0010\u0001"+
-    "\u0051\u0001\u0010\u0001\uffff\u0001\u0010\u0001\u0023\u0001\uffff\u0001"+
-    "\u0010\u0001\uffff\u0001\u0045\u0001\uffff\u0004\u0010\u0001\u0045\u0001"+
-    "\u0010\u0001\u005b\u0001\uffff\u0002\u0010\u0001\u005e\u0001\u0010\u0002"+
-    "\u0045\u0001\u0010\u0001\u0045\u0002\uffff\u0002\u0045\u0001\uffff\u0001"+
-    "\u0010\u0001\u0045\u0002\u0010\u0001\u0049",
-    DFA10_eofS:
-        "\u0064\uffff",
-    DFA10_minS:
-        "\u0001\u0009\u0001\u0041\u0001\u0023\u0004\u0041\u0001\u0023\u0002"+
-    "\uffff\u0006\u0041\u0006\uffff\u0001\u004c\u0002\uffff\u0001\u0042\u0001"+
-    "\u0052\u0002\u0023\u0001\uffff\u0001\u0044\u0001\uffff\u0001\u0043\u0001"+
-    "\uffff\u0001\u004c\u0001\uffff\u0001\u004e\u0001\u0043\u0001\u0041\u0001"+
-    "\u0048\u0001\u004a\u0001\u0053\u0001\u004c\u0001\u0052\u0001\u004e\u0001"+
-    "\u0044\u0001\u0046\u0001\u0041\u0001\u0049\u0001\u0023\u0001\uffff\u0003"+
-    "\u0041\u0001\u0054\u0001\u0041\u0001\u0047\u0001\u0045\u0004\u0041\u0001"+
-    "\u0047\u0001\u0049\u0001\u002b\u0001\u004f\u0001\uffff\u0001\u0050\u0001"+
-    "\u0023\u0001\uffff\u0001\u004c\u0001\uffff\u0001\u0041\u0001\uffff\u0001"+
-    "\u0055\u0001\u0045\u0001\u0052\u0001\u0055\u0002\u0041\u0001\u002b\u0001"+
-    "\uffff\u0001\u0043\u0001\u0054\u0001\u0041\u0001\u0053\u0002\u0041\u0001"+
-    "\u0042\u0001\u0041\u0002\uffff\u0002\u0041\u0001\uffff\u0001\u0049\u0001"+
-    "\u0041\u0001\u004f\u0001\u004e\u0001\u0041",
-    DFA10_maxS:
-        "\u0001\u007a\u0001\u0069\u0001\u007e\u0001\u0065\u0001\u006f\u0001"+
-    "\u006e\u0001\u0072\u0001\u007e\u0002\uffff\u0006\u005a\u0006\uffff\u0001"+
-    "\u004c\u0002\uffff\u0001\u0042\u0001\u0052\u0002\u007e\u0001\uffff\u0001"+
-    "\u0044\u0001\uffff\u0001\u0043\u0001\uffff\u0001\u004c\u0001\uffff\u0001"+
-    "\u004e\u0001\u0043\u0001\u0041\u0001\u0048\u0001\u004a\u0001\u0053\u0001"+
-    "\u004c\u0001\u0052\u0001\u004e\u0001\u0044\u0001\u0046\u0001\u005a\u0001"+
-    "\u0049\u0001\u007e\u0001\uffff\u0001\u005a\u0001\u0041\u0001\u005a\u0001"+
-    "\u0054\u0001\u005a\u0001\u0047\u0001\u0045\u0004\u005a\u0001\u0047\u0001"+
-    "\u0049\u0001\u005a\u0001\u004f\u0001\uffff\u0001\u0050\u0001\u007e\u0001"+
-    "\uffff\u0001\u004c\u0001\uffff\u0001\u005a\u0001\uffff\u0001\u0055\u0001"+
-    "\u0045\u0001\u0052\u0001\u0055\u0001\u005a\u0001\u0041\u0001\u002b\u0001"+
-    "\uffff\u0001\u0043\u0001\u0054\u0001\u005a\u0001\u0053\u0002\u005a\u0001"+
-    "\u0042\u0001\u005a\u0002\uffff\u0002\u005a\u0001\uffff\u0001\u0049\u0001"+
-    "\u005a\u0001\u004f\u0001\u004e\u0001\u005a",
-    DFA10_acceptS:
-        "\u0008\uffff\u0001\u000c\u0001\u000d\u0006\uffff\u0001\u0012\u0001"+
+    DFA11_eotS:
+        "\u0003\uffff\u0001\u0009\u0004\uffff\u0001\u0009\u000e\uffff\u0001"+
+    "\u0011\u0002\uffff\u0001\u0011\u0002\u002f\u0001\uffff\u0001\u0011\u0001"+
+    "\uffff\u0001\u0011\u0001\uffff\u0001\u0011\u0001\uffff\u0009\u0011\u0001"+
+    "\u003c\u0001\u002f\u0001\uffff\u0002\u0011\u0001\u0040\u0001\u0041\u0001"+
+    "\u0043\u0001\u0011\u0001\u0043\u0004\u0011\u0001\u004a\u0001\uffff\u0001"+
+    "\u0023\u0002\u0011\u0002\uffff\u0001\u0011\u0001\uffff\u0001\u0043\u0001"+
+    "\u0011\u0001\u0043\u0002\u0011\u0001\u0052\u0001\uffff\u0001\u0011\u0001"+
+    "\u0054\u0001\u0011\u0002\u0043\u0001\u0011\u0002\uffff\u0001\u0043\u0001"+
+    "\uffff\u0003\u0011\u0001\u0043\u0001\u0011\u0001\u0041",
+    DFA11_eofS:
+        "\u005b\uffff",
+    DFA11_minS:
+        "\u0001\u0009\u0002\u0041\u0001\u0023\u0004\u0041\u0001\u0023\u0002"+
+    "\uffff\u0006\u0041\u0006\uffff\u0001\u004c\u0002\uffff\u0001\u0042\u0002"+
+    "\u0023\u0001\uffff\u0001\u004c\u0001\uffff\u0001\u0043\u0001\uffff\u0001"+
+    "\u004c\u0001\uffff\u0001\u0043\u0001\u0054\u0001\u0053\u0002\u0054\u0002"+
+    "\u0041\u0001\u0054\u0001\u0046\u0001\u0041\u0001\u0023\u0001\uffff\u0001"+
+    "\u0045\u0004\u0041\u0001\u0054\u0001\u0041\u0001\u0043\u0001\u0044\u0001"+
+    "\u0043\u0001\u0049\u0001\u002b\u0001\uffff\u0001\u0023\u0001\u0054\u0001"+
+    "\u004c\u0002\uffff\u0001\u0055\u0001\uffff\u0001\u0041\u0001\u0048\u0001"+
+    "\u0041\u0001\u0045\u0001\u004f\u0001\u002b\u0001\uffff\u0001\u0045\u0001"+
+    "\u0041\u0001\u0053\u0002\u0041\u0001\u004e\u0002\uffff\u0001\u0041\u0001"+
+    "\uffff\u0001\u0049\u0001\u0053\u0001\u004f\u0001\u0041\u0001\u004e\u0001"+
+    "\u0041",
+    DFA11_maxS:
+        "\u0001\u007a\u0001\u0069\u0001\u0065\u0001\u007e\u0001\u0065\u0001"+
+    "\u006f\u0001\u006e\u0001\u0072\u0001\u007e\u0002\uffff\u0006\u005a\u0006"+
+    "\uffff\u0001\u004c\u0002\uffff\u0001\u0042\u0002\u007e\u0001\uffff\u0001"+
+    "\u004c\u0001\uffff\u0001\u0043\u0001\uffff\u0001\u004c\u0001\uffff\u0001"+
+    "\u0043\u0001\u0054\u0001\u0053\u0002\u0054\u0002\u0041\u0001\u0054\u0001"+
+    "\u0046\u0001\u005f\u0001\u007e\u0001\uffff\u0001\u0045\u0001\u0041\u0003"+
+    "\u005f\u0001\u0054\u0001\u005f\u0001\u0043\u0001\u0044\u0001\u0043\u0001"+
+    "\u0049\u0001\u005f\u0001\uffff\u0001\u007e\u0001\u0054\u0001\u004c\u0002"+
+    "\uffff\u0001\u0055\u0001\uffff\u0001\u005f\u0001\u0048\u0001\u005f\u0001"+
+    "\u0045\u0001\u004f\u0001\u002b\u0001\uffff\u0001\u0045\u0001\u005f\u0001"+
+    "\u0053\u0002\u005f\u0001\u004e\u0002\uffff\u0001\u005f\u0001\uffff\u0001"+
+    "\u0049\u0001\u0053\u0001\u004f\u0001\u005f\u0001\u004e\u0001\u005f",
+    DFA11_acceptS:
+        "\u0009\uffff\u0001\u000c\u0001\u000d\u0006\uffff\u0001\u0012\u0001"+
     "\u0013\u0001\u0014\u0001\u0015\u0001\u0016\u0001\u0017\u0001\uffff\u0001"+
-    "\u0004\u0001\u0008\u0004\uffff\u0001\u0006\u0001\uffff\u0001\u0007\u0001"+
-    "\uffff\u0001\u0009\u0001\uffff\u0001\u0005\u000e\uffff\u0001\u000b\u000f"+
-    "\uffff\u0001\u000f\u0002\uffff\u0001\u0011\u0001\uffff\u0001\u000e\u0001"+
-    "\uffff\u0001\u0010\u0007\uffff\u0001\u0001\u0008\uffff\u0001\u0003\u0001"+
-    "\u0002\u0002\uffff\u0001\u000a\u0005\uffff",
-    DFA10_specialS:
-        "\u0064\uffff}>",
-    DFA10_transitionS: [
-            "\u0002\u0014\u0001\uffff\u0002\u0014\u0012\uffff\u0001\u0014"+
-            "\u0002\uffff\u0001\u0015\u0004\uffff\u0001\u0012\u0001\u0013"+
-            "\u0001\u0008\u0001\uffff\u0001\u0011\u0001\uffff\u0001\u0008"+
-            "\u0001\uffff\u000a\u0007\u0007\uffff\u0001\u0005\u0001\u0010"+
-            "\u0001\u000c\u0001\u0003\u0001\u0010\u0001\u0006\u0002\u0010"+
-            "\u0001\u000a\u0002\u0010\u0001\u0004\u0001\u000f\u0001\u0010"+
-            "\u0001\u000b\u0001\u000e\u0002\u0010\u0001\u0001\u0004\u0010"+
-            "\u0001\u000d\u0002\u0010\u0003\uffff\u0001\u0009\u0002\uffff"+
-            "\u0005\u0007\u0001\u0002\u0014\u0007",
-            "\u0002\u0010\u0001\u001a\u0001\u0010\u0001\u0016\u000f\u0010"+
-            "\u0001\u0019\u0005\u0010\u0006\uffff\u0001\u0018\u0007\uffff"+
-            "\u0001\u0017",
+    "\u0004\u0001\u0008\u0003\uffff\u0001\u0006\u0001\uffff\u0001\u0007\u0001"+
+    "\uffff\u0001\u0009\u0001\uffff\u0001\u0005\u000b\uffff\u0001\u000b\u000c"+
+    "\uffff\u0001\u000f\u0003\uffff\u0001\u000e\u0001\u0010\u0001\uffff\u0001"+
+    "\u0011\u0006\uffff\u0001\u0001\u0006\uffff\u0001\u0003\u0001\u0002\u0001"+
+    "\uffff\u0001\u000a\u0006\uffff",
+    DFA11_specialS:
+        "\u005b\uffff}>",
+    DFA11_transitionS: [
+            "\u0002\u0015\u0001\uffff\u0002\u0015\u0012\uffff\u0001\u0015"+
+            "\u0002\uffff\u0001\u0016\u0004\uffff\u0001\u0013\u0001\u0014"+
+            "\u0001\u0009\u0001\uffff\u0001\u0012\u0001\uffff\u0001\u0009"+
+            "\u0001\uffff\u000a\u0008\u0007\uffff\u0001\u0006\u0002\u0011"+
+            "\u0001\u0004\u0001\u0011\u0001\u0007\u0001\u000c\u0001\u000e"+
+            "\u0001\u000b\u0002\u0011\u0001\u0005\u0002\u0011\u0001\u0010"+
+            "\u0001\u000d\u0001\u0011\u0001\u0002\u0001\u0001\u0001\u000f"+
+            "\u0006\u0011\u0003\uffff\u0001\u000a\u0002\uffff\u0005\u0008"+
+            "\u0001\u0003\u0014\u0008",
+            "\u0004\u0011\u0001\u0017\u000f\u0011\u0001\u001a\u0005\u0011"+
+            "\u0006\uffff\u0001\u0019\u0007\uffff\u0001\u0018",
+            "\u001a\u0011\u000a\uffff\u0001\u0018",
             "\u0001\u001c\u0001\uffff\u0002\u001c\u0005\uffff\u0010\u001c"+
             "\u0001\uffff\u0001\u001c\u0001\uffff\u001d\u001c\u0001\uffff"+
             "\u0001\u001c\u0001\uffff\u0001\u001c\u0001\uffff\u0011\u001c"+
             "\u0001\u001b\u0008\u001c\u0003\uffff\u0001\u001c",
-            "\u0013\u0010\u0001\u001e\u0006\u0010\u000a\uffff\u0001\u001d",
-            "\u000e\u0010\u0001\u0020\u000b\u0010\u0014\uffff\u0001\u001f",
-            "\u000b\u0010\u0001\u0022\u000e\u0010\u0008\uffff\u0001\u0021"+
+            "\u0004\u0011\u0001\u001e\u0015\u0011\u000a\uffff\u0001\u001d",
+            "\u000e\u0011\u0001\u0020\u000b\u0011\u0014\uffff\u0001\u001f",
+            "\u000b\u0011\u0001\u0022\u000e\u0011\u0008\uffff\u0001\u0021"+
             "\u000a\uffff\u0001\u001f",
-            "\u000e\u0010\u0001\u0024\u000b\u0010\u0017\uffff\u0001\u0023",
+            "\u001a\u0011\u0017\uffff\u0001\u0023",
             "\u0001\u001c\u0001\uffff\u0002\u001c\u0005\uffff\u0010\u001c"+
             "\u0001\uffff\u0001\u001c\u0001\uffff\u001d\u001c\u0001\uffff"+
             "\u0001\u001c\u0001\uffff\u0001\u001c\u0001\uffff\u001a\u001c"+
             "\u0003\uffff\u0001\u001c",
             "",
             "",
-            "\u000c\u0010\u0001\u0026\u0001\u0025\u000c\u0010",
-            "\u0001\u0010\u0001\u0028\u0011\u0010\u0001\u0027\u0006\u0010",
-            "\u0012\u0010\u0001\u0029\u0007\u0010",
-            "\u0001\u0010\u0001\u002a\u0005\u0010\u0001\u002b\u0012\u0010",
-            "\u0008\u0010\u0001\u002c\u0011\u0010",
-            "\u0004\u0010\u0001\u002d\u0015\u0010",
+            "\u000d\u0011\u0001\u0024\u000c\u0011",
+            "\u0004\u0011\u0001\u0025\u0015\u0011",
+            "\u0001\u0028\u000d\u0011\u0001\u0026\u0005\u0011\u0001\u0027"+
+            "\u0005\u0011",
+            "\u0004\u0011\u0001\u0029\u0015\u0011",
+            "\u0011\u0011\u0001\u002a\u0008\u0011",
+            "\u000f\u0011\u0001\u002b\u000a\u0011",
             "",
             "",
             "",
             "",
             "",
             "",
-            "\u0001\u002e",
+            "\u0001\u002c",
             "",
             "",
-            "\u0001\u002f",
-            "\u0001\u0030",
-            "\u0001\u001c\u0001\uffff\u0002\u001c\u0003\uffff\u0001\u0008"+
+            "\u0001\u002d",
+            "\u0001\u001c\u0001\uffff\u0002\u001c\u0003\uffff\u0001\u0009"+
             "\u0001\uffff\u0010\u001c\u0001\uffff\u0001\u001c\u0001\uffff"+
             "\u001d\u001c\u0001\uffff\u0001\u001c\u0001\uffff\u0001\u001c"+
-            "\u0001\uffff\u000e\u001c\u0001\u0031\u000b\u001c\u0003\uffff"+
+            "\u0001\uffff\u000e\u001c\u0001\u002e\u000b\u001c\u0003\uffff"+
             "\u0001\u001c",
-            "\u0001\u001c\u0001\uffff\u0002\u001c\u0003\uffff\u0001\u0008"+
+            "\u0001\u001c\u0001\uffff\u0002\u001c\u0003\uffff\u0001\u0009"+
             "\u0001\uffff\u0010\u001c\u0001\uffff\u0001\u001c\u0001\uffff"+
             "\u001d\u001c\u0001\uffff\u0001\u001c\u0001\uffff\u0001\u001c"+
             "\u0001\uffff\u001a\u001c\u0003\uffff\u0001\u001c",
             "",
-            "\u0001\u0033",
+            "\u0001\u0030",
             "",
-            "\u0001\u0034",
+            "\u0001\u0031",
             "",
-            "\u0001\u0035",
+            "\u0001\u0032",
             "",
+            "\u0001\u0033",
+            "\u0001\u0034",
+            "\u0001\u0035",
             "\u0001\u0036",
             "\u0001\u0037",
             "\u0001\u0038",
             "\u0001\u0039",
             "\u0001\u003a",
             "\u0001\u003b",
-            "\u0001\u003c",
-            "\u0001\u003d",
-            "\u0001\u003e",
-            "\u0001\u003f",
-            "\u0001\u0040",
-            "\u0003\u0010\u0001\u0041\u0016\u0010",
-            "\u0001\u0043",
-            "\u0001\u001c\u0001\uffff\u0002\u001c\u0003\uffff\u0001\u0008"+
+            "\u001a\u0011\u0004\uffff\u0001\u0011",
+            "\u0001\u001c\u0001\uffff\u0002\u001c\u0003\uffff\u0001\u0009"+
             "\u0001\uffff\u0010\u001c\u0001\uffff\u0001\u001c\u0001\uffff"+
             "\u001d\u001c\u0001\uffff\u0001\u001c\u0001\uffff\u0001\u001c"+
-            "\u0001\uffff\u000c\u001c\u0001\u0044\u000d\u001c\u0003\uffff"+
+            "\u0001\uffff\u000c\u001c\u0001\u003d\u000d\u001c\u0003\uffff"+
             "\u0001\u001c",
             "",
-            "\u001a\u0010",
+            "\u0001\u003e",
+            "\u0001\u003f",
+            "\u001a\u0011\u0004\uffff\u0001\u0011",
+            "\u000b\u0011\u0001\u0042\u000e\u0011\u0004\uffff\u0001\u0011",
+            "\u001a\u0011\u0004\uffff\u0001\u0011",
+            "\u0001\u0044",
+            "\u001a\u0011\u0004\uffff\u0001\u0011",
+            "\u0001\u0045",
             "\u0001\u0046",
-            "\u001a\u0010",
+            "\u0001\u0047",
             "\u0001\u0048",
-            "\u000b\u0010\u0001\u004a\u000e\u0010",
-            "\u0001\u004b",
-            "\u0001\u004c",
-            "\u0012\u0010\u0001\u004d\u0007\u0010",
-            "\u001a\u0010",
-            "\u001a\u0010",
-            "\u001a\u0010",
-            "\u0001\u004e",
-            "\u0001\u004f",
-            "\u0001\u0050\u0015\uffff\u001a\u0010",
-            "\u0001\u0052",
+            "\u0001\u0049\u0015\uffff\u001a\u0011\u0004\uffff\u0001\u0011",
             "",
-            "\u0001\u0053",
-            "\u0001\u001c\u0001\uffff\u0002\u001c\u0003\uffff\u0001\u0008"+
+            "\u0001\u001c\u0001\uffff\u0002\u001c\u0003\uffff\u0001\u0009"+
             "\u0001\uffff\u0010\u001c\u0001\uffff\u0001\u001c\u0001\uffff"+
             "\u001d\u001c\u0001\uffff\u0001\u001c\u0001\uffff\u0001\u001c"+
             "\u0001\uffff\u001a\u001c\u0003\uffff\u0001\u001c",
+            "\u0001\u004b",
+            "\u0001\u004c",
+            "",
             "",
-            "\u0001\u0054",
+            "\u0001\u004d",
             "",
-            "\u001a\u0010",
+            "\u001a\u0011\u0004\uffff\u0001\u0011",
+            "\u0001\u004e",
+            "\u001a\u0011\u0004\uffff\u0001\u0011",
+            "\u0001\u004f",
+            "\u0001\u0050",
+            "\u0001\u0051",
             "",
+            "\u0001\u0053",
+            "\u001a\u0011\u0004\uffff\u0001\u0011",
             "\u0001\u0055",
+            "\u001a\u0011\u0004\uffff\u0001\u0011",
+            "\u001a\u0011\u0004\uffff\u0001\u0011",
             "\u0001\u0056",
+            "",
+            "",
+            "\u001a\u0011\u0004\uffff\u0001\u0011",
+            "",
             "\u0001\u0057",
             "\u0001\u0058",
-            "\u001a\u0010",
             "\u0001\u0059",
+            "\u001a\u0011\u0004\uffff\u0001\u0011",
             "\u0001\u005a",
-            "",
-            "\u0001\u005c",
-            "\u0001\u005d",
-            "\u001a\u0010",
-            "\u0001\u005f",
-            "\u001a\u0010",
-            "\u001a\u0010",
-            "\u0001\u0060",
-            "\u001a\u0010",
-            "",
-            "",
-            "\u001a\u0010",
-            "\u001a\u0010",
-            "",
-            "\u0001\u0061",
-            "\u001a\u0010",
-            "\u0001\u0062",
-            "\u0001\u0063",
-            "\u001a\u0010"
+            "\u001a\u0011\u0004\uffff\u0001\u0011"
     ]
 });
 
 org.antlr.lang.augmentObject(ABELexer, {
-    DFA10_eot:
-        org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA10_eotS),
-    DFA10_eof:
-        org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA10_eofS),
-    DFA10_min:
-        org.antlr.runtime.DFA.unpackEncodedStringToUnsignedChars(ABELexer.DFA10_minS),
-    DFA10_max:
-        org.antlr.runtime.DFA.unpackEncodedStringToUnsignedChars(ABELexer.DFA10_maxS),
-    DFA10_accept:
-        org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA10_acceptS),
-    DFA10_special:
-        org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA10_specialS),
-    DFA10_transition: (function() {
+    DFA11_eot:
+        org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA11_eotS),
+    DFA11_eof:
+        org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA11_eofS),
+    DFA11_min:
+        org.antlr.runtime.DFA.unpackEncodedStringToUnsignedChars(ABELexer.DFA11_minS),
+    DFA11_max:
+        org.antlr.runtime.DFA.unpackEncodedStringToUnsignedChars(ABELexer.DFA11_maxS),
+    DFA11_accept:
+        org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA11_acceptS),
+    DFA11_special:
+        org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA11_specialS),
+    DFA11_transition: (function() {
         var a = [],
             i,
-            numStates = ABELexer.DFA10_transitionS.length;
+            numStates = ABELexer.DFA11_transitionS.length;
         for (i=0; i<numStates; i++) {
-            a.push(org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA10_transitionS[i]));
+            a.push(org.antlr.runtime.DFA.unpackEncodedString(ABELexer.DFA11_transitionS[i]));
         }
         return a;
     })()
 });
 
-ABELexer.DFA10 = function(recognizer) {
+ABELexer.DFA11 = function(recognizer) {
     this.recognizer = recognizer;
-    this.decisionNumber = 10;
-    this.eot = ABELexer.DFA10_eot;
-    this.eof = ABELexer.DFA10_eof;
-    this.min = ABELexer.DFA10_min;
-    this.max = ABELexer.DFA10_max;
-    this.accept = ABELexer.DFA10_accept;
-    this.special = ABELexer.DFA10_special;
-    this.transition = ABELexer.DFA10_transition;
+    this.decisionNumber = 11;
+    this.eot = ABELexer.DFA11_eot;
+    this.eof = ABELexer.DFA11_eof;
+    this.min = ABELexer.DFA11_min;
+    this.max = ABELexer.DFA11_max;
+    this.accept = ABELexer.DFA11_accept;
+    this.special = ABELexer.DFA11_special;
+    this.transition = ABELexer.DFA11_transition;
 };
 
-org.antlr.lang.extend(ABELexer.DFA10, org.antlr.runtime.DFA, {
+org.antlr.lang.extend(ABELexer.DFA11, org.antlr.runtime.DFA, {
     getDescription: function() {
-        return "1:1: Tokens : ( T__28 | T__29 | T__30 | T_SITE | T_FROM | A_DENY | A_LOGOUT | A_SANDBOX | A_ACCEPT | LOCATION | URI | GLOB | REGEXP | ALL | SUB | INC | INC_TYPE | HTTPVERB | COMMA | LPAR | RPAR | WS | COMMENT );";
+        return "1:1: Tokens : ( T__28 | T__29 | T__30 | T_SITE | T_FROM | A_DENY | A_LOGOUT | A_SANDBOX | A_ACCEPT | LOCATION | URI | GLOB | REGEXP | ALL | SUB | INC | HTTPVERB | INC_TYPE | COMMA | LPAR | RPAR | WS | COMMENT );";
     },
     dummy: null
 });
diff --git a/chrome/noscript.jar!/content/noscript/ABEParser.js b/chrome/noscript.jar!/content/noscript/ABEParser.js
index ca7a838..a347bc0 100644
--- a/chrome/noscript.jar!/content/noscript/ABEParser.js
+++ b/chrome/noscript.jar!/content/noscript/ABEParser.js
@@ -1,4 +1,4 @@
-// $ANTLR 3.1.1 ABE.g 2011-03-21 12:45:42
+// $ANTLR 3.1.1 ABE.g 2017-07-26 00:44:40
 
 var ABEParser = function(input, state) {
     if (!state) {
@@ -251,7 +251,7 @@ org.antlr.lang.augmentObject(ABEParser.prototype, {
 
 
             // AST REWRITE
-            // elements: subject, predicate
+            // elements: predicate, subject
             // token labels: 
             // rule labels: retval
             // token list labels: 
@@ -379,7 +379,7 @@ org.antlr.lang.augmentObject(ABEParser.prototype, {
 
 
             // AST REWRITE
-            // elements: methods, origin, action
+            // elements: action, methods, origin
             // token labels: 
             // rule labels: retval
             // token list labels: 
diff --git a/chrome/noscript.jar!/content/noscript/FrameScript.jsm b/chrome/noscript.jar!/content/noscript/FrameScript.jsm
index 3196491..bddc453 100644
--- a/chrome/noscript.jar!/content/noscript/FrameScript.jsm
+++ b/chrome/noscript.jar!/content/noscript/FrameScript.jsm
@@ -23,7 +23,7 @@ function FrameScript(ctx) {
 
   this.ctx = ctx;
   new PasteHandler(ctx);
-  new UISync(ctx);
+  ctx.uiSync = new UISync(ctx);
 }
 
 FrameScript.prototype = {
diff --git a/chrome/noscript.jar!/content/noscript/InjectionChecker.js b/chrome/noscript.jar!/content/noscript/InjectionChecker.js
index 1027dbf..b90c2c0 100644
--- a/chrome/noscript.jar!/content/noscript/InjectionChecker.js
+++ b/chrome/noscript.jar!/content/noscript/InjectionChecker.js
@@ -1,1711 +1,1733 @@
-
-const wordCharRx = /\w/g;
-function fuzzify(s) {
-  return s.replace(wordCharRx, '\\W*(?:/[*/][\\s\\S]*)?$&');
-}
-
-const IC_COMMENT_PATTERN = '\\s*(?:\\/[\\/\\*][\\s\\S]+)?';
-const IC_WINDOW_OPENER_PATTERN = fuzzify("alert|confirm|prompt|open(?:URL)?|print|show") + "\\w*" + fuzzify("Dialog");
-const IC_EVAL_PATTERN = "\\b(?:" +
-  fuzzify('eval|set(?:Timeout|Interval)|(?:f|F)unction|Script|toString|Worker|document|constructor|generateCRMFRequest|jQuery|fetch|write(?:ln)?|__(?:define(?:S|G)etter|noSuchMethod)__|definePropert(?:y|ies)') +
-   "|\\$|" + IC_WINDOW_OPENER_PATTERN + ")\\b";
-const IC_EVENT_PATTERN = "on(?:m(?:o(?:z(?:browser(?:beforekey(?:down|up)|afterkey(?:down|up))|(?:network(?:down|up)loa|accesskeynotfoun)d|pointerlock(?:change|error)|(?:orientation|time)change|fullscreen(?:change|error)|interrupt(?:begin|end)|key(?:down|up)onplugin)|use(?:(?:lea|mo)ve|o(?:ver|ut)|enter|wheel|down|up)|ve(?:start|end)?)|a(?:p(?:se(?:tmessagestatus|ndmessage)|message(?:slisting|update)|folderlisting|getmessage)req|rk)|essage)|c(?:o(?:n(?:nect(?:i(?:on(?:statechanged|availa [...]
-  // autogenerated from nsHtml5AtomList.h and nsGkAtomList.h
-  ;
-const IC_EVENT_DOS_PATTERN =
-      "\\b(?:" + IC_EVENT_PATTERN + ")[\\s\\S]*=[\\s\\S]*\\b(?:" + IC_WINDOW_OPENER_PATTERN + ")\\b" +
-      "|\\b(?:" + IC_WINDOW_OPENER_PATTERN + ")\\b[\\s\\S]+\\b(?:" + IC_EVENT_PATTERN + ")[\\s\\S]*=";
-
-var InjectionChecker = {
-  reset: function () {
-
-    this.isPost =
-      this.base64 =
-      this.nameAssignment = false;
-
-    this.base64tested = [];
-
-  },
-
-  fuzzify: fuzzify,
-  syntax: new SyntaxChecker(),
-  _log: function(msg, t, i) {
-    if (msg) msg = this._printable(msg);
-    if(!(i || t)) {
-      msg += " - LINES: ";
-      var lines = [];
-      for (var stack = Components.stack; (stack = stack.caller);) {
-        lines.push(stack.lineNumber);
-      }
-      msg += lines.join(", ");
-    }
-    else {
-      if (t) msg += " - TIME: " + (Date.now() - t);
-      if (i) msg += " - ITER: " + i;
-    }
-    this.dump("[NoScript InjectionChecker] " + msg + "\n");
-  },
-
-  _printable: function (msg) {
-    return msg.toString().replace(/[^\u0020-\u007e]/g, function(s) { return "{" + s.charCodeAt(0).toString(16) + "}"; });
-  },
-
-  dump: dump,
-  log: function() {},
-  get logEnabled() { return this.log == this._log; },
-  set logEnabled(v) { this.log = v ? this._log : function() {}; },
-
-  escalate: function(msg) {
-    this.log(msg);
-    ns.log("[NoScript InjectionChecker] " + msg);
-  },
-
-  bb: function(brac, s, kets) {
-    for(var j = 3; j-- > 0;) {
-      s = brac + s + kets;
-      if (this.checkJSSyntax(s)) return true;
-    }
-    return false;
-  },
-
-  checkJSSyntax: function(s) {
-    // bracket balancing for micro injections like "''), e v a l (name,''"
-    if (/^(?:''|"")?[^\('"]*\)/.test(s)) return this.bb("x(\n", s, "\n)");
-    if (/^(?:''|"")?[^\['"]*\\]/.test(s)) return this.bb("y[\n", s, "\n]");
-    if (/^(?:''|"")?[^\{'"]*\}/.test(s)) return this.bb("function z() {\n", s, "\n}");
-
-    s += " /* COMMENT_TERMINATOR */\nDUMMY_EXPR";
-    if (this.syntax.check(s)) {
-      this.log("Valid fragment " + s);
-      return true;
-    }
-    return false;
-  },
-
-  get breakStops() {
-    var def = "\\/\\?&#;\\s\\x00}<>"; // we stop on URL, JS and HTML delimiters
-    var bs = {
-      nq: new RegExp("[" + def + "]")
-    };
-    Array.forEach("'\"`", // special treatment for quotes
-      function(c) { bs[c] = new RegExp("[" + def + c + "]"); }
-    );
-    delete this.breakStops;
-    return this.breakStops = bs;
-  },
-
-  collapseChars: (s) => s.replace(/\;+/g, ';').replace(/\/{4,}/g, '////')
-        .replace(/\s+/g, (s) => /\n/g.test(s) ? '\n' : ' '),
-
-  _reduceBackslashes: (bs) => bs.length % 2 ? "\\" : "",
-
-  reduceQuotes: function(s) {
-    if (s[0] == '/') {
-      // reduce common leading path fragment resembling a regular expression or a comment
-      s = s.replace(/^\/[^\/\n\r]+\//, '_RX_').replace(/^\/\/[^\r\n]*/, '//_COMMENT_');
-    }
-
-    if (/\/\*/.test(s) || // C-style comments, would make everything really tricky
-      /\w\s*(\/\/[\s\S]*)?\[[\s\S]*\w[\s\S]*\]/.test(s)) { // property accessors, risky
-      return s;
-    }
-
-    if (/['"\/]/.test(s)) {
-
-      // drop noisy backslashes
-      s = s.replace(/\\{2,}/g, this._reduceBackslashes);
-
-      // drop escaped quotes
-      s = s.replace(/\\["'\/]/g, " EQ ");
-      var expr;
-      for(;;) {
-         expr = s.replace(/(^[^'"\/]*[;,\+\-=\(\[]\s*)\/[^\/]+\//g, "$1 _RX_ ")
-                .replace(/(^[^'"\/]*)(["']).*?\2/g, "$1 _QS_ ");
-         if(expr == s) break;
-         s = expr;
-      }
-    }
-
-    // remove c++ style comments
-    return s.replace(/^([^'"`\\]*?)\/\/[^\r\n]*/g, "$1//_COMMENT_");
-  },
-
-  reduceURLs: function(s) {
-    // nested URLs with protocol are parsed as C++ style comments, and since
-    // they're potentially very expensive, we preemptively remove them if possible
-    while (/^[^'"]*?:\/\//.test(s)) {
-      s = s.replace(/:\/\/[^*\s]*/, ':');
-    }
-    s = s.replace(/:\/\/[^'"*\n]*/g, ':');
-
-    return (/\bhttps?:$/.test(s) && !/\bh\W*t\W*t\W*p\W*s?.*=/.test(s))
-      ? s.replace(/\b(?:[\w.]+=)?https?:$/, '')
-      : s;
-  },
-
-  reduceJSON: function(s) {
-    const toStringRx = /^function\s*toString\(\)\s*{\s*\[native code\]\s*\}$/;
-    // optimistic case first, one big JSON block
-    for (;;) {
-
-      let m = s.match(/{[\s\S]+}/);
-      if (!m) return s;
-
-      let whole = s;
-      let expr = m[0];
-      let json = ns.json;
-      if (json) {
-        try {
-          if (!toStringRx.test(JSON.parse(expr).toString))
-            return s;
-
-          this.log("Reducing big JSON " + expr);
-          return s.replace(expr, '{}');
-        } catch(e) {}
-      }
-
-      // heavier duty, scattered JSON blocks
-      while((m = s.match(/\{[^\{\}:]+:[^\{\}]+\}/g))) {
-        let prev = s;
-
-        for (expr  of m) {
-          if (json) try {
-            if (!toStringRx.test(JSON.parse(expr).toString))
-              continue;
-
-            this.log("Reducing JSON " + expr);
-            s = s.replace(expr, '{}');
-            continue;
-          } catch(e) {}
-
-          if (/\btoString\b[\s\S]*:/.test(expr)) continue;
-
-          let qred = this.reduceQuotes(expr);
-          if (/\{(?:\s*(?:(?:\w+:)+\w+)+;\s*)+\}/.test(qred)) {
-             this.log("Reducing pseudo-JSON " + expr);
-             s = s.replace(expr, '{}');
-          } else if (!/[(=.]|[^:\s]\s*\[|:\s*(?:location|document|set(?:Timeout|Interval)|eval|open|show\w*Dialog|alert|confirm|prompt)\b|(?:\]|set)\s*:/.test(qred) &&
-             this.checkJSSyntax("JSON = " + qred) // no-assignment JSON fails with "invalid label"
-          ) {
-            this.log("Reducing slow JSON " + expr);
-            s = s.replace(expr, '{}');
-          }
-        }
-
-        if (s == prev) break;
-      }
-
-      if (s == whole) break;
-    }
-
-    return s;
-  },
-
-  reduceXML: function reduceXML(s) {
-    var res;
-
-    for (let pos = s.indexOf("<"); pos !== -1; pos = s.indexOf("<", 1)) {
-
-      let head = s.substring(0, pos);
-      let tail = s.substring(pos);
-
-      let qnum = 0;
-      for (pos = -1; (pos = head.indexOf('"', ++pos)) > -1; ) {
-        if (pos === 0 || head[pos - 1] != '\\') qnum++;
-      }
-      if (qnum % 2)  break; // odd quotes
-
-      let t = tail.replace(/^<(\??\s*\/?[a-zA-Z][\w:-]*)(?:[\s+]+[\w:-]+="[^"]*")*[\s+]*(\/?\??)>/, '<$1$2>');
-
-      (res || (res = [])).push(head);
-      s = t;
-    }
-    if (res) {
-      res.push(s);
-      s = res.join('');
-    }
-
-    return s;
-  }
-,
-
-  _singleAssignmentRx: new RegExp(
-    "(?:\\b" + fuzzify('document') + "\\b[\\s\\S]*\\.|\\s" + fuzzify('setter') + "\\b[\\s\\S]*=)|/.*/[\\s\\S]*(?:\\.(?:" +
-     "\\b" + fuzzify("onerror") + "\\b[\\s\\S]*=|" +
-      + fuzzify('source|toString') + ")|\\[)|" + IC_EVENT_DOS_PATTERN
-  ),
-  _riskyAssignmentRx: new RegExp(
-    "\\b(?:" + fuzzify('location|innerHTML|outerHTML') + ")\\b[\\s\\S]*="
-  ),
-  _nameRx: new RegExp(
-    "=[\\s\\S]*\\b" + fuzzify('name') + "\\b|" +
-    fuzzify("hostname") + "[\\s\\S]*=[\\s\\S]*(?:\\b\\d|[\"'{}~^|<*/+-])"
-  ),
-  _evalAliasingRx: new RegExp(
-    "=[\\s\\S]+\\[" + IC_EVAL_PATTERN + "\\W*\\]" // TODO: check if it can be coalesced into _maybeJSRx
-  ),
-
-  _maybeJSRx: new RegExp(
-    // accessor followed by function call or assignment.
-    '(?:(?:\\[[\\s\\S]*\\]|\\.\\D)[\\s\\S]*(?:\\([\\s\\S]*\\)|`[\\s\\S]+`|=[\\s\\S]*\\S)' +
-    // double function call
-    '|\\([\\s\\S]*\\([\\s\\S]*\\)' +
-    ')|(?:^|\\W)(?:' + IC_EVAL_PATTERN +
-    ')(?:\\W+[\\s\\S]*|)[(`]|(?:[=(]|\\{[\\s\\S]+:)[\\s\\S]*(?:' + // calling eval-like functions directly or...
-    IC_EVAL_PATTERN + // ... assigning them to another function possibly called by the victim later
-    ')[\\s\\S]*[\\n,;:|]|\\b(?:' +
-    fuzzify('setter|location|innerHTML|outerHTML') +  // eval-like assignments
-    ')\\b[\\s\\S]*=|' +
-    '.' + IC_COMMENT_PATTERN + "src" + IC_COMMENT_PATTERN + '=' +
-    IC_EVENT_DOS_PATTERN +
-    "|\\b" + fuzzify("onerror") + "\\b[\\s\\S]*=" +
-    "|=[s\\\\[ux]?\d{2}" + // escape (unicode/ascii/octal)
-    "|\\b(?:toString|valueOf)\\b" + IC_COMMENT_PATTERN + "=[\\s\\S]*(?:" + IC_EVAL_PATTERN + ")" +
-    "|(?:\\)|(?:[^\\w$]|^)[$a-zA-Z_\\u0ff-\\uffff][$\\w\\u0ff-\\uffff]*)" + IC_COMMENT_PATTERN + '=>' + // concise function definition
-    "|(?:[^\\w$]|^)" + IC_EVENT_PATTERN + IC_COMMENT_PATTERN + "="
-  )
- ,
-
-  _riskyParensRx: new RegExp(
-    "(?:^|\\W)(?:(?:" + IC_EVAL_PATTERN + "|on\\w+)\\s*[(`]|" +
-    fuzzify("with") + "\\b[\\s\\S]*\\(|" +
-    fuzzify("for") + "\\b[\\s\\S]*\\([\\s\\S]*[\\w$\\u0080-\\uffff]+[\\s\\S]*\\b(?:" +
-    fuzzify ("in|of") + ")\\b)"
-  ),
-
-  _dotRx: /\./g,
-  _removeDotsRx: /^openid\.[\w.-]+(?==)|(?:[?&#\/]|^)[\w.-]+(?=[\/\?&#]|$)|[\w\.]*\.(?:\b[A-Z]+|\w*\d|[a-z][$_])[\w.-]*|=[a-z.-]+\.(?:com|net|org|biz|info|xxx|[a-z]{2})(?:[;&/]|$)/g,
-  _removeDots: (p) => p.replace(InjectionChecker._dotRx, '|'),
-  _arrayAccessRx: /\s*\[\d+\]/g,
-  _riskyOperatorsRx: /[+-]{2}\s*(?:\/[*/][\s\S]+)?(?:\w+(?:\/[*/][\s\S]+)?[[.]|location)|(?:\]|\.\s*(?:\/[*/][\s\S]+)?\w+|location)\s*(?:\/[*/][\s\S]+)?([+-]{2}|[+*\/<>~-]+\s*(?:\/[*/][\s\S]+)?=)/, // inc/dec/self-modifying assignments on DOM props
-  _assignmentRx: /^(?:[^()="'\s]+=(?:[^(='"\[+]+|[?a-zA-Z_0-9;,&=/]+|[\d.|]+))$/,
-  _badRightHandRx: /=[\s\S]*(?:_QS_\b|[|.][\s\S]*source\b|<[\s\S]*\/[^>]*>)/,
-  _wikiParensRx: /^(?:[\w.|-]+\/)*\(*[\w\s-]+\([\w\s-]+\)[\w\s-]*\)*$/,
-  _neutralDotsRx: /(?:^|[\/;&#])[\w-]+\.[\w-]+[\?;\&#]/g,
-  _openIdRx: /^scope=(?:\w+\+)\w/, // OpenID authentication scope parameter, see http://forums.informaction.com/viewtopic.php?p=69851#p69851
-  _gmxRx: /\$\(clientName\)-\$\(dataCenter\)\.(\w+\.)+\w+/, // GMX webmail, see http://forums.informaction.com/viewtopic.php?p=69700#p69700
-
-  maybeJS: function(expr) {
-
-
-    if (/`[\s\S]*`/.test(expr) ||  // ES6 templates, extremely insidious!!!
-        this._evalAliasingRx.test(expr) ||
-        this._riskyOperatorsRx.test(expr) // this must be checked before removing dots...
-        ) return true;
-
-    expr = // dotted URL components can lead to false positives, let's remove them
-      expr.replace(this._removeDotsRx, this._removeDots)
-        .replace(this._arrayAccessRx, '_ARRAY_ACCESS_')
-        .replace(/<([\w:]+)>[^</(="'`]+<\/\1>/g, '<$1/>') // reduce XML text nodes
-        .replace(/<!--/g, '') // remove HTML comments preamble (see next line)
-        .replace(/(^(?:[^/]*[=;.+-])?)\s*[\[(]+/g, '$1') // remove leading parens and braces
-        .replace(this._openIdRx, '_OPENID_SCOPE_=XYZ')
-        .replace(/^[^=]*OPENid\.(\w+)=/gi, "OPENid_\1")
-        .replace(this._gmxRx, '_GMX_-_GMX_')
-        ;
-
-    if (expr.indexOf(")") !== -1) expr += ")"; // account for externally balanced parens
-    if(this._assignmentRx.test(expr) && !this._badRightHandRx.test(expr)) // commonest case, single assignment or simple chained assignments, no break
-       return this._singleAssignmentRx.test(expr) || this._riskyAssignmentRx.test(expr) && this._nameRx.test(expr);
-
-    return this._riskyParensRx.test(expr) ||
-      this._maybeJSRx.test(expr.replace(this._neutralDotsRx, '')) &&
-        !this._wikiParensRx.test(expr);
-
-  },
-
-  checkNonTrivialJSSyntax: function(expr) {
-    return this.maybeJS(this.reduceQuotes(expr)) && this.checkJSSyntax(expr);
-  },
-
-
-  wantsExpression: (s) => /(?:^[+-]|[!%&(,*/:;<=>?\[^|]|[^-]-|[^+]\+)\s*$/.test(s),
-
-  stripLiteralsAndComments: function(s) {
-    "use strict";
-
-    const MODE_NORMAL = 0;
-    const MODE_REGEX = 1;
-    const MODE_SINGLEQUOTE = 2;
-    const MODE_DOUBLEQUOTE = 3;
-    const MODE_BLOCKCOMMENT = 4;
-    const MODE_LINECOMMENT = 6;
-    const MODE_INTERPOLATION = 7;
-
-    let mode = MODE_NORMAL;
-    let escape = false;
-    let res = [];
-    function handleQuotes(c, q, type) {
-       if (escape) {
-          escape = false;
-        } else if (c == '\\') {
-          escape = true;
-        } else if (c === q) {
-          res.push(type);
-          mode = MODE_NORMAL;
-        }
-    }
-    for (let j = 0, l = s.length; j < l; j++) {
-
-        switch(mode) {
-          case MODE_REGEX:
-            handleQuotes(s[j], '/', "_REGEXP_");
-            break;
-          case MODE_SINGLEQUOTE:
-            handleQuotes(s[j], "'", "_QS_");
-            break;
-          case MODE_DOUBLEQUOTE:
-            handleQuotes(s[j], '"', "_DQS_");
-            break;
-          case MODE_INTERPOLATION:
-            handleQuotes(s[j], '`', "``");
-            break;
-          case MODE_BLOCKCOMMENT:
-            if (s[j] === '/' && s[j-1] === '*') {
-               res.push("/**/");
-               mode = MODE_NORMAL;
-            }
-            break;
-          case MODE_LINECOMMENT:
-            if (s[j] === '\n') {
-               res.push("//\n");
-               mode = MODE_NORMAL;
-            }
-            break;
-        default:
-          switch(s[j]) {
-             case '"':
-                mode = MODE_DOUBLEQUOTE;
-                break;
-             case "'":
-                mode = MODE_SINGLEQUOTE;
-                break;
-             case "`":
-                mode = MODE_INTERPOLATION;
-                break;
-             case '/':
-                switch(s[j+1]) {
-                   case '*':
-                      mode = MODE_BLOCKCOMMENT;
-                      j+=2;
-                      break;
-                   case '/':
-                      mode = MODE_LINECOMMENT;
-                      break;
-                   default:
-                      let r = res.join('');
-                      res = [r];
-                      if (this.wantsExpression(r)) mode = MODE_REGEX;
-                      else res.push('/'); // after a self-contained expression: division operator
-                }
-                break;
-             default:
-                res.push(s[j]);
-          }
-
-       }
-    }
-    return res.join('');
-  },
-
-  checkLastFunction: function() {
-    var fn = this.syntax.lastFunction;
-    if (!fn) return false;
-    var m = fn.toSource().match(/\{([\s\S]*)\}/);
-    if (!m) return false;
-    var expr = this.stripLiteralsAndComments(m[1]);
-    return /=[\s\S]*cookie|\b(?:setter|document|location|(?:inn|out)erHTML|\.\W*src)[\s\S]*=|[\w$\u0080-\uffff\)\]]\s*[\[\(]/.test(expr) ||
-            this.maybeJS(expr);
-  },
-
-  _createInvalidRanges: function() {
-    function x(n) { return '\\u' + ("0000" + n.toString(16)).slice(-4); }
-
-    var ret = "";
-    var first = -1;
-    var last = -1;
-    var cur = 0x7e;
-    while(cur++ <= 0xffff) {
-      try {
-        eval("var _" + String.fromCharCode(cur) + "_=1");
-      } catch(e) {
-        if (!/illegal char/.test(e.message)) continue;
-        if (first == -1) {
-          first = last = cur;
-          ret += x(cur);
-          continue;
-        }
-        if (cur - last == 1) {
-          last = cur;
-          continue;
-        }
-
-        if(last != first) ret += "-" + x(last);
-        ret+= x(cur);
-        last = first = cur;
-      }
-    }
-    return ret;
-  },
-
-  get invalidCharsRx() {
-    delete this.invalidCharsRx;
-    return this.invalidCharsRx = new RegExp("^[^\"'`/<>]*[" + this._createInvalidRanges() + "]");
-  },
-
-  checkJSBreak: function InjectionChecker_checkJSBreak(s) {
-    // Direct script injection breaking JS string literals or comments
-
-
-    // cleanup most urlencoded noise and reduce JSON/XML
-    s = ';' + this.reduceXML(this.reduceJSON(this.collapseChars(
-        s.replace(/\%\d+[a-z\(]\w*/gi, '§')
-          .replace(/[\r\n\u2028\u2029]+/g, "\n")
-          .replace(/[\x01-\x09\x0b-\x20]+/g, ' ')
-        )));
-
-    if (s.indexOf("*/") > 0 && /\*\/[\s\S]+\/\*/.test(s)) { // possible scrambled multi-point with comment balancing
-      s += ';' + s.match(/\*\/[\s\S]+/);
-    }
-
-    if (!this.maybeJS(s)) return false;
-
-    const MAX_TIME = 8000, MAX_LOOPS = 1200;
-
-    const logEnabled = this.logEnabled;
-
-    const
-      invalidCharsRx = /[\u007f-\uffff]/.test(s) && this.invalidCharsRx,
-      dangerRx = /\(|(?:^|[+-]{2}|[+*/<>~-]+\\s*=)|`[\s\S]*`|\[[^\]]+\]|(?:setter|location|(?:inn|out)erHTML|cookie|on\w{3,}|\.\D)[^&]*=[\s\S]*?(?:\/\/|[\w$\u0080-\uFFFF.[\]})'"-]+)/,
-      exprMatchRx = /^[\s\S]*?(?:[=\)]|`[\s\S]*`|[+-]{2}|[+*/<>~-]+\\s*=)/,
-      safeCgiRx = /^(?:(?:[\.\?\w\-\/&:§\[\]]+=[\w \-:\+%#,§\.]*(?:[&\|](?=[^&\|])|$)){2,}|\w+:\/\/\w[\w\-\.]*)/,
-        // r2l, chained query string parameters, protocol://domain
-      headRx = /^(?:[^'"\/\[\(]*[\]\)]|[^"'\/]*(?:§|[^&]&[\w\.]+=[^=]))/
-        // irrepairable syntax error, such as closed parens in the beginning
-    ;
-
-    const injectionFinderRx = /(['"`#;>:{}]|[/?=](?![?&=])|&(?![\w-.[\]&!-]*=)|\*\/)(?!\1)/g;
-    injectionFinderRx.lastIndex = 0;
-
-    const t = Date.now();
-    var iterations = 0;
-
-    for (let dangerPos = 0, m; (m = injectionFinderRx.exec(s));) {
-
-      let startPos = injectionFinderRx.lastIndex;
-      let subj = s.substring(startPos);
-      if (startPos > dangerPos) {
-        dangerRx.lastIndex = startPos;
-        if (!dangerRx.exec(s)) {
-          this.log("Can't find any danger in " + s);
-          return false;
-        }
-        dangerPos = dangerRx.lastIndex;
-      }
-
-      let breakSeq = m[1];
-      let quote = breakSeq in this.breakStops ? breakSeq : '';
-
-      if (!this.maybeJS(quote ? quote + subj : subj)) {
-         this.log("Fast escape on " + subj, t, iterations);
-         return false;
-      }
-
-      let script = this.reduceURLs(subj);
-
-      if (script.length < subj.length) {
-        if (!this.maybeJS(script)) {
-          this.log("Skipping to first nested URL in " + subj, t, iterations);
-          injectionFinderRx.lastIndex += subj.indexOf("://") + 1;
-          continue;
-        }
-        subj = script;
-        script = this.reduceURLs(subj.substring(0, dangerPos - startPos));
-      } else {
-        script = subj.substring(0, dangerPos - startPos);
-      }
-
-      let expr = subj.match(exprMatchRx);
-
-      if (expr) {
-        expr = expr[0];
-        if (expr.length < script.length) {
-          expr = script;
-        }
-      } else {
-        expr = script;
-      }
-
-      // quickly skip (mis)leading innocuous CGI patterns
-      if ((m = subj.match(safeCgiRx))) {
-
-        this.log("Skipping CGI pattern in " + subj);
-
-        injectionFinderRx.lastIndex += m[0].length - 1;
-        continue;
-      }
-
-      let bs = this.breakStops[quote || 'nq']
-
-      for (let len = expr.length, moved = false, hunt = !!expr, lastExpr = ''; hunt;) {
-
-        if (Date.now() - t > MAX_TIME) {
-          this.log("Too long execution time! Assuming DOS... " + (Date.now() - t), t, iterations);
-          return true;
-        }
-
-        hunt = expr.length < subj.length;
-
-        if (moved) {
-          moved = false;
-        } else if (hunt) {
-          let pos = subj.substring(len).search(bs);
-          if (pos < 0) {
-            expr = subj;
-            hunt = false;
-          } else {
-            len += pos;
-            if (quote && subj[len] === quote) {
-              len++;
-            } else if (subj[len - 1] === '<') {
-              // invalid JS, and maybe in the middle of XML block
-              len++;
-              continue;
-            }
-            expr = subj.substring(0, len);
-            if (pos === 0) len++;
-          }
-        }
-
-        if(lastExpr === expr) {
-          lastExpr = '';
-          continue;
-        }
-
-        lastExpr = expr;
-
-        if(invalidCharsRx && invalidCharsRx.test(expr)) {
-          this.log("Quick skipping invalid chars");
-          break;
-        }
-
-
-
-        if (quote) {
-          if (this.checkNonTrivialJSSyntax(expr)) {
-            this.log("Non-trivial JS inside quoted string detected", t, iterations);
-            return true;
-          }
-          script = this.syntax.unquote(quote + expr, quote);
-          if(script && this.maybeJS(script) &&
-            (this.checkNonTrivialJSSyntax(script) ||
-              /'./.test(script) && this.checkNonTrivialJSSyntax("''" + script + "'") ||
-              /"./.test(script) && this.checkNonTrivialJSSyntax('""' + script + '"')
-            ) && this.checkLastFunction()
-            ) {
-            this.log("JS quote Break Injection detected", t, iterations);
-            return true;
-          }
-          script = quote + quote + expr + quote;
-        } else {
-          script = expr;
-        }
-
-        if (headRx.test(script.split("//")[0])) {
-          let balanced = script.replace(/^[^"'{}(]*\)/, 'P ');
-          if (balanced !== script && balanced.indexOf('(') > -1) {
-            script = balanced + ")";
-          } else {
-            this.log("SKIP (head syntax) " + script, t, iterations);
-            break; // unrepairable syntax error in the head, move left cursor forward
-          }
-        }
-
-        if (this.maybeJS(this.reduceQuotes(script))) {
-
-          if (this.checkJSSyntax(script) && this.checkLastFunction()) {
-            this.log("JS Break Injection detected", t, iterations);
-            return true;
-          }
-          if (++iterations > MAX_LOOPS) {
-            this.log("Too many syntax checks! Assuming DOS... " + s, t, iterations);
-            return true;
-          }
-          if(this.syntax.lastError) { // could be null if we're here thanks to checkLastFunction()
-            let errmsg = this.syntax.lastError.message;
-            if (logEnabled) this.log(errmsg + " --- " + this.syntax.sandbox.script + " --- ", t, iterations);
-            if(!quote) {
-              if (errmsg.indexOf("left-hand") !== -1) {
-                let m = subj.match(/^([^\]\(\\'"=\?]+?)[\w$\u0080-\uffff\s]+[=\?]/);
-                if (m) {
-                  injectionFinderRx.lastIndex += m[1].length - 1;
-                }
-                break;
-              } else if (errmsg.indexOf("unterminated string literal") !== -1) {
-                let quotePos = subj.substring(len).search(/["']/);
-                if(quotePos > -1) {
-                  expr = subj.substring(0, len += ++quotePos);
-                  moved = true;
-                } else break;
-              } else if (errmsg.indexOf("syntax error") !== -1) {
-                let dblSlashPos = subj.indexOf("//");
-                if (dblSlashPos > -1) {
-                  let pos = subj.search(/['"\n\\\(]|\/\*/);
-                  if (pos < 0 || pos > dblSlashPos)
-                    break;
-                }
-                if (/^([\w\[\]]*=)?\w*&[\w\[\]]*=/.test(subj)) { // CGI param concatenation
-                  break;
-                }
-              }
-            } else if (errmsg.indexOf("left-hand") !== -1) break;
-
-            if (/invalid .*\bflag\b|missing ; before statement|invalid label|illegal character|identifier starts immediately/.test(errmsg)) {
-              if (errmsg.indexOf("illegal character") === -1 && /#\d*\s*$/.test(script)) { // sharp vars exceptional behavior
-                if (!quote) break;
-                // let's retry without quotes
-                quote = lastExpr = '';
-                hunt = moved = true;
-              } else break;
-            }
-            else if((m = errmsg.match(/\b(?:property id\b|missing ([:\]\)\}]) )/))) {
-              let char = m[1] || '}';
-              let newLen = subj.indexOf(char, len);
-              let nextParamPos = subj.substring(len).search(/[^&]&(?!&)/)
-              if (newLen !== -1 && (nextParamPos === -1 || newLen <= len + nextParamPos)) {
-                this.log("Extending to next " + char);
-                expr = subj.substring(0, len = ++newLen);
-                moved = char !== ':';
-              } else if (char !== ':') {
-                let lastChar = expr[expr.length - 1];
-                if (lastChar === char && (len > subj.length || lastChar != subj[len - 1])) break;
-                expr += char;
-                moved = hunt = true;
-                len++;
-                this.log("Balancing " + char, t, iterations);
-              } else {
-                 break;
-              }
-            }
-            else if (/finally without try/.test(errmsg)) {
-              expr = "try{" + expr;
-              hunt = moved = true;
-            }
-          }
-        }
-      }
-    }
-    this.log(s, t, iterations);
-    return false;
-  },
-
-
-  checkJS: function(s, unescapedUni) {
-    this.log(s);
-
-    if (/\?name\b[\s\S]*:|[^&?]\bname\b/.test(s)) {
-      this.nameAssignment = true;
-    }
-
-    var hasUnicodeEscapes = !unescapedUni && /\\u[0-9a-f]{4}/i.test(s);
-    if (hasUnicodeEscapes && /\\u00[0-7][0-9a-f]/i.test(s)) {
-      this.escalate("Unicode-escaped lower ASCII");
-      return true;
-    }
-
-    if (/\\x[0-9a-f]{2}[\s\S]*['"]/i.test(s)) {
-      this.escalate("Obfuscated string literal");
-      return true;
-    }
-
-    if (/`[\s\S]*\$\{[\s\S]+[=(][\s\S]+\}[\s\S]*`/.test(s)) {
-      this.escalate("ES6 string interpolation");
-      return true;
-    }
-
-    this.syntax.lastFunction = null;
-    let ret = this.checkAttributes(s) ||
-      (/[\\\(]|=[^=]/.test(s) || this._riskyOperatorsRx.test(s)) &&  this.checkJSBreak(s) || // MAIN
-      hasUnicodeEscapes && this.checkJS(this.unescapeJS(s), true); // optional unescaped recursion
-    if (ret) {
-      let msg = "JavaScript Injection in " + s;
-      if (this.syntax.lastFunction) {
-        msg += "\n" + this.syntax.lastFunction.toSource();
-      }
-      this.escalate(msg);
-    }
-    return ret;
-  },
-
-  unescapeJS: function(s) {
-    return s.replace(/\\u([0-9a-f]{4})/gi, function(s, c) {
-      return String.fromCharCode(parseInt(c, 16));
-    });
-  },
-   unescapeJSLiteral: function(s) {
-    return s.replace(/\\x([0-9a-f]{2})/gi, function(s, c) {
-      return String.fromCharCode(parseInt(c, 16));
-    });
-  },
-
-  unescapeCSS: function(s) {
-    // see http://www.w3.org/TR/CSS21/syndata.html#characters
-    return s.replace(/\\([\da-f]{0,6})\s?/gi, function($0, $1) {
-      try {
-        return String.fromCharCode(parseInt($1, 16));
-      } catch(e) {
-        return "";
-      }
-    });
-  },
-
-  reduceDashPlus: function(s) {
-    // http://forums.mozillazine.org/viewtopic.php?p=5592865#p5592865
-    return s.replace(/\-+/g, "-")
-        .replace(/\++/g, "+")
-        .replace(/\s+/g, ' ')
-        .replace(/(?: \-)+/g, ' -')
-        .replace(/(?:\+\-)+/g, '+-');
-  },
-
-  _rxCheck: function(checker, s) {
-    var rx = this[checker + "Checker"];
-    var ret = rx.exec(s);
-    if (ret) {
-      this.escalate(checker + " injection:\n" + ret + "\nmatches " + rx.source);
-      return true;
-    }
-    return false;
-  },
-
-  AttributesChecker: new RegExp(
-    "(?:\\W|^)(?:javascript:(?:[\\s\\S]+[=\\\\\\(`\\[\\.<]|[\\s\\S]*(?:\\bname\\b|\\\\[ux]\\d))|" +
-    "data:(?:(?:[a-z]\\w+/\\w[\\w+-]+\\w)?[;,]|[\\s\\S]*;[\\s\\S]*\\b(?:base64|charset=)|[\\s\\S]*,[\\s\\S]*<[\\s\\S]*\\w[\\s\\S]*>))|@" +
-    ("import\\W*(?:\\/\\*[\\s\\S]*)?(?:[\"']|url[\\s\\S]*\\()" +
-      "|-moz-binding[\\s\\S]*:[\\s\\S]*url[\\s\\S]*\\(")
-      .replace(/[a-rt-z\-]/g, "\\W*$&"),
-    "i"),
-  checkAttributes: function(s) {
-    s = this.reduceDashPlus(s);
-    if (this._rxCheck("Attributes", s)) return true;
-    if (/\\/.test(s) && this._rxCheck("Attributes", this.unescapeCSS(s))) return true;
-    let dataPos = s.search(/data:\S*\s/i);
-    if (dataPos !== -1) {
-      let data = this.urlUnescape(s.substring(dataPos).replace(/\s/g, ''));
-      if (this.checkHTML(data) || this.checkAttributes(data)) return true;
-    }
-    return false;
-  },
-
-  HTMLChecker: new RegExp("<[^\\w<>]*(?:[^<>\"'\\s]*:)?[^\\w<>]*(?:" + // take in account quirks and namespaces
-   fuzzify("script|form|style|svg|marquee|(?:link|object|embed|applet|param|i?frame|base|body|meta|ima?ge?|video|audio|bindings|set|isindex|animate") +
-    ")[^>\\w])|['\"\\s\\0/](?:formaction|style|background|src|lowsrc|ping|" + IC_EVENT_PATTERN +
-     ")[\\s\\0]*=", "i"),
-
-  checkHTML: function(s) {
-     let links = s.match(/\b(?:href|src|(?:form)?action)[\s\0]*=[\s\0]*(?:(["'])[\s\S]*?\1|[^'"<>][^>\s]*)/ig);
-     if (links) {
-      for (let l  of links) {
-        l = l.replace(/[^=]*=[\s\0]*/i, '');
-        l = /^["']/.test(l) ? l.replace(/^(['"])([\s\S]*)\1/g, '$2') : l.replace(/[\s>][\s\S]*/, '');
-        if (/^(?:javascript|data):/i.test(l) || this._checkRecursive(l, 3)) return true;
-      }
-    }
-    return this._rxCheck("HTML", s);
-  },
-
-  checkNoscript: function(s) {
-    this.log(s);
-    return s.indexOf("\x1b(J") !== -1 && this.checkNoscript(s.replace(/\x1b\(J/g, '')) || // ignored in iso-2022-jp
-     s.indexOf("\x7e\x0a") !== -1 && this.checkNoscript(s.replace(/\x7e\x0a/g, '')) || // ignored in hz-gb-2312
-      this.checkHTML(s) || this.checkSQLI(s) || this.checkHeaders(s);
-  },
-
-  HeadersChecker: /[\r\n]\s*(?:content-(?:type|encoding))\s*:/i,
-  checkHeaders: function(s) { return this._rxCheck("Headers", s); },
-  SQLIChecker: /(?:(?:(?:\b|[^a-z])union[^a-z]|\()[\w\W]*(?:\b|[^a-z])select[^a-z]|(?:updatexml|extractvalue)(?:\b|[^a-z])[\w\W]*\()[\w\W]+(?:(?:0x|x')[0-9a-f]{16}|(?:0b|b')[01]{64}|\(|\|\||\+)/i
-  ,
-  checkSQLI: function(s) { return this._rxCheck("SQLI", s); },
-
-  base64: false,
-  base64tested: [],
-  get base64Decoder() { return Base64; }, // exposed here just for debugging purposes
-
-
-  checkBase64: function(url) {
-    this.base64 = false;
-
-    const MAX_TIME = 8000;
-    const DOS_MSG = "Too long execution time, assuming DOS in Base64 checks";
-
-    this.log(url);
-
-
-    var parts = url.split("#"); // check hash
-    if (parts.length > 1 && this.checkBase64FragEx(unescape(parts[1])))
-      return true;
-
-    parts = parts[0].split(/[&;]/); // check query string
-    if (parts.length > 0 && parts.some(function(p) {
-        var pos = p.indexOf("=");
-        if (pos > -1) p = p.substring(pos + 1);
-        return this.checkBase64FragEx(unescape(p));
-      }, this))
-      return true;
-
-    url = parts[0];
-    parts = Base64.purify(url).split("/");
-    if (parts.length > 255) {
-      this.log("More than 255 base64 slash chunks, assuming DOS");
-      return true;
-    }
-
-
-    var t = Date.now();
-    if (parts.some(function(p) {
-        if (Date.now() - t > MAX_TIME) {
-            this.log(DOS_MSG);
-            return true;
-        }
-        return this.checkBase64Frag(Base64.purify(Base64.alt(p)));
-      }, this))
-      return true;
-
-
-    var uparts = Base64.purify(unescape(url)).split("/");
-
-    t = Date.now();
-    while(parts.length) {
-      if (Date.now() - t > MAX_TIME) {
-          this.log(DOS_MSG);
-          return true;
-      }
-      if (this.checkBase64Frag(parts.join("/")) ||
-          this.checkBase64Frag(uparts.join("/")))
-        return true;
-
-      parts.shift();
-      uparts.shift();
-    }
-
-    return false;
-  },
-
-
-  checkBase64Frag: function(f) {
-    if (this.base64tested.indexOf(f) < 0) {
-      this.base64tested.push(f);
-      try {
-        var s = Base64.decode(f);
-        if(s && s.replace(/[^\w\(\)]/g, '').length > 7 &&
-           (this.checkHTML(s) ||
-              this.checkAttributes(s))
-           // this.checkJS(s) // -- alternate, whose usefulness is doubious but which easily leads to DOS
-           ) {
-          this.log("Detected BASE64 encoded injection: " + f + " --- (" + s + ")");
-          return this.base64 = true;
-        }
-      } catch(e) {}
-    }
-    return false;
-  },
-
-  checkBase64FragEx: function(f) {
-    return this.checkBase64Frag(Base64.purify(f)) || this.checkBase64Frag(Base64.purify(Base64.alt(f)));
-  },
-
-
-  checkURL: function(url) {
-    return this.checkRecursive(url
-      // assume protocol and host are safe, but keep the leading double slash to keep comments in account
-      .replace(/^[a-z]+:\/\/.*?(?=\/|$)/, "//")
-      // Remove outer parenses from ASP.NET cookieless session's AppPathModifier
-      .replace(/\/\((S\(\w{24}\))\)\//, '/$1/')
-    );
-  },
-
-  checkRecursive: function(s, depth, isPost) {
-    if (typeof(depth) != "number")
-      depth = 3;
-
-    this.reset();
-    this.isPost = isPost || false;
-
-    if (ASPIdiocy.affects(s)) {
-      if (this.checkRecursive(ASPIdiocy.process(s), depth, isPost))
-        return true;
-    } else if (ASPIdiocy.hasBadPercents(s) && this.checkRecursive(ASPIdiocy.removeBadPercents(s), depth, isPost))
-      return true;
-
-    if (FlashIdiocy.affects(s)) {
-      let purged = FlashIdiocy.purgeBadEncodings(s);
-      if (purged !== s && this.checkRecursive(purged, depth, isPost))
-        return true;
-      let decoded = FlashIdiocy.platformDecode(purged);
-      if (decoded !== purged && this.checkRecursive(decoded, depth, isPost))
-        return true;
-    }
-
-    if (s.indexOf("coalesced:") !== 0) {
-      let coalesced = ASPIdiocy.coalesceQuery(s);
-      if (coalesced !== s && this.checkRecursive("coalesced:" + coalesced, depth, isPost))
-        return true;
-    }
-
-    if (isPost) {
-      s = this.formUnescape(s);
-      if (this.checkBase64Frag(Base64.purify(s))) return true;
-
-      if (s.indexOf("<") > -1) {
-        // remove XML-embedded Base64 binary data
-        s = s.replace(/<((?:\w+:)?\w+)>[0-9a-zA-Z+\/]+=*<\/\1>/g, '');
-      }
-
-      s = "#" + s;
-    } else {
-      if (this.checkBase64(s.replace(/^\/{1,3}/, ''))) return true;
-    }
-
-    if (isPost) s = "#" + s; // allows the string to be JS-checked as a whole
-    return this._checkRecursive(s, depth);
-  },
-
-  _checkRecursive: function(s, depth) {
-
-    if (this.checkHTML(s) || this.checkJS(s) || this.checkSQLI(s) || this.checkHeaders(s))
-      return true;
-
-    if (s.indexOf("&") !== -1) {
-      let unent = Entities.convertAll(s);
-      if (unent !== s && this._checkRecursive(unent, depth)) return true;
-    }
-
-    if (--depth <= 0)
-      return false;
-
-    if (s.indexOf('+') !== -1 && this._checkRecursive(this.formUnescape(s), depth))
-      return true;
-
-    var unescaped = this.urlUnescape(s);
-    let badUTF8 = this.utf8EscapeError;
-
-    if (this._checkOverDecoding(s, unescaped))
-      return true;
-
-    if (/[\n\r\t]|&#/.test(unescaped)) {
-      let unent = Entities.convertAll(unescaped).replace(/[\n\r\t]/g, '');
-      if (unescaped != unent && this._checkRecursive(unent, depth)) {
-        this.log("Trash-stripped nested URL match!"); // http://mxr.mozilla.org/mozilla-central/source/netwerk/base/src/nsURLParsers.cpp#100
-        return true;
-      }
-    }
-
-    if (/\\x[0-9a-f]/i.test(unescaped)) {
-      let literal = this.unescapeJSLiteral(unescaped);
-      if (unescaped !== literal && this._checkRecursive(literal, depth)) {
-        this.log("Escaped literal match!");
-        return true;
-      }
-    }
-
-    if (unescaped.indexOf("\x1b(J") !== -1 && this._checkRecursive(unescaped.replace(/\x1b\(J/g, ''), depth) || // ignored in iso-2022-jp
-        unescaped.indexOf("\x7e\x0a") !== -1 && this._checkRecursive(unescaped.replace(/\x7e\x0a/g, '')) // ignored in hz-gb-2312
-      )
-      return true;
-
-    if (unescaped !== s) {
-      if (badUTF8) {
-        try {
-          if (this._checkRecursive(this.toUnicode(unescaped, "UTF-8"))) return true;
-        } catch (e) {
-          this.log(e);
-        }
-      }
-      if (this._checkRecursive(unescaped, depth)) return true;
-    }
-
-    s = this.ebayUnescape(unescaped);
-    if (s != unescaped && this._checkRecursive(s, depth))
-      return true;
-
-    return false;
-  },
-
-  _checkOverDecoding: function(s, unescaped) {
-    if (/%[8-9a-f]/i.test(s)) {
-      const rx = /[<'"]/g;
-      var m1 = unescape(this.utf8OverDecode(s, false)).match(rx);
-      if (m1) {
-        unescaped = unescaped || this.urlUnescape(s);
-        var m0 = unescaped.match(rx);
-        if (!m0 || m0.length < m1.length) {
-          this.log("Potential utf8_decode() exploit!");
-          return true;
-        }
-      }
-    }
-    return false;
-  },
-
-  utf8OverDecode: function(url, strict) {
-    return url.replace(strict
-      ? /%(?:f0%80%80|e0%80|c0)%[8-b][0-f]/gi
-      : /%(?:f[a-f0-9](?:%[0-9a-f]0){2}|e0%[4-9a-f]0|c[01])%[a-f0-9]{2}/gi,
-      function(m) {
-        var hex = m.replace(/%/g, '');
-        if (strict) {
-          for (var j = 2; j < hex.length; j += 2) {
-            if ((parseInt(hex.substring(j, j + 2), 16) & 0xc0) != 0x80) return m;
-          }
-        }
-        switch (hex.length) {
-          case 8:
-            hex = hex.substring(2);
-          case 6:
-            c = (parseInt(hex.substring(0, 2), 16) & 0x3f) << 12 |
-                   (parseInt(hex.substring(2, 4), 16) & 0x3f) << 6 |
-                    parseInt(hex.substring(4, 6), 16) & 0x3f;
-            break;
-          default:
-            c = (parseInt(hex.substring(0, 2), 16) & 0x3f) << 6 |
-                    parseInt(hex.substring(2, 4), 16) & 0x3f;
-        }
-        return encodeURIComponent(String.fromCharCode(c & 0x3f));
-      }
-    );
-  },
-
-  toUnicode: function(s, charset) {
-    let sis = Cc["@mozilla.org/io/string-input-stream;1"]
-          .createInstance(Ci.nsIStringInputStream);
-    sis.setData(s, s.length);
-    let is = Cc["@mozilla.org/intl/converter-input-stream;1"]
-          .createInstance(Ci.nsIConverterInputStream);
-    is.init(sis, charset || null, 0, is.DEFAULT_REPLACEMENT_CHARACTER);
-    let str = {};
-    if (is.readString(4096, str) === 0) return str.value;
-    let ret = [str.value];
-    while (is.readString(4096, str) !== 0) {
-      ret.push(str.value);
-    }
-    return ret.join('');
-  },
-
-  utf8EscapeError: true,
-  urlUnescape: function(url, brutal) {
-    var od = this.utf8OverDecode(url, !brutal);
-    this.utf8EscapeError = false;
-    try {
-      return decodeURIComponent(od);
-    } catch(warn) {
-      this.utf8EscapeError = true;
-      if (url != od) url += " (" + od + ")";
-      this.log("Problem decoding " + url + ", maybe not an UTF-8 encoding? " + warn.message);
-      return unescape(brutal ? ASPIdiocy.filter(od) : od);
-    }
-  },
-
-  formUnescape: function(s, brutal) {
-    return this.urlUnescape(s.replace(/\+/g, ' '), brutal);
-  },
-
-  aspUnescape: function(s) {
-    return unescape(ASPIdiocy.filter(s).replace(/\+/g, ' '));
-  },
-
-  ebayUnescape: function(url) {
-    return url.replace(/Q([\da-fA-F]{2})/g, function(s, c) {
-      return String.fromCharCode(parseInt(c, 16));
-    });
-  },
-
-  checkPost: function(channel, skip) {
-    if (!((channel instanceof Ci.nsIUploadChannel)
-          && channel.uploadStream && (channel.uploadStream instanceof Ci.nsISeekableStream)))
-      return false;
-
-    var clen = -1;
-    try {
-      clen = channel.getRequestHeader("Content-length");
-    } catch(e) {}
-    MaxRunTime.increase(clen < 0 || clen > 300000 ? 60 : Math.ceil(20 * clen / 100000));
-
-    this.log("Extracting post data...");
-    return this.checkPostStream(channel.URI.spec, channel.uploadStream, skip);
-  },
-
-  checkPostStream: function(url, stream, skip) {
-     var ic = this;
-     var pc = new PostChecker(url, stream, skip);
-     return pc.check(
-      function(chunk) {
-        return chunk.length > 6 &&
-          ic.checkRecursive(chunk, 2, !pc.isFile) && chunk;
-      }
-    );
-  },
-
-  testCheckPost: function(url, strData) {
-    var stream = Cc["@mozilla.org/io/string-input-stream;1"].
-            createInstance(Ci.nsIStringInputStream);
-    stream.setData(strData, strData.length);
-    return this.checkPostStream(url, stream);
-  },
-
-
-  checkWindowName: function (window, url) {
-     var originalAttempt = window.name;
-     try {
-       if (/^https?:\/\/(?:[^/]*\.)?\byimg\.com\/rq\/darla\//.test(url) &&
-          ns.getPref("filterXExceptions.darla_name")) {
-         window.name = "DARLA_JUNK";
-         return;
-       }
-
-       if (/\s*{[\s\S]+}\s*/.test(originalAttempt)) {
-         try {
-           JSON.parse(originalAttempt); // fast track for crazy JSON in name like on NYT
-           return;
-         } catch(e) {}
-       }
-
-       if (/[%=\(\\<]/.test(originalAttempt) && InjectionChecker.checkURL(originalAttempt)) {
-         window.name = originalAttempt.replace(/[%=\(\\<]/g, " ");
-       }
-
-       if (originalAttempt.length > 11) {
-         try {
-           if ((originalAttempt.length % 4 === 0)) {
-             var bin = window.atob(window.name);
-             if(/[%=\(\\]/.test(bin) && InjectionChecker.checkURL(bin)) {
-               window.name = "BASE_64_XSS";
-             }
-           }
-         } catch(e) {}
-       }
-    } finally {
-      if (originalAttempt != window.name) {
-        ns.log('[NoScript XSS]: sanitized window.name, "' + originalAttempt + '"\nto\n"' + window.name + '"\nURL: ' + url);
-        ns.log(url + "\n" + window.location.href);
-      }
-    }
-  },
-
-};
-
-function PostChecker(url, uploadStream, skip) {
-  this.url = url;
-  this.uploadStream = uploadStream;
-  this.skip = skip || false;
-}
-
-PostChecker.prototype = {
-  boundary: null,
-  isFile: false,
-  postData: '',
-  check: function(callback) {
-    var m, chunks, data, size, available, ret;
-    const BUF_SIZE = 3 * 1024 * 1024; // 3MB
-    const MAX_FIELD_SIZE = BUF_SIZE;
-    try {
-      var us = this.uploadStream;
-      us.seek(0, 0);
-      const sis = Cc['@mozilla.org/binaryinputstream;1'].createInstance(Ci.nsIBinaryInputStream);
-      sis.setInputStream(us);
-
-      // reset status
-      delete this.boundary;
-      delete this.isFile;
-      delete this.postData;
-
-      if ((available = sis.available())) do {
-        size = this.postData.length;
-        if (size >= MAX_FIELD_SIZE) return size + " bytes or more in one non-file field, assuming memory DOS attempt!";
-
-        data = sis.readBytes(Math.min(available, BUF_SIZE));
-
-        if (size !== 0) {
-          this.postData += data;
-        } else {
-           if (data.length === 0) return false;
-           this.postData = data;
-        }
-        available = sis.available();
-        chunks = this.parse(!available);
-
-        for (var j = 0, len = chunks.length; j < len; j++) {
-          ret = callback(chunks[j]);
-          if (ret) return ret;
-        }
-      } while(available)
-    } catch(ex) {
-      dump(ex + "\n" + ex.stack + "\n");
-      return ex;
-    } finally {
-        try {
-          us.seek(0, 0); // rewind
-        } catch(e) {}
-    }
-    return false;
-  },
-
-  parse: function(eof) {
-    var postData = this.postData;
-    var m;
-
-    if (typeof(this.boundary) != "string") {
-      m = postData.match(/^Content-type: multipart\/form-data;\s*boundary=(\S*)/i);
-      this.boundary = m && m[1] || '';
-      if (this.boundary) this.boundary = "--" + this.boundary;
-      postData = postData.substring(postData.indexOf("\r\n\r\n") + 2);
-    }
-
-    this.postData = '';
-
-    var boundary = this.boundary;
-
-    var chunks = [];
-    var j, len, name;
-
-    var skip = this.skip;
-
-    if (boundary) { // multipart/form-data, see http://www.faqs.org/ftp/rfc/rfc2388.txt
-      if(postData.indexOf(boundary) < 0) {
-        // skip big file chunks
-        return chunks;
-      }
-      var parts = postData.split(boundary);
-
-      var part, last;
-      for(j = 0, len = parts.length; j < len;) {
-        part = parts[j];
-        last = ++j == len;
-        if (j == 1 && part.length && this.isFile) {
-          // skip file internal terminal chunk
-          this.isFile = false;
-          continue;
-        }
-        m = part.match(/^\s*Content-Disposition: form-data; name="(.*?)"(?:;\s*filename="(.*)"|[^;])\r?\n(Content-Type: \w)?.*\r?\n/i);
-
-        if (m) {
-          // name and filename are backslash-quoted according to RFC822
-          name = m[1];
-          if (name) {
-            chunks.push(name.replace(/\\\\/g, "\\")); // name and file name
-          }
-          if (m[2]) {
-            chunks.push(m[2].replace(/\\\\/g, "\\")); // filename
-            if (m[3]) {
-              // Content-type: skip, it's a file
-              this.isFile = true;
-
-              if (last && !eof)
-                this.postData = part.substring(part.length - boundary.length);
-
-              continue;
-            }
-          }
-          if (eof || !last) {
-            if (!(skip && skip.indexOf(name) !== -1))
-              chunks.push(part.substring(m[0].length)); // parameter body
-          } else {
-            this.postData = part;
-          }
-          this.isFile = false;
-        } else {
-          // malformed part, check it all or push it back
-          if (eof || !last) {
-            chunks.push(part)
-          } else {
-            this.postData = this.isFile ? part.substring(part.length - boundary.length) : part;
-          }
-        }
-      }
-    } else {
-      this.isFile = false;
-
-      parts = postData.replace(/^\s+/, '').split("&");
-      if (!eof) this.postData = parts.pop();
-
-      for (j = 0, len = parts.length; j < len; j++) {
-        m = parts[j].split("=");
-        name = m[0];
-        if (skip && skip.indexOf(name) > -1) continue;
-        chunks.push(name, m[1] || '');
-      }
-    }
-    return chunks;
-  }
-}
-
-
-function XSanitizer(primaryBlacklist, extraBlacklist) {
-  this.primaryBlacklist = primaryBlacklist;
-  this.extraBlacklist = extraBlacklist;
-  this.injectionChecker = InjectionChecker;
-}
-
-XSanitizer.prototype = {
-  brutal: false,
-  base64: false,
-  sanitizeURL: function(url) {
-    var original = url.clone();
-    this.brutal = this.brutal || this.injectionChecker.checkURL(url.spec);
-    this.base64 = this.injectionChecker.base64;
-
-    const changes = { minor: false, major: false, qs: false };
-    // sanitize credentials
-    if (url.username) url.username = this.sanitizeEnc(url.username);
-    if (url.password) url.password = this.sanitizeEnc(url.password);
-    url.host = this.sanitizeEnc(url.host);
-
-    if (url instanceof Ci.nsIURL) {
-      // sanitize path
-
-      if (url.param) {
-        url.path = this.sanitizeURIComponent(url.path); // param is the URL part after filePath and a semicolon ?!
-      } else if(url.filePath) {
-        url.filePath = this.sanitizeURIComponent(url.filePath); // true == lenient == allow ()=
-      }
-      // sanitize query
-      if (url.query) {
-        url.query = this.sanitizeQuery(url.query, changes);
-        if (this.brutal) {
-          url.query = this.sanitizeWholeQuery(url.query, changes);
-        }
-      }
-      // sanitize fragment
-      var fragPos = url.path.indexOf("#");
-      if (url.ref || fragPos > -1) {
-        if (fragPos >= url.filePath.length + url.query.length) {
-          url.path = url.path.substring(0, fragPos) + "#" + this.sanitizeEnc(url.path.substring(fragPos + 1));
-        } else {
-          url.ref = this.sanitizeEnc(url.ref);
-        }
-      }
-    } else {
-      // fallback for non-URL URIs, we should never get here anyway
-      if (url.path) url.path = this.sanitizeURIComponent(url.path);
-    }
-
-    var urlSpec = url.spec;
-    var neutralized = Entities.neutralizeAll(urlSpec, /[^\\'"\x00-\x07\x09\x0B\x0C\x0E-\x1F\x7F<>]/);
-    if (urlSpec != neutralized) url.spec = neutralized;
-
-    if (this.base64 ||
-        FlashIdiocy.affects(urlSpec) ||
-        FlashIdiocy.affects(unescape(urlSpec))
-      ) {
-      url.spec = url.prePath; // drastic, but with base64 / FlashIdiocy we cannot take the risk!
-    }
-
-    if (url.getRelativeSpec(original) && unescape(url.spec) != unescape(original.spec)) { // ok, this seems overkill but take my word, the double check is needed
-      changes.minor = true;
-      changes.major = changes.major || changes.qs ||
-                      unescape(original.spec.replace(/\?.*/g, ""))
-                        != unescape(url.spec.replace(/\?.*/g, ""));
-      url.spec = url.spec.replace(/'/g, "%27")
-      if (changes.major) {
-        url.ref = Math.random().toString().concat(Math.round(Math.random() * 999 + 1)).replace(/0./, '') // randomize URI
-      }
-    } else {
-      changes.minor = false;
-      url.spec = original.spec.replace(/'/g, "%27");
-    }
-    return changes;
-  },
-
-  sanitizeWholeQuery: function(query, changes) {
-    var original = query;
-    query = Entities.convertAll(query);
-    if (query === original) return query;
-    var unescaped = InjectionChecker.urlUnescape(original, true);
-    query = this.sanitize(unescaped);
-    if (query === unescaped) return original;
-    if(changes) changes.qs = true;
-    return escape(query);
-  },
-
-  _queryRecursionLevel: 0,
-  sanitizeQuery: function(query, changes, sep) {
-    const MAX_RECUR = 2;
-
-    var canRecur = this._queryRecursionLevel++ < MAX_RECUR;
-    // replace every character matching noscript.filterXGetRx with a single ASCII space (0x20)
-    changes = changes || {};
-    if (!sep) {
-      sep = query.indexOf("&") > -1 || this.brutal ? "&" : ";"
-    }
-    const parms = query.split(sep);
-
-    for (let j = parms.length; j-- > 0;) {
-      let pieces = parms[j].split("=");
-
-      try {
-        for (let k = pieces.length; k-- > 0;) {
-
-          let encodedPz =  InjectionChecker.utf8OverDecode(pieces[k]);
-
-          let pz = null, encodeURL = null;
-          if (encodedPz.indexOf("+") < 0) {
-            try {
-              pz = decodeURIComponent(encodedPz);
-              encodeURL = encodeURIComponent;
-            } catch(e) {}
-          }
-          if (pz == null) {
-            pz = unescape(ASPIdiocy.filter(encodedPz));
-            encodeURL = escape;
-          }
-
-          let origPz = pz;
-
-          // recursion for nested (partial?) URIs
-
-          let nestedURI = null;
-
-          if (canRecur && /^https?:\/\//i.test(pz)) {
-            // try to sanitize as a nested URL
-            try {
-              nestedURI = IOUtil.newURI(pz).QueryInterface(Ci.nsIURL);
-              changes.qs = changes.qs || this.sanitizeURL(nestedURI).major;
-              if (unescape(pz).replace(/\/+$/, '') != unescape(nestedURI.spec).replace(/\/+$/, '')) pz = nestedURI.spec;
-            } catch(e) {
-              nestedURI = null;
-            }
-          }
-
-          if (!nestedURI) {
-            let qpos;
-            if (canRecur &&
-                 (qpos = pz.indexOf("?")) > - 1 &&
-                 (spos = pz.search(/[&;]/) > qpos)) {
-              // recursive query string?
-              // split, sanitize and rejoin
-              pz = [ this.sanitize(pz.substring(0, qpos)),
-                    this.sanitizeQuery(pz.substring(qpos + 1), changes)
-                   ].join("?")
-
-            } else {
-              pz = this.sanitize(pz);
-            }
-            if (origPz != pz) changes.qs = true;
-          }
-
-          if (origPz != pz) pieces[k] = encodeURL(pz);
-
-        }
-        parms[j] = pieces.join("=");
-      } catch(e) {
-        // decoding exception, skip this param
-        parms.splice(j, 1);
-      }
-    }
-    this._queryRecursionLevel--;
-    return parms.join(sep);
-  },
-
-  sanitizeURIComponent: function(s) {
-    try {
-      var unescaped = InjectionChecker.urlUnescape(s, this.brutal);
-      var sanitized = this.sanitize(unescaped);
-      return sanitized == unescaped ? s : encodeURI(sanitized);
-    } catch(e) {
-      return "";
-    }
-  },
-  sanitizeEnc: function(s) {
-    try {
-      return encodeURIComponent(this.sanitize(decodeURIComponent(s)));
-    } catch(e) {
-      return "";
-    }
-  },
-  sanitize: function(unsanitized) {
-    var s, orig;
-    orig = s = Entities.convertDeep(unsanitized);
-
-    if (s.indexOf('"') > -1 && !this.brutal) {
-      // try to play nice on search engine queries with grouped quoted elements
-      // by allowing double quotes but stripping even more aggressively other chars
-
-      // Google preserves "$" and recognizes ~, + and ".." as operators
-      // All the other non alphanumeric chars (aside double quotes) are ignored.
-      // We will preserve the site: modifier as well
-      // Ref.: http://www.google.com/help/refinesearch.html
-      s = s.replace(/[^\w\$\+\.\~"&;\- :\u0080-\uffff]/g,
-          " " // strip everything but alphnum and operators
-          ).replace(":",
-          function(k, pos, s) { // strip colons as well, unless it's the site: operator
-            return (s.substring(0, pos) == "site" || s.substring(pos - 5) == " site") ? ":" : " "
-          }
-        );
-      if (s.replace(/[^"]/g, "").length % 2) s += '"'; // close unpaired quotes
-      return s;
-    }
-
-    if (this.brutal) {
-      s = s.replace(/\x1bJ\(/g, '').replace(/\x7e\x0a/g, ''); // ignored in some encodings
-    }
-    // regular duty
-    s = s.replace(this.primaryBlacklist, " ")
-      .replace(/\bjavascript:+|\bdata:[^,]+,(?=[^<]*<|%25%20|%\s+[2-3][0-9a-f])|-moz-binding|@import/ig,
-                function(m) { return m.replace(/(.*?)(\w)/, "$1#no$2"); });
-
-    if (this.extraBlacklist) { // additional user-defined blacklist for emergencies
-      s = s.replace(this.extraBlacklist, " ");
-    }
-
-    if (this.brutal) { // injection checks were positive
-      s = InjectionChecker.reduceDashPlus(s)
-        .replace(/\bdata:/ig, "nodata:")
-        .replace(/['\(\)\=\[\]<\r\n`]/g, " ")
-        .replace(/0x[0-9a-f]{16,}|0b[01]{64,}/gi, " ")
-        .replace(this._dangerousWordsRx, this._dangerousWordsReplace)
-        .replace(/Q[\da-fA-Fa]{2}/g, "Q20") // Ebay-style escaping
-        .replace(/%[\n\r\t]*[0-9a-f][\n\r\t]*[0-9a-f]/gi, " ")
-        // .replace(/percnt/, 'percent')
-        ;
-    }
-
-    return s == orig ? unsanitized : s;
-  },
-
-  _regularReplRx: new RegExp(
-    fuzzify('(?:javascript|data)') + '\\W*:+|' +
-      fuzzify('-moz-binding|@import'),
-    "ig"
-  ),
-  _dangerousWordsRx: new RegExp(
-    '\\b(?:' + fuzzify('setter|location|innerHTML|outerHTML|cookie|name|document|toString|') +
-    IC_EVAL_PATTERN + '|' + IC_EVENT_PATTERN + ')\\b',
-    "g"
-  ),
-  _dangerousWordsReplace: (s) => s.replace(/\S/g, "$&\u2063")
-
-};
-
-// we need this because of https://bugzilla.mozilla.org/show_bug.cgi?id=439276
-
-var Base64 = {
-
-  purify: function(input) {
-    return input.replace(/[^A-Za-z0-9\+\/=]+/g, '');
-  },
-
-  alt: function(s) {
-    // URL base64 variant, see http://en.wikipedia.org/wiki/Base64#URL_applications
-    return s.replace(/-/g, '+').replace(/_/g, '/')
-  },
-
-  decode: function (input, strict) {
-    var output = '';
-    var chr1, chr2, chr3;
-    var enc1, enc2, enc3, enc4;
-    var i = 0;
-
-    // if (/[^A-Za-z0-9\+\/\=]/.test(input)) return ""; // we don't need this, caller checks for us
-
-    const k = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
-    while (i < input.length) {
-
-        enc1 = k.indexOf(input.charAt(i++));
-        enc2 = k.indexOf(input.charAt(i++));
-        enc3 = k.indexOf(input.charAt(i++));
-        enc4 = k.indexOf(input.charAt(i++));
-
-        chr1 = (enc1 << 2) | (enc2 >> 4);
-        chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
-        chr3 = ((enc3 & 3) << 6) | enc4;
-
-        output += String.fromCharCode(chr1);
-
-        if (enc3 != 64) {
-          output += String.fromCharCode(chr2);
-        }
-        if (enc4 != 64) {
-          output += String.fromCharCode(chr3);
-        }
-
-    }
-    return output;
-
-  }
-};
-
-
-
-
-var ASPIdiocy = {
-  _replaceRx: /%u([0-9a-fA-F]{4})/g,
-  _affectsRx: /%u[0-9a-fA-F]{4}/,
-  _badPercentRx: /%(?!u[0-9a-fA-F]{4}|[0-9a-fA-F]{2})|%(?:00|u0000)[^&=]*/g,
-
-  hasBadPercents: function(s) { return this._badPercentRx.test(s) },
-  removeBadPercents: function(s) { return s.replace(this._badPercentRx, ''); },
-  affects: function(s) { return this._affectsRx.test(s); },
-  process: function(s) {
-    s = this.filter(s);
-    return /[\uff5f-\uffff]/.test(s) ? s + '&' + s.replace(/[\uff5f-\uffff]/g, '?') : s;
-  },
-  filter: function(s) { return this.removeBadPercents(s).replace(this._replaceRx, this._replace) },
-
-  coalesceQuery: function(s) { // HPP protection, see https://www.owasp.org/images/b/ba/AppsecEU09_CarettoniDiPaola_v0.8.pdf
-    let qm = s.indexOf("?");
-    if (qm < 0) return s;
-    let p = s.substring(0, qm);
-    let q = s.substring(qm + 1);
-    if (!q) return s;
-
-    let unchanged = true;
-    let emptyParams = false;
-
-    let pairs = (function rearrange(joinNames) {
-      let pairs = q.split("&");
-      let accumulator = { __proto__: null };
-      for (let j = 0, len = pairs.length; j < len; j++) {
-        let nv = pairs[j];
-        let eq = nv.indexOf("=");
-        if (eq === -1) {
-          emptyParams = true;
-          if (joinNames && j < len - 1) {
-            pairs[j + 1] = nv + "&" + pairs[j + 1];
-            delete pairs[j];
-          }
-          continue;
-        }
-        let key = "#" + unescape(nv.substring(0, eq)).toLowerCase();
-        if (key in accumulator) {
-          delete pairs[j];
-          pairs[accumulator[key]] += ", " + nv.substring(eq + 1);
-          unchanged = false;
-        } else {
-          accumulator[key] = j;
-        }
-      }
-      return (emptyParams && !(unchanged || joinNames))
-        ? pairs.concat(rearrange(true).filter(p => pairs.indexOf(p) === -1))
-        : pairs;
-    })();
-
-    if (unchanged) return s;
-    for (let j = pairs.length; j-- > 0;) if (!pairs[j]) pairs.splice(j, 1);
-    return p + pairs.join("&");
-  },
-
-  _replace: function(match, hex) {
-     // lazy init
-     INCLUDE("ASPIdiocy");
-     return ASPIdiocy._replace(match, hex);
-  }
-}
-
-var FlashIdiocy = {
-  _affectsRx: /%(?:[8-9a-f]|[0-7]?[^0-9a-f])/i, // high (non-ASCII) percent encoding or invalid second digit
-  affects: function(s) { return this._affectsRx.test(s); },
-
-  purgeBadEncodings: function(s) {
-    INCLUDE("FlashIdiocy");
-    return this.purgeBadEncodings(s);
-  }
-}
+
+const wordCharRx = /\w/g;
+function fuzzify(s) {
+  return s.replace(wordCharRx, '\\W*(?:/[*/][\\s\\S]*)?$&');
+}
+
+const IC_COMMENT_PATTERN = '\\s*(?:\\/[\\/\\*][\\s\\S]+)?';
+const IC_WINDOW_OPENER_PATTERN = fuzzify("alert|confirm|prompt|open(?:URL)?|print|show") + "\\w*" + fuzzify("Dialog");
+const IC_EVAL_PATTERN = "\\b(?:" +
+  fuzzify('eval|set(?:Timeout|Interval)|(?:f|F)unction|Script|toString|Worker|document|constructor|generateCRMFRequest|jQuery|fetch|write(?:ln)?|__(?:define(?:S|G)etter|noSuchMethod)__|definePropert(?:y|ies)') +
+   "|\\$|" + IC_WINDOW_OPENER_PATTERN + ")\\b";
+const IC_EVENT_PATTERN = "on(?:c(?:o(?:n(?:nect(?:i(?:on(?:statechanged|available)|ng)|ed)?|t(?:rollerchange|extmenu))|m(?:p(?:osition(?:update|start|end)|lete)|mand(?:update)?)|py)|h(?:a(?:r(?:ging(?:time)?change|acteristicchanged)|nge)|ecking)|a(?:n(?:play(?:through)?|cel)|(?:llschang|ch)ed|rdstatechange)|u(?:rrent(?:channel|source)changed|echange|t)|l(?:i(?:rmodechange|ck)|ose)|fstatechange)|p(?:o(?:inter(?:l(?:ock(?:change|error)|eave)|o(?:ver|ut)|cancel|enter|down|move|up)|p(?:up(?: [...]
+  // autogenerated from nsHtml5AtomList.h and nsGkAtomList.h
+  ;
+const IC_EVENT_DOS_PATTERN =
+      "\\b(?:" + IC_EVENT_PATTERN + ")[\\s\\S]*=[\\s\\S]*\\b(?:" + IC_WINDOW_OPENER_PATTERN + ")\\b" +
+      "|\\b(?:" + IC_WINDOW_OPENER_PATTERN + ")\\b[\\s\\S]+\\b(?:" + IC_EVENT_PATTERN + ")[\\s\\S]*=";
+
+var InjectionChecker = {
+  reset: function () {
+
+    this.isPost =
+      this.base64 =
+      this.nameAssignment = false;
+
+    this.base64tested = [];
+
+  },
+
+  fuzzify: fuzzify,
+  syntax: new SyntaxChecker(),
+  _log: function(msg, t, i) {
+    if (msg) msg = this._printable(msg);
+    if(!(i || t)) {
+      msg += " - LINES: ";
+      var lines = [];
+      for (var stack = Components.stack; (stack = stack.caller);) {
+        lines.push(stack.lineNumber);
+      }
+      msg += lines.join(", ");
+    }
+    else {
+      if (t) msg += " - TIME: " + (Date.now() - t);
+      if (i) msg += " - ITER: " + i;
+    }
+    this.dump("[NoScript InjectionChecker] " + msg + "\n");
+  },
+
+  _printable: function (msg) {
+    return msg.toString().replace(/[^\u0020-\u007e]/g, function(s) { return "{" + s.charCodeAt(0).toString(16) + "}"; });
+  },
+
+  dump: dump,
+  log: function() {},
+  get logEnabled() { return this.log == this._log; },
+  set logEnabled(v) { this.log = v ? this._log : function() {}; },
+
+  escalate: function(msg) {
+    this.log(msg);
+    ns.log("[NoScript InjectionChecker] " + msg);
+  },
+
+  bb: function(brac, s, kets) {
+    for(var j = 3; j-- > 0;) {
+      s = brac + s + kets;
+      if (this.checkJSSyntax(s)) return true;
+    }
+    return false;
+  },
+
+  checkJSSyntax(s) {
+     // bracket balancing for micro injections like "''), e v a l (name,''"
+    if (/^(?:''|"")?[^\('"]*\)/.test(s)) return this.bb("x(\n", s, "\n)");
+    if (/^(?:''|"")?[^\['"]*\\]/.test(s)) return this.bb("y[\n", s, "\n]");
+    if (/^(?:''|"")?[^\{'"]*\}/.test(s)) return this.bb("function z() {\n", s, "\n}");
+
+    let syntax = this.syntax;
+    s += " /* COMMENT_TERMINATOR */\nDUMMY_EXPR";
+    if (syntax.check(s)) {
+      this.log("Valid fragment " + s);
+      return true;
+    }
+    return false;
+  },
+
+  checkTemplates(script) {
+    let templateExpressions = script.replace(/[[\]{}]/g, ";");
+    return templateExpressions !== script &&
+        this.maybeMavo(script) ||
+        (this.maybeJS(templateExpressions, true) &&
+        (this.syntax.check(templateExpressions) ||
+          /[^><=]=[^=]/.test(templateExpressions) && this.syntax.check(
+            templateExpressions.replace(/([^><=])=(?=[^=])/g, '$1=='))
+        ));
+  },
+
+  maybeMavo(s) {
+    return /\[[^]*\([^]*\)[^]*\]/.test(s) && /\b(?:and|or|mod|\$url\b)/.test(s) &&
+      this.maybeJS(s.replace(/\b(?:and|or|mod|[[\]])/g, ',').replace(/\$url\b/g, 'location'), true);
+  },
+  get breakStops() {
+    var def = "\\/\\?&#;\\s\\x00}<>"; // we stop on URL, JS and HTML delimiters
+    var bs = {
+      nq: new RegExp("[" + def + "]")
+    };
+    Array.forEach("'\"`", // special treatment for quotes
+      function(c) { bs[c] = new RegExp("[" + def + c + "]"); }
+    );
+    delete this.breakStops;
+    return (this.breakStops = bs);
+  },
+
+  collapseChars: (s) => s.replace(/\;+/g, ';').replace(/\/{4,}/g, '////')
+        .replace(/\s+/g, (s) => /\n/g.test(s) ? '\n' : ' '),
+
+  _reduceBackslashes: (bs) => bs.length % 2 ? "\\" : "",
+
+  reduceQuotes: function(s) {
+    if (s[0] == '/') {
+      // reduce common leading path fragment resembling a regular expression or a comment
+      s = s.replace(/^\/[^\/\n\r]+\//, '_RX_').replace(/^\/\/[^\r\n]*/, '//_COMMENT_');
+    }
+
+    if (/\/\*/.test(s) || // C-style comments, would make everything really tricky
+      /\w\s*(\/\/[\s\S]*)?\[[\s\S]*\w[\s\S]*\]/.test(s)) { // property accessors, risky
+      return s;
+    }
+
+    if (/['"\/]/.test(s)) {
+
+      // drop noisy backslashes
+      s = s.replace(/\\{2,}/g, this._reduceBackslashes);
+
+      // drop escaped quotes
+      s = s.replace(/\\["'\/]/g, " EQ ");
+      var expr;
+      for(;;) {
+         expr = s.replace(/(^[^'"\/]*[;,\+\-=\(\[]\s*)\/[^\/]+\//g, "$1 _RX_ ")
+                .replace(/(^[^'"\/]*)(["']).*?\2/g, "$1 _QS_ ");
+         if(expr == s) break;
+         s = expr;
+      }
+    }
+
+    // remove c++ style comments
+    return s.replace(/^([^'"`\\]*?)\/\/[^\r\n]*/g, "$1//_COMMENT_");
+  },
+
+  reduceURLs: function(s) {
+    // nested URLs with protocol are parsed as C++ style comments, and since
+    // they're potentially very expensive, we preemptively remove them if possible
+    while (/^[^'"]*?:\/\//.test(s)) {
+      s = s.replace(/:\/\/[^*\s]*/, ':');
+    }
+    s = s.replace(/:\/\/[^'"*\n]*/g, ':');
+
+    return (/\bhttps?:$/.test(s) && !/\bh\W*t\W*t\W*p\W*s?.*=/.test(s))
+      ? s.replace(/\b(?:[\w.]+=)?https?:$/, '')
+      : s;
+  },
+
+  reduceJSON: function(s) {
+    const toStringRx = /^function\s*toString\(\)\s*{\s*\[native code\]\s*\}$/;
+    // optimistic case first, one big JSON block
+    for (;;) {
+
+      let m = s.match(/{[^]+}|\[[^]*{[^]+}[^]*\]/);
+      if (!m) return s;
+
+      let whole = s;
+      let expr = m[0];
+      try {
+        if (toStringRx.test(JSON.parse(expr).toString)) {
+          this.log("Reducing big JSON " + expr);
+          return this.reduceJSON(s.replace(expr, '{}'));
+        }
+      } catch(e) {}
+
+
+      // heavier duty, scattered JSON blocks
+      while((m = s.match(/{[^{}:]+:[^{}]+}/g))) {
+        let prev = s;
+
+        for (expr  of m) {
+          try {
+            if (!toStringRx.test(JSON.parse(expr).toString))
+              continue;
+
+            this.log("Reducing JSON " + expr);
+            s = s.replace(expr, '{}');
+            continue;
+          } catch(e) {}
+
+          if (/\btoString\b[\s\S]*:/.test(expr)) continue;
+
+          let qred = this.reduceQuotes(expr);
+          if (/\{(?:\s*(?:(?:\w+:)+\w+)+;\s*)+\}/.test(qred)) {
+             this.log("Reducing pseudo-JSON " + expr);
+             s = s.replace(expr, '{}');
+          } else if (!/[(=.]|[^:\s]\s*\[|:\s*(?:location|document|set(?:Timeout|Interval)|eval|open|show\w*Dialog|alert|confirm|prompt)\b|(?:\]|set)\s*:/.test(qred) &&
+             this.checkJSSyntax("JSON = " + qred) // no-assignment JSON fails with "invalid label"
+          ) {
+            this.log("Reducing slow JSON " + expr);
+            s = s.replace(expr, '{}');
+          }
+        }
+
+        if (s === prev) break;
+      }
+
+      if (s === whole) break;
+    }
+
+    return s;
+  },
+
+  reduceXML: function reduceXML(s) {
+    var res;
+
+    for (let pos = s.indexOf("<"); pos !== -1; pos = s.indexOf("<", 1)) {
+
+      let head = s.substring(0, pos);
+      let tail = s.substring(pos);
+
+      let qnum = 0;
+      for (pos = -1; (pos = head.indexOf('"', ++pos)) > -1; ) {
+        if (pos === 0 || head[pos - 1] != '\\') qnum++;
+      }
+      if (qnum % 2)  break; // odd quotes
+
+      let t = tail.replace(/^<(\??\s*\/?[a-zA-Z][\w:-]*)(?:[\s+]+[\w:-]+="[^"]*")*[\s+]*(\/?\??)>/, '<$1$2>');
+
+      (res || (res = [])).push(head);
+      s = t;
+    }
+    if (res) {
+      res.push(s);
+      s = res.join('');
+    }
+
+    return s;
+  }
+,
+
+  _singleAssignmentRx: new RegExp(
+    "(?:\\b" + fuzzify('document') + "\\b[\\s\\S]*\\.|\\s" + fuzzify('setter') + "\\b[\\s\\S]*=)|/.*/[\\s\\S]*(?:\\.(?:" +
+     "\\b" + fuzzify("onerror") + "\\b[\\s\\S]*=|" +
+      + fuzzify('source|toString') + ")|\\[)|" + IC_EVENT_DOS_PATTERN
+  ),
+  _riskyAssignmentRx: new RegExp(
+    "\\b(?:" + fuzzify('location|innerHTML|outerHTML') + ")\\b[\\s\\S]*="
+  ),
+  _nameRx: new RegExp(
+    "=[\\s\\S]*\\b" + fuzzify('name') + "\\b|" +
+    fuzzify("hostname") + "[\\s\\S]*=[\\s\\S]*(?:\\b\\d|[\"'{}~^|<*/+-])"
+  ),
+  _evalAliasingRx: new RegExp(
+    "=[\\s\\S]+\\[" + IC_EVAL_PATTERN + "\\W*\\]" // TODO: check if it can be coalesced into _maybeJSRx
+  ),
+
+  _maybeJSRx: new RegExp(
+    // accessor followed by function call or assignment.
+    '(?:(?:\\[[\\s\\S]*\\]|\\.\\D)[\\s\\S]*(?:\\([\\s\\S]*\\)|`[\\s\\S]+`|=[\\s\\S]*\\S)' +
+    // double function call
+    '|\\([\\s\\S]*\\([\\s\\S]*\\)' +
+    ')|(?:^|\\W)(?:' + IC_EVAL_PATTERN +
+    ')(?:\\W+[\\s\\S]*|)[(`]|(?:[=(]|\\{[\\s\\S]+:)[\\s\\S]*(?:' + // calling eval-like functions directly or...
+    IC_EVAL_PATTERN + // ... assigning them to another function possibly called by the victim later
+    ')[\\s\\S]*[\\n,;:|]|\\b(?:' +
+    fuzzify('setter|location|innerHTML|outerHTML') +  // eval-like assignments
+    ')\\b[\\s\\S]*=|' +
+    '.' + IC_COMMENT_PATTERN + "src" + IC_COMMENT_PATTERN + '=' +
+    IC_EVENT_DOS_PATTERN +
+    "|\\b" + fuzzify("onerror") + "\\b[\\s\\S]*=" +
+    "|=[s\\\\[ux]?\d{2}" + // escape (unicode/ascii/octal)
+    "|\\b(?:toString|valueOf)\\b" + IC_COMMENT_PATTERN + "=[\\s\\S]*(?:" + IC_EVAL_PATTERN + ")" +
+    "|(?:\\)|(?:[^\\w$]|^)[$a-zA-Z_\\u0ff-\\uffff][$\\w\\u0ff-\\uffff]*)" + IC_COMMENT_PATTERN + '=>' + // concise function definition
+    "|(?:[^\\w$]|^)" + IC_EVENT_PATTERN + IC_COMMENT_PATTERN + "="
+  )
+ ,
+
+  _riskyParensRx: new RegExp(
+    "(?:^|\\W)(?:(?:" + IC_EVAL_PATTERN + "|on\\w+)\\s*[(`]|" +
+    fuzzify("with") + "\\b[\\s\\S]*\\(|" +
+    fuzzify("for") + "\\b[\\s\\S]*\\([\\s\\S]*[\\w$\\u0080-\\uffff]+[\\s\\S]*\\b(?:" +
+    fuzzify ("in|of") + ")\\b)"
+  ),
+
+  _dotRx: /\./g,
+  _removeDotsRx: /^openid\.[\w.-]+(?==)|(?:[?&#\/]|^)[\w.-]+(?=[\/\?&#]|$)|[\w\.]*\.(?:\b[A-Z]+|\w*\d|[a-z][$_])[\w.-]*|=[a-z.-]+\.(?:com|net|org|biz|info|xxx|[a-z]{2})(?:[;&/]|$)/g,
+  _removeDots: (p) => p.replace(InjectionChecker._dotRx, '|'),
+  _arrayAccessRx: /\s*\[\d+\]/g,
+  _riskyOperatorsRx: /[+-]{2}\s*(?:\/[*/][\s\S]+)?(?:\w+(?:\/[*/][\s\S]+)?[[.]|location)|(?:\]|\.\s*(?:\/[*/][\s\S]+)?\w+|location)\s*(?:\/[*/][\s\S]+)?([+-]{2}|[+*\/<>~-]+\s*(?:\/[*/][\s\S]+)?=)/, // inc/dec/self-modifying assignments on DOM props
+  _assignmentRx: /^(?:[^()="'\s]+=(?:[^(='"\[+]+|[?a-zA-Z_0-9;,&=/]+|[\d.|]+))$/,
+  _badRightHandRx: /=[\s\S]*(?:_QS_\b|[|.][\s\S]*source\b|<[\s\S]*\/[^>]*>)/,
+  _wikiParensRx: /^(?:[\w.|-]+\/)*\(*[\w\s-]+\([\w\s-]+\)[\w\s-]*\)*$/,
+  _neutralDotsRx: /(?:^|[\/;&#])[\w-]+\.[\w-]+[\?;\&#]/g,
+  _openIdRx: /^scope=(?:\w+\+)\w/, // OpenID authentication scope parameter, see http://forums.informaction.com/viewtopic.php?p=69851#p69851
+  _gmxRx: /\$\(clientName\)-\$\(dataCenter\)\.(\w+\.)+\w+/, // GMX webmail, see http://forums.informaction.com/viewtopic.php?p=69700#p69700
+
+  maybeJS(expr, mavoChecked = false) {
+    if (!mavoChecked && this.maybeMavo(expr)) return true;
+
+    if (/`[\s\S]*`/.test(expr) ||  // ES6 templates, extremely insidious!!!
+        this._evalAliasingRx.test(expr) ||
+        this._riskyOperatorsRx.test(expr) // this must be checked before removing dots...
+        ) return true;
+
+    expr = // dotted URL components can lead to false positives, let's remove them
+      expr.replace(this._removeDotsRx, this._removeDots)
+        .replace(this._arrayAccessRx, '_ARRAY_ACCESS_')
+        .replace(/<([\w:]+)>[^</(="'`]+<\/\1>/g, '<$1/>') // reduce XML text nodes
+        .replace(/<!--/g, '') // remove HTML comments preamble (see next line)
+        .replace(/(^(?:[^/]*[=;.+-])?)\s*[\[(]+/g, '$1') // remove leading parens and braces
+        .replace(this._openIdRx, '_OPENID_SCOPE_=XYZ')
+        .replace(/^[^=]*OPENid\.(\w+)=/gi, "OPENid_\1")
+        .replace(this._gmxRx, '_GMX_-_GMX_')
+        ;
+
+    if (expr.indexOf(")") !== -1) expr += ")"; // account for externally balanced parens
+    if(this._assignmentRx.test(expr) && !this._badRightHandRx.test(expr)) // commonest case, single assignment or simple chained assignments, no break
+       return this._singleAssignmentRx.test(expr) || this._riskyAssignmentRx.test(expr) && this._nameRx.test(expr);
+
+    return this._riskyParensRx.test(expr) ||
+      this._maybeJSRx.test(expr.replace(this._neutralDotsRx, '')) &&
+        !this._wikiParensRx.test(expr);
+
+  },
+
+  checkNonTrivialJSSyntax: function(expr) {
+    return this.maybeJS(this.reduceQuotes(expr)) && this.checkJSSyntax(expr);
+  },
+
+
+  wantsExpression: (s) => /(?:^[+-]|[!%&(,*/:;<=>?\[^|]|[^-]-|[^+]\+)\s*$/.test(s),
+
+  stripLiteralsAndComments: function(s) {
+    "use strict";
+
+    const MODE_NORMAL = 0;
+    const MODE_REGEX = 1;
+    const MODE_SINGLEQUOTE = 2;
+    const MODE_DOUBLEQUOTE = 3;
+    const MODE_BLOCKCOMMENT = 4;
+    const MODE_LINECOMMENT = 6;
+    const MODE_INTERPOLATION = 7;
+
+    let mode = MODE_NORMAL;
+    let escape = false;
+    let res = [];
+    function handleQuotes(c, q, type) {
+       if (escape) {
+          escape = false;
+        } else if (c == '\\') {
+          escape = true;
+        } else if (c === q) {
+          res.push(type);
+          mode = MODE_NORMAL;
+        }
+    }
+    for (let j = 0, l = s.length; j < l; j++) {
+
+        switch(mode) {
+          case MODE_REGEX:
+            handleQuotes(s[j], '/', "_REGEXP_");
+            break;
+          case MODE_SINGLEQUOTE:
+            handleQuotes(s[j], "'", "_QS_");
+            break;
+          case MODE_DOUBLEQUOTE:
+            handleQuotes(s[j], '"', "_DQS_");
+            break;
+          case MODE_INTERPOLATION:
+            handleQuotes(s[j], '`', "``");
+            break;
+          case MODE_BLOCKCOMMENT:
+            if (s[j] === '/' && s[j-1] === '*') {
+               res.push("/**/");
+               mode = MODE_NORMAL;
+            }
+            break;
+          case MODE_LINECOMMENT:
+            if (s[j] === '\n') {
+               res.push("//\n");
+               mode = MODE_NORMAL;
+            }
+            break;
+        default:
+          switch(s[j]) {
+             case '"':
+                mode = MODE_DOUBLEQUOTE;
+                break;
+             case "'":
+                mode = MODE_SINGLEQUOTE;
+                break;
+             case "`":
+                mode = MODE_INTERPOLATION;
+                break;
+             case '/':
+                switch(s[j+1]) {
+                   case '*':
+                      mode = MODE_BLOCKCOMMENT;
+                      j+=2;
+                      break;
+                   case '/':
+                      mode = MODE_LINECOMMENT;
+                      break;
+                   default:
+                      let r = res.join('');
+                      res = [r];
+                      if (this.wantsExpression(r)) mode = MODE_REGEX;
+                      else res.push('/'); // after a self-contained expression: division operator
+                }
+                break;
+             default:
+                res.push(s[j]);
+          }
+
+       }
+    }
+    return res.join('');
+  },
+
+  checkLastFunction: function() {
+    var fn = this.syntax.lastFunction;
+    if (!fn) return false;
+    var m = fn.toSource().match(/\{([\s\S]*)\}/);
+    if (!m) return false;
+    var expr = this.stripLiteralsAndComments(m[1]);
+    return /=[\s\S]*cookie|\b(?:setter|document|location|(?:inn|out)erHTML|\.\W*src)[\s\S]*=|[\w$\u0080-\uffff\)\]]\s*[\[\(]/.test(expr) ||
+            this.maybeJS(expr);
+  },
+
+  _createInvalidRanges: function() {
+    function x(n) { return '\\u' + ("0000" + n.toString(16)).slice(-4); }
+
+    var ret = "";
+    var first = -1;
+    var last = -1;
+    var cur = 0x7e;
+    while(cur++ <= 0xffff) {
+      try {
+        eval("var _" + String.fromCharCode(cur) + "_=1");
+      } catch(e) {
+        if (!/illegal char/.test(e.message)) continue;
+        if (first == -1) {
+          first = last = cur;
+          ret += x(cur);
+          continue;
+        }
+        if (cur - last == 1) {
+          last = cur;
+          continue;
+        }
+
+        if(last != first) ret += "-" + x(last);
+        ret+= x(cur);
+        last = first = cur;
+      }
+    }
+    return ret;
+  },
+
+  get invalidCharsRx() {
+    delete this.invalidCharsRx;
+    return this.invalidCharsRx = new RegExp("^[^\"'`/<>]*[" + this._createInvalidRanges() + "]");
+  },
+
+  checkJSBreak: function InjectionChecker_checkJSBreak(s) {
+    // Direct script injection breaking JS string literals or comments
+
+
+    // cleanup most urlencoded noise and reduce JSON/XML
+    s = ';' + this.reduceXML(this.reduceJSON(this.collapseChars(
+        s.replace(/\%\d+[a-z\(]\w*/gi, '§')
+          .replace(/[\r\n\u2028\u2029]+/g, "\n")
+          .replace(/[\x01-\x09\x0b-\x20]+/g, ' ')
+        )));
+
+    if (s.indexOf("*/") > 0 && /\*\/[\s\S]+\/\*/.test(s)) { // possible scrambled multi-point with comment balancing
+      s += ';' + s.match(/\*\/[\s\S]+/);
+    }
+
+    if (!this.maybeJS(s)) return false;
+
+    const MAX_TIME = 8000, MAX_LOOPS = 1200;
+
+    const logEnabled = this.logEnabled;
+
+    const
+      invalidCharsRx = /[\u007f-\uffff]/.test(s) && this.invalidCharsRx,
+      dangerRx = /\(|(?:^|[+-]{2}|[+*/<>~-]+\\s*=)|`[\s\S]*`|\[[^\]]+\]|(?:setter|location|(?:inn|out)erHTML|cookie|on\w{3,}|\.\D)[^&]*=[\s\S]*?(?:\/\/|[\w$\u0080-\uFFFF.[\]})'"-]+)/,
+      exprMatchRx = /^[\s\S]*?(?:[=\)]|`[\s\S]*`|[+-]{2}|[+*/<>~-]+\\s*=)/,
+      safeCgiRx = /^(?:(?:[\.\?\w\-\/&:§\[\]]+=[\w \-:\+%#,§\.]*(?:[&\|](?=[^&\|])|$)){2,}|\w+:\/\/\w[\w\-\.]*)/,
+        // r2l, chained query string parameters, protocol://domain
+      headRx = /^(?:[^'"\/\[\(]*[\]\)]|[^"'\/]*(?:§|[^&]&[\w\.]+=[^=]))/
+        // irrepairable syntax error, such as closed parens in the beginning
+    ;
+
+    const injectionFinderRx = /(['"`#;>:{}]|[/?=](?![?&=])|&(?![\w-.[\]&!-]*=)|\*\/)(?!\1)/g;
+    injectionFinderRx.lastIndex = 0;
+
+    const t = Date.now();
+    var iterations = 0;
+
+    for (let dangerPos = 0, m; (m = injectionFinderRx.exec(s));) {
+
+      let startPos = injectionFinderRx.lastIndex;
+      let subj = s.substring(startPos);
+      if (startPos > dangerPos) {
+        dangerRx.lastIndex = startPos;
+        if (!dangerRx.exec(s)) {
+          this.log("Can't find any danger in " + s);
+          return false;
+        }
+        dangerPos = dangerRx.lastIndex;
+      }
+
+      let breakSeq = m[1];
+      let quote = breakSeq in this.breakStops ? breakSeq : '';
+
+      if (!this.maybeJS(quote ? quote + subj : subj)) {
+         this.log("Fast escape on " + subj, t, iterations);
+         return false;
+      }
+
+      let script = this.reduceURLs(subj);
+
+      if (script.length < subj.length) {
+        if (!this.maybeJS(script)) {
+          this.log("Skipping to first nested URL in " + subj, t, iterations);
+          injectionFinderRx.lastIndex += subj.indexOf("://") + 1;
+          continue;
+        }
+        subj = script;
+        script = this.reduceURLs(subj.substring(0, dangerPos - startPos));
+      } else {
+        script = subj.substring(0, dangerPos - startPos);
+      }
+
+      let expr = subj.match(exprMatchRx);
+
+      if (expr) {
+        expr = expr[0];
+        if (expr.length < script.length) {
+          expr = script;
+        }
+      } else {
+        expr = script;
+      }
+
+      // quickly skip (mis)leading innocuous CGI patterns
+      if ((m = subj.match(safeCgiRx))) {
+
+        this.log("Skipping CGI pattern in " + subj);
+
+        injectionFinderRx.lastIndex += m[0].length - 1;
+        continue;
+      }
+
+      let bs = this.breakStops[quote || 'nq']
+
+      for (let len = expr.length, moved = false, hunt = !!expr, lastExpr = ''; hunt;) {
+
+        if (Date.now() - t > MAX_TIME) {
+          this.log("Too long execution time! Assuming DOS... " + (Date.now() - t), t, iterations);
+          return true;
+        }
+
+        hunt = expr.length < subj.length;
+
+        if (moved) {
+          moved = false;
+        } else if (hunt) {
+          let pos = subj.substring(len).search(bs);
+          if (pos < 0) {
+            expr = subj;
+            hunt = false;
+          } else {
+            len += pos;
+            if (quote && subj[len] === quote) {
+              len++;
+            } else if (subj[len - 1] === '<') {
+              // invalid JS, and maybe in the middle of XML block
+              len++;
+              continue;
+            }
+            expr = subj.substring(0, len);
+            if (pos === 0) len++;
+          }
+        }
+
+        if(lastExpr === expr) {
+          lastExpr = '';
+          continue;
+        }
+
+        lastExpr = expr;
+
+        if(invalidCharsRx && invalidCharsRx.test(expr)) {
+          this.log("Quick skipping invalid chars");
+          break;
+        }
+
+
+
+        if (quote) {
+          if (this.checkNonTrivialJSSyntax(expr)) {
+            this.log("Non-trivial JS inside quoted string detected", t, iterations);
+            return true;
+          }
+          script = this.syntax.unquote(quote + expr, quote);
+          if(script && this.maybeJS(script) &&
+            (this.checkNonTrivialJSSyntax(script) ||
+              /'./.test(script) && this.checkNonTrivialJSSyntax("''" + script + "'") ||
+              /"./.test(script) && this.checkNonTrivialJSSyntax('""' + script + '"')
+            ) && this.checkLastFunction()
+            ) {
+            this.log("JS quote Break Injection detected", t, iterations);
+            return true;
+          }
+          script = quote + quote + expr + quote;
+        } else {
+          script = expr;
+        }
+
+        if (headRx.test(script.split("//")[0])) {
+          let balanced = script.replace(/^[^"'{}(]*\)/, 'P ');
+          if (balanced !== script && balanced.indexOf('(') > -1) {
+            script = balanced + ")";
+          } else {
+            this.log("SKIP (head syntax) " + script, t, iterations);
+            break; // unrepairable syntax error in the head, move left cursor forward
+          }
+        }
+
+        if (this.maybeJS(this.reduceQuotes(script))) {
+
+          if (this.checkJSSyntax(script) && this.checkLastFunction()) {
+            this.log("JS Break Injection detected", t, iterations);
+            return true;
+          }
+
+          if (this.checkTemplates(script)) {
+            this.log("JS template expression injection detected", t, iterations);
+            return true;
+          }
+
+          if (++iterations > MAX_LOOPS) {
+            this.log("Too many syntax checks! Assuming DOS... " + s, t, iterations);
+            return true;
+          }
+          if(this.syntax.lastError) { // could be null if we're here thanks to checkLastFunction()
+            let errmsg = this.syntax.lastError.message;
+            if (logEnabled) this.log(errmsg + " --- " + this.syntax.sandbox.script + " --- ", t, iterations);
+            if(!quote) {
+              if (errmsg.indexOf("left-hand") !== -1) {
+                let m = subj.match(/^([^\]\(\\'"=\?]+?)[\w$\u0080-\uffff\s]+[=\?]/);
+                if (m) {
+                  injectionFinderRx.lastIndex += m[1].length - 1;
+                }
+                break;
+              } else if (errmsg.indexOf("unterminated string literal") !== -1) {
+                let quotePos = subj.substring(len).search(/["']/);
+                if(quotePos > -1) {
+                  expr = subj.substring(0, len += ++quotePos);
+                  moved = true;
+                } else break;
+              } else if (errmsg.indexOf("syntax error") !== -1) {
+                let dblSlashPos = subj.indexOf("//");
+                if (dblSlashPos > -1) {
+                  let pos = subj.search(/['"\n\\\(]|\/\*/);
+                  if (pos < 0 || pos > dblSlashPos)
+                    break;
+                }
+                if (/^([\w\[\]]*=)?\w*&[\w\[\]]*=/.test(subj)) { // CGI param concatenation
+                  break;
+                }
+              }
+            } else if (errmsg.indexOf("left-hand") !== -1) break;
+
+            if (/invalid .*\bflag\b|missing ; before statement|invalid label|illegal character|identifier starts immediately/.test(errmsg)) {
+              if (errmsg.indexOf("illegal character") === -1 && /#\d*\s*$/.test(script)) { // sharp vars exceptional behavior
+                if (!quote) break;
+                // let's retry without quotes
+                quote = lastExpr = '';
+                hunt = moved = true;
+              } else break;
+            }
+            else if((m = errmsg.match(/\b(?:property id\b|missing ([:\]\)\}]) )/))) {
+              let char = m[1] || '}';
+              let newLen = subj.indexOf(char, len);
+              let nextParamPos = subj.substring(len).search(/[^&]&(?!&)/)
+              if (newLen !== -1 && (nextParamPos === -1 || newLen <= len + nextParamPos)) {
+                this.log("Extending to next " + char);
+                expr = subj.substring(0, len = ++newLen);
+                moved = char !== ':';
+              } else if (char !== ':') {
+                let lastChar = expr[expr.length - 1];
+                if (lastChar === char && (len > subj.length || lastChar != subj[len - 1])) break;
+                expr += char;
+                moved = hunt = true;
+                len++;
+                this.log("Balancing " + char, t, iterations);
+              } else {
+                 break;
+              }
+            }
+            else if (/finally without try/.test(errmsg)) {
+              expr = "try{" + expr;
+              hunt = moved = true;
+            }
+          }
+        }
+      }
+    }
+    this.log(s, t, iterations);
+    return false;
+  },
+
+
+  checkJS: function(s, unescapedUni) {
+    this.log(s);
+
+    if (/\?name\b[\s\S]*:|[^&?]\bname\b/.test(s)) {
+      this.nameAssignment = true;
+    }
+
+    var hasUnicodeEscapes = !unescapedUni && /\\u(?:[0-9a-f]{4}|\{[0-9a-f]+\})/i.test(s);
+    if (hasUnicodeEscapes && /\\u(?:\{0*|00)[0-7][0-9a-f]/i.test(s)) {
+      this.escalate("Unicode-escaped lower ASCII");
+      return true;
+    }
+
+    if (/\\x[0-9a-f]{2}[\s\S]*['"]/i.test(s)) {
+      this.escalate("Obfuscated string literal");
+      return true;
+    }
+
+    if (/`[\s\S]*\$\{[\s\S]+[=(][\s\S]+\}[\s\S]*`/.test(s)) {
+      this.escalate("ES6 string interpolation");
+      return true;
+    }
+
+    this.syntax.lastFunction = null;
+    let ret = this.checkAttributes(s) ||
+      (/[\\\(]|=[^=]/.test(s) || this._riskyOperatorsRx.test(s)) &&  this.checkJSBreak(s) || // MAIN
+      hasUnicodeEscapes && this.checkJS(this.unescapeJS(s), true); // optional unescaped recursion
+    if (ret) {
+      let msg = "JavaScript Injection in " + s;
+      if (this.syntax.lastFunction) {
+        msg += "\n" + this.syntax.lastFunction.toSource();
+      }
+      this.escalate(msg);
+    }
+    return ret;
+  },
+
+  unescapeJS: function(s) {
+    return s.replace(/\\u([0-9a-f]{4})/gi, function(s, c) {
+      return String.fromCharCode(parseInt(c, 16));
+    });
+  },
+   unescapeJSLiteral: function(s) {
+    return s.replace(/\\x([0-9a-f]{2})/gi, function(s, c) {
+      return String.fromCharCode(parseInt(c, 16));
+    });
+  },
+
+  unescapeCSS: function(s) {
+    // see http://www.w3.org/TR/CSS21/syndata.html#characters
+    return s.replace(/\\([\da-f]{0,6})\s?/gi, function($0, $1) {
+      try {
+        return String.fromCharCode(parseInt($1, 16));
+      } catch(e) {
+        return "";
+      }
+    });
+  },
+
+  reduceDashPlus: function(s) {
+    // http://forums.mozillazine.org/viewtopic.php?p=5592865#p5592865
+    return s.replace(/\-+/g, "-")
+        .replace(/\++/g, "+")
+        .replace(/\s+/g, ' ')
+        .replace(/(?: \-)+/g, ' -')
+        .replace(/(?:\+\-)+/g, '+-');
+  },
+
+  _rxCheck: function(checker, s) {
+    var rx = this[checker + "Checker"];
+    var ret = rx.exec(s);
+    if (ret) {
+      this.escalate(checker + " injection:\n" + ret + "\nmatches " + rx.source);
+      return true;
+    }
+    return false;
+  },
+
+  AttributesChecker: new RegExp(
+    "(?:\\W|^)(?:javascript:(?:[\\s\\S]+[=\\\\\\(`\\[\\.<]|[\\s\\S]*(?:\\bname\\b|\\\\[ux]\\d))|" +
+    "data:(?:(?:[a-z]\\w+/\\w[\\w+-]+\\w)?[;,]|[\\s\\S]*;[\\s\\S]*\\b(?:base64|charset=)|[\\s\\S]*,[\\s\\S]*<[\\s\\S]*\\w[\\s\\S]*>))|@" +
+    ("import\\W*(?:\\/\\*[\\s\\S]*)?(?:[\"']|url[\\s\\S]*\\()" +
+      "|-moz-binding[\\s\\S]*:[\\s\\S]*url[\\s\\S]*\\(|\\{\\{[\\s\\S]+\\}\\}")
+      .replace(/[a-rt-z\-]/g, "\\W*$&"),
+    "i"),
+  checkAttributes: function(s) {
+    s = this.reduceDashPlus(s);
+    if (this._rxCheck("Attributes", s)) return true;
+    if (/\\/.test(s) && this._rxCheck("Attributes", this.unescapeCSS(s))) return true;
+    let dataPos = s.search(/data:\S*\s/i);
+    if (dataPos !== -1) {
+      let data = this.urlUnescape(s.substring(dataPos).replace(/\s/g, ''));
+      if (this.checkHTML(data) || this.checkAttributes(data)) return true;
+    }
+    return false;
+  },
+
+  GlobalsChecker: /https?:\/\/[\S\s]+["'\s\0](?:id|class|data-\w+)[\s\0]*=[\s\0]*("')?\w{3,}(?:[\s\0]|\1|$)|(?:id|class|data-\w+)[\s\0]*=[\s\0]*("')?\w{3,}(?:[\s\0]|\1)[\s\S]*["'\s\0]href[\s\0]*=[\s\0]*(?:"')?https?:\/\//i
+  ,
+  HTMLChecker: new RegExp("<[^\\w<>]*(?:[^<>\"'\\s]*:)?[^\\w<>]*(?:" + // take in account quirks and namespaces
+   fuzzify("script|form|style|svg|marquee|(?:link|object|embed|applet|param|i?frame|base|body|meta|ima?ge?|video|audio|bindings|set|isindex|animate|template") +
+    ")[^>\\w])|['\"\\s\\0/](?:formaction|style|background|src|lowsrc|ping|innerhtml|data-bind|(?:data-)?mv-(?:\\w+[\\w-]*)|" + IC_EVENT_PATTERN +
+     ")[\\s\\0]*=|<%[\\s\\S]+[=(][\\s\\S]+%>", "i"),
+
+  checkHTML: function(s) {
+    let links = s.match(/\b(?:href|src|(?:form)?action|\w+-\w+)[\s\0]*=[\s\0]*(?:(["'])[\s\S]*?\1|[^'"<>][^>\s]*)/ig);
+     if (links) {
+       for (let l  of links) {
+         l = l.replace(/[^=]*=[\s\0]*/i, '');
+         l = /^["']/.test(l) ? l.replace(/^(['"])([^]*?)\1[^]*/g, '$2') : l.replace(/[\s>][^]*/, '');
+         if (/^(?:javascript|data):|\[[^]+\]/i.test(l) || /[<'"(]/.test(decodeURIComponent(l))) return true;
+       }
+     }
+     return this._rxCheck("HTML", s) || this._rxCheck("Globals", s);
+  },
+
+  checkNoscript: function(s) {
+    this.log(s);
+    return s.indexOf("\x1b(J") !== -1 && this.checkNoscript(s.replace(/\x1b\(J/g, '')) || // ignored in iso-2022-jp
+     s.indexOf("\x7e\x0a") !== -1 && this.checkNoscript(s.replace(/\x7e\x0a/g, '')) || // ignored in hz-gb-2312
+      this.checkHTML(s) || this.checkSQLI(s) || this.checkHeaders(s);
+  },
+
+  HeadersChecker: /[\r\n]\s*(?:content-(?:type|encoding))\s*:/i,
+  checkHeaders: function(s) { return this._rxCheck("Headers", s); },
+  SQLIChecker: /(?:(?:(?:\b|[^a-z])union[^a-z]|\()[\w\W]*(?:\b|[^a-z])select[^a-z]|(?:updatexml|extractvalue)(?:\b|[^a-z])[\w\W]*\()[\w\W]+(?:(?:0x|x')[0-9a-f]{16}|(?:0b|b')[01]{64}|\(|\|\||\+)/i
+  ,
+  checkSQLI: function(s) { return this._rxCheck("SQLI", s); },
+
+  base64: false,
+  base64tested: [],
+  get base64Decoder() { return Base64; }, // exposed here just for debugging purposes
+
+
+  checkBase64: function(url) {
+    this.base64 = false;
+
+    const MAX_TIME = 8000;
+    const DOS_MSG = "Too long execution time, assuming DOS in Base64 checks";
+
+    this.log(url);
+
+
+    var parts = url.split("#"); // check hash
+    if (parts.length > 1 && this.checkBase64FragEx(unescape(parts[1])))
+      return true;
+
+    parts = parts[0].split(/[&;]/); // check query string
+    if (parts.length > 0 && parts.some(function(p) {
+        var pos = p.indexOf("=");
+        if (pos > -1) p = p.substring(pos + 1);
+        return this.checkBase64FragEx(unescape(p));
+      }, this))
+      return true;
+
+    url = parts[0];
+    parts = Base64.purify(url).split("/");
+    if (parts.length > 255) {
+      this.log("More than 255 base64 slash chunks, assuming DOS");
+      return true;
+    }
+
+
+    var t = Date.now();
+    if (parts.some(function(p) {
+        if (Date.now() - t > MAX_TIME) {
+            this.log(DOS_MSG);
+            return true;
+        }
+        return this.checkBase64Frag(Base64.purify(Base64.alt(p)));
+      }, this))
+      return true;
+
+
+    var uparts = Base64.purify(unescape(url)).split("/");
+
+    t = Date.now();
+    while(parts.length) {
+      if (Date.now() - t > MAX_TIME) {
+          this.log(DOS_MSG);
+          return true;
+      }
+      if (this.checkBase64Frag(parts.join("/")) ||
+          this.checkBase64Frag(uparts.join("/")))
+        return true;
+
+      parts.shift();
+      uparts.shift();
+    }
+
+    return false;
+  },
+
+
+  checkBase64Frag: function(f) {
+    if (this.base64tested.indexOf(f) < 0) {
+      this.base64tested.push(f);
+      try {
+        var s = Base64.decode(f);
+        if(s && s.replace(/[^\w\(\)]/g, '').length > 7 &&
+           (this.checkHTML(s) ||
+              this.checkAttributes(s))
+           // this.checkJS(s) // -- alternate, whose usefulness is doubious but which easily leads to DOS
+           ) {
+          this.log("Detected BASE64 encoded injection: " + f + " --- (" + s + ")");
+          return this.base64 = true;
+        }
+      } catch(e) {}
+    }
+    return false;
+  },
+
+  checkBase64FragEx: function(f) {
+    return this.checkBase64Frag(Base64.purify(f)) || this.checkBase64Frag(Base64.purify(Base64.alt(f)));
+  },
+
+
+  checkURL: function(url) {
+    return this.checkRecursive(url
+      // assume protocol and host are safe, but keep the leading double slash to keep comments in account
+      .replace(/^[a-z]+:\/\/.*?(?=\/|$)/, "//")
+      // Remove outer parenses from ASP.NET cookieless session's AppPathModifier
+      .replace(/\/\((S\(\w{24}\))\)\//, '/$1/')
+    );
+  },
+
+  checkRecursive: function(s, depth, isPost) {
+    if (typeof(depth) != "number")
+      depth = 3;
+
+    this.reset();
+    this.isPost = isPost || false;
+
+    if (ASPIdiocy.affects(s)) {
+      if (this.checkRecursive(ASPIdiocy.process(s), depth, isPost))
+        return true;
+    } else if (ASPIdiocy.hasBadPercents(s) && this.checkRecursive(ASPIdiocy.removeBadPercents(s), depth, isPost))
+      return true;
+
+    if (FlashIdiocy.affects(s)) {
+      let purged = FlashIdiocy.purgeBadEncodings(s);
+      if (purged !== s && this.checkRecursive(purged, depth, isPost))
+        return true;
+      let decoded = FlashIdiocy.platformDecode(purged);
+      if (decoded !== purged && this.checkRecursive(decoded, depth, isPost))
+        return true;
+    }
+
+    if (s.indexOf("coalesced:") !== 0) {
+      let coalesced = ASPIdiocy.coalesceQuery(s);
+      if (coalesced !== s && this.checkRecursive("coalesced:" + coalesced, depth, isPost))
+        return true;
+    }
+
+    if (isPost) {
+      s = this.formUnescape(s);
+      if (this.checkBase64Frag(Base64.purify(s))) return true;
+
+      if (s.indexOf("<") > -1) {
+        // remove XML-embedded Base64 binary data
+        s = s.replace(/<((?:\w+:)?\w+)>[0-9a-zA-Z+\/]+=*<\/\1>/g, '');
+      }
+
+      s = "#" + s;
+    } else {
+      if (this.checkBase64(s.replace(/^\/{1,3}/, ''))) return true;
+    }
+
+    if (isPost) s = "#" + s; // allows the string to be JS-checked as a whole
+    return this._checkRecursive(s, depth);
+  },
+
+  _checkRecursive: function(s, depth) {
+
+    if (this.checkHTML(s) || this.checkJS(s) || this.checkSQLI(s) || this.checkHeaders(s))
+      return true;
+
+    if (s.indexOf("&") !== -1) {
+      let unent = Entities.convertAll(s);
+      if (unent !== s && this._checkRecursive(unent, depth)) return true;
+    }
+
+    if (--depth <= 0)
+      return false;
+
+    if (s.indexOf('+') !== -1 && this._checkRecursive(this.formUnescape(s), depth))
+      return true;
+
+    var unescaped = this.urlUnescape(s);
+    let badUTF8 = this.utf8EscapeError;
+
+    if (this._checkOverDecoding(s, unescaped))
+      return true;
+
+    if (/[\n\r\t]|&#/.test(unescaped)) {
+      let unent = Entities.convertAll(unescaped).replace(/[\n\r\t]/g, '');
+      if (unescaped != unent && this._checkRecursive(unent, depth)) {
+        this.log("Trash-stripped nested URL match!"); // http://mxr.mozilla.org/mozilla-central/source/netwerk/base/src/nsURLParsers.cpp#100
+        return true;
+      }
+    }
+
+    if (/\\x[0-9a-f]/i.test(unescaped)) {
+      let literal = this.unescapeJSLiteral(unescaped);
+      if (unescaped !== literal && this._checkRecursive(literal, depth)) {
+        this.log("Escaped literal match!");
+        return true;
+      }
+    }
+
+    if (unescaped.indexOf("\x1b(J") !== -1 && this._checkRecursive(unescaped.replace(/\x1b\(J/g, ''), depth) || // ignored in iso-2022-jp
+        unescaped.indexOf("\x7e\x0a") !== -1 && this._checkRecursive(unescaped.replace(/\x7e\x0a/g, '')) // ignored in hz-gb-2312
+      )
+      return true;
+
+    if (unescaped !== s) {
+      if (badUTF8) {
+        try {
+          if (this._checkRecursive(this.toUnicode(unescaped, "UTF-8"))) return true;
+        } catch (e) {
+          this.log(e);
+        }
+      }
+      if (this._checkRecursive(unescaped, depth)) return true;
+    }
+
+    s = this.ebayUnescape(unescaped);
+    if (s != unescaped && this._checkRecursive(s, depth))
+      return true;
+
+    return false;
+  },
+
+  _checkOverDecoding: function(s, unescaped) {
+    if (/%[8-9a-f]/i.test(s)) {
+      const rx = /[<'"]/g;
+      var m1 = unescape(this.utf8OverDecode(s, false)).match(rx);
+      if (m1) {
+        unescaped = unescaped || this.urlUnescape(s);
+        var m0 = unescaped.match(rx);
+        if (!m0 || m0.length < m1.length) {
+          this.log("Potential utf8_decode() exploit!");
+          return true;
+        }
+      }
+    }
+    return false;
+  },
+
+  utf8OverDecode: function(url, strict) {
+    return url.replace(strict
+      ? /%(?:f0%80%80|e0%80|c0)%[8-b][0-f]/gi
+      : /%(?:f[a-f0-9](?:%[0-9a-f]0){2}|e0%[4-9a-f]0|c[01])%[a-f0-9]{2}/gi,
+      function(m) {
+        var hex = m.replace(/%/g, '');
+        if (strict) {
+          for (var j = 2; j < hex.length; j += 2) {
+            if ((parseInt(hex.substring(j, j + 2), 16) & 0xc0) != 0x80) return m;
+          }
+        }
+        switch (hex.length) {
+          case 8:
+            hex = hex.substring(2);
+          case 6:
+            c = (parseInt(hex.substring(0, 2), 16) & 0x3f) << 12 |
+                   (parseInt(hex.substring(2, 4), 16) & 0x3f) << 6 |
+                    parseInt(hex.substring(4, 6), 16) & 0x3f;
+            break;
+          default:
+            c = (parseInt(hex.substring(0, 2), 16) & 0x3f) << 6 |
+                    parseInt(hex.substring(2, 4), 16) & 0x3f;
+        }
+        return encodeURIComponent(String.fromCharCode(c & 0x3f));
+      }
+    );
+  },
+
+  toUnicode: function(s, charset) {
+    let sis = Cc["@mozilla.org/io/string-input-stream;1"]
+          .createInstance(Ci.nsIStringInputStream);
+    sis.setData(s, s.length);
+    let is = Cc["@mozilla.org/intl/converter-input-stream;1"]
+          .createInstance(Ci.nsIConverterInputStream);
+    is.init(sis, charset || null, 0, is.DEFAULT_REPLACEMENT_CHARACTER);
+    let str = {};
+    if (is.readString(4096, str) === 0) return str.value;
+    let ret = [str.value];
+    while (is.readString(4096, str) !== 0) {
+      ret.push(str.value);
+    }
+    return ret.join('');
+  },
+
+  utf8EscapeError: true,
+  urlUnescape: function(url, brutal) {
+    var od = this.utf8OverDecode(url, !brutal);
+    this.utf8EscapeError = false;
+    try {
+      return decodeURIComponent(od);
+    } catch(warn) {
+      this.utf8EscapeError = true;
+      if (url != od) url += " (" + od + ")";
+      this.log("Problem decoding " + url + ", maybe not an UTF-8 encoding? " + warn.message);
+      return unescape(brutal ? ASPIdiocy.filter(od) : od);
+    }
+  },
+
+  formUnescape: function(s, brutal) {
+    return this.urlUnescape(s.replace(/\+/g, ' '), brutal);
+  },
+
+  aspUnescape: function(s) {
+    return unescape(ASPIdiocy.filter(s).replace(/\+/g, ' '));
+  },
+
+  ebayUnescape: function(url) {
+    return url.replace(/Q([\da-fA-F]{2})/g, function(s, c) {
+      return String.fromCharCode(parseInt(c, 16));
+    });
+  },
+
+  checkPost: function(channel, skip) {
+    if (!((channel instanceof Ci.nsIUploadChannel)
+          && channel.uploadStream && (channel.uploadStream instanceof Ci.nsISeekableStream)))
+      return false;
+
+    var clen = -1;
+    try {
+      clen = channel.getRequestHeader("Content-length");
+    } catch(e) {}
+    MaxRunTime.increase(clen < 0 || clen > 300000 ? 60 : Math.ceil(20 * clen / 100000));
+
+    this.log("Extracting post data...");
+    return this.checkPostStream(channel.URI.spec, channel.uploadStream, skip);
+  },
+
+  checkPostStream: function(url, stream, skip) {
+     var ic = this;
+     var pc = new PostChecker(url, stream, skip);
+     return pc.check(
+      function(chunk) {
+        return chunk.length > 6 &&
+          ic.checkRecursive(chunk, 2, !pc.isFile) && chunk;
+      }
+    );
+  },
+
+  testCheckPost: function(url, strData) {
+    var stream = Cc["@mozilla.org/io/string-input-stream;1"].
+            createInstance(Ci.nsIStringInputStream);
+    stream.setData(strData, strData.length);
+    return this.checkPostStream(url, stream);
+  },
+
+
+  checkWindowName: function (window, url) {
+     var originalAttempt = window.name;
+     try {
+       if (/^https?:\/\/(?:[^/]*\.)?\byimg\.com\/rq\/darla\//.test(url) &&
+          ns.getPref("filterXExceptions.darla_name")) {
+         window.name = "DARLA_JUNK";
+         return;
+       }
+
+       if (/\s*{[\s\S]+}\s*/.test(originalAttempt)) {
+         try {
+           JSON.parse(originalAttempt); // fast track for crazy JSON in name like on NYT
+           return;
+         } catch(e) {}
+       }
+
+       if (/[%=\(\\<]/.test(originalAttempt) && InjectionChecker.checkURL(originalAttempt)) {
+         window.name = originalAttempt.replace(/[%=\(\\<]/g, " ");
+       }
+
+       if (originalAttempt.length > 11) {
+         try {
+           if ((originalAttempt.length % 4 === 0)) {
+             var bin = window.atob(window.name);
+             if(/[%=\(\\]/.test(bin) && InjectionChecker.checkURL(bin)) {
+               window.name = "BASE_64_XSS";
+             }
+           }
+         } catch(e) {}
+       }
+    } finally {
+      if (originalAttempt != window.name) {
+        ns.log('[NoScript XSS]: sanitized window.name, "' + originalAttempt + '"\nto\n"' + window.name + '"\nURL: ' + url);
+        ns.log(url + "\n" + window.location.href);
+      }
+    }
+  },
+
+};
+
+function PostChecker(url, uploadStream, skip) {
+  this.url = url;
+  this.uploadStream = uploadStream;
+  this.skip = skip || false;
+}
+
+PostChecker.prototype = {
+  boundary: null,
+  isFile: false,
+  postData: '',
+  check: function(callback) {
+    var m, chunks, data, size, available, ret;
+    const BUF_SIZE = 3 * 1024 * 1024; // 3MB
+    const MAX_FIELD_SIZE = BUF_SIZE;
+    try {
+      var us = this.uploadStream;
+      us.seek(0, 0);
+      const sis = Cc['@mozilla.org/binaryinputstream;1'].createInstance(Ci.nsIBinaryInputStream);
+      sis.setInputStream(us);
+
+      // reset status
+      delete this.boundary;
+      delete this.isFile;
+      delete this.postData;
+
+      if ((available = sis.available())) do {
+        size = this.postData.length;
+        if (size >= MAX_FIELD_SIZE) return size + " bytes or more in one non-file field, assuming memory DOS attempt!";
+
+        data = sis.readBytes(Math.min(available, BUF_SIZE));
+
+        if (size !== 0) {
+          this.postData += data;
+        } else {
+           if (data.length === 0) return false;
+           this.postData = data;
+        }
+        available = sis.available();
+        chunks = this.parse(!available);
+
+        for (var j = 0, len = chunks.length; j < len; j++) {
+          ret = callback(chunks[j]);
+          if (ret) return ret;
+        }
+      } while(available)
+    } catch(ex) {
+      dump(ex + "\n" + ex.stack + "\n");
+      return ex;
+    } finally {
+        try {
+          us.seek(0, 0); // rewind
+        } catch(e) {}
+    }
+    return false;
+  },
+
+  parse: function(eof) {
+    var postData = this.postData;
+    var m;
+
+    if (typeof(this.boundary) != "string") {
+      m = postData.match(/^Content-type: multipart\/form-data;\s*boundary=(\S*)/i);
+      this.boundary = m && m[1] || '';
+      if (this.boundary) this.boundary = "--" + this.boundary;
+      postData = postData.substring(postData.indexOf("\r\n\r\n") + 2);
+    }
+
+    this.postData = '';
+
+    var boundary = this.boundary;
+
+    var chunks = [];
+    var j, len, name;
+
+    var skip = this.skip;
+
+    if (boundary) { // multipart/form-data, see http://www.faqs.org/ftp/rfc/rfc2388.txt
+      if(postData.indexOf(boundary) < 0) {
+        // skip big file chunks
+        return chunks;
+      }
+      var parts = postData.split(boundary);
+
+      var part, last;
+      for(j = 0, len = parts.length; j < len;) {
+        part = parts[j];
+        last = ++j == len;
+        if (j == 1 && part.length && this.isFile) {
+          // skip file internal terminal chunk
+          this.isFile = false;
+          continue;
+        }
+        m = part.match(/^\s*Content-Disposition: form-data; name="(.*?)"(?:;\s*filename="(.*)"|[^;])\r?\n(Content-Type: \w)?.*\r?\n/i);
+
+        if (m) {
+          // name and filename are backslash-quoted according to RFC822
+          name = m[1];
+          if (name) {
+            chunks.push(name.replace(/\\\\/g, "\\")); // name and file name
+          }
+          if (m[2]) {
+            chunks.push(m[2].replace(/\\\\/g, "\\")); // filename
+            if (m[3]) {
+              // Content-type: skip, it's a file
+              this.isFile = true;
+
+              if (last && !eof)
+                this.postData = part.substring(part.length - boundary.length);
+
+              continue;
+            }
+          }
+          if (eof || !last) {
+            if (!(skip && skip.indexOf(name) !== -1))
+              chunks.push(part.substring(m[0].length)); // parameter body
+          } else {
+            this.postData = part;
+          }
+          this.isFile = false;
+        } else {
+          // malformed part, check it all or push it back
+          if (eof || !last) {
+            chunks.push(part)
+          } else {
+            this.postData = this.isFile ? part.substring(part.length - boundary.length) : part;
+          }
+        }
+      }
+    } else {
+      this.isFile = false;
+
+      parts = postData.replace(/^\s+/, '').split("&");
+      if (!eof) this.postData = parts.pop();
+
+      for (j = 0, len = parts.length; j < len; j++) {
+        m = parts[j].split("=");
+        name = m[0];
+        if (skip && skip.indexOf(name) > -1) continue;
+        chunks.push(name, m[1] || '');
+      }
+    }
+    return chunks;
+  }
+}
+
+
+function XSanitizer(primaryBlacklist, extraBlacklist) {
+  this.primaryBlacklist = primaryBlacklist;
+  this.extraBlacklist = extraBlacklist;
+  this.injectionChecker = InjectionChecker;
+}
+
+XSanitizer.prototype = {
+  brutal: false,
+  base64: false,
+  sanitizeURL: function(url) {
+    var original = url.clone();
+    this.brutal = this.brutal || this.injectionChecker.checkURL(url.spec);
+    this.base64 = this.injectionChecker.base64;
+
+    const changes = { minor: false, major: false, qs: false };
+    // sanitize credentials
+    if (url.username) url.username = this.sanitizeEnc(url.username);
+    if (url.password) url.password = this.sanitizeEnc(url.password);
+    url.host = this.sanitizeEnc(url.host);
+
+    if (url instanceof Ci.nsIURL) {
+      // sanitize path
+
+      if (url.param) {
+        url.path = this.sanitizeURIComponent(url.path); // param is the URL part after filePath and a semicolon ?!
+      } else if(url.filePath) {
+        url.filePath = this.sanitizeURIComponent(url.filePath); // true == lenient == allow ()=
+      }
+      // sanitize query
+      if (url.query) {
+        url.query = this.sanitizeQuery(url.query, changes);
+        if (this.brutal) {
+          url.query = this.sanitizeWholeQuery(url.query, changes);
+        }
+      }
+      // sanitize fragment
+      var fragPos = url.path.indexOf("#");
+      if (url.ref || fragPos > -1) {
+        if (fragPos >= url.filePath.length + url.query.length) {
+          url.path = url.path.substring(0, fragPos) + "#" + this.sanitizeEnc(url.path.substring(fragPos + 1));
+        } else {
+          url.ref = this.sanitizeEnc(url.ref);
+        }
+      }
+    } else {
+      // fallback for non-URL URIs, we should never get here anyway
+      if (url.path) url.path = this.sanitizeURIComponent(url.path);
+    }
+
+    var urlSpec = url.spec;
+    var neutralized = Entities.neutralizeAll(urlSpec, /[^\\'"\x00-\x07\x09\x0B\x0C\x0E-\x1F\x7F<>]/);
+    if (urlSpec != neutralized) url.spec = neutralized;
+
+    if (this.base64 ||
+        FlashIdiocy.affects(urlSpec) ||
+        FlashIdiocy.affects(unescape(urlSpec))
+      ) {
+      url.spec = url.prePath; // drastic, but with base64 / FlashIdiocy we cannot take the risk!
+    }
+
+    if (url.getRelativeSpec(original) && unescape(url.spec) != unescape(original.spec)) { // ok, this seems overkill but take my word, the double check is needed
+      changes.minor = true;
+      changes.major = changes.major || changes.qs ||
+                      unescape(original.spec.replace(/\?.*/g, ""))
+                        != unescape(url.spec.replace(/\?.*/g, ""));
+      url.spec = url.spec.replace(/'/g, "%27")
+      if (changes.major) {
+        url.ref = Math.random().toString().concat(Math.round(Math.random() * 999 + 1)).replace(/0./, '') // randomize URI
+      }
+    } else {
+      changes.minor = false;
+      url.spec = original.spec.replace(/'/g, "%27");
+    }
+    return changes;
+  },
+
+  sanitizeWholeQuery: function(query, changes) {
+    var original = query;
+    query = Entities.convertAll(query);
+    if (query === original) return query;
+    var unescaped = InjectionChecker.urlUnescape(original, true);
+    query = this.sanitize(unescaped);
+    if (query === unescaped) return original;
+    if(changes) changes.qs = true;
+    return escape(query);
+  },
+
+  _queryRecursionLevel: 0,
+  sanitizeQuery: function(query, changes, sep) {
+    const MAX_RECUR = 2;
+
+    var canRecur = this._queryRecursionLevel++ < MAX_RECUR;
+    // replace every character matching noscript.filterXGetRx with a single ASCII space (0x20)
+    changes = changes || {};
+    if (!sep) {
+      sep = query.indexOf("&") > -1 || this.brutal ? "&" : ";"
+    }
+    const parms = query.split(sep);
+
+    for (let j = parms.length; j-- > 0;) {
+      let pieces = parms[j].split("=");
+
+      try {
+        for (let k = pieces.length; k-- > 0;) {
+
+          let encodedPz =  InjectionChecker.utf8OverDecode(pieces[k]);
+
+          let pz = null, encodeURL = null;
+          if (encodedPz.indexOf("+") < 0) {
+            try {
+              pz = decodeURIComponent(encodedPz);
+              encodeURL = encodeURIComponent;
+            } catch(e) {}
+          }
+          if (pz == null) {
+            pz = unescape(ASPIdiocy.filter(encodedPz));
+            encodeURL = escape;
+          }
+
+          let origPz = pz;
+
+          // recursion for nested (partial?) URIs
+
+          let nestedURI = null;
+
+          if (canRecur && /^https?:\/\//i.test(pz)) {
+            // try to sanitize as a nested URL
+            try {
+              nestedURI = IOUtil.newURI(pz).QueryInterface(Ci.nsIURL);
+              changes.qs = changes.qs || this.sanitizeURL(nestedURI).major;
+              if (unescape(pz).replace(/\/+$/, '') != unescape(nestedURI.spec).replace(/\/+$/, '')) pz = nestedURI.spec;
+            } catch(e) {
+              nestedURI = null;
+            }
+          }
+
+          if (!nestedURI) {
+            let qpos;
+            if (canRecur &&
+                 (qpos = pz.indexOf("?")) > - 1 &&
+                 (spos = pz.search(/[&;]/) > qpos)) {
+              // recursive query string?
+              // split, sanitize and rejoin
+              pz = [ this.sanitize(pz.substring(0, qpos)),
+                    this.sanitizeQuery(pz.substring(qpos + 1), changes)
+                   ].join("?")
+
+            } else {
+              pz = this.sanitize(pz);
+            }
+            if (origPz != pz) changes.qs = true;
+          }
+
+          if (origPz != pz) pieces[k] = encodeURL(pz);
+
+        }
+        parms[j] = pieces.join("=");
+      } catch(e) {
+        // decoding exception, skip this param
+        parms.splice(j, 1);
+      }
+    }
+    this._queryRecursionLevel--;
+    return parms.join(sep);
+  },
+
+  sanitizeURIComponent: function(s) {
+    try {
+      var unescaped = InjectionChecker.urlUnescape(s, this.brutal);
+      var sanitized = this.sanitize(unescaped);
+      return sanitized == unescaped ? s : encodeURI(sanitized);
+    } catch(e) {
+      return "";
+    }
+  },
+  sanitizeEnc: function(s) {
+    try {
+      return encodeURIComponent(this.sanitize(decodeURIComponent(s)));
+    } catch(e) {
+      return "";
+    }
+  },
+  sanitize: function(unsanitized) {
+    var s, orig;
+    orig = s = Entities.convertDeep(unsanitized);
+
+    if (s.indexOf('"') > -1 && !this.brutal) {
+      // try to play nice on search engine queries with grouped quoted elements
+      // by allowing double quotes but stripping even more aggressively other chars
+
+      // Google preserves "$" and recognizes ~, + and ".." as operators
+      // All the other non alphanumeric chars (aside double quotes) are ignored.
+      // We will preserve the site: modifier as well
+      // Ref.: http://www.google.com/help/refinesearch.html
+      s = s.replace(/[^\w\$\+\.\~"&;\- :\u0080-\uffff]/g,
+          " " // strip everything but alphnum and operators
+          ).replace(":",
+          function(k, pos, s) { // strip colons as well, unless it's the site: operator
+            return (s.substring(0, pos) == "site" || s.substring(pos - 5) == " site") ? ":" : " "
+          }
+        );
+      if (s.replace(/[^"]/g, "").length % 2) s += '"'; // close unpaired quotes
+      return s;
+    }
+
+    if (this.brutal) {
+      s = s.replace(/\x1bJ\(/g, '').replace(/\x7e\x0a/g, ''); // ignored in some encodings
+    }
+    // regular duty
+    s = s.replace(this.primaryBlacklist, " ")
+      .replace(/\bjavascript:+|\bdata:[^,]+,(?=[^<]*<|%25%20|%\s+[2-3][0-9a-f])|-moz-binding|@import/ig,
+                function(m) { return m.replace(/(.*?)(\w)/, "$1#no$2"); });
+
+    if (this.extraBlacklist) { // additional user-defined blacklist for emergencies
+      s = s.replace(this.extraBlacklist, " ");
+    }
+
+    if (this.brutal) { // injection checks were positive
+      s = InjectionChecker.reduceDashPlus(s)
+        .replace(/\bdata:/ig, "nodata:")
+        .replace(/['\(\)\=\[\]<\r\n`]/g, " ")
+        .replace(/0x[0-9a-f]{16,}|0b[01]{64,}/gi, " ")
+        .replace(this._dangerousWordsRx, this._dangerousWordsReplace)
+        .replace(/Q[\da-fA-Fa]{2}/g, "Q20") // Ebay-style escaping
+        .replace(/%[\n\r\t]*[0-9a-f][\n\r\t]*[0-9a-f]/gi, " ")
+        // .replace(/percnt/, 'percent')
+        ;
+    }
+
+    return s == orig ? unsanitized : s;
+  },
+
+  _regularReplRx: new RegExp(
+    fuzzify('(?:javascript|data)') + '\\W*:+|' +
+      fuzzify('-moz-binding|@import'),
+    "ig"
+  ),
+  _dangerousWordsRx: new RegExp(
+    '\\b(?:' + fuzzify('setter|location|innerHTML|outerHTML|cookie|name|document|toString|') +
+    IC_EVAL_PATTERN + '|' + IC_EVENT_PATTERN + ')\\b',
+    "g"
+  ),
+  _dangerousWordsReplace: (s) => s.replace(/\S/g, "$&\u2063")
+
+};
+
+// we need this because of https://bugzilla.mozilla.org/show_bug.cgi?id=439276
+
+var Base64 = {
+
+  purify: function(input) {
+    return input.replace(/[^A-Za-z0-9\+\/=]+/g, '');
+  },
+
+  alt: function(s) {
+    // URL base64 variant, see http://en.wikipedia.org/wiki/Base64#URL_applications
+    return s.replace(/-/g, '+').replace(/_/g, '/')
+  },
+
+  decode: function (input, strict) {
+    var output = '';
+    var chr1, chr2, chr3;
+    var enc1, enc2, enc3, enc4;
+    var i = 0;
+
+    // if (/[^A-Za-z0-9\+\/\=]/.test(input)) return ""; // we don't need this, caller checks for us
+
+    const k = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+    while (i < input.length) {
+
+        enc1 = k.indexOf(input.charAt(i++));
+        enc2 = k.indexOf(input.charAt(i++));
+        enc3 = k.indexOf(input.charAt(i++));
+        enc4 = k.indexOf(input.charAt(i++));
+
+        chr1 = (enc1 << 2) | (enc2 >> 4);
+        chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
+        chr3 = ((enc3 & 3) << 6) | enc4;
+
+        output += String.fromCharCode(chr1);
+
+        if (enc3 != 64) {
+          output += String.fromCharCode(chr2);
+        }
+        if (enc4 != 64) {
+          output += String.fromCharCode(chr3);
+        }
+
+    }
+    return output;
+
+  }
+};
+
+
+
+
+var ASPIdiocy = {
+  _replaceRx: /%u([0-9a-fA-F]{4})/g,
+  _affectsRx: /%u[0-9a-fA-F]{4}/,
+  _badPercentRx: /%(?!u[0-9a-fA-F]{4}|[0-9a-fA-F]{2})|%(?:00|u0000)[^&=]*/g,
+
+  hasBadPercents: function(s) { return this._badPercentRx.test(s) },
+  removeBadPercents: function(s) { return s.replace(this._badPercentRx, ''); },
+  affects: function(s) { return this._affectsRx.test(s); },
+  process: function(s) {
+    s = this.filter(s);
+    return /[\uff5f-\uffff]/.test(s) ? s + '&' + s.replace(/[\uff5f-\uffff]/g, '?') : s;
+  },
+  filter: function(s) { return this.removeBadPercents(s).replace(this._replaceRx, this._replace) },
+
+  coalesceQuery: function(s) { // HPP protection, see https://www.owasp.org/images/b/ba/AppsecEU09_CarettoniDiPaola_v0.8.pdf
+    let qm = s.indexOf("?");
+    if (qm < 0) return s;
+    let p = s.substring(0, qm);
+    let q = s.substring(qm + 1);
+    if (!q) return s;
+
+    let unchanged = true;
+    let emptyParams = false;
+
+    let pairs = (function rearrange(joinNames) {
+      let pairs = q.split("&");
+      let accumulator = { __proto__: null };
+      for (let j = 0, len = pairs.length; j < len; j++) {
+        let nv = pairs[j];
+        let eq = nv.indexOf("=");
+        if (eq === -1) {
+          emptyParams = true;
+          if (joinNames && j < len - 1) {
+            pairs[j + 1] = nv + "&" + pairs[j + 1];
+            delete pairs[j];
+          }
+          continue;
+        }
+        let key = "#" + unescape(nv.substring(0, eq)).toLowerCase();
+        if (key in accumulator) {
+          delete pairs[j];
+          pairs[accumulator[key]] += ", " + nv.substring(eq + 1);
+          unchanged = false;
+        } else {
+          accumulator[key] = j;
+        }
+      }
+      return (emptyParams && !(unchanged || joinNames))
+        ? pairs.concat(rearrange(true).filter(p => pairs.indexOf(p) === -1))
+        : pairs;
+    })();
+
+    if (unchanged) return s;
+    for (let j = pairs.length; j-- > 0;) if (!pairs[j]) pairs.splice(j, 1);
+    return p + pairs.join("&");
+  },
+
+  _replace: function(match, hex) {
+     // lazy init
+     INCLUDE("ASPIdiocy");
+     return ASPIdiocy._replace(match, hex);
+  }
+}
+
+var FlashIdiocy = {
+  _affectsRx: /%(?:[8-9a-f]|[0-7]?[^0-9a-f])/i, // high (non-ASCII) percent encoding or invalid second digit
+  affects: function(s) { return this._affectsRx.test(s); },
+
+  purgeBadEncodings: function(s) {
+    INCLUDE("FlashIdiocy");
+    return this.purgeBadEncodings(s);
+  }
+}
+
diff --git a/chrome/noscript.jar!/content/noscript/MSEInterception.js b/chrome/noscript.jar!/content/noscript/MSEInterception.js
index 50e4439..0b89729 100644
--- a/chrome/noscript.jar!/content/noscript/MSEInterception.js
+++ b/chrome/noscript.jar!/content/noscript/MSEInterception.js
@@ -31,7 +31,7 @@ var MSEInterception = {
         doc.defaultView.addEventListener("load", () => delete sites[site], false);
       }
     }
-    ns.recordBlocked(doc.defaultView, url, site);
+    ns.recordBlocked(url, site);
   },
 
   get interceptionDef() {
diff --git a/chrome/noscript.jar!/content/noscript/Main.js b/chrome/noscript.jar!/content/noscript/Main.js
index 5eefd87..634ec8c 100644
--- a/chrome/noscript.jar!/content/noscript/Main.js
+++ b/chrome/noscript.jar!/content/noscript/Main.js
@@ -108,7 +108,7 @@ this.__defineGetter__("ABE", function() {
 });
 
 const ns = {
-  VERSION: "2.9.5.2",
+  VERSION: "5.0.8.1",
   classDescription: CLASS_NAME,
 	classID: Components.ID(SERVICE_ID),
 	contractID: SERVICE_CTRID,
@@ -244,7 +244,6 @@ const ns = {
   forbidFrames: false,
 
   alwaysBlockUntrustedContent: true,
-  docShellJSBlocking: 1, // 0 - don't touch docShells, 1 - block untrusted, 2 - block not whitelisted
 
   forbidXBL: 4,
   forbidXHR: 1,
@@ -365,7 +364,6 @@ const ns = {
           this.forbidIFrames || this.forbidFrames;
       break;
 
-      case "docShellJSBlocking":
       case "emulateFrameBreak":
       case "filterXPost":
       case "filterXGet":
@@ -697,7 +695,7 @@ const ns = {
     Thread.hostRunning = true;
 
     this._inited = true;
-    
+
     this.beforeInit();
 
     this._initResources();
@@ -729,7 +727,6 @@ const ns = {
       "autoAllow",
       "allowedMimeRegExp", "hideOnUnloadRegExp", "requireReloadRegExp",
       "consoleDump", "consoleLog", "contentBlocker", "alwaysShowObjectSources",
-      "docShellJSBlocking",
       "filterXPost", "filterXGet",
       "filterXGetRx", "filterXGetUserRx",
       "filterXExceptions",
@@ -801,7 +798,7 @@ const ns = {
       this._inited = false;
 
       for (let t of this.disposalTasks) t();
-      
+
       this.shouldLoad = this.shouldProcess = CP_NOP;
 
       OS.removeObserver(this, "em-action-requested");
@@ -943,8 +940,6 @@ const ns = {
     this.httpStarted = true;
     this.initContentPolicy(true);
 
-    this.categoryManager.addCategoryEntry("net-channel-event-sinks", this.contractID, this.contractID, false, true);
-
     delete this.requestWatchdog;
     return (this.requestWatchdog = new RequestWatchdog());
   },
@@ -975,7 +970,7 @@ const ns = {
   isMandatory: function(s) {
     return s && this.mandatorySites.matches(s);
   },
-  
+
   tempSites: new PolicySites(),
   gTempSites: new PolicySites(),
   isTemp: function(s) {
@@ -1086,7 +1081,7 @@ const ns = {
   isGlobalHttps: function(win, /*optional */ s) {
     let allow = false;
     if (s && !this._isHttpsAndNotUntrusted(s)) return false;
-
+    if (!win) return !!s;
     for (;; win = win.parent) {
       let site = this.getSite(this.getPrincipalOrigin(this.getPrincipal(win.document)));
       if (!(allow = s && site === s || this._isHttpsAndNotUntrusted(site)) || win === win.parent)
@@ -1137,7 +1132,7 @@ const ns = {
     if (window) {
       let top = window.top;
       enabled = enabled ||
-               this.globalHttpsWhitelist && s.indexOf("https:") === 0 && (window === top || this.isGlobalHttps(window));
+               this.globalHttpsWhitelist && s.startsWith("https:") && (window === top || this.isGlobalHttps(window));
       if (enabled ? this.restrictSubdocScripting : this.cascadePermissions) {
         let topOrigin = this.getPrincipalOrigin(this.getPrincipal(top.document));
         if (this.isBrowserOrigin(topOrigin)) {
@@ -1187,17 +1182,22 @@ const ns = {
       null;
   },
   getPrincipalOrigin(p) {
-    let origin = p.originNoSuffix || p.origin;
-    if (this._buggyIPV6rx.test(origin)) {
-      try {
-        let uri = p.URI;
-        let hostPort = uri.hostPort;
-        if (hostPort && hostPort[0] === '[') origin = uri.scheme + "://" + hostPort;
-      } catch (e) {
-        ns.log(e);
+    try {
+      let origin = p.originNoSuffix || p.origin;
+      if (this._buggyIPV6rx.test(origin)) {
+        try {
+          let uri = p.URI;
+          let hostPort = uri.hostPort;
+          if (hostPort && hostPort[0] === '[') origin = uri.scheme + "://" + hostPort;
+        } catch (e) {
+          ns.log(e);
+        }
       }
+      return origin;
+    } catch (e) {
+      if (ns.consoleDump) ns.dump(`${e} grabbing origin for ${p.URI.spec}, falling back to full URI`);
     }
-    return origin;
+    return p.URI.spec;
   },
 
   _removeAutoPorts: function(site) {
@@ -1292,6 +1292,7 @@ const ns = {
   },
 
   savePrefs: function() {
+    if (this.webExt && this.webExt.started) this.webExt.saveData();
     var res = this.prefService.savePrefFile(null);
     return res;
   },
@@ -1313,7 +1314,7 @@ const ns = {
     try {
       this.caps.clearUserPref(prefName);
     } catch(e) {}
-    
+
     this.setPref("global", enabled);
     if (enabled) {
       try {
@@ -1437,7 +1438,7 @@ const ns = {
 
     this.resetJSCaps();
     if (!(this.allowLocalLinks || this.allowClipboard)) return;
-    
+
     this._editingPolicies = true;
     try {
       const POLICY_NAME = this.POLICY_NAME;
@@ -1617,6 +1618,8 @@ const ns = {
       if (this.consoleDump) this.dump("Adding content policy.");
       catMan.addCategoryEntry(cat, this.contractID, this.contractID, false, true);
     } else this.dump("No category?!" + (cpMixin === NOPContentPolicy) + ", " + last + ", " + this.mimeService);
+    
+    catMan.addCategoryEntry("net-channel-event-sinks", this.contractID, this.contractID, false, true);
 
 
     if (!this.mimeService) {
@@ -1626,7 +1629,28 @@ const ns = {
     }
   },
 
-
+  REQDATA_HEADER: "X-NoScript-ReqData",
+  REQDATA_SERIALIZABLE: ["checkWindowName", "protectName"],
+  serializeReqData(req) {
+    let reqData = this.reqData(req);
+    if (!reqData.policyHints) try {
+      req.setResponseHeader(this.REQDATA_HEADER,
+        JSON.stringify(reqData, this.REQDATA_SERIALIZABLE),
+        false);
+    } catch (e) {
+      this.log(`Cannot serialize reqData: ${uneval(reqData)}`);
+    }
+  },
+  unserializeReqData: IPC.parent ? function() {} : function(req) {
+    if (req instanceof Ci.nsIHttpChannel) {
+      try {
+        Object.assign(ns.reqData(req), JSON.parse(req.getResponseHeader(this.REQDATA_HEADER)));
+      } catch (e) {
+        //Cu.reportError(e);
+        return;
+      }
+    }
+  },
   reqData(req, remove = false) {
     return IOUtil.reqData(req, "net.noscript.channelData", remove);
   },
@@ -1731,7 +1755,7 @@ const ns = {
 
   syncUI: function(aContext) {
     let doc = aContext && (aContext instanceof Ci.nsIDOMDocument ? aContext : aContext.ownerDocument || aContext.document);
-    if (doc) {
+    if (doc && doc.defaultView) {
       let ev = doc.createEvent("Events");
       ev.initEvent("NoScript:syncUI", true, false);
       aContext.dispatchEvent(ev);
@@ -2910,7 +2934,8 @@ const ns = {
       pluginExtras: [],
       pluginSites: [],
       docSites: [],
-      all: []
+      recentlyBlocked: [],
+      all: [],
     };
     if (browser) {
       if (browser.content) {
@@ -3055,100 +3080,113 @@ const ns = {
 
     const nsIDocShell = Ci.nsIDocShell;
 
-    let top;
     let all = sites.all;
-    sites.docJSBlocked = !browser.docShell.allowJavascript;
-    this.traverseDocShells(function(docShell) {
+    let docShell = browser.docShell;
+    var document, topWin;
+    sites.docJSBlocked = !docShell.allowJavascript;
+    try {
+      sites.cspBlocked = /\b(?:sandbox|script-src\s+'none')\s*(?:[,;]|$)/
+        .test(docShell.currentDocumentChannel.QueryInterface(Ci.nsIHttpChannel)
+              .getResponseHeader("Content-Security-Policy"));
+    } catch (e) {
+      sites.cspBlocked = false;
+    }
 
-      let document = docShell.document;
-      if (!document) return;
+    try {
+      this.traverseDocShells(function(docShell) {
 
-      // Truncate title as needed
-      if (this.truncateTitle && document.title.length > this.truncateTitleLen) {
-        document.title = document.title.substring(0, this.truncateTitleLen);
-      }
+        let document = docShell.document;
+        if (!document) return;
 
-      // Collect document / cached plugin URLs
-      let win = document.defaultView;
-      let docURI = document.documentURI;
-      let url = this.getSite(docURI);
+        // Truncate title as needed
+        if (this.truncateTitle && document.title.length > this.truncateTitleLen) {
+          document.title = document.title.substring(0, this.truncateTitleLen);
+        }
 
-      if (url) {
-        try {
-          let domain = document.domain
-          if (domain && domain != this.getDomain(url, true) && url != "chrome:" && url != "about:blank") {
-           // temporary allow changed document.domain on allow page
-            if (this.getExpando(browser, "allowPageURL") == browser.docShell.currentURI.spec &&
-                this.getBaseDomain(domain).length >= domain.length &&
-                !(this.isJSEnabled(domain) || this.isUntrusted(domain))) {
-             this.setTemp(domain, true);
-             this.setJSEnabled(domain, true);
-             this.quickReload(win);
-           }
-           all.unshift(domain);
-          }
-        } catch(e) {}
+        // Collect document / cached plugin URLs
+        let win = document.defaultView;
+        let docURI = document.documentURI;
+        let url = this.getSite(docURI);
 
-        sites.docSites.push(url);
-        all.push(url);
+        if (url) {
+          try {
+            let domain = document.domain;
+            if (domain && domain != this.getDomain(url, true) && url != "chrome:" && url != "about:blank") {
+             // temporary allow changed document.domain on allow page
+              if (this.getExpando(browser, "allowPageURL") == browser.docShell.currentURI.spec &&
+                  this.getBaseDomain(domain).length >= domain.length &&
+                  !(this.isJSEnabled(domain) || this.isUntrusted(domain))) {
+               this.setTemp(domain, true);
+               this.setJSEnabled(domain, true);
+               this.quickReload(win);
+             }
+             all.unshift(domain);
+            }
+          } catch(e) {}
 
-        for (let redir  of this.getRedirCache(browser, docURI)) {
-          all.push(redir.site);
-        }
-      }
+          sites.docSites.push(url);
+          all.push(url);
 
-      let domLoaded = !!this.getExpando(document, "domLoaded");
+          for (let redir  of this.getRedirCache(browser, docURI)) {
+            all.push(redir.site);
+          }
+        }
 
-      if (win === (top || (top = win.top))) {
-        sites.topSite = url;
-        if (domLoaded) this.setExpando(browser, "allowPageURL", null);
-      }
+        let domLoaded = !!this.getExpando(document, "domLoaded");
+        if (!topWin) {
+          topWin = win.top;
+          sites.topSite = url;
+          if (domLoaded) this.setExpando(browser, "allowPageURL", null);
+        }
 
-      let loaded = !((docShell instanceof nsIWebProgress) && docShell.isLoadingDocument);
-      if (!(domLoaded || loaded))
-        return;
+        let loaded = !((docShell instanceof nsIWebProgress) && docShell.isLoadingDocument);
+        if (!(domLoaded || loaded))
+          return;
 
-      this.processObjectElements(document, sites);
-      this.processScriptElements(document, sites, url);
+        this.processObjectElements(document, sites);
+        this.processScriptElements(document, sites, url);
 
-    }, this, browser);
+      }, this, browser);
 
-    let document = top.document;
-    let cache = this.getExpando(document, "objectSites");
-    if(cache) {
-      if(this.consoleDump & LOG_CONTENT_INTERCEPT) {
-        try { // calling toSource() can throw unexpected exceptions
-          this.dump("Adding plugin sites: " + cache.toSource() + " to " + all.toSource());
-        } catch(e) {
-          this.dump("Adding " + cache.length + " cached plugin sites");
+      document = topWin.document;
+      let cache = this.getExpando(document, "objectSites");
+      if(cache) {
+        if(this.consoleDump & LOG_CONTENT_INTERCEPT) {
+          try { // calling toSource() can throw unexpected exceptions
+            this.dump("Adding plugin sites: " + cache.toSource() + " to " + all.toSource());
+          } catch(e) {
+            this.dump("Adding " + cache.length + " cached plugin sites");
+          }
         }
-      }
-      if (!this.contentBlocker || this.alwaysShowObjectSources)
-        all.push.apply(sites.all, cache);
+        if (!this.contentBlocker || this.alwaysShowObjectSources)
+          all.push.apply(all, cache);
 
-      all.push.apply(sites.pluginSites, cache);
-    }
+        all.push.apply(sites.pluginSites, cache);
+      }
 
-    cache = this.getExpando(document, "codeSites");
-    if (cache) all.push.apply(sites.all, cache);
+      cache = this.getExpando(topWin, "codeSites");
+      if (cache) all.push.apply(all, [...cache]);
 
-    const removeBlank = !(this.showBlankSources || sites.topSite == "about:blank");
+      const removeBlank = !(this.showBlankSources || sites.topSite == "about:blank");
 
-    for (let j = all.length; j-- > 0;) {
-      let url = all[j];
-      if (/:/.test(url) &&
-          (removeBlank && url == "about:blank" ||
-            !(
-              /^(?:file:\/\/|[a-z]+:\/*[^\/\s]+)/.test(url) ||
-             // doesn't this URL type support host?
-              this.getSite(url + "x") == url
-            )
-          ) && url != "about:"
-        ) {
-        all.splice(j, 1); // reject scheme-only URLs
+      for (let j = all.length; j-- > 0;) {
+        let url = all[j];
+        if (/:/.test(url) &&
+            (removeBlank && url == "about:blank" ||
+              !(
+                /^(?:file:\/\/|[a-z]+:\/*[^\/\s]+)/.test(url) ||
+               // doesn't this URL type support host?
+                this.getSite(url + "x") == url
+              )
+            ) && url != "about:"
+          ) {
+          all.splice(j, 1); // reject scheme-only URLs
+        }
       }
+    } catch (e) {
+      Cu.reportError(e);
     }
-
+    sites.recentlyBlocked = this.recentlyBlocked;
 
     if (!sites.topSite) sites.topSite = all[0] || '';
     sites.all = this.sortedSiteSet(all);
@@ -3256,12 +3294,10 @@ const ns = {
   },
 
   _recentlyBlockedMax: 40,
-  recordBlocked: function(win, site, origin) {
-    if (!(win && this.getPref("showRecentlyBlocked"))) return;
-    let overlay = DOM.getChromeWindow(win).noscriptOverlay;
-    if (!overlay) return;
-
-    const l = overlay.recentlyBlocked;
+  recentlyBlocked: [],
+  recordBlocked: function(site, origin) {
+    if (!this.getPref("showRecentlyBlocked")) return;
+    let l = this.recentlyBlocked;
     let pos = l.length;
     while (pos-- > 0) if (l[pos].site === site) break;
 
@@ -3276,7 +3312,7 @@ const ns = {
 
     l.push(entry);
     if (l.length > this._recentlyBlockedMax) {
-      overlay.recentlyBlocked = l.slice(- this._recentlyBlockedMax / 2);
+      this.recentlyBlocked = l.slice(- this._recentlyBlockedMax / 2);
     }
   },
 
@@ -3447,12 +3483,13 @@ const ns = {
       if (this.consoleDump) this.dump(e);
     }
   },
- 
+
   onBeforeLoad: function(win) {
     let docShell = DOM.getDocShellForWindow(win);
     if (!docShell) return;
     let channel = docShell.currentDocumentChannel;
     if (!channel) return;
+    this.unserializeReqData(channel);
 
     const uri = channel.URI;
     const originURI = ABE.getOriginalOrigin(channel);
@@ -3469,13 +3506,16 @@ const ns = {
     if (ns.reqData(channel).checkWindowName) {
       InjectionChecker.checkWindowName(win, channel.URI.spec);
     }
-    
+
     if (!IOUtil.isMediaDocOrFrame(channel, contentType)) {
       return;
     }
-    
+
     try {
-      if (this.shouldLoad(7, uri, topWin ? uri : originURI || uri, win.frameElement || win, contentType,
+      let body = win.document.body;
+      let media = body && body.children.length === 1  && body.firstChild;
+      if (!(media instanceof win.HTMLMediaElement)) media = null;
+      if (this.shouldLoad(media ? 15 : 7, uri, topWin ? uri : originURI || uri, media || win.frameElement || win, contentType,
                           win.frameElement ? CP_FRAMECHECK : CP_SHOULDPROCESS) !== CP_OK) {
 
         channel.loadFlags |= channel.INHIBIT_CACHING;
@@ -3483,6 +3523,14 @@ const ns = {
         if (this.consoleDump & LOG_CONTENT_INTERCEPT)
           this.dump("Media document content type detected");
 
+        if (media) {
+          if (this.consoleDump & LOG_CONTENT_BLOCK)
+            this.dump("Aborting media " + contentType);
+          IOUtil.abort(channel);
+         return;
+        }
+
+
         if(!topWin) {
           // check if this is an iframe
 
@@ -3500,7 +3548,7 @@ const ns = {
 
           let browser = DOM.findBrowserForNode(win) || DOM.getFrameMM(win);
           this.getRedirCache(browser, win.top.document.documentURI).push({site: this.getSite(url), type: 7});
-        
+
 
           Thread.asap(function() {
             IOUtil.abort(channel);
@@ -3551,7 +3599,7 @@ const ns = {
     delete this._abortPluginDocLoads;
     return (this._abortPluginDocLoads = this.geckoVersionCheck("18.0.1") < 0);
   },
-  
+
   processXSSInfo(req) {
     let browser = IOUtil.findBrowser(req);
     if (browser) {
@@ -3567,7 +3615,7 @@ const ns = {
       }
     }
   },
-  
+
   hasClearClickHandler: false,
   get clearClickHandler() {
       delete this.clearClickHandler;
@@ -3575,89 +3623,6 @@ const ns = {
       return this.clearClickHandler = new ClearClickHandler(this);
   },
 
-  DOC_JS_STATUS_KEY: "noscript.dsjsBlocked",
-  _handleDocJS: function(win, req, requireNetwork) {
-    const abeSandboxed = req instanceof Ci.nsIHttpChannel && ABE.isSandboxed(req);
-    const docShellJSBlocking = this.docShellJSBlocking || abeSandboxed;
-
-    if (!docShellJSBlocking || (win instanceof Ci.nsIDOMChromeWindow)) return;
-    const dump = this.consoleDump & LOG_JS;
-    try {
-
-      let docShell = DOM.getDocShellForWindow(win) ||
-                     DOM.getDocShellForWindow(IOUtil.findWindow(req));
-
-      if (requireNetwork == docShell.restoringDocument) return;
-
-      let url = req.URI.spec;
-      if (!/^https?:/.test(url)) url = req.originalURI.spec;
-
-      if (!docShell) {
-        if (this.consoleDump) this.dump("DocShell not found for JS switching in " + url);
-        return;
-      }
-
-      if (abeSandboxed) {
-        ABE.sandbox(docShell, true);
-        return;
-      }
-
-      let jsEnabled;
-      if (docShellJSBlocking & 2) { // block not whitelisted
-        jsEnabled = url && this.isJSEnabled(this.getSite(url)) || /^about:/.test(url);
-      } else if (docShellJSBlocking & 1) { // block untrusted only
-        let site = this.getSite(url);
-        jsEnabled = !(this.isUntrusted(site) || this.isForbiddenByHttpsStatus(site));
-      } else return;
-
-      const prevStatus = docShell.allowJavascript;
-      // Trying to be kind with other docShell-level blocking apps (such as Tab Mix Plus), we
-      // check if we're the ones who actually blocked this docShell, or if this channel is out of our control
-
-      if (dump) this.dump("About to retrieve previously blocked info...");
-      let prevBlocked = requireNetwork && (req.loadFlags & req.LOAD_REPLACE) &&
-                      this.reqData(req).docJSBlocked ||
-                      this.getExpando(win, "docJSBlocked");
-
-      if (dump)
-        this.dump("DocShell JS Switch: " + url + " - " + jsEnabled + "/" + prevStatus + "/" + prevBlocked);
-
-      if (jsEnabled && !prevStatus) {
-
-        // be nice with other blockers
-        if (!prevBlocked) return;
-
-        // purge body events
-        try {
-          var aa = win.document.body && win.document.body.attributes;
-          if (aa) for (var j = aa.length; j-- > 0;) {
-            if(/^on/i.test(aa[j].name)) aa[j].value = "";
-          }
-        } catch(e1) {
-          if (dump)
-            this.dump("Error purging body attributes: " + e2);
-        }
-      }
-      let dsjsBlocked = // !jsEnabled && (prevBlocked || prevStatus)
-                        // we're the cause of the current disablement if
-                        // we're disabling and (was already blocked by us or was not blocked)
-                        !(jsEnabled || !(prevBlocked || prevStatus)) // De Morgan for the above, i.e.
-                        // we're the cause of the current disablement unless
-                        // we're enabling or (was already blocked by someone else = was not (blocked by us or enabled))
-                        // we prefer the latter because it coerces to boolean
-                        ;
-
-      this.reqData(req).docJSBlocked = dsjsBlocked;
-
-
-      ABE.sandbox(docShell, false);
-      docShell.allowJavascript = jsEnabled;
-    } catch(e2) {
-      if (dump)
-        this.dump("Error switching docShell JS: " + e2 + e2.stack);
-    }
-  },
-
   _pageModMaskRx: /^(?:chrome|resource|view-source):/,
   onWindowSwitch: function(url, win, docShell) {
     let channel = docShell.currentDocumentChannel;
@@ -3680,7 +3645,7 @@ const ns = {
       url = "wyciwyg:"; // don't execute on document.open() pages with a misleading URL
       jsBlocked = false;
     }
-    
+
     if (channel) {
       this.setExpando(win, "docJSBlocked", ns.reqData(channel).docJBlocked);
     }
@@ -3812,7 +3777,7 @@ const ns = {
       let channel = docShell.currentDocumentChannel;
       if (channel instanceof Ci.nsIHttpChannel) {
         let originalContentType = channel.getResponseHeader("Content-Type");
-        if (/\/json(?:;|^)/i.test(originalContentType) && channel.contentType === "text/html") blockIt = false;
+        if (/\/json(?:;|$)/i.test(originalContentType) && channel.contentType === "text/html") blockIt = false;
       }
     } catch (e) {
       this.log(e)
@@ -4044,7 +4009,6 @@ const ns = {
                 return;
               }
             }
-            this._handleDocJS(w, req, false);
           }
         }
       }
@@ -4400,6 +4364,8 @@ const ns = {
     if (!this.allowLocalLinks)
       return fromPolicy;
 
+    if (!principal) return true;
+
     if (url instanceof Ci.nsIURI) {
       if (!url.schemeIs("file")) return fromPolicy;
       url = url.spec;
diff --git a/chrome/noscript.jar!/content/noscript/MainChild.js b/chrome/noscript.jar!/content/noscript/MainChild.js
index 343fb34..c03c692 100644
--- a/chrome/noscript.jar!/content/noscript/MainChild.js
+++ b/chrome/noscript.jar!/content/noscript/MainChild.js
@@ -19,10 +19,13 @@ var MainChild = {
     }
   },
   afterInit: function() {
+    let snapshot = Services.cpmm.sendSyncMessage(IPC_P_MSG.GET_SNAPSHOT)[0];
+    this.jsPolicySites.sitesString = snapshot.trusted;
+    this.untrustedSites.sitesString = snapshot.untrusted;
+    this.manualSites.sitesString = snapshot.manual;
+    this.objectWhitelist = snapshot.objectWhitelist;
+    this.objectWhitelistLen = Object.keys(this.objectWhitelist).length;
     this.initContentPolicy(true);
-    Cc['@mozilla.org/docloaderservice;1'].getService(nsIWebProgress).addProgressListener(this,
-      nsIWebProgress.NOTIFY_LOCATION | nsIWebProgress.NOTIFY_STATE_REQUEST | nsIWebProgress.NOTIFY_STATUS |
-      ("NOTIFY_REFRESH" in nsIWebProgress ? nsIWebProgress.NOTIFY_REFRESH : 0));
   },
 
   "http-on-opening-request": {
@@ -586,14 +589,7 @@ var MainChild = {
 
     if (args[1]) {
       let win = DOM.findWindow(args[3]);
-      let focusedWin = win;
-      if (!focusedWin) {
-        focusedWin = DOM.mostRecentBrowserWindow;
-        focusedWin = focusedWin && focusedWin.content;
-      }
-      if (focusedWin) {
-        this.recordBlocked(focusedWin, this.getSite(args[1].spec) || "", this.getSite(win && win.location.href || args[2] && args[2].spec));
-      }
+      this.recordBlocked(this.getSite(args[1].spec) || "", this.getSite(win && win.location.href || args[2] && args[2].spec));
     }
 
     return CP_REJECT;
@@ -603,11 +599,11 @@ var MainChild = {
 
   forbiddenXMLRequest: function(aRequestOrigin, aContentLocation, aContext, forbidDelegate) {
     let originURL, locationURL;
-    if (aContentLocation.schemeIs("chrome") || !aRequestOrigin ||
+    if (aContentLocation.schemeIs("chrome") || aContentLocation.schemeIs("moz-extension") || !aRequestOrigin ||
          // GreaseMonkey Ajax comes from resource: hidden window
          // Google Toolbar Ajax from about:blank
            aRequestOrigin.schemeIs("chrome") || aRequestOrigin.schemeIs("resource") ||
-           aRequestOrigin.schemeIs("about") ||
+           aRequestOrigin.schemeIs("about") || aRequestOrigin.schemeIs("moz-extension") ||
            // Web Developer extension "appears" to XHR towards about:blank
            (locationURL = aContentLocation.spec) == "about:blank"
           ) return false;
@@ -617,11 +613,21 @@ var MainChild = {
         this.autoTemp(locationSite);
 
     var win = aContext && aContext.defaultView;
-    if(win) this.getExpando(win.top.document, "codeSites", []).push(locationSite);
-
+    if(win) {
+      this.cacheCodeSite(win, locationSite);
+    }
     return forbidDelegate.call(this, originURL, locationURL, win);
   },
 
+  cacheCodeSite(win, site) {
+    win = win.top;
+    let cache = this.getExpando(win, "codeSites");
+    if (!cache) {
+      cache = this.setExpando(win, "codeSites", new Set());
+    }
+    cache.add(site);
+  },
+
 
   addFlashVars: function(url, embed) {
     // add flashvars to have a better URL ID
diff --git a/chrome/noscript.jar!/content/noscript/MainParent.js b/chrome/noscript.jar!/content/noscript/MainParent.js
index 793e648..ef39d09 100644
--- a/chrome/noscript.jar!/content/noscript/MainParent.js
+++ b/chrome/noscript.jar!/content/noscript/MainParent.js
@@ -31,7 +31,13 @@ var MainParent = {
     this._updateSync();
 
     this.reloadWhereNeeded(this.RELOAD_NO); // init snapshots
+
+    if (this.getPref("webext.enabled")) { // experimental, only in dev builds for now
+      INCLUDE("WebExt");
+      this.webExt = WebExt;
+    }
   },
+  webExt: null,
 
    _initE10s: function() {
     INCLUDE("e10sParent");
@@ -76,8 +82,6 @@ var MainParent = {
           }
 
           let abeReq = ns.requestWatchdog.onHttpStart(channel);
-
-          if (abeReq && abeReq.isDoc) ns._handleDocJS(abeReq.window, channel, true);
         }
 
       } catch (e) {
@@ -254,8 +258,9 @@ var MainParent = {
     }
   },
 
-  _dontSerialize: ["version", "temp", "preset", "placesPrefs.ts", "mandatory", "default"],
-  serializeConf: function(beauty) {
+   _dontSerialize: ["version", "temp", "preset", "placesPrefs.ts", "mandatory", "default"],
+
+  conf2JSON() {
     const exclude = this._dontSerialize;
     const prefs = {};
     for (let key  of this.prefs.getChildList("", {})) {
@@ -263,13 +268,15 @@ var MainParent = {
         prefs[key] = this.getPref(key);
       }
     }
-
-    const conf = JSON.stringify({
+    return {
       prefs: prefs,
       whitelist: this.getPermanentSites().sitesString,
       V: this.VERSION
-    });
+    };
+  },
 
+  serializeConf: function(beauty) {
+    const conf = JSON.stringify(this.conf2JSON());
     return beauty ? conf.replace(/([^\\]"[^"]*[,\{])"/g, "$1\r\n\"").replace(/},?(?:\n|$)/g, "\r\n$&") : conf;
   },
 
@@ -428,5 +435,10 @@ var MainParent = {
     Services.mm.broadcastAsyncMessage("NoScript:reload", payload);
 
   },
+
+  purgeRecent() {
+    this.recentlyBlocked = [];
+    Services.mm.broadcastAsyncMessage("NoScript:purgeRecent", null);
+  },
 };
 
diff --git a/chrome/noscript.jar!/content/noscript/Policy.js b/chrome/noscript.jar!/content/noscript/Policy.js
index 80b284f..7953928 100644
--- a/chrome/noscript.jar!/content/noscript/Policy.js
+++ b/chrome/noscript.jar!/content/noscript/Policy.js
@@ -1,3 +1,7 @@
+Cc['@mozilla.org/docloaderservice;1'].getService(nsIWebProgress).addProgressListener(ns,
+      nsIWebProgress.NOTIFY_LOCATION | nsIWebProgress.NOTIFY_STATE_REQUEST | nsIWebProgress.NOTIFY_STATUS |
+      ("NOTIFY_REFRESH" in nsIWebProgress ? nsIWebProgress.NOTIFY_REFRESH : 0));
+
 var PolicyState = {
   hintsList: [],
   checking: [],
@@ -204,6 +208,10 @@ var MainContentPolicy = {
         return this.reject("Empty Flash object", arguments);
       aContentLocation = aRequestOrigin;
     }
+
+    var locationURL =aContentLocation.spec;
+    if (locationURL === "about:blank") return CP_OK;
+
     if (aContentType === 5 && /^application\/x-java\b/i.test(aMimeTypeGuess) &&
         aInternalCall !== CP_OBJECTARC) {
       try {
@@ -290,7 +298,7 @@ var MainContentPolicy = {
       PolicyState.addCheck(aContentLocation);
     }
     
-    var originURL, locationURL, originSite, locationSite, scheme,
+    var originURL, originSite, locationSite, scheme,
           forbid, isScript, isJava, isFlash, isSilverlight,
           isLegacyFrame, blockThisFrame, contentDocument,
           unwrappedLocation, mimeKey,
@@ -562,7 +570,7 @@ var MainContentPolicy = {
                   }
                 } else if (
                   !(aContext.ownerDocument.URL === originURL // Addon-SDK panels
-                     || this.isJSEnabled(originSite = this.getSite(originURL)))
+                     || this.isJSEnabled(originSite = this.getSite(originURL), aContext.ownerDocument.defaultView))
                   ) {
                   return this.reject("top level data: URI from forbidden origin", arguments);
                 }
@@ -642,7 +650,7 @@ var MainContentPolicy = {
         // we get the embedding document URL explicitly,
         // otherwise on redirection we would get the previous redirected URL
         if (contentDocument) { // XSLT comes with no context sometimes...
-          this.getExpando(contentDocument.defaultView.top.document, "codeSites", []).push(locationSite);
+          this.cacheCodeSite(contentDocument.defaultView, locationSite);
           originURL = contentDocument.URL;
         } else {
           originURL = aRequestOrigin && aRequestOrigin.spec;
diff --git a/chrome/noscript.jar!/content/noscript/RequestWatchdog.js b/chrome/noscript.jar!/content/noscript/RequestWatchdog.js
index deac04b..7e7f07e 100644
--- a/chrome/noscript.jar!/content/noscript/RequestWatchdog.js
+++ b/chrome/noscript.jar!/content/noscript/RequestWatchdog.js
@@ -83,11 +83,13 @@ RequestWatchdog.prototype = {
         cached = false;
 
       case "http-on-examine-cached-response":
-
+        ns.serializeReqData(channel);
         if (ns.externalFilters.enabled)
           ns.callExternalFilters(channel, cached);
 
         if (channel.loadFlags & this.DOCUMENT_LOAD_FLAGS) {
+          ns.serializeReqData(channel);
+          ABE.handleSandbox(channel);
           ns.onContentSniffed(channel);
         } else {
           if (!((ns.inclusionTypeChecking || ns.nosniff) && ns.checkInclusionType(channel)))
@@ -274,9 +276,12 @@ RequestWatchdog.prototype = {
   resetUntrustedReloadInfo: function(browser, channel) {
     if (!browser) return;
     var window = IOUtil.findWindow(channel);
-    if (browser.contentWindow == window) {
-      if (ns.consoleDump) this.dump(channel, "Top level document, resetting former untrusted browser info");
-      this.setUntrustedReloadInfo(browser, false);
+    try {
+      if (browser.contentWindow == window) {
+        if (ns.consoleDump) this.dump(channel, "Top level document, resetting former untrusted browser info");
+        this.setUntrustedReloadInfo(browser, false);
+      }
+    } catch (e) {
     }
   },
   setUntrustedReloadInfo: function(browser, status) {
@@ -441,8 +446,8 @@ RequestWatchdog.prototype = {
           if (ns.checkShorthands(targetSite)) {
             ns.autoTemp(targetSite);
             trustedTarget = true;
-          } else if (window) {
-            ns.recordBlocked(window, targetSite, originSite);
+          } else {
+            ns.recordBlocked(targetSite, originSite);
           }
         }
       }
@@ -712,12 +717,11 @@ RequestWatchdog.prototype = {
 
       if (injectionCheck < 3 && originSite && abeReq.originURI.schemeIs("https")) {
         
-        if (targetDomain === originDomain) {
-          this.dump(channel, "Same domain with HTTPS origin");
+        if (targetDomain === originDomain || ns.getBaseDomain(originDomain) === ns.getBaseDomain(targetDomain)) {
+          this.dump(channel, "Same base domain with HTTPS origin");
           return;
         }
       }
-
     }
 
     let stripPost = trustedTarget && originDomain && !trustedOrigin && ns.filterXPost &&
diff --git a/chrome/noscript.jar!/content/noscript/Thread.js b/chrome/noscript.jar!/content/noscript/Thread.js
index 9654bda..46b5203 100644
--- a/chrome/noscript.jar!/content/noscript/Thread.js
+++ b/chrome/noscript.jar!/content/noscript/Thread.js
@@ -16,7 +16,7 @@ var Thread = {
 
   _spinInternal: function(ctrl) {
     var t = ctrl.startTime;
-    var maxTime = parseInt(ctrl.maxTime)
+    var maxTime = parseInt(ctrl.maxTime);
     if (maxTime) {
       while(ctrl.running && this.hostRunning) {
         this.yield();
diff --git a/chrome/noscript.jar!/content/noscript/UISync.jsm b/chrome/noscript.jar!/content/noscript/UISync.jsm
index 343d7c5..ff8cf87 100644
--- a/chrome/noscript.jar!/content/noscript/UISync.jsm
+++ b/chrome/noscript.jar!/content/noscript/UISync.jsm
@@ -3,7 +3,7 @@ var EXPORTED_SYMBOLS = ["UISync"];
 let { interfaces: Ci, classes: Cc, utils: Cu, results: Cr } = Components;
 
 const HTMLDocument = Ci.nsIDOMHTMLDocument;
-const messages = ["NoScript:reload", "NoScript:reloadAllowedObjects"];
+const messages = ["NoScript:reload", "NoScript:reloadAllowedObjects", "NoScript:purgeRecent", "NoScript:forceSync"];
 
 function UISync(ctx) {
   this.ctx = ctx;
@@ -13,12 +13,18 @@ function UISync(ctx) {
 }
 
 UISync.prototype = {
+  eraser: {
+    tapped: null,
+    delKey: false,
+  },
   wire: function() {
     let ctx = this.ctx;
+    let eraser = this.eraser;
+
     ctx.addEventListener("DOMWindowCreated", () => this.sync());
     ctx.addEventListener("NoScript:syncUI", ev => {
        ev.stopPropagation();
-       this.sync();
+       this.scheduleSync();
     }, true);
     ctx.addEventListener("DOMContentLoaded", ev => {
       this.onContentLoad(ev);
@@ -27,8 +33,51 @@ UISync.prototype = {
       this.onPageShow(ev);
     }, true);
     ctx.addEventListener("pagehide", ev => {
+      eraser.tapped = null;
+      eraser.delKey = false;
       this.onPageHide(ev);
     }, true);
+
+    
+    ctx.addEventListener("keyup", ev => {
+      let el = eraser.tapped;
+      if (el && ev.keyCode === 46 &&
+          ctx.ns.getPref("eraseFloatingElements")
+        ) {
+        eraser.tapped = null;
+        eraser.delKey = true;
+        let doc = el.ownerDocument;
+        let w = doc.defaultView;
+        if (w.getSelection().isCollapsed) {
+          let root = doc.body || doc.documentElement;
+          let posRx = /^(?:absolute|fixed)$/;
+          do {
+            if (posRx.test(w.getComputedStyle(el, '').position)) {
+              (eraser.tapped = el.parentNode).removeChild(el);
+              break;
+            }
+          } while ((el = el.parentNode) && el != root);
+        }
+      }
+    }, true);
+
+    ctx.addEventListener("mousedown", ev => {
+      if (ev.button === 0) {
+        eraser.tapped = ev.target;
+        eraser.delKey = false;
+      }
+    }, true);
+
+    ctx.addEventListener("mouseup", ev => {
+      if (eraser.delKey) {
+        eraser.delKey = false;
+        ev.preventDefault();
+        ev.stopPropagation();
+      }
+      eraser.tapped = null;
+    }, true);
+
+
     for (let m of messages) {
       ctx.addMessageListener(m, this);
     }
@@ -43,7 +92,7 @@ UISync.prototype = {
   receiveMessage: function(msg) {
     let ctx = this.ctx;
     let ns = ctx.ns;
-    if (ns.consoleDump) ns.dump(`Received message ${msg.name} ${msg.data.toSource()}`);
+    if (ns.consoleDump) ns.dump(`Received message ${msg.name} ${uneval(msg.data)}`);
     switch(msg.name) {
       case "NoScript:reload":
         let { innerWindowID, snapshots, reloadPolicy, mustReload } = msg.data;
@@ -54,10 +103,23 @@ UISync.prototype = {
       break;
       case "NoScript:resetClearClickTimeout":
         ns.clearClickHandler.rapidFire.ts = 0;
+      break;
+      case "NoScript:purgeRecent":
+        ns.recentlyBlocked = [];
+      case "NoScript:forceSync":
+        this.sync();
+      break;
     }
   },
 
+  _syncScheduled: false,
+  scheduleSync() {
+    if (this._syncScheduled) return;
+    this.ctx.ns.delayExec(() => this.sync(), 500);
+    this._syncScheduled = true;
+  },
   sync() {
+    this._syncScheduled = false;
     let ctx = this.ctx;
     let sites = ctx.ns.getSites(this.ctx);
     if (sites.pluginExtras && sites.pluginExtras.length) {
diff --git a/chrome/noscript.jar!/content/noscript/WebExt.js b/chrome/noscript.jar!/content/noscript/WebExt.js
new file mode 100644
index 0000000..6c6ac5c
--- /dev/null
+++ b/chrome/noscript.jar!/content/noscript/WebExt.js
@@ -0,0 +1,50 @@
+var WebExt = {
+  enabled: false,
+  started: false,
+  running: false,
+  port: null,
+  saveData(json = ns.conf2JSON()) {
+    if (this.port) {
+      this.port.postMessage({ type: "saveData", data: json });
+    }
+  }
+};
+
+try {
+
+  const addonId = EXTENSION_ID;
+  const {
+    AddonManager,
+  } = Components.utils.import("resource://gre/modules/AddonManager.jsm", {});
+
+  AddonManager.getAddonByID(addonId, addon => {
+    const baseURI = addon.getResourceURI("/");
+    const {
+      LegacyExtensionsUtils,
+    } = Components.utils.import("resource://gre/modules/LegacyExtensionsUtils.jsm");
+
+    const embeddedWebExtension = LegacyExtensionsUtils.getEmbeddedExtensionFor({
+      id: addonId, resourceURI: baseURI,
+    });
+    WebExt.enabled = true;
+    embeddedWebExtension.startup().then(({browser}) => {
+      WebExt.started = true;
+      ns.dump(`${addonId} - embedded webext started`);
+      browser.runtime.onMessage.addListener(msg => {
+        WebExt.running = true;
+        ns.dump(`${addonId} - received message from embedded webext ${msg}`);
+      });
+      browser.runtime.onConnect.addListener(port => {
+        ns.dump(`${addonId} - webext connected`);
+        WebExt.port = port;
+        WebExt.saveData();
+      });
+    }).catch(err => {
+      Components.utils.reportError(
+        `${addonId} - embedded webext startup failed: ${err.message} ${err.stack}\n`
+      );
+    });
+  });
+} catch (e) {
+  Cu.reportError(e);
+}
diff --git a/chrome/noscript.jar!/content/noscript/WebGLInterception.js b/chrome/noscript.jar!/content/noscript/WebGLInterception.js
index 8dcbad4..e53f0d5 100644
--- a/chrome/noscript.jar!/content/noscript/WebGLInterception.js
+++ b/chrome/noscript.jar!/content/noscript/WebGLInterception.js
@@ -19,7 +19,7 @@ var WebGLInterception = {
         doc.defaultView.addEventListener("load", () => delete sites[site], false);
       }
     }
-    ns.recordBlocked(doc.defaultView, site, site);
+    ns.recordBlocked(site, site);
   },
   get interceptionDef() {
     delete this.interceptionDef;
diff --git a/chrome/noscript.jar!/content/noscript/about.xul b/chrome/noscript.jar!/content/noscript/about.xul
index 698d062..f0e296e 100644
--- a/chrome/noscript.jar!/content/noscript/about.xul
+++ b/chrome/noscript.jar!/content/noscript/about.xul
@@ -48,7 +48,7 @@ function about_onload() {
   
   var str = getString("aboutTitle",["NoScript"]);
   if(str) document.title = str;
-  str = getString("version", ["2.9.5.2"]);
+  str = getString("version", ["5.0.8.1"]);
   if(str) document.getElementById("extensionVersion").setAttribute("value", str);
   
   setString("extensionDescription",null,"extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description");
@@ -86,7 +86,7 @@ function about_open(url, features) {
 <hbox id="headBox" align="end">
 <vbox flex="1">
 <label value="NoScript" id="extensionName" crop="right"/>
-<label value="Version 2.9.5.2" id="extensionVersion" crop="right"/>
+<label value="Version 5.0.8.1" id="extensionVersion" crop="right"/>
 </vbox>
 <vbox flex="1" align="end">
 <hbox align="end">
@@ -99,7 +99,7 @@ function about_open(url, features) {
 <spacer flex="1"/>
 <hbox id="creatorBox">
 <label id="extensionCreatorLabel" value="Author:"/>
-<label id="extensionCreator" class="text-link" tooltiptext="Visit Author Home Page" onclick="about_open('http://maone.CHA')" value="Giorgio Maone" flex="1"/>
+<label id="extensionCreator" class="text-link" tooltiptext="Visit Author Home Page" onclick="about_open('http://maone.net')" value="Giorgio Maone" flex="1"/>
 </hbox>
 </vbox>
 </hbox>
@@ -115,7 +115,7 @@ function about_open(url, features) {
 <description class="contributor">Asaf Bartov & baryoni (Hebrew translation)</description>
 <description class="contributor">Alf and Liesbeth (Dutch translation)</description>
 <description class="contributor">Alexander Sokolov, Sergei Smirnov and negodnik (Russian translation)</description>
-<description class="contributor">Batuhan Çetin and eveterinary (Turkish translation)</description>
+<description class="contributor">Batuhan Çetin, Volkan Gezer and eveterinary (Turkish translation)</description>
 <description class="contributor">Baurzhan Muftakhidinov (Kazakh translation)</description>
 <description class="contributor">Beerboy & Haebaru (Japanese translation)</description>
 <description class="contributor">Carsten Winkler (Danish translation)</description>
@@ -154,7 +154,7 @@ function about_open(url, features) {
 <description class="contributor">Stiepan A. Kovac (Croatian translation)</description>
 <description class="contributor">swarnava (Bengali translation)</description>
 <description class="contributor">Tomaz Macus (Slovenian translation)</description>
-<description class="contributor">Thomas Weber & Volker Hable (German translation)</description>
+<description class="contributor">Thomas, milupo & Volker Hable (German translation)</description>
 <description class="contributor">tonynguyen and loveleeyoungae (Vietnamese translation)</description>
 <description class="contributor">x10firefox and Ultravioletu (Romanian translation)</description>
 <description class="contributor">Xavier Robin & BlackJack (French translation)</description>
@@ -164,7 +164,7 @@ function about_open(url, features) {
 <hbox>
 <label id="license" class="text-link" tooltiptext="Read end-user license" onclick="about_open('chrome://noscript/content/NoScript_License.txt')">License</label>
 <spacer flex="1"/>
-<label id="changelog" class="text-link" align="center" tooltiptext="See Changelog" onclick="about_open('https://noscript.net/changelog#2.9.5.2')">Changelog</label>
+<label id="changelog" class="text-link" align="center" tooltiptext="See Changelog" onclick="about_open('https://noscript.net/changelog#5.0.8.1')">Changelog</label>
 <spacer flex="1"/>
 <label id="extensionHomepage" class="text-link" tooltiptext="Visit Extension Home Page" onclick="about_open('https://noscript.net')">https://noscript.net</label>
 </hbox>
diff --git a/chrome/noscript.jar!/content/noscript/e10sIPC.js b/chrome/noscript.jar!/content/noscript/e10sIPC.js
index ce7e89b..43be529 100644
--- a/chrome/noscript.jar!/content/noscript/e10sIPC.js
+++ b/chrome/noscript.jar!/content/noscript/e10sIPC.js
@@ -8,6 +8,7 @@ IPC_P_MSG = {
   CALL: "NoScript:remoteCall",
   RESUME: "NoScript:resume",
   GET_PREF: "NoScript:getPref",
+  GET_SNAPSHOT: "NoScript:getSnapshot",
 }
 
 var IPC = {
diff --git a/chrome/noscript.jar!/content/noscript/e10sParent.js b/chrome/noscript.jar!/content/noscript/e10sParent.js
index 8666f7d..f708582 100644
--- a/chrome/noscript.jar!/content/noscript/e10sParent.js
+++ b/chrome/noscript.jar!/content/noscript/e10sParent.js
@@ -62,6 +62,13 @@ IPC.parent = {
           }
         }
         return null;
+      case IPC_P_MSG.GET_SNAPSHOT:
+        return {
+          trusted: ns.jsPolicySites.sitesString,
+          untrusted: ns.untrustedSites.sitesString,
+          manual: ns.manualSites.sitesString,
+          objectWhitelist: ns.objectWhitelist,
+        };
     }
   },
 
diff --git a/chrome/noscript.jar!/content/noscript/noscriptOverlay.js b/chrome/noscript.jar!/content/noscript/noscriptOverlay.js
index a027fac..a61409d 100644
--- a/chrome/noscript.jar!/content/noscript/noscriptOverlay.js
+++ b/chrome/noscript.jar!/content/noscript/noscriptOverlay.js
@@ -7,7 +7,6 @@ const Ci = Components.interfaces;
 return noscriptUtil.service ? {
 
   ns: noscriptUtil.service,
-  recentlyBlocked: [],
 
   getString: (key, parms) => noscriptUtil.getString(key, parms),
 
@@ -681,7 +680,7 @@ return noscriptUtil.service ? {
     var parent = null, extraNode = null;
     var untrustedCount = 0, unknownCount = 0, tempCount = 0;
     const untrustedSites = ns.untrustedSites;
-    var docJSBlocked = false;
+    var externalJSBlocked = false;
 
     const ignorePorts = ns.ignorePorts;
     const portRx = /:\d+$/;
@@ -731,8 +730,8 @@ return noscriptUtil.service ? {
       let showInMain = embedOnlySites
         ? embedOnlySites.indexOf(site) === -1 || hideUntrustedPlaceholder && enabled : true;
 
-      docJSBlocked = enabled && isTop && sites.docJSBlocked;
-      if (docJSBlocked) enabled = false;
+      externalJSBlocked = enabled && isTop && (sites.docJSBlocked || sites.cspBlocked);
+      if (externalJSBlocked) enabled = false;
 
       if (enabled && !global || (matchingSite = untrusted)) {
         if (ignorePorts && hasPort) {
@@ -814,7 +813,7 @@ return noscriptUtil.service ? {
       let max = ns.getPref("recentlyBlockedCount");
       let dejaVu = [],
           count = 0,
-          recent = this.recentlyBlocked,
+          recent = sites.recentlyBlocked,
           current = false;
 
       let tooltip = this.getSiteTooltip(false, !!ns.getPref("siteInfoProvider"));
@@ -913,7 +912,7 @@ return noscriptUtil.service ? {
         parent = showUntrusted && untrusted ? untrustedFrag : mainFrag;
         if (!parent) continue;
 
-        domain = isTop && docJSBlocked ? "[ " + menuSite + " ]" : menuSite;
+        domain = isTop && externalJSBlocked ? "[ " + menuSite + " ]" : menuSite;
 
         node = refMI.cloneNode(false);
         if (isTop) {
@@ -924,7 +923,7 @@ return noscriptUtil.service ? {
 
 
         let blurred = false;
-        let disabled = locked || (enabled ? ns.isMandatory(menuSite) : blurred = ns.isForbiddenByHttpsStatus(menuSite));
+        let disabled = locked || (enabled ? ns.isMandatory(menuSite) : blurred = externalJSBlocked || ns.isForbiddenByHttpsStatus(menuSite));
         if (disabled) {
           node.setAttribute("disabled", "true");
         } else {
@@ -1983,7 +1982,7 @@ return noscriptUtil.service ? {
         let site = !isUntrusted && (global || globalHttps && ns.isGlobalHttps(win, url) ? url : jsPSs.matches(url));
 
         if (url == sites.topSite) {
-          if (site && (!ns.httpStarted || !sites.docJSBlocked)) topTrusted = true;
+          if (site && (!ns.httpStarted || !(sites.docJSBlocked || sites.cspBlocked))) topTrusted = true;
           else {
             site = null;
             if (isUntrusted) topUntrusted = true;
@@ -2022,7 +2021,7 @@ return noscriptUtil.service ? {
                   ? allowed === total - blockedObjects
                       ? (global ? "glb-emb" : "emb")
                       : (cascadePermissions ? "yes" : "prt")
-                  : ns.docShellJSBlocking === 2 || cascadePermissions || ns.restrictSubdocScripting
+                  : cascadePermissions || ns.restrictSubdocScripting
                       ? "no"
                       : "subprt"
               );
@@ -2133,7 +2132,7 @@ return noscriptUtil.service ? {
           noscriptOverlay.syncUI(subject);
           return;
         case "browser:purge-session-history":
-          noscriptOverlay.recentlyBlocked = [];
+          noscriptOverlay.ns.purgeRecent();
           return;
       }
 
@@ -2443,52 +2442,6 @@ return noscriptUtil.service ? {
       noscriptOverlay.shortcutKeys.register();
       noscriptOverlay.observer.register();
 
-      let self = this;
-
-      window.addEventListener("keyup", function(ev) {
-        if (self.tapped && ev.keyCode === 46 &&
-            noscriptOverlay.ns.getPref("eraseFloatingElements")
-          ) {
-          let el = self.tapped;
-          self.tapped = null;
-          self.delKey = true;
-          let doc = el.ownerDocument;
-          let w = doc.defaultView;
-          if (w.top == content && !('' + w.getSelection())) {
-            let root = doc.body || doc.documentElement;
-            let posRx = /^(?:absolute|fixed)$/;
-            do {
-              if (posRx.test(w.getComputedStyle(el, '').position)) {
-                (self.tapped = el.parentNode).removeChild(el);
-                break;
-              }
-            } while ((el = el.parentNode) && el != root);
-          }
-        }
-      }, true);
-
-      window.addEventListener("mousedown", function(ev) {
-        if (ev.button === 0) {
-          let ns = noscriptOverlay.ns;
-          let el = ev.target;
-          self.tapped = ns.isJSEnabled(ns.getSite(el.ownerDocument.documentURI))
-            ? null
-            : (el.ownerDocument.defaultView.top == content) && el;
-          self.delKey = false;
-        }
-      }, true);
-
-      window.addEventListener("mouseup", function(ev) {
-        if (self.delKey) {
-          self.delKey = false;
-          if (ev.target.ownerDocument.defaultView.top == content) {
-            ev.preventDefault();
-            ev.stopPropagation();
-          }
-        }
-        self.tapped = null;
-      }, true);
-
       if ("CustomizableUI" in window) {
         CustomizableUI.addListener(this.customizableUIListener);
       }
diff --git a/chrome/noscript.jar!/content/noscript/noscriptOverlay.xul b/chrome/noscript.jar!/content/noscript/noscriptOverlay.xul
index 2daba5a..a39964d 100644
--- a/chrome/noscript.jar!/content/noscript/noscriptOverlay.xul
+++ b/chrome/noscript.jar!/content/noscript/noscriptOverlay.xul
@@ -157,7 +157,7 @@
               label="&noscriptReset;"
               class="menuitem-iconic"
               accesskey="&noscriptReset.accesskey;"
-              oncommand="noscriptOverlay.recentlyBlocked = []"
+              oncommand="noscriptOverlay.ns.purgeRecent()"
              />
           </menupopup>
        </menu>
diff --git a/chrome/noscript.jar!/locale/bg-BG/noscript/noscript.dtd b/chrome/noscript.jar!/locale/bg-BG/noscript/noscript.dtd
index ed4fce9..975f03b 100644
--- a/chrome/noscript.jar!/locale/bg-BG/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/bg-BG/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Настройки…">
 <!ENTITY noscriptOptions.accesskey "Н">
 <!ENTITY noscriptOptionsLong "Настройки на NoScript">
-<!ENTITY noscriptAbout "За NoScript 2.9.5.2">
+<!ENTITY noscriptAbout "За NoScript 5.0.8.1">
 <!ENTITY noscriptPermissionsText "Можете да зададете в кои уеб-сайтове е позволено да се използват скриптовете. Напишете адреса или домейна (например "http://www.site.com" или "site.com") на сайта, който искате да разрешите и натиснете Разреши.">
 <!ENTITY noscriptWebAddress "Адрес на уеб-сайта:">
 <!ENTITY noscriptAllow "Разреши">
diff --git a/chrome/noscript.jar!/locale/ca-AD/noscript/noscript.dtd b/chrome/noscript.jar!/locale/ca-AD/noscript/noscript.dtd
index add9386..9db5e9c 100644
--- a/chrome/noscript.jar!/locale/ca-AD/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/ca-AD/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Opcions...">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "Opcions de NoScript">
-<!ENTITY noscriptAbout "Quant a NoScript 2.9.5.2">
+<!ENTITY noscriptAbout "Quant a NoScript 5.0.8.1">
 <!ENTITY noscriptPermissionsText "Podeu especificar quins llocs web poden executar seqüències. El tipus d'adreça o el domini (p.ex. "http://www.site.com" o "site.com") del lloc al qual voleu donar permissos i feu clic a Permet.">
 <!ENTITY noscriptWebAddress "Adreça del lloc web:">
 <!ENTITY noscriptAllow "Permet">
diff --git a/chrome/noscript.jar!/locale/cs-CZ/noscript/noscript.dtd b/chrome/noscript.jar!/locale/cs-CZ/noscript/noscript.dtd
index 763fdeb..c2c7049 100644
--- a/chrome/noscript.jar!/locale/cs-CZ/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/cs-CZ/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Nastavení...">
 <!ENTITY noscriptOptions.accesskey "N">
 <!ENTITY noscriptOptionsLong "Nastavení NoScript">
-<!ENTITY noscriptAbout "O rozšíření NoScript 2.9.5.2">
+<!ENTITY noscriptAbout "O rozšíření NoScript 5.0.8.1">
 <!ENTITY noscriptPermissionsText "Můžete si zvolit, které webové stránky mají povoleno spouštět skripty. Zadejte adresu (např. http://www.site.com nebo site.com) na které se nachází stránka, pro kterou chcete skripty povolit a klepněte na Povolit.">
 <!ENTITY noscriptWebAddress "Adresa webové stránky:">
 <!ENTITY noscriptAllow "Povolit">
diff --git a/chrome/noscript.jar!/locale/cy-GB/noscript/noscript.dtd b/chrome/noscript.jar!/locale/cy-GB/noscript/noscript.dtd
index c854ec0..cc311a2 100644
--- a/chrome/noscript.jar!/locale/cy-GB/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/cy-GB/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Opsiynau">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "Opsiynau NoScript">
-<!ENTITY noscriptAbout "Yngylch NoScript 2.9.5.2">
+<!ENTITY noscriptAbout "Yngylch NoScript 5.0.8.1">
 <!ENTITY noscriptPermissionsText "Cewch enwi pa wefannau sy'n cael rhedeg sgriptiau. Teipiwch gyfeiriad neu barth (e.e. "http://www.site.com" neu "site.com") y safle rydych eisiau ei ganiatau ac wedyn cliciwch Caniatau.">
 <!ENTITY noscriptWebAddress "Cyfeiriad wefan">
 <!ENTITY noscriptAllow "Caniatau">
diff --git a/chrome/noscript.jar!/locale/da/noscript/noscript.dtd b/chrome/noscript.jar!/locale/da/noscript/noscript.dtd
index 31eb3c4..c07db9e 100644
--- a/chrome/noscript.jar!/locale/da/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/da/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Indstillinger…">
 <!ENTITY noscriptOptions.accesskey "I">
 <!ENTITY noscriptOptionsLong "NoScript Indstillinger">
-<!ENTITY noscriptAbout "Om NoScript 2.9.5.2">
+<!ENTITY noscriptAbout "Om NoScript 5.0.8.1">
 <!ENTITY noscriptPermissionsText "Du kan angive hvilke websteder der må udføre scripts. Indtast adresse eller domæne (f.eks. "http://www.site.com" eller "site.com") på det websted du ønsker at tillade og klik på Tillad.">
 <!ENTITY noscriptWebAddress "Webstedets adresse:">
 <!ENTITY noscriptAllow "Tillad">
diff --git a/chrome/noscript.jar!/locale/de/noscript/noscript.dtd b/chrome/noscript.jar!/locale/de/noscript/noscript.dtd
index 67f86e3..7827664 100644
--- a/chrome/noscript.jar!/locale/de/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/de/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Einstellungen…">
 <!ENTITY noscriptOptions.accesskey "E">
 <!ENTITY noscriptOptionsLong "NoScript - Einstellungen">
-<!ENTITY noscriptAbout "Über NoScript 2.9.5.2…">
+<!ENTITY noscriptAbout "Über NoScript 5.0.8.1…">
 <!ENTITY noscriptPermissionsText "Sie können festlegen, welchen Websites Sie das Ausführen von Skripten erlauben möchten. Geben Sie bitte die exakte Adresse oder die Domain der Website ein (z.B. "http://www.site.com" oder "site.com"), für die Sie dies zulassen möchten, und klicken Sie dann auf "Erlauben".">
 <!ENTITY noscriptWebAddress "Adresse der Website:">
 <!ENTITY noscriptAllow "Erlauben">
@@ -184,8 +184,8 @@
 <!ENTITY noscript.hoverUI "Berechtigungen-Menü öffnen beim Überfahren des NoScript-Symbols mit dem Mauszeiger">
 <!ENTITY noscriptDonate "Spenden">
 <!ENTITY noscriptDonate.accesskey "S">
-<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
-<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
-<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
-<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
-<!ENTITY noscriptPermanentInPrivate "Permanent "Allow" commands in private windows">
+<!ENTITY noscriptAutoReload.currentTab "Nur den aktuellen Tab neu laden">
+<!ENTITY noscriptCascadePermissions "Rechte des Hauptdokuments auf alle Unterdokumente und Skripte Dritter anwenden">
+<!ENTITY noscriptRestrictSubdocScripting "Skripte in Unterdokumenten der Positivliste blockieren, die zu Seiten gehören, die nicht in der Positivliste sind">
+<!ENTITY noscriptGlobalHttpsWhitelist "HTTPS Skripte generell bei HTTPS Dokumenten erlauben">
+<!ENTITY noscriptPermanentInPrivate "Permanentes "Zulassen" von Befehle in privaten Fenstern">
diff --git a/chrome/noscript.jar!/locale/de/noscript/noscript.properties b/chrome/noscript.jar!/locale/de/noscript/noscript.properties
index 3c2ff8f..965e5cc 100644
--- a/chrome/noscript.jar!/locale/de/noscript/noscript.properties
+++ b/chrome/noscript.jar!/locale/de/noscript/noscript.properties
@@ -47,10 +47,10 @@ ef.newName=Einen Namen für den neuen Filter festlegen:
 ef.locateExe=Eine ausführbare Datei für den Filter "%S" auswählen
 disable=%S deaktiviert
 disable.accessKey=d
-allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
-removal.title=Security Downgrade Warning
-removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
-removal.no=No, just stop blocking scripts
-removal.yes=Yes, remove ALL protections
-incompatibleOptions.title=Incompatible Options Warning
-incompatibleOptions="1$%S"\nis incompatible with "%2$S".\bDo you want to enable the former and disable the latter?
+allowed.glb-emb=Skripte sind global erlaubt, einige Einbettungen sind jedoch blockiert
+removal.title=Warnung vor Verschlechterung der Sicherheit
+removal.message=Wenn Sie NoScript deaktivieren oder deinstallieren, verzichten Sie auf JEDEN von NoScript angebotenen Schutz.\n\nWenn Sie es überdrüssig sind, Skriptrechte für jede einzelne Website zu verwalten, gibt es eine sicherere Wahl.\n\n NoScript kann das Blockieren von Skripten beenden, außer von denen, die Sie als nicht vertrauenswürdig markieren, während Sie sich weiterhin mit den fortgeschrittensten Sicherheitsmaßnahmen gegen XSS, Clickjacking, CSRF und andere Webbedrohungen s [...]
+removal.no=Nein, Skripte einfach nicht mehr blockieren
+removal.yes=Ja, jeden Schutz entfernen
+incompatibleOptions.title=Warnung vor inkompatiblen Einstellungen
+incompatibleOptions="1$%S"\nist mit "%2$S" inkompatibel.\bMöchten Sie Ersteres aktivieren und Letzteres deaktivieren?
diff --git a/chrome/noscript.jar!/locale/el/noscript/noscript.dtd b/chrome/noscript.jar!/locale/el/noscript/noscript.dtd
index 40eaa39..3efc066 100644
--- a/chrome/noscript.jar!/locale/el/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/el/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Επιλογές">
 <!ENTITY noscriptOptions.accesskey "Ε">
 <!ENTITY noscriptOptionsLong "Επιλογές NoScript">
-<!ENTITY noscriptAbout "Περί NoScript 2.9.5.2">
+<!ENTITY noscriptAbout "Περί NoScript 5.0.8.1">
 <!ENTITY noscriptPermissionsText "Μπορείτε να καθορίσετε για ποιους ιστότοπους θα επιτρέπεται η εκτέλεση σεναρίων εντολών. Πληκτρολογήστε τη διεύθυνση τομέα (πχ. "http://www.site.com" or "site.com") του ιστότοπου που θέλετε και μετά κάντε κλικ στο «Να επιτρέπεται»">
 <!ENTITY noscriptWebAddress "Διεύθυνση ιστότοπου">
 <!ENTITY noscriptAllow "Να επιτρέπεται">
diff --git a/chrome/noscript.jar!/locale/en-GB/noscript/noscript.dtd b/chrome/noscript.jar!/locale/en-GB/noscript/noscript.dtd
index d59ea43..a86176f 100644
--- a/chrome/noscript.jar!/locale/en-GB/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/en-GB/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Options…">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "NoScript Options">
-<!ENTITY noscriptAbout "About NoScript 2.9.5.2…">
+<!ENTITY noscriptAbout "About NoScript 5.0.8.1…">
 <!ENTITY noscriptPermissionsText "You can specify which web sites are allowed to execute scripts. Type the address or the domain (e.g. "http://www.site.com" or "site.com") of the site you want to allow and then click Allow.">
 <!ENTITY noscriptWebAddress "Address of web site:">
 <!ENTITY noscriptAllow "Allow">
diff --git a/chrome/noscript.jar!/locale/en-US/noscript/noscript.dtd b/chrome/noscript.jar!/locale/en-US/noscript/noscript.dtd
index ee1ae06..ed01da5 100644
--- a/chrome/noscript.jar!/locale/en-US/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/en-US/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Options…">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "NoScript Options">
-<!ENTITY noscriptAbout "About NoScript 2.9.5.2…">
+<!ENTITY noscriptAbout "About NoScript 5.0.8.1…">
 <!ENTITY noscriptPermissionsText "You can specify which web sites are allowed to execute scripts. Type the address or the domain (e.g. "http://www.site.com" or "site.com") of the site you want to allow and then click Allow.">
 <!ENTITY noscriptWebAddress "Address of web site:">
 <!ENTITY noscriptAllow "Allow">
diff --git a/chrome/noscript.jar!/locale/eo/noscript/noscript.dtd b/chrome/noscript.jar!/locale/eo/noscript/noscript.dtd
index cbf8638..c542cab 100644
--- a/chrome/noscript.jar!/locale/eo/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/eo/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Opcioj…">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "Opcioj de NoScript">
-<!ENTITY noscriptAbout "Pri NoScript 2.9.5.2…">
+<!ENTITY noscriptAbout "Pri NoScript 5.0.8.1…">
 <!ENTITY noscriptPermissionsText "Vi povas specifi, kiuj ttt-ejoj rajtu plenumigi skriptojn. Entajpu la adreson aŭ la domajnonomon (ekz. “http://www.retejo.org” aŭ “retejo.org”) de la ttt-ejo, kiun vi volas rajtigi, kaj poste alklaku “Rajtigi”.">
 <!ENTITY noscriptWebAddress "Adreso de retpaĝaro:">
 <!ENTITY noscriptAllow "Rajtigi">
diff --git a/chrome/noscript.jar!/locale/es-AR/noscript/noscript.dtd b/chrome/noscript.jar!/locale/es-AR/noscript/noscript.dtd
index 3f41c06..38a4c5c 100644
--- a/chrome/noscript.jar!/locale/es-AR/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/es-AR/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Opciones…">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "Opciones de NoScript">
-<!ENTITY noscriptAbout "Acerca de NoScript 2.9.5.2">
+<!ENTITY noscriptAbout "Acerca de NoScript 5.0.8.1">
 <!ENTITY noscriptPermissionsText "Puede especificar a cuáles sitios web le permitirá ejecutar scripts. Escriba la dirección o el dominio (por ejemplo, "http://www.sitio.com" o "sitio.com") del sitio y luego haga clic en Permitir.">
 <!ENTITY noscriptWebAddress "Dirección del sitio web:">
 <!ENTITY noscriptAllow "Permitir">
diff --git a/chrome/noscript.jar!/locale/es-CL/noscript/noscript.dtd b/chrome/noscript.jar!/locale/es-CL/noscript/noscript.dtd
index 766b02d..293b640 100644
--- a/chrome/noscript.jar!/locale/es-CL/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/es-CL/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Options…">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "Opciones de NoScript">
-<!ENTITY noscriptAbout "About NoScript 2.9.5.2…">
+<!ENTITY noscriptAbout "About NoScript 5.0.8.1…">
 <!ENTITY noscriptPermissionsText "You can specify which web sites are allowed to execute scripts. Type the address or the domain (e.g. "http://www.site.com" or "site.com") of the site you want to allow and then click Allow.">
 <!ENTITY noscriptWebAddress "Address of web site:">
 <!ENTITY noscriptAllow "Allow">
diff --git a/chrome/noscript.jar!/locale/es-ES/noscript/noscript.dtd b/chrome/noscript.jar!/locale/es-ES/noscript/noscript.dtd
index 8facea4..b97991d 100644
--- a/chrome/noscript.jar!/locale/es-ES/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/es-ES/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Opciones…">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "Configuración de NoScript">
-<!ENTITY noscriptAbout "Acerca de NoScript 2.9.5.2">
+<!ENTITY noscriptAbout "Acerca de NoScript 5.0.8.1">
 <!ENTITY noscriptPermissionsText "Aquí puede especificar las páginas web a las que va a permitir ejecutar código JavaScript. Escriba la dirección de la web que quiera incluir (ej. "http://www.paginaweb.com" o "paginaweb.com") y después pulse "Permitir".">
 <!ENTITY noscriptWebAddress "Dirección de la página web:">
 <!ENTITY noscriptAllow "Permitir">
diff --git a/chrome/noscript.jar!/locale/et-EE/noscript/noscript.dtd b/chrome/noscript.jar!/locale/et-EE/noscript/noscript.dtd
index d295e30..e5ab06a 100644
--- a/chrome/noscript.jar!/locale/et-EE/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/et-EE/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Sätted…">
 <!ENTITY noscriptOptions.accesskey "S">
 <!ENTITY noscriptOptionsLong "NoScripti sätted">
-<!ENTITY noscriptAbout "Täpsemalt lisast NoScript 2.9.5.2…">
+<!ENTITY noscriptAbout "Täpsemalt lisast NoScript 5.0.8.1…">
 <!ENTITY noscriptPermissionsText "Sa saad määrata, millistel veebilehtedel lubatakse skripte käivitada. Kirjuta veebilehe aadress või domeeni, mida soovid lubada (nt "http://www.site.com" või "site.com") ja klõpsa Luba nuppu">
 <!ENTITY noscriptWebAddress "Veebilehe aadress:">
 <!ENTITY noscriptAllow "Luba">
diff --git a/chrome/noscript.jar!/locale/eu/noscript/noscript.dtd b/chrome/noscript.jar!/locale/eu/noscript/noscript.dtd
index 859ae17..5cc37b5 100644
--- a/chrome/noscript.jar!/locale/eu/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/eu/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Aukerak:">
 <!ENTITY noscriptOptions.accesskey "A">
 <!ENTITY noscriptOptionsLong "NoScript aukerak">
-<!ENTITY noscriptAbout "NoScript 2.9.5.2-eri buruz:">
+<!ENTITY noscriptAbout "NoScript 5.0.8.1-eri buruz:">
 <!ENTITY noscriptPermissionsText "Zein webgunek script-ak exekuta ditzakeen zehaztu dezakezu. Idatzi script-ak erabiltzea onartzea nahi duzun domeinuaren izena (adib. "http://www.gunea.org" or "gunea.org") eta Onartu sakatu.">
 <!ENTITY noscriptWebAddress "Webgunearen helbidea:">
 <!ENTITY noscriptAllow "Onartu">
diff --git a/chrome/noscript.jar!/locale/fa-IR/noscript/noscript.dtd b/chrome/noscript.jar!/locale/fa-IR/noscript/noscript.dtd
index 68016c5..01b2eae 100644
--- a/chrome/noscript.jar!/locale/fa-IR/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/fa-IR/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "تنظیمات...">
 <!ENTITY noscriptOptions.accesskey "ت">
 <!ENTITY noscriptOptionsLong "تنظیمات NoScript">
-<!ENTITY noscriptAbout "درباره NoScript 2.9.5.2">
+<!ENTITY noscriptAbout "درباره NoScript 5.0.8.1">
 <!ENTITY noscriptPermissionsText "شما می توانید سایت هایی را که اجازه اجرای اسکریپت دارند را مشخص کنید.آدرس سایت یا نام دامنه را وارد کنید.(به عنوان مثال "http://www.site.com" یا "site.com")">
 <!ENTITY noscriptWebAddress "آدرس وب سایت :">
 <!ENTITY noscriptAllow "اجازه دادن">
diff --git a/chrome/noscript.jar!/locale/fi/noscript/noscript.dtd b/chrome/noscript.jar!/locale/fi/noscript/noscript.dtd
index 53c3dac..afad65c 100644
--- a/chrome/noscript.jar!/locale/fi/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/fi/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Asetukset…">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "NoScript asetukset">
-<!ENTITY noscriptAbout "Tietoja NoScript 2.9.5.2istä…">
+<!ENTITY noscriptAbout "Tietoja NoScript 5.0.8.1istä…">
 <!ENTITY noscriptPermissionsText "Voit määrittää verkkosivut joiden sallitaan suorittaa scriptejä. Kirjoita verkko-osoite tai verkkonimi (esim. "http://www.site.com" tai "site.com") jonka haluat sallia ja paina Salli.">
 <!ENTITY noscriptWebAddress "Verkkosivun osoite:">
 <!ENTITY noscriptAllow "Salli">
diff --git a/chrome/noscript.jar!/locale/fr/noscript/noscript.dtd b/chrome/noscript.jar!/locale/fr/noscript/noscript.dtd
index f79d11b..9e42ed5 100644
--- a/chrome/noscript.jar!/locale/fr/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/fr/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Options">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "Options de NoScript">
-<!ENTITY noscriptAbout "À propos de NoScript 2.9.5.2…">
+<!ENTITY noscriptAbout "À propos de NoScript 5.0.8.1…">
 <!ENTITY noscriptPermissionsText "Il est possible de spécifier quels sites Web sont autorisés à exécuter des scripts. Saisissez l'adresse exacte du site que vous désirez autoriser puis cliquez sur Autoriser.">
 <!ENTITY noscriptWebAddress "Adresse du site Web :">
 <!ENTITY noscriptAllow "Autoriser">
diff --git a/chrome/noscript.jar!/locale/gl-ES/noscript/noscript.dtd b/chrome/noscript.jar!/locale/gl-ES/noscript/noscript.dtd
index c4171eb..dbf1e3e 100644
--- a/chrome/noscript.jar!/locale/gl-ES/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/gl-ES/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Opcións...">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "Opcións de NoScript">
-<!ENTITY noscriptAbout "Acerca de NoScript 2.9.5.2">
+<!ENTITY noscriptAbout "Acerca de NoScript 5.0.8.1">
 <!ENTITY noscriptPermissionsText "Podes especificar que páxinas web poden executar scripts. Teclea o enderezo ou o dominio (por exemplo "http://www.paxina.com" ou "paxina.com") do sitio que queres autorizar e despois preme en "Permitir".">
 <!ENTITY noscriptWebAddress "Enderezo web:">
 <!ENTITY noscriptAllow "Permitir">
diff --git a/chrome/noscript.jar!/locale/he-IL/noscript/noscript.dtd b/chrome/noscript.jar!/locale/he-IL/noscript/noscript.dtd
index e43bcdb..ffb6277 100644
--- a/chrome/noscript.jar!/locale/he-IL/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/he-IL/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "הגדרות...">
 <!ENTITY noscriptOptions.accesskey "">
 <!ENTITY noscriptOptionsLong "NoScript הגדרות של">
-<!ENTITY noscriptAbout "אודות NoScript 2.9.5.2">
+<!ENTITY noscriptAbout "אודות NoScript 5.0.8.1">
 <!ENTITY noscriptPermissionsText "ציין אילו אתרים יכולים לקבל היתר להפעלת קבצי Script. הקלד את כתובת האתר או את שם התחום (כגון: "http://www.site.com" או "site.com") ולאחר מכן לחץ על התר.">
 <!ENTITY noscriptWebAddress "כתובת/תחום:">
 <!ENTITY noscriptAllow "התר">
diff --git a/chrome/noscript.jar!/locale/hr-HR/noscript/noscript.dtd b/chrome/noscript.jar!/locale/hr-HR/noscript/noscript.dtd
index 4d9d154..0315bac 100644
--- a/chrome/noscript.jar!/locale/hr-HR/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/hr-HR/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Opcije...">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "NoScript Opcije">
-<!ENTITY noscriptAbout "O NoScript 2.9.5.2">
+<!ENTITY noscriptAbout "O NoScript 5.0.8.1">
 <!ENTITY noscriptPermissionsText "Možete odrediti koje web stranice imaju dopuštenje za izvođenje skripti. Upišite adresu ili domenu (npr. "http://www.stranica.hr" ili "stranica.hr") stranice kojoj želite dopustiti i kliknite na Dopusti.">
 <!ENTITY noscriptWebAddress "Adresa web stranice:">
 <!ENTITY noscriptAllow "Dopusti">
diff --git a/chrome/noscript.jar!/locale/hsb/noscript/noscript.dtd b/chrome/noscript.jar!/locale/hsb/noscript/noscript.dtd
index 126f31e..340280e 100644
--- a/chrome/noscript.jar!/locale/hsb/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/hsb/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Opcije…">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "Opcije NoScript">
-<!ENTITY noscriptAbout "Wo NoScript 2.9.5.2…">
+<!ENTITY noscriptAbout "Wo NoScript 5.0.8.1…">
 <!ENTITY noscriptPermissionsText "Móžeće podać, kotre websydła smědźa skripty wuwjesć. Zapisajće adresu abo domenu  (na př. "http://www.site.com" abo "site.com") websydła, kotremuž chceće to dowolić a klikńće potom na "Dowolić".">
 <!ENTITY noscriptWebAddress "Adresa websydła:">
 <!ENTITY noscriptAllow "Dowolić">
diff --git a/chrome/noscript.jar!/locale/hu-HU/noscript/noscript.dtd b/chrome/noscript.jar!/locale/hu-HU/noscript/noscript.dtd
index b4be1cc..d7971f7 100644
--- a/chrome/noscript.jar!/locale/hu-HU/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/hu-HU/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Beállítások…">
 <!ENTITY noscriptOptions.accesskey "B">
 <!ENTITY noscriptOptionsLong "A NoScript beállításai">
-<!ENTITY noscriptAbout "A NoScript 2.9.5.2 névjegye">
+<!ENTITY noscriptAbout "A NoScript 5.0.8.1 névjegye">
 <!ENTITY noscriptPermissionsText "Megadhatja, hogy mely webhelyek számára engedélyezi a parancsfájlok futtatását. Írja be az engedélyezni kívánt webhely címét vagy tartomány nevét (pl. "http://www.webhely.hu" vagy "webhely.hu"), majd kattintson az Engedélyezés gombra.">
 <!ENTITY noscriptWebAddress "A webhely címe:">
 <!ENTITY noscriptAllow "Engedélyezés">
diff --git a/chrome/noscript.jar!/locale/id-ID/noscript/noscript.dtd b/chrome/noscript.jar!/locale/id-ID/noscript/noscript.dtd
index 9727612..925d02d 100644
--- a/chrome/noscript.jar!/locale/id-ID/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/id-ID/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Pilihan...">
 <!ENTITY noscriptOptions.accesskey "P">
 <!ENTITY noscriptOptionsLong "Pilihan NoScript">
-<!ENTITY noscriptAbout "Tentang NoScript 2.9.5.2">
+<!ENTITY noscriptAbout "Tentang NoScript 5.0.8.1">
 <!ENTITY noscriptPermissionsText "Anda dapat menentukan situs web mana yang diijinkan menjalankan naskah. Masukkan alamat atau domain (contoh: "http://www.site.com" atau "site.com") yang akan diberi ijin kemudian klik Ijinkan.">
 <!ENTITY noscriptWebAddress "Alamat situs web:">
 <!ENTITY noscriptAllow "Ijinkan">
diff --git a/chrome/noscript.jar!/locale/it/noscript/noscript.dtd b/chrome/noscript.jar!/locale/it/noscript/noscript.dtd
index d38f4af..b247264 100644
--- a/chrome/noscript.jar!/locale/it/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/it/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Opzioni…">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "Opzioni NoScript">
-<!ENTITY noscriptAbout "Informazioni su NoScript 2.9.5.2…">
+<!ENTITY noscriptAbout "Informazioni su NoScript 5.0.8.1…">
 <!ENTITY noscriptPermissionsText "Qui si possono indicare i siti per i quali l'esecuzione degli script è consentita. Digitare l'indirizzo o il dominio (es. "http://www.sito.com" oppure "sito.com")  e fare clic su Permetti.">
 <!ENTITY noscriptWebAddress "Indirizzo del sito:">
 <!ENTITY noscriptAllow "Permetti">
diff --git a/chrome/noscript.jar!/locale/ja-JP/noscript/noscript.dtd b/chrome/noscript.jar!/locale/ja-JP/noscript/noscript.dtd
index 8093523..5bd4ce8 100644
--- a/chrome/noscript.jar!/locale/ja-JP/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/ja-JP/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "オプション...">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "NoScript オプション">
-<!ENTITY noscriptAbout "NoScript 2.9.5.2について...">
+<!ENTITY noscriptAbout "NoScript 5.0.8.1について...">
 <!ENTITY noscriptPermissionsText "JavaScriptを許可するサイトを指定する事ができます。許可したいサイトのアドレスかドメインを入力して、ボタンを押してください。(例: "http://www.site.com" または "site.com")">
 <!ENTITY noscriptWebAddress "ウェブサイトのアドレス:">
 <!ENTITY noscriptAllow "許可する">
diff --git a/chrome/noscript.jar!/locale/kk-KZ/noscript/noscript.dtd b/chrome/noscript.jar!/locale/kk-KZ/noscript/noscript.dtd
index 3988374..6564789 100644
--- a/chrome/noscript.jar!/locale/kk-KZ/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/kk-KZ/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Баптаулары">
 <!ENTITY noscriptOptions.accesskey "Б">
 <!ENTITY noscriptOptionsLong "NoScript баптаулары">
-<!ENTITY noscriptAbout "NoScript 2.9.5.2 туралы...">
+<!ENTITY noscriptAbout "NoScript 5.0.8.1 туралы...">
 <!ENTITY noscriptPermissionsText "Қай сайттарға JavaScript орындауға рұқсат екенін көрсете аласыз. Рұқсат етілетін сайттың домен адресін енгізіңіз (мысалы, "http://www.site.com" немесе "site.com"), содан кейін Рұқсат ету басыңыз.">
 <!ENTITY noscriptWebAddress "Веб-сайт адресі:">
 <!ENTITY noscriptAllow "Рұқсат ету">
diff --git a/chrome/noscript.jar!/locale/km-KH/noscript/noscript.dtd b/chrome/noscript.jar!/locale/km-KH/noscript/noscript.dtd
index e2576e8..3d3b992 100644
--- a/chrome/noscript.jar!/locale/km-KH/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/km-KH/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Options...">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "NoScript Options">
-<!ENTITY noscriptAbout "About NoScript 2.9.5.2">
+<!ENTITY noscriptAbout "About NoScript 5.0.8.1">
 <!ENTITY noscriptPermissionsText "You can specify which web sites are allowed to execute scripts. Type the address or the domain (e.g. "http://www.site.com" or "site.com") of the site you want to allow and then click Allow.">
 <!ENTITY noscriptWebAddress "Address of web site:">
 <!ENTITY noscriptAllow "Allow">
diff --git a/chrome/noscript.jar!/locale/ko-KR/noscript/noscript.dtd b/chrome/noscript.jar!/locale/ko-KR/noscript/noscript.dtd
index e907759..ca439e8 100644
--- a/chrome/noscript.jar!/locale/ko-KR/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/ko-KR/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "옵션...">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "NoScript 옵션">
-<!ENTITY noscriptAbout "NoScript 2.9.5.2 정보...">
+<!ENTITY noscriptAbout "NoScript 5.0.8.1 정보...">
 <!ENTITY noscriptPermissionsText "스크립트 실행을 허용할 웹 사이트를 지정할 수 있습니다. 스크립트를 허용할 사이트의 주소나 도메인 (예를 들면, "http://www.site.com" 또는 "site.com")을 입력한 후 [허용] 버튼을 클릭합니다.">
 <!ENTITY noscriptWebAddress "웹 사이트 주소">
 <!ENTITY noscriptAllow "허용">
diff --git a/chrome/noscript.jar!/locale/lt/noscript/noscript.dtd b/chrome/noscript.jar!/locale/lt/noscript/noscript.dtd
index 35e569a..456ef8e 100644
--- a/chrome/noscript.jar!/locale/lt/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/lt/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Nuostatos...">
 <!ENTITY noscriptOptions.accesskey "N">
 <!ENTITY noscriptOptionsLong "NoScript nuostatos">
-<!ENTITY noscriptAbout "Apie NoScript 2.9.5.2">
+<!ENTITY noscriptAbout "Apie NoScript 5.0.8.1">
 <!ENTITY noscriptPermissionsText "Jūs galite nurodyti, kurioms interneto svetainėms suteikiamas leidimas vykdyti programinius kodus. Įveskite adresą arba domeną (pvz., "http://www.svetaine.lt" arba "svetaine.lt") svetainės, kuriai norite suteikti leidimą ir spauskite Leisti.">
 <!ENTITY noscriptWebAddress "Interneto svetainės adresas:">
 <!ENTITY noscriptAllow "Leisti">
diff --git a/chrome/noscript.jar!/locale/mk-MK/noscript/noscript.dtd b/chrome/noscript.jar!/locale/mk-MK/noscript/noscript.dtd
index 4647f9c..574bd68 100644
--- a/chrome/noscript.jar!/locale/mk-MK/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/mk-MK/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Опции...">
 <!ENTITY noscriptOptions.accesskey "О">
 <!ENTITY noscriptOptionsLong "NoScript Опции">
-<!ENTITY noscriptAbout "За NoScript 2.9.5.2">
+<!ENTITY noscriptAbout "За NoScript 5.0.8.1">
 <!ENTITY noscriptPermissionsText "Можете да ги назначите страните, на кои што скриптите ќе бидат дозволени. Напишете ја дозволената адреса (на пример http://www.site.com или site.com) и кликнете „Дозволи“">
 <!ENTITY noscriptWebAddress "Адреса на дозволената веб страна:">
 <!ENTITY noscriptAllow "Дозволи">
diff --git a/chrome/noscript.jar!/locale/ms-MY/noscript/noscript.dtd b/chrome/noscript.jar!/locale/ms-MY/noscript/noscript.dtd
index 6dc091d..c8f11c5 100644
--- a/chrome/noscript.jar!/locale/ms-MY/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/ms-MY/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Tetapan...">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "Tetapan NoScript">
-<!ENTITY noscriptAbout "Tentang NoScript 2.9.5.2">
+<!ENTITY noscriptAbout "Tentang NoScript 5.0.8.1">
 <!ENTITY noscriptPermissionsText "Anda boleh menentukan laman web yang anda benarkan skripnya diproses. Taipkan alamat atau domain(contoh:"http://www.tapak.com" atau "tapak.com") laman web yang diingini dan klik Benarkan">
 <!ENTITY noscriptWebAddress "Alamat laman web:">
 <!ENTITY noscriptAllow "Benarkan">
diff --git a/chrome/noscript.jar!/locale/nb-NO/noscript/noscript.dtd b/chrome/noscript.jar!/locale/nb-NO/noscript/noscript.dtd
index 41b8261..3e2e6db 100644
--- a/chrome/noscript.jar!/locale/nb-NO/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/nb-NO/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Innstillinger">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "NoScript Innstillinger">
-<!ENTITY noscriptAbout "Om NoScript 2.9.5.2">
+<!ENTITY noscriptAbout "Om NoScript 5.0.8.1">
 <!ENTITY noscriptPermissionsText "Du kan spesifisere hvilke websider som har tillatelse til å kjøre scritper. Skriv inn adresse, eller domene (F.eks: "http://www.side.no", eller &quotside.no") du ønsker å gi tillatelse til, og klikk Tillat.">
 <!ENTITY noscriptWebAddress "Webadresse:">
 <!ENTITY noscriptAllow "Tillat">
diff --git a/chrome/noscript.jar!/locale/nl/noscript/noscript.dtd b/chrome/noscript.jar!/locale/nl/noscript/noscript.dtd
index 5e50dfe..4d4e9b6 100644
--- a/chrome/noscript.jar!/locale/nl/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/nl/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Opties…">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "NoScript-opties">
-<!ENTITY noscriptAbout "Over NoScript 2.9.5.2">
+<!ENTITY noscriptAbout "Over NoScript 5.0.8.1">
 <!ENTITY noscriptPermissionsText "U kunt opgeven welke websites scripts mogen gebruiken. Typ het adres of domein (bv. ‘http://www.website.com’ of ‘website.com’) van de website die u wilt toestaan, en klik daarna op Toestaan.">
 <!ENTITY noscriptWebAddress "Adres van website:">
 <!ENTITY noscriptAllow "Toestaan">
@@ -13,7 +13,7 @@
 <!ENTITY noscriptUntrust "Markeren als niet vertrouwd">
 <!ENTITY noscriptUntrust.accesskey "n">
 <!ENTITY noscriptRemoveSelected "Geselecteerde websites verwijderen">
-<!ENTITY noscriptGloballyEnabled "Scripts worden algemeen toegestaan (gevaarlijk)">
+<!ENTITY noscriptGloballyEnabled "Scripts worden overal toegestaan (gevaarlijk)">
 <!ENTITY noscriptAutoReload "Betrokken pagina’s automatisch vernieuwen als toestemmingen wijzigen">
 <!ENTITY noscriptAutoReload.currentTab "Alleen het huidige tabblad opnieuw laden">
 <!ENTITY noscriptGeneral "Algemeen">
@@ -187,5 +187,5 @@
 <!ENTITY noscriptDonate.accesskey "D">
 <!ENTITY noscriptCascadePermissions "Toestemmingen van bovenste document aan scripts van derden doorgeven">
 <!ENTITY noscriptRestrictSubdocScripting "Scripts in toegestane subdocumenten van niet-toegestane pagina’s blokkeren">
-<!ENTITY noscriptGlobalHttpsWhitelist "HTTPS-scripts op HTTPS-documenten algemeen toestaan">
+<!ENTITY noscriptGlobalHttpsWhitelist "HTTPS-scripts op HTTPS-documenten overal toestaan">
 <!ENTITY noscriptPermanentInPrivate "Permanente ‘Toestaan’-opdrachten in privévensters">
diff --git a/chrome/noscript.jar!/locale/nl/noscript/noscript.properties b/chrome/noscript.jar!/locale/nl/noscript/noscript.properties
index d9ed2d6..00b0bdb 100644
--- a/chrome/noscript.jar!/locale/nl/noscript/noscript.properties
+++ b/chrome/noscript.jar!/locale/nl/noscript/noscript.properties
@@ -1,15 +1,15 @@
-allowGlobal=Scripts algemeen toestaan (gevaarlijk)
-forbidGlobal=Scripts algemeen niet toestaan (geadviseerd)
+allowGlobal=Scripts overal toestaan (gevaarlijk)
+forbidGlobal=Scripts overal verbieden (geadviseerd)
 allowLocal=%S toestaan
 allowTemp=%S tijdelijk toestaan
-forbidLocal=%S niet toestaan
-allowed.glb=Gevaar! Scripts worden algemeen toegestaan
-allowed.glb-emb=Scripts worden algemeen toegestaan, maar sommige insluitingen geblokkeerd
-allowed.yes=JavaScript wordt momenteel toegestaan
-allowed.prt=JavaScript wordt gedeeltelijk toegestaan
-allowed.no=JavaScript wordt momenteel niet toegestaan
+forbidLocal=%S verbieden
+allowed.glb=Gevaar! Scripts worden overal toegestaan
+allowed.glb-emb=Scripts worden overal toegestaan, maar sommige insluitingen geblokkeerd
+allowed.yes=Scripts worden momenteel toegestaan
+allowed.prt=Scripts worden gedeeltelijk toegestaan
+allowed.no=Scripts worden momenteel niet toegestaan
 global.warning.title=Waarschuwing!
-global.warning.text=Scripts zullen algemeen worden toegestaan (voor alle websites).\nDit is een potentieel gevaarlijke actie.\nWilt u echt doorgaan?
+global.warning.text=Scripts zullen overal worden toegestaan (voor alle websites).\nDit is een potentieel gevaarlijke actie.\nWilt u echt doorgaan?
 audio.samples=Geluidsvoorbeelden
 confirm=Weet u het zeker?
 alwaysAsk=Altijd om bevestiging vragen
diff --git a/chrome/noscript.jar!/locale/pl/noscript/noscript.dtd b/chrome/noscript.jar!/locale/pl/noscript/noscript.dtd
index 1220d71..8ce6d9f 100644
--- a/chrome/noscript.jar!/locale/pl/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/pl/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Ustawienia">
 <!ENTITY noscriptOptions.accesskey "U">
 <!ENTITY noscriptOptionsLong "NoScript – ustawienia">
-<!ENTITY noscriptAbout "NoScript 2.9.5.2 – informacje">
+<!ENTITY noscriptAbout "NoScript 5.0.8.1 – informacje">
 <!ENTITY noscriptPermissionsText "Tutaj można określić witryny internetowe, które będą mogły uruchamiać skrypty. Proszę wprowadzić adres lub domenę witryny (np: „http://www.witryna.pl” lub „witryna.pl”) i nacisnąć przycisk Pozwól.">
 <!ENTITY noscriptWebAddress "Adres witryny:">
 <!ENTITY noscriptAllow "Pozwól">
diff --git a/chrome/noscript.jar!/locale/pt-BR/noscript/noscript.dtd b/chrome/noscript.jar!/locale/pt-BR/noscript/noscript.dtd
index 6244a36..ffdc9d7 100644
--- a/chrome/noscript.jar!/locale/pt-BR/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/pt-BR/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Opções">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "Opções do NoScript">
-<!ENTITY noscriptAbout "Sobre o NoScript 2.9.5.2…">
+<!ENTITY noscriptAbout "Sobre o NoScript 5.0.8.1…">
 <!ENTITY noscriptPermissionsText "Você pode especificar os sites que podem executar JavaScripts. Escreva o endereço ou o domínio (ex "http://www.site.com" ou "site.com") do site que deseja permitir e depois clique em Permitir.">
 <!ENTITY noscriptWebAddress "Endereço:">
 <!ENTITY noscriptAllow "Permitir">
diff --git a/chrome/noscript.jar!/locale/pt-PT/noscript/noscript.dtd b/chrome/noscript.jar!/locale/pt-PT/noscript/noscript.dtd
index 089a32b..b483fe8 100644
--- a/chrome/noscript.jar!/locale/pt-PT/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/pt-PT/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Opções">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "Opções do NoScript">
-<!ENTITY noscriptAbout "Sobre o NoScript 2.9.5.2">
+<!ENTITY noscriptAbout "Sobre o NoScript 5.0.8.1">
 <!ENTITY noscriptPermissionsText "Pode especificar os sítios que podem executar scripts. Escreva o endereço ou o domínio (ex: "http://www.sitio.com" ou "sitio.com") do sítio que deseja permitir e depois pressione em Permitir.">
 <!ENTITY noscriptWebAddress "Endereço:">
 <!ENTITY noscriptAllow "Permitir">
diff --git a/chrome/noscript.jar!/locale/ro/noscript/noscript.dtd b/chrome/noscript.jar!/locale/ro/noscript/noscript.dtd
index d1f4797..803cb5c 100644
--- a/chrome/noscript.jar!/locale/ro/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/ro/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Opțiuni...">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "Opțiuni NoScript">
-<!ENTITY noscriptAbout "Despre NoScript 2.9.5.2">
+<!ENTITY noscriptAbout "Despre NoScript 5.0.8.1">
 <!ENTITY noscriptPermissionsText "Puteți specifica saiturile cărora li se permite să execute scripturi. Scrieți adresa sau domeniul paginii (exemplu: „http://www.sait.ro“ sau „sait.ro“), apoi apăsați pe butonul „Permite“.">
 <!ENTITY noscriptWebAddress "Adresă sait:">
 <!ENTITY noscriptAllow "Permite">
diff --git a/chrome/noscript.jar!/locale/sk-SK/noscript/noscript.dtd b/chrome/noscript.jar!/locale/sk-SK/noscript/noscript.dtd
index 12135a1..15bc236 100644
--- a/chrome/noscript.jar!/locale/sk-SK/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/sk-SK/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Možnosti...">
 <!ENTITY noscriptOptions.accesskey "M">
 <!ENTITY noscriptOptionsLong "NoScript – Možnosti">
-<!ENTITY noscriptAbout "O rozšírení NoScript 2.9.5.2">
+<!ENTITY noscriptAbout "O rozšírení NoScript 5.0.8.1">
 <!ENTITY noscriptPermissionsText "Môžete určiť, ktoré webové stránky majú povolené spúšťať JavaScript. Zadajte adresu alebo doménu (napríklad "http://www.site.com" alebo "site.com") stránky, ktorú chcete povoliť, a potom kliknite na tlačidlo Povoliť.">
 <!ENTITY noscriptWebAddress "Adresa webovej stránky:">
 <!ENTITY noscriptAllow "Povoliť">
diff --git a/chrome/noscript.jar!/locale/sl-SI/noscript/noscript.dtd b/chrome/noscript.jar!/locale/sl-SI/noscript/noscript.dtd
index c263bc9..6a44a1b 100644
--- a/chrome/noscript.jar!/locale/sl-SI/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/sl-SI/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Možnosti...">
 <!ENTITY noscriptOptions.accesskey "M">
 <!ENTITY noscriptOptionsLong "NoScript Možnosti">
-<!ENTITY noscriptAbout "O NoScript 2.9.5.2 programu...">
+<!ENTITY noscriptAbout "O NoScript 5.0.8.1 programu...">
 <!ENTITY noscriptPermissionsText "Določite lahko na katerih straneh bo izvajanje skript dovoljeno. Vnesite naslov ali domeno (pr. "http://www.domena.com" or "domena.com") strani, na kateri želite omogočiti izvajanje skript in kliknite Dovoli.">
 <!ENTITY noscriptWebAddress "Naslov strani:">
 <!ENTITY noscriptAllow "Dovoli">
diff --git a/chrome/noscript.jar!/locale/sr-RS/noscript/noscript.dtd b/chrome/noscript.jar!/locale/sr-RS/noscript/noscript.dtd
index c8ea100..f581ef5 100644
--- a/chrome/noscript.jar!/locale/sr-RS/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/sr-RS/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Подешавања...">
 <!ENTITY noscriptOptions.accesskey "П">
 <!ENTITY noscriptOptionsLong "NoScript подешавања">
-<!ENTITY noscriptAbout "О NoScript 2.9.5.2-у">
+<!ENTITY noscriptAbout "О NoScript 5.0.8.1-у">
 <!ENTITY noscriptPermissionsText "Можете да наведете којим веб странама је дозвољено да извршавају скриптове. Унесите адресу или домен (нпр. "http://www.site.com" или "site.com") стране којој желите да дате дозволу и онда кликните Дозволи.">
 <!ENTITY noscriptWebAddress "Адреса веб стране:">
 <!ENTITY noscriptAllow "Дозволи">
diff --git a/chrome/noscript.jar!/locale/sv-SE/noscript/noscript.dtd b/chrome/noscript.jar!/locale/sv-SE/noscript/noscript.dtd
index 2b842a7..82bab6f 100644
--- a/chrome/noscript.jar!/locale/sv-SE/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/sv-SE/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Alternativ...">
 <!ENTITY noscriptOptions.accesskey "A">
 <!ENTITY noscriptOptionsLong "NoScript-alternativ">
-<!ENTITY noscriptAbout "Om NoScript 2.9.5.2">
+<!ENTITY noscriptAbout "Om NoScript 5.0.8.1">
 <!ENTITY noscriptPermissionsText "Ange vilka webbplatser som får köra skript. Skriv webbadressen eller domänen (t ex. "http://www.webbplats.se" eller "webbplats.se") för den webbplats där skript ska tillåtas. Klicka sedan på "Tillåt".">
 <!ENTITY noscriptWebAddress "Sidans adress:">
 <!ENTITY noscriptAllow "Tillåt">
diff --git a/chrome/noscript.jar!/locale/te-IN/noscript/noscript.dtd b/chrome/noscript.jar!/locale/te-IN/noscript/noscript.dtd
index 22ace4c..405da24 100644
--- a/chrome/noscript.jar!/locale/te-IN/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/te-IN/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Options…">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "NoScript Options">
-<!ENTITY noscriptAbout "About NoScript 2.9.5.2…">
+<!ENTITY noscriptAbout "About NoScript 5.0.8.1…">
 <!ENTITY noscriptPermissionsText "You can specify which web sites are allowed to execute scripts. Type the address or the domain (e.g. "http://www.site.com" or "site.com") of the site you want to allow and then click Allow.">
 <!ENTITY noscriptWebAddress "Address of web site:">
 <!ENTITY noscriptAllow "Allow">
diff --git a/chrome/noscript.jar!/locale/th/noscript/noscript.dtd b/chrome/noscript.jar!/locale/th/noscript/noscript.dtd
index 44ad5f1..f9f5625 100644
--- a/chrome/noscript.jar!/locale/th/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/th/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "ตัวเลือก...">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "ตัวเลือก NoScript">
-<!ENTITY noscriptAbout "เกี่ยวกับ NoScript 2.9.5.2">
+<!ENTITY noscriptAbout "เกี่ยวกับ NoScript 5.0.8.1">
 <!ENTITY noscriptPermissionsText "คุณสามารถกำหนดเว็บไซต์ที่จะอนุญาตดำเนินการสคริปต์ พิมพ์ที่อยู่หรือโดเมน (เช่น "http://www.site.com" หรือ "site.com") ของไซต์ที่คุณต้องการอนุญาตและคลิกอนุญาต">
 <!ENTITY noscriptWebAddress "ที่อยู่เว็บไซต์:">
 <!ENTITY noscriptAllow "อนุญาต">
diff --git a/chrome/noscript.jar!/locale/tr/noscript/about.properties b/chrome/noscript.jar!/locale/tr/noscript/about.properties
index 531fbc1..4150405 100644
--- a/chrome/noscript.jar!/locale/tr/noscript/about.properties
+++ b/chrome/noscript.jar!/locale/tr/noscript/about.properties
@@ -1,4 +1,4 @@
-extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Firefox için ek koruma eklentisi: NoScript eklentisi ile sadece güvendiğiniz sitelere JavaScript kullanımı için izin verebilir veya yasaklayabilirsiniz. Uzmanlar size firefon;un NoScript eklentisi ile daha güvenli olduğunu tavsiye edeceklerdir. :-)
+extensions.{73a6fe31-595d-460b-a920-fcc0f8843232}.description=Firefox'unuz için ek koruma: NoScript sadece güvendiğiniz sitelerde (örneğin bankanızın web sitesi) JavaScript, Java (ve diğer eklentiler) kullanımına izin verebilir veya yasaklayabilirsiniz. Beyaz liste tabanlı öncelikli engelleme yaklaşımı, güvenlik açıklarının yayılmasını hiçbir işlev kaybı olmadan önler (bilinen veya bilinmeyen!)… Uzmanlar Firefox'un NoScript eklentisi ile daha güvenli olduğunda hemfikir olacaklardır :-)
 aboutTitle=%S Hakkında
 extensionContributors=Emeği geçenler:
 extensionContributors.tip=Bu eklenti için teşekkür etmeniz gerekenler
@@ -7,9 +7,9 @@ changelog=Değişiklikler
 changelog.tip=Değişiklikleri göster
 license=Lisans
 license.tip=Son kullanıcı lisansını oku
-logo.tip=Eklentinin internet sayfasına git
-sponsor.tip=Sponsor sayfasına git
-informaction.tip=InformAction sayfasına git
-extensionHomepage.tip=Eklenti sayfasına git
-extensionCreator.tip=Yazarın sayfasına git
-version=Versiyon %S
+logo.tip=Uzantı ana sayfasına git
+sponsor.tip=Sponsor ana sayfasına git
+informaction.tip=InformAction ana sayfasına git
+extensionHomepage.tip=Uzantı ana sayfasına git
+extensionCreator.tip=Yazarın ana sayfasına git
+version=Sürüm %S
\ No newline at end of file
diff --git a/chrome/noscript.jar!/locale/tr/noscript/noscript.dtd b/chrome/noscript.jar!/locale/tr/noscript/noscript.dtd
index 37d4876..3b9d9ac 100644
--- a/chrome/noscript.jar!/locale/tr/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/tr/noscript/noscript.dtd
@@ -1,8 +1,8 @@
 <!ENTITY noscriptOptions "Seçenekler">
 <!ENTITY noscriptOptions.accesskey "S">
 <!ENTITY noscriptOptionsLong "NoScript Seçenekleri">
-<!ENTITY noscriptAbout "NoScript 2.9.5.2 Hakkında">
-<!ENTITY noscriptPermissionsText "Hangi web sayfalarında JavaScript'e izni vereceğinizi kolayca seçebilirsiniz. Lütfen adresi tam olarak girin ve 'İzin ver' düğmesine tıklayarak sayfanın JavaScript kullanmasına izin verin.">
+<!ENTITY noscriptAbout "NoScript 5.0.8.1 @VERSION@ Hakkında">
+<!ENTITY noscriptPermissionsText "Hangi web sayfalarında JavaScript'e izni vereceğinizi kolayca seçebilirsiniz. Lütfen adresi tam olarak girin (örn. "http://www.site.com" veya "site.com") ve 'İzin ver' düğmesine tıklayarak sayfanın JavaScript kullanmasına izin verin.">
 <!ENTITY noscriptWebAddress "Site adresi:">
 <!ENTITY noscriptAllow "İzin ver">
 <!ENTITY noscriptAllow.accesskey "z">
@@ -13,70 +13,70 @@
 <!ENTITY noscriptUntrust "Güvensiz Olarak İşaretle">
 <!ENTITY noscriptUntrust.accesskey "v">
 <!ENTITY noscriptRemoveSelected "Seçili Siteleri Kaldır">
-<!ENTITY noscriptGloballyEnabled "JavaScript'e Tüm Siteler İçin Açıldı (Tehlikelidir)">
+<!ENTITY noscriptGloballyEnabled "Betiklere Tüm Siteler İçin İzin Verilir (Tehlikelidir)">
 <!ENTITY noscriptAutoReload "İzinler değişince etkilenen sayfayı otomatik olarak tazele">
 <!ENTITY noscriptGeneral "Genel">
 <!ENTITY noscriptAppearance "Görünüm">
 <!ENTITY noscriptShow "Göster…">
-<!ENTITY noscriptCtxMenu "NoScript Menüsü">
-<!ENTITY noscriptStatusIcon "Durum çubugunda ikon olarak">
-<!ENTITY noscriptFullAddr "Tam adres (http://www.noscript.net)">
-<!ENTITY noscriptFullDom "Tam alanadı (www.noscript.net)">
-<!ENTITY noscriptBaseDom "Temel 2nci seviye alanadı (noscript.net)">
-<!ENTITY noscriptTempCmd "[…] geçici olarak izin ver">
+<!ENTITY noscriptCtxMenu "Bağlamsal menü">
+<!ENTITY noscriptStatusIcon "Durum çubugu simgesi">
+<!ENTITY noscriptFullAddr "Tam Adresler (http://www.noscript.net)">
+<!ENTITY noscriptFullDom "Tam Alan Adları (www.noscript.net)">
+<!ENTITY noscriptBaseDom "Temel 2. Seviye Alan Adları (noscript.net)">
+<!ENTITY noscriptTempCmd "[…] eylemine geçici olarak izin ver">
 <!ENTITY noscriptSound "Kodlar engellenince ses dosyası çal">
 <!ENTITY noscriptImport "İçe aktar">
 <!ENTITY noscriptImport.accesskey "K">
 <!ENTITY noscriptExport "Dışa aktar">
 <!ENTITY noscriptExport.accesskey "A">
-<!ENTITY noscriptNotify "Kod engellendiğinde uyar">
-<!ENTITY noscriptNotify.bottom "Uyarıları asağıdaki kenarda göster">
-<!ENTITY noscriptSound.choose "Seçin">
+<!ENTITY noscriptNotify "Betikler engellendiğinde ileti göster">
+<!ENTITY noscriptNotify.bottom "İletiyi aşağıdaki kenarda göster">
+<!ENTITY noscriptSound.choose "Seç">
 <!ENTITY noscriptSound.choose.accesskey "S">
 <!ENTITY noscriptSound.play "Çal">
 <!ENTITY noscriptSound.play.accesskey "a">
 <!ENTITY noscriptSound.reset "Varsayılanları yükle">
 <!ENTITY noscriptSound.reset.accesskey "R">
 <!ENTITY noscriptAdvanced "Gelişmiş">
-<!ENTITY noscriptAdditionalPermissions "Güvenli sayfalar için ilave haklar">
-<!ENTITY noscriptAllowClipboard "Kopyala ve Yapıştır işlemine izin ver">
-<!ENTITY noscriptAdditionalRestrictions "Güvensiz sayfalar için ilave kısıtlamalar">
+<!ENTITY noscriptAdditionalPermissions "Güvenli siteler için ek izinler">
+<!ENTITY noscriptAllowClipboard "Harici panoda zengin Kopyala ve Yapıştır işlemlerine izin ver">
+<!ENTITY noscriptAdditionalRestrictions "Güvensiz siteler için ek kısıtlamalar">
 <!ENTITY noscriptPlugins "Eklentiler">
 <!ENTITY noscriptContentBlocker "Bu sınırlamaları güvenilen sitelere de uygula">
-<!ENTITY noscriptForbidJava "Java™'yı engelle">
-<!ENTITY noscriptForbidXSLT "XSLT'yı engelle">
-<!ENTITY noscriptForbidSilverlight "Microsoft® Silverlight™'ı engelle">
-<!ENTITY noscriptForbidIFrames "Tüm <IFRAME>'leri engelle">
-<!ENTITY noscriptForbidFrames "Tüm <FRAME>'leri engelle">
-<!ENTITY noscriptForbidFonts "Yazıtipi @font-face tanımını engelle">
-<!ENTITY noscriptForbidMedia "Engelle <AUDIO> / <VIDEO>">
-<!ENTITY noscriptForbidFlash "Adobe® Flash®'ı engelle">
+<!ENTITY noscriptForbidJava "Java™'yı yasakla">
+<!ENTITY noscriptForbidXSLT "XSLT'yı yasakla">
+<!ENTITY noscriptForbidSilverlight "Microsoft® Silverlight™'ı yasakla">
+<!ENTITY noscriptForbidIFrames "<IFRAME>'leri yasakla">
+<!ENTITY noscriptForbidFrames "<FRAME>'leri yasakla">
+<!ENTITY noscriptForbidFonts "Yazıtipi @font-face tanımını yasakla">
+<!ENTITY noscriptForbidMedia "<AUDIO> / <VIDEO> yasakla">
+<!ENTITY noscriptForbidFlash "Adobe® Flash®'ı yasakla">
 <!ENTITY noscriptForbidPlugins "Diğer eklentileri yasakla">
-<!ENTITY noscriptForbidWebGL "Yazıtipi WebGL tanımını engelle">
-<!ENTITY noscriptReloadWarn "Bu ayarlar sadece yeni veya kendinizin yüklediği sayfalar için geçerlidir.">
-<!ENTITY noscriptConfirmUnblock "Bir nesneyi geçici olarak engellerken onay iste">
-<!ENTITY noscriptStatusLabel "Durum cubuğu etiketi">
+<!ENTITY noscriptForbidWebGL "Yazıtipi WebGL tanımını yasakla">
+<!ENTITY noscriptReloadWarn "Bu ayarlar sadece yeni veya kendinizin yeniden yüklediği sayfalar için geçerlidir.">
+<!ENTITY noscriptConfirmUnblock "Bir nesne engelini geçici olarak kaldırırken onay iste">
+<!ENTITY noscriptStatusLabel "Durum çubuğu etiketi">
 <!ENTITY noscriptForbidBookmarklets "Yer imlerini yasakla">
-<!ENTITY noscriptShowPlaceholder "Yer tutucuları göster">
+<!ENTITY noscriptShowPlaceholder "Yer tutucu simgelerini göster">
 <!ENTITY noscriptTruncateTitle "Belge başlığını kes">
 <!ENTITY noscriptFixLinks "JavaScript bağlantılarını düzeltmeye çalış">
 <!ENTITY noscriptAllowBookmarks "Yer imlerimde kayıtlı sitelere izin ver">
 <!ENTITY noscriptAllowViaBookmarks "Yer imlerinden açılan sitelere izin ver">
-<!ENTITY noscriptAllowPing "İzin ver <A PING…>">
+<!ENTITY noscriptAllowPing "<A PING…>'e izin ver">
 <!ENTITY noscriptAllowLocalLinks "Yerel bağlantılara izin ver">
-<!ENTITY noscriptForbidPing "Yasakla <A PING…>">
-<!ENTITY noscriptForbidMetaRefresh "<NOSCRIPT> elementleri içinde META yenidenyönlendirmelerini engelle">
+<!ENTITY noscriptForbidPing "<A PING…>'i yasakla">
+<!ENTITY noscriptForbidMetaRefresh "<NOSCRIPT> öğeleri içindeki META yeniden yönlendirmelerini engelle">
 <!ENTITY noscriptForbidMetaRefresh.accesskey "M">
 <!ENTITY noscriptNotifyMeta "Engellenen META yeniden yönlendirmeleri hakkında bilgilendir">
 <!ENTITY noscriptNotifyMeta.accesskey "M">
 <!ENTITY noscriptWhitelist "Beyazliste">
 <!ENTITY noscriptPermissions "İzinler">
 <!ENTITY noscriptRefresh "Tazele">
-<!ENTITY noscriptNotifications "Uyarılar">
-<!ENTITY noscriptToolbarToggle "Araç çubuğundaki NoScript düğmesine sol tıklayarak sitenin erişim haklarını değiştirebilirsiniz.">
-<!ENTITY noscriptTrusted "Güvenli">
-<!ENTITY noscriptUntrusted "Güvensiz">
-<!ENTITY noscriptUnknown "Bilinmiyor">
+<!ENTITY noscriptNotifications "Bildirimler">
+<!ENTITY noscriptToolbarToggle "Araç çubuğundaki NoScript düğmesine sol tıklayarak üst seviye sitenin erişim izinlerini değiştirebilirsiniz">
+<!ENTITY noscriptTrusted "Güvenilen">
+<!ENTITY noscriptUntrusted "Güvenilmeyen">
+<!ENTITY noscriptUnknown "Bilinmeyen">
 <!ENTITY noscriptAdd "Ekle">
 <!ENTITY noscriptAdd.accesskey "E">
 <!ENTITY noscriptClose "Kapat">
@@ -87,22 +87,22 @@
 <!ENTITY noscriptSitePolicies "Siteye özel ilkeler">
 <!ENTITY noscriptNselNever "<NOSCRIPT> öğelerini sakla">
 <!ENTITY noscriptNselForce "<SCRIPT>'den sonra oluşan <NOSCRIPT> öğelerini göster">
-<!ENTITY noscriptAutoAllowTopLevel "Varsayılan olarak aktif sitelere geçici izin verilir">
-<!ENTITY noscriptDescription "Firefox'unuz için ekstra güvenlik: NoScript seçiminize göre, sadece izin verdiğiniz sitelerde Java (ve diğer eklentilere) izin verebilir. Bu Beyazliste temelli öngörmeli engelleme tekniği güvenlik açıklarını(bilinen ve bilinmeyen) kapatmaya yararken işlevsellik kaybına neden olmaz… Uzmanlar katılacaklardır: Firefox NoScript ile birlikte daha güvenli :-)">
-<!ENTITY noscriptOptBlockCssScanners "CSS-temelli tarayıcıları engelle">
-<!ENTITY noscriptOptFilterXGet "Çapraz-site şüpeli isteklerini temizle">
+<!ENTITY noscriptAutoAllowTopLevel "Varsayılan olarak üst seviye sitelere geçici izin ver">
+<!ENTITY noscriptDescription "Firefox'unuz için ek koruma: NoScript sadece güvendiğiniz sitelerde (örneğin bankanızın web sitesi) JavaScript, Java (ve diğer eklentiler) kullanımına izin verebilir veya yasaklayabilirsiniz. Beyaz liste tabanlı öncelikli engelleme yaklaşımı, güvenlik açıklarının yayılmasını hiçbir işlev kaybı olmadan önler (bilinen veya bilinmeyen!)… Uzmanlar Firefox'un NoScript eklentisi ile daha güvenli olduğunda hemfikir olacaklardır :-)">
+<!ENTITY noscriptOptBlockCssScanners "CSS temelli tarayıcıları engelle">
+<!ENTITY noscriptOptFilterXGet "Çapraz-site şüpheli isteklerini temizle">
 <!ENTITY noscriptOptFilterXPost "Çapraz-site POST isteklerini GET'e çevir">
-<!ENTITY noscriptShowConsole "Konsolu göster">
-<!ENTITY noscriptShowConsole.accesskey "S">
+<!ENTITY noscriptShowConsole "Konsolu Göster…">
+<!ENTITY noscriptShowConsole.accesskey "K">
 <!ENTITY noscriptXss "XSS">
 <!ENTITY noscriptXss.accesskey "X">
 <!ENTITY noscriptXssFaq "XSS SSS…">
 <!ENTITY noscriptXssFaq.accesskey "S">
-<!ENTITY noscriptUnsafeReload "Güvensiz TekrarYükleme">
+<!ENTITY noscriptUnsafeReload "Güvensiz Tekrar Yükleme">
 <!ENTITY noscriptUnsafeReload.accesskey "Y">
-<!ENTITY noscriptXssExceptions "Anti-XSS Koruma Ayrıcalıklıları">
+<!ENTITY noscriptXssExceptions "Anti-XSS Koruma Ayrıcalıkları">
 <!ENTITY noscriptXssExceptions.description "Aşağıdaki tanımlara uyan hedefler XSS'e karşı KORUNMAYACAKLAR.">
-<!ENTITY noscriptMatchSample "Tanım uyum örneği:">
+<!ENTITY noscriptMatchSample "Eşleşen desen örneği:">
 <!ENTITY noscriptReset "Sıfırla">
 <!ENTITY noscriptReset.accesskey "s">
 <!ENTITY noscriptResetDef "Varsayılana Sıfırla">
@@ -110,59 +110,59 @@
 <!ENTITY noscriptOptionsWidth "40em">
 <!ENTITY noscriptRevokeTemp "Geçici İzinleri Kaldır">
 <!ENTITY noscriptRevokeTemp.accesskey "K">
-<!ENTITY noscriptNoUntrustedPlaceholder "Güvensiz işaretlenen sitelerden gelen nesnelerde yertutucuları gösterme">
+<!ENTITY noscriptNoUntrustedPlaceholder "Güvensiz işaretlenen sitelerden gelen nesnelerde yer tutucuları gösterme">
 <!ENTITY noscriptCollapseBlockedObjects "Engellenen nesneleri daralt">
 <!ENTITY noscriptExceptions "Hariç tutulanlar…">
 <!ENTITY noscriptBlockedObjects "Engellenen Nesneler">
 <!ENTITY noscriptAlwaysBlockUntrustedContent "Güvensiz olarak işaretlenen sitelerden gelen tüm nesneleri engelle">
-<!ENTITY noscriptTempAllowPage "Tüm bu sayfalara geçici izin ver">
+<!ENTITY noscriptTempAllowPage "Geçici olarak bu sayfanın tümüne izin ver">
 <!ENTITY noscriptTempAllowPage.accesskey "G">
-<!ENTITY noscriptAllowPage "Tüm bu sayfalara İzin Ver">
+<!ENTITY noscriptAllowPage "Bu sayfanın tümüne izin ver">
 <!ENTITY noscriptAllowPage.accesskey "z">
 <!ENTITY noscriptTempToPerm "Sayfa izinlerini kalıcı yap">
 <!ENTITY noscriptTempToPerm.accesskey "k">
 <!ENTITY noscriptHttps "HTTPS">
 <!ENTITY noscriptHttpsFaq "HTTPS SSS...">
 <!ENTITY noscriptHttpsFaq.accesskey "S">
-<!ENTITY noscriptHttps.behavior "Davranis">
-<!ENTITY noscriptHttps.cookies "Cerezler">
-<!ENTITY noscriptHttps.description "Aktif icerik guvenli baglanti uzerinden gelmezse(HTTPS) engelle:">
+<!ENTITY noscriptHttps.behavior "Davranış">
+<!ENTITY noscriptHttps.cookies "Çerezler">
+<!ENTITY noscriptHttps.description "Etkin web içeriği, güvenli bağlantı üzerinden gelmezse (HTTPS) engelle:">
 <!ENTITY noscriptHttps.never "Asla">
-<!ENTITY noscriptHttps.proxy "Proksi kullanirken(Tor kullanirken tavsiye edilir)">
-<!ENTITY noscriptHttps.always "Herzaman">
-<!ENTITY noscriptHttpsForced "Bu siteleri guvenli baglanti kullanmaya zorla(HTTPS):">
-<!ENTITY noscriptHttpsForcedExceptions "Bu siteleri guvenli baglanti(HTTPS) kullanmaya asla zorlama:">
-<!ENTITY noscriptSecureCookies "Otomatik Guvenli Cerez Yonetimini aktive et">
-<!ENTITY noscriptSecureCookiesForced "Bu sitelerin cerezlerinin HTTPS uzerinden gonderilmesine zorla:">
-<!ENTITY noscriptSecureCookiesExceptions "Guvensiz HTTPS uzerinden gonderilen cerezleri bu siteler icin yoksay:">
-<!ENTITY noscriptClearClickTitle "TemizTik Uyarisi">
-<!ENTITY noscriptClearClickHeader "Potansiyel TiklamaHilesi/YenidenAdresleme Denemesi">
-<!ENTITY noscriptClearClickDescription "NoScript kismen gizlenmis olan bir element ile fare veya klavyenin etkilesimini engelledi. Engellenmis ve temiz versiyonu arasinda gecis yapmak icin ustteki resme tiklayin.">
-<!ENTITY noscriptClearClickOpt "TemizTik korumasi yap...">
+<!ENTITY noscriptHttps.proxy "Vekil sunucu kullanırken (Tor kullanırken tavsiye edilir)">
+<!ENTITY noscriptHttps.always "Her zaman">
+<!ENTITY noscriptHttpsForced "Bu siteleri güvenli bağlantı kullanmaya zorla (HTTPS):">
+<!ENTITY noscriptHttpsForcedExceptions "Bu siteleri güvenli bağlantı (HTTPS) kullanmaya asla zorlama:">
+<!ENTITY noscriptSecureCookies "Otomatik Güvenli Çerez Yönetimini etkinleştir">
+<!ENTITY noscriptSecureCookiesForced "Bu sitelerin HTTPS üzerinden gönderilen çerezlerinin şifrelenmesini zorla:">
+<!ENTITY noscriptSecureCookiesExceptions "HTTPS üzerinden gönderilen güvensiz çerezleri bu siteler için yoksay:">
+<!ENTITY noscriptClearClickTitle "TemizTıklama Uyarısı">
+<!ENTITY noscriptClearClickHeader "Muhtemel Tıklama Hilesi/Yeniden Adresleme Denemesi">
+<!ENTITY noscriptClearClickDescription "NoScript kısmen gizlenmiş bir öğe ile fare veya klavyenin etkileşimini engelledi. Engellenmiş ve temiz sürüm arasında geçiş yapmak için üstteki resme tıklayın.">
+<!ENTITY noscriptClearClickOpt "Sayfalarda TemizTıklama koruması yap…">
 <!ENTITY noscriptClearClickReport "Bildir">
 <!ENTITY noscriptClearClickReport.accesskey "B">
-<!ENTITY noscriptClearClickReportId "Bildiri NO:">
-<!ENTITY noscriptTrustedPagesAdj "guvenilenlerde">
-<!ENTITY noscriptUntrustedPagesAdj "guvensizlerde">
-<!ENTITY noscriptKeepLocked "Bu nesneyi kilitli olarak birak (tavsiye edilir)">
+<!ENTITY noscriptClearClickReportId "Bildiri Kimliği:">
+<!ENTITY noscriptTrustedPagesAdj "güvenilenlerde">
+<!ENTITY noscriptUntrustedPagesAdj "güvenilmeyenlerde">
+<!ENTITY noscriptKeepLocked "Bu öğeyi kilitli olarak bırak (tavsiye edilir)">
 <!ENTITY noscriptEmbeddings "Gömülü Nesneler">
-<!ENTITY noscriptPrev "Previuous">
-<!ENTITY noscriptNext "Next">
+<!ENTITY noscriptPrev "Önceki">
+<!ENTITY noscriptNext "Sonraki">
 <!ENTITY noscriptFrameOptErr.title "Bu içerik bir çerçeve içerisinde gösterilemez">
-<!ENTITY noscriptFrameOptErr.desc "Güvenliğinizi korumak için, bu içeriğin sağlayıcısı bir çerçeve içerisinde gösterilmesine izin vermiyor">
+<!ENTITY noscriptFrameOptErr.desc "Güvenliğinizi korumak için, bu içeriğin sağlayıcısı bir çerçeve içerisinde gösterilmesine izin vermiyor.">
 <!ENTITY noscriptFrameOptErr.link "İçeriği yeni bir pencere içerisinde açmak için buraya tıklayın">
-<!ENTITY noscriptBookmarkSync "NoScript ayarlarımı kolay senkronizasyon için yer imlerine yedekle">
+<!ENTITY noscriptBookmarkSync "NoScript yapılandırmasını kolay eşitleme için yer imlerine yedekle">
 <!ENTITY noscriptShowReleaseNotes "Güncelleme olduğunda sürüm notlarını görüntüle">
 <!ENTITY ABE "ABE">
 <!ENTITY ABE.accesskey "A">
-<!ENTITY ABE.rulesets.label "Kurallar:">
-<!ENTITY ABE.enabled.label "ABE'yi Aktive et">
-<!ENTITY ABE.siteEnabled.label "Sitelerin kendi kuralkümelerini kullanmasına izin ver">
-<!ENTITY ABE.edit.label "Düzenle...">
+<!ENTITY ABE.rulesets.label "Kural Kümeleri:">
+<!ENTITY ABE.enabled.label "ABE (Uygulama Sınır Zorlayıcı) Etkinleştir">
+<!ENTITY ABE.siteEnabled.label "Sitelerin kendi kural kümelerini kullanmasına izin ver">
+<!ENTITY ABE.edit.label "Düzenle…">
 <!ENTITY ABE.edit.accesskey "D">
-<!ENTITY ABE.enable.label "T">
+<!ENTITY ABE.enable.label "Etkinleştir">
 <!ENTITY ABE.enable.accesskey "n">
-<!ENTITY ABE.disable.label "D">
+<!ENTITY ABE.disable.label "Devre Dışı Bırak">
 <!ENTITY ABE.disable.accesskey "E">
 <!ENTITY ABE.refresh.label "Yenile">
 <!ENTITY ABE.refresh.accesskey "Y">
@@ -170,22 +170,22 @@
 <!ENTITY noscriptRecentBlocked "Yakın zamanda engellenen siteler">
 <!ENTITY noscriptExternalFilters "Harici Süzgeçler">
 <!ENTITY noscriptEF.enable "Harici süzgeçleri etkinleştir">
-<!ENTITY noscriptEF.add "Yeni Süzgeç...">
-<!ENTITY noscriptEF.executable "Çalıştırılabilir dosya:">
+<!ENTITY noscriptEF.add "Yeni Süzgeç…">
+<!ENTITY noscriptEF.executable "Uygulama dosyası:">
 <!ENTITY noscriptEF.browse "Gözat...">
-<!ENTITY noscriptEF.contentType "Süzülecek içerik türü (MIME) (tam metin veya regex):">
+<!ENTITY noscriptEF.contentType "Süzülecek içerik türü (MIME) (tam metin veya düzenli ifade):">
 <!ENTITY noscriptEF.exceptions "Bu sitelerden gelen nesneleri süzme:">
-<!ENTITY noscriptEF.remove "Sil">
+<!ENTITY noscriptEF.remove "Kaldır">
 <!ENTITY noscriptPreset "Güvenlik Seviyesi">
 <!ENTITY noscriptPreset.off "Kapalı (ciddi misiniz?!)">
 <!ENTITY noscriptPreset.low "Kolay kullanım (Karaliste + Web Güvenliği)">
 <!ENTITY noscriptPreset.medium "Klasik (Beyazliste + Web Güvenliği)">
 <!ENTITY noscriptPreset.high "Kale (Tamamen kilitle)">
-<!ENTITY noscript.hoverUI "Fare ile NoScript ikonu üzerine gidince izinler listesini aç">
+<!ENTITY noscript.hoverUI "Fare ile NoScript simgesi üzerine gidince izinler listesini aç">
 <!ENTITY noscriptDonate "Bağış Yap">
 <!ENTITY noscriptDonate.accesskey "B">
-<!ENTITY noscriptAutoReload.currentTab "Reload the current tab only">
-<!ENTITY noscriptCascadePermissions "Cascade top document's permissions to 3rd party scripts">
-<!ENTITY noscriptRestrictSubdocScripting "Block scripting in whitelisted subdocuments of non-whitelisted pages">
-<!ENTITY noscriptGlobalHttpsWhitelist "Allow HTTPS scripts globally on HTTPS documents">
-<!ENTITY noscriptPermanentInPrivate "Permanent "Allow" commands in private windows">
+<!ENTITY noscriptAutoReload.currentTab "Sadece geçerli sekmeyi yeniden yükle">
+<!ENTITY noscriptCascadePermissions "Üst belge izinlerini 3. parti betiklere de indir">
+<!ENTITY noscriptRestrictSubdocScripting "Beyaz listede olmayan sayfaların, beyaz listedeki alt sayfalarında bulunan betikleri engelle">
+<!ENTITY noscriptGlobalHttpsWhitelist "HTTPS belgelerinde HTTPS betiklerine genel olarak izin ver">
+<!ENTITY noscriptPermanentInPrivate "Özel pencerelerdeki komutlara kalıcı olarak "İzin Ver"">
diff --git a/chrome/noscript.jar!/locale/tr/noscript/noscript.properties b/chrome/noscript.jar!/locale/tr/noscript/noscript.properties
index 682d45f..08edefd 100644
--- a/chrome/noscript.jar!/locale/tr/noscript/noscript.properties
+++ b/chrome/noscript.jar!/locale/tr/noscript/noscript.properties
@@ -1,56 +1,56 @@
-allowGlobal=JavaScript'e Tüm Sitelerde İzin Ver (Tehlikelidir)
-forbidGlobal=Sadece güvenli sayfalara JavaScript izni ver (tavsiye edilen)
-allowLocal=%S Sitesine izin ver
-allowTemp=%S Sayfasına Geçici İzin ver
-forbidLocal=%S Sayfasını Engelle
-allowed.glb=Dikkat! JavaScript Tüm Sitelerde Açık
-allowed.yes=JavaScript Şuan Açık
-allowed.prt=JavaScript Kısmen Açık
-allowed.no=JavaScript Şuanda Kapalı
-global.warning.title=Uyarı!
-global.warning.text=JavaScript bütün sayfalar için etkin.\n Bu potensiyel olarak güvenlik açığı oluşturabilir.\nDevam etmek istediğinizden emin misiniz?
-audio.samples=Ses dosyaları
-confirm=Emin misiniz?
-alwaysAsk=Herzaman onay iste
-notifyHide=%S saniye sonra gizle
-trust=%S adresine güven
-distrust=%S adresine güvenme
-untrustedOrigin=güvensiz bir kaynak
-xss.notify.generic=NoScript, %S adresinden olan potansiyel bir çapraz-site scriptini(XSS) filtreledi. Teknik detaylar Konsola kaydedildi.
-xss.notify.showConsole=Konsol'u göster…
-xss.notify.showConsole.accessKey=K
-xss.reason.filterXGet=Şüpheli istek temizlendi. Orjinal URL [%1$S] istenen sayfa [%2$S]. Temizlenen URL: [%3$S].)
-xss.reason.filterXGetRef=Şüpheli referer isteği temizlendi. URL [%1$S] istenilen sayfa [%2$S]. Temizlenen Referrer: [%3$S].)
-xss.reason.filterXPost=[%2$S] den [%1$S]'a şüpeli yükleme temizlendi: sadece-indirme GET isteğine çevrildi.
-unsafeReload.warning=GÜVENSİZ yenidenyükleme\n\n%1$S [%2$S]\n\nkaynak [%3$S]\n\nNoScript bu isteği koruyamayacak!\n
-metaRefresh.notify=NoScript <NOSCRIPT> içindeki bir <META> yenidenyönlendirmesini engelledi: %S sayfasına %S saniye sonraki.
-metaRefresh.notify.follow=YenidenYönlendirmeleri Kabulet
-metaRefresh.notify.follow.accessKey=Y
-notify.options=Seçenekler
-notify.options.accessKey=s
-reset.title=NoScript Ayar Sıfırlama
-reset.warning=Tüm NoScript ayarları ve site izinleri varsayılan değerlerine alınacaktır.\nBu işlem geri alınamaz.\nDevam etmek istediğinize emin misiniz?
-bookmarkSync.title=NoScript Ayar Yer İmi
-bookmarkSync.message=Bu Yer İminin açılması gerekli değildir, Weave veya XMarks eklentileri ile senkronizasyonda kullanmak içindir.
-bookmarkSync.confirm=NoScript \n%S.\ntarihinde kaydedilen bir ayar yerimi buldu. Yerel NoScript ayarınızın üzerine bu dosyayı yazmak istediğinize emin misiniz?
-ABE.notify=%1$S isteği ABE tarafından filtrelendi: <%2$S> %3$S
-ABE.chooseEditor=Lütfen ABE kuralkümeleri için bir metin editörü seçin
-ABE.syntaxError=ABE kuralkümelerinde sözdizimi hatası var!
-ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
-allowFrom=Buna hep izin ver: %S
-allowTempFrom=Buna geçici izin ver: %S
-siteInfo.confirm=%2$S sorgusunu yaparak \n"%1$S" sitesi hakkında bilgi istemek üzeresiniz.\nDevam etmek istiyor musunuz?
-siteInfo.tooltip=Site hakkında bilgi almak için orta tuşa veya Shift ile tıklayın
-ef.activate=Süz %S
-ef.options=%S seçenekler...
-ef.newName=Yeni süzgeç adını girin:
-ef.locateExe=%S süzgeci için yürütülebilir dosyayı seçin
-disable=Kapat %S
-disable.accessKey=K
-allowed.glb-emb=Scripts Globally Allowed but Some Embeddings Blocked
-removal.title=Security Downgrade Warning
-removal.message=By disabling or uninstalling NoScript, you give up ALL the protections provided by NoScript.\n\nIf you're just tired of handling script permissions site by site, there's a safer choice.\n\nNoScript can stop blocking scripts, except those you mark as untrusted, while still protecting you with the most advanced security countermeasures against XSS, Clickjacking, CSRF and other web threats.\n\nDo you really want to remove ALL the NoScript protections?\n
-removal.no=No, just stop blocking scripts
-removal.yes=Yes, remove ALL protections
-incompatibleOptions.title=Incompatible Options Warning
-incompatibleOptions="1$%S"\nis incompatible with "%2$S".\bDo you want to enable the former and disable the latter?
+allowGlobal=Betiklere Tüm Sitelerde İzin Ver (tehlikeli)
+forbidGlobal=Betikleri Tüm Sitelerde Yasakla (tavsiye edilen)
+allowLocal=%S adresine izin ver
+allowTemp=%S adresine geçici izin ver
+forbidLocal=%S adresini yasakla
+allowed.glb=Dikkat! Betiklere Tüm Sitelerde İzin Veriliyor
+allowed.yes=Betiklere Şu An İzin Veriliyor
+allowed.prt=Betiklere Şu An Kısmen İzin Veriliyor
+allowed.no=Betikler Şu An Yasaklı
+global.warning.title=Uyarı!
+global.warning.text=Betiklere genel olarak izin verilecek (her site için).\n Bu muhtemel tehlikeli bir eylemdir.\nDevam etmek istediğinizden emin misiniz?
+audio.samples=Ses örnekleri
+confirm=Emin misiniz?
+alwaysAsk=Her zaman onay iste
+notifyHide=%S saniye sonra gizle
+trust=%S adresine güven
+distrust=%S adresine güvenme
+untrustedOrigin=güvensiz bir kaynak
+xss.notify.generic=NoScript, %S adresinden olan potansiyel bir çapraz-site betiğini (XSS) filtreledi. Teknik detaylar Konsola kaydedildi.
+xss.notify.showConsole=Konsolu Göster…
+xss.notify.showConsole.accessKey=K
+xss.reason.filterXGet=Şüpheli istek temizlendi. Özgün URL [%1$S], [%2$S] sayfasından istendi. Temizlenen URL: [%3$S].
+xss.reason.filterXGetRef=Şüpheli yönlendirici isteği temizlendi. URL [%1$S], [%2$S] sayfasından istendi. Temizlenen Referrer: [%3$S].)
+xss.reason.filterXPost=[%2$S] adresinden [%1$S] üzerine şüpheli yükleme temizlendi: sadece-indir GET isteğine çevrildi.
+unsafeReload.warning=GÜVENSİZ yeniden yükleme\n\n%1$S [%2$S]\n\nKAYNAK [%3$S]\n\nNoScript bu isteği KORUMAYACAK!\n
+metaRefresh.notify=NoScript <NOSCRIPT> içindeki bir <META> yeniden yönlendirmesini engelledi: %S için son %S saniye.
+metaRefresh.notify.follow=Yeniden Yönlendirmeleri Takip Et
+metaRefresh.notify.follow.accessKey=Y
+notify.options=Seçenekler
+notify.options.accessKey=s
+reset.title=NoScript Sıfırla
+reset.warning=Tüm NoScript ayarları ve site izinleri varsayılan değerlerine alınacaktır.\nBu işlem geri alınamaz.\nDevam etmek istediğinize emin misiniz?
+bookmarkSync.title=NoScript Ayar Yer İmi
+bookmarkSync.message=Bu Yer İminin açılması gerekli DEĞİLDİR, fakat Weave veya XMarks uzantıları gibi hizmetler kullanarak eşitlemek içindir.
+bookmarkSync.confirm=NoScript %S tarihinde kaydedilen bir ayar yerimi buldu.\nYerel NoScript ayarınızın üzerine bu dosyayı yazmak istediğinize emin misiniz?
+ABE.notify=%1$S isteği ABE tarafından filtrelendi: <%2$S> %3$S
+ABE.chooseEditor=Lütfen ABE kural kümeleri için bir metin düzenleyici seçin
+ABE.syntaxError=ABE kural kümelerinde sözdizimi hatası var!
+ABE.wanIpAsLocal=WAN IP (%S) ∈ LOCAL
+allowFrom=Şuradan gelen her şeye izin ver: %S
+allowTempFrom=Şuradan gelen her şeye geçici izin ver: %S
+siteInfo.confirm=%2$S sorgusunu yaparak \n"%1$S" sitesi hakkında bilgi istemek üzeresiniz.\nDevam etmek istiyor musunuz?
+siteInfo.tooltip=Site hakkında bilgi almak için orta tuş ile tıklayın veya Üst Karakter tuşu ile tıklayın
+ef.activate=Süz: %S
+ef.options=%S seçenekleri…
+ef.newName=Yeni süzgeç adını girin:
+ef.locateExe=%S süzgeci için yürütülebilir dosyayı seçin
+disable=%S Devre Dışı Bırak
+disable.accessKey=K
+allowed.glb-emb=Betiklere Genel Olarak İzin Veriliyor ancak Bazı Gömülü Nesneler Engelli
+removal.title=Güvenlik Düşürme Uyarısı
+removal.message=NoScript'i devre dışı bırakarak veya kaldırarak, NoScript tarafından sağlanan TÜM korumalardan vazgeçiyorsunuz.\n\nHer site için betik izinlerini ayarlamaktan yorulduysanız, daha güvenli bir seçenek var.\n\nNoScript hala güvenilmez olarak işaretlediğiniz betikleri engellerken, en gelişmiş güvenlik önlemleri ile sizi XSS, Tıklama Hilesi (Clickjacking), CSRF ve diğer web tehditlerine karşı koruyabilir.\n\nGerçekten tüm NoScript korumalarını kaldırmak istiyor musunuz?\n
+removal.no=Hayır, sadece betikleri engellemeyi durdur
+removal.yes=Evet, TÜM korumaları kaldır
+incompatibleOptions.title=Uyumsuz Seçenek Uyarısı
+incompatibleOptions="1$%S"\n seçeneği "%2$S" ile uyumsuz.\bİlkini etkinleştirip ikinciyi devre dışı bırakmak ister misiniz?
\ No newline at end of file
diff --git a/chrome/noscript.jar!/locale/vi/noscript/noscript.dtd b/chrome/noscript.jar!/locale/vi/noscript/noscript.dtd
index 10373c4..98807ed 100644
--- a/chrome/noscript.jar!/locale/vi/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/vi/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "Tùy chọn">
 <!ENTITY noscriptOptions.accesskey "y">
 <!ENTITY noscriptOptionsLong "Tùy chọn cho NoScript">
-<!ENTITY noscriptAbout "Thông tin về NoScript 2.9.5.2">
+<!ENTITY noscriptAbout "Thông tin về NoScript 5.0.8.1">
 <!ENTITY noscriptPermissionsText "Bạn có thể chỉ định trang web nào được phép chạy script. Gõ địa chỉ hay tên miền (v.d. "http://www.nhaccodien.com" hay "nhaccodien.com") của trang mà bạn muốn cho phép, rồi nhấn Cho phép.">
 <!ENTITY noscriptWebAddress "Địa chỉ của trang web:">
 <!ENTITY noscriptAllow "Cho phép">
diff --git a/chrome/noscript.jar!/locale/zh-CN/noscript/noscript.dtd b/chrome/noscript.jar!/locale/zh-CN/noscript/noscript.dtd
index 4d0409c..7333ed8 100644
--- a/chrome/noscript.jar!/locale/zh-CN/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/zh-CN/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "选项...">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "NoScript 选项">
-<!ENTITY noscriptAbout "关于 NoScript 2.9.5.2">
+<!ENTITY noscriptAbout "关于 NoScript 5.0.8.1">
 <!ENTITY noscriptPermissionsText "您可以指定允许执行脚本的网站。请输入您想要允许的网站地址或域名(例如: “http://www.site.com”或者“site.com”)然后单击“允许”。">
 <!ENTITY noscriptWebAddress "网站地址:">
 <!ENTITY noscriptAllow "允许">
diff --git a/chrome/noscript.jar!/locale/zh-TW/noscript/noscript.dtd b/chrome/noscript.jar!/locale/zh-TW/noscript/noscript.dtd
index 81c640a..8ddbf71 100644
--- a/chrome/noscript.jar!/locale/zh-TW/noscript/noscript.dtd
+++ b/chrome/noscript.jar!/locale/zh-TW/noscript/noscript.dtd
@@ -1,7 +1,7 @@
 <!ENTITY noscriptOptions "選項…">
 <!ENTITY noscriptOptions.accesskey "O">
 <!ENTITY noscriptOptionsLong "NoScript 選項">
-<!ENTITY noscriptAbout "關於 NoScript 2.9.5.2">
+<!ENTITY noscriptAbout "關於 NoScript 5.0.8.1">
 <!ENTITY noscriptPermissionsText "您可以指定允許執行 JavaScript 的網站。輸入您要允許的網址或網域(例如 "http://www.site.com" 或 "site.com"),然後按下允許.">
 <!ENTITY noscriptWebAddress "網址:">
 <!ENTITY noscriptAllow "允許">
diff --git a/defaults/preferences/noscript.js b/defaults/preferences/noscript.js
index 352857f..087c1ed 100644
--- a/defaults/preferences/noscript.js
+++ b/defaults/preferences/noscript.js
@@ -201,8 +201,6 @@ pref("noscript.silverlightPatch", true);
 pref("noscript.allowURLBarJS", false);
 pref("noscript.allowURLBarImports", false);
 
-pref("noscript.docShellJSBlocking", 1);
-
 pref("noscript.hideOnUnloadRegExp", "video/.*");
 
 pref("noscript.untrusted", "");
@@ -270,10 +268,10 @@ pref("noscript.surrogate.digg.replacement", "window.location.href=document.query
 pref("noscript.surrogate.dimtus.sources", "!@^http://(?:dimtus|imageteam)\\.(?:com|org)/img-");
 pref("noscript.surrogate.dimtus.replacement", "document.querySelector('.overlay_ad').style.display='none'");
 pref("noscript.surrogate.ga.sources", "*.google-analytics.com");
-pref("noscript.surrogate.ga.replacement", "(function(){var _0=$S(function()_0),_u=function(){};_0.__noSuchMethod__=_0;('ga'in window)||(ga=_u);window.urchinTracker=window._u||_u;window._gaq=$S({__noSuchMethod__:_0,push:function(f){if(typeof f=='function')f();else if(f&&f.shift&&f[0]in this)this[f.shift()].apply(this,f)},_set:function(a,b){if(typeof b=='function')b()},_link:function(h){if(h)location.href=h},_linkByPost:function(f){if(f&&f.submit)f.submit();return true},_getLinkerUrl:funct [...]
+pref("noscript.surrogate.ga.replacement", "(function(){var _0=$S(function()_0),_u=function(){};_0.__noSuchMethod__=_0;('ga'in window)||(ga=_u);window.urchinTracker=window._u||_u;window._gaq=$S({__noSuchMethod__:_0,push:function(f){if(typeof f=='function')f();else if(f&&f.shift&&f[0]in this)this[f.shift()].apply(this,f)},_set:function(a,b){if(typeof b=='function')b()},_link:function(h){if(h)location.href=h},_linkByPost:function(f){if(f&&f.submit)f.submit();return true},_getLinkerUrl:funct [...]
 pref("noscript.surrogate.glinks.replacement", "['focus','mouseover','mousedown','click'].forEach(function(et){addEventListener(et,function(e){var a=e.target,href=a.href&&a.getAttribute&&a.getAttribute('href');if(href&&/^(?:http|\\/url)/.test(href)&&!a._href){a._href=a.href=a.href.replace(/.*\\/url.*[?&](?:url|q)=(http[^&]+).*/,function(a,b)decodeURIComponent(b));do{if(/\\brwt\\(/.test(a.getAttribute('onmousedown')))a.removeAttribute('onmousedown')}while((a=a.parentElement))}},true)})");
 pref("noscript.surrogate.glinks.sources", "!@^https?://[^/]+google\\..*/search");
-pref("noscript.surrogate.googletag.replacement", "if(typeof googletag==='undefined'){googletag={slots:{},cmd:$S({__noSuchMethod__:function()this,push:function(f){return f()}})};} googletag.defineSlot=function(){return $S({__noSuchMethod__:function(){},addService:function(){return $S({__noSuchMethod__:function(){return googletag.addService();}})},setTargeting:function(){return this}})};let _gt=googletag;googletag=new Proxy(_gt,{get:function(s,w,e){return w in s?s[w]:function(){return $S({ [...]
+pref("noscript.surrogate.googletag.replacement", "if(typeof googletag==='undefined'){googletag={slots:{},cmd:$S({__noSuchMethod__:function(){return $S(this)},push:function(f){return f()}})};}googletag.defineSlot=function(){return $S({__noSuchMethod__:function(){return $S(this)}})};let _gt=googletag;googletag=new Proxy(_gt,{get:function(s,w,e){return w in s?s[w]:function(){return $S({__noSuchMethod__:function(){return googletag;}})};}});let _renderedAds=new Proxy({},{get:function(a,b){ret [...]
 pref("noscript.surrogate.googletag.sources", ".googletagservices.com");
 pref("noscript.surrogate.gravatar.sources", ".gravatar.com");
 pref("noscript.surrogate.gravatar.replacement", "Gravatar=$S({my_hash:'', profile_cb:function(){}, init:function(){}, __noSuchMethod__:function(){}})");
@@ -433,3 +431,4 @@ pref("noscript.smartClickToPlay", true);
 
 pref("noscript.removalWarning", true);
 pref("noscript.middlemouse_temp_allow_main_site", true);
+pref("noscript.webext.enabled", true);
diff --git a/install.rdf b/install.rdf
index 0453fd9..b1b75e1 100644
--- a/install.rdf
+++ b/install.rdf
@@ -5,7 +5,7 @@
 
    <em:id>{73a6fe31-595d-460b-a920-fcc0f8843232}</em:id>
    <em:name>NoScript</em:name>
-   <em:version>2.9.5.2</em:version>
+   <em:version>5.0.8.1</em:version>
    <em:description>Extra protection for your Firefox: NoScript allows JavaScript, Java (and other plugins) only for trusted domains of your choice (e.g. your home-banking web site). This whitelist based pre-emptive blocking approach  prevents exploitation of security vulnerabilities (known and even unknown!) with no loss of functionality... Experts will agree: Firefox is really safer with NoScript :-)</em:description>
    <em:creator>Giorgio Maone</em:creator>
    <em:type>2</em:type>
@@ -15,7 +15,7 @@
    <em:contributor>Asaf Bartov & baryoni (Hebrew translation)</em:contributor>
    <em:contributor>Alf and Liesbeth (Dutch translation)</em:contributor>
    <em:contributor>Alexander Sokolov, Sergei Smirnov and negodnik (Russian translation)</em:contributor>
-   <em:contributor>Batuhan Çetin and eveterinary (Turkish translation)</em:contributor>
+   <em:contributor>Batuhan Çetin, Volkan Gezer and eveterinary (Turkish translation)</em:contributor>
    <em:contributor>Baurzhan Muftakhidinov (Kazakh translation)</em:contributor>
    <em:contributor>Beerboy & Haebaru (Japanese translation)</em:contributor>
    <em:contributor>Carsten Winkler (Danish translation)</em:contributor>
@@ -54,7 +54,7 @@
    <em:contributor>Stiepan A. Kovac (Croatian translation)</em:contributor>
    <em:contributor>swarnava (Bengali translation)</em:contributor>
    <em:contributor>Tomaz Macus (Slovenian translation)</em:contributor>
-   <em:contributor>Thomas Weber & Volker Hable (German translation)</em:contributor>
+   <em:contributor>Thomas, milupo & Volker Hable (German translation)</em:contributor>
    <em:contributor>tonynguyen and loveleeyoungae (Vietnamese translation)</em:contributor>
    <em:contributor>x10firefox and Ultravioletu (Romanian translation)</em:contributor>
    <em:contributor>Xavier Robin & BlackJack (French translation)</em:contributor>
@@ -65,6 +65,7 @@
    <em:icon64URL>chrome://noscript/skin/icon64.png</em:icon64URL>
    <em:aboutURL>chrome://noscript/content/about.xul</em:aboutURL>
    <em:multiprocessCompatible>true</em:multiprocessCompatible>
+   <em:hasEmbeddedWebExtension>true</em:hasEmbeddedWebExtension>
    <!-- Firefox -->
    <em:targetApplication>
      <Description>
@@ -74,16 +75,25 @@
      </Description>
    </em:targetApplication>
 
-
    <!-- SeaMonkey -->
    <em:targetApplication>
       <Description>
         <em:id>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</em:id>
-        <em:minVersion>2.43</em:minVersion>
+        <em:minVersion>2.42</em:minVersion>
         <em:maxVersion>*</em:maxVersion>
       </Description>
    </em:targetApplication>
-
+ <!-- Pale Moon -->
+   <em:targetApplication>
+     <Description>
+     <em:id>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</em:id>
+     <em:minVersion>27.0.2</em:minVersion>
+     <em:maxVersion>*</em:maxVersion>
+     </Description>
+   </em:targetApplication>
  </Description>
 
+   
+
+
 </RDF>
diff --git a/webextension/background.js b/webextension/background.js
new file mode 100644
index 0000000..849fac1
--- /dev/null
+++ b/webextension/background.js
@@ -0,0 +1,70 @@
+var policy;
+var webRequestInitialized = false;
+
+function initWebRequest() {
+  if (webRequestInitialized) return;
+  webRequestInitialized = true;
+  browser.webRequest.onHeadersReceived.addListener(setCSP,
+    {urls: ["<all_urls>"]},
+    ["blocking", "responseHeaders"]
+  );
+  console.log(`NoScript WebExt webRequest initialized`);
+}
+var legacyPort = browser.runtime.connect({name: "legacy"});
+legacyPort.onMessage.addListener(msg => {
+
+  switch(msg.type) {
+    case "configure":
+      initWebRequest();
+      policy = msg.policy;
+    break;
+    case "saveData":
+      browser.storage.local.set(msg.data);
+    break;
+
+    case "dumpData":
+      browser.storage.local.get(null, items => console.log(items));
+    break;
+  }
+});
+
+const CSP = {
+  name: "Content-Security-Policy",
+  value: "x-NoScript-start; script-src 'none'; x-NoScript-stop;"
+};
+
+function isJSEnabled(urlString) {
+  if (!(policy && policy.enforced)) {
+    return true;
+  }
+  let url = new URL(urlString);
+  return url.origin in policy.origins && policy.origins[url.origin].js;
+}
+
+function setCSP(e) {
+  let header;
+  for (let h of e.responseHeaders) {
+    if (h.name === CSP.name) {
+      while(e.value.includes(CSP.value)) {
+        h.value = h.value.replace(CSP.value, '');
+        if (/^\s*$/.test(h.value)) {
+          header = h;
+          h.value = "";
+        }
+      }
+    }
+  }
+  if (!isJSEnabled(e.url)) {
+    if (header) {
+      header.value = CSP.value;
+    } else {
+      e.responseHeaders.push(header = CSP);
+    }
+  }
+  return header ? {responseHeaders: e.responseHeaders} : null;
+}
+
+
+browser.runtime.sendMessage("READY");
+console.log("NoScript WebExt Ready");
+
diff --git a/webextension/manifest.json b/webextension/manifest.json
new file mode 100644
index 0000000..7c665df
--- /dev/null
+++ b/webextension/manifest.json
@@ -0,0 +1,15 @@
+{
+  "manifest_version": 2,
+  "name": "NoScript",
+  "version": "10.1.0",
+  "description": "NoScript Security Suite",
+
+  "permissions": [
+    "storage", "webNavigation",
+    "webRequest", "webRequestBlocking", "<all_urls>"
+  ],
+
+  "background": {
+    "scripts": ["background.js"]
+  }
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/noscript.git



More information about the Pkg-mozext-commits mailing list