diff options
author | Jesús <heckyel@hyperbola.info> | 2022-04-06 10:38:06 +0800 |
---|---|---|
committer | Jesús <heckyel@hyperbola.info> | 2022-04-06 10:38:06 +0800 |
commit | 8aeb670be1d252807252ee2bfe99b15b81c3e28d (patch) | |
tree | ced0973165449d620c5c40876c37ab16b17655f9 | |
parent | 5aa99a2ea2b683ba35eb36dfc54efd79f3cfcb85 (diff) | |
download | ematrix-8aeb670be1d252807252ee2bfe99b15b81c3e28d.tar.lz ematrix-8aeb670be1d252807252ee2bfe99b15b81c3e28d.tar.xz ematrix-8aeb670be1d252807252ee2bfe99b15b81c3e28d.zip |
update from upstream
117 files changed, 8842 insertions, 12400 deletions
@@ -26,7 +26,7 @@ # 2) It gives some flexibility in that files can be created or deleted # freely as long as they are not part of any of these lists -VERSION := 3.1.2 +VERSION := 3.1.3 help: @echo 'Makefile for generate eMatrix ' @@ -109,30 +109,18 @@ LOC1 := locale/en/messages.properties locale/bg/messages.properties \ locale/cs/messages.properties locale/de/messages.properties \ locale/el/messages.properties -LOC2 := locale/eo/messages.properties locale/es/messages.properties \ - locale/et/messages.properties locale/fa/messages.properties \ - locale/fi/messages.properties locale/fil/messages.properties \ - locale/fr/messages.properties locale/he/messages.properties +LOC2 := locale/es/messages.properties locale/fr/messages.properties \ + locale/hu/messages.properties locale/it/messages.properties \ + locale/ko/messages.properties locale/nl/messages.properties \ + locale/pl/messages.properties -LOC3 := locale/hi/messages.properties locale/hu/messages.properties \ - locale/id/messages.properties locale/it/messages.properties \ - locale/ja/messages.properties locale/ko/messages.properties \ - locale/lv/messages.properties locale/ml/messages.properties - -LOC4 := locale/nb/messages.properties locale/nl/messages.properties \ - locale/pl/messages.properties \ - locale/pt-BR/messages.properties \ +LOC3 := locale/pt-BR/messages.properties \ locale/pt-PT/messages.properties \ - locale/ro/messages.properties locale/ru/messages.properties \ - locale/sl/messages.properties - -LOC5 := locale/sr/messages.properties locale/sv/messages.properties \ - locale/te/messages.properties locale/tr/messages.properties \ - locale/uk/messages.properties locale/vi/messages.properties \ - locale/zh-CN/messages.properties \ - locale/zh-TW/messages.properties + locale/ru/messages.properties locale/sv/messages.properties \ + locale/tr/messages.properties locale/uk/messages.properties \ + locale/zh-CN/messages.properties -LOCALE := $(LOC1) $(LOC2) $(LOC3) $(LOC4) $(LOC5) +LOCALE := $(LOC1) $(LOC2) $(LOC3) # The js folder is split into parts because it's a long list # and it's somewhat easier to read this way diff --git a/assets/assets.json b/assets/assets.json index 082e8a6..bee211a 100644 --- a/assets/assets.json +++ b/assets/assets.json @@ -36,7 +36,7 @@ "https://someonewhocares.org/hosts/hosts", "assets/thirdparties/someonewhocares.org/hosts/hosts.txt" ], - "supportURL": "https://someonewhocares.org/hosts/" + "supportURL": "http://someonewhocares.org/hosts/" }, "mvps-0": { "content": "filters", diff --git a/bootstrap.js b/bootstrap.js index 0127d89..c49d77b 100644 --- a/bootstrap.js +++ b/bootstrap.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -36,7 +36,7 @@ let version; const restartListener = { get messageManager() { return Cc['@mozilla.org/parentprocessmessagemanager;1'] - .getService(Ci.nsIMessageListenerManager); + .getService(Ci.nsIMessageListenerManager); }, receiveMessage: function() { @@ -64,20 +64,21 @@ function startup(data, reason) { function createBgProcess(parentDocument) { bgProcess = parentDocument - .documentElement - .appendChild(parentDocument - .createElementNS('http://www.w3.org/1999/xhtml', - 'iframe')); + .documentElement + .appendChild(parentDocument + .createElementNS('http://www.w3.org/1999/xhtml', + 'iframe')); bgProcess.setAttribute('src', - 'chrome://ematrix/content/background.html#' - + version); + 'chrome://ematrix/content/background.html#' + + version); + // https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIMessageListenerManager#addMessageListener%28%29 // "If the same listener registers twice for the same message, the // "second registration is ignored." restartListener - .messageManager - .addMessageListener('ematrix-restart', restartListener); + .messageManager + .addMessageListener('ematrix-restart', restartListener); } function getWindowlessBrowserFrame(appShell) { @@ -96,8 +97,8 @@ function getWindowlessBrowserFrame(appShell) { onStateChange: function(wbp, request, stateFlags, status) { if (!request) { - return; - } + return; + } if (stateFlags & Ci.nsIWebProgressListener.STATE_STOP) { webProgress.removeProgressListener(windowlessBrowserPL); @@ -108,10 +109,10 @@ function getWindowlessBrowserFrame(appShell) { }; webProgress.addProgressListener(windowlessBrowserPL, - Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT); + Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT); windowlessBrowser.document.location = - "data:application/vnd.mozilla.xul+xml;charset=utf-8,<window%20id='ematrix-win'/>"; + "data:application/vnd.mozilla.xul+xml;charset=utf-8,<window%20id='ematrix-win'/>"; } function waitForHiddenWindow() { @@ -123,7 +124,7 @@ function waitForHiddenWindow() { try { hiddenDoc = appShell.hiddenDOMWindow && - appShell.hiddenDOMWindow.document; + appShell.hiddenDOMWindow.document; } catch (ex) { } @@ -205,7 +206,7 @@ function shutdown(data, reason) { if (windowlessBrowser !== null) { // close() does not exist for older versions of Firefox. - // ηMatrix: how old? But keeping it doesn't really hurt that much. + // ηMatrix: how old? But keeping it doesn't really hurt that much. if (typeof windowlessBrowser.close === 'function') { windowlessBrowser.close(); } @@ -219,22 +220,22 @@ function shutdown(data, reason) { // Remove the restartObserver only when the extension is being disabled restartListener - .messageManager - .removeMessageListener('ematrix-restart', restartListener); + .messageManager + .removeMessageListener('ematrix-restart', restartListener); } function install(data, reason) { // https://bugzil.la/719376 Cc['@mozilla.org/intl/stringbundle;1'] - .getService(Ci.nsIStringBundleService) - .flushBundles(); + .getService(Ci.nsIStringBundleService) + .flushBundles(); if (reason === ADDON_UPGRADE) { - let Services = - Cu.import('resource://gre/modules/Services.jsm', null).Services + let Services = + Cu.import('resource://gre/modules/Services.jsm', null).Services - Services.obs.notifyObservers(null, 'chrome-flush-caches', null); - Services.obs.notifyObservers(null, 'message-manager-flush-caches', null); + Services.obs.notifyObservers(null, 'chrome-flush-caches', null); + Services.obs.notifyObservers(null, 'message-manager-flush-caches', null); } } @@ -246,6 +247,6 @@ function uninstall(data, aReason) { // To cleanup vAPI.localStorage in vapi-common.js, aka // "extensions.ematrix.*" in `about:config`. Cu.import('resource://gre/modules/Services.jsm', null) - .Services.prefs.getBranch('extensions.ematrix') - .deleteBranch(''); + .Services.prefs.getBranch('extensions.ematrix.') + .deleteBranch(''); } diff --git a/css/cloud-ui.css b/css/cloud-ui.css index 64dea40..2e53f70 100644 --- a/css/cloud-ui.css +++ b/css/cloud-ui.css @@ -1,7 +1,7 @@ /******************************************************************************* ηMatrix - a browser extension to black/white list requests. - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -26,10 +26,10 @@ margin: 0.5em 0; padding: 1em 1em 0 1em; position: relative; -} + } #cloudWidget.hide { display: none; -} + } #cloudWidget > button { display: inline-block; font-family: FontAwesome; @@ -40,30 +40,30 @@ padding: 0.2em 0.25em 0.1em 0.25em; position: relative; vertical-align: baseline; -} + } #cloudWidget > button[disabled] { visibility: hidden; -} + } #cloudWidget > button.error { color: red; -} + } #cloudPush:after { content: '\f0ee'; -} + } #cloudPull:before, #cloudPullAndMerge:before { content: '\f0ed'; } #cloudPullAndMerge { margin: 0 0.25em; -} + } #cloudPullAndMerge:after { content: '\f067'; font-size: 50%; position: absolute; right: 0; top: 10%; -} + } #cloudWidget > span { color: gray; display: inline-block; @@ -72,15 +72,15 @@ padding: 0; vertical-align: bottom; white-space: pre; -} + } #cloudError { color: red; margin: 0; padding: 0.5em 0; -} + } #cloudError > span { font-size: x-small; -} + } #cloudWidget > #cloudCog { cursor: pointer; display: inline-block; @@ -90,16 +90,16 @@ padding: 4px; position: absolute; top: 0; -} + } body[dir="ltr"] #cloudWidget > #cloudCog { right: 0; -} + } body[dir="rtl"] #cloudWidget > #cloudCog { left: 0; -} + } #cloudWidget > #cloudCog:hover { opacity: 1; -} + } #cloudWidget > #cloudOptions { align-items: center; -webkit-align-items: center; @@ -113,14 +113,14 @@ body[dir="rtl"] #cloudWidget > #cloudCog { right: 0; top: 0; z-index: 2000; -} + } #cloudWidget > #cloudOptions.show { display: flex; display: -webkit-flex; -} + } #cloudWidget > #cloudOptions > div { background-color: white; border-radius: 3px; padding: 1em; text-align: center; -} + } diff --git a/css/common.css b/css/common.css index 7553c0e..9f1a4ab 100644 --- a/css/common.css +++ b/css/common.css @@ -1,7 +1,7 @@ /******************************************************************************* ηMatrix - a browser extension to black/white list requests. - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://notabug.org/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ diff --git a/css/dashboard-common.css b/css/dashboard-common.css index f138794..44ec471 100644 --- a/css/dashboard-common.css +++ b/css/dashboard-common.css @@ -1,7 +1,7 @@ /******************************************************************************* ηMatrix - a browser extension to black/white list requests. - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -26,44 +26,44 @@ body { margin: 0; padding: 0 0.5em 0 0.5em; font: 15px/1.4 sans-serif; -} + } body > *:first-child { margin-top: 0; -} + } h2, h3 { margin: 1em 0; font-family: sans-serif; -} + } h2 { font-size: 18px; -} + } h2:nth-of-type(1) { margin-top: 0; -} + } h3 { font-size: 16px; -} + } h2 + * { padding: 0; -} + } html.ltr h2 + * { margin: 0 0 0 1em; -} + } html.rtl h2 + * { margin: 0 1em 0 0; -} + } a { text-decoration: none; -} + } button { padding: 0.3em 0.5em; -} + } input[disabled] + label { color: gray; -} + } .para { width: 40em; -} + } .whatisthis { margin: 0 0 0 8px; @@ -72,13 +72,13 @@ input[disabled] + label { padding: 0 0 4px 0; cursor: pointer; opacity: 0.4; -} + } .whatisthis:before { content: '\f059'; -} + } .whatisthis:hover { opacity: 1.0; -} + } .whatisthis-expandable { background-color: #F8F8F8; border: 1px dotted #aaa; @@ -87,19 +87,19 @@ input[disabled] + label { margin: 0.5em 0 1em 1.25em; padding: 0.5em; white-space: pre-line; -} + } .whatisthis-expandable > p { margin-top: 1em; margin-bottom: 0; -} + } .whatisthis-expandable > p:first-child { margin-top: 0; -} + } .whatisthis-expandable.whatisthis-expanded { display: block; -} + } .warn { margin: 0; padding: 5px; background-color: #FEDAE0; -} + } diff --git a/css/dashboard.css b/css/dashboard.css index 67a266f..8198ac9 100644 --- a/css/dashboard.css +++ b/css/dashboard.css @@ -1,7 +1,7 @@ /******************************************************************************* ηMatrix - a browser extension to black/white list requests. - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -29,7 +29,7 @@ body { width: 100vw; height: 100vh; overflow: hidden; -} + } #dashboard-nav { margin: 0; border: 0; @@ -39,18 +39,18 @@ body { width: 100vw; height: 50px; z-index: 10; -} + } #dashboard-nav-widgets { margin: 0; border-bottom: 1px solid #ccc; padding: 4px 0 0 0; white-space: nowrap; background-color: white; -} + } #dashboard-nav-widgets span { padding: 0 0.5em; font-size: larger; -} + } .tabButton { margin: 0; border: 1px solid #ccc; @@ -65,17 +65,17 @@ body { font: inherit; cursor: pointer; text-decoration: none; -} + } .tabButton:focus { outline: 0; -} + } .tabButton:active,.tabButton:visited { color: inherited; -} + } .tabButton.selected { border-bottom: 1px solid white; background-color: white; -} + } iframe { margin: 0; border: 0; @@ -86,4 +86,4 @@ iframe { top: 50px; width: 100%; height: calc(100% - 50px); -} + } diff --git a/css/hosts-files.css b/css/hosts-files.css index fa3e07b..8c71ad8 100644 --- a/css/hosts-files.css +++ b/css/hosts-files.css @@ -1,7 +1,7 @@ /******************************************************************************* ηMatrix - a browser extension to black/white list requests. - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -29,74 +29,74 @@ 67.5% { transform: rotate(225deg); -webkit-transform: rotate(225deg); } 75% { transform: rotate(270deg); -webkit-transform: rotate(270deg); } 87.5% { transform: rotate(315deg); -webkit-transform: rotate(315deg); } -} + } ul { padding: 0; list-style-type: none; -} + } ul#options { margin-top: 0; -} + } ul#options li { margin-bottom: 0.5em; -} + } ul#lists { margin: 0.5em 0 0 0; padding: 0; -} + } li.listEntry { margin: 0 auto 0 auto; padding: 0.2em 0; -} + } body[dir="ltr"] li.listEntry { margin-left: 1em; margin-right: 0em; -} + } body[dir="rtl"] li.listEntry { margin-left: 0em; margin-right: 1em; -} + } li.listEntry > * { margin-right: 0.5em; text-indent: 0; unicode-bidi: embed; -} + } li.listEntry > a:nth-of-type(2) { font-size: 13px; opacity: 0.5; -} + } li.listEntry.toRemove > input[type="checkbox"] { visibility: hidden; -} + } li.listEntry.toRemove > a.content { text-decoration: line-through; -} + } li.listEntry > .fa { color: inherit; display: none; font-size: 110%; opacity: 0.5; vertical-align: baseline; -} + } li.listEntry > a.fa:hover { opacity: 1; -} + } li.listEntry.support > a.support { display: inline-block; -} + } li.listEntry > a.remove, li.listEntry > a.remove:visited { color: darkred; -} + } li.listEntry.external > a.remove { display: inline-block; -} + } li.listEntry.mustread > a.mustread { display: inline-block; -} + } li.listEntry.mustread > a.mustread:hover { color: mediumblue; -} + } li.listEntry > .counts { display: none; font-size: smaller; @@ -111,54 +111,54 @@ li.listEntry span.status { } li.listEntry span.status:hover { opacity: 1; -} + } li.listEntry span.unsecure { - color: darkred; -} + color: #444; + } li.listEntry.unsecure > input[type="checkbox"]:checked ~ span.unsecure { display: inline-block; -} + } li.listEntry span.failed { color: darkred; -} + } li.listEntry.failed span.failed { display: inline-block; -} + } li.listEntry span.cache { cursor: pointer; -} + } li.listEntry.cached:not(.obsolete) > input[type="checkbox"]:checked ~ span.cache { display: inline-block; -} + } li.listEntry span.obsolete { color: hsl(36, 100%, 40%); -} + } body:not(.updating) li.listEntry.obsolete > input[type="checkbox"]:checked ~ span.obsolete { display: inline-block; -} + } li.listEntry span.updating { transform-origin: 50% 46%; -} + } body.updating li.listEntry.obsolete > input[type="checkbox"]:checked ~ span.updating { animation: spin 1s step-start infinite; display: inline-block; -} + } .dim { opacity: 0.5; -} + } #externalLists { margin: 2em auto 0 auto; -} + } body[dir="ltr"] #externalListsDiv { margin-left: 1em; -} + } body[dir="rtl"] #externalListsDiv { margin-right: 1em; -} + } #externalHostsFiles { box-sizing: border-box; font-size: smaller; width: 100%; height: 12em; white-space: pre; -} + } diff --git a/css/legacy-toolbar-button.css b/css/legacy-toolbar-button.css index b3cbd8a..03411ed 100644 --- a/css/legacy-toolbar-button.css +++ b/css/legacy-toolbar-button.css @@ -1,7 +1,7 @@ /******************************************************************************* ηMatrix - a browser extension to black/white list requests. - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ diff --git a/css/logger-ui.css b/css/logger-ui.css index 41448a7..387b3ff 100644 --- a/css/logger-ui.css +++ b/css/logger-ui.css @@ -1,7 +1,7 @@ /******************************************************************************* ηMatrix - a browser extension to black/white list requests. - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -30,7 +30,7 @@ body { overflow-x: hidden; padding: 0; width: 100%; -} + } #toolbar { background-color: white; border: 0; @@ -44,7 +44,7 @@ body { top: 0; width: 100%; z-index: 10; -} + } #toolbar .button { background-color: white; border: none; @@ -55,53 +55,53 @@ body { font-size: 150%; margin: 0; padding: 8px; -} + } #toolbar .button.disabled { opacity: 0.2; pointer-events: none; -} + } #toolbar .button:hover { background-color: #eee; -} + } #toolbar > div { white-space: nowrap; -} + } #toolbar > div:first-of-type { font-size: 120%; -} + } #toolbar > div > * { vertical-align: middle; -} + } #pageSelector { width: 28em; padding: 0.2em 0; -} + } body #compactViewToggler.button:before { content: '\f102'; -} + } body.compactView #compactViewToggler.button:before { content: '\f103'; -} + } #filterButton { opacity: 0.25; -} + } body.f #filterButton { opacity: 1; -} + } #filterInput.bad { background-color: #fee; -} + } #maxEntries { margin: 0 2em; -} + } input:focus { background-color: #ffe; -} + } #content { font-family: "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 13px; width: 100%; -} + } #content table { border: 0; @@ -109,43 +109,43 @@ input:focus { direction: ltr; table-layout: fixed; width: 100%; -} + } #content table > colgroup > col:nth-of-type(1) { width: 4.6em; -} + } #content table > colgroup > col:nth-of-type(2) { width: 2.2em; -} + } #content table > colgroup > col:nth-of-type(3) { width: 2.2em; -} + } #content table > colgroup > col:nth-of-type(4) { width: 5.4em; -} + } #content table > colgroup > col:nth-of-type(5) { width: calc(100% - 14.4em); -} + } #content table tr { background-color: #fafafa; -} + } body.f table tr.f { display: none; -} + } #content table tr:nth-of-type(2n+1) { background-color: #eee; -} + } #content table tr.cat_info { color: #00f; -} + } #content table tr.blocked { color: #f00; -} + } #content table tr.doc { background-color: #666; color: white; text-align: center; -} + } body #content td { border: 1px solid #ccc; @@ -155,61 +155,61 @@ body #content td { white-space: normal; word-break: break-all; word-wrap: break-word; -} + } #content table tr td:first-of-type { border-left: none; -} + } #content table tr td:last-of-type { border-right: none; -} + } body.compactView #content tr:not(.vExpanded) td { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; -} + } #content table tr td:nth-of-type(1) { cursor: default; text-align: right; white-space: nowrap; -} + } #content table tr td:nth-of-type(2) { text-align: center; white-space: nowrap; -} + } #content table tr.tab_bts > td:nth-of-type(2):before { content: '\f070'; font: 1em FontAwesome; -} + } #content table tr.tab:not(.canMtx) { opacity: 0.3; -} + } #content table tr.tab:not(.canMtx):hover { opacity: 0.7; -} + } #content table tr.tab:not(.canMtx) > td:nth-of-type(2):before { content: '\f00d'; font: 1em FontAwesome; -} + } body:not(.popupOn) #content table tr.canMtx td:nth-of-type(2) { cursor: zoom-in; -} + } body:not(.popupOn) #content table tr.canMtx td:nth-of-type(2):hover { background: #ccc; -} + } #content table tr.cat_net td:nth-of-type(3) { font: 12px monospace; text-align: center; white-space: nowrap; -} + } #content table tr.cat_net td:nth-of-type(5) { -} + } #content table tr.cat_net td:nth-of-type(5) > span > * { opacity: 0.6; -} + } #content table tr.cat_net td:nth-of-type(5) > span > b:first-of-type { opacity: 1; -} + } #popupContainer { background: white; @@ -220,36 +220,36 @@ body:not(.popupOn) #content table tr.canMtx td:nth-of-type(2):hover { right: 1em; top: 0; z-index: 200; -} + } body.popupOn #popupContainer { display: block; -} + } #popupContainer > div { background: #888; border: 0; -} + } #popupContainer > div { text-align: right; -} + } #popupContainer > div > span { color: #ccc; cursor: pointer; display: inline-block; font: 14px FontAwesome; padding: 3px; -} + } #popupContainer > div > span:hover { color: white; -} + } #popupContainer > iframe { border: 0; padding: 0; margin: 0; width: 100%; -} + } #popupContainer.hide { width: 6em !important; -} + } #popupContainer.hide > iframe { display: none; -} + } diff --git a/css/popup.css b/css/popup.css index a070e1d..9f466f2 100644 --- a/css/popup.css +++ b/css/popup.css @@ -1,7 +1,7 @@ /******************************************************************************* ηMatrix - a browser extension to black/white list requests. - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -33,19 +33,19 @@ body { overflow-y: auto; padding: 0; position: relative; -} + } *:focus { outline: none; -} + } a { color: inherit; text-decoration: none; -} + } #version { font-size: 10px; font-weight: normal; -} + } #gotoDashboard { background-color: #444; border: 0; @@ -58,17 +58,17 @@ a { padding: 3px 0; position: relative; text-align: center; -} + } #gotoDashboard > span:last-of-type { opacity: 0.5; position: absolute; -} + } body[dir="ltr"] #gotoDashboard > span:last-of-type { left: 3px; -} + } body[dir="rtl"] #gotoDashboard > span:last-of-type { right: 3px; -} + } .paneHead { background-color: white; @@ -78,10 +78,10 @@ body[dir="rtl"] #gotoDashboard > span:last-of-type { right: 0; top: 0; z-index: 100; -} + } .paneContent { padding-top: 5.5em; -} + } .paneHead > a:first-child { @@ -96,7 +96,7 @@ body[dir="rtl"] #gotoDashboard > span:last-of-type { margin: 0; padding: 2px 0; text-align: center; -} + } #toolbarContainer { display: flex; justify-content: space-between; @@ -106,7 +106,7 @@ body[dir="rtl"] #gotoDashboard > span:last-of-type { display: inline-flex; margin: 0; padding: 0; -} + } body .toolbar button { background-color: white; @@ -116,69 +116,69 @@ body .toolbar button { margin: 0; padding: 0.2em 0.2em 0.1em 0.2em; position: relative; -} + } body .toolbar button:hover { background-color: #eee; -} + } body .toolbar button.disabled { color: #ccc; -} + } body .toolbar button.fa { font: 1.7em FontAwesome; min-width: 1.4em; -} + } #mtxSwitch_matrix-off.switchTrue { color: #a00; -} + } #mtxSwitches > li { align-items: center; color: #888; display: flex; -} + } #mtxSwitches > li.switchTrue { color: #000; -} + } #mtxSwitches > li > svg { display: inline; height: 1em; margin-right: 0.4em; width: 1.5em; -} + } #mtxSwitches > li > svg * { fill-opacity: 1; opacity: 1; stroke: none; -} + } #mtxSwitches > li.relevant > svg .dot { fill: #aaa; -} + } #mtxSwitches > li.switchTrue.relevant > svg .dot { fill: #eee; -} + } #mtxSwitches > li > svg .off, #mtxSwitches > li.switchTrue > svg .on, #mtxSwitches > li.relevant > svg .dot { display: block; -} + } #mtxSwitches > li > svg .on, #mtxSwitches > li > svg .dot, #mtxSwitches > li.switchTrue > svg .off { display: none; -} + } #mtxSwitches > li > span[data-i18n] { flex-grow: 1; -} + } #mtxSwitches > li > a { color: #000; opacity: 0; -} + } #mtxSwitches > li:hover > a { opacity: 0.1; -} + } #mtxSwitches > li > a:hover { opacity: 0.8; -} + } .dropdown-menu-capture { background-color: transparent; @@ -192,10 +192,10 @@ body .toolbar button.fa { right: 0; top: 0; z-index: 300; -} + } .dropdown-menu-capture.show { display: block; -} + } .dropdown-menu { border: 0; display: inline-block; @@ -203,7 +203,7 @@ body .toolbar button.fa { padding: 3px 0 0 0; position: absolute; white-space: normal; -} + } .dropdown-menu > ul { margin: 0; border: 0; @@ -212,7 +212,7 @@ body .toolbar button.fa { padding: 0; background-color: white; list-style-type: none; -} + } .dropdown-menu > ul > li.dropdown-menu-entry { border: 0; color: black; @@ -220,21 +220,21 @@ body .toolbar button.fa { margin: 0; padding: 0.2em 0.25em; white-space: nowrap; -} + } .dropdown-menu > ul > li.dropdown-menu-entry:hover { background: #eee; -} + } .dropdown-menu > ul > li.dropdown-menu-entry-divider { border-top: 1px solid #ccc; margin: 0.5em 0; -} + } .dropdown-menu.show { display: block; -} + } #buttonReload { margin-left: 1em; -} + } button > span.badge { padding: 1px 1px; @@ -245,19 +245,19 @@ button > span.badge { bottom: 1px; color: #000; background-color: rgba(240,240,240,0.75) -} + } button.disabled > span.badge { display: none; -} + } #buttonPresets + .dropdown-menu { position: fixed; left: 10vw; width: 80vw; -} + } .presetInfo { margin: 0.25em 0.5em; text-align: center; -} + } .presetEntry { margin: 0.25em 0.25em; border-radius: 3px; @@ -265,14 +265,14 @@ button.disabled > span.badge { display: inline-block; cursor: pointer; background-color: #eee; -} + } .presetEntry .fa { margin-right: 0.25em; font-size: 110%; -} + } .presetEntry:hover { background-color: #80e2ff; -} + } #presetMore > *:first-child { margin: 0; padding: 0; @@ -280,19 +280,19 @@ button.disabled > span.badge { color: #888; cursor: pointer; font-size: 13px; -} + } #presetMore > *:first-child + div { margin: 0.25em 0 0 0; padding: 0.25em 0 0 0; display: none; text-align: center; -} + } #presetMore > *:first-child + div.show { display: block; -} + } #presetMore > *:first-child + div > * { vertical-align: middle; -} + } #presetMoreRecipe { border: 1px solid #aaa; width: 75%; @@ -301,20 +301,20 @@ button.disabled > span.badge { resize: none; font-size: 10px; color: #888; -} + } #presetMoreRecipe.bad { border: 1px solid #fcc; color: #aaa; -} + } #presetMoreWrite.bad { visibility: hidden; -} + } /* I think this is obsolete */ .dropdown-menu > li > a > i { padding: 0 6px; font-size: 1.2em; -} + } body .toolbar .scope { background-color: #ccc; @@ -326,75 +326,75 @@ body .toolbar .scope { margin: 0; padding: 1px; cursor: pointer; -} + } body .toolbar .scope > span { align-items: center; display: inline-flex; -} + } body .toolbar .scope > span > span { pointer-events: none; white-space: nowrap; -} + } body .toolbar #specificScope { direction: ltr; justify-content: flex-end; width: 16em; -} + } body .toolbar #specificScope.on { background-color: #24c; border-color: #24c; -} + } body .toolbar #specificScope > span { background-color: #ccc; justify-content: flex-end; -} + } body .toolbar #specificScope > span.on { background-color: #24c; -} + } body .toolbar #specificScope > span:first-of-type:not(.on):hover, body .toolbar #specificScope > span:first-of-type:not(.on):hover ~ span:not(.on), body .toolbar #specificScope > span:not(.on) + span:not(.on):hover, body .toolbar #specificScope > span:not(.on) + span:not(.on):hover ~ span:not(.on) { background-color: #999; -} + } body .toolbar #specificScope > span:first-of-type:not(.on):hover ~ span, body .toolbar #specificScope > span:not(.on) + span:not(.on):hover ~ span, body .toolbar #specificScope > span.on + span:hover, body .toolbar #specificScope > span.on + span:hover ~ span { background-color: #139; -} + } body .toolbar #specificScope > span:first-of-type { flex: 1; -} + } body .toolbar #globalScope { justify-content: center; margin-left: 1px; width: 1.8em; -} + } body .toolbar #globalScope.on { background-color: #000; border-color: #000; -} + } body .toolbar #globalScope:not(.on):hover { background-color: #999; border-color: #999; -} + } body .toolbar .scopeRel { color: #24c; -} + } body.globalScope .toolbar .scopeRel { color: #000; -} + } body.globalScope .toolbar .scopeRel.disabled { color: #ccc; -} + } .matrix { text-align: left; -} + } .matRow { white-space: nowrap; -} + } .matCell { margin: 1px 1px 0 0; border: 1px dotted rgba(0,0,0,0.2); @@ -407,23 +407,23 @@ body.globalScope .toolbar .scopeRel.disabled { text-align: center; line-height: 110%; position: relative; -} + } #matHead { border-top: 1px dotted #ccc; padding-top: 1px; margin: 1px 0 0 0; -} + } .paneHead .matCell:nth-child(2) { letter-spacing: -0.3px; -} + } .paneContent .matrix .matRow > .matCell:first-child { font-weight: 100; -} + } .paneContent .matrix .matRow > .matCell:first-child > b { font-weight: normal; -} + } /* RFC 3987 Internationalized Resource Identifiers (IRIs) -- 4.4 */ .matrix .matRow > .matCell:first-child { @@ -431,42 +431,42 @@ body.globalScope .toolbar .scopeRel.disabled { text-align: right; unicode-bidi: embed; width: 16em; -} + } .matrix .matGroup.g4 .matRow.ro > .matCell:first-child { direction: inherit; -} + } .matrix .matRow.l2 > .matCell:first-child { margin-left: 1px; width: calc(16em - 1px); -} + } .matrix .matRow > .matCell:hover { border-style: solid; -} + } .matrix .matGroup .matSection { margin: 2px 0 0 0; border: 0; padding: 0; /* background-color: rgba(0,0,0,0.05); */ -} + } .matrix .matGroup.g0 .matSection:first-child { margin-top: 0; -} + } .matrix .matGroup.g4 .matSection:first-child { margin-top: 0; -} + } /* Collapsing of domains */ .matrix .matSection .matRow.meta { display: none; -} + } .matrix .matSection.collapsible.collapsed .matRow.meta { display: block; -} + } .matrix .matSection.collapsible.collapsed .matRow.l1:not(.meta) { display: none; -} + } .matrix .matSection.collapsible.collapsed .matRow.l2.collapsible { display: none; -} + } /* Collapsing of blacklisted */ .matrix .g4Meta { @@ -475,106 +475,106 @@ body.globalScope .toolbar .scopeRel.disabled { border: 0; height: 6px; background: url('../img/matrix-group-hide.png') no-repeat center top, - url('../img/matrix-group-hline.png') repeat-x center top 3px; + url('../img/matrix-group-hline.png') repeat-x center top 3px; opacity: 0.2; cursor: pointer; -} + } .matrix .g4Meta:hover { opacity: 0.4; -} + } .matrix .g4Meta.g4Collapsed { background: url('../img/matrix-group-show.png') no-repeat center top, - url('../img/matrix-group-hline.png') repeat-x center top 3px; -} + url('../img/matrix-group-hline.png') repeat-x center top 3px; + } .matrix .g4Meta.g4Collapsed ~ .matSection { display: none; -} + } body.powerOff .matrix .g4Meta.g4Collapsed ~ .matSection { display: block; -} + } .matrix .g4Meta ~ .matRow.ro { display: none; -} + } .matrix .g4Meta.g4Collapsed ~ .matRow.ro { display: block; -} + } body.powerOff .matrix .g4Meta.g4Collapsed ~ .matRow.ro { display: none; -} + } .matrix .matGroup .g4Meta + *,.matrix .matGroup .g4Meta + * + * { margin-top: 0; padding-top: 0; -} + } /* Cell coloring */ .t81 { color: white; background-color: #c00; -} + } .t82 { color: white; background-color: #080; -} + } .t1 { border-color: #debaba; color: black; background-color: #f8d0d0; -} + } .t2 { border-color: #bad6ba; color: black; background-color: #d0f0d0; -} + } .matCell.p81 { background-image: url('../img/permanent-black-small.png'); background-repeat: no-repeat; background-position: -1px -1px; -} + } .matCell.p82 { background-image: url('../img/permanent-white-small.png'); background-repeat: no-repeat; background-position: -1px -1px; -} + } /* Cell coloring for color blind-friendly (hopefully) */ body.colorblind .t81 { color: white; background-color: rgb(0, 19, 110); -} + } body.colorblind .t82 { border-color: rgb(255, 194, 57); color: black; background-color: rgb(255, 194, 57); -} + } body.colorblind .t1 { border-color: rgba(0, 19, 110, 0.3); color: black; background-color: rgba(0, 19, 110, 0.2); -} + } body.colorblind .t2 { border-color: rgba(255, 194, 57, 0.3); color: black; background-color: rgba(255, 194, 57, 0.2); -} + } body.colorblind .matCell.p81 { background-image: url('../img/permanent-black-small-cb.png'); -} + } body.colorblind .matCell.p82 { background-image: url('../img/permanent-white-small-cb.png'); -} + } .matRow.rw .matCell { cursor: pointer; -} + } body.powerOff .matRow.rw .matCell { cursor: auto; opacity: 0.6; -} + } .top { font-weight: bold; -} + } #cellHotspots { margin: 0; @@ -586,7 +586,7 @@ body.powerOff .matRow.rw .matCell { width: 100%; height: 100%; z-index: 10; -} + } #whitelist, #blacklist { margin: 0; border: 0; @@ -596,54 +596,54 @@ body.powerOff .matRow.rw .matCell { width: 100%; height: 50%; background: transparent; -} + } #whitelist { top: 0; -} + } #blacklist { top: 50%; -} + } body.powerOff #whitelist, body.powerOff #blacklist { display: none; -} + } .rw .matCell.t1 #whitelist:hover { background-color: #080; opacity: 0.25; -} + } body.colorblind .rw .matCell.t1 #whitelist:hover, body.colorblind .rw .matCell.t2 #whitelist:hover { background-color: rgb(255, 194, 57); opacity: 0.6; -} + } .rw .matCell.t2 #whitelist:hover { background-color: #080; opacity: 0.25; -} + } .matCell.t81 #whitelist:hover { background-color: transparent; -} + } .matCell.t82 #whitelist:hover { background-color: transparent; -} + } .rw .matCell.t1 #blacklist:hover { background-color: #c00; opacity: 0.25; -} + } body.colorblind .rw .matCell.t1 #blacklist:hover, body.colorblind .rw .matCell.t2 #blacklist:hover { background-color: rgb(0, 19, 110); opacity: 0.4; -} + } .rw .matCell.t2 #blacklist:hover { background-color: #c00; opacity: 0.25; -} + } .matCell.t81 #blacklist:hover { background-color: transparent; -} + } .matCell.t82 #blacklist:hover { background-color: transparent; -} + } #domainOnly { margin: 0; border: 1px solid gray; @@ -659,35 +659,35 @@ body.colorblind .rw .matCell.t2 #blacklist:hover { opacity: 0.25; z-index: 10000; cursor: pointer; -} + } .matSection #domainOnly .fa:before { content: '\f106'; -} + } .matSection.collapsed #domainOnly .fa:before { content: '\f107'; -} + } .matSection.collapsible .matRow.l1 .matCell:nth-of-type(1):hover #domainOnly { display: block; -} + } #matHead #domainOnly .fa:before { content: '\f106'; -} + } #matHead.collapsed #domainOnly .fa:before { content: '\f107'; -} + } #matHead.collapsible .matRow .matCell:nth-of-type(1):hover #domainOnly { display: block; -} + } #domainOnly:hover { opacity: 1; -} + } /* No data was found for the tab */ body.noTabFound .paneHead, body.noTabFound .paneContent { display: none; -} + } body.noTabFound #noTabFound { align-items: center; color: gray; @@ -695,19 +695,19 @@ body.noTabFound #noTabFound { font-size: xx-large; height: 100vh; justify-content: center; -} + } /* Mobile-friendly rules */ body.hConstrained { overflow-x: auto; -} + } body.hConstrained .paneHead { left: auto; position: absolute; right: auto; width: 100%; -} + } body[data-touch="true"] .matCell { line-height: 200%; -} + } diff --git a/css/raw-settings.css b/css/raw-settings.css index 77b76e2..fa2386d 100644 --- a/css/raw-settings.css +++ b/css/raw-settings.css @@ -1,7 +1,7 @@ /******************************************************************************* ηMatrix - a browser extension to black/white list requests. - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -25,10 +25,10 @@ body { flex-direction: column; height: 100vh; justify-content: space-between; -} + } p { margin: 0.5em 0; -} + } textarea { box-sizing: border-box; flex-grow: 1; @@ -37,4 +37,4 @@ textarea { white-space: pre; width: 100%; word-wrap: normal; -} + } diff --git a/css/user-rules.css b/css/user-rules.css index ad02f2f..acdf422 100644 --- a/css/user-rules.css +++ b/css/user-rules.css @@ -1,7 +1,7 @@ /******************************************************************************* ηMatrix - a browser extension to black/white list requests. - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,16 +16,16 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ div > p:first-child { margin-top: 0; -} + } div > p:last-child { margin-bottom: 0; -} + } #diff { border: 0; margin: 0; @@ -42,14 +42,14 @@ div > p:last-child { vertical-align: top; white-space: normal; width: calc(50% - 2px); -} + } #diff > .pane > div { padding: 0 0 1em 0; text-align: center; -} + } #diff > .pane > div > span { float: left; -} + } body[dir="ltr"] #revertButton:after { content: '\2009\f061'; font-family: FontAwesome; @@ -58,7 +58,7 @@ body[dir="ltr"] #revertButton:after { line-height: 1; vertical-align: baseline; display: inline-block; -} + } body[dir="rtl"] #revertButton:after { content: '\2009\f060'; font-family: FontAwesome; @@ -67,7 +67,7 @@ body[dir="rtl"] #revertButton:after { line-height: 1; vertical-align: baseline; display: inline-block; -} + } body[dir="ltr"] #commitButton:before { content: '\f060\2009'; font-family: FontAwesome; @@ -76,7 +76,7 @@ body[dir="ltr"] #commitButton:before { line-height: 1; vertical-align: baseline; display: inline-block; -} + } body[dir="rtl"] #commitButton:before { content: '\f061\2009'; font-family: FontAwesome; @@ -85,30 +85,30 @@ body[dir="rtl"] #commitButton:before { line-height: 1; vertical-align: baseline; display: inline-block; -} + } #revertButton, #commitButton, #diff.edit #editEnterButton { opacity: 0.25; pointer-events: none; -} + } #editStopButton, #editCancelButton { display: none; -} + } #diff.dirty:not(.edit) #revertButton, #diff.dirty:not(.edit) #commitButton { opacity: 1; pointer-events: auto; -} + } #diff.edit #editStopButton, #diff.edit #editCancelButton { display: initial; -} + } #diff.edit #importButton, #diff.edit #exportButton { display: none; -} + } #diff ul { border: 0; border-top: 1px solid #eee; @@ -116,50 +116,50 @@ body[dir="rtl"] #commitButton:before { margin: 0; overflow: hidden; padding: 1em 0 0 0; -} + } #diff ul, #diff textarea { font: 12px/1.8 monospace; -} + } #diff.edit .right ul { visibility: hidden; -} + } #diff .left { padding: 0 0 0 0; -} + } #diff .right > ul { color: #888; -} + } #diff li { background-color: white; direction: ltr; padding: 0; text-align: left; white-space: nowrap; -} + } #diff li:nth-of-type(2n+0) { background-color: #eee; -} + } #diff .right li { cursor: pointer; -} + } #diff .right li:hover { background-color: #ffc; color: #000; -} + } #diff .right li.notLeft { color: #000; -} + } #diff .right li.notLeft:hover { text-decoration: line-through; -} + } #diff .right li.notRight { color: #000; -} + } #diff .right li.toRemove { color: #000; text-decoration: line-through; -} + } #diff textarea { border: 0; border-top: 1px solid #eee; @@ -175,10 +175,10 @@ body[dir="rtl"] #commitButton:before { visibility: hidden; white-space: pre; width: 100%; -} + } #diff.edit textarea { visibility: visible; -} + } .hidden { display: none; -} + } diff --git a/frameScript.js b/frameScript.js index f8acc54..bdd274d 100644 --- a/frameScript.js +++ b/frameScript.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 The µBlock authors - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -29,35 +29,35 @@ var locationChangeListener; // Keep alive while frameScript is alive (function () { let injectContentScripts = function (win) { - if (!win || !win.document) { + if (!win || !win.document) { return; - } + } - contentObserver.observe(win.document); + contentObserver.observe(win.document); - if (win.frames && win.frames.length) { - for (let i = win.frames.length; i>0; --i) { - injectContentScripts(win.frames[i]); + if (win.frames && win.frames.length) { + for (let i = win.frames.length; i>0; --i) { + injectContentScripts(win.frames[i]); } - } + } }; let onLoadCompleted = function () { - removeMessageListener('ematrix-load-completed', onLoadCompleted); - injectContentScripts(content); + removeMessageListener('ematrix-load-completed', onLoadCompleted); + injectContentScripts(content); }; addMessageListener('ematrix-load-completed', onLoadCompleted); if (docShell) { - let Ci = Components.interfaces; - let wp = docShell - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebProgress); - let dw = wp.DOMWindow; + let Ci = Components.interfaces; + let wp = docShell + .QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebProgress); + let dw = wp.DOMWindow; - if (dw === dw.top) { + if (dw === dw.top) { locationChangeListener = new LocationChangeListener(docShell); - } + } } })(); diff --git a/install.rdf b/install.rdf index 7943ccd..858e97e 100644 --- a/install.rdf +++ b/install.rdf @@ -22,7 +22,7 @@ <r:RDF xmlns:r="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.mozilla.org/2004/em-rdf#"> <r:Description about="urn:mozilla:install-manifest"> <id>eMatrix@vannilla.org</id> - <version>3.1.2</version> + <version>3.1.3</version> <name>ηMatrix</name> <description>Point & click to forbid/allow any class of requests made by your browser. Use it to block scripts, iframes, ads, facebook, etc.</description> <!-- uMatrix homepageURL --> diff --git a/js/about.js b/js/about.js index a35b45c..9ada80e 100644 --- a/js/about.js +++ b/js/about.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/js/asset-viewer.js b/js/asset-viewer.js index 8998892..12f0e3b 100644 --- a/js/asset-viewer.js +++ b/js/asset-viewer.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -36,7 +36,7 @@ } vAPI.messaging.send('asset-viewer.js', { - what : 'getAssetContent', - url: matches[1] + what : 'getAssetContent', + url: matches[1] }, onAssetContentReceived); })(); diff --git a/js/assets.js b/js/assets.js index 286cf0d..9bb2470 100644 --- a/js/assets.js +++ b/js/assets.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2013-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,14 +17,12 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ 'use strict'; -/******************************************************************************/ - ηMatrix.assets = (function() { let api = {}; @@ -33,21 +31,21 @@ let connectionError = vAPI.i18n('errorCantConnectTo'); let notifyObservers = function (topic, details) { - let result; + let result; - for (let i=0; i<observers.length; ++i) { - result = observers[i](topic, details); - } + for (let i=0; i<observers.length; ++i) { + result = observers[i](topic, details); + } - return result; + return result; } function isEmptyString(s) { - return (typeof s === 'string' && s === ''); + return (typeof s === 'string' && s === ''); } function noOp() { - return; + return; } // Cache Registry @@ -57,308 +55,257 @@ let cacheRegistryStart = Date.now(); let saveCacheRegistry = (function () { - let timer; - - function save() { - timer = undefined; - vAPI.cacheStorage.set({ - assetCacheRegistry: cacheRegistry, - }); - } - - return function (lazy) { - if (timer !== undefined) { - clearTimeout(timer); - } - - if (lazy === true) { - timer = vAPI.setTimeout(save, 500); - } else { - save(); - } - }; + let timer; + + let save = function () { + timer = undefined; + vAPI.cacheStorage.set({ + assetCacheRegistry: cacheRegistry, + }); + } + + return function (lazy) { + if (timer !== undefined) { + clearTimeout(timer); + } + + if (lazy === true) { + timer = vAPI.setTimeout(save, 500); + } else { + save(); + } + }; })(); let getCacheRegistry = function (callback) { - if (cacheRegistryReady == true) { - callback(cacheRegistry); - return; - } - - if (cacheRegistryCallbacks !== undefined) { - // If it's not undefined it's always an array - // - // eMatrix: this block in particular is probably never - // called: originally, it was used because uMatrix called - // some code in a callback that could wait - // - // While waiting, more elements could've been pushed in - // the array - // - // Since the waiting callback is not used here, any - // further callback are likely to be handled by the - // condition above - // This block is left here just in case - cacheRegistryCallbacks.push(callback); - return; - } - - cacheRegistryCallbacks = [callback]; - cacheRegistryReady = true; - - let onRead = function (bin) { - if (!bin || !bin['assetCacheRegistry']) { - cacheRegistry = {}; - } else { - cacheRegistry = bin['assetCacheRegistry']; - } - }; - - vAPI.cacheStorage.get('assetCacheRegistry', onRead); - - let f; - while ((f = cacheRegistryCallbacks.shift())) { - f(cacheRegistry); - } + if (cacheRegistryReady == true) { + callback(cacheRegistry); + return; + } + + if (cacheRegistryCallbacks !== undefined) { + // If it's not undefined it's always an array + // + // eMatrix: this block in particular is probably never + // called: originally, it was used because uMatrix called + // some code in a callback that could wait + // + // While waiting, more elements could've been pushed in + // the array + // + // Since the waiting callback is not used here, any + // further callback are likely to be handled by the + // condition above + // This block is left here just in case + cacheRegistryCallbacks.push(callback); + return; + } + + cacheRegistryCallbacks = [callback]; + + let onRead = function (bin) { + if (!bin || !bin['assetCacheRegistry']) { + cacheRegistry = {}; + } else { + cacheRegistry = bin['assetCacheRegistry']; + } + + cacheRegistryReady = true; + + let f; + while ((f = cacheRegistryCallbacks.shift())) { + f(cacheRegistry); + } + }; + + vAPI.cacheStorage.get('assetCacheRegistry', onRead); }; let readCache = function (key, callback) { - let report = function (content, error) { - let details = { - assetKey: key, - content: content, - }; - - if (error) { - details.error = error; - } - - callback(details); - }; - - let onRead = function (bin) { - if (!bin || !bin[key]) { - report('', 'E_NOTFOUND'); - return; - } - - let entry = cacheRegistry[key]; - if (entry === undefined) { - let onRead2 = function (bin) { - if (!bin || !bin['assetCacheRegistry']) { - cacheRegistry = {}; - } else { - cacheRegistry = bin['assetCacheRegistry']; - } - }; - - vAPI.cacheStorage.get('assetCacheRegistry', onRead2); - - entry = cacheRegistry[key]; - if (entry === undefined) { - report('', 'E_NOTFOUND'); - return; - } - } - - entry.readTime = Date.now(); - saveCacheRegistry(true); - - report(bin[key]); - }; - - let onReady = function () { - vAPI.cacheStorage.get(key, onRead); - }; - - getCacheRegistry(onReady); - }; - - let writeCache = function (key, details, callback) { - let content = ''; - - if (typeof details === 'string') { - content = details; - } else if (details instanceof Object) { - content = details.content || ''; - } - - if (content === '') { - removeCache(key, callback); - return; - } - - let report = function (content) { - let details = { - assetKey: key, - content: content, - }; - - if (typeof callback === 'function') { - callback(details); - } - - notifyObservers('after-asset-updated', details); - }; - - let onReady = function () { - let entry = cacheRegistry[key]; - if (entry === undefined) { - entry = cacheRegistry[key] = {}; - } - - entry.writeTime = entry.readTime = Date.now(); - if (details instanceof Object && typeof details.url === 'string') { - entry.remoteURL = details.url; - } - - let bin = { - assetCacheRegistry: cacheRegistry, - }; - - bin[key] = content; - vAPI.cacheStorage.set(bin); - report(content); - }; - - getCacheRegistry(onReady); - }; - - let cacheRemove = function (pattern, callback) { - let onReady = function (cache) { - let entries = []; + let fullkey = 'cache/' + key; + let cache = { placeholder: true }; - for (let key in cache) { - if (pattern instanceof RegExp && !pattern.test(key)) { - continue; - } + let report = function (content, error) { + let details = { + assetKey: key, + content: content, + }; - if (typeof pattern === 'string' && key !== pattern) { - continue; - } + if (error) { + details.error = error; + } - entries.push(key); + return callback(details); + }; - delete cache[key]; - } + let onRead = function (bin) { + if (!bin || !bin[fullkey]) { + return report('', 'E_NOTFOUND'); + } - if (entries.length !== 0) { - vAPI.cacheStorage.remove(content); + let entry = cache[key]; + if (entry === undefined) { + return report('', 'E_NOTFOUND'); + } - let bin = { - assetCacheRegistry: cache, - }; - vAPI.cacheStorage.set(bin); - } + entry.readTime = Date.now(); + saveCacheRegistry(true); - if (typeof callback === 'function') { - callback(); - } + report(bin[fullkey]); + }; - for (let i=0; i<entries.length; ++i) { - notifyObservers('after-asset-updated', { - assetKey: entries[i], - }); - } - }; + let onReady = function (registry) { + cache = registry; + vAPI.cacheStorage.get(fullkey, onRead); + }; - getCacheRegistry(onReady); + getCacheRegistry(onReady); }; - let markDirtyCache = function (pattern, exclude, callback) { - let onReady = function (registry) { - let entry; - let mustSave = false; - - for (let key in registry) { - if (pattern instanceof RegExp && pattern.test(key) === false) { - continue; - } else if (typeof pattern === 'string' && key !== pattern) { - continue; - } else if (Array.isArray(pattern) - && pattern.indexOf(key) === -1) { - continue; - } - - if (exclude instanceof RegExp && exclude.test(key)) { - continue; - } else if (typeof exclude === 'string' && key === exclude) { - continue; - } else if (Array.isArray(exclude) - && exclude.indexOf(key) !== -1) { - continue; - } - - entry = registry[key]; - if (!entry.writeTime) { - continue; - } - - registry[key].writeTime = 0; - mustSave = true; - } - - if (mustSave) { - let bin = { - assetCacheRegistry: registry, - }; - vAPI.cacheStorage.set(bin); - } - - if (typeof callback === 'function') { - callback(); - } - }; - - if (typeof exclude === 'function') { - callback = exclude; - exclude = undefined; - } - - getCacheRegistry(onReady); + let writeCache = function (key, details, callback) { + let fullkey = 'cache/' + key; + let content = ''; + + if (typeof details === 'string') { + content = details; + } else if (details instanceof Object) { + content = details.content || ''; + } + + if (content === '') { + return removeCache(key, callback); + } + + let report = function (content) { + let details = { + assetKey: key, + content: content, + }; + + if (typeof callback === 'function') { + callback(details); + } + + notifyObservers('after-asset-updated', details); + }; + + let onReady = function (registry) { + let entry = registry[key]; + if (entry === undefined) { + entry = registry[key] = {}; + } + + entry.writeTime = entry.readTime = Date.now(); + if (details instanceof Object && typeof details.url === 'string') { + entry.remoteURL = details.url; + } + + let bin = { + assetCacheRegistry: cacheRegistry, + }; + + bin[fullkey] = content; + vAPI.cacheStorage.set(bin); + report(content); + }; + + getCacheRegistry(onReady); }; - let removeCache = function (key, callback) { - let onReady = function (cacheRegistry) { - let removedEntries = []; - let removedContent = []; + let removeCache = function (pattern, callback) { + let onReady = function (cache) { + let entries = []; + let contents = []; + + for (let key in cache) { + if (pattern instanceof RegExp && !pattern.test(key)) { + continue; + } - for (let k in cacheRegistry) { - if (key instanceof RegExp && !key.test(k)) { - continue; - } - if (typeof key === 'string' && k !== key) { - continue; - } + if (typeof pattern === 'string' && key !== pattern) { + continue; + } - removedEntries.push(k); - removedContent.push(k); + entries.push(key); + contents.push('cache/' + key); - delete cacheRegistry[k]; - } + delete cache[key]; + } - if (removedContent.length > 0) { - vAPI.cacheStorage.remove(removedContent); + if (contents.length !== 0) { + vAPI.cacheStorage.remove(contents); - let bin = { - assetCacheRegistry: cacheRegistry, - }; + let bin = { + assetCacheRegistry: cache, + }; + vAPI.cacheStorage.set(bin); + } - vAPI.cacheStorage.set(bin); - } + if (typeof callback === 'function') { + callback(); + } - if (typeof callback === 'function') { - callback(); - } + for (let i=0; i<entries.length; ++i) { + notifyObservers('after-asset-updated', { + assetKey: entries[i], + }); + } + }; - for (let i=0; i<removedEntries.length; ++i) { - notifyObservers('after-asset-updated', { - assetKey: removedEntries[i], - }); - } - }; + getCacheRegistry(onReady); + }; - getCacheRegistry(onReady); + let markDirtyCache = function (pattern, exclude, callback) { + let onReady = function (registry) { + let entry; + let mustSave = false; + + for (let key in registry) { + if (pattern instanceof RegExp && pattern.test(key) === false) { + continue; + } else if (typeof pattern === 'string' && key !== pattern) { + continue; + } else if (Array.isArray(pattern) + && pattern.indexOf(key) === -1) { + continue; + } + + if (exclude instanceof RegExp && exclude.test(key)) { + continue; + } else if (typeof exclude === 'string' && key === exclude) { + continue; + } else if (Array.isArray(exclude) + && exclude.indexOf(key) !== -1) { + continue; + } + + entry = registry[key]; + if (!entry.writeTime) { + continue; + } + + registry[key].writeTime = 0; + mustSave = true; + } + + if (mustSave) { + let bin = { + assetCacheRegistry: registry, + }; + vAPI.cacheStorage.set(bin); + } + + if (typeof callback === 'function') { + callback(); + } + }; + + if (typeof exclude === 'function') { + callback = exclude; + exclude = undefined; + } + + getCacheRegistry(onReady); }; // Source Registry @@ -367,248 +314,252 @@ let sourceRegistryCallbacks = undefined; let saveSourceRegistry = (function () { - let timer; - - function save() { - timer = undefined; - vAPI.cacheStorage.set({ - assetSourceRegistry: sourceRegistry, - }); - } - - return function (lazy) { - if (timer !== undefined) { - clearTimeout(timer); - } - - if (lazy === true) { - timer = vAPI.setTimeout(save, 500); - } else { - save(); - } - }; + let timer; + + let save = function () { + timer = undefined; + vAPI.cacheStorage.set({ + assetSourceRegistry: sourceRegistry, + }); + } + + return function (lazy) { + if (timer !== undefined) { + clearTimeout(timer); + } + + if (lazy === true) { + timer = vAPI.setTimeout(save, 500); + } else { + save(); + } + }; })(); let registerSource = function (key, details) { - let entry = sourceRegistry[key] || {}; - - for (let p in details) { - if (details.hasOwnProperty(p) === false) { - continue; - } - - if (details[p] !== undefined) { - entry[p] = details[p]; - } else { - delete entry[p]; - } - } - - let contentUrl = details.contentURL; - if (contentUrl) { - if (typeof contentUrl === 'string') { - contentUrl = entry.contentURL = [contentUrl]; - } else if (Array.isArray(contentUrl) === false) { - contentUrl = entry.contentURL = []; - } - - let remoteCount = 0; - - for (let i=0; i<contentUrl.length; ++i) { - if (externalPathRegex.test(contentUrl[i])) { - ++remoteCount; - } - } - - entry.hasLocalURL = (remoteCount !== contentUrl.length); - entry.hasRemoteURL = (remoteCount !== 0); - } else { - entry.contentURL = []; - } - - if (typeof entry.updateAfter !== 'number') { - entry.updateAfter = 13; - } - - if (entry.submitter) { - entry.submitTime = Date.now(); // Detects stale entries - } - - sourceRegistry[key] = entry; + let entry = sourceRegistry[key] || {}; + + for (let p in details) { + if (details.hasOwnProperty(p) === false) { + continue; + } + + if (details[p] !== undefined) { + entry[p] = details[p]; + } else { + delete entry[p]; + } + } + + let contentUrl = details.contentURL; + if (contentUrl) { + if (typeof contentUrl === 'string') { + contentUrl = entry.contentURL = [contentUrl]; + } else if (Array.isArray(contentUrl) === false) { + contentUrl = entry.contentURL = []; + } + + let remoteCount = 0; + + for (let i=0; i<contentUrl.length; ++i) { + if (externalPathRegex.test(contentUrl[i])) { + ++remoteCount; + } + } + + entry.hasLocalURL = (remoteCount !== contentUrl.length); + entry.hasRemoteURL = (remoteCount !== 0); + } else { + entry.contentURL = []; + } + + if (typeof entry.updateAfter !== 'number') { + entry.updateAfter = 13; + } + + if (entry.submitter) { + entry.submitTime = Date.now(); // Detects stale entries + } + + sourceRegistry[key] = entry; }; let unregisterSource = function (key) { - removeCache(key); - delete sourceRegistry[key]; - saveSourceRegistry(); + removeCache(key); + delete sourceRegistry[key]; + saveSourceRegistry(); }; let updateSourceRegistry = function (string, silent) { - let json; - - try { - json = JSON.parse(string); - } catch (e) { - return; - } - - for (let key in sourceRegistry) { - if (json[key] === undefined - && sourceRegistry[key].submitter === undefined) { - unregisterSource(key); - } - } - - for (let key in json) { - if (sourceRegistry[key] === undefined && !silent) { - notifyObservers('builtin-asset-source-added', { - assetKey: key, - entry: json[key], - }); - } - - registerSource(key, json[key]); - } - - saveSourceRegistry(); + let json; + + try { + json = JSON.parse(string); + } catch (e) { + return; + } + + if (json instanceof Object === false) { + return; + } + + for (let key in sourceRegistry) { + if (json[key] === undefined + && sourceRegistry[key].submitter === undefined) { + unregisterSource(key); + } + } + + for (let key in json) { + if (sourceRegistry[key] === undefined && !silent) { + notifyObservers('builtin-asset-source-added', { + assetKey: key, + entry: json[key], + }); + } + + registerSource(key, json[key]); + } + + saveSourceRegistry(); }; let getSourceRegistry = function (callback) { - if (sourceRegistryReady === true) { - callback(sourceRegistry); - return; - } - - if (sourceRegistryCallbacks !== undefined) { - // If it's not undefined it's always an array - sourceRegistryCallbacks.push(callback); - return; - } - - sourceRegistryCallbacks = [callback]; - - let onReady = function () { - sourceRegistryReady = true; - - let f; - while ((f = sourceRegistryCallbacks.shift())) { - f(sourceRegistry); - } - }; - - let createRegistry = function () { - api.fetchText - (ηMatrix.assetsBootstrapLocation || 'assets/assets.json', - function (details) { - updateSourceRegistry(details.content, true); - onReady(); - }); - }; - - let onRead = function (bin) { - if (!bin || !bin.assetSourceRegistry - || Object.keys(bin.assetSourceRegistry).length == 0) { - createRegistry(); - return; - } - - sourceRegistry = bin.assetSourceRegistry; - onReady(); - }; - - vAPI.cacheStorage.get('assetSourceRegistry', onRead); + if (sourceRegistryReady === true) { + callback(sourceRegistry); + return; + } + + if (sourceRegistryCallbacks !== undefined) { + // If it's not undefined it's always an array + sourceRegistryCallbacks.push(callback); + return; + } + + sourceRegistryCallbacks = [callback]; + + let onReady = function () { + sourceRegistryReady = true; + + let f; + while ((f = sourceRegistryCallbacks.shift())) { + f(sourceRegistry); + } + }; + + let createRegistry = function () { + api.fetchText + (ηMatrix.assetsBootstrapLocation || 'assets/assets.json', + function (details) { + updateSourceRegistry(details.content, true); + onReady(); + }); + }; + + let onRead = function (bin) { + if (!bin || !bin.assetSourceRegistry + || Object.keys(bin.assetSourceRegistry).length == 0) { + createRegistry(); + return; + } + + sourceRegistry = bin.assetSourceRegistry; + onReady(); + }; + + vAPI.cacheStorage.get('assetSourceRegistry', onRead); }; // Remote let getRemote = function (key, callback) { - let assetDetails = {}; - let contentUrl; - - let report = function (content, error) { - let details = { - assetKey: key, - content: content, - }; - if (error) { - details.error = assetDetails.lastError = error; - } else { - assetDetails.lastError = undefined; - } - callback(details); - }; - - let tryLoad = function (tries) { - let urls = []; - - let tr = (tries === undefined) ? 10 : tries; - - if (tr <= 0) { - console.warn('ηMatrix could not load the asset ' - +assetDetails.title); - return; - } - - if (typeof assetDetails.contentURL === 'string') { - urls = [assetDetails.contentURL]; - } else if (Array.isArray(assetDetails.contentURL)) { - urls = assetDetails.contentURL.slice(0); - } - - while ((contentUrl = urls.shift())) { - if (externalPathRegex.test(contentUrl)) { - break; - } - } - - if (!contentUrl) { - report('', 'E_NOTFOUND'); - return; - } - - api.fetchText(contentUrl, onRemoteContentLoad, onRemoteContentError, - tr-1); - }; - - let onRemoteContentLoad = function (details, tries) { - if (isEmptyString(details.content) === true) { - registerSource(key, { - error: { - time: Date.now(), - error: 'No content' - } - }); - tryLoad(tries); - } - - writeCache(key, { - content: details.content, - url: contentUrl, - }); - - registerSource(key, {error: undefined}); - report(details.content); - }; - - let onRemoteContentError = function (details, tries) { - let text = details.statusText; - if (details.statusCode === 0) { - text = 'network error'; - } - registerSource(key, { - error: { - time: Date.now(), - error: text, - } - }); - tryLoad(tries); - }; - - let onReady = function (registry) { - assetDetails = registry[key] || {}; - tryLoad(); - }; - - getSourceRegistry(onReady); + let assetDetails = {}; + let contentUrl = ''; + let urls = []; + + let report = function (content, error) { + let details = { + assetKey: key, + content: content, + }; + if (error) { + details.error = assetDetails.lastError = error; + } else { + assetDetails.lastError = undefined; + } + callback(details); + }; + + let tryLoad = function (tries) { + let tr = (tries === undefined) ? 10 : tries; + + if (tr <= 0) { + console.warn('ηMatrix could not load the asset ' + +assetDetails.title); + return; + } + + while ((contentUrl = urls.shift())) { + if (externalPathRegex.test(contentUrl)) { + break; + } + } + + if (!contentUrl) { + report('', 'E_NOTFOUND'); + return; + } + + api.fetchText(contentUrl, + onRemoteContentLoad, + onRemoteContentError, + tr-1); + }; + + let onRemoteContentLoad = function (details, tries) { + if (isEmptyString(details.content) === true) { + registerSource(key, { + error: { + time: Date.now(), + error: 'No content' + } + }); + return tryLoad(tries); + } + + writeCache(key, { + content: details.content, + url: contentUrl, + }); + + registerSource(key, {error: undefined}); + report(details.content); + }; + + let onRemoteContentError = function (details, tries) { + let text = details.statusText; + if (details.statusCode === 0) { + text = 'network error'; + } + registerSource(key, { + error: { + time: Date.now(), + error: text, + } + }); + tryLoad(tries); + }; + + let onReady = function (registry) { + assetDetails = registry[key] || {}; + if (typeof assetDetails.contentURL === 'string') { + urls = [assetDetails.contentURL]; + } else if (Array.isArray(assetDetails.contentURL)) { + urls = assetDetails.contentURL.slice(0); + } + tryLoad(); + }; + + getSourceRegistry(onReady); }; // Updater @@ -620,443 +571,446 @@ let updateFetch = new Set(); let updateStart = function () { - updateStatus = 'running'; - updateFetch.clear(); - updated = []; - notifyObservers('before-assets-updated'); - updateNext(); + updateStatus = 'running'; + updateFetch.clear(); + updated = []; + notifyObservers('before-assets-updated'); + updateNext(); }; let updateNext = function () { - let cacheReg = undefined; - let sourceReg = undefined; - - let gcOne = function (key) { - let entry = cacheReg[key]; - if (entry && entry.readTime < cacheRegistryStart) { - cacheRemove(key); - } - }; - - let findOne = function () { - let now = Date.now(); - let sourceEntry; - let cacheEntry; - - for (let key in sourceReg) { - sourceEntry = sourceReg[key]; - if (sourceEntry.hasRemoteURL !== true) { - continue; - } - if (updateFetch.has(key)) { - continue; - } - - cacheEntry = cacheReg[key]; - if (cacheEntry - && (cacheEntry.writeTime - + sourceEntry.updateAfter*86400000) > now) { - continue; - } - if (notifyObservers('before-asset-updated', {assetKey: key})) { - return key; - } - - gcOne(key); - } - - return undefined; - }; - - let onUpdate = function (details) { - if (details.content !== '') { - updated.push(details.assetKey); - if (details.assetKey === 'assets.json') { - updateSourceRegistry(details.content); - } - } else { - notifyObservers('asset-update-failed', { - assetKey: details.assetKey, - }); - } - - if (findOne() !== undefined) { - vAPI.setTimeout(updateNext, updateDelay); - } else { - updateEnd(); - } - }; - - let updateOne = function () { - let key = findOne(); - if (key === undefined) { - updateEnd(); - return; - } - - updateFetch.add(key); - getRemote(key, onUpdate); - }; - - let onSourceReady = function (registry) { - sourceReg = registry; - updateOne(); - }; - - let onCacheReady = function (registry) { - cacheReg = registry; - getSourceRegistry(onSourceReady); - }; - - getCacheRegistry(onCacheReady); + let cacheReg = undefined; + let sourceReg = undefined; + + let gcOne = function (key) { + let entry = cacheReg[key]; + if (entry && entry.readTime < cacheRegistryStart) { + removeCache(key); + } + }; + + let findOne = function () { + let now = Date.now(); + let sourceEntry; + let cacheEntry; + + for (let key in sourceReg) { + sourceEntry = sourceReg[key]; + if (sourceEntry.hasRemoteURL !== true) { + continue; + } + if (updateFetch.has(key)) { + continue; + } + + cacheEntry = cacheReg[key]; + if (cacheEntry + && (cacheEntry.writeTime + + sourceEntry.updateAfter*86400000) > now) { + continue; + } + if (notifyObservers('before-asset-updated', {assetKey: key})) { + return key; + } + + gcOne(key); + } + + return undefined; + }; + + let onUpdate = function (details) { + if (details.content !== '') { + updated.push(details.assetKey); + if (details.assetKey === 'assets.json') { + updateSourceRegistry(details.content); + } + } else { + notifyObservers('asset-update-failed', { + assetKey: details.assetKey, + }); + } + + if (findOne() !== undefined) { + vAPI.setTimeout(updateNext, updateDelay); + } else { + updateEnd(); + } + }; + + let updateOne = function () { + let key = findOne(); + if (key === undefined) { + updateEnd(); + return; + } + + updateFetch.add(key); + getRemote(key, onUpdate); + }; + + let onSourceReady = function (registry) { + sourceReg = registry; + updateOne(); + }; + + let onCacheReady = function (registry) { + cacheReg = registry; + getSourceRegistry(onSourceReady); + }; + + getCacheRegistry(onCacheReady); }; let updateEnd = function () { - let keys = updated.slice(0); - updateFetch.clear(); - updateStatus = 'stop'; - updateDelay = updateDefaultDelay; - notifyObservers('after-asset-updated', { - assetKeys: keys, - }); + let keys = updated.slice(0); + updateFetch.clear(); + updateStatus = 'stop'; + updateDelay = updateDefaultDelay; + notifyObservers('after-asset-updated', { + assetKeys: keys, + }); }; // Assets API api.addObserver = function (observer) { - if (observers.indexOf(observer) === -1) { - observers.push(observer); - } + if (observers.indexOf(observer) === -1) { + observers.push(observer); + } }; api.removeObserver = function (observer) { - let pos = observers.indexOf(observer); - if (pos !== -1) { - observers.splice(pos, 1); - } + let pos = observers.indexOf(observer); + while (pos !== -1) { + observers.splice(pos, 1); + pos = observers.indexOf(observer); + } }; api.fetchText = function (url, onLoad, onError, tries) { - let iurl = externalPathRegex.test(url) ? url : vAPI.getURL(url); - let tr = (tries === undefined) ? 10 : tries; - - if (typeof onError !== 'function') { - onError = onLoad; - } - - let onResponseReceived = function () { - this.onload = this.onerror = this.ontimeout = null; - - let details = { - url: url, - content: '', - // On local files this.status is 0, but the request - // is successful - statusCode: this.status || 200, - statusText: this.statusText || '', - }; - - if (details.statusCode < 200 || details.statusCode >= 300) { - onError.call(null, details, tr); - return; - } - - if (isEmptyString(this.responseText) === true) { - onError.call(null, details, tr); - return; - } - - let t = this.responseText.trim(); - - // Discard HTML as it's probably an error - // (the request expects plain text as a response) - if (t.startsWith('<') && t.endsWith('>')) { - onError.call(null, details, tr); - return; - } - - details.content = t; - onLoad.call(null, details, tr); - }; - - let onErrorReceived = function () { - this.onload = this.onerror = this.ontimeout = null; - - ηMatrix.logger.writeOne('', 'error', - connectionError.replace('{{url}}', iurl)); - - onError.call(null, { - url: url, - content: '', - }, tr); - }; - - let req = new XMLHttpRequest(); - req.open('GET', iurl, true); - req.timeout = 30000; - req.onload = onResponseReceived; - req.onerror = onErrorReceived; - req.ontimeout = onErrorReceived; - req.responseType = 'text'; - - try { - // This can throw in some cases - req.send(); - } catch (e) { - onErrorReceived.call(req); - } + let iurl = externalPathRegex.test(url) ? url : vAPI.getURL(url); + let tr = (tries === undefined) ? 10 : tries; + + if (typeof onError !== 'function') { + onError = onLoad; + } + + let onResponseReceived = function () { + this.onload = this.onerror = this.ontimeout = null; + + let details = { + url: url, + content: '', + // On local files this.status is 0, but the request + // is successful + statusCode: this.status || 200, + statusText: this.statusText || '', + }; + + if (details.statusCode < 200 || details.statusCode >= 300) { + return onError.call(null, details, tr); + } + + if (isEmptyString(this.responseText) === true) { + return onError.call(null, details, tr); + } + + let t = this.responseText.trim(); + + // Discard HTML as it's probably an error + // (the request expects plain text as a response) + if (t.startsWith('<') && t.endsWith('>')) { + return onError.call(null, details, tr); + } + + details.content = t; + return onLoad.call(null, details, tr); + }; + + let onErrorReceived = function () { + this.onload = this.onerror = this.ontimeout = null; + + ηMatrix.logger.writeOne('', 'error', + connectionError.replace('{{url}}', iurl)); + + onError.call(null, { + url: url, + content: '', + }, tr); + }; + + let req = new XMLHttpRequest(); + req.open('GET', iurl, true); + req.timeout = 30000; + req.onload = onResponseReceived; + req.onerror = onErrorReceived; + req.ontimeout = onErrorReceived; + req.responseType = 'text'; + + try { + // This can throw in some cases + req.send(); + } catch (e) { + onErrorReceived.call(req); + } }; api.registerAssetSource = function (key, details) { - getSourceRegistry(function () { - registerSource(key, details); - saveSourceRegistry(true); - }); + getSourceRegistry(function () { + registerSource(key, details); + saveSourceRegistry(true); + }); }; api.unregisterAssetSource = function (key) { - getSourceRegistry(function () { - unregisterSource(key); - saveSourceRegistry(true); - }); + getSourceRegistry(function () { + unregisterSource(key); + saveSourceRegistry(true); + }); }; api.get = function (key, options, callback) { - let cb; - let opt; - - if (typeof options === 'function') { - cb = options; - opt = {}; - } else if (typeof callback !== 'function') { - cb = noOp; - opt = options; - } else { - cb = callback; - opt = options; - } - - let assetDetails = {}; - let contentUrl = undefined; - - let report = function (content, error) { - let details = { - assetKey: key, - content: content, - }; - - if (error) { - details.error = assetDetails.error = error; - } else { - assetDetails.error = undefined; - } - - cb(details); - }; - - let onContentNotLoaded = function (details, tries) { - let external; - let urls = []; - - let tr = (tries === undefined) ? 10 : tries; - - if (tr <= 0) { - console.warn('ηMatrix couldn\'t download the asset ' - +assetDetails.title); - return; - } - - if (typeof assetDetails.contentURL === 'string') { - urls = [assetDetails.contentURL]; - } else if (Array.isArray(assetDetails.contentURL)) { - urls = assetDetails.contentURL.slice(0); - } - - while ((contentUrl = urls.shift())) { - external = externalPathRegex.test(contentUrl); - if (external === true && assetDetails.loaded !== true) { - break; - } - if (external === false || assetDetails.hasLocalURL !== true) { - break; - } - } - - if (!contentUrl) { - report('', 'E_NOTFOUND'); - return; - } - - api.fetchText(contentUrl, onContentLoaded, onContentNotLoaded, - tr-1); - }; - - let onContentLoaded = function (details, tries) { - if (isEmptyString(details.content) === true) { - onContentNotLoaded(undefined, tries); - return; - } - - if (externalPathRegex.test(details.url) - && opt.dontCache !== true) { - writeCache(key, { - content: details.content, - url: contentUrl, - }); - } - - assetDetails.loaded = true; - - report(details.content); - }; - - let onCachedContentLoad = function (details) { - if (details.content !== '') { - report(details.content); - return; - } - - let onReady = function (registry) { - assetDetails = registry[key] || {}; - onContentNotLoaded(); - } - - getSourceRegistry(onReady); - }; - - readCache(key, onCachedContentLoad); + let cb; + let opt; + + if (typeof options === 'function') { + cb = options; + opt = {}; + } else if (typeof callback !== 'function') { + cb = noOp; + opt = options; + } else { + cb = callback; + opt = options; + } + + let assetDetails = {}; + let urls = []; + let contentUrl = ''; + + let report = function (content, error) { + let details = { + assetKey: key, + content: content, + }; + + if (error) { + details.error = assetDetails.error = error; + } else { + assetDetails.error = undefined; + } + + cb(details); + }; + + let onContentNotLoaded = function (details, tries) { + let external; + + let tr = (tries === undefined) ? 10 : tries; + + if (tr <= 0) { + console.warn('ηMatrix couldn\'t download the asset ' + +assetDetails.title); + return; + } + + while ((contentUrl = urls.shift())) { + external = externalPathRegex.test(contentUrl); + if (external === true && assetDetails.loaded !== true) { + break; + } + if (external === false || assetDetails.hasLocalURL !== true) { + break; + } + } + + if (!contentUrl) { + return report('', 'E_NOTFOUND'); + } + + api.fetchText(contentUrl, + onContentLoaded, + onContentNotLoaded, + tr-1); + }; + + let onContentLoaded = function (details, tries) { + if (isEmptyString(details.content) === true) { + return onContentNotLoaded(undefined, tries); + } + + if (externalPathRegex.test(details.url) + && opt.dontCache !== true) { + writeCache(key, { + content: details.content, + url: contentUrl, + }); + } + + assetDetails.loaded = true; + + report(details.content); + }; + + let onCachedContentLoad = function (details) { + if (details.content !== '') { + return report(details.content); + } + + let onRead = function (details) { + console.debug(details); + report(details.content || 'missing contents'); + } + + let onReady = function (registry) { + assetDetails = registry[key] || {}; + if (typeof assetDetails.contentURL === 'string') { + urls = [assetDetails.contentURL]; + } else if (Array.isArray(assetDetails.contentURL)) { + urls = assetDetails.contentURL.slice(0); + } + if (true === assetDetails.loaded) { + readCache(key, onRead); + } else { + onContentNotLoaded(); + } + } + + getSourceRegistry(onReady); + }; + + readCache(key, onCachedContentLoad); }; api.put = function (key, content, callback) { - writeCache(key, content, callback); + writeCache(key, content, callback); }; api.metadata = function (callback) { - let onSourceReady = function (registry) { - let source = JSON.parse(JSON.stringify(registry)); - let cache = cacheRegistry; - let sourceEntry; - let cacheEntry; - let now = Date.now(); - let obsoleteAfter; - - for (let key in source) { - sourceEntry = source[key]; - cacheEntry = cache[key]; - - if (cacheEntry) { - sourceEntry.cached = true; - sourceEntry.writeTime = cacheEntry.writeTime; - obsoleteAfter = cacheEntry.writeTime - + sourceEntry.updateAfter * 86400000; - sourceEntry.obsolete = obsoleteAfter < now; - sourceEntry.remoteURL = cacheEntry.remoteURL; - } else { - sourceEntry.writeTime = 0; - obsoleteAfter = 0; - sourceEntry.obsolete = true; - } - } - - callback(source); - } - - let onCacheReady = function () { - getSourceRegistry(onSourceReady); - } - - getCacheRegistry(onCacheReady); + let onSourceReady = function (registry) { + let source = JSON.parse(JSON.stringify(registry)); + let cache = cacheRegistry; + let sourceEntry; + let cacheEntry; + let now = Date.now(); + let obsoleteAfter; + + for (let key in source) { + sourceEntry = source[key]; + cacheEntry = cache[key]; + + if (cacheEntry) { + sourceEntry.cached = true; + sourceEntry.writeTime = cacheEntry.writeTime; + obsoleteAfter = cacheEntry.writeTime + + sourceEntry.updateAfter * 86400000; + sourceEntry.obsolete = obsoleteAfter < now; + sourceEntry.remoteURL = cacheEntry.remoteURL; + } else { + sourceEntry.writeTime = 0; + obsoleteAfter = 0; + sourceEntry.obsolete = true; + } + } + + callback(source); + } + + let onCacheReady = function () { + getSourceRegistry(onSourceReady); + } + + getCacheRegistry(onCacheReady); }; api.purge = function (pattern, exclude, callback) { - markDirtyCache(pattern, exclude, callback); + markDirtyCache(pattern, exclude, callback); }; api.remove = function (pattern, callback) { - cacheRemove(pattern, callback); + removeCache(pattern, callback); }; api.rmrf = function () { - cacheRemove(/./); + removeCache(/./); }; api.updateStart = function (details) { - let oldDelay = updateDelay; - let newDelay = details.delay || updateDefaultDelay; + let oldDelay = updateDelay; + let newDelay = details.delay || updateDefaultDelay; - updateDelay = Math.min(oldDelay, newDelay); + updateDelay = Math.min(oldDelay, newDelay); - if (updateStatus !== undefined) { - if (newDelay < oldDelay) { - clearTimeout(updateTimer); - updateTimer = vAPI.setTimeout(updateNext, updateDelay); - } - return; - } + if (updateStatus !== 'stop') { + if (newDelay < oldDelay) { + clearTimeout(updateTimer); + updateTimer = vAPI.setTimeout(updateNext, updateDelay); + } + return; + } - updateStart(); + updateStart(); }; api.updateStop = function () { - if (updateTimer) { - clearTimeout(updateTimer); - updateTimer = undefined; - } - if (updateStatus === 'running') { - updateEnd(); - } + if (updateTimer) { + clearTimeout(updateTimer); + updateTimer = undefined; + } + if (updateStatus === 'running') { + updateEnd(); + } }; api.checkVersion = function () { - let cache; - - let onSourceReady = function (registry) { - let source = JSON.parse(JSON.stringify(registry)); - let version = ηMatrix.userSettings.assetVersion; - - if (!version) { - ηMatrix.userSettings.assetVersion = 1; - version = 1; - } - - if (!source["assets.json"].version - || version > source["assets.json"].version) { - for (let key in source) { - switch (key) { - case "hphosts": - case "malware-0": - case "malware-1": - delete source[key]; - api.remove(key, function () {}); - break; - default: - break; - } - - source["assets.json"].version = version; - } - - let createRegistry = function () { - api.fetchText - (ηMatrix.assetsBootstrapLocation || 'assets/assets.json', - function (details) { - updateSourceRegistry(details.content, true); - }); - }; - - createRegistry(); - } - }; - - let onCacheReady = function (registry) { - cache = JSON.parse(JSON.stringify(registry)); - - getSourceRegistry(onSourceReady); - }; - - getCacheRegistry(onCacheReady); + let cache; + + let onSourceReady = function (registry) { + let source = JSON.parse(JSON.stringify(registry)); + let version = ηMatrix.userSettings.assetVersion; + + if (!version) { + ηMatrix.userSettings.assetVersion = 1; + version = 1; + } + + if (!source["assets.json"].version + || version > source["assets.json"].version) { + for (let key in source) { + switch (key) { + case "hphosts": + case "malware-0": + case "malware-1": + delete source[key]; + api.remove(key, function () {}); + break; + default: + break; + } + + source["assets.json"].version = version; + } + + let createRegistry = function () { + api.fetchText + (ηMatrix.assetsBootstrapLocation || 'assets/assets.json', + function (details) { + updateSourceRegistry(details.content, true); + }); + }; + + createRegistry(); + } + }; + + let onCacheReady = function (registry) { + cache = JSON.parse(JSON.stringify(registry)); + + getSourceRegistry(onSourceReady); + }; + + getCacheRegistry(onCacheReady); }; return api; })(); - -/******************************************************************************/ diff --git a/js/background.js b/js/background.js index 889decd..b31bbed 100644 --- a/js/background.js +++ b/js/background.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -32,45 +32,45 @@ var ηMatrix = (function () { let oneDay = 24 * oneHour; let _RequestStats = function () { - this.reset(); + this.reset(); }; _RequestStats.prototype.reset = function () { - this.all = - this.doc = - this.frame = - this.script = - this.css = - this.image = - this.media = - this.xhr = - this.other = - this.cookie = 0; + this.all = + this.doc = + this.frame = + this.script = + this.css = + this.image = + this.media = + this.xhr = + this.other = + this.cookie = 0; }; var RequestStats = function () { - this.allowed = new _RequestStats (); - this.blocked = new _RequestStats (); + this.allowed = new _RequestStats (); + this.blocked = new _RequestStats (); }; RequestStats.prototype.reset = function () { - this.blocked.reset(); - this.allowed.reset(); + this.blocked.reset(); + this.allowed.reset(); }; RequestStats.prototype.record = function (type, blocked) { - // Remember: always test against **false** - if (blocked !== false) { + // Remember: always test against **false** + if (blocked !== false) { this.blocked[type] += 1; this.blocked.all += 1; - } else { + } else { this.allowed[type] += 1; this.allowed.all += 1; - } + } }; var requestStatsFactory = function () { - return new RequestStats(); + return new RequestStats(); }; /** @@ -93,8 +93,8 @@ var ηMatrix = (function () { */ var rawSettingsDefault = { - disableCSPReportInjection: false, - placeholderBackground: [ + disableCSPReportInjection: false, + placeholderBackground: [ 'url("data:image/png;base64,', 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAK', 'CAAAAACoWZBhAAAABGdBTUEAALGPC/xh', @@ -108,13 +108,13 @@ var ηMatrix = (function () { 'KzAzOjAwa+9TNQAAAABJRU5ErkJggg==', '") ', 'repeat scroll #fff' - ].join(''), - placeholderBorder: '1px solid rgba(0, 0, 0, 0.1)', - imagePlaceholder: true, - imagePlaceholderBackground: 'default', - imagePlaceholderBorder: 'default', - framePlaceholder: true, - framePlaceholderDocument: [ + ].join(''), + placeholderBorder: '1px solid rgba(0, 0, 0, 0.1)', + imagePlaceholder: true, + imagePlaceholderBackground: 'default', + imagePlaceholderBorder: 'default', + framePlaceholder: true, + framePlaceholderDocument: [ '<html><head>', '<meta charset="utf-8">', '<style>', @@ -145,13 +145,13 @@ var ηMatrix = (function () { '</a>{{url}}</span>', '</body></html>' ].join(''), - framePlaceholderBackground: 'default', + framePlaceholderBackground: 'default', }; return { - onBeforeStartQueue: [], + onBeforeStartQueue: [], - userSettings: { + userSettings: { alwaysDetachLogger: false, autoUpdate: false, clearBrowserCache: true, @@ -173,56 +173,56 @@ var ηMatrix = (function () { popupScopeLevel: 'domain', processHyperlinkAuditing: true, processReferer: false, - disableUpdateIcon: false, - resolveCname: false, - assetsVersion: 1, - }, - - rawSettingsDefault: rawSettingsDefault, - rawSettings: Object.assign({}, rawSettingsDefault), - rawSettingsWriteTime: 0, - - clearBrowserCacheCycle: 0, - cspNoInlineScript: "script-src 'unsafe-eval' blob: *", - cspNoInlineStyle: "style-src blob: *", - cspNoWorker: undefined, - updateAssetsEvery: 11 * oneDay + 1 * oneHour + 1 * oneMinute + 1 * oneSecond, - firstUpdateAfter: 11 * oneMinute, - nextUpdateAfter: 11 * oneHour, - assetsBootstrapLocation: 'assets/assets.json', - pslAssetKey: 'public_suffix_list.dat', - - // list of live hosts files - liveHostsFiles: { - }, - - // urls stats are kept on the back burner while waiting to be - // reactivated in a tab or another. - pageStores: {}, - pageStoresToken: 0, - pageStoreCemetery: {}, - - // page url => permission scope - tMatrix: null, - pMatrix: null, - - ubiquitousBlacklist: new LiquidDict(), - ubiquitousWhitelist: new LiquidDict(), - - // various stats - requestStatsFactory: requestStatsFactory, - requestStats: requestStatsFactory(), - cookieRemovedCounter: 0, - localStorageRemovedCounter: 0, - cookieHeaderFoiledCounter: 0, - refererHeaderFoiledCounter: 0, - hyperlinkAuditingFoiledCounter: 0, - browserCacheClearedCounter: 0, - storageUsed: 0, - - // record what the browser is doing behind the scene - behindTheSceneScope: 'behind-the-scene', - - noopFunc: function () {}, + disableUpdateIcon: false, + resolveCname: false, + assetsVersion: 1, + }, + + rawSettingsDefault: rawSettingsDefault, + rawSettings: Object.assign({}, rawSettingsDefault), + rawSettingsWriteTime: 0, + + clearBrowserCacheCycle: 0, + cspNoInlineScript: "script-src 'unsafe-eval' blob: *", + cspNoInlineStyle: "style-src blob: *", + cspNoWorker: undefined, + updateAssetsEvery: 11 * oneDay + 1 * oneHour + 1 * oneMinute + 1 * oneSecond, + firstUpdateAfter: 11 * oneMinute, + nextUpdateAfter: 11 * oneHour, + assetsBootstrapLocation: 'assets/assets.json', + pslAssetKey: 'public_suffix_list.dat', + + // list of live hosts files + liveHostsFiles: { + }, + + // urls stats are kept on the back burner while waiting to be + // reactivated in a tab or another. + pageStores: {}, + pageStoresToken: 0, + pageStoreCemetery: {}, + + // page url => permission scope + tMatrix: null, + pMatrix: null, + + ubiquitousBlacklist: new LiquidDict(), + ubiquitousWhitelist: new LiquidDict(), + + // various stats + requestStatsFactory: requestStatsFactory, + requestStats: requestStatsFactory(), + cookieRemovedCounter: 0, + localStorageRemovedCounter: 0, + cookieHeaderFoiledCounter: 0, + refererHeaderFoiledCounter: 0, + hyperlinkAuditingFoiledCounter: 0, + browserCacheClearedCounter: 0, + storageUsed: 0, + + // record what the browser is doing behind the scene + behindTheSceneScope: 'behind-the-scene', + + noopFunc: function () {}, }; })(); diff --git a/js/browsercache.js b/js/browsercache.js index 496d2d2..283820e 100644 --- a/js/browsercache.js +++ b/js/browsercache.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2015-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -27,29 +27,29 @@ // Browser data jobs let clearCache = function () { - vAPI.setTimeout(clearCache, 15 * 60 * 1000); + vAPI.setTimeout(clearCache, 15 * 60 * 1000); - var ηm = ηMatrix; - if (!ηm.userSettings.clearBrowserCache) { + var ηm = ηMatrix; + if (!ηm.userSettings.clearBrowserCache) { return; - } + } - ηm.clearBrowserCacheCycle -= 15; - if (ηm.clearBrowserCacheCycle > 0) { + ηm.clearBrowserCacheCycle -= 15; + if (ηm.clearBrowserCacheCycle > 0) { return; - } + } - vAPI.browser.data.clearCache(); + vAPI.browser.data.clearCache(); - ηm.clearBrowserCacheCycle = ηm.userSettings.clearBrowserCacheAfter; - ++ηm.browserCacheClearedCounter; + ηm.clearBrowserCacheCycle = ηm.userSettings.clearBrowserCacheAfter; + ++ηm.browserCacheClearedCounter; - // TODO: i18n - ηm.logger.writeOne('', 'info', - vAPI.i18n('loggerEntryBrowserCacheCleared')); + // TODO: i18n + ηm.logger.writeOne('', 'info', + vAPI.i18n('loggerEntryBrowserCacheCleared')); - // console.debug('clearBrowserCacheCallback()> ' - // + 'vAPI.browser.data.clearCache() called'); + // console.debug('clearBrowserCacheCallback()> ' + // + 'vAPI.browser.data.clearCache() called'); }; vAPI.setTimeout(clearCache, 15 * 60 * 1000); diff --git a/js/cloud-ui.js b/js/cloud-ui.js index 6d5e875..51919af 100644 --- a/js/cloud-ui.js +++ b/js/cloud-ui.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2015-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uBlock */ @@ -25,34 +25,34 @@ (function () { self.cloud = { - options: {}, - datakey: '', - data: undefined, - onPush: null, - onPull: null + options: {}, + datakey: '', + data: undefined, + onPush: null, + onPull: null }; let widget = uDom.nodeFromId('cloudWidget'); if (widget === null) { - return; + return; } self.cloud.datakey = widget.getAttribute('data-cloud-entry') || ''; if (self.cloud.datakey === '') { - return; + return; } let onCloudDataReceived = function (entry) { - if (typeof entry !== 'object' || entry === null) { + if (typeof entry !== 'object' || entry === null) { return; - } + } - self.cloud.data = entry.data; + self.cloud.data = entry.data; - uDom.nodeFromId('cloudPull').removeAttribute('disabled'); - uDom.nodeFromId('cloudPullAndMerge').removeAttribute('disabled'); + uDom.nodeFromId('cloudPull').removeAttribute('disabled'); + uDom.nodeFromId('cloudPullAndMerge').removeAttribute('disabled'); - let timeOptions = { + let timeOptions = { weekday: 'short', year: 'numeric', month: 'short', @@ -61,100 +61,100 @@ minute: 'numeric', second: 'numeric', timeZoneName: 'short', - }; + }; - let time = new Date(entry.tstamp); - widget.querySelector('span').textContent = entry.source - + '\n' - + time.toLocaleString('fullwide', timeOptions); + let time = new Date(entry.tstamp); + widget.querySelector('span').textContent = entry.source + + '\n' + + time.toLocaleString('fullwide', timeOptions); }; let fetchCloudData = function () { - vAPI.messaging.send('cloud-ui.js', { - what: 'cloudPull', - datakey: self.cloud.datakey + vAPI.messaging.send('cloud-ui.js', { + what: 'cloudPull', + datakey: self.cloud.datakey }, onCloudDataReceived); }; let pushData = function () { - if (typeof self.cloud.onPush !== 'function') { + if (typeof self.cloud.onPush !== 'function') { return; - } + } - vAPI.messaging.send('cloud-ui.js', { - what: 'cloudPush', - datakey: self.cloud.datakey, - data: self.cloud.onPush() + vAPI.messaging.send('cloud-ui.js', { + what: 'cloudPush', + datakey: self.cloud.datakey, + data: self.cloud.onPush() }, fetchCloudData); }; let pullData = function (ev) { - if (typeof self.cloud.onPull === 'function') { + if (typeof self.cloud.onPull === 'function') { self.cloud.onPull(self.cloud.data, ev.shiftKey); - } + } }; let pullAndMergeData = function () { - if (typeof self.cloud.onPull === 'function') { + if (typeof self.cloud.onPull === 'function') { self.cloud.onPull(self.cloud.data, true); - } + } }; let openOptions = function () { - let input = uDom.nodeFromId('cloudDeviceName'); - input.value = self.cloud.options.deviceName; - input.setAttribute('placeholder', self.cloud.options.defaultDeviceName); - uDom.nodeFromId('cloudOptions').classList.add('show'); + let input = uDom.nodeFromId('cloudDeviceName'); + input.value = self.cloud.options.deviceName; + input.setAttribute('placeholder', self.cloud.options.defaultDeviceName); + uDom.nodeFromId('cloudOptions').classList.add('show'); }; let closeOptions = function (ev) { - let root = uDom.nodeFromId('cloudOptions'); - if (ev.target !== root) { + let root = uDom.nodeFromId('cloudOptions'); + if (ev.target !== root) { return; - } - root.classList.remove('show'); + } + root.classList.remove('show'); }; let submitOptions = function () { - let onOptions = function (options) { + let onOptions = function (options) { if (typeof options !== 'object' || options === null) { - return; + return; } self.cloud.options = options; - }; + }; - vAPI.messaging.send('cloud-ui.js', { + vAPI.messaging.send('cloud-ui.js', { what: 'cloudSetOptions', options: { - deviceName: uDom.nodeFromId('cloudDeviceName').value + deviceName: uDom.nodeFromId('cloudDeviceName').value } - }, onOptions); - uDom.nodeFromId('cloudOptions').classList.remove('show'); + }, onOptions); + uDom.nodeFromId('cloudOptions').classList.remove('show'); }; let onInitialize = function (options) { - if (typeof options !== 'object' || options === null) { + if (typeof options !== 'object' || options === null) { return; - } + } - if (!options.enabled) { + if (!options.enabled) { return; - } - self.cloud.options = options; - - let xhr = new XMLHttpRequest(); - xhr.open('GET', 'cloud-ui.html', true); - xhr.overrideMimeType('text/html;charset=utf-8'); - xhr.responseType = 'text'; - xhr.onload = function () { + } + self.cloud.options = options; + + let xhr = new XMLHttpRequest(); + xhr.open('GET', 'cloud-ui.html', true); + xhr.overrideMimeType('text/html;charset=utf-8'); + xhr.responseType = 'text'; + xhr.onload = function () { this.onload = null; let parser = new DOMParser(); - let parsed = parser.parseFromString(this.responseText, 'text/html'); - let fromParent = parsed.body; + let parsed = parser.parseFromString(this.responseText, 'text/html'); + let fromParent = parsed.body; while (fromParent.firstElementChild !== null) { - widget.appendChild(document - .adoptNode(fromParent.firstElementChild)); + widget.appendChild(document + .adoptNode(fromParent.firstElementChild)); } vAPI.i18n.render(widget); @@ -168,13 +168,13 @@ uDom('#cloudOptionsSubmit').on('click', submitOptions); fetchCloudData(); - }; + }; - xhr.send(); + xhr.send(); }; vAPI.messaging.send('cloud-ui.js', { - what: 'cloudGetOptions' + what: 'cloudGetOptions' }, onInitialize); // https://www.youtube.com/watch?v=aQFp67VoiDA diff --git a/js/contentscript-start.js b/js/contentscript-start.js index 4680e8c..b7d74ba 100644 --- a/js/contentscript-start.js +++ b/js/contentscript-start.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2017-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -26,7 +26,7 @@ // Injected into content pages (function () { if (typeof vAPI !== 'object') { - return; + return; } vAPI.selfWorkerSrcReported = vAPI.selfWorkerSrcReported || false; @@ -35,15 +35,15 @@ var handler = function(ev) { if (ev.isTrusted !== true - || ev.originalPolicy.includes('report-uri about:blank') === false) { + || ev.originalPolicy.includes('report-uri about:blank') === false) { return false; } // Firefox and Chromium differs in how they fill the // 'effectiveDirective' property. - // ηMatrix: what does Pale Moon/Basilisk do? + // ηMatrix: what does Pale Moon/Basilisk do? if (ev.effectiveDirective.startsWith('worker-src') === false - && ev.effectiveDirective.startsWith('frame-src') === false) { + && ev.effectiveDirective.startsWith('frame-src') === false) { return false; } @@ -62,8 +62,8 @@ // reports. if (ev.blockedURI.includes('://') === false) { if (vAPI.selfWorkerSrcReported) { - return true; - } + return true; + } vAPI.selfWorkerSrcReported = true; } @@ -80,8 +80,8 @@ document.addEventListener('securitypolicyviolation', function (ev) { if (!handler(ev)) { - return; - } + return; + } ev.stopPropagation(); ev.preventDefault(); }, true); diff --git a/js/contentscript.js b/js/contentscript.js index 21fbcf1..9fb15f8 100644 --- a/js/contentscript.js +++ b/js/contentscript.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -29,54 +29,54 @@ // https://github.com/chrisaljoudi/uBlock/issues/464 // https://github.com/gorhill/uMatrix/issues/621 if (document instanceof HTMLDocument === false - && document instanceof XMLDocument === false) { - return; + && document instanceof XMLDocument === false) { + return; } // This can also happen (for example if script injected into a // `data:` URI doc) if (!window.location) { - return; + return; } // This can happen if (typeof vAPI !== 'object') { - //console.debug('contentscript.js > vAPI not found'); - return; + //console.debug('contentscript.js > vAPI not found'); + return; } // https://github.com/chrisaljoudi/uBlock/issues/456 // Already injected? if (vAPI.contentscriptEndInjected) { - //console.debug('contentscript.js > content script already injected'); - return; + //console.debug('contentscript.js > content script already injected'); + return; } vAPI.contentscriptEndInjected = true; // Executed only once. (function () { - let localStorageHandler = function (mustRemove) { + let localStorageHandler = function (mustRemove) { if (mustRemove) { - window.localStorage.clear(); - window.sessionStorage.clear(); + window.localStorage.clear(); + window.sessionStorage.clear(); } - }; + }; - // Check with extension whether local storage must be emptied - // rhill 2014-03-28: we need an exception handler in case - // 3rd-party access to site data is disabled. - // https://github.com/gorhill/httpswitchboard/issues/215 - try { + // Check with extension whether local storage must be emptied + // rhill 2014-03-28: we need an exception handler in case + // 3rd-party access to site data is disabled. + // https://github.com/gorhill/httpswitchboard/issues/215 + try { let hasLocalStorage = - window.localStorage && window.localStorage.length !== 0; + window.localStorage && window.localStorage.length !== 0; let hasSessionStorage = - window.sessionStorage && window.sessionStorage.length !== 0; + window.sessionStorage && window.sessionStorage.length !== 0; if (hasLocalStorage || hasSessionStorage) { - vAPI.messaging.send('contentscript.js', { + vAPI.messaging.send('contentscript.js', { what: 'contentScriptHasLocalStorage', originURL: window.location.origin - }, localStorageHandler); + }, localStorageHandler); } // TODO: indexedDB @@ -92,13 +92,13 @@ // "There is no way to enumerate or delete the databases available for an origin from this API." // Ref.: http://www.w3.org/TR/webdatabase/#databases // } - } catch (e) { - } + } catch (e) { + } })(); // https://github.com/gorhill/uMatrix/issues/45 let collapser = (function () { - let resquestIdGenerator = 1; + let resquestIdGenerator = 1; let processTimer; let toProcess = []; let toFilter = []; @@ -107,320 +107,320 @@ let cachedBlockedMapHash; let cachedBlockedMapTimer; let reURLPlaceholder = /\{\{url\}\}/g; - let src1stProps = { + let src1stProps = { embed: 'src', iframe: 'src', img: 'src', object: 'data', - }; - let src2ndProps = { + }; + let src2ndProps = { img: 'srcset', - }; - let tagToTypeMap = { + }; + let tagToTypeMap = { embed: 'media', iframe: 'frame', img: 'image', object: 'media', - }; - let cachedBlockedSetClear = function () { + }; + let cachedBlockedSetClear = function () { cachedBlockedMap = - cachedBlockedMapHash = - cachedBlockedMapTimer = undefined; - }; + cachedBlockedMapHash = + cachedBlockedMapTimer = undefined; + }; - // https://github.com/chrisaljoudi/uBlock/issues/174 - // Do not remove fragment from src URL - let onProcessed = function (response) { + // https://github.com/chrisaljoudi/uBlock/issues/174 + // Do not remove fragment from src URL + let onProcessed = function (response) { if (!response) { // This happens if uBO is disabled or restarted. - toCollapse.clear(); - return; + toCollapse.clear(); + return; } let targets = toCollapse.get(response.id); if (targets === undefined) { - return; - } + return; + } toCollapse.delete(response.id); if (cachedBlockedMapHash !== response.hash) { - cachedBlockedMap = new Map(response.blockedResources); - cachedBlockedMapHash = response.hash; - if (cachedBlockedMapTimer !== undefined) { + cachedBlockedMap = new Map(response.blockedResources); + cachedBlockedMapHash = response.hash; + if (cachedBlockedMapTimer !== undefined) { clearTimeout(cachedBlockedMapTimer); - } - cachedBlockedMapTimer = - vAPI.setTimeout(cachedBlockedSetClear, 30000); + } + cachedBlockedMapTimer = + vAPI.setTimeout(cachedBlockedSetClear, 30000); } if (cachedBlockedMap === undefined || cachedBlockedMap.size === 0) { - return; + return; } let placeholders = response.placeholders; for (let target of targets) { - let tag = target.localName; + let tag = target.localName; - let prop = src1stProps[tag]; - if (prop === undefined) { - continue; - } + let prop = src1stProps[tag]; + if (prop === undefined) { + continue; + } - let src = target[prop]; - if (typeof src !== 'string' || src.length === 0) { + let src = target[prop]; + if (typeof src !== 'string' || src.length === 0) { prop = src2ndProps[tag]; if (prop === undefined) { - continue; - } + continue; + } src = target[prop]; if (typeof src !== 'string' || src.length === 0) { - continue; - } - } - - let collapsed = cachedBlockedMap.get(tagToTypeMap[tag] - + ' ' - + src); - if (collapsed === undefined) { - continue; - } - - if (collapsed) { + continue; + } + } + + let collapsed = cachedBlockedMap.get(tagToTypeMap[tag] + + ' ' + + src); + if (collapsed === undefined) { + continue; + } + + if (collapsed) { target.style.setProperty('display', 'none', 'important'); target.hidden = true; continue; - } + } - switch (tag) { - case 'iframe': + switch (tag) { + case 'iframe': if (placeholders.frame !== true) { - break; - } + break; + } let docurl = 'data:text/html,' - + encodeURIComponent(placeholders - .frameDocument - .replace(reURLPlaceholder, src)); + + encodeURIComponent(placeholders + .frameDocument + .replace(reURLPlaceholder, src)); let replaced = false; // Using contentWindow.location prevent tainting browser // history -- i.e. breaking back button (seen on Chromium). if (target.contentWindow) { - try { + try { target.contentWindow.location.replace(docurl); replaced = true; - } catch(ex) { - } + } catch(ex) { + } } if (!replaced) { - target.setAttribute('src', docurl); + target.setAttribute('src', docurl); } break; - case 'img': + case 'img': if (placeholders.image !== true) { - break; - } + break; + } target.style.setProperty('display', 'inline-block'); target.style.setProperty('min-width', '20px', 'important'); target.style.setProperty('min-height', '20px', 'important'); target.style.setProperty('border', placeholders.imageBorder, - 'important'); + 'important'); target.style.setProperty('background', - placeholders.imageBackground, - 'important'); + placeholders.imageBackground, + 'important'); break; - } + } } - }; + }; - let send = function () { + let send = function () { processTimer = undefined; toCollapse.set(resquestIdGenerator, toProcess); let msg = { - what: 'lookupBlockedCollapsibles', - id: resquestIdGenerator, - toFilter: toFilter, - hash: cachedBlockedMapHash + what: 'lookupBlockedCollapsibles', + id: resquestIdGenerator, + toFilter: toFilter, + hash: cachedBlockedMapHash }; vAPI.messaging.send('contentscript.js', msg, onProcessed); toProcess = []; toFilter = []; resquestIdGenerator += 1; - }; + }; - let process = function (delay) { + let process = function (delay) { if (toProcess.length === 0) { - return; - } + return; + } if (delay === 0) { - if (processTimer !== undefined) { + if (processTimer !== undefined) { clearTimeout(processTimer); - } - send(); + } + send(); } else if (processTimer === undefined) { - processTimer = vAPI.setTimeout(send, delay || 47); + processTimer = vAPI.setTimeout(send, delay || 47); } - }; + }; - let add = function (target) { + let add = function (target) { toProcess.push(target); - }; + }; - let addMany = function (targets) { - for (let i=targets.length-1; i>=0; --i) { - toProcess.push(targets[i]); + let addMany = function (targets) { + for (let i=targets.length-1; i>=0; --i) { + toProcess.push(targets[i]); } - }; + }; - let iframeSourceModified = function (mutations) { - for (let i=mutations.length-1; i>=0; --i) { - addIFrame(mutations[i].target, true); + let iframeSourceModified = function (mutations) { + for (let i=mutations.length-1; i>=0; --i) { + addIFrame(mutations[i].target, true); } process(); - }; + }; - let iframeSourceObserver; - let iframeSourceObserverOptions = { + let iframeSourceObserver; + let iframeSourceObserverOptions = { attributes: true, attributeFilter: [ 'src' ] - }; + }; - let addIFrame = function (iframe, dontObserve) { + let addIFrame = function (iframe, dontObserve) { // https://github.com/gorhill/uBlock/issues/162 // Be prepared to deal with possible change of src attribute. if (dontObserve !== true) { - if (iframeSourceObserver === undefined) { + if (iframeSourceObserver === undefined) { iframeSourceObserver = - new MutationObserver(iframeSourceModified); - } - iframeSourceObserver.observe(iframe, - iframeSourceObserverOptions); + new MutationObserver(iframeSourceModified); + } + iframeSourceObserver.observe(iframe, + iframeSourceObserverOptions); } let src = iframe.src; if (src === '' || typeof src !== 'string') { - return; - } + return; + } if (src.startsWith('http') === false) { - return; - } + return; + } toFilter.push({ - type: 'frame', - url: iframe.src, - }); + type: 'frame', + url: iframe.src, + }); add(iframe); - }; + }; - let addIFrames = function (iframes) { - for (let i=iframes.length-1; i>=0; --i) { - addIFrame(iframes[i]); + let addIFrames = function (iframes) { + for (let i=iframes.length-1; i>=0; --i) { + addIFrame(iframes[i]); } - }; - - let addNodeList = function (nodeList) { - for (let i=nodeList.length-1; i>=0; --i) { - let node = nodeList[i]; - if (node.nodeType !== 1) { - continue; - } - if (node.localName === 'iframe') { + }; + + let addNodeList = function (nodeList) { + for (let i=nodeList.length-1; i>=0; --i) { + let node = nodeList[i]; + if (node.nodeType !== 1) { + continue; + } + if (node.localName === 'iframe') { addIFrame(node); - } - if (node.childElementCount !== 0) { + } + if (node.childElementCount !== 0) { addIFrames(node.querySelectorAll('iframe')); - } + } } - }; + }; - let onResourceFailed = function (ev) { + let onResourceFailed = function (ev) { if (tagToTypeMap[ev.target.localName] !== undefined) { - add(ev.target); - process(); + add(ev.target); + process(); } - }; - document.addEventListener('error', onResourceFailed, true); + }; + document.addEventListener('error', onResourceFailed, true); - vAPI.shutdown.add(function () { + vAPI.shutdown.add(function () { document.removeEventListener('error', onResourceFailed, true); if (iframeSourceObserver !== undefined) { - iframeSourceObserver.disconnect(); - iframeSourceObserver = undefined; + iframeSourceObserver.disconnect(); + iframeSourceObserver = undefined; } if (processTimer !== undefined) { - clearTimeout(processTimer); - processTimer = undefined; + clearTimeout(processTimer); + processTimer = undefined; } - }); + }); - return { + return { addMany: addMany, addIFrames: addIFrames, addNodeList: addNodeList, process: process - }; + }; })(); // Observe changes in the DOM // Added node lists will be cumulated here before being processed (function () { - // This fixes http://acid3.acidtests.org/ - if (!document.body) { - return; - } + // This fixes http://acid3.acidtests.org/ + if (!document.body) { + return; + } - let addedNodeLists = []; - let addedNodeListsTimer; + let addedNodeLists = []; + let addedNodeListsTimer; - let treeMutationObservedHandler = function () { + let treeMutationObservedHandler = function () { addedNodeListsTimer = undefined; - for (let i=addedNodeLists.length-1; i>=0; --i) { - collapser.addNodeList(addedNodeLists[i]); + for (let i=addedNodeLists.length-1; i>=0; --i) { + collapser.addNodeList(addedNodeLists[i]); } collapser.process(); addedNodeLists = []; - }; - - // https://github.com/gorhill/uBlock/issues/205 - // Do not handle added node directly from within mutation observer. - let treeMutationObservedHandlerAsync = function (mutations) { - for (let i=mutations.length-1; i>=0; --i) { - let nodeList = mutations[i].addedNodes; - if (nodeList.length !== 0) { + }; + + // https://github.com/gorhill/uBlock/issues/205 + // Do not handle added node directly from within mutation observer. + let treeMutationObservedHandlerAsync = function (mutations) { + for (let i=mutations.length-1; i>=0; --i) { + let nodeList = mutations[i].addedNodes; + if (nodeList.length !== 0) { addedNodeLists.push(nodeList); - } + } } if (addedNodeListsTimer === undefined) { - addedNodeListsTimer = - vAPI.setTimeout(treeMutationObservedHandler, 47); + addedNodeListsTimer = + vAPI.setTimeout(treeMutationObservedHandler, 47); } - }; + }; - // https://github.com/gorhill/httpswitchboard/issues/176 - let treeObserver = - new MutationObserver(treeMutationObservedHandlerAsync); - treeObserver.observe(document.body, { + // https://github.com/gorhill/httpswitchboard/issues/176 + let treeObserver = + new MutationObserver(treeMutationObservedHandlerAsync); + treeObserver.observe(document.body, { childList: true, subtree: true - }); + }); - vAPI.shutdown.add(function () { + vAPI.shutdown.add(function () { if (addedNodeListsTimer !== undefined) { - clearTimeout(addedNodeListsTimer); - addedNodeListsTimer = undefined; + clearTimeout(addedNodeListsTimer); + addedNodeListsTimer = undefined; } if (treeObserver !== null) { - treeObserver.disconnect(); - treeObserver = undefined; + treeObserver.disconnect(); + treeObserver = undefined; } addedNodeLists = []; - }); + }); })(); // Executed only once. @@ -437,58 +437,58 @@ // Report inline styles. (function () { - if (document.querySelector('script:not([src])') !== null - || document.querySelector('a[href^="javascript:"]') !== null - || document.querySelector('[onabort],[onblur],[oncancel],' - + '[oncanplay],[oncanplaythrough],' - + '[onchange],[onclick],[onclose],' - + '[oncontextmenu],[oncuechange],' - + '[ondblclick],[ondrag],[ondragend],' - + '[ondragenter],[ondragexit],' - + '[ondragleave],[ondragover],' - + '[ondragstart],[ondrop],' - + '[ondurationchange],[onemptied],' - + '[onended],[onerror],[onfocus],' - + '[oninput],[oninvalid],[onkeydown],' - + '[onkeypress],[onkeyup],[onload],' - + '[onloadeddata],[onloadedmetadata],' - + '[onloadstart],[onmousedown],' - + '[onmouseenter],[onmouseleave],' - + '[onmousemove],[onmouseout],' - + '[onmouseover],[onmouseup],[onwheel],' - + '[onpause],[onplay],[onplaying],' - + '[onprogress],[onratechange],[onreset],' - + '[onresize],[onscroll],[onseeked],' - + '[onseeking],[onselect],[onshow],' - + '[onstalled],[onsubmit],[onsuspend],' - + '[ontimeupdate],[ontoggle],' - + '[onvolumechange],[onwaiting],' - + '[onafterprint],[onbeforeprint],' - + '[onbeforeunload],[onhashchange],' - + '[onlanguagechange],[onmessage],' - + '[onoffline],[ononline],[onpagehide],' - + '[onpageshow],[onrejectionhandled],' - + '[onpopstate],[onstorage],' - + '[onunhandledrejection],[onunload],' - + '[oncopy],[oncut],[onpaste]') !== null) { + if (document.querySelector('script:not([src])') !== null + || document.querySelector('a[href^="javascript:"]') !== null + || document.querySelector('[onabort],[onblur],[oncancel],' + + '[oncanplay],[oncanplaythrough],' + + '[onchange],[onclick],[onclose],' + + '[oncontextmenu],[oncuechange],' + + '[ondblclick],[ondrag],[ondragend],' + + '[ondragenter],[ondragexit],' + + '[ondragleave],[ondragover],' + + '[ondragstart],[ondrop],' + + '[ondurationchange],[onemptied],' + + '[onended],[onerror],[onfocus],' + + '[oninput],[oninvalid],[onkeydown],' + + '[onkeypress],[onkeyup],[onload],' + + '[onloadeddata],[onloadedmetadata],' + + '[onloadstart],[onmousedown],' + + '[onmouseenter],[onmouseleave],' + + '[onmousemove],[onmouseout],' + + '[onmouseover],[onmouseup],[onwheel],' + + '[onpause],[onplay],[onplaying],' + + '[onprogress],[onratechange],[onreset],' + + '[onresize],[onscroll],[onseeked],' + + '[onseeking],[onselect],[onshow],' + + '[onstalled],[onsubmit],[onsuspend],' + + '[ontimeupdate],[ontoggle],' + + '[onvolumechange],[onwaiting],' + + '[onafterprint],[onbeforeprint],' + + '[onbeforeunload],[onhashchange],' + + '[onlanguagechange],[onmessage],' + + '[onoffline],[ononline],[onpagehide],' + + '[onpageshow],[onrejectionhandled],' + + '[onpopstate],[onstorage],' + + '[onunhandledrejection],[onunload],' + + '[oncopy],[oncut],[onpaste]') !== null) { vAPI.messaging.send('contentscript.js', { - what: 'securityPolicyViolation', - directive: 'script-src', - documentURI: window.location.href + what: 'securityPolicyViolation', + directive: 'script-src', + documentURI: window.location.href }); - } + } - if (document.querySelector('style,[style]') !== null) { + if (document.querySelector('style,[style]') !== null) { vAPI.messaging.send('contentscript.js', { - what: 'securityPolicyViolation', - directive: 'style-src', - documentURI: window.location.href + what: 'securityPolicyViolation', + directive: 'style-src', + documentURI: window.location.href }); - } + } - collapser.addMany(document.querySelectorAll('img')); - collapser.addIFrames(document.querySelectorAll('iframe')); - collapser.process(); + collapser.addMany(document.querySelectorAll('img')); + collapser.addIFrames(document.querySelectorAll('iframe')); + collapser.process(); })(); // Executed only once. @@ -496,88 +496,88 @@ // Force `display` property, Firefox is still affected by the issue. (function () { - let noscripts = document.querySelectorAll('noscript'); - if (noscripts.length === 0) { - return; - } + let noscripts = document.querySelectorAll('noscript'); + if (noscripts.length === 0) { + return; + } - let redirectTimer; + let redirectTimer; let reMetaContent = /^\s*(\d+)\s*;\s*url=(['"]?)([^'"]+)\2/i; let reSafeURL = /^https?:\/\//; - let autoRefresh = function (root) { + let autoRefresh = function (root) { let meta = - root.querySelector('meta[http-equiv="refresh"][content]'); + root.querySelector('meta[http-equiv="refresh"][content]'); if (meta === null) { - return; - } + return; + } let match = reMetaContent.exec(meta.getAttribute('content')); if (match === null || match[3].trim() === '') { - return; - } + return; + } let url = new URL(match[3], document.baseURI); if (reSafeURL.test(url.href) === false) { - return; - } + return; + } redirectTimer = setTimeout(function () { location.assign(url.href); - }, parseInt(match[1], 10) * 1000 + 1); + }, parseInt(match[1], 10) * 1000 + 1); meta.parentNode.removeChild(meta); - }; + }; - let morphNoscript = function (from) { + let morphNoscript = function (from) { if (/^application\/(?:xhtml\+)?xml/.test(document.contentType)) { - let to = document.createElement('span'); - while (from.firstChild !== null) { + let to = document.createElement('span'); + while (from.firstChild !== null) { to.appendChild(from.firstChild); - } - return to; + } + return to; } let parser = new DOMParser(); let doc = - parser.parseFromString('<span>' + from.textContent + '</span>', - 'text/html'); + parser.parseFromString('<span>' + from.textContent + '</span>', + 'text/html'); return document.adoptNode(doc.querySelector('span')); - }; + }; - let renderNoscriptTags = function (response) { + let renderNoscriptTags = function (response) { if (response !== true) { - return; - } + return; + } for (let noscript of noscripts) { - let parent = noscript.parentNode; - if (parent === null) { - continue; - } + let parent = noscript.parentNode; + if (parent === null) { + continue; + } - let span = morphNoscript(noscript); - span.style.setProperty('display', 'inline', 'important'); + let span = morphNoscript(noscript); + span.style.setProperty('display', 'inline', 'important'); - if (redirectTimer === undefined) { + if (redirectTimer === undefined) { autoRefresh(span); - } + } - parent.replaceChild(span, noscript); + parent.replaceChild(span, noscript); } - }; + }; - vAPI.messaging.send('contentscript.js', { - what: 'mustRenderNoscriptTags?' - }, renderNoscriptTags); + vAPI.messaging.send('contentscript.js', { + what: 'mustRenderNoscriptTags?' + }, renderNoscriptTags); })(); vAPI.messaging.send('contentscript.js', { - what: 'shutdown?' + what: 'shutdown?' }, function (response) { if (response === true) { - vAPI.shutdown.exec(); + vAPI.shutdown.exec(); } }); })(); diff --git a/js/cookies.js b/js/cookies.js index 217468b..b176fbb 100644 --- a/js/cookies.js +++ b/js/cookies.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2013-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -50,205 +50,205 @@ // Look for cookies to record for a specific web page let recordPageCookiesAsync = function (pageStats) { - // Store the page stats objects so that it doesn't go away - // before we handle the job. - // rhill 2013-10-19: pageStats could be nil, for example, this can - // happens if a file:// ... makes an xmlHttpRequest - if (!pageStats) { + // Store the page stats objects so that it doesn't go away + // before we handle the job. + // rhill 2013-10-19: pageStats could be nil, for example, this can + // happens if a file:// ... makes an xmlHttpRequest + if (!pageStats) { return; - } - recordPageCookiesQueue.set(pageStats.pageUrl, pageStats); - if (processPageRecordQueueTimer === null) { + } + recordPageCookiesQueue.set(pageStats.pageUrl, pageStats); + if (processPageRecordQueueTimer === null) { processPageRecordQueueTimer = - vAPI.setTimeout(processPageRecordQueue, 1000); - } + vAPI.setTimeout(processPageRecordQueue, 1000); + } }; let cookieLogEntryBuilder = [ - '', - '{', - '', - '-cookie:', - '', - '}' + '', + '{', + '', + '-cookie:', + '', + '}' ]; let recordPageCookie = function (pageStore, key) { - if (vAPI.isBehindTheSceneTabId(pageStore.tabId)) { + if (vAPI.isBehindTheSceneTabId(pageStore.tabId)) { + return; + } + + let entry = CookieCache.get(key); + let pageHostname = pageStore.pageHostname; + let block = ηm.mustBlock(pageHostname, entry.hostname, 'cookie'); + + cookieLogEntryBuilder[0] = CookieUtils.urlFromEntry(entry); + cookieLogEntryBuilder[2] = entry.session ? 'session' : 'persistent'; + cookieLogEntryBuilder[4] = encodeURIComponent(entry.name); + + let cookieURL = cookieLogEntryBuilder.join(''); + + // rhill 2013-11-20: + // https://github.com/gorhill/httpswitchboard/issues/60 + // Need to URL-encode cookie name + pageStore.recordRequest('cookie', cookieURL, block); + ηm.logger.writeOne(pageStore.tabId, 'net', + pageHostname, cookieURL, 'cookie', block); + + entry.usedOn.add(pageHostname); + + // rhill 2013-11-21: + // https://github.com/gorhill/httpswitchboard/issues/65 + // Leave alone cookies from behind-the-scene requests if + // behind-the-scene processing is disabled. + if (!block) { return; - } - - let entry = CookieCache.get(key); - let pageHostname = pageStore.pageHostname; - let block = ηm.mustBlock(pageHostname, entry.hostname, 'cookie'); - - cookieLogEntryBuilder[0] = CookieUtils.urlFromEntry(entry); - cookieLogEntryBuilder[2] = entry.session ? 'session' : 'persistent'; - cookieLogEntryBuilder[4] = encodeURIComponent(entry.name); - - let cookieURL = cookieLogEntryBuilder.join(''); - - // rhill 2013-11-20: - // https://github.com/gorhill/httpswitchboard/issues/60 - // Need to URL-encode cookie name - pageStore.recordRequest('cookie', cookieURL, block); - ηm.logger.writeOne(pageStore.tabId, 'net', - pageHostname, cookieURL, 'cookie', block); - - entry.usedOn.add(pageHostname); - - // rhill 2013-11-21: - // https://github.com/gorhill/httpswitchboard/issues/65 - // Leave alone cookies from behind-the-scene requests if - // behind-the-scene processing is disabled. - if (!block) { - return; - } - if (!ηm.userSettings.deleteCookies) { + } + if (!ηm.userSettings.deleteCookies) { return; - } - removeCookieAsync(key); + } + removeCookieAsync(key); }; // Look for cookies to potentially remove for a specific web page let removePageCookiesAsync = function (pageStats) { - // Hold onto pageStats objects so that it doesn't go away - // before we handle the job. - // rhill 2013-10-19: pageStats could be nil, for example, this can - // happens if a file:// ... makes an xmlHttpRequest - if (!pageStats) { + // Hold onto pageStats objects so that it doesn't go away + // before we handle the job. + // rhill 2013-10-19: pageStats could be nil, for example, this can + // happens if a file:// ... makes an xmlHttpRequest + if (!pageStats) { return; - } - removePageCookiesQueue.set(pageStats.pageUrl, pageStats); - if (processPageRemoveQueueTimer === null) { + } + removePageCookiesQueue.set(pageStats.pageUrl, pageStats); + if (processPageRemoveQueueTimer === null) { processPageRemoveQueueTimer = - vAPI.setTimeout(processPageRemoveQueue, 15 * 1000); - } + vAPI.setTimeout(processPageRemoveQueue, 15 * 1000); + } }; // Candidate for removal let removeCookieAsync = function (key) { - removeCookieQueue.add(key); + removeCookieQueue.add(key); }; let chromeCookieRemove = function (entry, name) { - let url = CookieUtils.urlFromEntry(entry); - if (url === '') { + let url = CookieUtils.urlFromEntry(entry); + if (url === '') { return; - } - let sessionKey = CookieUtils.keyFromURL(UriTools.set(url), - 'session', name); - let persistKey = CookieUtils.keyFromURL(UriTools.set(url), - 'persistent', name); + } + let sessionKey = CookieUtils.keyFromURL(UriTools.set(url), + 'session', name); + let persistKey = CookieUtils.keyFromURL(UriTools.set(url), + 'persistent', name); - let callback = function(details) { + let callback = function(details) { let success = !!details; let template = success ? - i18nCookieDeleteSuccess : - i18nCookieDeleteFailure; + i18nCookieDeleteSuccess : + i18nCookieDeleteFailure; if (CookieCache.remove(sessionKey)) { - if (success) { + if (success) { ηm.cookieRemovedCounter += 1; - } - ηm.logger.writeOne('', 'info', 'cookie', - template.replace('{{value}}', - sessionKey)); + } + ηm.logger.writeOne('', 'info', 'cookie', + template.replace('{{value}}', + sessionKey)); } if (CookieCache.remove(persistKey)) { - if (success) { + if (success) { ηm.cookieRemovedCounter += 1; - } - ηm.logger.writeOne('', 'info', 'cookie', - template.replace('{{value}}', - persistKey)); + } + ηm.logger.writeOne('', 'info', 'cookie', + template.replace('{{value}}', + persistKey)); } - }; + }; - vAPI.cookies.remove({ - url: url, name: name - }, callback); + vAPI.cookies.remove({ + url: url, name: name + }, callback); }; let i18nCookieDeleteSuccess = vAPI.i18n('loggerEntryCookieDeleted'); let i18nCookieDeleteFailure = vAPI.i18n('loggerEntryDeleteCookieError'); let processPageRecordQueue = function () { - processPageRecordQueueTimer = null; + processPageRecordQueueTimer = null; - for (let pageStore of recordPageCookiesQueue.values()) { + for (let pageStore of recordPageCookiesQueue.values()) { findAndRecordPageCookies(pageStore); - } - recordPageCookiesQueue.clear(); + } + recordPageCookiesQueue.clear(); }; let processPageRemoveQueue = function () { - processPageRemoveQueueTimer = null; + processPageRemoveQueueTimer = null; - for (let pageStore of removePageCookiesQueue.values()) { + for (let pageStore of removePageCookiesQueue.values()) { findAndRemovePageCookies(pageStore); - } - removePageCookiesQueue.clear(); + } + removePageCookiesQueue.clear(); }; // Effectively remove cookies. let processRemoveQueue = function () { - let userSettings = ηm.userSettings; - let deleteCookies = userSettings.deleteCookies; - - // Session cookies which timestamp is *after* tstampObsolete will - // be left untouched - // https://github.com/gorhill/httpswitchboard/issues/257 - let dusc = userSettings.deleteUnusedSessionCookies; - let dusca = userSettings.deleteUnusedSessionCookiesAfter; - let tstampObsolete = dusc ? - Date.now() - dusca * 60 * 1000 : + let userSettings = ηm.userSettings; + let deleteCookies = userSettings.deleteCookies; + + // Session cookies which timestamp is *after* tstampObsolete will + // be left untouched + // https://github.com/gorhill/httpswitchboard/issues/257 + let dusc = userSettings.deleteUnusedSessionCookies; + let dusca = userSettings.deleteUnusedSessionCookiesAfter; + let tstampObsolete = dusc ? + Date.now() - dusca * 60 * 1000 : 0; - let srcHostnames; - let entry; + let srcHostnames; + let entry; - for (let key of removeCookieQueue) { + for (let key of removeCookieQueue) { // rhill 2014-05-12: Apparently this can happen. I have to // investigate how (A session cookie has same name as a // persistent cookie?) entry = CookieCache.get(key); if (entry === undefined) { - continue; - } + continue; + } // Delete obsolete session cookies: enabled. if (tstampObsolete !== 0 && entry.session) { - if (entry.tstamp < tstampObsolete) { + if (entry.tstamp < tstampObsolete) { chromeCookieRemove(entry, entry.name); continue; - } + } } // Delete all blocked cookies: disabled. if (deleteCookies === false) { - continue; + continue; } // Query scopes only if we are going to use them if (srcHostnames === undefined) { - srcHostnames = ηm.tMatrix.extractAllSourceHostnames(); + srcHostnames = ηm.tMatrix.extractAllSourceHostnames(); } // Ensure cookie is not allowed on ALL current web pages: It can // happen that a cookie is blacklisted on one web page while // being whitelisted on another (because of per-page permissions). if (canRemoveCookie(key, srcHostnames)) { - chromeCookieRemove(entry, entry.name); + chromeCookieRemove(entry, entry.name); } - } + } - removeCookieQueue.clear(); + removeCookieQueue.clear(); - vAPI.setTimeout(processRemoveQueue, processRemoveQueuePeriod); + vAPI.setTimeout(processRemoveQueue, processRemoveQueuePeriod); }; // Once in a while, we go ahead and clean everything that might have been @@ -258,145 +258,145 @@ // maybe a user has 1000s of cookies sitting in his browser... let processClean = function () { - let us = ηm.userSettings; + let us = ηm.userSettings; - if (us.deleteCookies || us.deleteUnusedSessionCookies) { + if (us.deleteCookies || us.deleteUnusedSessionCookies) { let keys = Array.from(CookieCache.keys()); - let len = keys.length; - let step, offset, n; + let len = keys.length; + let step, offset, n; if (len > 25) { - step = len / 25; - offset = Math.floor(Math.random() * len); - n = 25; + step = len / 25; + offset = Math.floor(Math.random() * len); + n = 25; } else { - step = 1; - offset = 0; - n = len; + step = 1; + offset = 0; + n = len; } let i = offset; while (n--) { - removeCookieAsync(keys[Math.floor(i % len)]); - i += step; + removeCookieAsync(keys[Math.floor(i % len)]); + i += step; } - } + } - vAPI.setTimeout(processClean, processCleanPeriod); + vAPI.setTimeout(processClean, processCleanPeriod); }; let findAndRecordPageCookies = function (pageStore) { - for (let key of CookieCache.keys()) { + for (let key of CookieCache.keys()) { if (CookieUtils.matchDomains(key, pageStore.allHostnamesString)) { - recordPageCookie(pageStore, key); + recordPageCookie(pageStore, key); } - } + } }; let findAndRemovePageCookies = function (pageStore) { - for (let key of CookieCache.keys()) { + for (let key of CookieCache.keys()) { if (CookieUtils.matchDomains(key, pageStore.allHostnamesString)) { - removeCookieAsync(key); + removeCookieAsync(key); } - } + } }; let canRemoveCookie = function (key, srcHostnames) { - let entry = CookieCache.get(key); - if (entry === undefined) { - return false; - } + let entry = CookieCache.get(key); + if (entry === undefined) { + return false; + } - let cookieHostname = entry.hostname; - let srcHostname; + let cookieHostname = entry.hostname; + let srcHostname; - for (srcHostname of entry.usedOn) { + for (srcHostname of entry.usedOn) { if (ηm.mustAllow(srcHostname, cookieHostname, 'cookie')) { - return false; + return false; } - } + } - // Maybe there is a scope in which the cookie is 1st-party-allowed. - // For example, if I am logged in into `github.com`, I do not want to be - // logged out just because I did not yet open a `github.com` page after - // re-starting the browser. - srcHostname = cookieHostname; + // Maybe there is a scope in which the cookie is 1st-party-allowed. + // For example, if I am logged in into `github.com`, I do not want to be + // logged out just because I did not yet open a `github.com` page after + // re-starting the browser. + srcHostname = cookieHostname; - let pos; + let pos; - for (;;) { + for (;;) { if (srcHostnames.has(srcHostname)) { - if (ηm.mustAllow(srcHostname, cookieHostname, 'cookie')) { + if (ηm.mustAllow(srcHostname, cookieHostname, 'cookie')) { return false; - } + } } if (srcHostname === entry.domain) { - break; + break; } pos = srcHostname.indexOf('.'); if (pos === -1) { - break; + break; } srcHostname = srcHostname.slice(pos + 1); - } - return true; + } + return true; }; // Listen to any change in cookieland, we will update page stats accordingly. vAPI.cookies.onChanged = function (cookie) { - // rhill 2013-12-11: If cookie value didn't change, no need to record. - // https://github.com/gorhill/httpswitchboard/issues/79 - let key = CookieUtils.keyFromCookie(cookie); - let entry = CookieCache.get(key); + // rhill 2013-12-11: If cookie value didn't change, no need to record. + // https://github.com/gorhill/httpswitchboard/issues/79 + let key = CookieUtils.keyFromCookie(cookie); + let entry = CookieCache.get(key); - if (entry === undefined) { + if (entry === undefined) { entry = CookieCache.add(cookie); - } else { + } else { entry.tstamp = Date.now(); if (cookie.value === entry.value) { - return; - } + return; + } entry.value = cookie.value; - } + } - // Go through all pages and update if needed, as one cookie can be used - // by many web pages, so they need to be recorded for all these pages. - let pageStores = ηm.pageStores; - let pageStore; - for (let tabId in pageStores) { + // Go through all pages and update if needed, as one cookie can be used + // by many web pages, so they need to be recorded for all these pages. + let pageStores = ηm.pageStores; + let pageStore; + for (let tabId in pageStores) { if (pageStores.hasOwnProperty(tabId) === false) { - continue; + continue; } pageStore = pageStores[tabId]; if (!CookieUtils.matchDomains(key, pageStore.allHostnamesString)) { - continue; + continue; } recordPageCookie(pageStore, key); - } + } }; // Listen to any change in cookieland, we will update page stats accordingly. vAPI.cookies.onRemoved = function (cookie) { - let key = CookieUtils.keyFromCookie(cookie); - if (CookieCache.remove(key)) { + let key = CookieUtils.keyFromCookie(cookie); + if (CookieCache.remove(key)) { ηm.logger.writeOne('', 'info', 'cookie', - i18nCookieDeleteSuccess.replace('{{value}}', - key)); - } + i18nCookieDeleteSuccess.replace('{{value}}', + key)); + } }; // Listen to any change in cookieland, we will update page stats accordingly. vAPI.cookies.onAllRemoved = function () { - for (let key of CookieCache.keys()) { + for (let key of CookieCache.keys()) { if (CookieCache.remove(key)) { - ηm.logger.writeOne('', 'info', 'cookie', - i18nCookieDeleteSuccess.replace('{{value}}', - key)); + ηm.logger.writeOne('', 'info', 'cookie', + i18nCookieDeleteSuccess.replace('{{value}}', + key)); } - } + } }; vAPI.cookies.getAll(CookieCache.addVector); @@ -408,7 +408,7 @@ // Expose only what is necessary return { - recordPageCookies: recordPageCookiesAsync, - removePageCookies: removePageCookiesAsync + recordPageCookies: recordPageCookiesAsync, + removePageCookies: removePageCookiesAsync }; })(); diff --git a/js/dashboard-common.js b/js/dashboard-common.js index 677a3f3..b0eb9cf 100644 --- a/js/dashboard-common.js +++ b/js/dashboard-common.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -28,8 +28,8 @@ uDom.onLoad(function () { uDom('a').attr('target', '_blank'); uDom('a[href*="dashboard.html"]').attr('target', '_parent'); uDom('.whatisthis').on('click', function () { - uDom(this) - .parent() + uDom(this) + .parent() .descendants('.whatisthis-expandable') .toggleClass('whatisthis-expanded'); }); diff --git a/js/dashboard.js b/js/dashboard.js index 8e565f6..6a466be 100644 --- a/js/dashboard.js +++ b/js/dashboard.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -30,7 +30,7 @@ uDom('iframe').attr('src', url); uDom('.tabButton').forEach(function (button) { button.toggleClass('selected', - button.attr('data-dashboard-panel-url') === url); + button.attr('data-dashboard-panel-url') === url); }); }; diff --git a/js/hosts-files.js b/js/hosts-files.js index b2f19f6..92a7efc 100644 --- a/js/hosts-files.js +++ b/js/hosts-files.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -30,104 +30,104 @@ let reValidExternalList = /[a-z-]+:\/\/\S*\/\S+/; vAPI.messaging.addListener(function (msg) { - switch (msg.what) { - case 'assetUpdated': + switch (msg.what) { + case 'assetUpdated': updateAssetStatus(msg); break; - case 'assetsUpdated': + case 'assetsUpdated': document.body.classList.remove('updating'); break; - case 'loadHostsFilesCompleted': + case 'loadHostsFilesCompleted': renderHostsFiles(); break; - default: + default: break; - } + } }); let renderNumber = function (value) { - return value.toLocaleString(); + return value.toLocaleString(); }; let renderHostsFiles = function (soft) { - let listEntryTemplate = uDom('#templates .listEntry'); + let listEntryTemplate = uDom('#templates .listEntry'); let listStatsTemplate = vAPI.i18n('hostsFilesPerFileStats'); let renderETTS = vAPI.i18n.renderElapsedTimeToString; let reExternalHostFile = /^https?:/; - // Assemble a pretty list name if possible - let listNameFromListKey = function (listKey) { + // Assemble a pretty list name if possible + let listNameFromListKey = function (listKey) { let list = - listDetails.current[listKey] || listDetails.available[listKey]; + listDetails.current[listKey] || listDetails.available[listKey]; let listTitle = list ? list.title : ''; if (listTitle === '') { - return listKey; - } + return listKey; + } return listTitle; - }; + }; - let liFromListEntry = function (listKey, li) { + let liFromListEntry = function (listKey, li) { let entry = listDetails.available[listKey]; - let elem; + let elem; if (!li) { - li = listEntryTemplate.clone().nodeAt(0); + li = listEntryTemplate.clone().nodeAt(0); } if (li.getAttribute('data-listkey') !== listKey) { - li.setAttribute('data-listkey', listKey); + li.setAttribute('data-listkey', listKey); - elem = li.querySelector('input[type="checkbox"]'); - elem.checked = (entry.off !== true); - elem = li.querySelector('a:nth-of-type(1)'); - elem.setAttribute('href', - 'asset-viewer.html?url=' + encodeURI(listKey)); - elem.setAttribute('type', 'text/html'); - elem.textContent = listNameFromListKey(listKey); + elem = li.querySelector('input[type="checkbox"]'); + elem.checked = (entry.off !== true); + elem = li.querySelector('a:nth-of-type(1)'); + elem.setAttribute('href', + 'asset-viewer.html?url=' + encodeURI(listKey)); + elem.setAttribute('type', 'text/html'); + elem.textContent = listNameFromListKey(listKey); - li.classList.remove('toRemove'); + li.classList.remove('toRemove'); - if (entry.supportName) { + if (entry.supportName) { li.classList.add('support'); elem = li.querySelector('a.support'); elem.setAttribute('href', entry.supportURL); elem.setAttribute('title', entry.supportName); - } else { + } else { li.classList.remove('support'); - } + } - if (entry.external) { + if (entry.external) { li.classList.add('external'); - } else { + } else { li.classList.remove('external'); - } + } - if (entry.instructionURL) { + if (entry.instructionURL) { li.classList.add('mustread'); elem = li.querySelector('a.mustread'); elem.setAttribute('href', entry.instructionURL); - } else { + } else { li.classList.remove('mustread'); - } + } } // https://github.com/gorhill/uBlock/issues/1429 if (!soft) { - elem = li.querySelector('input[type="checkbox"]'); - elem.checked = entry.off !== true; + elem = li.querySelector('input[type="checkbox"]'); + elem.checked = entry.off !== true; } elem = li.querySelector('span.counts'); let text = ''; if (!isNaN(+entry.entryUsedCount) && !isNaN(+entry.entryCount)) { - text = listStatsTemplate + text = listStatsTemplate .replace('{{used}}', - renderNumber(entry.off ? 0 : entry.entryUsedCount)) + renderNumber(entry.off ? 0 : entry.entryUsedCount)) .replace('{{total}}', - renderNumber(entry.entryCount)); + renderNumber(entry.entryCount)); } elem.textContent = text; @@ -137,26 +137,26 @@ let remoteURL = asset.remoteURL; li.classList.toggle('unsecure', - typeof remoteURL === 'string' - && remoteURL.lastIndexOf('http:', 0) === 0); + typeof remoteURL === 'string' + && remoteURL.lastIndexOf('http:', 0) === 0); li.classList.toggle('failed', asset.error !== undefined); li.classList.toggle('obsolete', asset.obsolete === true); li.classList.toggle('cached', - asset.cached === true && asset.writeTime > 0); + asset.cached === true && asset.writeTime > 0); if (asset.cached) { - li.querySelector('.status.cache') - .setAttribute('title', - lastUpdateTemplateString - .replace('{{ago}}', - renderETTS(asset.writeTime))); + li.querySelector('.status.cache') + .setAttribute('title', + lastUpdateTemplateString + .replace('{{ago}}', + renderETTS(asset.writeTime))); } li.classList.remove('discard'); return li; - }; + }; - let onListsReceived = function (details) { + let onListsReceived = function (details) { // Before all, set context vars listDetails = details; @@ -165,225 +165,227 @@ uDom('#lists .listEntry').addClass('discard'); let availableLists = details.available; - let listKeys = Object.keys(details.available); + let listKeys = Object.keys(details.available); // Sort works this way: // - Send /^https?:/ items at the end (custom hosts file URL) listKeys.sort(function (a, b) { - let ta = availableLists[a].title || a; + let ta = availableLists[a].title || a; let tb = availableLists[b].title || b; + let ca = reExternalHostFile.test(ta); + let cb = reExternalHostFile.test(tb); - if (reExternalHostFile.test(ta) === reExternalHostFile.test(tb)) { + if (ca === cb) { return ta.localeCompare(tb); - } + } - return reExternalHostFile.test(tb) ? -1 : 1; + return (cb) ? -1 : 1; }); let ulList = document.querySelector('#lists'); for (let i=0; i<listKeys.length; ++i) { - let liEntry = liFromListEntry(listKeys[i], ulList.children[i]); - if (liEntry.parentElement === null) { + let liEntry = liFromListEntry(listKeys[i], ulList.children[i]); + if (liEntry.parentElement === null) { ulList.appendChild(liEntry); - } + } } uDom('#lists .listEntry.discard').remove(); uDom('#listsOfBlockedHostsPrompt') - .text(vAPI.i18n('hostsFilesStats') - .replace('{{blockedHostnameCount}}', - renderNumber(details.blockedHostnameCount))); + .text(vAPI.i18n('hostsFilesStats') + .replace('{{blockedHostnameCount}}', + renderNumber(details.blockedHostnameCount))); uDom('#autoUpdate').prop('checked', - listDetails.autoUpdate === true); + listDetails.autoUpdate === true); if (!soft) { - hostsFilesSettingsHash = hashFromCurrentFromSettings(); + hostsFilesSettingsHash = hashFromCurrentFromSettings(); } renderWidgets(); - }; + }; - vAPI.messaging.send('hosts-files.js', { - what: 'getLists' - }, onListsReceived); + vAPI.messaging.send('hosts-files.js', { + what: 'getLists' + }, onListsReceived); }; let renderWidgets = function () { - let sel1 = - 'body:not(.updating) #lists .listEntry.obsolete ' - + '> input[type="checkbox"]:checked'; - let sel2 = '#lists .listEntry.cached'; - - uDom('#buttonUpdate') - .toggleClass('disabled', document.querySelector(sel1) === null); - uDom('#buttonPurgeAll') - .toggleClass('disabled', document.querySelector(sel2) === null); - uDom('#buttonApply') - .toggleClass('disabled', - hostsFilesSettingsHash === - hashFromCurrentFromSettings()); + let sel1 = + 'body:not(.updating) #lists .listEntry.obsolete ' + + '> input[type="checkbox"]:checked'; + let sel2 = '#lists .listEntry.cached'; + + uDom('#buttonUpdate') + .toggleClass('disabled', document.querySelector(sel1) === null); + uDom('#buttonPurgeAll') + .toggleClass('disabled', document.querySelector(sel2) === null); + uDom('#buttonApply') + .toggleClass('disabled', + hostsFilesSettingsHash === + hashFromCurrentFromSettings()); }; let updateAssetStatus = function (details) { - let li = document - .querySelector('#lists .listEntry[data-listkey="'+details.key+'"]'); - if (li === null) { - return; - } - - li.classList.toggle('failed', !!details.failed); - li.classList.toggle('obsolete', !details.cached); - li.classList.toggle('cached', !!details.cached); - - if (details.cached) { - let str = vAPI.i18n.renderElapsedTimeToString(Date.now()); + let li = document + .querySelector('#lists .listEntry[data-listkey="'+details.key+'"]'); + if (li === null) { + return; + } + + li.classList.toggle('failed', !!details.failed); + li.classList.toggle('obsolete', !details.cached); + li.classList.toggle('cached', !!details.cached); + + if (details.cached) { + let str = vAPI.i18n.renderElapsedTimeToString(Date.now()); li.querySelector('.status.cache') - .setAttribute('title', - lastUpdateTemplateString.replace('{{ago}}', str)); - } + .setAttribute('title', + lastUpdateTemplateString.replace('{{ago}}', str)); + } - renderWidgets(); + renderWidgets(); }; /** - Compute a hash from all the settings affecting how filter lists are loaded - in memory. + Compute a hash from all the settings affecting how filter lists are loaded + in memory. **/ let hashFromCurrentFromSettings = function () { - let hash = []; + let hash = []; let listHash = []; - let sel = '#lists .listEntry[data-listkey]:not(.toRemove)'; - let ext = 'externalHostsFiles'; + let sel = '#lists .listEntry[data-listkey]:not(.toRemove)'; + let ext = 'externalHostsFiles'; let listEntries = document.querySelectorAll(sel); for (let i=listEntries.length-1; i>=0; --i) { let li = listEntries[i]; if (li.querySelector('input[type="checkbox"]:checked') !== null) { - listHash.push(li.getAttribute('data-listkey')); + listHash.push(li.getAttribute('data-listkey')); } - } + } - hash.push(listHash.sort().join(), - reValidExternalList.test(document.getElementById(ext).value), - document.querySelector('#lists .listEntry.toRemove') !== null); + hash.push(listHash.sort().join(), + reValidExternalList.test(document.getElementById(ext).value), + document.querySelector('#lists .listEntry.toRemove') !== null); - return hash.join(); + return hash.join(); }; let onHostsFilesSettingsChanged = function () { - renderWidgets(); + renderWidgets(); }; let onRemoveExternalHostsFile = function (ev) { - let liEntry = uDom(this).ancestors('[data-listkey]'); + let liEntry = uDom(this).ancestors('[data-listkey]'); let listKey = liEntry.attr('data-listkey'); - if (listKey) { + if (listKey) { liEntry.toggleClass('toRemove'); renderWidgets(); - } + } - ev.preventDefault(); + ev.preventDefault(); }; let onPurgeClicked = function () { - let button = uDom(this); + let button = uDom(this); let liEntry = button.ancestors('[data-listkey]'); let listKey = liEntry.attr('data-listkey'); - if (!listKey) { - return; - } + if (!listKey) { + return; + } - vAPI.messaging.send('hosts-files.js', { - what: 'purgeCache', - assetKey: listKey - }); + vAPI.messaging.send('hosts-files.js', { + what: 'purgeCache', + assetKey: listKey + }); - liEntry.addClass('obsolete'); - liEntry.removeClass('cached'); + liEntry.addClass('obsolete'); + liEntry.removeClass('cached'); - if (liEntry.descendants('input').first().prop('checked')) { + if (liEntry.descendants('input').first().prop('checked')) { renderWidgets(); - } + } }; let selectHostsFiles = function (callback) { - // Hosts files to select - let toSelect = []; - let sel = '#lists .listEntry[data-listkey]:not(.toRemove)'; - let sel2 = '#lists .listEntry.toRemove[data-listkey]'; + // Hosts files to select + let toSelect = []; + let sel = '#lists .listEntry[data-listkey]:not(.toRemove)'; + let sel2 = '#lists .listEntry.toRemove[data-listkey]'; let liEntries = document.querySelectorAll(sel); for (let i=liEntries.length-1; i>=0; --i) { let li = liEntries[i]; if (li.querySelector('input[type="checkbox"]:checked') !== null) { - toSelect.push(li.getAttribute('data-listkey')); + toSelect.push(li.getAttribute('data-listkey')); } - } + } - // External hosts files to remove - let toRemove = []; - liEntries = document.querySelectorAll(sel2); + // External hosts files to remove + let toRemove = []; + liEntries = document.querySelectorAll(sel2); - for (let i=liEntries.length-1; i>=0; --i) { + for (let i=liEntries.length-1; i>=0; --i) { toRemove.push(liEntries[i].getAttribute('data-listkey')); - } + } - // External hosts files to import - let externalListsElem = document.getElementById('externalHostsFiles'); + // External hosts files to import + let externalListsElem = document.getElementById('externalHostsFiles'); let toImport = externalListsElem.value.trim(); - externalListsElem.value = ''; + externalListsElem.value = ''; - vAPI.messaging.send('hosts-files.js', { - what: 'selectHostsFiles', - toSelect: toSelect, - toImport: toImport, - toRemove: toRemove + vAPI.messaging.send('hosts-files.js', { + what: 'selectHostsFiles', + toSelect: toSelect, + toImport: toImport, + toRemove: toRemove }, callback); - hostsFilesSettingsHash = hashFromCurrentFromSettings(); + hostsFilesSettingsHash = hashFromCurrentFromSettings(); }; let buttonApplyHandler = function () { - uDom('#buttonApply').removeClass('enabled'); - selectHostsFiles(function () { + uDom('#buttonApply').removeClass('enabled'); + selectHostsFiles(function () { vAPI.messaging.send('hosts-files.js', { - what: 'reloadHostsFiles' - }); - }); + what: 'reloadHostsFiles' + }); + }); - renderWidgets(); + renderWidgets(); }; let buttonUpdateHandler = function () { - uDom('#buttonUpdate').removeClass('enabled'); - selectHostsFiles(function () { + uDom('#buttonUpdate').removeClass('enabled'); + selectHostsFiles(function () { document.body.classList.add('updating'); vAPI.messaging.send('hosts-files.js', { - what: 'forceUpdateAssets' - }); + what: 'forceUpdateAssets' + }); renderWidgets(); - }); - renderWidgets(); + }); + renderWidgets(); }; let buttonPurgeAllHandler = function () { - uDom('#buttonPurgeAll').removeClass('enabled'); - vAPI.messaging.send('hosts-files.js', { - what: 'purgeAllCaches' - }, function () { - renderHostsFiles(true); + uDom('#buttonPurgeAll').removeClass('enabled'); + vAPI.messaging.send('hosts-files.js', { + what: 'purgeAllCaches' + }, function () { + renderHostsFiles(true); }); }; let autoUpdateCheckboxChanged = function () { - vAPI.messaging.send('hosts-files.js', { - what: 'userSettings', - name: 'autoUpdate', - value: this.checked + vAPI.messaging.send('hosts-files.js', { + what: 'userSettings', + name: 'autoUpdate', + value: this.checked }); }; @@ -392,9 +394,9 @@ uDom('#buttonUpdate').on('click', buttonUpdateHandler); uDom('#buttonPurgeAll').on('click', buttonPurgeAllHandler); uDom('#lists').on('change', '.listEntry > input', - onHostsFilesSettingsChanged); + onHostsFilesSettingsChanged); uDom('#lists').on('click', '.listEntry > a.remove', - onRemoveExternalHostsFile); + onRemoveExternalHostsFile); uDom('#lists').on('click', 'span.cache', onPurgeClicked); uDom('#externalHostsFiles').on('input', onHostsFilesSettingsChanged); diff --git a/js/httpsb.js b/js/httpsb.js index be487d5..1a8362a 100644 --- a/js/httpsb.js +++ b/js/httpsb.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -44,187 +44,187 @@ // in case. let reSafeTags = - /^([\s\S]*?)<(b|blockquote|code|em|i|kbd|span|sup)>(.+?)<\/\2>([\s\S]*)$/; + /^([\s\S]*?)<(b|blockquote|code|em|i|kbd|span|sup)>(.+?)<\/\2>([\s\S]*)$/; let reSafeInput = /^([\s\S]*?)<(input type="[^"]+")>(.*?)([\s\S]*)$/; let reInput = /^input type=(['"])([a-z]+)\1$/; let reSafeLink = - /^([\s\S]*?)<(a href=['"]https?:\/\/[^'" <>]+['"])>(.+?)<\/a>([\s\S]*)$/; + /^([\s\S]*?)<(a href=['"]https?:\/\/[^'" <>]+['"])>(.+?)<\/a>([\s\S]*)$/; let reLink = /^a href=(['"])(https?:\/\/[^'"]+)\1$/; let safeTextToTagNode = function (text) { - let matches; - let node; + let matches; + let node; - if (text.lastIndexOf('a ', 0) === 0) { + if (text.lastIndexOf('a ', 0) === 0) { matches = reLink.exec(text); if (matches === null) { - return null; - } + return null; + } node = document.createElement('a'); node.setAttribute('href', matches[2]); return node; - } - if (text.lastIndexOf('input ', 0) === 0) { + } + if (text.lastIndexOf('input ', 0) === 0) { matches = reInput.exec(text); if (matches === null) { - return null; - } + return null; + } node = document.createElement('input'); node.setAttribute('type', matches[2]); return node; - } - // Firefox extension validator warns if using a variable as - // argument for document.createElement(). - // ηMatrix: is it important for us? - // ηMatrix (4.4.3 onwards): let's just use the variable and - // hope for the best, no need to have a redundant switch. - /* - switch (text) { - case 'b': + } + // Firefox extension validator warns if using a variable as + // argument for document.createElement(). + // ηMatrix: is it important for us? + // ηMatrix (4.4.3 onwards): let's just use the variable and + // hope for the best, no need to have a redundant switch. + /* + switch (text) { + case 'b': return document.createElement('b'); - case 'blockquote': + case 'blockquote': return document.createElement('blockquote'); - case 'code': + case 'code': return document.createElement('code'); - case 'em': + case 'em': return document.createElement('em'); - case 'i': + case 'i': return document.createElement('i'); - case 'kbd': + case 'kbd': return document.createElement('kbd'); - case 'span': + case 'span': return document.createElement('span'); - case 'sup': + case 'sup': return document.createElement('sup'); - default: + default: break; - } - */ - return document.createElement(text); + } + */ + return document.createElement(text); }; let safeTextToTextNode = function (text) { - if (text.indexOf('&') !== -1) { + if (text.indexOf('&') !== -1) { text = text - .replace(/“/g, '“') - .replace(/”/g, '”') - .replace(/‘/g, '‘') - .replace(/’/g, '’') - .replace(/</g, '<') - .replace(/>/g, '>') - .replace(/'/g, '\''); - } - return document.createTextNode(text); + .replace(/“/g, '“') + .replace(/”/g, '”') + .replace(/‘/g, '‘') + .replace(/’/g, '’') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/'/g, '\''); + } + return document.createTextNode(text); }; let safeTextToDOM = function (text, parent) { - if (text === '') { - return; - } + if (text === '') { + return; + } - if (text.indexOf('<') === -1) { + if (text.indexOf('<') === -1) { return parent.appendChild(safeTextToTextNode(text)); - } + } - // Using the raw <p> element is not allowed for security reason, - // but it's good for formatting content, so here it's substituted - // for a safer equivalent (for the extension.) - text = text - .replace(/^<p>|<\/p>/g, '') + // Using the raw <p> element is not allowed for security reason, + // but it's good for formatting content, so here it's substituted + // for a safer equivalent (for the extension.) + text = text + .replace(/^<p>|<\/p>/g, '') .replace(/<p>/g, '\n\n'); - let matches; - let matches1 = reSafeTags.exec(text); - let matches2 = reSafeLink.exec(text); - if (matches1 !== null && matches2 !== null) { + let matches; + let matches1 = reSafeTags.exec(text); + let matches2 = reSafeLink.exec(text); + if (matches1 !== null && matches2 !== null) { matches = matches1.index < matches2.index ? matches1 : matches2; - } else if (matches1 !== null) { + } else if (matches1 !== null) { matches = matches1; - } else if (matches2 !== null) { + } else if (matches2 !== null) { matches = matches2; - } else { + } else { matches = reSafeInput.exec(text); - } - if (matches === null) { + } + if (matches === null) { parent.appendChild(safeTextToTextNode(text)); return; - } + } - safeTextToDOM(matches[1], parent); - let node = safeTextToTagNode(matches[2]) || parent; - safeTextToDOM(matches[3], node); - parent.appendChild(node); - safeTextToDOM(matches[4], parent); + safeTextToDOM(matches[1], parent); + let node = safeTextToTagNode(matches[2]) || parent; + safeTextToDOM(matches[3], node); + parent.appendChild(node); + safeTextToDOM(matches[4], parent); }; // Helper to deal with the i18n'ing of HTML files. vAPI.i18n.render = function (context) { - let docu = document; + let docu = document; let root = context || docu; let i, elem, text; - let elems = root.querySelectorAll('[data-i18n]'); - let n = elems.length; - for (i=0; i<n; ++i) { + let elems = root.querySelectorAll('[data-i18n]'); + let n = elems.length; + for (i=0; i<n; ++i) { elem = elems[i]; text = vAPI.i18n(elem.getAttribute('data-i18n')); if (!text) { - continue; - } + continue; + } // TODO: remove once it's all replaced with <input type="..."> if (text.indexOf('{') !== -1) { - text = - text.replace(/\{\{input:([^}]+)\}\}/g, '<input type="$1">'); + text = + text.replace(/\{\{input:([^}]+)\}\}/g, '<input type="$1">'); } safeTextToDOM(text, elem); - } + } - uDom('[title]', context).forEach(function (elem) { + uDom('[title]', context).forEach(function (elem) { let title = vAPI.i18n(elem.attr('title')); if (title) { - elem.attr('title', title); + elem.attr('title', title); } - }); + }); - uDom('[placeholder]', context).forEach(function (elem) { + uDom('[placeholder]', context).forEach(function (elem) { elem.attr('placeholder', vAPI.i18n(elem.attr('placeholder'))); - }); + }); - uDom('[data-i18n-tip]', context).forEach(function (elem) { + uDom('[data-i18n-tip]', context).forEach(function (elem) { elem.attr('data-tip', - vAPI.i18n(elem.attr('data-i18n-tip')) + vAPI.i18n(elem.attr('data-i18n-tip')) .replace(/<br>/g, '\n') .replace(/\n{3,}/g, '\n\n')); - }); + }); }; vAPI.i18n.render(); vAPI.i18n.renderElapsedTimeToString = function (tstamp) { - let value = (Date.now() - tstamp) / 60000; - if (value < 2) { + let value = (Date.now() - tstamp) / 60000; + if (value < 2) { return vAPI.i18n('elapsedOneMinuteAgo'); - } - if (value < 60) { + } + if (value < 60) { return vAPI - .i18n('elapsedManyMinutesAgo') - .replace('{{value}}', Math.floor(value).toLocaleString()); - } - value /= 60; - if (value < 2) { + .i18n('elapsedManyMinutesAgo') + .replace('{{value}}', Math.floor(value).toLocaleString()); + } + value /= 60; + if (value < 2) { return vAPI.i18n('elapsedOneHourAgo'); - } - if (value < 24) { + } + if (value < 24) { return vAPI - .i18n('elapsedManyHoursAgo') - .replace('{{value}}', Math.floor(value).toLocaleString()); - } - value /= 24; - if (value < 2) { + .i18n('elapsedManyHoursAgo') + .replace('{{value}}', Math.floor(value).toLocaleString()); + } + value /= 24; + if (value < 2) { return vAPI.i18n('elapsedOneDayAgo'); - } - return vAPI - .i18n('elapsedManyDaysAgo') - .replace('{{value}}', Math.floor(value).toLocaleString()); + } + return vAPI + .i18n('elapsedManyDaysAgo') + .replace('{{value}}', Math.floor(value).toLocaleString()); }; })(); diff --git a/js/liquid-dict.js b/js/liquid-dict.js index 8a03d7a..085f67e 100644 --- a/js/liquid-dict.js +++ b/js/liquid-dict.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -27,176 +27,176 @@ ηMatrix.LiquidDict = (function() { - /******************************************************************************/ - - var LiquidDict = function() { - this.dict = {}; - this.count = 0; - this.duplicateCount = 0; - this.bucketCount = 0; - this.frozenBucketCount = 0; - - // Somewhat arbitrary: I need to come up with hard data to know at which - // point binary search is better than indexOf. - this.cutoff = 500; - }; - - /******************************************************************************/ - - var meltBucket = function(ldict, len, bucket) { - ldict.frozenBucketCount -= 1; - var map = {}; - if ( bucket.charAt(0) === ' ' ) { - bucket.trim().split(' ').map(function(k) { - map[k] = true; - }); - } else { - var offset = 0; - while ( offset < bucket.length ) { - map[bucket.substring(offset, len)] = true; - offset += len; - } - } - return map; - }; - - /******************************************************************************/ - - var melt = function(ldict) { - var buckets = ldict.dict; - var bucket; - for ( var key in buckets ) { - bucket = buckets[key]; - if ( typeof bucket === 'string' ) { - buckets[key] = meltBucket(ldict, key.charCodeAt(0) & 0xFF, bucket); - } - } - }; +/******************************************************************************/ - /******************************************************************************/ +var LiquidDict = function() { + this.dict = {}; + this.count = 0; + this.duplicateCount = 0; + this.bucketCount = 0; + this.frozenBucketCount = 0; - var freezeBucket = function(ldict, bucket) { - ldict.frozenBucketCount += 1; - var words = Object.keys(bucket); - var wordLen = words[0].length; - if ( wordLen * words.length < ldict.cutoff ) { - return ' ' + words.join(' ') + ' '; - } - return words.sort().join(''); - }; - - /******************************************************************************/ - - // How the key is derived dictates the number and size of buckets. - // - // http://jsperf.com/makekey-concat-vs-join/3 - // - // Question: Why is using a prototyped function better than a standalone - // helper function? - - LiquidDict.prototype.makeKey = function(word) { - var len = word.length; - if ( len > 255 ) { - len = 255; - } - var i = len >> 2; - return String.fromCharCode( - (word.charCodeAt( 0) & 0x03) << 14 | - (word.charCodeAt( i) & 0x03) << 12 | - (word.charCodeAt( i+i) & 0x03) << 10 | - (word.charCodeAt(i+i+i) & 0x03) << 8 | - len - ); - }; - - /******************************************************************************/ - - LiquidDict.prototype.test = function(word) { - var key = this.makeKey(word); - var bucket = this.dict[key]; - if ( bucket === undefined ) { - return false; - } - if ( typeof bucket === 'object' ) { - return bucket[word] !== undefined; - } - if ( bucket.charAt(0) === ' ' ) { - return bucket.indexOf(' ' + word + ' ') >= 0; - } - // binary search - var len = word.length; - var left = 0; - // http://jsperf.com/or-vs-floor/3 - var right = ~~(bucket.length / len + 0.5); - var i, needle; - while ( left < right ) { - i = left + right >> 1; - needle = bucket.substr( len * i, len ); - if ( word < needle ) { - right = i; - } else if ( word > needle ) { - left = i + 1; - } else { - return true; - } - } - return false; - }; + // Somewhat arbitrary: I need to come up with hard data to know at which + // point binary search is better than indexOf. + this.cutoff = 500; +}; - /******************************************************************************/ +/******************************************************************************/ - LiquidDict.prototype.add = function(word) { - var key = this.makeKey(word); - if ( key === undefined ) { - return false; +var meltBucket = function(ldict, len, bucket) { + ldict.frozenBucketCount -= 1; + var map = {}; + if ( bucket.charAt(0) === ' ' ) { + bucket.trim().split(' ').map(function(k) { + map[k] = true; + }); + } else { + var offset = 0; + while ( offset < bucket.length ) { + map[bucket.substring(offset, len)] = true; + offset += len; } - var bucket = this.dict[key]; - if ( bucket === undefined ) { - this.dict[key] = bucket = {}; - this.bucketCount += 1; - bucket[word] = true; - this.count += 1; - return true; - } else if ( typeof bucket === 'string' ) { - this.dict[key] = bucket = meltBucket(this, word.len, bucket); + } + return map; +}; + +/******************************************************************************/ + +var melt = function(ldict) { + var buckets = ldict.dict; + var bucket; + for ( var key in buckets ) { + bucket = buckets[key]; + if ( typeof bucket === 'string' ) { + buckets[key] = meltBucket(ldict, key.charCodeAt(0) & 0xFF, bucket); } - if ( bucket[word] === undefined ) { - bucket[word] = true; - this.count += 1; + } +}; + +/******************************************************************************/ + +var freezeBucket = function(ldict, bucket) { + ldict.frozenBucketCount += 1; + var words = Object.keys(bucket); + var wordLen = words[0].length; + if ( wordLen * words.length < ldict.cutoff ) { + return ' ' + words.join(' ') + ' '; + } + return words.sort().join(''); +}; + +/******************************************************************************/ + +// How the key is derived dictates the number and size of buckets. +// +// http://jsperf.com/makekey-concat-vs-join/3 +// +// Question: Why is using a prototyped function better than a standalone +// helper function? + +LiquidDict.prototype.makeKey = function(word) { + var len = word.length; + if ( len > 255 ) { + len = 255; + } + var i = len >> 2; + return String.fromCharCode( + (word.charCodeAt( 0) & 0x03) << 14 | + (word.charCodeAt( i) & 0x03) << 12 | + (word.charCodeAt( i+i) & 0x03) << 10 | + (word.charCodeAt(i+i+i) & 0x03) << 8 | + len + ); +}; + +/******************************************************************************/ + +LiquidDict.prototype.test = function(word) { + var key = this.makeKey(word); + var bucket = this.dict[key]; + if ( bucket === undefined ) { + return false; + } + if ( typeof bucket === 'object' ) { + return bucket[word] !== undefined; + } + if ( bucket.charAt(0) === ' ' ) { + return bucket.indexOf(' ' + word + ' ') >= 0; + } + // binary search + var len = word.length; + var left = 0; + // http://jsperf.com/or-vs-floor/3 + var right = ~~(bucket.length / len + 0.5); + var i, needle; + while ( left < right ) { + i = left + right >> 1; + needle = bucket.substr( len * i, len ); + if ( word < needle ) { + right = i; + } else if ( word > needle ) { + left = i + 1; + } else { return true; } - this.duplicateCount += 1; + } + return false; +}; + +/******************************************************************************/ + +LiquidDict.prototype.add = function(word) { + var key = this.makeKey(word); + if ( key === undefined ) { return false; - }; - - /******************************************************************************/ - - LiquidDict.prototype.freeze = function() { - var buckets = this.dict; - var bucket; - for ( var key in buckets ) { - bucket = buckets[key]; - if ( typeof bucket === 'object' ) { - buckets[key] = freezeBucket(this, bucket); - } + } + var bucket = this.dict[key]; + if ( bucket === undefined ) { + this.dict[key] = bucket = {}; + this.bucketCount += 1; + bucket[word] = true; + this.count += 1; + return true; + } else if ( typeof bucket === 'string' ) { + this.dict[key] = bucket = meltBucket(this, word.len, bucket); + } + if ( bucket[word] === undefined ) { + bucket[word] = true; + this.count += 1; + return true; + } + this.duplicateCount += 1; + return false; +}; + +/******************************************************************************/ + +LiquidDict.prototype.freeze = function() { + var buckets = this.dict; + var bucket; + for ( var key in buckets ) { + bucket = buckets[key]; + if ( typeof bucket === 'object' ) { + buckets[key] = freezeBucket(this, bucket); } - }; + } +}; - /******************************************************************************/ +/******************************************************************************/ - LiquidDict.prototype.reset = function() { - this.dict = {}; - this.count = 0; - this.duplicateCount = 0; - this.bucketCount = 0; - this.frozenBucketCount = 0; - }; +LiquidDict.prototype.reset = function() { + this.dict = {}; + this.count = 0; + this.duplicateCount = 0; + this.bucketCount = 0; + this.frozenBucketCount = 0; +}; - /******************************************************************************/ +/******************************************************************************/ - return LiquidDict; +return LiquidDict; - /******************************************************************************/ +/******************************************************************************/ })(); diff --git a/js/logger-ui.js b/js/logger-ui.js index 8f4ffbf..5f9aedb 100644 --- a/js/logger-ui.js +++ b/js/logger-ui.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2015-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/sessbench */ @@ -39,249 +39,249 @@ let hiddenTemplate = document.querySelector('#hiddenTemplate > span'); let prettyRequestTypes = { - 'main_frame': 'doc', - 'stylesheet': 'css', - 'sub_frame': 'frame', - 'xmlhttprequest': 'xhr' + 'main_frame': 'doc', + 'stylesheet': 'css', + 'sub_frame': 'frame', + 'xmlhttprequest': 'xhr' }; let dontEmphasizeSet = new Set([ - 'COOKIE', - 'CSP', - 'REFERER' + 'COOKIE', + 'CSP', + 'REFERER' ]); // Adjust top padding of content table, to match that of toolbar height. document - .getElementById('content') - .style - .setProperty('margin-top', - document.getElementById('toolbar').clientHeight + 'px'); + .getElementById('content') + .style + .setProperty('margin-top', + document.getElementById('toolbar').clientHeight + 'px'); let classNameFromTabId = function (tabId) { - if (tabId === noTabId) { + if (tabId === noTabId) { return 'tab_bts'; - } - if (tabId !== '') { + } + if (tabId !== '') { return 'tab_' + tabId; - } - return ''; + } + return ''; }; // Emphasize hostname and cookie name. let emphasizeCookie = function (s) { - let pnode = emphasizeHostname(s); - if (pnode.childNodes.length !== 3) { + let pnode = emphasizeHostname(s); + if (pnode.childNodes.length !== 3) { return pnode; - } + } - let prefix = '-cookie:'; - let text = pnode.childNodes[2].textContent; + let prefix = '-cookie:'; + let text = pnode.childNodes[2].textContent; - let beg = text.indexOf(prefix); - if (beg === -1) { + let beg = text.indexOf(prefix); + if (beg === -1) { return pnode; - } - beg += prefix.length; + } + beg += prefix.length; - let end = text.indexOf('}', beg); - if (end === -1) { + let end = text.indexOf('}', beg); + if (end === -1) { return pnode; - } + } - let cnode = emphasizeTemplate.cloneNode(true); - cnode.childNodes[0].textContent = text.slice(0, beg); - cnode.childNodes[1].textContent = text.slice(beg, end); - cnode.childNodes[2].textContent = text.slice(end); - pnode.replaceChild(cnode.childNodes[0], pnode.childNodes[2]); - pnode.appendChild(cnode.childNodes[0]); - pnode.appendChild(cnode.childNodes[0]); + let cnode = emphasizeTemplate.cloneNode(true); + cnode.childNodes[0].textContent = text.slice(0, beg); + cnode.childNodes[1].textContent = text.slice(beg, end); + cnode.childNodes[2].textContent = text.slice(end); + pnode.replaceChild(cnode.childNodes[0], pnode.childNodes[2]); + pnode.appendChild(cnode.childNodes[0]); + pnode.appendChild(cnode.childNodes[0]); - return pnode; + return pnode; }; // Emphasize hostname in URL. let emphasizeHostname = function (url) { - let hnbeg = url.indexOf('://'); - if (hnbeg === -1) { + let hnbeg = url.indexOf('://'); + if (hnbeg === -1) { return document.createTextNode(url); - } - hnbeg += 3; + } + hnbeg += 3; - let hnend = url.indexOf('/', hnbeg); - if (hnend === -1) { + let hnend = url.indexOf('/', hnbeg); + if (hnend === -1) { hnend = url.slice(hnbeg).search(/\?#/); if (hnend !== -1) { - hnend += hnbeg; + hnend += hnbeg; } else { - hnend = url.length; + hnend = url.length; } - } + } - let node = emphasizeTemplate.cloneNode(true); - node.childNodes[0].textContent = url.slice(0, hnbeg); - node.childNodes[1].textContent = url.slice(hnbeg, hnend); - node.childNodes[2].textContent = url.slice(hnend); + let node = emphasizeTemplate.cloneNode(true); + node.childNodes[0].textContent = url.slice(0, hnbeg); + node.childNodes[1].textContent = url.slice(hnbeg, hnend); + node.childNodes[2].textContent = url.slice(hnend); - return node; + return node; }; let createCellAt = function (tr, index) { - let td = tr.cells[index]; - let mustAppend = !td; - if (mustAppend) { + let td = tr.cells[index]; + let mustAppend = !td; + if (mustAppend) { td = tdJunkyard.pop(); - } + } - if (td) { + if (td) { td.removeAttribute('colspan'); td.textContent = ''; - } else { + } else { td = document.createElement('td'); - } - if (mustAppend) { + } + if (mustAppend) { tr.appendChild(td); - } + } - return td; + return td; }; let createRow = function (layout) { - let tr = trJunkyard.pop(); - if (tr) { + let tr = trJunkyard.pop(); + if (tr) { tr.className = ''; - } else { + } else { tr = document.createElement('tr'); - } + } - let index; - for (index=0; index<firstVarDataCol; ++index) { + let index; + for (index=0; index<firstVarDataCol; ++index) { createCellAt(tr, index); - } + } - let i = 1, span = 1, td; - for (;;) { + let i = 1, span = 1, td; + for (;;) { td = createCellAt(tr, index); if (i === lastVarDataIndex) { - break; + break; } if (layout.charAt(i) !== '1') { - span += 1; + span += 1; } else { - if (span !== 1) { + if (span !== 1) { td.setAttribute('colspan', span); - } - index += 1; - span = 1; + } + index += 1; + span = 1; } i += 1; - } + } - if (span !== 1) { + if (span !== 1) { td.setAttribute('colspan', span); - } - index += 1; - while ((td = tr.cells[index])) { + } + index += 1; + while ((td = tr.cells[index])) { tdJunkyard.push(tr.removeChild(td)); - } + } - return tr; + return tr; }; let createHiddenTextNode = function (text) { - let node = hiddenTemplate.cloneNode(true); - node.textContent = text; - return node; + let node = hiddenTemplate.cloneNode(true); + node.textContent = text; + return node; }; let padTo2 = function (v) { - return v < 10 ? '0' + v : v; + return v < 10 ? '0' + v : v; }; let createGap = function (tabId, url) { - let tr = createRow('1'); - tr.classList.add('doc'); - tr.classList.add('tab'); - tr.classList.add('canMtx'); - tr.classList.add('tab_' + tabId); - tr.cells[firstVarDataCol].textContent = url; - tbody.insertBefore(tr, tbody.firstChild); + let tr = createRow('1'); + tr.classList.add('doc'); + tr.classList.add('tab'); + tr.classList.add('canMtx'); + tr.classList.add('tab_' + tabId); + tr.cells[firstVarDataCol].textContent = url; + tbody.insertBefore(tr, tbody.firstChild); }; let renderLogEntry = function (entry) { - let tr; - let fvdc = firstVarDataCol; + let tr; + let fvdc = firstVarDataCol; - switch (entry.cat) { - case 'error': - case 'info': + switch (entry.cat) { + case 'error': + case 'info': tr = createRow('1'); if (entry.d0 === 'cookie') { - tr.cells[fvdc].appendChild(emphasizeCookie(entry.d1)); + tr.cells[fvdc].appendChild(emphasizeCookie(entry.d1)); } else { - tr.cells[fvdc].textContent = entry.d0; + tr.cells[fvdc].textContent = entry.d0; } break; - case 'net': + case 'net': tr = createRow('111'); tr.classList.add('canMtx'); // If the request is that of a root frame, insert a gap in the table // in order to visually separate entries for different documents. if (entry.d2 === 'doc' && entry.tab !== noTabId) { - createGap(entry.tab, entry.d1); + createGap(entry.tab, entry.d1); } if (entry.d3) { - tr.classList.add('blocked'); - tr.cells[fvdc].textContent = '--'; + tr.classList.add('blocked'); + tr.cells[fvdc].textContent = '--'; } else { - tr.cells[fvdc].textContent = ''; + tr.cells[fvdc].textContent = ''; } tr.cells[fvdc+1].textContent = - (prettyRequestTypes[entry.d2] || entry.d2); + (prettyRequestTypes[entry.d2] || entry.d2); if (dontEmphasizeSet.has(entry.d2)) { - tr.cells[fvdc+2].textContent = entry.d1; + tr.cells[fvdc+2].textContent = entry.d1; } else if ( entry.d2 === 'cookie' ) { - tr.cells[fvdc+2].appendChild(emphasizeCookie(entry.d1)); + tr.cells[fvdc+2].appendChild(emphasizeCookie(entry.d1)); } else { - tr.cells[fvdc+2].appendChild(emphasizeHostname(entry.d1)); + tr.cells[fvdc+2].appendChild(emphasizeHostname(entry.d1)); } break; - default: + default: tr = createRow('1'); tr.cells[fvdc].textContent = entry.d0; break; - } - - // Fields common to all rows. - let time = logDate; - time.setTime(entry.tstamp - logDateTimezoneOffset); - tr.cells[0].textContent = padTo2(time.getUTCHours()) - + ':' - + padTo2(time.getUTCMinutes()) - + ':' - + padTo2(time.getSeconds()); - - if (entry.tab) { + } + + // Fields common to all rows. + let time = logDate; + time.setTime(entry.tstamp - logDateTimezoneOffset); + tr.cells[0].textContent = padTo2(time.getUTCHours()) + + ':' + + padTo2(time.getUTCMinutes()) + + ':' + + padTo2(time.getSeconds()); + + if (entry.tab) { tr.classList.add('tab'); tr.classList.add(classNameFromTabId(entry.tab)); if (entry.tab === noTabId) { - tr.cells[1].appendChild(createHiddenTextNode('bts')); + tr.cells[1].appendChild(createHiddenTextNode('bts')); } - } - if (entry.cat !== '') { + } + if (entry.cat !== '') { tr.classList.add('cat_' + entry.cat); - } + } - rowFilterer.filterOne(tr, true); + rowFilterer.filterOne(tr, true); - tbody.insertBefore(tr, tbody.firstChild); + tbody.insertBefore(tr, tbody.firstChild); }; // Reuse date objects. @@ -289,180 +289,180 @@ let logDateTimezoneOffset = logDate.getTimezoneOffset() * 60000; let renderLogEntries = function (response) { - let entries = response.entries; - if (entries.length === 0) { + let entries = response.entries; + if (entries.length === 0) { return; - } + } - // Preserve scroll position - let height = tbody.offsetHeight; + // Preserve scroll position + let height = tbody.offsetHeight; - let tabIds = response.tabIds; - let n = entries.length; - let entry; - for (let i=0; i<n; ++i) { + let tabIds = response.tabIds; + let n = entries.length; + let entry; + for (let i=0; i<n; ++i) { entry = entries[i]; // Unlikely, but it may happen if (entry.tab && tabIds.hasOwnProperty(entry.tab) === false) { - continue; + continue; } renderLogEntry(entries[i]); - } + } - // Prevent logger from growing infinitely and eating all memory. For - // instance someone could forget that it is left opened for some - // dynamically refreshed pages. - truncateLog(maxEntries); + // Prevent logger from growing infinitely and eating all memory. For + // instance someone could forget that it is left opened for some + // dynamically refreshed pages. + truncateLog(maxEntries); - let yDelta = tbody.offsetHeight - height; - if (yDelta === 0) { + let yDelta = tbody.offsetHeight - height; + if (yDelta === 0) { return; - } + } - // Chromium: - // body.scrollTop = good value - // body.parentNode.scrollTop = 0 - // if (document.body.scrollTop !== 0) { + // Chromium: + // body.scrollTop = good value + // body.parentNode.scrollTop = 0 + // if (document.body.scrollTop !== 0) { // document.body.scrollTop += yDelta; // return; - // } + // } - // Firefox: - // body.scrollTop = 0 - // body.parentNode.scrollTop = good value - let parentNode = document.body.parentNode; - if (parentNode && parentNode.scrollTop !== 0) { + // Firefox: + // body.scrollTop = 0 + // body.parentNode.scrollTop = good value + let parentNode = document.body.parentNode; + if (parentNode && parentNode.scrollTop !== 0) { parentNode.scrollTop += yDelta; - } + } }; let synchronizeTabIds = function (newTabIds) { - let oldTabIds = allTabIds; - let autoDeleteVoidRows = - !!vAPI.localStorage.getItem('loggerAutoDeleteVoidRows'); - let rowVoided = false; - let trs; + let oldTabIds = allTabIds; + let autoDeleteVoidRows = + !!vAPI.localStorage.getItem('loggerAutoDeleteVoidRows'); + let rowVoided = false; + let trs; - for (let tabId in oldTabIds) { + for (let tabId in oldTabIds) { if (oldTabIds.hasOwnProperty(tabId) === false) { - continue; + continue; } if (newTabIds.hasOwnProperty(tabId)) { - continue; + continue; } // Mark or remove voided rows trs = uDom('.tab_' + tabId); if (autoDeleteVoidRows) { - toJunkyard(trs); + toJunkyard(trs); } else { - trs.removeClass('canMtx'); - rowVoided = true; + trs.removeClass('canMtx'); + rowVoided = true; } // Remove popup if it is currently bound to a removed tab. if (tabId === popupManager.tabId) { - popupManager.toggleOff(); + popupManager.toggleOff(); } - } + } - let select = document.getElementById('pageSelector'); - let selectValue = select.value; - let tabIds = Object.keys(newTabIds).sort(function (a, b) { + let select = document.getElementById('pageSelector'); + let selectValue = select.value; + let tabIds = Object.keys(newTabIds).sort(function (a, b) { return newTabIds[a].localeCompare(newTabIds[b]); - }); + }); - let i, j; - for (i=0, j=2; i<tabIds.length; ++i) { + let i, j; + for (i=0, j=2; i<tabIds.length; ++i) { let tabId = tabIds[i]; if (tabId === noTabId) { - continue; + continue; } let option = select.options[j]; j += 1; if (!option) { - option = document.createElement('option'); - select.appendChild(option); + option = document.createElement('option'); + select.appendChild(option); } option.textContent = newTabIds[tabId]; option.value = classNameFromTabId(tabId); if (option.value === selectValue) { - option.setAttribute('selected', ''); + option.setAttribute('selected', ''); } else { - option.removeAttribute('selected'); + option.removeAttribute('selected'); } - } + } - while (j < select.options.length) { + while (j < select.options.length) { select.removeChild(select.options[j]); - } + } - if (select.value !== selectValue) { + if (select.value !== selectValue) { select.selectedIndex = 0; select.value = ''; select.options[0].setAttribute('selected', ''); pageSelectorChanged(); - } + } - allTabIds = newTabIds; + allTabIds = newTabIds; - return rowVoided; + return rowVoided; }; let truncateLog = function (size) { - if (size === 0) { + if (size === 0) { size = 5000; - } + } - let tbody = document.querySelector('#content tbody'); - size = Math.min(size, 10000); + let tbody = document.querySelector('#content tbody'); + size = Math.min(size, 10000); - while (tbody.childElementCount > size) { + while (tbody.childElementCount > size) { let tr = tbody.lastElementChild; trJunkyard.push(tbody.removeChild(tr)); - } + } }; let onLogBufferRead = function (response) { - if (!response || response.unavailable) { + if (!response || response.unavailable) { readLogBufferAsync(); return; - } + } - // This tells us the behind-the-scene tab id - noTabId = response.noTabId; + // This tells us the behind-the-scene tab id + noTabId = response.noTabId; - // This may have changed meanwhile - if (response.maxLoggedRequests !== maxEntries) { + // This may have changed meanwhile + if (response.maxLoggedRequests !== maxEntries) { maxEntries = response.maxLoggedRequests; uDom('#maxEntries').val(maxEntries || ''); - } + } - // Neuter rows for which a tab does not exist anymore - let rowVoided = false; - if (response.tabIdsToken !== allTabIdsToken) { + // Neuter rows for which a tab does not exist anymore + let rowVoided = false; + if (response.tabIdsToken !== allTabIdsToken) { rowVoided = synchronizeTabIds(response.tabIds); allTabIdsToken = response.tabIdsToken; - } + } - renderLogEntries(response); + renderLogEntries(response); - if (rowVoided) { + if (rowVoided) { uDom('#clean') - .toggleClass('disabled', - tbody - .querySelector('tr.tab:not(.canMtx)') === null); - } + .toggleClass('disabled', + tbody + .querySelector('tr.tab:not(.canMtx)') === null); + } - // Synchronize toolbar with content of log - uDom('#clear').toggleClass('disabled', - tbody.querySelector('tr') === null); + // Synchronize toolbar with content of log + uDom('#clear').toggleClass('disabled', + tbody.querySelector('tr') === null); - readLogBufferAsync(); + readLogBufferAsync(); }; // This can be called only once, at init time. After that, this @@ -471,83 +471,83 @@ // no multi time out events. let readLogBuffer = function () { - if (ownerId === undefined) { - return; - } - - vAPI.messaging.send('logger-ui.js', { - what: 'readMany', - ownerId: ownerId - }, onLogBufferRead); + if (ownerId === undefined) { + return; + } + + vAPI.messaging.send('logger-ui.js', { + what: 'readMany', + ownerId: ownerId + }, onLogBufferRead); }; let readLogBufferAsync = function () { - if (ownerId === undefined) { - return; - } - vAPI.setTimeout(readLogBuffer, 1200); + if (ownerId === undefined) { + return; + } + vAPI.setTimeout(readLogBuffer, 1200); }; let pageSelectorChanged = function () { - let style = document.getElementById('tabFilterer'); - let tabClass = document.getElementById('pageSelector').value; - let sheet = style.sheet; + let style = document.getElementById('tabFilterer'); + let tabClass = document.getElementById('pageSelector').value; + let sheet = style.sheet; - while (sheet.cssRules.length !== 0) { + while (sheet.cssRules.length !== 0) { sheet.deleteRule(0); - } + } - if (tabClass !== '') { + if (tabClass !== '') { sheet.insertRule('#content table tr:not(.' - + tabClass - + ') { display: none; }', 0); - } - uDom('#refresh').toggleClass('disabled', - tabClass === '' || tabClass === 'tab_bts'); + + tabClass + + ') { display: none; }', 0); + } + uDom('#refresh').toggleClass('disabled', + tabClass === '' || tabClass === 'tab_bts'); }; let refreshTab = function () { - let tabClass = document.getElementById('pageSelector').value; - let matches = tabClass.match(/^tab_(.+)$/); - if (matches === null) { + let tabClass = document.getElementById('pageSelector').value; + let matches = tabClass.match(/^tab_(.+)$/); + if (matches === null) { return; - } + } - if (matches[1] === 'bts') { + if (matches[1] === 'bts') { return; - } + } - vAPI.messaging.send('logger-ui.js', { - what: 'forceReloadTab', - tabId: matches[1] - }); + vAPI.messaging.send('logger-ui.js', { + what: 'forceReloadTab', + tabId: matches[1] + }); }; let onMaxEntriesChanged = function () { - let raw = uDom(this).val(); + let raw = uDom(this).val(); - try { + try { maxEntries = parseInt(raw, 10); if (isNaN(maxEntries)) { - maxEntries = 0; + maxEntries = 0; } - } catch (e) { + } catch (e) { maxEntries = 0; - } + } - vAPI.messaging.send('logger-ui.js', { + vAPI.messaging.send('logger-ui.js', { what: 'userSettings', name: 'maxLoggedRequests', value: maxEntries - }); + }); - truncateLog(maxEntries); + truncateLog(maxEntries); }; let rowFilterer = (function () { - let filters = []; + let filters = []; - let parseInput = function () { + let parseInput = function () { filters = []; let rawPart, hardBeg, hardEnd; @@ -557,69 +557,69 @@ let n = rawParts.length; for (let i=0; i<n; ++i) { - rawPart = rawParts[i]; - if (rawPart.charAt(0) === '!') { + rawPart = rawParts[i]; + if (rawPart.charAt(0) === '!') { if (reStrs.length === 0) { - not = true; + not = true; } rawPart = rawPart.slice(1); - } + } - hardBeg = rawPart.charAt(0) === '|'; - if (hardBeg) { + hardBeg = rawPart.charAt(0) === '|'; + if (hardBeg) { rawPart = rawPart.slice(1); - } + } - hardEnd = rawPart.slice(-1) === '|'; - if (hardEnd) { + hardEnd = rawPart.slice(-1) === '|'; + if (hardEnd) { rawPart = rawPart.slice(0, -1); - } + } - if ( rawPart === '' ) { + if ( rawPart === '' ) { continue; - } + } - reStr = rawPart.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); - if (hardBeg) { + reStr = rawPart.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + if (hardBeg) { reStr = '(?:^|\\s)' + reStr; - } - if (hardEnd) { + } + if (hardEnd) { reStr += '(?:\\s|$)'; - } + } - reStrs.push(reStr); - if (i < (n - 1) && rawParts[i + 1] === '||') { + reStrs.push(reStr); + if (i < (n - 1) && rawParts[i + 1] === '||') { i += 1; continue; - } + } - reStr = reStrs.length === 1 ? reStrs[0] : reStrs.join('|'); - filters.push({ + reStr = reStrs.length === 1 ? reStrs[0] : reStrs.join('|'); + filters.push({ re: new RegExp(reStr, 'i'), r: !not - }); - reStrs = []; - not = false; + }); + reStrs = []; + not = false; } - }; + }; - let filterOne = function (tr, clean) { + let filterOne = function (tr, clean) { let ff = filters; let fcount = ff.length; if (fcount === 0 && clean === true) { - return; + return; } // do not filter out doc boundaries, they help separate // important section of log. let cl = tr.classList; if (cl.contains('doc')) { - return; + return; } if (fcount === 0) { - cl.remove('f'); - return; + cl.remove('f'); + return; } let cc = tr.cells; @@ -631,141 +631,141 @@ // positive filter expression = there must one hit on any field // negative filter expression = there must be no hit on all fields for (let i=0; i<fcount; ++i) { - f = ff[i]; - hit = !f.r; + f = ff[i]; + hit = !f.r; - for (j=0; j<ccount; ++j) { + for (j=0; j<ccount; ++j) { if (f.re.test(cc[j].textContent)) { - hit = f.r; - break; + hit = f.r; + break; } - } + } - if (!hit) { + if (!hit) { cl.add('f'); return; - } + } } cl.remove('f'); - }; + }; - let filterAll = function () { + let filterAll = function () { // Special case: no filter if (filters.length === 0) { - uDom('#content tr').removeClass('f'); - return; + uDom('#content tr').removeClass('f'); + return; } let tbody = document.querySelector('#content tbody'); let rows = tbody.rows; for (let i=rows.length-1; i>=0; --i) { - filterOne(rows[i]); + filterOne(rows[i]); } - }; + }; - let onFilterChangedAsync = (function () { + let onFilterChangedAsync = (function () { let timer = null; let commit = function () { - timer = null; - parseInput(); - filterAll(); + timer = null; + parseInput(); + filterAll(); }; return function () { - if (timer !== null) { + if (timer !== null) { clearTimeout(timer); - } - timer = vAPI.setTimeout(commit, 750); + } + timer = vAPI.setTimeout(commit, 750); }; - })(); + })(); - let onFilterButton = function () { + let onFilterButton = function () { let cl = document.body.classList; cl.toggle('f', cl.contains('f') === false); - }; + }; - uDom('#filterButton').on('click', onFilterButton); - uDom('#filterInput').on('input', onFilterChangedAsync); + uDom('#filterButton').on('click', onFilterButton); + uDom('#filterInput').on('input', onFilterChangedAsync); - return { + return { filterOne: filterOne, filterAll: filterAll, - }; + }; })(); let toJunkyard = function (trs) { - trs.remove(); - for (let i=trs.length-1; i>=0; --i) { + trs.remove(); + for (let i=trs.length-1; i>=0; --i) { trJunkyard.push(trs.nodeAt(i)); - } + } }; let clearBuffer = function () { - let tbody = document.querySelector('#content tbody'); - let tr; + let tbody = document.querySelector('#content tbody'); + let tr; - while (tbody.firstChild !== null) { + while (tbody.firstChild !== null) { tr = tbody.lastElementChild; trJunkyard.push(tbody.removeChild(tr)); - } + } - uDom('#clear').addClass('disabled'); - uDom('#clean').addClass('disabled'); + uDom('#clear').addClass('disabled'); + uDom('#clean').addClass('disabled'); }; let cleanBuffer = function () { - let rows = uDom('#content tr.tab:not(.canMtx)').remove(); - for (let i=rows.length-1; i>=0; --i) { + let rows = uDom('#content tr.tab:not(.canMtx)').remove(); + for (let i=rows.length-1; i>=0; --i) { trJunkyard.push(rows.nodeAt(i)); - } - uDom('#clean').addClass('disabled'); + } + uDom('#clean').addClass('disabled'); }; let toggleCompactView = function () { - document.body.classList.toggle('compactView'); - uDom('#content table .vExpanded').removeClass('vExpanded'); + document.body.classList.toggle('compactView'); + uDom('#content table .vExpanded').removeClass('vExpanded'); }; let toggleCompactRow = function (ev) { - ev.target.parentElement.classList.toggle('vExpanded'); + ev.target.parentElement.classList.toggle('vExpanded'); }; let popupManager = (function () { - let realTabId = null; - let localTabId = null; - let container = null; - let popup = null; - let popupObserver = null; - let style = null; - let styleTemplate = [ + let realTabId = null; + let localTabId = null; + let container = null; + let popup = null; + let popupObserver = null; + let style = null; + let styleTemplate = [ 'tr:not(.tab_{{tabId}}) {', 'cursor: not-allowed;', 'opacity: 0.2;', '}' - ].join('\n'); + ].join('\n'); - let resizePopup = function () { + let resizePopup = function () { if (popup === null) { - return; + return; } let popupBody = popup.contentWindow.document.body; if (popupBody.clientWidth !== 0 - && container.clientWidth !== popupBody.clientWidth) { - container.style.setProperty('width', popupBody.clientWidth + 'px'); + && container.clientWidth !== popupBody.clientWidth) { + container.style.setProperty('width', popupBody.clientWidth + 'px'); } popup.style.removeProperty('height'); if (popupBody.clientHeight !== 0 - && popup.clientHeight !== popupBody.clientHeight) { - popup.style.setProperty('height', popupBody.clientHeight + 'px'); + && popup.clientHeight !== popupBody.clientHeight) { + popup.style.setProperty('height', popupBody.clientHeight + 'px'); } let ph = document.documentElement.clientHeight; let crect = container.getBoundingClientRect(); if (crect.height > ph) { - popup.style.setProperty('height', 'calc(' + ph + 'px - 1.8em)'); + popup.style.setProperty('height', 'calc(' + ph + 'px - 1.8em)'); } // Adjust width for presence/absence of vertical scroll bar which may @@ -773,54 +773,54 @@ let cw = container.clientWidth; let dw = popup.contentWindow.document.documentElement.clientWidth; if (cw !== dw) { - container.style.setProperty('width', (2 * cw - dw) + 'px'); + container.style.setProperty('width', (2 * cw - dw) + 'px'); } - }; + }; - let toggleSize = function () { + let toggleSize = function () { container.classList.toggle('hide'); - }; + }; - let onResizeRequested = function () { + let onResizeRequested = function () { let popupBody = popup.contentWindow.document.body; if (popupBody.hasAttribute('data-resize-popup') === false) { - return; + return; } popupBody.removeAttribute('data-resize-popup'); resizePopup(); - }; + }; - let onLoad = function () { + let onLoad = function () { resizePopup(); let popupBody = popup.contentDocument.body; popupBody.removeAttribute('data-resize-popup'); popupObserver.observe(popupBody, { - attributes: true, - attributesFilter: [ 'data-resize-popup' ] + attributes: true, + attributesFilter: [ 'data-resize-popup' ] }); - }; + }; - let toggleOn = function (td) { + let toggleOn = function (td) { let tr = td.parentNode; let matches = tr.className.match(/(?:^| )tab_([^ ]+)/); if (matches === null) { - return; + return; } realTabId = localTabId = matches[1]; if (localTabId === 'bts') { - realTabId = noTabId; + realTabId = noTabId; } container = document.getElementById('popupContainer'); container - .querySelector('div > span:nth-of-type(1)') - .addEventListener('click', toggleSize); + .querySelector('div > span:nth-of-type(1)') + .addEventListener('click', toggleSize); container - .querySelector('div > span:nth-of-type(2)') - .addEventListener('click', toggleOff); + .querySelector('div > span:nth-of-type(2)') + .addEventListener('click', toggleOff); popup = document.createElement('iframe'); popup.addEventListener('load', onLoad); @@ -832,17 +832,17 @@ style.textContent = styleTemplate.replace('{{tabId}}', localTabId); document.body.classList.add('popupOn'); - }; + }; - let toggleOff = function () { + let toggleOff = function () { document.body.classList.remove('popupOn'); container - .querySelector('div > span:nth-of-type(1)') - .removeEventListener('click', toggleSize); + .querySelector('div > span:nth-of-type(1)') + .removeEventListener('click', toggleSize); container - .querySelector('div > span:nth-of-type(2)') - .removeEventListener('click', toggleOff); + .querySelector('div > span:nth-of-type(2)') + .removeEventListener('click', toggleOff); container.classList.remove('hide'); popup.removeEventListener('load', onLoad); @@ -857,48 +857,48 @@ container = null; realTabId = null; - }; + }; - let exports = { + let exports = { toggleOn: function (ev) { - if (realTabId === null) { + if (realTabId === null) { toggleOn(ev.target); - } + } }, toggleOff: function () { - if (realTabId !== null) { + if (realTabId !== null) { toggleOff(); - } + } } - }; + }; - Object.defineProperty(exports, 'tabId', { + Object.defineProperty(exports, 'tabId', { get: function () { - return realTabId || 0; - }, - }); + return realTabId || 0; + }, + }); - return exports; + return exports; })(); let grabView = function () { - if (ownerId === undefined) { + if (ownerId === undefined) { ownerId = Date.now(); - } - readLogBufferAsync(); + } + readLogBufferAsync(); }; let releaseView = function () { - if (ownerId === undefined) { - return; - } + if (ownerId === undefined) { + return; + } - vAPI.messaging.send('logger-ui.js', { - what: 'releaseView', - ownerId: ownerId - }); + vAPI.messaging.send('logger-ui.js', { + what: 'releaseView', + ownerId: ownerId + }); - ownerId = undefined; + ownerId = undefined; }; window.addEventListener('pagehide', releaseView); @@ -915,7 +915,7 @@ uDom('#clear').on('click', clearBuffer); uDom('#maxEntries').on('change', onMaxEntriesChanged); uDom('#content table').on('click', 'tr > td:nth-of-type(1)', - toggleCompactRow); + toggleCompactRow); uDom('#content table').on('click', 'tr.canMtx > td:nth-of-type(2)', - popupManager.toggleOn); + popupManager.toggleOn); })(); diff --git a/js/logger.js b/js/logger.js index a602d91..86f8c9c 100644 --- a/js/logger.js +++ b/js/logger.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2015-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uBlock */ @@ -48,7 +48,7 @@ var janitor = function () { if (buffer !== null - && lastReadTime < (Date.now() - logBufferObsoleteAfter)) { + && lastReadTime < (Date.now() - logBufferObsoleteAfter)) { buffer = null; writePtr = 0; api.ownerId = undefined; @@ -63,8 +63,8 @@ writeOne: function () { if (buffer === null) { - return; - } + return; + } if (writePtr === buffer.length) { buffer.push(new LogEntry(arguments)); diff --git a/js/main-blocked.js b/js/main-blocked.js index cea79ce..20703a7 100644 --- a/js/main-blocked.js +++ b/js/main-blocked.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2015-2019 Raymond Hill - Copyright (C) 2019-2020-2021 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/js/matrix.js b/js/matrix.js index fc0c90d..58276f6 100644 --- a/js/matrix.js +++ b/js/matrix.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -32,844 +32,844 @@ Cu.import('chrome://ematrix/content/lib/Punycode.jsm'); Cu.import('chrome://ematrix/content/lib/UriTools.jsm'); - /******************************************************************************/ +/******************************************************************************/ - var ηm = ηMatrix; - var magicId = 'axyorpwxtmnf'; - var uniqueIdGenerator = 1; +var ηm = ηMatrix; +var magicId = 'axyorpwxtmnf'; +var uniqueIdGenerator = 1; - /******************************************************************************/ +/******************************************************************************/ - var Matrix = function() { - this.id = uniqueIdGenerator++; - this.reset(); - this.sourceRegister = ''; - this.decomposedSourceRegister = ['']; - this.specificityRegister = 0; - }; +var Matrix = function() { + this.id = uniqueIdGenerator++; + this.reset(); + this.sourceRegister = ''; + this.decomposedSourceRegister = ['']; + this.specificityRegister = 0; +}; - /******************************************************************************/ - - Matrix.Transparent = 0; - Matrix.Red = 1; - Matrix.Green = 2; - Matrix.Gray = 3; - - Matrix.Indirect = 0x00; - Matrix.Direct = 0x80; - - Matrix.RedDirect = Matrix.Red | Matrix.Direct; - Matrix.RedIndirect = Matrix.Red | Matrix.Indirect; - Matrix.GreenDirect = Matrix.Green | Matrix.Direct; - Matrix.GreenIndirect = Matrix.Green | Matrix.Indirect; - Matrix.GrayDirect = Matrix.Gray | Matrix.Direct; - Matrix.GrayIndirect = Matrix.Gray | Matrix.Indirect; - - /******************************************************************************/ - - var typeBitOffsets = new Map([ - [ '*', 0 ], - [ 'doc', 2 ], - [ 'cookie', 4 ], - [ 'css', 6 ], - [ 'image', 8 ], - [ 'media', 10 ], - [ 'script', 12 ], - [ 'xhr', 14 ], - [ 'frame', 16 ], - [ 'other', 18 ] - ]); - - var stateToNameMap = new Map([ - [ 1, 'block' ], - [ 2, 'allow' ], - [ 3, 'inherit' ] - ]); - - var nameToStateMap = { - 'block': 1, - 'allow': 2, - 'noop': 2, - 'inherit': 3 - }; +/******************************************************************************/ - var switchBitOffsets = new Map([ - [ 'matrix-off', 0 ], - [ 'https-strict', 2 ], - /* 4 is now unused, formerly assigned to UA spoofing */ - [ 'referrer-spoof', 6 ], - [ 'noscript-spoof', 8 ], - [ 'no-workers', 10 ] - ]); - - var switchStateToNameMap = new Map([ - [ 1, 'true' ], - [ 2, 'false' ] - ]); - - var nameToSwitchStateMap = { - 'true': 1, - 'false': 2 - }; +Matrix.Transparent = 0; +Matrix.Red = 1; +Matrix.Green = 2; +Matrix.Gray = 3; - /******************************************************************************/ +Matrix.Indirect = 0x00; +Matrix.Direct = 0x80; - Matrix.columnHeaderIndices = (function() { - var out = new Map(), - i = 0; - for ( var type of typeBitOffsets.keys() ) { - out.set(type, i++); - } - return out; - })(); +Matrix.RedDirect = Matrix.Red | Matrix.Direct; +Matrix.RedIndirect = Matrix.Red | Matrix.Indirect; +Matrix.GreenDirect = Matrix.Green | Matrix.Direct; +Matrix.GreenIndirect = Matrix.Green | Matrix.Indirect; +Matrix.GrayDirect = Matrix.Gray | Matrix.Direct; +Matrix.GrayIndirect = Matrix.Gray | Matrix.Indirect; +/******************************************************************************/ - Matrix.switchNames = new Set(switchBitOffsets.keys()); +var typeBitOffsets = new Map([ + [ '*', 0 ], + [ 'doc', 2 ], + [ 'cookie', 4 ], + [ 'css', 6 ], + [ 'image', 8 ], + [ 'media', 10 ], + [ 'script', 12 ], + [ 'xhr', 14 ], + [ 'frame', 16 ], + [ 'other', 18 ] +]); + +var stateToNameMap = new Map([ + [ 1, 'block' ], + [ 2, 'allow' ], + [ 3, 'inherit' ] +]); + +var nameToStateMap = { + 'block': 1, + 'allow': 2, + 'noop': 2, + 'inherit': 3 +}; + +var switchBitOffsets = new Map([ + [ 'matrix-off', 0 ], + [ 'https-strict', 2 ], + /* 4 is now unused, formerly assigned to UA spoofing */ + [ 'referrer-spoof', 6 ], + [ 'noscript-spoof', 8 ], + [ 'no-workers', 10 ] +]); + +var switchStateToNameMap = new Map([ + [ 1, 'true' ], + [ 2, 'false' ] +]); + +var nameToSwitchStateMap = { + 'true': 1, + 'false': 2 +}; - /******************************************************************************/ +/******************************************************************************/ - // For performance purpose, as simple tests as possible - var reHostnameVeryCoarse = /[g-z_-]/; - var reIPv4VeryCoarse = /\.\d+$/; +Matrix.columnHeaderIndices = (function() { + var out = new Map(), + i = 0; + for ( var type of typeBitOffsets.keys() ) { + out.set(type, i++); + } + return out; +})(); - // http://tools.ietf.org/html/rfc5952 - // 4.3: "MUST be represented in lowercase" - // Also: http://en.wikipedia.org/wiki/IPv6_address#Literal_IPv6_addresses_in_network_resource_identifiers - var isIPAddress = function(hostname) { - if ( reHostnameVeryCoarse.test(hostname) ) { - return false; - } - if ( reIPv4VeryCoarse.test(hostname) ) { - return true; - } - return hostname.charAt(0) === '['; - }; +Matrix.switchNames = new Set(switchBitOffsets.keys()); - /******************************************************************************/ +/******************************************************************************/ - var toBroaderHostname = function(hostname) { - if ( hostname === '*' ) { return ''; } - if ( isIPAddress(hostname) ) { - return toBroaderIPAddress(hostname); - } - var pos = hostname.indexOf('.'); - if ( pos === -1 ) { - return '*'; - } - return hostname.slice(pos + 1); - }; +// For performance purpose, as simple tests as possible +var reHostnameVeryCoarse = /[g-z_-]/; +var reIPv4VeryCoarse = /\.\d+$/; - var toBroaderIPAddress = function(ipaddress) { - // Can't broaden IPv6 (for now) - if ( ipaddress.charAt(0) === '[' ) { - return '*'; - } - var pos = ipaddress.lastIndexOf('.'); - return pos !== -1 ? ipaddress.slice(0, pos) : '*'; - }; +// http://tools.ietf.org/html/rfc5952 +// 4.3: "MUST be represented in lowercase" +// Also: http://en.wikipedia.org/wiki/IPv6_address#Literal_IPv6_addresses_in_network_resource_identifiers - Matrix.toBroaderHostname = toBroaderHostname; +var isIPAddress = function(hostname) { + if ( reHostnameVeryCoarse.test(hostname) ) { + return false; + } + if ( reIPv4VeryCoarse.test(hostname) ) { + return true; + } + return hostname.charAt(0) === '['; +}; - /******************************************************************************/ +/******************************************************************************/ - // Find out src-des relationship, using coarse-to-fine grained tests for - // speed. If desHostname is 1st-party to srcHostname, the domain is returned, - // otherwise the empty string. +var toBroaderHostname = function(hostname) { + if ( hostname === '*' ) { return ''; } + if ( isIPAddress(hostname) ) { + return toBroaderIPAddress(hostname); + } + var pos = hostname.indexOf('.'); + if ( pos === -1 ) { + return '*'; + } + return hostname.slice(pos + 1); +}; + +var toBroaderIPAddress = function(ipaddress) { + // Can't broaden IPv6 (for now) + if ( ipaddress.charAt(0) === '[' ) { + return '*'; + } + var pos = ipaddress.lastIndexOf('.'); + return pos !== -1 ? ipaddress.slice(0, pos) : '*'; +}; + +Matrix.toBroaderHostname = toBroaderHostname; - var extractFirstPartyDesDomain = function(srcHostname, desHostname) { - if ( srcHostname === '*' || desHostname === '*' || desHostname === '1st-party' ) { - return ''; - } - var ηmuri = UriTools; - var srcDomain = ηmuri.domainFromHostname(srcHostname) || srcHostname; - var desDomain = ηmuri.domainFromHostname(desHostname) || desHostname; - return desDomain === srcDomain ? desDomain : ''; - }; +/******************************************************************************/ - /******************************************************************************/ +// Find out src-des relationship, using coarse-to-fine grained tests for +// speed. If desHostname is 1st-party to srcHostname, the domain is returned, +// otherwise the empty string. - Matrix.prototype.reset = function() { - this.switches = new Map(); - this.rules = new Map(); - this.rootValue = Matrix.RedIndirect; - this.modifiedTime = 0; - }; +var extractFirstPartyDesDomain = function(srcHostname, desHostname) { + if ( srcHostname === '*' || desHostname === '*' || desHostname === '1st-party' ) { + return ''; + } + var ηmuri = UriTools; + var srcDomain = ηmuri.domainFromHostname(srcHostname) || srcHostname; + var desDomain = ηmuri.domainFromHostname(desHostname) || desHostname; + return desDomain === srcDomain ? desDomain : ''; +}; - /******************************************************************************/ +/******************************************************************************/ - Matrix.prototype.decomposeSource = function(srcHostname) { - if ( srcHostname === this.sourceRegister ) { return; } - var hn = srcHostname; - this.decomposedSourceRegister[0] = this.sourceRegister = hn; - var i = 1; - for (;;) { - hn = toBroaderHostname(hn); - this.decomposedSourceRegister[i++] = hn; - if ( hn === '' ) { break; } - } - }; +Matrix.prototype.reset = function() { + this.switches = new Map(); + this.rules = new Map(); + this.rootValue = Matrix.RedIndirect; + this.modifiedTime = 0; +}; - /******************************************************************************/ +/******************************************************************************/ - // Copy another matrix to self. Do this incrementally to minimize impact on - // a live matrix. +Matrix.prototype.decomposeSource = function(srcHostname) { + if ( srcHostname === this.sourceRegister ) { return; } + var hn = srcHostname; + this.decomposedSourceRegister[0] = this.sourceRegister = hn; + var i = 1; + for (;;) { + hn = toBroaderHostname(hn); + this.decomposedSourceRegister[i++] = hn; + if ( hn === '' ) { break; } + } +}; - Matrix.prototype.assign = function(other) { - var k, entry; - // Remove rules not in other - for ( k of this.rules.keys() ) { - if ( other.rules.has(k) === false ) { - this.rules.delete(k); - } - } - // Remove switches not in other - for ( k of this.switches.keys() ) { - if ( other.switches.has(k) === false ) { - this.switches.delete(k); - } - } - // Add/change rules in other - for ( entry of other.rules ) { - this.rules.set(entry[0], entry[1]); - } - // Add/change switches in other - for ( entry of other.switches ) { - this.switches.set(entry[0], entry[1]); - } - this.modifiedTime = other.modifiedTime; - return this; - }; +/******************************************************************************/ - // https://www.youtube.com/watch?v=e9RS4biqyAc +// Copy another matrix to self. Do this incrementally to minimize impact on +// a live matrix. - /******************************************************************************/ +Matrix.prototype.assign = function(other) { + var k, entry; + // Remove rules not in other + for ( k of this.rules.keys() ) { + if ( other.rules.has(k) === false ) { + this.rules.delete(k); + } + } + // Remove switches not in other + for ( k of this.switches.keys() ) { + if ( other.switches.has(k) === false ) { + this.switches.delete(k); + } + } + // Add/change rules in other + for ( entry of other.rules ) { + this.rules.set(entry[0], entry[1]); + } + // Add/change switches in other + for ( entry of other.switches ) { + this.switches.set(entry[0], entry[1]); + } + this.modifiedTime = other.modifiedTime; + return this; +}; + +// https://www.youtube.com/watch?v=e9RS4biqyAc - // If value is undefined, the switch is removed +/******************************************************************************/ - Matrix.prototype.setSwitch = function(switchName, srcHostname, newVal) { - var bitOffset = switchBitOffsets.get(switchName); - if ( bitOffset === undefined ) { - return false; - } - if ( newVal === this.evaluateSwitch(switchName, srcHostname) ) { - return false; - } - var bits = this.switches.get(srcHostname) || 0; - bits &= ~(3 << bitOffset); - bits |= newVal << bitOffset; - if ( bits === 0 ) { - this.switches.delete(srcHostname); - } else { - this.switches.set(srcHostname, bits); - } - this.modifiedTime = Date.now(); - return true; - }; +// If value is undefined, the switch is removed - /******************************************************************************/ +Matrix.prototype.setSwitch = function(switchName, srcHostname, newVal) { + var bitOffset = switchBitOffsets.get(switchName); + if ( bitOffset === undefined ) { + return false; + } + if ( newVal === this.evaluateSwitch(switchName, srcHostname) ) { + return false; + } + var bits = this.switches.get(srcHostname) || 0; + bits &= ~(3 << bitOffset); + bits |= newVal << bitOffset; + if ( bits === 0 ) { + this.switches.delete(srcHostname); + } else { + this.switches.set(srcHostname, bits); + } + this.modifiedTime = Date.now(); + return true; +}; - Matrix.prototype.setCell = function(srcHostname, desHostname, type, state) { - var bitOffset = typeBitOffsets.get(type), - k = srcHostname + ' ' + desHostname, - oldBitmap = this.rules.get(k); - if ( oldBitmap === undefined ) { - oldBitmap = 0; - } - var newBitmap = oldBitmap & ~(3 << bitOffset) | (state << bitOffset); - if ( newBitmap === oldBitmap ) { - return false; - } - if ( newBitmap === 0 ) { - this.rules.delete(k); - } else { - this.rules.set(k, newBitmap); - } - this.modifiedTime = Date.now(); - return true; - }; +/******************************************************************************/ - /******************************************************************************/ +Matrix.prototype.setCell = function(srcHostname, desHostname, type, state) { + var bitOffset = typeBitOffsets.get(type), + k = srcHostname + ' ' + desHostname, + oldBitmap = this.rules.get(k); + if ( oldBitmap === undefined ) { + oldBitmap = 0; + } + var newBitmap = oldBitmap & ~(3 << bitOffset) | (state << bitOffset); + if ( newBitmap === oldBitmap ) { + return false; + } + if ( newBitmap === 0 ) { + this.rules.delete(k); + } else { + this.rules.set(k, newBitmap); + } + this.modifiedTime = Date.now(); + return true; +}; - Matrix.prototype.blacklistCell = function(srcHostname, desHostname, type) { - var r = this.evaluateCellZ(srcHostname, desHostname, type); - if ( r === 1 ) { - return false; - } - this.setCell(srcHostname, desHostname, type, 0); - r = this.evaluateCellZ(srcHostname, desHostname, type); - if ( r === 1 ) { - return true; - } - this.setCell(srcHostname, desHostname, type, 1); +/******************************************************************************/ + +Matrix.prototype.blacklistCell = function(srcHostname, desHostname, type) { + var r = this.evaluateCellZ(srcHostname, desHostname, type); + if ( r === 1 ) { + return false; + } + this.setCell(srcHostname, desHostname, type, 0); + r = this.evaluateCellZ(srcHostname, desHostname, type); + if ( r === 1 ) { return true; - }; + } + this.setCell(srcHostname, desHostname, type, 1); + return true; +}; - /******************************************************************************/ +/******************************************************************************/ - Matrix.prototype.whitelistCell = function(srcHostname, desHostname, type) { - var r = this.evaluateCellZ(srcHostname, desHostname, type); - if ( r === 2 ) { - return false; - } - this.setCell(srcHostname, desHostname, type, 0); - r = this.evaluateCellZ(srcHostname, desHostname, type); - if ( r === 2 ) { - return true; - } - this.setCell(srcHostname, desHostname, type, 2); +Matrix.prototype.whitelistCell = function(srcHostname, desHostname, type) { + var r = this.evaluateCellZ(srcHostname, desHostname, type); + if ( r === 2 ) { + return false; + } + this.setCell(srcHostname, desHostname, type, 0); + r = this.evaluateCellZ(srcHostname, desHostname, type); + if ( r === 2 ) { return true; - }; + } + this.setCell(srcHostname, desHostname, type, 2); + return true; +}; - /******************************************************************************/ +/******************************************************************************/ - Matrix.prototype.graylistCell = function(srcHostname, desHostname, type) { - var r = this.evaluateCellZ(srcHostname, desHostname, type); - if ( r === 0 || r === 3 ) { - return false; - } - this.setCell(srcHostname, desHostname, type, 0); - r = this.evaluateCellZ(srcHostname, desHostname, type); - if ( r === 0 || r === 3 ) { - return true; - } - this.setCell(srcHostname, desHostname, type, 3); +Matrix.prototype.graylistCell = function(srcHostname, desHostname, type) { + var r = this.evaluateCellZ(srcHostname, desHostname, type); + if ( r === 0 || r === 3 ) { + return false; + } + this.setCell(srcHostname, desHostname, type, 0); + r = this.evaluateCellZ(srcHostname, desHostname, type); + if ( r === 0 || r === 3 ) { return true; - }; - - /******************************************************************************/ + } + this.setCell(srcHostname, desHostname, type, 3); + return true; +}; - Matrix.prototype.evaluateCell = function(srcHostname, desHostname, type) { - var key = srcHostname + ' ' + desHostname; - var bitmap = this.rules.get(key); - if ( bitmap === undefined ) { - return 0; - } - return bitmap >> typeBitOffsets.get(type) & 3; - }; +/******************************************************************************/ - /******************************************************************************/ +Matrix.prototype.evaluateCell = function(srcHostname, desHostname, type) { + var key = srcHostname + ' ' + desHostname; + var bitmap = this.rules.get(key); + if ( bitmap === undefined ) { + return 0; + } + return bitmap >> typeBitOffsets.get(type) & 3; +}; - Matrix.prototype.evaluateCellZ = function(srcHostname, desHostname, type) { - this.decomposeSource(srcHostname); +/******************************************************************************/ - var bitOffset = typeBitOffsets.get(type), - s, v, i = 0; - for (;;) { - s = this.decomposedSourceRegister[i++]; - if ( s === '' ) { break; } - v = this.rules.get(s + ' ' + desHostname); - if ( v !== undefined ) { - v = v >> bitOffset & 3; - if ( v !== 0 ) { - return v; - } +Matrix.prototype.evaluateCellZ = function(srcHostname, desHostname, type) { + this.decomposeSource(srcHostname); + + var bitOffset = typeBitOffsets.get(type), + s, v, i = 0; + for (;;) { + s = this.decomposedSourceRegister[i++]; + if ( s === '' ) { break; } + v = this.rules.get(s + ' ' + desHostname); + if ( v !== undefined ) { + v = v >> bitOffset & 3; + if ( v !== 0 ) { + return v; } } - // srcHostname is '*' at this point + } + // srcHostname is '*' at this point - // Preset blacklisted hostnames are blacklisted in global scope - if ( type === '*' && ηm.ubiquitousBlacklist.test(desHostname) ) { - return 1; - } + // Preset blacklisted hostnames are blacklisted in global scope + if ( type === '*' && ηm.ubiquitousBlacklist.test(desHostname) ) { + return 1; + } - // https://github.com/gorhill/uMatrix/issues/65 - // Hardcoded global `doc` rule - if ( type === 'doc' && desHostname === '*' ) { - return 2; - } + // https://github.com/gorhill/uMatrix/issues/65 + // Hardcoded global `doc` rule + if ( type === 'doc' && desHostname === '*' ) { + return 2; + } - return 0; - }; - - /******************************************************************************/ + return 0; +}; - Matrix.prototype.evaluateCellZXY = function(srcHostname, desHostname, type) { - // Matrix filtering switch - this.specificityRegister = 0; - if ( this.evaluateSwitchZ('matrix-off', srcHostname) ) { - return Matrix.GreenIndirect; - } - - // TODO: There are cells evaluated twice when the type is '*'. Unsure - // whether it's worth trying to avoid that, as this could introduce - // overhead which may not be gained back by skipping the redundant tests. - // And this happens *only* when building the matrix UI, not when - // evaluating net requests. - - // Specific-hostname specific-type cell - this.specificityRegister = 1; - var r = this.evaluateCellZ(srcHostname, desHostname, type); - if ( r === 1 ) { return Matrix.RedDirect; } - if ( r === 2 ) { return Matrix.GreenDirect; } - - // Specific-hostname any-type cell - this.specificityRegister = 2; - var rl = this.evaluateCellZ(srcHostname, desHostname, '*'); - if ( rl === 1 ) { return Matrix.RedIndirect; } - - var d = desHostname; - var firstPartyDesDomain = extractFirstPartyDesDomain(srcHostname, desHostname); - - // Ancestor cells, up to 1st-party destination domain - if ( firstPartyDesDomain !== '' ) { - this.specificityRegister = 3; - for (;;) { - if ( d === firstPartyDesDomain ) { break; } - d = d.slice(d.indexOf('.') + 1); - - // specific-hostname specific-type cell - r = this.evaluateCellZ(srcHostname, d, type); - if ( r === 1 ) { return Matrix.RedIndirect; } - if ( r === 2 ) { return Matrix.GreenIndirect; } - // Do not override a narrower rule - if ( rl !== 2 ) { - rl = this.evaluateCellZ(srcHostname, d, '*'); - if ( rl === 1 ) { return Matrix.RedIndirect; } - } - } - - // 1st-party specific-type cell: it's a special row, looked up only - // when destination is 1st-party to source. - r = this.evaluateCellZ(srcHostname, '1st-party', type); - if ( r === 1 ) { return Matrix.RedIndirect; } - if ( r === 2 ) { return Matrix.GreenIndirect; } - // Do not override narrower rule - if ( rl !== 2 ) { - rl = this.evaluateCellZ(srcHostname, '1st-party', '*'); - if ( rl === 1 ) { return Matrix.RedIndirect; } - } - } +/******************************************************************************/ - // Keep going, up to root - this.specificityRegister = 4; +Matrix.prototype.evaluateCellZXY = function(srcHostname, desHostname, type) { + // Matrix filtering switch + this.specificityRegister = 0; + if ( this.evaluateSwitchZ('matrix-off', srcHostname) ) { + return Matrix.GreenIndirect; + } + + // TODO: There are cells evaluated twice when the type is '*'. Unsure + // whether it's worth trying to avoid that, as this could introduce + // overhead which may not be gained back by skipping the redundant tests. + // And this happens *only* when building the matrix UI, not when + // evaluating net requests. + + // Specific-hostname specific-type cell + this.specificityRegister = 1; + var r = this.evaluateCellZ(srcHostname, desHostname, type); + if ( r === 1 ) { return Matrix.RedDirect; } + if ( r === 2 ) { return Matrix.GreenDirect; } + + // Specific-hostname any-type cell + this.specificityRegister = 2; + var rl = this.evaluateCellZ(srcHostname, desHostname, '*'); + if ( rl === 1 ) { return Matrix.RedIndirect; } + + var d = desHostname; + var firstPartyDesDomain = extractFirstPartyDesDomain(srcHostname, desHostname); + + // Ancestor cells, up to 1st-party destination domain + if ( firstPartyDesDomain !== '' ) { + this.specificityRegister = 3; for (;;) { - d = toBroaderHostname(d); - if ( d === '*' ) { break; } + if ( d === firstPartyDesDomain ) { break; } + d = d.slice(d.indexOf('.') + 1); // specific-hostname specific-type cell r = this.evaluateCellZ(srcHostname, d, type); if ( r === 1 ) { return Matrix.RedIndirect; } if ( r === 2 ) { return Matrix.GreenIndirect; } - // Do not override narrower rule + // Do not override a narrower rule if ( rl !== 2 ) { rl = this.evaluateCellZ(srcHostname, d, '*'); if ( rl === 1 ) { return Matrix.RedIndirect; } } } - // Any-hostname specific-type cells - this.specificityRegister = 5; - r = this.evaluateCellZ(srcHostname, '*', type); - // Line below is strict-blocking + // 1st-party specific-type cell: it's a special row, looked up only + // when destination is 1st-party to source. + r = this.evaluateCellZ(srcHostname, '1st-party', type); if ( r === 1 ) { return Matrix.RedIndirect; } - // Narrower rule wins - if ( rl === 2 ) { return Matrix.GreenIndirect; } if ( r === 2 ) { return Matrix.GreenIndirect; } + // Do not override narrower rule + if ( rl !== 2 ) { + rl = this.evaluateCellZ(srcHostname, '1st-party', '*'); + if ( rl === 1 ) { return Matrix.RedIndirect; } + } + } - // Any-hostname any-type cell - this.specificityRegister = 6; - r = this.evaluateCellZ(srcHostname, '*', '*'); + // Keep going, up to root + this.specificityRegister = 4; + for (;;) { + d = toBroaderHostname(d); + if ( d === '*' ) { break; } + + // specific-hostname specific-type cell + r = this.evaluateCellZ(srcHostname, d, type); if ( r === 1 ) { return Matrix.RedIndirect; } if ( r === 2 ) { return Matrix.GreenIndirect; } - return this.rootValue; - }; - - // https://www.youtube.com/watch?v=4C5ZkwrnVfM + // Do not override narrower rule + if ( rl !== 2 ) { + rl = this.evaluateCellZ(srcHostname, d, '*'); + if ( rl === 1 ) { return Matrix.RedIndirect; } + } + } + + // Any-hostname specific-type cells + this.specificityRegister = 5; + r = this.evaluateCellZ(srcHostname, '*', type); + // Line below is strict-blocking + if ( r === 1 ) { return Matrix.RedIndirect; } + // Narrower rule wins + if ( rl === 2 ) { return Matrix.GreenIndirect; } + if ( r === 2 ) { return Matrix.GreenIndirect; } + + // Any-hostname any-type cell + this.specificityRegister = 6; + r = this.evaluateCellZ(srcHostname, '*', '*'); + if ( r === 1 ) { return Matrix.RedIndirect; } + if ( r === 2 ) { return Matrix.GreenIndirect; } + return this.rootValue; +}; + +// https://www.youtube.com/watch?v=4C5ZkwrnVfM - /******************************************************************************/ +/******************************************************************************/ - Matrix.prototype.evaluateRowZXY = function(srcHostname, desHostname) { - var out = []; - for ( var type of typeBitOffsets.keys() ) { - out.push(this.evaluateCellZXY(srcHostname, desHostname, type)); - } - return out; - }; +Matrix.prototype.evaluateRowZXY = function(srcHostname, desHostname) { + var out = []; + for ( var type of typeBitOffsets.keys() ) { + out.push(this.evaluateCellZXY(srcHostname, desHostname, type)); + } + return out; +}; - /******************************************************************************/ +/******************************************************************************/ - Matrix.prototype.mustBlock = function(srcHostname, desHostname, type) { - return (this.evaluateCellZXY(srcHostname, desHostname, type) & 3) === Matrix.Red; - }; +Matrix.prototype.mustBlock = function(srcHostname, desHostname, type) { + return (this.evaluateCellZXY(srcHostname, desHostname, type) & 3) === Matrix.Red; +}; - /******************************************************************************/ +/******************************************************************************/ - Matrix.prototype.srcHostnameFromRule = function(rule) { - return rule.slice(0, rule.indexOf(' ')); - }; +Matrix.prototype.srcHostnameFromRule = function(rule) { + return rule.slice(0, rule.indexOf(' ')); +}; - /******************************************************************************/ +/******************************************************************************/ - Matrix.prototype.desHostnameFromRule = function(rule) { - return rule.slice(rule.indexOf(' ') + 1); - }; +Matrix.prototype.desHostnameFromRule = function(rule) { + return rule.slice(rule.indexOf(' ') + 1); +}; - /******************************************************************************/ +/******************************************************************************/ - Matrix.prototype.setSwitchZ = function(switchName, srcHostname, newState) { - var bitOffset = switchBitOffsets.get(switchName); - if ( bitOffset === undefined ) { - return false; - } - var state = this.evaluateSwitchZ(switchName, srcHostname); - if ( newState === state ) { - return false; - } - if ( newState === undefined ) { - newState = !state; - } - var bits = this.switches.get(srcHostname) || 0; - bits &= ~(3 << bitOffset); - if ( bits === 0 ) { - this.switches.delete(srcHostname); - } else { - this.switches.set(srcHostname, bits); - } - this.modifiedTime = Date.now(); - state = this.evaluateSwitchZ(switchName, srcHostname); - if ( state === newState ) { - return true; - } - this.switches.set(srcHostname, bits | ((newState ? 1 : 2) << bitOffset)); +Matrix.prototype.setSwitchZ = function(switchName, srcHostname, newState) { + var bitOffset = switchBitOffsets.get(switchName); + if ( bitOffset === undefined ) { + return false; + } + var state = this.evaluateSwitchZ(switchName, srcHostname); + if ( newState === state ) { + return false; + } + if ( newState === undefined ) { + newState = !state; + } + var bits = this.switches.get(srcHostname) || 0; + bits &= ~(3 << bitOffset); + if ( bits === 0 ) { + this.switches.delete(srcHostname); + } else { + this.switches.set(srcHostname, bits); + } + this.modifiedTime = Date.now(); + state = this.evaluateSwitchZ(switchName, srcHostname); + if ( state === newState ) { return true; - }; + } + this.switches.set(srcHostname, bits | ((newState ? 1 : 2) << bitOffset)); + return true; +}; - /******************************************************************************/ +/******************************************************************************/ - // 0 = inherit from broader scope, up to default state - // 1 = non-default state - // 2 = forced default state (to override a broader non-default state) +// 0 = inherit from broader scope, up to default state +// 1 = non-default state +// 2 = forced default state (to override a broader non-default state) - Matrix.prototype.evaluateSwitch = function(switchName, srcHostname) { - var bits = this.switches.get(srcHostname) || 0; - if ( bits === 0 ) { - return 0; - } - var bitOffset = switchBitOffsets.get(switchName); - if ( bitOffset === undefined ) { - return 0; - } - return (bits >> bitOffset) & 3; - }; +Matrix.prototype.evaluateSwitch = function(switchName, srcHostname) { + var bits = this.switches.get(srcHostname) || 0; + if ( bits === 0 ) { + return 0; + } + var bitOffset = switchBitOffsets.get(switchName); + if ( bitOffset === undefined ) { + return 0; + } + return (bits >> bitOffset) & 3; +}; - /******************************************************************************/ +/******************************************************************************/ - Matrix.prototype.evaluateSwitchZ = function(switchName, srcHostname) { - var bitOffset = switchBitOffsets.get(switchName); - if ( bitOffset === undefined ) { return false; } +Matrix.prototype.evaluateSwitchZ = function(switchName, srcHostname) { + var bitOffset = switchBitOffsets.get(switchName); + if ( bitOffset === undefined ) { return false; } - this.decomposeSource(srcHostname); + this.decomposeSource(srcHostname); - var s, bits, i = 0; - for (;;) { - s = this.decomposedSourceRegister[i++]; - if ( s === '' ) { break; } - bits = this.switches.get(s) || 0; + var s, bits, i = 0; + for (;;) { + s = this.decomposedSourceRegister[i++]; + if ( s === '' ) { break; } + bits = this.switches.get(s) || 0; + if ( bits !== 0 ) { + bits = bits >> bitOffset & 3; if ( bits !== 0 ) { - bits = bits >> bitOffset & 3; - if ( bits !== 0 ) { - return bits === 1; - } + return bits === 1; } } - return false; - }; + } + return false; +}; - /******************************************************************************/ - - Matrix.prototype.extractAllSourceHostnames = (function() { - var cachedResult = new Set(); - var matrixId = 0; - var readTime = 0; - - return function() { - if ( matrixId !== this.id || readTime !== this.modifiedTime ) { - cachedResult.clear(); - for ( var rule of this.rules.keys() ) { - cachedResult.add(rule.slice(0, rule.indexOf(' '))); - } - matrixId = this.id; - readTime = this.modifiedTime; - } - return cachedResult; - }; - })(); - - /******************************************************************************/ - - Matrix.prototype.toString = function() { - var out = []; - var rule, type, switchName, val; - var srcHostname, desHostname; - for ( rule of this.rules.keys() ) { - srcHostname = this.srcHostnameFromRule(rule); - desHostname = this.desHostnameFromRule(rule); - for ( type of typeBitOffsets.keys() ) { - val = this.evaluateCell(srcHostname, desHostname, type); - if ( val === 0 ) { continue; } - out.push( - Punycode.toUnicode(srcHostname) + ' ' + - Punycode.toUnicode(desHostname) + ' ' + - type + ' ' + - stateToNameMap.get(val) - ); - } - } - for ( srcHostname of this.switches.keys() ) { - for ( switchName of switchBitOffsets.keys() ) { - val = this.evaluateSwitch(switchName, srcHostname); - if ( val === 0 ) { continue; } - out.push(switchName + ': ' + srcHostname + ' ' + switchStateToNameMap.get(val)); +/******************************************************************************/ + +Matrix.prototype.extractAllSourceHostnames = (function() { + var cachedResult = new Set(); + var matrixId = 0; + var readTime = 0; + + return function() { + if ( matrixId !== this.id || readTime !== this.modifiedTime ) { + cachedResult.clear(); + for ( var rule of this.rules.keys() ) { + cachedResult.add(rule.slice(0, rule.indexOf(' '))); } + matrixId = this.id; + readTime = this.modifiedTime; } - return out.sort().join('\n'); + return cachedResult; }; +})(); + +/******************************************************************************/ - /******************************************************************************/ - - Matrix.prototype.fromString = function(text, append) { - var matrix = append ? this : new Matrix(); - var textEnd = text.length; - var lineBeg = 0, lineEnd; - var line, pos; - var fields, fieldVal; - var switchName; - var srcHostname = ''; - var desHostname = ''; - var type, state; - - while ( lineBeg < textEnd ) { - lineEnd = text.indexOf('\n', lineBeg); +Matrix.prototype.toString = function() { + var out = []; + var rule, type, switchName, val; + var srcHostname, desHostname; + for ( rule of this.rules.keys() ) { + srcHostname = this.srcHostnameFromRule(rule); + desHostname = this.desHostnameFromRule(rule); + for ( type of typeBitOffsets.keys() ) { + val = this.evaluateCell(srcHostname, desHostname, type); + if ( val === 0 ) { continue; } + out.push( + Punycode.toUnicode(srcHostname) + ' ' + + Punycode.toUnicode(desHostname) + ' ' + + type + ' ' + + stateToNameMap.get(val) + ); + } + } + for ( srcHostname of this.switches.keys() ) { + for ( switchName of switchBitOffsets.keys() ) { + val = this.evaluateSwitch(switchName, srcHostname); + if ( val === 0 ) { continue; } + out.push(switchName + ': ' + srcHostname + ' ' + switchStateToNameMap.get(val)); + } + } + return out.sort().join('\n'); +}; + +/******************************************************************************/ + +Matrix.prototype.fromString = function(text, append) { + var matrix = append ? this : new Matrix(); + var textEnd = text.length; + var lineBeg = 0, lineEnd; + var line, pos; + var fields, fieldVal; + var switchName; + var srcHostname = ''; + var desHostname = ''; + var type, state; + + while ( lineBeg < textEnd ) { + lineEnd = text.indexOf('\n', lineBeg); + if ( lineEnd < 0 ) { + lineEnd = text.indexOf('\r', lineBeg); if ( lineEnd < 0 ) { - lineEnd = text.indexOf('\r', lineBeg); - if ( lineEnd < 0 ) { - lineEnd = textEnd; - } + lineEnd = textEnd; } - line = text.slice(lineBeg, lineEnd).trim(); - lineBeg = lineEnd + 1; + } + line = text.slice(lineBeg, lineEnd).trim(); + lineBeg = lineEnd + 1; - pos = line.indexOf('# '); - if ( pos !== -1 ) { - line = line.slice(0, pos).trim(); - } - if ( line === '' ) { - continue; - } + pos = line.indexOf('# '); + if ( pos !== -1 ) { + line = line.slice(0, pos).trim(); + } + if ( line === '' ) { + continue; + } - fields = line.split(/\s+/); + fields = line.split(/\s+/); - // Less than 2 fields makes no sense - if ( fields.length < 2 ) { - continue; - } + // Less than 2 fields makes no sense + if ( fields.length < 2 ) { + continue; + } - fieldVal = fields[0]; + fieldVal = fields[0]; - // Special directives: + // Special directives: - // title - pos = fieldVal.indexOf('title:'); - if ( pos !== -1 ) { - // TODO - continue; - } + // title + pos = fieldVal.indexOf('title:'); + if ( pos !== -1 ) { + // TODO + continue; + } - // Name - pos = fieldVal.indexOf('name:'); - if ( pos !== -1 ) { - // TODO - continue; - } + // Name + pos = fieldVal.indexOf('name:'); + if ( pos !== -1 ) { + // TODO + continue; + } - // Switch on/off + // Switch on/off - // `switch:` srcHostname state - // state = [`true`, `false`] - switchName = ''; - if ( fieldVal === 'switch:' || fieldVal === 'matrix:' ) { - fieldVal = 'matrix-off:'; - } - pos = fieldVal.indexOf(':'); - if ( pos !== -1 ) { - switchName = fieldVal.slice(0, pos); + // `switch:` srcHostname state + // state = [`true`, `false`] + switchName = ''; + if ( fieldVal === 'switch:' || fieldVal === 'matrix:' ) { + fieldVal = 'matrix-off:'; + } + pos = fieldVal.indexOf(':'); + if ( pos !== -1 ) { + switchName = fieldVal.slice(0, pos); + } + if ( switchBitOffsets.has(switchName) ) { + srcHostname = Punycode.toASCII(fields[1]); + + // No state field: reject + fieldVal = fields[2]; + if ( fieldVal === null ) { + continue; } - if ( switchBitOffsets.has(switchName) ) { - srcHostname = Punycode.toASCII(fields[1]); - - // No state field: reject - fieldVal = fields[2]; - if ( fieldVal === null ) { - continue; - } - // Unknown state: reject - if ( nameToSwitchStateMap.hasOwnProperty(fieldVal) === false ) { - continue; - } - - // Backward compatibility: - // `chromium-behind-the-scene` is now `behind-the-scene` - if ( srcHostname === 'chromium-behind-the-scene' ) { - srcHostname = 'behind-the-scene'; - } - - matrix.setSwitch(switchName, srcHostname, nameToSwitchStateMap[fieldVal]); + // Unknown state: reject + if ( nameToSwitchStateMap.hasOwnProperty(fieldVal) === false ) { continue; } - // Unknown directive - if ( fieldVal.endsWith(':') ) { - continue; + // Backward compatibility: + // `chromium-behind-the-scene` is now `behind-the-scene` + if ( srcHostname === 'chromium-behind-the-scene' ) { + srcHostname = 'behind-the-scene'; } - // Valid rule syntax: + matrix.setSwitch(switchName, srcHostname, nameToSwitchStateMap[fieldVal]); + continue; + } - // srcHostname desHostname [type [state]] - // type = a valid request type - // state = [`block`, `allow`, `inherit`] + // Unknown directive + if ( fieldVal.endsWith(':') ) { + continue; + } - // srcHostname desHostname type - // type = a valid request type - // state = `allow` + // Valid rule syntax: - // srcHostname desHostname - // type = `*` - // state = `allow` + // srcHostname desHostname [type [state]] + // type = a valid request type + // state = [`block`, `allow`, `inherit`] - // Lines with invalid syntax silently ignored + // srcHostname desHostname type + // type = a valid request type + // state = `allow` - srcHostname = Punycode.toASCII(fields[0]); - desHostname = Punycode.toASCII(fields[1]); + // srcHostname desHostname + // type = `*` + // state = `allow` - fieldVal = fields[2]; + // Lines with invalid syntax silently ignored - if ( fieldVal !== undefined ) { - type = fieldVal; - // https://github.com/gorhill/uMatrix/issues/759 - // Backward compatibility. - if ( type === 'plugin' ) { - type = 'media'; - } - // Unknown type: reject - if ( typeBitOffsets.has(type) === false ) { - continue; - } - } else { - type = '*'; - } + srcHostname = Punycode.toASCII(fields[0]); + desHostname = Punycode.toASCII(fields[1]); - fieldVal = fields[3]; + fieldVal = fields[2]; - if ( fieldVal !== undefined ) { - // Unknown state: reject - if ( nameToStateMap.hasOwnProperty(fieldVal) === false ) { - continue; - } - state = nameToStateMap[fieldVal]; - } else { - state = 2; + if ( fieldVal !== undefined ) { + type = fieldVal; + // https://github.com/gorhill/uMatrix/issues/759 + // Backward compatibility. + if ( type === 'plugin' ) { + type = 'media'; } - - matrix.setCell(srcHostname, desHostname, type, state); + // Unknown type: reject + if ( typeBitOffsets.has(type) === false ) { + continue; + } + } else { + type = '*'; } - if ( !append ) { - this.assign(matrix); + fieldVal = fields[3]; + + if ( fieldVal !== undefined ) { + // Unknown state: reject + if ( nameToStateMap.hasOwnProperty(fieldVal) === false ) { + continue; + } + state = nameToStateMap[fieldVal]; + } else { + state = 2; } - this.modifiedTime = Date.now(); - }; + matrix.setCell(srcHostname, desHostname, type, state); + } - /******************************************************************************/ + if ( !append ) { + this.assign(matrix); + } - Matrix.prototype.toSelfie = function() { - return { - magicId: magicId, - switches: Array.from(this.switches), - rules: Array.from(this.rules) - }; - }; + this.modifiedTime = Date.now(); +}; - /******************************************************************************/ +/******************************************************************************/ - Matrix.prototype.fromSelfie = function(selfie) { - if ( selfie.magicId !== magicId ) { return false; } - this.switches = new Map(selfie.switches); - this.rules = new Map(selfie.rules); - this.modifiedTime = Date.now(); - return true; +Matrix.prototype.toSelfie = function() { + return { + magicId: magicId, + switches: Array.from(this.switches), + rules: Array.from(this.rules) }; +}; - /******************************************************************************/ +/******************************************************************************/ - Matrix.prototype.diff = function(other, srcHostname, desHostnames) { - var out = []; - var desHostname, type; - var switchName, i, thisVal, otherVal; - for (;;) { - for ( switchName of switchBitOffsets.keys() ) { - thisVal = this.evaluateSwitch(switchName, srcHostname); - otherVal = other.evaluateSwitch(switchName, srcHostname); - if ( thisVal !== otherVal ) { - out.push({ - 'what': switchName, - 'src': srcHostname - }); - } - } - i = desHostnames.length; - while ( i-- ) { - desHostname = desHostnames[i]; - for ( type of typeBitOffsets.keys() ) { - thisVal = this.evaluateCell(srcHostname, desHostname, type); - otherVal = other.evaluateCell(srcHostname, desHostname, type); - if ( thisVal === otherVal ) { continue; } - out.push({ - 'what': 'rule', - 'src': srcHostname, - 'des': desHostname, - 'type': type - }); - } - } - srcHostname = toBroaderHostname(srcHostname); - if ( srcHostname === '' ) { - break; - } - } - return out; - }; +Matrix.prototype.fromSelfie = function(selfie) { + if ( selfie.magicId !== magicId ) { return false; } + this.switches = new Map(selfie.switches); + this.rules = new Map(selfie.rules); + this.modifiedTime = Date.now(); + return true; +}; - /******************************************************************************/ +/******************************************************************************/ - Matrix.prototype.applyDiff = function(diff, from) { - var changed = false; - var i = diff.length; - var action, val; - while ( i-- ) { - action = diff[i]; - if ( action.what === 'rule' ) { - val = from.evaluateCell(action.src, action.des, action.type); - changed = this.setCell(action.src, action.des, action.type, val) || changed; - continue; +Matrix.prototype.diff = function(other, srcHostname, desHostnames) { + var out = []; + var desHostname, type; + var switchName, i, thisVal, otherVal; + for (;;) { + for ( switchName of switchBitOffsets.keys() ) { + thisVal = this.evaluateSwitch(switchName, srcHostname); + otherVal = other.evaluateSwitch(switchName, srcHostname); + if ( thisVal !== otherVal ) { + out.push({ + 'what': switchName, + 'src': srcHostname + }); } - if ( switchBitOffsets.has(action.what) ) { - val = from.evaluateSwitch(action.what, action.src); - changed = this.setSwitch(action.what, action.src, val) || changed; - continue; + } + i = desHostnames.length; + while ( i-- ) { + desHostname = desHostnames[i]; + for ( type of typeBitOffsets.keys() ) { + thisVal = this.evaluateCell(srcHostname, desHostname, type); + otherVal = other.evaluateCell(srcHostname, desHostname, type); + if ( thisVal === otherVal ) { continue; } + out.push({ + 'what': 'rule', + 'src': srcHostname, + 'des': desHostname, + 'type': type + }); } } - return changed; - }; + srcHostname = toBroaderHostname(srcHostname); + if ( srcHostname === '' ) { + break; + } + } + return out; +}; + +/******************************************************************************/ - /******************************************************************************/ +Matrix.prototype.applyDiff = function(diff, from) { + var changed = false; + var i = diff.length; + var action, val; + while ( i-- ) { + action = diff[i]; + if ( action.what === 'rule' ) { + val = from.evaluateCell(action.src, action.des, action.type); + changed = this.setCell(action.src, action.des, action.type, val) || changed; + continue; + } + if ( switchBitOffsets.has(action.what) ) { + val = from.evaluateSwitch(action.what, action.src); + changed = this.setSwitch(action.what, action.src, val) || changed; + continue; + } + } + return changed; +}; - return Matrix; +/******************************************************************************/ + +return Matrix; - /******************************************************************************/ +/******************************************************************************/ - // https://www.youtube.com/watch?v=wlNrQGmj6oQ +// https://www.youtube.com/watch?v=wlNrQGmj6oQ })(); diff --git a/js/messaging.js b/js/messaging.js index 6dd0979..86ac038 100644 --- a/js/messaging.js +++ b/js/messaging.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://notabug.org/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -343,7 +343,7 @@ let sz = ηm.tMatrix.evaluateSwitchZ(request.switchName, request.srcHostname); ηm.tMatrix.setSwitchZ(request.switchName, - request.scrHostname, + request.srcHostname, sz === false); return undefined; }); @@ -676,7 +676,7 @@ addMethod('purgeCache', function (request, sender, cb) { ηm.assets.purge(request.assetKey); - ηm.assets.remove('compiled/' + request.assetKey); + ηm.assets.remove('cache/' + request.assetKey); return undefined; }); @@ -722,16 +722,16 @@ }; let onAllRemoved = function () { - vAPI.storage.set(userData.settings, onCountdown); + vAPI.storage.set(data.settings, onCountdown); vAPI.storage.set({ - userMatrix: userData.rules, + userMatrix: data.rules, }, onCountdown); vAPI.storage.set({ - liveHostsFiles: userData.hostsFiles, + liveHostsFiles: data.hostsFiles, }, onCountdown); - if (userData.rawSettings instanceof Object) { - ηMatrix.saveRawSettings(userData.rawSettings, onCountdown); + if (data.rawSettings instanceof Object) { + ηMatrix.saveRawSettings(data.rawSettings, onCountdown); } }; @@ -740,7 +740,7 @@ ηm.XAL.keyvalRemoveAll(onAllRemoved); }; - restoreUserData(request.userData); + restoreData(request.userData); return undefined; }); @@ -750,6 +750,8 @@ }; ηm.XAL.keyvalRemoveAll(onAllRemoved); + /* Let's also clear the database, just to really make it a reset */ + ηm.assets.rmrf(); return undefined; }); @@ -768,7 +770,7 @@ let tabIds = {}; for (let id in ηm.pageStores) { - let store = ηm.pageStoreFromTabId(tabId); + let store = ηm.pageStoreFromTabId(id); if (store === null) { continue; diff --git a/js/pagestats.js b/js/pagestats.js index b4c65c1..fd1757d 100644 --- a/js/pagestats.js +++ b/js/pagestats.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2013-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,58 +30,58 @@ let ηm = ηMatrix; let BlockedCollapsibles = function () { - this.boundPruneAsyncCallback = this.pruneAsyncCallback.bind(this); - this.blocked = new Map(); - this.hash = 0; - this.timer = null; + this.boundPruneAsyncCallback = this.pruneAsyncCallback.bind(this); + this.blocked = new Map(); + this.hash = 0; + this.timer = null; }; BlockedCollapsibles.prototype = { - shelfLife: 10 * 1000, + shelfLife: 10 * 1000, - add: function (type, url, isSpecific) { + add: function (type, url, isSpecific) { if (this.blocked.size === 0) { - this.pruneAsync(); - } + this.pruneAsync(); + } let now = Date.now() / 1000 | 0; // The following "trick" is to encode the specifity into // the lsb of the time stamp so as to avoid to have to // allocate a memory structure to store both time stamp // and specificity. if (isSpecific) { - now |= 0x00000001; + now |= 0x00000001; } else { - now &= 0xFFFFFFFE; + now &= 0xFFFFFFFE; } this.blocked.set(type + ' ' + url, now); this.hash = now; - }, - reset: function () { + }, + reset: function () { this.blocked.clear(); this.hash = 0; if (this.timer !== null) { - clearTimeout(this.timer); - this.timer = null; + clearTimeout(this.timer); + this.timer = null; } - }, - pruneAsync: function () { + }, + pruneAsync: function () { if (this.timer === null) { - this.timer = vAPI.setTimeout(this.boundPruneAsyncCallback, - this.shelfLife * 2); + this.timer = vAPI.setTimeout(this.boundPruneAsyncCallback, + this.shelfLife * 2); } - }, - pruneAsyncCallback: function () { + }, + pruneAsyncCallback: function () { this.timer = null; let obsolete = Date.now() - this.shelfLife; for (let entry of this.blocked) { - if (entry[1] <= obsolete) { + if (entry[1] <= obsolete) { this.blocked.delete(entry[0]); - } + } } if (this.blocked.size !== 0) { - this.pruneAsync(); - } - } + this.pruneAsync(); + } + } }; // Ref: Given a URL, returns a (somewhat) unique 32-bit value @@ -89,19 +89,19 @@ // http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-reference-source // The rest is custom, suited for uMatrix. let PageStore = function (tabContext) { - this.hostnameTypeCells = new Map(); - this.domains = new Set(); - this.blockedCollapsibles = new BlockedCollapsibles(); - this.requestStats = ηm.requestStatsFactory(); - this.off = false; - this.init(tabContext); + this.hostnameTypeCells = new Map(); + this.domains = new Set(); + this.blockedCollapsibles = new BlockedCollapsibles(); + this.requestStats = ηm.requestStatsFactory(); + this.off = false; + this.init(tabContext); }; PageStore.prototype = { - collapsibleTypes: new Set([ 'image' ]), - pageStoreJunkyard: [], + collapsibleTypes: new Set([ 'image' ]), + pageStoreJunkyard: [], - init: function (tabContext) { + init: function (tabContext) { this.tabId = tabContext.tabId; this.rawUrl = tabContext.rawURL; this.pageUrl = tabContext.normalURL; @@ -124,8 +124,8 @@ this.mtxContentModifiedTime = 0; this.mtxCountModifiedTime = 0; return this; - }, - dispose: function () { + }, + dispose: function () { this.rawUrl = ''; this.pageUrl = ''; this.pageHostname = ''; @@ -136,72 +136,72 @@ this.allHostnamesString = ' '; this.blockedCollapsibles.reset(); if (this.incinerationTimer !== null) { - clearTimeout(this.incinerationTimer); - this.incinerationTimer = null; + clearTimeout(this.incinerationTimer); + this.incinerationTimer = null; } if (this.pageStoreJunkyard.length < 8) { - this.pageStoreJunkyard.push(this); + this.pageStoreJunkyard.push(this); } - }, - cacheBlockedCollapsible: function (type, url, specificity) { + }, + cacheBlockedCollapsible: function (type, url, specificity) { if (this.collapsibleTypes.has(type)) { - this.blockedCollapsibles.add(type, - url, - specificity !== 0 - && specificity < 5); + this.blockedCollapsibles.add(type, + url, + specificity !== 0 + && specificity < 5); } - }, - lookupBlockedCollapsibles: function (request, response) { + }, + lookupBlockedCollapsibles: function (request, response) { let tabContext = ηm.tabContextManager.lookup(this.tabId); if (tabContext === null) { - return; - } + return; + } let collapseBlacklisted = ηm.userSettings.collapseBlacklisted; - let collapseBlocked = ηm.userSettings.collapseBlocked; + let collapseBlocked = ηm.userSettings.collapseBlocked; let blockedResources = response.blockedResources; if (Array.isArray(request.toFilter) && request.toFilter.length !== 0) { - let roothn = tabContext.rootHostname; + let roothn = tabContext.rootHostname; let hnFromURI = UriTools.hostnameFromURI; let tMatrix = ηm.tMatrix; - for (let entry of request.toFilter) { + for (let entry of request.toFilter) { if (tMatrix.mustBlock(roothn, - hnFromURI(entry.url), - entry.type) === false) { - continue; + hnFromURI(entry.url), + entry.type) === false) { + continue; } blockedResources.push([ - entry.type + ' ' + entry.url, - collapseBlocked - || collapseBlacklisted - && tMatrix.specificityRegister !== 0 - && tMatrix.specificityRegister < 5 + entry.type + ' ' + entry.url, + collapseBlocked + || collapseBlacklisted + && tMatrix.specificityRegister !== 0 + && tMatrix.specificityRegister < 5 ]); - } + } } if (this.blockedCollapsibles.hash === response.hash) { - return; - } + return; + } response.hash = this.blockedCollapsibles.hash; for (let entry of this.blockedCollapsibles.blocked) { - blockedResources.push([ + blockedResources.push([ entry[0], collapseBlocked - || collapseBlacklisted - && (entry[1] & 1) !== 0 - ]); + || collapseBlacklisted + && (entry[1] & 1) !== 0 + ]); } - }, - recordRequest: function (type, url, block) { - if (block !== false) { - this.perLoadBlockedRequestCount++; + }, + recordRequest: function (type, url, block) { + if (block !== false) { + this.perLoadBlockedRequestCount++; } else { - this.perLoadAllowedRequestCount++; + this.perLoadAllowedRequestCount++; } // Store distinct network requests. This is used to: @@ -209,19 +209,19 @@ // - count the number of distinct URLs for any given // hostname-type pair let hostname = UriTools.hostnameFromURI(url); - let key = hostname + ' ' + type; - let uids = this.hostnameTypeCells.get(key); + let key = hostname + ' ' + type; + let uids = this.hostnameTypeCells.get(key); if (uids === undefined) { - this.hostnameTypeCells.set(key, (uids = new Set())); + this.hostnameTypeCells.set(key, (uids = new Set())); } else if (uids.size > 99) { - return; + return; } let uid = this.uidFromURL(url); if (uids.has(uid)) { - return; - } + return; + } uids.add(uid); // Count blocked/allowed requests @@ -236,28 +236,28 @@ this.mtxCountModifiedTime = Date.now(); if (this.domains.has(hostname) === false) { - this.domains.add(hostname); - this.allHostnamesString += hostname + ' '; - this.mtxContentModifiedTime = Date.now(); + this.domains.add(hostname); + this.allHostnamesString += hostname + ' '; + this.mtxContentModifiedTime = Date.now(); } - }, - uidFromURL: function (uri) { + }, + uidFromURL: function (uri) { var hint = 0x811c9dc5; - let i = uri.length; + let i = uri.length; while (i--) { - hint ^= uri.charCodeAt(i) | 0; - hint += (hint<<1) + (hint<<4) + (hint<<7) + (hint<<8) + (hint<<24) | 0; - hint >>>= 0; + hint ^= uri.charCodeAt(i) | 0; + hint += (hint<<1) + (hint<<4) + (hint<<7) + (hint<<8) + (hint<<24) | 0; + hint >>>= 0; } return hint; - } + } }; return function (tabContext) { - let entry = PageStore.prototype.pageStoreJunkyard.pop(); - if (entry) { + let entry = PageStore.prototype.pageStoreJunkyard.pop(); + if (entry) { return entry.init(tabContext); - } - return new PageStore(tabContext); + } + return new PageStore(tabContext); }; })(); diff --git a/js/polyfill.js b/js/polyfill.js index 27f2984..83f2fdb 100644 --- a/js/polyfill.js +++ b/js/polyfill.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2017-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix This file has been originally imported from: diff --git a/js/popup.js b/js/popup.js index d750997..073f57a 100644 --- a/js/popup.js +++ b/js/popup.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -29,67 +29,67 @@ // Stuff which is good to do very early so as to avoid visual glitches. (function () { - let paneContentPaddingTop = - vAPI.localStorage.getItem('paneContentPaddingTop'); + let paneContentPaddingTop = + vAPI.localStorage.getItem('paneContentPaddingTop'); let touchDevice = vAPI.localStorage.getItem('touchDevice'); - if (typeof paneContentPaddingTop === 'string') { + if (typeof paneContentPaddingTop === 'string') { document - .querySelector('.paneContent') - .style - .setProperty('padding-top', - paneContentPaddingTop); - } - - /* This is for CSS */ - if (touchDevice === 'true') { + .querySelector('.paneContent') + .style + .setProperty('padding-top', + paneContentPaddingTop); + } + + /* This is for CSS */ + if (touchDevice === 'true') { document.body.setAttribute('data-touch', 'true'); - } else { + } else { document.addEventListener('touchstart', function onTouched(ev) { - document.removeEventListener(ev.type, onTouched); - document.body.setAttribute('data-touch', 'true'); - vAPI.localStorage.setItem('touchDevice', 'true'); - resizePopup(); + document.removeEventListener(ev.type, onTouched); + document.body.setAttribute('data-touch', 'true'); + vAPI.localStorage.setItem('touchDevice', 'true'); + resizePopup(); }); - } + } })(); let popupWasResized = function () { - document.body.setAttribute('data-resize-popup', ''); + document.body.setAttribute('data-resize-popup', ''); }; let resizePopup = (function () { - let timer; + let timer; - let fix = function () { + let fix = function () { timer = undefined; let doc = document; // Manually adjust the position of the main matrix according to the // height of the toolbar/matrix header. let paddingTop = - (doc.querySelector('.paneHead').clientHeight + 2) + 'px'; + (doc.querySelector('.paneHead').clientHeight + 2) + 'px'; let paneContent = doc.querySelector('.paneContent'); if (paddingTop !== paneContent.style.paddingTop) { - paneContent.style.setProperty('padding-top', paddingTop); - vAPI.localStorage.setItem('paneContentPaddingTop', paddingTop); + paneContent.style.setProperty('padding-top', paddingTop); + vAPI.localStorage.setItem('paneContentPaddingTop', paddingTop); } document - .body - .classList - .toggle('hConstrained', - window.innerWidth < document.body.clientWidth); + .body + .classList + .toggle('hConstrained', + window.innerWidth < document.body.clientWidth); popupWasResized(); - }; + }; - return function () { + return function () { if (timer !== undefined) { - clearTimeout(timer); + clearTimeout(timer); } timer = vAPI.setTimeout(fix, 97); - }; + }; })(); // Must be consistent with definitions in matrix.js @@ -106,15 +106,15 @@ let matrixCellHotspots = null; let matrixHeaderPrettyNames = { - 'all': '', - 'cookie': '', - 'css': '', - 'image': '', - 'media': '', - 'script': '', - 'xhr': '', - 'frame': '', - 'other': '' + 'all': '', + 'cookie': '', + 'css': '', + 'image': '', + 'media': '', + 'script': '', + 'xhr': '', + 'frame': '', + 'other': '' }; let firstPartyLabel = ''; @@ -122,30 +122,30 @@ let expandosIdGenerator = 1; let nodeToExpandosMap = (function () { - if (typeof window.Map === 'function') { + if (typeof window.Map === 'function') { return new window.Map(); - } + } })(); let expandosFromNode = function (node) { - if (node instanceof HTMLElement === false - && typeof node.nodeAt === 'function') { + if (node instanceof HTMLElement === false + && typeof node.nodeAt === 'function') { node = node.nodeAt(0); - } - if (nodeToExpandosMap) { + } + if (nodeToExpandosMap) { let expandosId = node.getAttribute('data-expandos'); if (!expandosId) { - expandosId = '' + (expandosIdGenerator++); - node.setAttribute('data-expandos', expandosId); + expandosId = '' + (expandosIdGenerator++); + node.setAttribute('data-expandos', expandosId); } let expandos = nodeToExpandosMap.get(expandosId); if (expandos === undefined) { - expandos = Object.create(null); - nodeToExpandosMap.set(expandosId, expandos); + expandos = Object.create(null); + nodeToExpandosMap.set(expandosId, expandos); } return expandos; - } - return node; + } + return node; }; function getUserSetting(setting) { @@ -153,28 +153,28 @@ } function setUserSetting(setting, value) { - matrixSnapshot.userSettings[setting] = value; - vAPI.messaging.send('popup.js', { + matrixSnapshot.userSettings[setting] = value; + vAPI.messaging.send('popup.js', { what: 'userSettings', name: setting, value: value - }); + }); } function getUISetting(setting) { - let r = vAPI.localStorage.getItem(setting); - if (typeof r !== 'string') { + let r = vAPI.localStorage.getItem(setting); + if (typeof r !== 'string') { return undefined; - } - return JSON.parse(r); + } + return JSON.parse(r); } function setUISetting(setting, value) { - vAPI.localStorage.setItem(setting, JSON.stringify(value)); + vAPI.localStorage.setItem(setting, JSON.stringify(value)); } function updateMatrixSnapshot() { - matrixSnapshotPoller.pollNow(); + matrixSnapshotPoller.pollNow(); } // For display purpose, create four distinct groups of rows: @@ -186,162 +186,162 @@ function getGroupStats() { - // Try to not reshuffle groups around while popup is opened if - // no new hostname added. - let latestDomainListSnapshot = - Object.keys(matrixSnapshot.rows).sort().join(); - if (latestDomainListSnapshot === allHostnamesSnapshot) { + // Try to not reshuffle groups around while popup is opened if + // no new hostname added. + let latestDomainListSnapshot = + Object.keys(matrixSnapshot.rows).sort().join(); + if (latestDomainListSnapshot === allHostnamesSnapshot) { return groupsSnapshot; - } - allHostnamesSnapshot = latestDomainListSnapshot; - - // First, group according to whether at least one node in the domain - // hierarchy is white or blacklisted - let pageDomain = matrixSnapshot.domain; - let rows = matrixSnapshot.rows; - let anyTypeOffset = matrixSnapshot.headerIndices.get('*'); - let hostname, domain; - let row, color, count; - let domainToGroupMap = {}; - - // These have hard-coded position which cannot be overriden - domainToGroupMap['1st-party'] = 0; - domainToGroupMap[pageDomain] = 1; - - // 1st pass: domain wins if it has an explicit rule or a count - for (hostname in rows) { + } + allHostnamesSnapshot = latestDomainListSnapshot; + + // First, group according to whether at least one node in the domain + // hierarchy is white or blacklisted + let pageDomain = matrixSnapshot.domain; + let rows = matrixSnapshot.rows; + let anyTypeOffset = matrixSnapshot.headerIndices.get('*'); + let hostname, domain; + let row, color, count; + let domainToGroupMap = {}; + + // These have hard-coded position which cannot be overriden + domainToGroupMap['1st-party'] = 0; + domainToGroupMap[pageDomain] = 1; + + // 1st pass: domain wins if it has an explicit rule or a count + for (hostname in rows) { if (rows.hasOwnProperty(hostname) === false) { - continue; + continue; } if (hostname === '*' || hostname === '1st-party') { - continue; + continue; } domain = rows[hostname].domain; if (domain === pageDomain || hostname !== domain) { - continue; + continue; } row = rows[domain]; color = row.temporary[anyTypeOffset]; if (color === DarkGreen) { - domainToGroupMap[domain] = 2; - continue; + domainToGroupMap[domain] = 2; + continue; } if (color === DarkRed) { - domainToGroupMap[domain] = 4; - continue; + domainToGroupMap[domain] = 4; + continue; } count = row.counts[anyTypeOffset]; if (count !== 0) { - domainToGroupMap[domain] = 3; - continue; + domainToGroupMap[domain] = 3; + continue; } - } + } - // 2nd pass: green wins - for (hostname in rows) { + // 2nd pass: green wins + for (hostname in rows) { if (rows.hasOwnProperty(hostname) === false) { - continue; + continue; } row = rows[hostname]; domain = row.domain; if (domainToGroupMap.hasOwnProperty(domain)) { - continue; + continue; } color = row.temporary[anyTypeOffset]; if (color === DarkGreen) { - domainToGroupMap[domain] = 2; + domainToGroupMap[domain] = 2; } - } + } - // 3rd pass: gray with count wins - for (hostname in rows) { + // 3rd pass: gray with count wins + for (hostname in rows) { if (rows.hasOwnProperty(hostname) === false) { - continue; + continue; } row = rows[hostname]; domain = row.domain; if (domainToGroupMap.hasOwnProperty(domain)) { - continue; + continue; } color = row.temporary[anyTypeOffset]; count = row.counts[anyTypeOffset]; if ( color !== DarkRed && count !== 0 ) { - domainToGroupMap[domain] = 3; + domainToGroupMap[domain] = 3; } - } + } - // 4th pass: red wins whatever is left - for (hostname in rows) { + // 4th pass: red wins whatever is left + for (hostname in rows) { if (rows.hasOwnProperty(hostname) === false) { - continue; + continue; } row = rows[hostname]; domain = row.domain; if (domainToGroupMap.hasOwnProperty(domain)) { - continue; + continue; } color = row.temporary[anyTypeOffset]; if (color === DarkRed) { - domainToGroupMap[domain] = 4; + domainToGroupMap[domain] = 4; } - } + } - // 5th pass: gray wins whatever is left - for (hostname in rows) { + // 5th pass: gray wins whatever is left + for (hostname in rows) { if (rows.hasOwnProperty(hostname) === false) { - continue; + continue; } domain = rows[hostname].domain; if (domainToGroupMap.hasOwnProperty(domain)) { - continue; + continue; } domainToGroupMap[domain] = 3; - } + } - // Last pass: put each domain in a group - let groups = [ - {}, {}, {}, {}, {} - ]; + // Last pass: put each domain in a group + let groups = [ + {}, {}, {}, {}, {} + ]; - for (hostname in rows) { + for (hostname in rows) { if (rows.hasOwnProperty(hostname) === false) { - continue; + continue; } if ( hostname === '*' ) { - continue; + continue; } domain = rows[hostname].domain; let groupIndex = domainToGroupMap[domain]; let group = groups[groupIndex]; if (group.hasOwnProperty(domain) === false) { - group[domain] = {}; + group[domain] = {}; } group[domain][hostname] = true; - } + } - groupsSnapshot = groups; + groupsSnapshot = groups; - return groups; + return groups; } // helpers function getTemporaryColor(hostname, type) { - return matrixSnapshot - .rows[hostname] - .temporary[matrixSnapshot.headerIndices.get(type)]; + return matrixSnapshot + .rows[hostname] + .temporary[matrixSnapshot.headerIndices.get(type)]; } function getPermanentColor(hostname, type) { - return matrixSnapshot - .rows[hostname] - .permanent[matrixSnapshot.headerIndices.get(type)]; + return matrixSnapshot + .rows[hostname] + .permanent[matrixSnapshot.headerIndices.get(type)]; } function addCellClass(cell, hostname, type) { - let cl = cell.classList; - cl.add('matCell'); - cl.add('t' + getTemporaryColor(hostname, type).toString(16)); - cl.add('p' + getPermanentColor(hostname, type).toString(16)); + let cl = cell.classList; + cl.add('matCell'); + cl.add('t' + getTemporaryColor(hostname, type).toString(16)); + cl.add('p' + getPermanentColor(hostname, type).toString(16)); } // This is required for when we update the matrix while it is open: @@ -349,118 +349,118 @@ // want to lose all his hardwork. function getCollapseState(domain) { - let states = getUISetting('popupCollapseSpecificDomains'); - if (typeof states === 'object' && states[domain] !== undefined) { + let states = getUISetting('popupCollapseSpecificDomains'); + if (typeof states === 'object' && states[domain] !== undefined) { return states[domain]; - } - return matrixSnapshot.collapseAllDomains === true; + } + return matrixSnapshot.collapseAllDomains === true; } function toggleCollapseState(elem) { - if (elem.ancestors('#matHead.collapsible').length > 0) { + if (elem.ancestors('#matHead.collapsible').length > 0) { toggleMainCollapseState(elem); - } else { + } else { toggleSpecificCollapseState(elem); - } - popupWasResized(); + } + popupWasResized(); } function toggleMainCollapseState(uelem) { - let matHead = - uelem.ancestors('#matHead.collapsible').toggleClass('collapsed'); - let collapsed = - matrixSnapshot.collapseAllDomains = matHead.hasClass('collapsed'); - - uDom('#matList .matSection.collapsible') - .toggleClass('collapsed', collapsed); - setUserSetting('popupCollapseAllDomains', collapsed); - - let specificCollapseStates = - getUISetting('popupCollapseSpecificDomains') || {}; - let domains = Object.keys(specificCollapseStates); - for (let i=domains.length-1; i>=0; --i) { + let matHead = + uelem.ancestors('#matHead.collapsible').toggleClass('collapsed'); + let collapsed = + matrixSnapshot.collapseAllDomains = matHead.hasClass('collapsed'); + + uDom('#matList .matSection.collapsible') + .toggleClass('collapsed', collapsed); + setUserSetting('popupCollapseAllDomains', collapsed); + + let specificCollapseStates = + getUISetting('popupCollapseSpecificDomains') || {}; + let domains = Object.keys(specificCollapseStates); + for (let i=domains.length-1; i>=0; --i) { let domain = domains[i]; if (specificCollapseStates[domain] === collapsed) { - delete specificCollapseStates[domain]; + delete specificCollapseStates[domain]; } - } - setUISetting('popupCollapseSpecificDomains', specificCollapseStates); + } + setUISetting('popupCollapseSpecificDomains', specificCollapseStates); } function toggleSpecificCollapseState(uelem) { - // Remember collapse state forever, but only if it is different - // from main collapse switch. - let section = - uelem.ancestors('.matSection.collapsible').toggleClass('collapsed'); + // Remember collapse state forever, but only if it is different + // from main collapse switch. + let section = + uelem.ancestors('.matSection.collapsible').toggleClass('collapsed'); let domain = expandosFromNode(section).domain; let collapsed = section.hasClass('collapsed'); let mainCollapseState = matrixSnapshot.collapseAllDomains === true; let specificCollapseStates = - getUISetting('popupCollapseSpecificDomains') || {}; + getUISetting('popupCollapseSpecificDomains') || {}; - if (collapsed !== mainCollapseState) { + if (collapsed !== mainCollapseState) { specificCollapseStates[domain] = collapsed; setUISetting('popupCollapseSpecificDomains', - specificCollapseStates); - } else if (specificCollapseStates[domain] !== undefined) { + specificCollapseStates); + } else if (specificCollapseStates[domain] !== undefined) { delete specificCollapseStates[domain]; setUISetting('popupCollapseSpecificDomains', - specificCollapseStates); - } + specificCollapseStates); + } } // Update count value of matrix cells(s) function updateMatrixCounts() { - let matCells = uDom('.matrix .matRow.rw > .matCell'); + let matCells = uDom('.matrix .matRow.rw > .matCell'); let matRow, matCell, count, counts; let headerIndices = matrixSnapshot.headerIndices; let rows = matrixSnapshot.rows; let expandos; - for (let i=matCells.length-1; i>=0; --i) { + for (let i=matCells.length-1; i>=0; --i) { matCell = matCells.nodeAt(i); expandos = expandosFromNode(matCell); if (expandos.hostname === '*' || expandos.reqType === '*') { - continue; + continue; } matRow = matCell.parentNode; counts = matRow.classList.contains('meta') ? 'totals' : 'counts'; count = rows[expandos.hostname][counts][headerIndices - .get(expandos.reqType)]; + .get(expandos.reqType)]; if (count === expandos.count) { - continue; - } + continue; + } expandos.count = count; matCell.textContent = cellTextFromCount(count); - } + } } function cellTextFromCount(count) { - if (count === 0) { - return '\u00A0'; - } + if (count === 0) { + return '\u00A0'; + } - if (count < 100) { - return count; - } + if (count < 100) { + return count; + } - return '99+'; + return '99+'; } // Update color of matrix cells(s) // Color changes when rules change function updateMatrixColors() { - let cells = uDom('.matrix .matRow.rw > .matCell').removeClass(); + let cells = uDom('.matrix .matRow.rw > .matCell').removeClass(); let cell, expandos; - for (let i=cells.length-1; i>=0; --i) { + for (let i=cells.length-1; i>=0; --i) { cell = cells.nodeAt(i); expandos = expandosFromNode(cell); addCellClass(cell, expandos.hostname, expandos.reqType); - } + } - popupWasResized(); + popupWasResized(); } // Update behavior of matrix: @@ -470,78 +470,78 @@ // - It is not part of group 3 (blacklisted hostnames) function updateMatrixBehavior() { - matrixList = matrixList || uDom('#matList'); - let sections = matrixList.descendants('.matSection'); - let section, subdomainRows, subdomainRow; - for (let i=sections.length-1; i>=0; --i) { + matrixList = matrixList || uDom('#matList'); + let sections = matrixList.descendants('.matSection'); + let section, subdomainRows, subdomainRow; + for (let i=sections.length-1; i>=0; --i) { section = sections.at(i); subdomainRows = section.descendants('.l2:not(.g4)'); for (let j=subdomainRows.length-1; j>=0; --j) { - subdomainRow = subdomainRows.at(j); - subdomainRow.toggleClass('collapsible', - subdomainRow - .descendants('.t81,.t82') - .length === 0); + subdomainRow = subdomainRows.at(j); + subdomainRow.toggleClass('collapsible', + subdomainRow + .descendants('.t81,.t82') + .length === 0); } section.toggleClass('collapsible', - subdomainRows.filter('.collapsible').length > 0); - } + subdomainRows.filter('.collapsible').length > 0); + } } // handle user interaction with filters function getCellAction(hostname, type, leaning) { - let temporaryColor = getTemporaryColor(hostname, type); - let hue = temporaryColor & 0x03; + let temporaryColor = getTemporaryColor(hostname, type); + let hue = temporaryColor & 0x03; - // Special case: root toggle only between two states - if (type === '*' && hostname === '*') { + // Special case: root toggle only between two states + if (type === '*' && hostname === '*') { return hue === Green ? - 'blacklistMatrixCell' : - 'whitelistMatrixCell'; - } + 'blacklistMatrixCell' : + 'whitelistMatrixCell'; + } - // When explicitly blocked/allowed, can only graylist - let saturation = temporaryColor & 0x80; - if (saturation === Dark) { + // When explicitly blocked/allowed, can only graylist + let saturation = temporaryColor & 0x80; + if (saturation === Dark) { return 'graylistMatrixCell'; - } + } - return leaning === 'whitelisting' ? - 'whitelistMatrixCell' : - 'blacklistMatrixCell'; + return leaning === 'whitelisting' ? + 'whitelistMatrixCell' : + 'blacklistMatrixCell'; } function handleFilter(button, leaning) { - // our parent cell knows who we are - let cell = button.ancestors('div.matCell'); + // our parent cell knows who we are + let cell = button.ancestors('div.matCell'); let expandos = expandosFromNode(cell); let type = expandos.reqType; let desHostname = expandos.hostname; - // https://github.com/gorhill/uMatrix/issues/24 - // No hostname can happen -- like with blacklist meta row - if (desHostname === '') { + // https://github.com/gorhill/uMatrix/issues/24 + // No hostname can happen -- like with blacklist meta row + if (desHostname === '') { return; - } + } - let request = { + let request = { what: getCellAction(desHostname, type, leaning), srcHostname: matrixSnapshot.scope, desHostname: desHostname, type: type - }; + }; - vAPI.messaging.send('popup.js', request, updateMatrixSnapshot); + vAPI.messaging.send('popup.js', request, updateMatrixSnapshot); } function handleWhitelistFilter(button) { - handleFilter(button, 'whitelisting'); + handleFilter(button, 'whitelisting'); } function handleBlacklistFilter(button) { - handleFilter(button, 'blacklisting'); + handleFilter(button, 'blacklisting'); } let matrixRowPool = []; @@ -551,299 +551,299 @@ let matrixList = null; let startMatrixUpdate = function () { - matrixList = matrixList || uDom('#matList'); - matrixList.detach(); - let rows = matrixList.descendants('.matRow'); - rows.detach(); - matrixRowPool = matrixRowPool.concat(rows.toArray()); - let sections = matrixList.descendants('.matSection'); - sections.detach(); - matrixSectionPool = matrixSectionPool.concat(sections.toArray()); - let groups = matrixList.descendants('.matGroup'); - groups.detach(); - matrixGroupPool = matrixGroupPool.concat(groups.toArray()); + matrixList = matrixList || uDom('#matList'); + matrixList.detach(); + let rows = matrixList.descendants('.matRow'); + rows.detach(); + matrixRowPool = matrixRowPool.concat(rows.toArray()); + let sections = matrixList.descendants('.matSection'); + sections.detach(); + matrixSectionPool = matrixSectionPool.concat(sections.toArray()); + let groups = matrixList.descendants('.matGroup'); + groups.detach(); + matrixGroupPool = matrixGroupPool.concat(groups.toArray()); }; let endMatrixUpdate = function () { - // https://github.com/gorhill/httpswitchboard/issues/246 If - // the matrix has no rows, we need to insert a dummy one, - // invisible, to ensure the extension pop-up is properly - // sized. This is needed because the header pane's `position` - // property is `fixed`, which means it doesn't affect layout - // size, hence the matrix header row will be truncated. - if (matrixSnapshot.rowCount <= 1) { + // https://github.com/gorhill/httpswitchboard/issues/246 If + // the matrix has no rows, we need to insert a dummy one, + // invisible, to ensure the extension pop-up is properly + // sized. This is needed because the header pane's `position` + // property is `fixed`, which means it doesn't affect layout + // size, hence the matrix header row will be truncated. + if (matrixSnapshot.rowCount <= 1) { matrixList.append(createMatrixRow().css('visibility', 'hidden')); - } + } - updateMatrixBehavior(); - matrixList.css('display', ''); - matrixList.appendTo('.paneContent'); + updateMatrixBehavior(); + matrixList.css('display', ''); + matrixList.appendTo('.paneContent'); }; let createMatrixGroup = function () { - let group = matrixGroupPool.pop(); - if (group) { + let group = matrixGroupPool.pop(); + if (group) { return uDom(group).removeClass().addClass('matGroup'); - } - return uDom(document.createElement('div')).addClass('matGroup'); + } + return uDom(document.createElement('div')).addClass('matGroup'); }; let createMatrixSection = function () { - let section = matrixSectionPool.pop(); - if (section) { + let section = matrixSectionPool.pop(); + if (section) { return uDom(section).removeClass().addClass('matSection'); - } - return uDom(document.createElement('div')).addClass('matSection'); + } + return uDom(document.createElement('div')).addClass('matSection'); }; let createMatrixRow = function () { - let row = matrixRowPool.pop(); - if (row) { + let row = matrixRowPool.pop(); + if (row) { row.style.visibility = ''; row = uDom(row); row.descendants('.matCell').removeClass().addClass('matCell'); row.removeClass().addClass('matRow'); return row; - } + } - if (matrixRowTemplate === null) { + if (matrixRowTemplate === null) { matrixRowTemplate = uDom('#templates .matRow'); - } + } - return matrixRowTemplate.clone(); + return matrixRowTemplate.clone(); }; function renderMatrixHeaderRow() { - let matHead = uDom('#matHead.collapsible'); - matHead.toggleClass('collapsed', - matrixSnapshot.collapseAllDomains === true); - - let cells = matHead.descendants('.matCell') - let cell = cells.nodeAt(0); - let expandos = expandosFromNode(cell); - expandos.reqType = '*'; - expandos.hostname = '*'; - addCellClass(cell, '*', '*'); - - cell = cells.nodeAt(1); - expandos = expandosFromNode(cell); - expandos.reqType = 'cookie'; - expandos.hostname = '*'; - addCellClass(cell, '*', 'cookie'); - - cell = cells.nodeAt(2); - expandos = expandosFromNode(cell); - expandos.reqType = 'css'; - expandos.hostname = '*'; - addCellClass(cell, '*', 'css'); - - cell = cells.nodeAt(3); - expandos = expandosFromNode(cell); - expandos.reqType = 'image'; - expandos.hostname = '*'; - addCellClass(cell, '*', 'image'); - - cell = cells.nodeAt(4); - expandos = expandosFromNode(cell); - expandos.reqType = 'media'; - expandos.hostname = '*'; - addCellClass(cell, '*', 'media'); - - cell = cells.nodeAt(5); - expandos = expandosFromNode(cell); - expandos.reqType = 'script'; - expandos.hostname = '*'; - addCellClass(cell, '*', 'script'); - - cell = cells.nodeAt(6); - expandos = expandosFromNode(cell); - expandos.reqType = 'xhr'; - expandos.hostname = '*'; - addCellClass(cell, '*', 'xhr'); - - cell = cells.nodeAt(7); - expandos = expandosFromNode(cell); - expandos.reqType = 'frame'; - expandos.hostname = '*'; - addCellClass(cell, '*', 'frame'); - - cell = cells.nodeAt(8); - expandos = expandosFromNode(cell); - expandos.reqType = 'other'; - expandos.hostname = '*'; - addCellClass(cell, '*', 'other'); - - uDom('#matHead .matRow').css('display', ''); + let matHead = uDom('#matHead.collapsible'); + matHead.toggleClass('collapsed', + matrixSnapshot.collapseAllDomains === true); + + let cells = matHead.descendants('.matCell') + let cell = cells.nodeAt(0); + let expandos = expandosFromNode(cell); + expandos.reqType = '*'; + expandos.hostname = '*'; + addCellClass(cell, '*', '*'); + + cell = cells.nodeAt(1); + expandos = expandosFromNode(cell); + expandos.reqType = 'cookie'; + expandos.hostname = '*'; + addCellClass(cell, '*', 'cookie'); + + cell = cells.nodeAt(2); + expandos = expandosFromNode(cell); + expandos.reqType = 'css'; + expandos.hostname = '*'; + addCellClass(cell, '*', 'css'); + + cell = cells.nodeAt(3); + expandos = expandosFromNode(cell); + expandos.reqType = 'image'; + expandos.hostname = '*'; + addCellClass(cell, '*', 'image'); + + cell = cells.nodeAt(4); + expandos = expandosFromNode(cell); + expandos.reqType = 'media'; + expandos.hostname = '*'; + addCellClass(cell, '*', 'media'); + + cell = cells.nodeAt(5); + expandos = expandosFromNode(cell); + expandos.reqType = 'script'; + expandos.hostname = '*'; + addCellClass(cell, '*', 'script'); + + cell = cells.nodeAt(6); + expandos = expandosFromNode(cell); + expandos.reqType = 'xhr'; + expandos.hostname = '*'; + addCellClass(cell, '*', 'xhr'); + + cell = cells.nodeAt(7); + expandos = expandosFromNode(cell); + expandos.reqType = 'frame'; + expandos.hostname = '*'; + addCellClass(cell, '*', 'frame'); + + cell = cells.nodeAt(8); + expandos = expandosFromNode(cell); + expandos.reqType = 'other'; + expandos.hostname = '*'; + addCellClass(cell, '*', 'other'); + + uDom('#matHead .matRow').css('display', ''); } function renderMatrixCellDomain(cell, domain) { - let expandos = expandosFromNode(cell); - expandos.hostname = domain; - expandos.reqType = '*'; - addCellClass(cell.nodeAt(0), domain, '*'); + let expandos = expandosFromNode(cell); + expandos.hostname = domain; + expandos.reqType = '*'; + addCellClass(cell.nodeAt(0), domain, '*'); - let contents = cell.contents(); - contents.nodeAt(0).textContent = domain === '1st-party' ? + let contents = cell.contents(); + contents.nodeAt(0).textContent = domain === '1st-party' ? firstPartyLabel : Punycode.toUnicode(domain); - contents.nodeAt(1).textContent = ' '; + contents.nodeAt(1).textContent = ' '; } function renderMatrixCellSubdomain(cell, domain, subomain) { - let expandos = expandosFromNode(cell); - expandos.hostname = subomain; - expandos.reqType = '*'; - addCellClass(cell.nodeAt(0), subomain, '*'); + let expandos = expandosFromNode(cell); + expandos.hostname = subomain; + expandos.reqType = '*'; + addCellClass(cell.nodeAt(0), subomain, '*'); - let contents = cell.contents(); - contents.nodeAt(0).textContent = - Punycode.toUnicode(subomain.slice(0, - subomain.lastIndexOf(domain)-1)) - + '.'; - contents.nodeAt(1).textContent = Punycode.toUnicode(domain); + let contents = cell.contents(); + contents.nodeAt(0).textContent = + Punycode.toUnicode(subomain.slice(0, + subomain.lastIndexOf(domain)-1)) + + '.'; + contents.nodeAt(1).textContent = Punycode.toUnicode(domain); } function renderMatrixMetaCellDomain(cell, domain) { - let expandos = expandosFromNode(cell); - expandos.hostname = domain; - expandos.reqType = '*'; - addCellClass(cell.nodeAt(0), domain, '*'); + let expandos = expandosFromNode(cell); + expandos.hostname = domain; + expandos.reqType = '*'; + addCellClass(cell.nodeAt(0), domain, '*'); - let contents = cell.contents(); - contents.nodeAt(0).textContent = '\u2217.' + Punycode.toUnicode(domain); - contents.nodeAt(1).textContent = ' '; + let contents = cell.contents(); + contents.nodeAt(0).textContent = '\u2217.' + Punycode.toUnicode(domain); + contents.nodeAt(1).textContent = ' '; } function renderMatrixCellType(cell, hostname, type, count) { - let node = cell.nodeAt(0); + let node = cell.nodeAt(0); let expandos = expandosFromNode(node); - expandos.hostname = hostname; - expandos.reqType = type; - expandos.count = count; - addCellClass(node, hostname, type); - node.textContent = cellTextFromCount(count); + expandos.hostname = hostname; + expandos.reqType = type; + expandos.count = count; + addCellClass(node, hostname, type); + node.textContent = cellTextFromCount(count); } function renderMatrixCellTypes(cells, hostname, countName) { - let counts = matrixSnapshot.rows[hostname][countName]; - let headerIndices = matrixSnapshot.headerIndices; - renderMatrixCellType(cells.at(1), hostname, 'cookie', - counts[headerIndices.get('cookie')]); - renderMatrixCellType(cells.at(2), hostname, 'css', - counts[headerIndices.get('css')]); - renderMatrixCellType(cells.at(3), hostname, 'image', - counts[headerIndices.get('image')]); - renderMatrixCellType(cells.at(4), hostname, 'media', - counts[headerIndices.get('media')]); - renderMatrixCellType(cells.at(5), hostname, 'script', - counts[headerIndices.get('script')]); - renderMatrixCellType(cells.at(6), hostname, 'xhr', - counts[headerIndices.get('xhr')]); - renderMatrixCellType(cells.at(7), hostname, 'frame', - counts[headerIndices.get('frame')]); - renderMatrixCellType(cells.at(8), hostname, 'other', - counts[headerIndices.get('other')]); + let counts = matrixSnapshot.rows[hostname][countName]; + let headerIndices = matrixSnapshot.headerIndices; + renderMatrixCellType(cells.at(1), hostname, 'cookie', + counts[headerIndices.get('cookie')]); + renderMatrixCellType(cells.at(2), hostname, 'css', + counts[headerIndices.get('css')]); + renderMatrixCellType(cells.at(3), hostname, 'image', + counts[headerIndices.get('image')]); + renderMatrixCellType(cells.at(4), hostname, 'media', + counts[headerIndices.get('media')]); + renderMatrixCellType(cells.at(5), hostname, 'script', + counts[headerIndices.get('script')]); + renderMatrixCellType(cells.at(6), hostname, 'xhr', + counts[headerIndices.get('xhr')]); + renderMatrixCellType(cells.at(7), hostname, 'frame', + counts[headerIndices.get('frame')]); + renderMatrixCellType(cells.at(8), hostname, 'other', + counts[headerIndices.get('other')]); } function makeMatrixRowDomain(domain) { - let matrixRow = createMatrixRow().addClass('rw'); - let cells = matrixRow.descendants('.matCell'); - renderMatrixCellDomain(cells.at(0), domain); - renderMatrixCellTypes(cells, domain, 'counts'); - return matrixRow; + let matrixRow = createMatrixRow().addClass('rw'); + let cells = matrixRow.descendants('.matCell'); + renderMatrixCellDomain(cells.at(0), domain); + renderMatrixCellTypes(cells, domain, 'counts'); + return matrixRow; } function makeMatrixRowSubdomain(domain, subdomain) { - let matrixRow = createMatrixRow().addClass('rw'); - let cells = matrixRow.descendants('.matCell'); - renderMatrixCellSubdomain(cells.at(0), domain, subdomain); - renderMatrixCellTypes(cells, subdomain, 'counts'); - return matrixRow; + let matrixRow = createMatrixRow().addClass('rw'); + let cells = matrixRow.descendants('.matCell'); + renderMatrixCellSubdomain(cells.at(0), domain, subdomain); + renderMatrixCellTypes(cells, subdomain, 'counts'); + return matrixRow; } function makeMatrixMetaRowDomain(domain) { - let matrixRow = createMatrixRow().addClass('rw'); - let cells = matrixRow.descendants('.matCell'); - renderMatrixMetaCellDomain(cells.at(0), domain); - renderMatrixCellTypes(cells, domain, 'totals'); - return matrixRow; + let matrixRow = createMatrixRow().addClass('rw'); + let cells = matrixRow.descendants('.matCell'); + renderMatrixMetaCellDomain(cells.at(0), domain); + renderMatrixCellTypes(cells, domain, 'totals'); + return matrixRow; } function renderMatrixMetaCellType(cell, count) { - // https://github.com/gorhill/uMatrix/issues/24 - // Don't forget to reset cell properties - let node = cell.nodeAt(0); + // https://github.com/gorhill/uMatrix/issues/24 + // Don't forget to reset cell properties + let node = cell.nodeAt(0); let expandos = expandosFromNode(node); - expandos.hostname = ''; - expandos.reqType = ''; - expandos.count = count; - cell.addClass('t1'); - node.textContent = cellTextFromCount(count); + expandos.hostname = ''; + expandos.reqType = ''; + expandos.count = count; + cell.addClass('t1'); + node.textContent = cellTextFromCount(count); } function makeMatrixMetaRow(totals) { - let headerIndices = matrixSnapshot.headerIndices; + let headerIndices = matrixSnapshot.headerIndices; let matrixRow = createMatrixRow().at(0).addClass('ro'); let cells = matrixRow.descendants('.matCell'); let contents = cells.at(0).addClass('t81').contents(); let expandos = expandosFromNode(cells.nodeAt(0)); - expandos.hostname = ''; - expandos.reqType = '*'; - contents.nodeAt(0).textContent = ' '; - contents.nodeAt(1).textContent = - blacklistedHostnamesLabel - .replace('{{count}}', - totals[headerIndices.get('*')].toLocaleString()); - - renderMatrixMetaCellType(cells.at(1), - totals[headerIndices.get('cookie')]); - renderMatrixMetaCellType(cells.at(2), - totals[headerIndices.get('css')]); - renderMatrixMetaCellType(cells.at(3), - totals[headerIndices.get('image')]); - renderMatrixMetaCellType(cells.at(4), - totals[headerIndices.get('media')]); - renderMatrixMetaCellType(cells.at(5), - totals[headerIndices.get('script')]); - renderMatrixMetaCellType(cells.at(6), - totals[headerIndices.get('xhr')]); - renderMatrixMetaCellType(cells.at(7), - totals[headerIndices.get('frame')]); - renderMatrixMetaCellType(cells.at(8), - totals[headerIndices.get('other')]); - return matrixRow; + expandos.hostname = ''; + expandos.reqType = '*'; + contents.nodeAt(0).textContent = ' '; + contents.nodeAt(1).textContent = + blacklistedHostnamesLabel + .replace('{{count}}', + totals[headerIndices.get('*')].toLocaleString()); + + renderMatrixMetaCellType(cells.at(1), + totals[headerIndices.get('cookie')]); + renderMatrixMetaCellType(cells.at(2), + totals[headerIndices.get('css')]); + renderMatrixMetaCellType(cells.at(3), + totals[headerIndices.get('image')]); + renderMatrixMetaCellType(cells.at(4), + totals[headerIndices.get('media')]); + renderMatrixMetaCellType(cells.at(5), + totals[headerIndices.get('script')]); + renderMatrixMetaCellType(cells.at(6), + totals[headerIndices.get('xhr')]); + renderMatrixMetaCellType(cells.at(7), + totals[headerIndices.get('frame')]); + renderMatrixMetaCellType(cells.at(8), + totals[headerIndices.get('other')]); + return matrixRow; } function computeMatrixGroupMetaStats(group) { - let headerIndices = matrixSnapshot.headerIndices; + let headerIndices = matrixSnapshot.headerIndices; let anyTypeIndex = headerIndices.get('*'); let totals = new Array(headerIndices.size); for (let i=headerIndices.size-1; i>=0; --i) { totals[i] = 0; - } + } - let rows = matrixSnapshot.rows; - let row; - for (let hostname in rows) { + let rows = matrixSnapshot.rows; + let row; + for (let hostname in rows) { if (rows.hasOwnProperty(hostname) === false) { - continue; + continue; } row = rows[hostname]; if (group.hasOwnProperty(row.domain) === false) { - continue; + continue; } if (row.counts[anyTypeIndex] === 0) { - continue; + continue; } totals[0] += 1; for (let i=1; i<headerIndices.size; ++i) { - totals[i] += row.counts[i]; + totals[i] += row.counts[i]; } - } + } - return totals; + return totals; } // Compare hostname helper, to order hostname in a logical manner: @@ -851,667 +851,667 @@ // named hostname function hostnameCompare(a, b) { - // Normalize: most significant parts first - if (!a.match(/^\d+(\.\d+){1,3}$/)) { + // Normalize: most significant parts first + if (!a.match(/^\d+(\.\d+){1,3}$/)) { let aa = a.split('.'); a = aa.slice(-2).concat(aa.slice(0,-2).reverse()).join('.'); - } + } - if (!b.match(/^\d+(\.\d+){1,3}$/)) { + if (!b.match(/^\d+(\.\d+){1,3}$/)) { let bb = b.split('.'); b = bb.slice(-2).concat(bb.slice(0,-2).reverse()).join('.'); - } + } - return a.localeCompare(b); + return a.localeCompare(b); } function makeMatrixGroup0SectionDomain() { - return makeMatrixRowDomain('1st-party').addClass('g0 l1'); + return makeMatrixRowDomain('1st-party').addClass('g0 l1'); } function makeMatrixGroup0Section() { - let domainDiv = createMatrixSection(); - expandosFromNode(domainDiv).domain = '1st-party'; - makeMatrixGroup0SectionDomain().appendTo(domainDiv); - return domainDiv; + let domainDiv = createMatrixSection(); + expandosFromNode(domainDiv).domain = '1st-party'; + makeMatrixGroup0SectionDomain().appendTo(domainDiv); + return domainDiv; } function makeMatrixGroup0() { - // Show literal "1st-party" row only if there is - // at least one 1st-party hostname - if (Object.keys(groupsSnapshot[1]).length === 0) { + // Show literal "1st-party" row only if there is + // at least one 1st-party hostname + if (Object.keys(groupsSnapshot[1]).length === 0) { return; - } - let groupDiv = createMatrixGroup().addClass('g0'); - makeMatrixGroup0Section().appendTo(groupDiv); - groupDiv.appendTo(matrixList); + } + let groupDiv = createMatrixGroup().addClass('g0'); + makeMatrixGroup0Section().appendTo(groupDiv); + groupDiv.appendTo(matrixList); } function makeMatrixGroup1SectionDomain(domain) { - return makeMatrixRowDomain(domain).addClass('g1 l1'); + return makeMatrixRowDomain(domain).addClass('g1 l1'); } function makeMatrixGroup1SectionSubomain(domain, subdomain) { - return makeMatrixRowSubdomain(domain, subdomain).addClass('g1 l2'); + return makeMatrixRowSubdomain(domain, subdomain).addClass('g1 l2'); } function makeMatrixGroup1SectionMetaDomain(domain) { - return makeMatrixMetaRowDomain(domain).addClass('g1 l1 meta'); + return makeMatrixMetaRowDomain(domain).addClass('g1 l1 meta'); } function makeMatrixGroup1Section(hostnames) { - let domain = hostnames[0]; - let domainDiv = - createMatrixSection().toggleClass('collapsed', - getCollapseState(domain)); - expandosFromNode(domainDiv).domain = domain; - if (hostnames.length > 1) { + let domain = hostnames[0]; + let domainDiv = + createMatrixSection().toggleClass('collapsed', + getCollapseState(domain)); + expandosFromNode(domainDiv).domain = domain; + if (hostnames.length > 1) { makeMatrixGroup1SectionMetaDomain(domain).appendTo(domainDiv); - } - makeMatrixGroup1SectionDomain(domain).appendTo(domainDiv); - for (let i=1; i<hostnames.length; ++i) { + } + makeMatrixGroup1SectionDomain(domain).appendTo(domainDiv); + for (let i=1; i<hostnames.length; ++i) { makeMatrixGroup1SectionSubomain(domain, hostnames[i]) - .appendTo(domainDiv); - } - return domainDiv; + .appendTo(domainDiv); + } + return domainDiv; } function makeMatrixGroup1(group) { - let domains = Object.keys(group).sort(hostnameCompare); - if (domains.length) { + let domains = Object.keys(group).sort(hostnameCompare); + if (domains.length) { let groupDiv = createMatrixGroup().addClass('g1'); makeMatrixGroup1Section(Object.keys(group[domains[0]]) - .sort(hostnameCompare)) - .appendTo(groupDiv); + .sort(hostnameCompare)) + .appendTo(groupDiv); for (let i=1; i<domains.length; ++i) { - makeMatrixGroup1Section(Object.keys(group[domains[i]]) - .sort(hostnameCompare)) + makeMatrixGroup1Section(Object.keys(group[domains[i]]) + .sort(hostnameCompare)) .appendTo(groupDiv); } groupDiv.appendTo(matrixList); - } + } } function makeMatrixGroup2SectionDomain(domain) { - return makeMatrixRowDomain(domain).addClass('g2 l1'); + return makeMatrixRowDomain(domain).addClass('g2 l1'); } function makeMatrixGroup2SectionSubomain(domain, subdomain) { - return makeMatrixRowSubdomain(domain, subdomain).addClass('g2 l2'); + return makeMatrixRowSubdomain(domain, subdomain).addClass('g2 l2'); } function makeMatrixGroup2SectionMetaDomain(domain) { - return makeMatrixMetaRowDomain(domain).addClass('g2 l1 meta'); + return makeMatrixMetaRowDomain(domain).addClass('g2 l1 meta'); } function makeMatrixGroup2Section(hostnames) { - let domain = hostnames[0]; - let domainDiv = - createMatrixSection().toggleClass('collapsed', - getCollapseState(domain)); - expandosFromNode(domainDiv).domain = domain; - if (hostnames.length > 1) { + let domain = hostnames[0]; + let domainDiv = + createMatrixSection().toggleClass('collapsed', + getCollapseState(domain)); + expandosFromNode(domainDiv).domain = domain; + if (hostnames.length > 1) { makeMatrixGroup2SectionMetaDomain(domain).appendTo(domainDiv); - } - makeMatrixGroup2SectionDomain(domain).appendTo(domainDiv); - for (let i=1; i<hostnames.length; ++i) { + } + makeMatrixGroup2SectionDomain(domain).appendTo(domainDiv); + for (let i=1; i<hostnames.length; ++i) { makeMatrixGroup2SectionSubomain(domain, hostnames[i]) - .appendTo(domainDiv); - } - return domainDiv; + .appendTo(domainDiv); + } + return domainDiv; } function makeMatrixGroup2(group) { - let domains = Object.keys(group).sort(hostnameCompare); - if (domains.length) { + let domains = Object.keys(group).sort(hostnameCompare); + if (domains.length) { let groupDiv = createMatrixGroup().addClass('g2'); makeMatrixGroup2Section(Object.keys(group[domains[0]]) - .sort(hostnameCompare)) - .appendTo(groupDiv); + .sort(hostnameCompare)) + .appendTo(groupDiv); for (let i=1; i<domains.length; ++i) { - makeMatrixGroup2Section(Object.keys(group[domains[i]]) - .sort(hostnameCompare)) + makeMatrixGroup2Section(Object.keys(group[domains[i]]) + .sort(hostnameCompare)) .appendTo(groupDiv); } groupDiv.appendTo(matrixList); - } + } } function makeMatrixGroup3SectionDomain(domain) { - return makeMatrixRowDomain(domain).addClass('g3 l1'); + return makeMatrixRowDomain(domain).addClass('g3 l1'); } function makeMatrixGroup3SectionSubomain(domain, subdomain) { - return makeMatrixRowSubdomain(domain, subdomain).addClass('g3 l2'); + return makeMatrixRowSubdomain(domain, subdomain).addClass('g3 l2'); } function makeMatrixGroup3SectionMetaDomain(domain) { - return makeMatrixMetaRowDomain(domain).addClass('g3 l1 meta'); + return makeMatrixMetaRowDomain(domain).addClass('g3 l1 meta'); } function makeMatrixGroup3Section(hostnames) { - let domain = hostnames[0]; - let domainDiv = createMatrixSection().toggleClass('collapsed', - getCollapseState(domain)); - expandosFromNode(domainDiv).domain = domain; - if (hostnames.length > 1) { + let domain = hostnames[0]; + let domainDiv = createMatrixSection().toggleClass('collapsed', + getCollapseState(domain)); + expandosFromNode(domainDiv).domain = domain; + if (hostnames.length > 1) { makeMatrixGroup3SectionMetaDomain(domain).appendTo(domainDiv); - } - makeMatrixGroup3SectionDomain(domain).appendTo(domainDiv); - for (let i=1; i<hostnames.length; ++i) { + } + makeMatrixGroup3SectionDomain(domain).appendTo(domainDiv); + for (let i=1; i<hostnames.length; ++i) { makeMatrixGroup3SectionSubomain(domain, hostnames[i]) - .appendTo(domainDiv); - } - return domainDiv; + .appendTo(domainDiv); + } + return domainDiv; } function makeMatrixGroup3(group) { - let domains = Object.keys(group).sort(hostnameCompare); - if (domains.length) { + let domains = Object.keys(group).sort(hostnameCompare); + if (domains.length) { let groupDiv = createMatrixGroup().addClass('g3'); makeMatrixGroup3Section(Object.keys(group[domains[0]]) - .sort(hostnameCompare)) - .appendTo(groupDiv); + .sort(hostnameCompare)) + .appendTo(groupDiv); for (let i=1; i<domains.length; ++i) { - makeMatrixGroup3Section(Object.keys(group[domains[i]]) - .sort(hostnameCompare)) + makeMatrixGroup3Section(Object.keys(group[domains[i]]) + .sort(hostnameCompare)) .appendTo(groupDiv); } groupDiv.appendTo(matrixList); - } + } } function makeMatrixGroup4SectionDomain(domain) { - return makeMatrixRowDomain(domain).addClass('g4 l1'); + return makeMatrixRowDomain(domain).addClass('g4 l1'); } function makeMatrixGroup4SectionSubomain(domain, subdomain) { - return makeMatrixRowSubdomain(domain, subdomain).addClass('g4 l2'); + return makeMatrixRowSubdomain(domain, subdomain).addClass('g4 l2'); } function makeMatrixGroup4Section(hostnames) { - let domain = hostnames[0]; - let domainDiv = createMatrixSection(); - expandosFromNode(domainDiv).domain = domain; - makeMatrixGroup4SectionDomain(domain).appendTo(domainDiv); - for (let i=1; i<hostnames.length; ++i) { + let domain = hostnames[0]; + let domainDiv = createMatrixSection(); + expandosFromNode(domainDiv).domain = domain; + makeMatrixGroup4SectionDomain(domain).appendTo(domainDiv); + for (let i=1; i<hostnames.length; ++i) { makeMatrixGroup4SectionSubomain(domain, hostnames[i]) - .appendTo(domainDiv); - } - return domainDiv; + .appendTo(domainDiv); + } + return domainDiv; } function makeMatrixGroup4(group) { - let domains = Object.keys(group).sort(hostnameCompare); - if (domains.length === 0) { + let domains = Object.keys(group).sort(hostnameCompare); + if (domains.length === 0) { return; - } - let groupDiv = createMatrixGroup().addClass('g4'); - createMatrixSection() + } + let groupDiv = createMatrixGroup().addClass('g4'); + createMatrixSection() .addClass('g4Meta') .toggleClass('g4Collapsed', - !!matrixSnapshot.collapseBlacklistedDomains) + !!matrixSnapshot.collapseBlacklistedDomains) .appendTo(groupDiv); - makeMatrixMetaRow(computeMatrixGroupMetaStats(group), 'g4') + makeMatrixMetaRow(computeMatrixGroupMetaStats(group), 'g4') .appendTo(groupDiv); - makeMatrixGroup4Section(Object.keys(group[domains[0]]) - .sort(hostnameCompare)) + makeMatrixGroup4Section(Object.keys(group[domains[0]]) + .sort(hostnameCompare)) .appendTo(groupDiv); - for (let i=1; i<domains.length; ++i) { + for (let i=1; i<domains.length; ++i) { makeMatrixGroup4Section(Object.keys(group[domains[i]]) - .sort(hostnameCompare)) - .appendTo(groupDiv); - } - groupDiv.appendTo(matrixList); + .sort(hostnameCompare)) + .appendTo(groupDiv); + } + groupDiv.appendTo(matrixList); } let makeMenu = function () { - let groupStats = getGroupStats(); + let groupStats = getGroupStats(); - if (Object.keys(groupStats).length === 0) { - return; - } + if (Object.keys(groupStats).length === 0) { + return; + } - // https://github.com/gorhill/httpswitchboard/issues/31 - if (matrixCellHotspots) { + // https://github.com/gorhill/httpswitchboard/issues/31 + if (matrixCellHotspots) { matrixCellHotspots.detach(); - } + } - renderMatrixHeaderRow(); + renderMatrixHeaderRow(); - startMatrixUpdate(); - makeMatrixGroup0(groupStats[0]); - makeMatrixGroup1(groupStats[1]); - makeMatrixGroup2(groupStats[2]); - makeMatrixGroup3(groupStats[3]); - makeMatrixGroup4(groupStats[4]); - endMatrixUpdate(); + startMatrixUpdate(); + makeMatrixGroup0(groupStats[0]); + makeMatrixGroup1(groupStats[1]); + makeMatrixGroup2(groupStats[2]); + makeMatrixGroup3(groupStats[3]); + makeMatrixGroup4(groupStats[4]); + endMatrixUpdate(); - initScopeCell(); - updateMatrixButtons(); - resizePopup(); + initScopeCell(); + updateMatrixButtons(); + resizePopup(); }; // Do all the stuff that needs to be done before building menu et al. function initMenuEnvironment() { - document.body.style.setProperty('font-size', - getUserSetting('displayTextSize')); - document.body.classList.toggle('colorblind', - getUserSetting('colorBlindFriendly')); - uDom.nodeFromId('version').textContent = - matrixSnapshot.appVersion || ''; - - let prettyNames = matrixHeaderPrettyNames; - let keys = Object.keys(prettyNames); - for (let i=keys.length-1; i>=0; --i) { + document.body.style.setProperty('font-size', + getUserSetting('displayTextSize')); + document.body.classList.toggle('colorblind', + getUserSetting('colorBlindFriendly')); + uDom.nodeFromId('version').textContent = + matrixSnapshot.appVersion || ''; + + let prettyNames = matrixHeaderPrettyNames; + let keys = Object.keys(prettyNames); + for (let i=keys.length-1; i>=0; --i) { let key = keys[i]; let cell = uDom('#matHead .matCell[data-req-type="'+ key +'"]'); let text = vAPI.i18n(key + 'PrettyName'); cell.text(text); prettyNames[key] = text; - } + } - firstPartyLabel = uDom('[data-i18n="matrix1stPartyLabel"]').text(); - blacklistedHostnamesLabel = - uDom('[data-i18n="matrixBlacklistedHostnames"]').text(); + firstPartyLabel = uDom('[data-i18n="matrix1stPartyLabel"]').text(); + blacklistedHostnamesLabel = + uDom('[data-i18n="matrixBlacklistedHostnames"]').text(); } // Create page scopes for the web page function selectGlobalScope() { - if (matrixSnapshot.scope === '*') { - return; - } - matrixSnapshot.scope = '*'; - document.body.classList.add('globalScope'); - matrixSnapshot.tMatrixModifiedTime = undefined; - updateMatrixSnapshot(); - dropDownMenuHide(); + if (matrixSnapshot.scope === '*') { + return; + } + matrixSnapshot.scope = '*'; + document.body.classList.add('globalScope'); + matrixSnapshot.tMatrixModifiedTime = undefined; + updateMatrixSnapshot(); + dropDownMenuHide(); } function selectSpecificScope(ev) { - let newScope = ev.target.getAttribute('data-scope'); - if (!newScope || matrixSnapshot.scope === newScope) { - return; - } - document.body.classList.remove('globalScope'); - matrixSnapshot.scope = newScope; - matrixSnapshot.tMatrixModifiedTime = undefined; - updateMatrixSnapshot(); - dropDownMenuHide(); + let newScope = ev.target.getAttribute('data-scope'); + if (!newScope || matrixSnapshot.scope === newScope) { + return; + } + document.body.classList.remove('globalScope'); + matrixSnapshot.scope = newScope; + matrixSnapshot.tMatrixModifiedTime = undefined; + updateMatrixSnapshot(); + dropDownMenuHide(); } function initScopeCell() { - // It's possible there is no page URL at this point: some pages cannot - // be filtered by ηMatrix. - if (matrixSnapshot.url === '') { - return; - } - let specificScope = uDom.nodeFromId('specificScope'); - - while (specificScope.firstChild !== null) { + // It's possible there is no page URL at this point: some pages cannot + // be filtered by ηMatrix. + if (matrixSnapshot.url === '') { + return; + } + let specificScope = uDom.nodeFromId('specificScope'); + + while (specificScope.firstChild !== null) { specificScope.removeChild(specificScope.firstChild); - } + } - // Fill in the scope menu entries - let pos = matrixSnapshot.domain.indexOf('.'); - let tld, labels; - if (pos === -1) { + // Fill in the scope menu entries + let pos = matrixSnapshot.domain.indexOf('.'); + let tld, labels; + if (pos === -1) { tld = ''; labels = matrixSnapshot.hostname; - } else { + } else { tld = matrixSnapshot.domain.slice(pos + 1); labels = matrixSnapshot.hostname.slice(0, -tld.length); - } - let beg = 0; - let span, label; - while (beg < labels.length) { + } + let beg = 0; + let span, label; + while (beg < labels.length) { pos = labels.indexOf('.', beg); if (pos === -1) { - pos = labels.length; + pos = labels.length; } else { - pos += 1; + pos += 1; } label = document.createElement('span'); label.appendChild(document - .createTextNode(Punycode - .toUnicode(labels.slice(beg, - pos)))); + .createTextNode(Punycode + .toUnicode(labels.slice(beg, + pos)))); span = document.createElement('span'); span.setAttribute('data-scope', labels.slice(beg) + tld); span.appendChild(label); specificScope.appendChild(span); beg = pos; - } - if (tld !== '') { + } + if (tld !== '') { label = document.createElement('span'); label.appendChild(document.createTextNode(Punycode.toUnicode(tld))); span = document.createElement('span'); span.setAttribute('data-scope', tld); span.appendChild(label); specificScope.appendChild(span); - } - updateScopeCell(); + } + updateScopeCell(); } function updateScopeCell() { - let specificScope = uDom.nodeFromId('specificScope'); + let specificScope = uDom.nodeFromId('specificScope'); let isGlobal = matrixSnapshot.scope === '*'; - document.body.classList.toggle('globalScope', isGlobal); - specificScope.classList.toggle('on', !isGlobal); - uDom.nodeFromId('globalScope').classList.toggle('on', isGlobal); + document.body.classList.toggle('globalScope', isGlobal); + specificScope.classList.toggle('on', !isGlobal); + uDom.nodeFromId('globalScope').classList.toggle('on', isGlobal); - for (let node of specificScope.children) { + for (let node of specificScope.children) { node.classList.toggle('on', - !isGlobal - && matrixSnapshot - .scope - .endsWith(node.getAttribute('data-scope'))); - } + !isGlobal + && matrixSnapshot + .scope + .endsWith(node.getAttribute('data-scope'))); + } } function updateMatrixSwitches() { - let count = 0; + let count = 0; let enabled; let switches = matrixSnapshot.tSwitches; - for (let switchName in switches) { + for (let switchName in switches) { if (switches.hasOwnProperty(switchName) === false) { - continue; - } + continue; + } enabled = switches[switchName]; if (enabled && switchName !== 'matrix-off') { - count += 1; + count += 1; } uDom('#mtxSwitch_' + switchName).toggleClass('switchTrue', enabled); - } - uDom.nodeFromId('mtxSwitch_https-strict') - .classList - .toggle('relevant', matrixSnapshot.hasMixedContent); - uDom.nodeFromId('mtxSwitch_no-workers') - .classList - .toggle('relevant', matrixSnapshot.hasWebWorkers); - uDom.nodeFromId('mtxSwitch_referrer-spoof') - .classList.toggle('relevant', matrixSnapshot.has3pReferrer); - uDom.nodeFromId('mtxSwitch_noscript-spoof') - .classList - .toggle('relevant', matrixSnapshot.hasNoscriptTags); - uDom.nodeFromSelector('#buttonMtxSwitches span.badge').textContent = + } + uDom.nodeFromId('mtxSwitch_https-strict') + .classList + .toggle('relevant', matrixSnapshot.hasMixedContent); + uDom.nodeFromId('mtxSwitch_no-workers') + .classList + .toggle('relevant', matrixSnapshot.hasWebWorkers); + uDom.nodeFromId('mtxSwitch_referrer-spoof') + .classList.toggle('relevant', matrixSnapshot.has3pReferrer); + uDom.nodeFromId('mtxSwitch_noscript-spoof') + .classList + .toggle('relevant', matrixSnapshot.hasNoscriptTags); + uDom.nodeFromSelector('#buttonMtxSwitches span.badge').textContent = count.toLocaleString(); - uDom.nodeFromSelector('#mtxSwitch_matrix-off span.badge').textContent = + uDom.nodeFromSelector('#mtxSwitch_matrix-off span.badge').textContent = matrixSnapshot.blockedCount.toLocaleString(); - document.body.classList.toggle('powerOff', switches['matrix-off']); + document.body.classList.toggle('powerOff', switches['matrix-off']); } function toggleMatrixSwitch(ev) { - if (ev.target.localName === 'a') { - return; - } - - let elem = ev.currentTarget; - let pos = elem.id.indexOf('_'); - if (pos === -1) { - return; - } - - let switchName = elem.id.slice(pos + 1); - let request = { + if (ev.target.localName === 'a') { + return; + } + + let elem = ev.currentTarget; + let pos = elem.id.indexOf('_'); + if (pos === -1) { + return; + } + + let switchName = elem.id.slice(pos + 1); + let request = { what: 'toggleMatrixSwitch', switchName: switchName, srcHostname: matrixSnapshot.scope - }; - vAPI.messaging.send('popup.js', request, updateMatrixSnapshot); + }; + vAPI.messaging.send('popup.js', request, updateMatrixSnapshot); } function updatePersistButton() { - let diffCount = matrixSnapshot.diff.length; - let button = uDom('#buttonPersist'); + let diffCount = matrixSnapshot.diff.length; + let button = uDom('#buttonPersist'); - button.contents() + button.contents() .filter(function () { - return this.nodeType===3; - }) - .first() + return this.nodeType===3; + }) + .first() .text(diffCount > 0 ? '\uf13e' : '\uf023'); - button.descendants('span.badge').text(diffCount > 0 ? diffCount : ''); + button.descendants('span.badge').text(diffCount > 0 ? diffCount : ''); - let disabled = diffCount === 0; + let disabled = diffCount === 0; - button.toggleClass('disabled', disabled); - uDom('#buttonRevertScope').toggleClass('disabled', disabled); + button.toggleClass('disabled', disabled); + uDom('#buttonRevertScope').toggleClass('disabled', disabled); } function persistMatrix() { - let request = { + let request = { what: 'applyDiffToPermanentMatrix', diff: matrixSnapshot.diff - }; - vAPI.messaging.send('popup.js', request, updateMatrixSnapshot); + }; + vAPI.messaging.send('popup.js', request, updateMatrixSnapshot); } // rhill 2014-03-12: revert completely ALL changes related to the // current page, including scopes. function revertMatrix() { - let request = { + let request = { what: 'applyDiffToTemporaryMatrix', diff: matrixSnapshot.diff - }; - vAPI.messaging.send('popup.js', request, updateMatrixSnapshot); + }; + vAPI.messaging.send('popup.js', request, updateMatrixSnapshot); } // Buttons which are affected by any changes in the matrix function updateMatrixButtons() { - updateScopeCell(); - updateMatrixSwitches(); - updatePersistButton(); + updateScopeCell(); + updateMatrixSwitches(); + updatePersistButton(); } function revertAll() { - let request = { + let request = { what: 'revertTemporaryMatrix' - }; - vAPI.messaging.send('popup.js', request, updateMatrixSnapshot); - dropDownMenuHide(); + }; + vAPI.messaging.send('popup.js', request, updateMatrixSnapshot); + dropDownMenuHide(); } function buttonReloadHandler(ev) { - vAPI.messaging.send('popup.js', { + vAPI.messaging.send('popup.js', { what: 'forceReloadTab', tabId: matrixSnapshot.tabId, bypassCache: ev.ctrlKey || ev.metaKey || ev.shiftKey - }); + }); } function mouseenterMatrixCellHandler(ev) { - matrixCellHotspots.appendTo(ev.target); + matrixCellHotspots.appendTo(ev.target); } function mouseleaveMatrixCellHandler() { - matrixCellHotspots.detach(); + matrixCellHotspots.detach(); } function gotoExtensionURL(ev) { - let url = uDom(ev.currentTarget).attr('data-extension-url'); - if (url) { + let url = uDom(ev.currentTarget).attr('data-extension-url'); + if (url) { vAPI.messaging.send('popup.js', { - what: 'gotoExtensionURL', - url: url, - shiftKey: ev.shiftKey + what: 'gotoExtensionURL', + url: url, + shiftKey: ev.shiftKey }); - } - dropDownMenuHide(); - vAPI.closePopup(); + } + dropDownMenuHide(); + vAPI.closePopup(); } function dropDownMenuShow(ev) { - let button = ev.target; - let menuOverlay = document.getElementById(button.getAttribute('data-dropdown-menu')); - let butnRect = button.getBoundingClientRect(); - let viewRect = document.body.getBoundingClientRect(); - let butnNormalLeft = butnRect.left / (viewRect.width - butnRect.width); - menuOverlay.classList.add('show'); - let menu = menuOverlay.querySelector('.dropdown-menu'); - let menuRect = menu.getBoundingClientRect(); - let menuLeft = butnNormalLeft * (viewRect.width - menuRect.width); - menu.style.left = menuLeft.toFixed(0) + 'px'; - menu.style.top = butnRect.bottom + 'px'; + let button = ev.target; + let menuOverlay = document.getElementById(button.getAttribute('data-dropdown-menu')); + let butnRect = button.getBoundingClientRect(); + let viewRect = document.body.getBoundingClientRect(); + let butnNormalLeft = butnRect.left / (viewRect.width - butnRect.width); + menuOverlay.classList.add('show'); + let menu = menuOverlay.querySelector('.dropdown-menu'); + let menuRect = menu.getBoundingClientRect(); + let menuLeft = butnNormalLeft * (viewRect.width - menuRect.width); + menu.style.left = menuLeft.toFixed(0) + 'px'; + menu.style.top = butnRect.bottom + 'px'; } function dropDownMenuHide() { - uDom('.dropdown-menu-capture').removeClass('show'); + uDom('.dropdown-menu-capture').removeClass('show'); } let onMatrixSnapshotReady = function (response) { - if (response === 'ENOTFOUND') { + if (response === 'ENOTFOUND') { uDom.nodeFromId('noTabFound').textContent = - vAPI.i18n('matrixNoTabFound'); + vAPI.i18n('matrixNoTabFound'); document.body.classList.add('noTabFound'); return; - } + } - // Now that tabId and pageURL are set, we can build our menu - initMenuEnvironment(); - makeMenu(); + // Now that tabId and pageURL are set, we can build our menu + initMenuEnvironment(); + makeMenu(); - // After popup menu is built, check whether there is a non-empty matrix - if (matrixSnapshot.url === '') { + // After popup menu is built, check whether there is a non-empty matrix + if (matrixSnapshot.url === '') { uDom('#matHead').remove(); uDom('#toolbarContainer').remove(); // https://github.com/gorhill/httpswitchboard/issues/191 uDom('#noNetTrafficPrompt').text(vAPI.i18n('matrixNoNetTrafficPrompt')); uDom('#noNetTrafficPrompt').css('display', ''); - } - - // Create a hash to find out whether the reload button needs to be - // highlighted. - // TODO: - // ηMatrix: not sure what the purpose of highlighting is... - // Maybe telling the user that the page needs refreshing? But - // that's hardly useful (and by now people have gotten used to - // the lack of such a feature.) - // Not really going to do it, but let's leave the comment. + } + + // Create a hash to find out whether the reload button needs to be + // highlighted. + // TODO: + // ηMatrix: not sure what the purpose of highlighting is... + // Maybe telling the user that the page needs refreshing? But + // that's hardly useful (and by now people have gotten used to + // the lack of such a feature.) + // Not really going to do it, but let's leave the comment. }; let matrixSnapshotPoller = (function () { - let timer = null; + let timer = null; - let preprocessMatrixSnapshot = function (snapshot) { + let preprocessMatrixSnapshot = function (snapshot) { if (Array.isArray(snapshot.headerIndices)) { - snapshot.headerIndices = new Map(snapshot.headerIndices); + snapshot.headerIndices = new Map(snapshot.headerIndices); } return snapshot; - }; + }; - let processPollResult = function (response) { + let processPollResult = function (response) { if (typeof response !== 'object') { - return; + return; } if (response.mtxContentModified === false - && response.mtxCountModified === false - && response.pMatrixModified === false - && response.tMatrixModified === false) { - return; + && response.mtxCountModified === false + && response.pMatrixModified === false + && response.tMatrixModified === false) { + return; } matrixSnapshot = preprocessMatrixSnapshot(response); if (response.mtxContentModified) { - makeMenu(); - return; + makeMenu(); + return; } if (response.mtxCountModified) { - updateMatrixCounts(); + updateMatrixCounts(); } if (response.pMatrixModified - || response.tMatrixModified - || response.scopeModified) { - updateMatrixColors(); - updateMatrixBehavior(); - updateMatrixButtons(); + || response.tMatrixModified + || response.scopeModified) { + updateMatrixColors(); + updateMatrixBehavior(); + updateMatrixButtons(); } - }; + }; - let onPolled = function (response) { + let onPolled = function (response) { processPollResult(response); pollAsync(); - }; + }; - let pollNow = function () { + let pollNow = function () { unpollAsync(); vAPI.messaging.send('popup.js', { - what: 'matrixSnapshot', - tabId: matrixSnapshot.tabId, - scope: matrixSnapshot.scope, - mtxContentModifiedTime: matrixSnapshot.mtxContentModifiedTime, - mtxCountModifiedTime: matrixSnapshot.mtxCountModifiedTime, - mtxDiffCount: matrixSnapshot.diff.length, - pMatrixModifiedTime: matrixSnapshot.pMatrixModifiedTime, - tMatrixModifiedTime: matrixSnapshot.tMatrixModifiedTime, + what: 'matrixSnapshot', + tabId: matrixSnapshot.tabId, + scope: matrixSnapshot.scope, + mtxContentModifiedTime: matrixSnapshot.mtxContentModifiedTime, + mtxCountModifiedTime: matrixSnapshot.mtxCountModifiedTime, + mtxDiffCount: matrixSnapshot.diff.length, + pMatrixModifiedTime: matrixSnapshot.pMatrixModifiedTime, + tMatrixModifiedTime: matrixSnapshot.tMatrixModifiedTime, }, onPolled); - }; + }; - let poll = function () { + let poll = function () { timer = null; pollNow(); - }; + }; - let pollAsync = function () { + let pollAsync = function () { if (timer !== null) { - return; + return; } if (document.defaultView === null) { - return; + return; } timer = vAPI.setTimeout(poll, 1414); - }; + }; - let unpollAsync = function () { + let unpollAsync = function () { if (timer !== null) { - clearTimeout(timer); - timer = null; + clearTimeout(timer); + timer = null; } - }; + }; - (function () { + (function () { let tabId = matrixSnapshot.tabId; // If no tab id yet, see if there is one specified in our URL if (tabId === undefined) { - let matches = window - .location - .search - .match(/(?:\?|&)tabId=([^&]+)/); + let matches = window + .location + .search + .match(/(?:\?|&)tabId=([^&]+)/); - if (matches !== null) { + if (matches !== null) { tabId = matches[1]; // No need for logger button when embedded in logger uDom('[data-extension-url="logger-ui.html"]').remove(); - } + } } let snapshotFetched = function (response) { - if (typeof response === 'object') { + if (typeof response === 'object') { matrixSnapshot = preprocessMatrixSnapshot(response); - } - onMatrixSnapshotReady(response); - pollAsync(); + } + onMatrixSnapshotReady(response); + pollAsync(); }; vAPI.messaging.send('popup.js', { - what: 'matrixSnapshot', - tabId: tabId + what: 'matrixSnapshot', + tabId: tabId }, snapshotFetched); - })(); + })(); - return { + return { pollNow: pollNow - }; + }; })(); // Below is UI stuff which is not key to make the menu, so this can @@ -1536,8 +1536,8 @@ matrixCellHotspots = uDom('#cellHotspots').detach(); uDom('body') - .on('mouseenter', '.matCell', mouseenterMatrixCellHandler) - .on('mouseleave', '.matCell', mouseleaveMatrixCellHandler); + .on('mouseenter', '.matCell', mouseenterMatrixCellHandler) + .on('mouseleave', '.matCell', mouseleaveMatrixCellHandler); uDom('#specificScope').on('click', selectSpecificScope); uDom('#globalScope').on('click', selectGlobalScope); @@ -1553,9 +1553,9 @@ uDom('body').on('click', '.dropdown-menu-capture', dropDownMenuHide); uDom('#matList').on('click', '.g4Meta', function (ev) { - matrixSnapshot.collapseBlacklistedDomains = + matrixSnapshot.collapseBlacklistedDomains = ev.target.classList.toggle('g4Collapsed'); - setUserSetting('popupCollapseBlacklistedDomains', - matrixSnapshot.collapseBlacklistedDomains); + setUserSetting('popupCollapseBlacklistedDomains', + matrixSnapshot.collapseBlacklistedDomains); }); })(); diff --git a/js/profiler.js b/js/profiler.js index 7406e92..49fe7d9 100644 --- a/js/profiler.js +++ b/js/profiler.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ diff --git a/js/raw-settings.js b/js/raw-settings.js index 5940188..54c5b3c 100644 --- a/js/raw-settings.js +++ b/js/raw-settings.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2018-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uBlock */ @@ -29,89 +29,89 @@ (function() { - /******************************************************************************/ +/******************************************************************************/ - var messaging = vAPI.messaging; - var cachedData = ''; - var rawSettingsInput = uDom.nodeFromId('rawSettings'); +var messaging = vAPI.messaging; +var cachedData = ''; +var rawSettingsInput = uDom.nodeFromId('rawSettings'); - /******************************************************************************/ +/******************************************************************************/ - var hashFromRawSettings = function(raw) { - return raw.trim().replace(/\s+/g, '|'); - }; +var hashFromRawSettings = function(raw) { + return raw.trim().replace(/\s+/g, '|'); +}; - /******************************************************************************/ +/******************************************************************************/ - // This is to give a visual hint that the content of user blacklist has changed. +// This is to give a visual hint that the content of user blacklist has changed. - var rawSettingsChanged = (function () { - var timer = null; +var rawSettingsChanged = (function () { + var timer = null; - var handler = function() { - timer = null; - var changed = - hashFromRawSettings(rawSettingsInput.value) !== cachedData; - uDom.nodeFromId('rawSettingsApply').disabled = !changed; - }; + var handler = function() { + timer = null; + var changed = + hashFromRawSettings(rawSettingsInput.value) !== cachedData; + uDom.nodeFromId('rawSettingsApply').disabled = !changed; + }; - return function() { - if ( timer !== null ) { - clearTimeout(timer); - } - timer = vAPI.setTimeout(handler, 100); - }; - })(); - - /******************************************************************************/ - - function renderRawSettings() { - var onRead = function(raw) { - cachedData = hashFromRawSettings(raw); - var pretty = [], - whitespaces = ' ', - lines = raw.split('\n'), - max = 0, - pos, - i, n = lines.length; - for ( i = 0; i < n; i++ ) { - pos = lines[i].indexOf(' '); - if ( pos > max ) { - max = pos; - } - } - for ( i = 0; i < n; i++ ) { - pos = lines[i].indexOf(' '); - pretty.push(whitespaces.slice(0, max - pos) + lines[i]); + return function() { + if ( timer !== null ) { + clearTimeout(timer); + } + timer = vAPI.setTimeout(handler, 100); + }; +})(); + +/******************************************************************************/ + +function renderRawSettings() { + var onRead = function(raw) { + cachedData = hashFromRawSettings(raw); + var pretty = [], + whitespaces = ' ', + lines = raw.split('\n'), + max = 0, + pos, + i, n = lines.length; + for ( i = 0; i < n; i++ ) { + pos = lines[i].indexOf(' '); + if ( pos > max ) { + max = pos; } - rawSettingsInput.value = pretty.join('\n') + '\n'; - rawSettingsChanged(); - rawSettingsInput.focus(); - }; - messaging.send('dashboard', { what: 'readRawSettings' }, onRead); - } - - /******************************************************************************/ - - var applyChanges = function() { - messaging.send( - 'dashboard', - { - what: 'writeRawSettings', - content: rawSettingsInput.value - }, - renderRawSettings - ); + } + for ( i = 0; i < n; i++ ) { + pos = lines[i].indexOf(' '); + pretty.push(whitespaces.slice(0, max - pos) + lines[i]); + } + rawSettingsInput.value = pretty.join('\n') + '\n'; + rawSettingsChanged(); + rawSettingsInput.focus(); }; + messaging.send('dashboard', { what: 'readRawSettings' }, onRead); +} + +/******************************************************************************/ + +var applyChanges = function() { + messaging.send( + 'dashboard', + { + what: 'writeRawSettings', + content: rawSettingsInput.value + }, + renderRawSettings + ); +}; - /******************************************************************************/ +/******************************************************************************/ - // Handle user interaction - uDom('#rawSettings').on('input', rawSettingsChanged); - uDom('#rawSettingsApply').on('click', applyChanges); +// Handle user interaction +uDom('#rawSettings').on('input', rawSettingsChanged); +uDom('#rawSettingsApply').on('click', applyChanges); - renderRawSettings(); +renderRawSettings(); - /******************************************************************************/ +/******************************************************************************/ })(); diff --git a/js/settings.js b/js/settings.js index 5694b83..a9e11b4 100644 --- a/js/settings.js +++ b/js/settings.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -27,100 +27,100 @@ let cachedSettings = {}; function changeUserSettings(name, value) { - vAPI.messaging.send('settings.js', { + vAPI.messaging.send('settings.js', { what: 'userSettings', name: name, value: value - }); + }); } function changeMatrixSwitch(name, state) { - vAPI.messaging.send('settings.js', { + vAPI.messaging.send('settings.js', { what: 'setMatrixSwitch', switchName: name, state: state - }); + }); } function onChangeValueHandler(elem, setting, min, max) { - let oldVal = cachedSettings.userSettings[setting]; - let newVal = Math.round(parseFloat(elem.value)); - if (typeof newVal !== 'number') { + let oldVal = cachedSettings.userSettings[setting]; + let newVal = Math.round(parseFloat(elem.value)); + if (typeof newVal !== 'number') { newVal = oldVal; - } else { + } else { newVal = Math.max(newVal, min); newVal = Math.min(newVal, max); - } - elem.value = newVal; - if (newVal !== oldVal) { + } + elem.value = newVal; + if (newVal !== oldVal) { changeUserSettings(setting, newVal); - } + } } function prepareToDie() { - onChangeValueHandler(uDom.nodeFromId('deleteUnusedSessionCookiesAfter'), - 'deleteUnusedSessionCookiesAfter', - 15, 1440); - onChangeValueHandler(uDom.nodeFromId('clearBrowserCacheAfter'), - 'clearBrowserCacheAfter', - 15, 1440); + onChangeValueHandler(uDom.nodeFromId('deleteUnusedSessionCookiesAfter'), + 'deleteUnusedSessionCookiesAfter', + 15, 1440); + onChangeValueHandler(uDom.nodeFromId('clearBrowserCacheAfter'), + 'clearBrowserCacheAfter', + 15, 1440); } function onInputChanged(ev) { - let target = ev.target; + let target = ev.target; - switch (target.id) { - case 'displayTextSize': + switch (target.id) { + case 'displayTextSize': changeUserSettings('displayTextSize', target.value + 'px'); break; - case 'clearBrowserCache': - case 'cloudStorageEnabled': - case 'collapseBlacklisted': - case 'colorBlindFriendly': - case 'deleteCookies': - case 'deleteLocalStorage': - case 'deleteUnusedSessionCookies': - case 'iconBadgeEnabled': - case 'processHyperlinkAuditing': - case 'disableUpdateIcon': - case 'resolveCname': - changeUserSettings(target.id, target.checked); - break; - case 'collapseBlocked': + case 'clearBrowserCache': + case 'cloudStorageEnabled': + case 'collapseBlacklisted': + case 'colorBlindFriendly': + case 'deleteCookies': + case 'deleteLocalStorage': + case 'deleteUnusedSessionCookies': + case 'iconBadgeEnabled': + case 'processHyperlinkAuditing': + case 'disableUpdateIcon': + case 'resolveCname': changeUserSettings(target.id, target.checked); - synchronizeWidgets(); break; - case 'noMixedContent': - case 'noscriptTagsSpoofed': - case 'processReferer': + case 'collapseBlocked': + changeUserSettings(target.id, target.checked); + synchronizeWidgets(); + break; + case 'noMixedContent': + case 'noscriptTagsSpoofed': + case 'processReferer': changeMatrixSwitch(target.getAttribute('data-matrix-switch'), - target.checked); + target.checked); break; - case 'deleteUnusedSessionCookiesAfter': + case 'deleteUnusedSessionCookiesAfter': onChangeValueHandler(target, 'deleteUnusedSessionCookiesAfter', - 15, 1440); + 15, 1440); break; - case 'clearBrowserCacheAfter': + case 'clearBrowserCacheAfter': onChangeValueHandler(target, 'clearBrowserCacheAfter', 15, 1440); break; - case 'popupScopeLevel': + case 'popupScopeLevel': changeUserSettings('popupScopeLevel', target.value); break; - default: + default: break; - } + } } function synchronizeWidgets() { - let e1, e2; + let e1, e2; - e1 = uDom.nodeFromId('collapseBlocked'); - e2 = uDom.nodeFromId('collapseBlacklisted'); - if (e1.checked) { + e1 = uDom.nodeFromId('collapseBlocked'); + e2 = uDom.nodeFromId('collapseBlacklisted'); + if (e1.checked) { e2.setAttribute('disabled', ''); - } else { + } else { e2.removeAttribute('disabled'); - } + } } let onSettingsReceived = function (settings) { @@ -131,24 +131,24 @@ let matrixSwitches = settings.matrixSwitches; uDom('[data-setting-bool]').forEach(function (elem) { - elem.prop('checked', userSettings[elem.prop('id')] === true); + elem.prop('checked', userSettings[elem.prop('id')] === true); }); uDom('[data-matrix-switch]').forEach(function (elem) { - let switchName = elem.attr('data-matrix-switch'); - if (typeof switchName === 'string' && switchName !== '') { + let switchName = elem.attr('data-matrix-switch'); + if (typeof switchName === 'string' && switchName !== '') { elem.prop('checked', matrixSwitches[switchName] === true); - } + } }); uDom.nodeFromId('displayTextSize').value = - parseInt(userSettings.displayTextSize, 10) || 14; + parseInt(userSettings.displayTextSize, 10) || 14; uDom.nodeFromId('popupScopeLevel').value = userSettings.popupScopeLevel; uDom.nodeFromId('deleteUnusedSessionCookiesAfter').value = - userSettings.deleteUnusedSessionCookiesAfter; + userSettings.deleteUnusedSessionCookiesAfter; uDom.nodeFromId('clearBrowserCacheAfter').value = - userSettings.clearBrowserCacheAfter; + userSettings.clearBrowserCacheAfter; synchronizeWidgets(); @@ -159,6 +159,6 @@ } vAPI.messaging.send('settings.js', { - what: 'getUserSettings' + what: 'getUserSettings' }, onSettingsReceived); })(); diff --git a/js/start.js b/js/start.js index b0f3970..f7867ee 100644 --- a/js/start.js +++ b/js/start.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -31,58 +31,58 @@ let ηm = ηMatrix; let processCallbackQueue = function (queue, callback) { - while (queue.length > 0) { - let fn = queue.pop(); - fn(); - } - - if (typeof callback === 'function') { - callback(); - } + while (queue.length > 0) { + let fn = queue.pop(); + fn(); + } + + if (typeof callback === 'function') { + callback(); + } }; let onAllDone = function () { - ηm.webRequest.start(); + ηm.webRequest.start(); - ηm.assets.checkVersion(); - ηm.assets.addObserver(ηm.assetObserver.bind(ηm)); - ηm.scheduleAssetUpdater(ηm.userSettings.autoUpdate ? 7 * 60 * 1000 : 0); + ηm.assets.checkVersion(); + ηm.assets.addObserver(ηm.assetObserver.bind(ηm)); + ηm.scheduleAssetUpdater(ηm.userSettings.autoUpdate ? 7 * 60 * 1000 : 0); - vAPI.cloud.start([ 'myRulesPane' ]); + vAPI.cloud.start([ 'myRulesPane' ]); }; let onTabsReady = function (tabs) { - for (let i=tabs.length-1; i>=0; --i) { - // console.debug('start.js > binding %d tabs', i); + for (let i=tabs.length-1; i>=0; --i) { + // console.debug('start.js > binding %d tabs', i); let tab = tabs[i]; ηm.tabContextManager.push(tab.id, tab.url, 'newURL'); - } + } - onAllDone(); + onAllDone(); }; let onUserSettingsLoaded = function () { - ηm.loadHostsFiles(); + ηm.loadHostsFiles(); }; let onPSLReady = function () { - ηm.loadUserSettings(onUserSettingsLoaded); - ηm.loadRawSettings(); - ηm.loadMatrix(); - - // rhill 2013-11-24: bind behind-the-scene virtual tab/url - // manually, since the normal way forbid binding behind the - // scene tab. - // https://github.com/gorhill/httpswitchboard/issues/67 - ηm.pageStores[vAPI.noTabId] = - ηm.pageStoreFactory(ηm.tabContextManager.mustLookup(vAPI.noTabId)); - ηm.pageStores[vAPI.noTabId].title = - vAPI.i18n('statsPageDetailedBehindTheScenePage'); - - vAPI.tabs.getAll(onTabsReady); + ηm.loadUserSettings(onUserSettingsLoaded); + ηm.loadRawSettings(); + ηm.loadMatrix(); + + // rhill 2013-11-24: bind behind-the-scene virtual tab/url + // manually, since the normal way forbid binding behind the + // scene tab. + // https://github.com/gorhill/httpswitchboard/issues/67 + ηm.pageStores[vAPI.noTabId] = + ηm.pageStoreFactory(ηm.tabContextManager.mustLookup(vAPI.noTabId)); + ηm.pageStores[vAPI.noTabId].title = + vAPI.i18n('statsPageDetailedBehindTheScenePage'); + + vAPI.tabs.getAll(onTabsReady); }; processCallbackQueue(ηm.onBeforeStartQueue, function () { - ηm.loadPublicSuffixList(onPSLReady); + ηm.loadPublicSuffixList(onPSLReady); }); })(); diff --git a/js/storage.js b/js/storage.js index f5afca8..24249ab 100644 --- a/js/storage.js +++ b/js/storage.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -552,7 +552,7 @@ Components.utils.import('chrome://ematrix/content/lib/Tools.jsm'); }; ηMatrix.scheduleAssetUpdater = (function () { - let timer; + let timer = undefined; let next = 0; return function (updateDelay) { @@ -618,11 +618,11 @@ Components.utils.import('chrome://ematrix/content/lib/Tools.jsm'); if (details.assetKeys.length !== 0) { this.loadHostsFiles(); } - if (this.userSettings.autoUpdate) { - this.scheduleAssetUpdater(25200000); - } else { - this.scheduleAssetUpdater(0); - } + + ηm.scheduleAssetUpdater(ηm.userSettings.autoUpdate ? + 7 * 60 * 100000 : + 0); + vAPI.messaging.broadcast({ what: 'assetsUpdated', assetKeys: details.assetKeys @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -40,47 +40,47 @@ // apply only to that scheme. ηm.normalizePageURL = function (tabId, pageURL) { - if (vAPI.isBehindTheSceneTabId(tabId)) { + if (vAPI.isBehindTheSceneTabId(tabId)) { return 'http://' + this.behindTheSceneScope + '/'; - } - - // https://github.com/gorhill/uMatrix/issues/992 - if (pageURL.startsWith('wyciwyg:')) { - // Matches strings like 'wyciwyg://101/' - let filter = /^wyciwyg:\/\/\d+\//.exec(pageURL); - if (filter) { - pageURL = pageURL.slice(filter[0].length); - } - } - - // If the URL is that of our "blocked page" document, return - // the URL of the blocked page. - if (pageURL.lastIndexOf(vAPI.getURL('main-blocked.html'), 0) === 0) { + } + + // https://github.com/gorhill/uMatrix/issues/992 + if (pageURL.startsWith('wyciwyg:')) { + // Matches strings like 'wyciwyg://101/' + let filter = /^wyciwyg:\/\/\d+\//.exec(pageURL); + if (filter) { + pageURL = pageURL.slice(filter[0].length); + } + } + + // If the URL is that of our "blocked page" document, return + // the URL of the blocked page. + if (pageURL.lastIndexOf(vAPI.getURL('main-blocked.html'), 0) === 0) { let matches = /main-blocked\.html\?details=([^&]+)/.exec(pageURL); if (matches && matches.length === 2) { - try { + try { let details = JSON.parse(atob(matches[1])); pageURL = details.url; - } catch (e) { - } + } catch (e) { + } } - } + } - let uri = UriTools.set(pageURL); - let scheme = uri.scheme; - if (scheme === 'https' || scheme === 'http') { + let uri = UriTools.set(pageURL); + let scheme = uri.scheme; + if (scheme === 'https' || scheme === 'http') { return UriTools.normalizedURI(); - } + } - let fakeHostname = scheme + '-scheme'; + let fakeHostname = scheme + '-scheme'; - if (uri.hostname !== '') { + if (uri.hostname !== '') { fakeHostname = uri.hostname + '.' + fakeHostname; - } else if (scheme === 'about') { + } else if (scheme === 'about') { fakeHostname = uri.path + '.' + fakeHostname; - } + } - return 'http://' + fakeHostname + '/'; + return 'http://' + fakeHostname + '/'; }; /* @@ -149,119 +149,119 @@ */ ηm.tabContextManager = (function () { - let tabContexts = Object.create(null); + let tabContexts = Object.create(null); - // https://github.com/chrisaljoudi/uBlock/issues/1001 - // This is to be used as last-resort fallback in case a tab is - // found to not be bound while network requests are fired for - // the tab. - let mostRecentRootDocURL = ''; - let mostRecentRootDocURLTimestamp = 0; + // https://github.com/chrisaljoudi/uBlock/issues/1001 + // This is to be used as last-resort fallback in case a tab is + // found to not be bound while network requests are fired for + // the tab. + let mostRecentRootDocURL = ''; + let mostRecentRootDocURLTimestamp = 0; - let gcPeriod = 31 * 60 * 1000; // every 31 minutes + let gcPeriod = 31 * 60 * 1000; // every 31 minutes - // A pushed entry is removed from the stack unless it is - // committed with a set time. - let StackEntry = function (url, commit) { + // A pushed entry is removed from the stack unless it is + // committed with a set time. + let StackEntry = function (url, commit) { this.url = url; this.committed = commit; this.tstamp = Date.now(); - }; + }; - let TabContext = function (tabId) { + let TabContext = function (tabId) { this.tabId = tabId; this.stack = []; this.rawURL = - this.normalURL = - this.scheme = - this.rootHostname = - this.rootDomain = ''; + this.normalURL = + this.scheme = + this.rootHostname = + this.rootDomain = ''; this.secure = false; this.commitTimer = null; this.gcTimer = null; tabContexts[tabId] = this; - }; + }; - TabContext.prototype.destroy = function () { + TabContext.prototype.destroy = function () { if (vAPI.isBehindTheSceneTabId(this.tabId)) { - return; + return; } if (this.gcTimer !== null) { - clearTimeout(this.gcTimer); - this.gcTimer = null; + clearTimeout(this.gcTimer); + this.gcTimer = null; } delete tabContexts[this.tabId]; - }; + }; - TabContext.prototype.onTab = function (tab) { + TabContext.prototype.onTab = function (tab) { if (tab) { - this.gcTimer = vAPI.setTimeout(this.onGC.bind(this), gcPeriod); + this.gcTimer = vAPI.setTimeout(this.onGC.bind(this), gcPeriod); } else { - this.destroy(); + this.destroy(); } - }; + }; - TabContext.prototype.onGC = function () { + TabContext.prototype.onGC = function () { this.gcTimer = null; if (vAPI.isBehindTheSceneTabId(this.tabId)) { - return; + return; } vAPI.tabs.get(this.tabId, this.onTab.bind(this)); - }; + }; - // https://github.com/gorhill/uBlock/issues/248 - // Stack entries have to be committed to stick. Non-committed - // stack entries are removed after a set delay. - TabContext.prototype.onCommit = function () { + // https://github.com/gorhill/uBlock/issues/248 + // Stack entries have to be committed to stick. Non-committed + // stack entries are removed after a set delay. + TabContext.prototype.onCommit = function () { if (vAPI.isBehindTheSceneTabId(this.tabId)) { - return; + return; } this.commitTimer = null; // Remove uncommitted entries at the top of the stack. let i = this.stack.length; while (i--) { - if (this.stack[i].committed) { + if (this.stack[i].committed) { break; - } + } } // https://github.com/gorhill/uBlock/issues/300 // If no committed entry was found, fall back on the bottom-most one // as being the committed one by default. if (i === -1 && this.stack.length !== 0) { - this.stack[0].committed = true; - i = 0; + this.stack[0].committed = true; + i = 0; } ++i; if (i < this.stack.length) { - this.stack.length = i; - this.update(); - ηm.bindTabToPageStats(this.tabId, 'newURL'); + this.stack.length = i; + this.update(); + ηm.bindTabToPageStats(this.tabId, 'newURL'); } - }; + }; - // This takes care of orphanized tab contexts. Can't be - // started for all contexts, as the behind-the-scene context - // is permanent -- so we do not want to flush it. - TabContext.prototype.autodestroy = function () { + // This takes care of orphanized tab contexts. Can't be + // started for all contexts, as the behind-the-scene context + // is permanent -- so we do not want to flush it. + TabContext.prototype.autodestroy = function () { if (vAPI.isBehindTheSceneTabId(this.tabId)) { - return; + return; } this.gcTimer = vAPI.setTimeout(this.onGC.bind(this), gcPeriod); - }; + }; - // Update just force all properties to be updated to match the - // most recent root URL. - TabContext.prototype.update = function () { + // Update just force all properties to be updated to match the + // most recent root URL. + TabContext.prototype.update = function () { if (this.stack.length === 0) { - this.rawURL = - this.normalURL = - this.scheme = - this.rootHostname = - this.rootDomain = ''; - this.secure = false; - return; + this.rawURL = + this.normalURL = + this.scheme = + this.rootHostname = + this.rootDomain = ''; + this.secure = false; + return; } this.rawURL = this.stack[this.stack.length - 1].url; @@ -269,71 +269,71 @@ this.scheme = UriTools.schemeFromURI(this.rawURL); this.rootHostname = UriTools.hostnameFromURI(this.normalURL); this.rootDomain = UriTools.domainFromHostname(this.rootHostname) - || this.rootHostname; + || this.rootHostname; this.secure = UriTools.isSecureScheme(this.scheme); - }; + }; - // Called whenever a candidate root URL is spotted for the tab. - TabContext.prototype.push = function (url, context) { + // Called whenever a candidate root URL is spotted for the tab. + TabContext.prototype.push = function (url, context) { if (vAPI.isBehindTheSceneTabId(this.tabId)) { - return; - } + return; + } let committed = context !== undefined; let count = this.stack.length; let topEntry = this.stack[count - 1]; if (topEntry && topEntry.url === url) { - if (committed) { + if (committed) { topEntry.committed = true; - } - return; + } + return; } if (this.commitTimer !== null) { - clearTimeout(this.commitTimer); + clearTimeout(this.commitTimer); } if (committed) { - this.stack = [new StackEntry(url, true)]; + this.stack = [new StackEntry(url, true)]; } else { - this.stack.push(new StackEntry(url)); - this.commitTimer = - vAPI.setTimeout(this.onCommit.bind(this), 1000); + this.stack.push(new StackEntry(url)); + this.commitTimer = + vAPI.setTimeout(this.onCommit.bind(this), 1000); } this.update(); ηm.bindTabToPageStats(this.tabId, context); - }; + }; - // These are to be used for the API of the tab context manager. + // These are to be used for the API of the tab context manager. - let push = function (tabId, url, context) { + let push = function (tabId, url, context) { let entry = tabContexts[tabId]; if (entry === undefined) { - entry = new TabContext(tabId); - entry.autodestroy(); + entry = new TabContext(tabId); + entry.autodestroy(); } entry.push(url, context); mostRecentRootDocURL = url; mostRecentRootDocURLTimestamp = Date.now(); return entry; - }; + }; - // Find a tab context for a specific tab. If none is found, - // attempt to fix this. When all fail, the behind-the-scene - // context is returned. - let mustLookup = function (tabId, url) { + // Find a tab context for a specific tab. If none is found, + // attempt to fix this. When all fail, the behind-the-scene + // context is returned. + let mustLookup = function (tabId, url) { let entry; if (url !== undefined) { - entry = push(tabId, url); + entry = push(tabId, url); } else { - entry = tabContexts[tabId]; + entry = tabContexts[tabId]; } if (entry !== undefined) { - return entry; + return entry; } // https://github.com/chrisaljoudi/uBlock/issues/1025 @@ -342,8 +342,8 @@ // it is too far in the future, at which point it ceases // to be a "best guess". if (mostRecentRootDocURL - !== '' && mostRecentRootDocURLTimestamp + 500 < Date.now()) { - mostRecentRootDocURL = ''; + !== '' && mostRecentRootDocURLTimestamp + 500 < Date.now()) { + mostRecentRootDocURL = ''; } // https://github.com/chrisaljoudi/uBlock/issues/1001 @@ -352,7 +352,7 @@ // document to the unbound tab. It's a guess, but better // than ending up filtering nothing at all. if (mostRecentRootDocURL !== '') { - return push(tabId, mostRecentRootDocURL); + return push(tabId, mostRecentRootDocURL); } // If all else fail at finding a page store, re-categorize @@ -363,69 +363,69 @@ // Example: Chromium + case #12 at // http://raymondhill.net/ublock/popup.html return tabContexts[vAPI.noTabId]; - }; + }; - let lookup = function (tabId) { + let lookup = function (tabId) { return tabContexts[tabId] || null; - }; + }; - // Behind-the-scene tab context - (function () { + // Behind-the-scene tab context + (function () { let entry = new TabContext(vAPI.noTabId); entry.stack.push(new StackEntry('', true)); entry.rawURL = ''; entry.normalURL = ηm.normalizePageURL(entry.tabId); entry.rootHostname = UriTools.hostnameFromURI(entry.normalURL); entry.rootDomain = UriTools.domainFromHostname(entry.rootHostname) - || entry.rootHostname; - })(); + || entry.rootHostname; + })(); - // https://github.com/gorhill/uMatrix/issues/513 - // Force a badge update here, it could happen that all the - // subsequent network requests are already in the page - // store, which would cause the badge to no be updated for - // these network requests. + // https://github.com/gorhill/uMatrix/issues/513 + // Force a badge update here, it could happen that all the + // subsequent network requests are already in the page + // store, which would cause the badge to no be updated for + // these network requests. - vAPI.tabs.onNavigation = function (details) { + vAPI.tabs.onNavigation = function (details) { let tabId = details.tabId; if (vAPI.isBehindTheSceneTabId(tabId)) { - return; - } + return; + } push(tabId, details.url, 'newURL'); ηm.updateBadgeAsync(tabId); - }; + }; - // https://github.com/gorhill/uMatrix/issues/872 - // `changeInfo.url` may not always be available (Firefox). + // https://github.com/gorhill/uMatrix/issues/872 + // `changeInfo.url` may not always be available (Firefox). - vAPI.tabs.onUpdated = function (tabId, changeInfo, tab) { + vAPI.tabs.onUpdated = function (tabId, changeInfo, tab) { if (vAPI.isBehindTheSceneTabId(tabId)) { - return; - } + return; + } if (typeof tab.url !== 'string' || tab.url === '') { - return; - } + return; + } let url = changeInfo.url || tab.url; if (url) { - push(tabId, url, 'updateURL'); + push(tabId, url, 'updateURL'); } - }; + }; - vAPI.tabs.onClosed = function (tabId) { + vAPI.tabs.onClosed = function (tabId) { ηm.unbindTabFromPageStats(tabId); let entry = tabContexts[tabId]; if (entry instanceof TabContext) { - entry.destroy(); + entry.destroy(); } - }; + }; - return { + return { push: push, lookup: lookup, mustLookup: mustLookup - }; + }; })(); vAPI.tabs.registerListeners(); @@ -433,30 +433,30 @@ // Create an entry for the tab if it doesn't exist ηm.bindTabToPageStats = function (tabId, context) { - this.updateBadgeAsync(tabId); + this.updateBadgeAsync(tabId); - // Do not create a page store for URLs which are of no - // interests Example: dev console - let tabContext = this.tabContextManager.lookup(tabId); - if (tabContext === null) { + // Do not create a page store for URLs which are of no + // interests Example: dev console + let tabContext = this.tabContextManager.lookup(tabId); + if (tabContext === null) { throw new Error('Unmanaged tab id: ' + tabId); - } + } - // rhill 2013-11-24: Never ever rebind behind-the-scene - // virtual tab. - // https://github.com/gorhill/httpswitchboard/issues/67 - if (vAPI.isBehindTheSceneTabId(tabId)) { + // rhill 2013-11-24: Never ever rebind behind-the-scene + // virtual tab. + // https://github.com/gorhill/httpswitchboard/issues/67 + if (vAPI.isBehindTheSceneTabId(tabId)) { return this.pageStores[tabId]; - } + } - let normalURL = tabContext.normalURL; - let pageStore = this.pageStores[tabId] || null; + let normalURL = tabContext.normalURL; + let pageStore = this.pageStores[tabId] || null; - // The previous page URL, if any, associated with the tab - if (pageStore !== null) { + // The previous page URL, if any, associated with the tab + if (pageStore !== null) { // No change, do not rebind if (pageStore.pageUrl === normalURL) { - return pageStore; + return pageStore; } // https://github.com/gorhill/uMatrix/issues/37 @@ -466,124 +466,124 @@ // https://github.com/gorhill/uMatrix/issues/72 // Need to double-check that the new scope is same as old scope if (context === 'updateURL' - && pageStore.pageHostname === tabContext.rootHostname) { - pageStore.rawURL = tabContext.rawURL; - pageStore.normalURL = normalURL; - this.updateTitle(tabId); - this.pageStoresToken = Date.now(); - return pageStore; + && pageStore.pageHostname === tabContext.rootHostname) { + pageStore.rawURL = tabContext.rawURL; + pageStore.normalURL = normalURL; + this.updateTitle(tabId); + this.pageStoresToken = Date.now(); + return pageStore; } // We won't be reusing this page store. this.unbindTabFromPageStats(tabId); - } + } - // Try to resurrect first. - pageStore = this.resurrectPageStore(tabId, normalURL); - if (pageStore === null) { + // Try to resurrect first. + pageStore = this.resurrectPageStore(tabId, normalURL); + if (pageStore === null) { pageStore = this.pageStoreFactory(tabContext); - } - this.pageStores[tabId] = pageStore; - this.updateTitle(tabId); - this.pageStoresToken = Date.now(); + } + this.pageStores[tabId] = pageStore; + this.updateTitle(tabId); + this.pageStoresToken = Date.now(); - return pageStore; + return pageStore; }; ηm.unbindTabFromPageStats = function (tabId) { - if (vAPI.isBehindTheSceneTabId(tabId)) { + if (vAPI.isBehindTheSceneTabId(tabId)) { return; - } + } - let pageStore = this.pageStores[tabId] || null; - if (pageStore === null) { + let pageStore = this.pageStores[tabId] || null; + if (pageStore === null) { return; - } + } - delete this.pageStores[tabId]; - this.pageStoresToken = Date.now(); + delete this.pageStores[tabId]; + this.pageStoresToken = Date.now(); - if (pageStore.incinerationTimer) { + if (pageStore.incinerationTimer) { clearTimeout(pageStore.incinerationTimer); pageStore.incinerationTimer = null; - } + } - if (this.pageStoreCemetery.hasOwnProperty(tabId) === false) { + if (this.pageStoreCemetery.hasOwnProperty(tabId) === false) { this.pageStoreCemetery[tabId] = {}; - } - let pageStoreCrypt = this.pageStoreCemetery[tabId]; + } + let pageStoreCrypt = this.pageStoreCemetery[tabId]; - let pageURL = pageStore.pageUrl; - pageStoreCrypt[pageURL] = pageStore; + let pageURL = pageStore.pageUrl; + pageStoreCrypt[pageURL] = pageStore; - pageStore.incinerationTimer = - vAPI.setTimeout(this.incineratePageStore.bind(this, tabId, pageURL), - 4 * 60 * 1000); + pageStore.incinerationTimer = + vAPI.setTimeout(this.incineratePageStore.bind(this, tabId, pageURL), + 4 * 60 * 1000); }; ηm.resurrectPageStore = function (tabId, pageURL) { - if (this.pageStoreCemetery.hasOwnProperty(tabId) === false) { + if (this.pageStoreCemetery.hasOwnProperty(tabId) === false) { return null; - } + } - let pageStoreCrypt = this.pageStoreCemetery[tabId]; + let pageStoreCrypt = this.pageStoreCemetery[tabId]; - if (pageStoreCrypt.hasOwnProperty(pageURL) === false) { + if (pageStoreCrypt.hasOwnProperty(pageURL) === false) { return null; - } + } - let pageStore = pageStoreCrypt[pageURL]; + let pageStore = pageStoreCrypt[pageURL]; - if (pageStore.incinerationTimer !== null) { + if (pageStore.incinerationTimer !== null) { clearTimeout(pageStore.incinerationTimer); pageStore.incinerationTimer = null; - } + } - delete pageStoreCrypt[pageURL]; - if (Object.keys(pageStoreCrypt).length === 0) { + delete pageStoreCrypt[pageURL]; + if (Object.keys(pageStoreCrypt).length === 0) { delete this.pageStoreCemetery[tabId]; - } + } - return pageStore; + return pageStore; }; ηm.incineratePageStore = function (tabId, pageURL) { - if (this.pageStoreCemetery.hasOwnProperty(tabId) === false) { + if (this.pageStoreCemetery.hasOwnProperty(tabId) === false) { return; - } + } - let pageStoreCrypt = this.pageStoreCemetery[tabId]; + let pageStoreCrypt = this.pageStoreCemetery[tabId]; - if (pageStoreCrypt.hasOwnProperty(pageURL) === false) { + if (pageStoreCrypt.hasOwnProperty(pageURL) === false) { return; - } + } - let pageStore = pageStoreCrypt[pageURL]; - if (pageStore.incinerationTimer !== null) { + let pageStore = pageStoreCrypt[pageURL]; + if (pageStore.incinerationTimer !== null) { clearTimeout(pageStore.incinerationTimer); pageStore.incinerationTimer = null; - } + } - delete pageStoreCrypt[pageURL]; + delete pageStoreCrypt[pageURL]; - if (Object.keys(pageStoreCrypt).length === 0) { + if (Object.keys(pageStoreCrypt).length === 0) { delete this.pageStoreCemetery[tabId]; - } + } - pageStore.dispose(); + pageStore.dispose(); }; ηm.pageStoreFromTabId = function (tabId) { - return this.pageStores[tabId] || null; + return this.pageStores[tabId] || null; }; // Never return null ηm.mustPageStoreFromTabId = function (tabId) { - return this.pageStores[tabId] || this.pageStores[vAPI.noTabId]; + return this.pageStores[tabId] || this.pageStores[vAPI.noTabId]; }; ηm.forceReload = function (tabId, bypassCache) { - vAPI.tabs.reload(tabId, bypassCache); + vAPI.tabs.reload(tabId, bypassCache); }; // Update badge @@ -595,9 +595,9 @@ // ηMatrix: does it matter to us? ηm.updateBadgeAsync = (function () { - let tabIdToTimer = Object.create(null); + let tabIdToTimer = Object.create(null); - let updateBadge = function (tabId) { + let updateBadge = function (tabId) { delete tabIdToTimer[tabId]; let iconId = null; @@ -605,81 +605,81 @@ let pageStore = this.pageStoreFromTabId(tabId); if (pageStore !== null) { - let total = pageStore.perLoadAllowedRequestCount + + let total = pageStore.perLoadAllowedRequestCount + pageStore.perLoadBlockedRequestCount; - if (total) { + if (total) { let squareSize = 19; let greenSize = squareSize * - Math.sqrt(pageStore.perLoadAllowedRequestCount / total); + Math.sqrt(pageStore.perLoadAllowedRequestCount / total); iconId = greenSize < squareSize/2 ? - Math.ceil(greenSize) : - Math.floor(greenSize); - } + Math.ceil(greenSize) : + Math.floor(greenSize); + } - if (this.userSettings.iconBadgeEnabled - && pageStore.perLoadBlockedRequestCount !== 0) { + if (this.userSettings.iconBadgeEnabled + && pageStore.perLoadBlockedRequestCount !== 0) { badgeStr = - this.formatCount(pageStore.perLoadBlockedRequestCount); - } + this.formatCount(pageStore.perLoadBlockedRequestCount); + } } vAPI.setIcon(tabId, iconId, badgeStr); - }; + }; - return function (tabId) { + return function (tabId) { if (tabIdToTimer[tabId]) { - return; + return; } if (vAPI.isBehindTheSceneTabId(tabId)) { - return; + return; } tabIdToTimer[tabId] = - vAPI.setTimeout(updateBadge.bind(this, tabId), 750); - }; + vAPI.setTimeout(updateBadge.bind(this, tabId), 750); + }; })(); ηm.updateTitle = (function () { - let tabIdToTimer = Object.create(null); - let tabIdToTryCount = Object.create(null); - let delay = 499; + let tabIdToTimer = Object.create(null); + let tabIdToTryCount = Object.create(null); + let delay = 499; - let tryNoMore = function (tabId) { + let tryNoMore = function (tabId) { delete tabIdToTryCount[tabId]; - }; + }; - let tryAgain = function (tabId) { + let tryAgain = function (tabId) { let count = tabIdToTryCount[tabId]; if (count === undefined) { - return false; + return false; } if (count === 1) { - delete tabIdToTryCount[tabId]; - return false; + delete tabIdToTryCount[tabId]; + return false; } tabIdToTryCount[tabId] = count - 1; tabIdToTimer[tabId] = - vAPI.setTimeout(updateTitle.bind(ηm, tabId), delay); + vAPI.setTimeout(updateTitle.bind(ηm, tabId), delay); return true; - }; + }; - let onTabReady = function (tabId, tab) { + let onTabReady = function (tabId, tab) { if (!tab) { - return tryNoMore(tabId); + return tryNoMore(tabId); } let pageStore = this.pageStoreFromTabId(tabId); if (pageStore === null) { - return tryNoMore(tabId); + return tryNoMore(tabId); } if (!tab.title && tryAgain(tabId)) { - return; + return; } // https://github.com/gorhill/uMatrix/issues/225 @@ -688,67 +688,67 @@ pageStore.title = tab.title || tab.url || ''; this.pageStoresToken = Date.now(); if (settled || !tryAgain(tabId)) { - tryNoMore(tabId); + tryNoMore(tabId); } - }; + }; - let updateTitle = function (tabId) { + let updateTitle = function (tabId) { delete tabIdToTimer[tabId]; vAPI.tabs.get(tabId, onTabReady.bind(this, tabId)); - }; + }; - return function (tabId) { + return function (tabId) { if (vAPI.isBehindTheSceneTabId(tabId)) { - return; + return; } if (tabIdToTimer[tabId]) { - clearTimeout(tabIdToTimer[tabId]); + clearTimeout(tabIdToTimer[tabId]); } tabIdToTimer[tabId] = - vAPI.setTimeout(updateTitle.bind(this, tabId), delay); + vAPI.setTimeout(updateTitle.bind(this, tabId), delay); tabIdToTryCount[tabId] = 5; - }; + }; })(); // Stale page store entries janitor // https://github.com/chrisaljoudi/uBlock/issues/455 (function () { - let cleanupPeriod = 7 * 60 * 1000; - let cleanupSampleAt = 0; - let cleanupSampleSize = 11; + let cleanupPeriod = 7 * 60 * 1000; + let cleanupSampleAt = 0; + let cleanupSampleSize = 11; - let cleanup = function () { + let cleanup = function () { let tabIds = Object.keys(ηm.pageStores).sort(); let checkTab = function(tabId) { - vAPI.tabs.get(tabId, function (tab) { + vAPI.tabs.get(tabId, function (tab) { if (!tab) { - ηm.unbindTabFromPageStats(tabId); + ηm.unbindTabFromPageStats(tabId); } - }); + }); }; if (cleanupSampleAt >= tabIds.length) { - cleanupSampleAt = 0; + cleanupSampleAt = 0; } let tabId; let n = - Math.min(cleanupSampleAt + cleanupSampleSize, tabIds.length); + Math.min(cleanupSampleAt + cleanupSampleSize, tabIds.length); for (let i=cleanupSampleAt; i<n; i++) { - tabId = tabIds[i]; - if (vAPI.isBehindTheSceneTabId(tabId)) { + tabId = tabIds[i]; + if (vAPI.isBehindTheSceneTabId(tabId)) { continue; - } - checkTab(tabId); + } + checkTab(tabId); } cleanupSampleAt = n; vAPI.setTimeout(cleanup, cleanupPeriod); - }; + }; - vAPI.setTimeout(cleanup, cleanupPeriod); + vAPI.setTimeout(cleanup, cleanupPeriod); })(); })(); diff --git a/js/traffic.js b/js/traffic.js index aae4070..e2d6a3e 100644 --- a/js/traffic.js +++ b/js/traffic.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://notabug.org/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,8 +26,6 @@ 'use strict'; -/******************************************************************************/ - // It's just a silly, minimalist DOM framework: this allows me to not rely // on jQuery. jQuery contains way too much stuff than I need, and as per // Opera rules, I am not allowed to use a cut-down version of jQuery. So @@ -288,7 +286,8 @@ var uDom = (function () { let i = this.nodes.length; while (i--) { let cn = this.nodes[i]; - if ((p = cn.parentNode)) { + let p = cn.parentNode; + if (p) { p.removeChild(cn); } } diff --git a/js/uritools.js b/js/uritools.js index 770d54a..9ec928f 100644 --- a/js/uritools.js +++ b/js/uritools.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -37,500 +37,500 @@ Naming convention from https://en.wikipedia.org/wiki/URI_scheme#Examples ηMatrix.URI = (function() { - /******************************************************************************/ - - // Favorite regex tool: http://regex101.com/ - - // Ref: <http://tools.ietf.org/html/rfc3986#page-50> - // I removed redundant capture groups: capture less = peform faster. See - // <http://jsperf.com/old-uritools-vs-new-uritools> - // Performance improvements welcomed. - // jsperf: <http://jsperf.com/old-uritools-vs-new-uritools> - var reRFC3986 = /^([^:\/?#]+:)?(\/\/[^\/?#]*)?([^?#]*)(\?[^#]*)?(#.*)?/; - - // Derived - var reSchemeFromURI = /^[^:\/?#]+:/; - var reAuthorityFromURI = /^(?:[^:\/?#]+:)?(\/\/[^\/?#]+)/; - var reOriginFromURI = /^(?:[^:\/?#]+:)?(?:\/\/[^\/?#]+)/; - var reCommonHostnameFromURL = /^https?:\/\/([0-9a-z_][0-9a-z._-]*[0-9a-z])\//; - var rePathFromURI = /^(?:[^:\/?#]+:)?(?:\/\/[^\/?#]*)?([^?#]*)/; - var reMustNormalizeHostname = /[^0-9a-z._-]/; - - // These are to parse authority field, not parsed by above official regex - // IPv6 is seen as an exception: a non-compatible IPv6 is first tried, and - // if it fails, the IPv6 compatible regex istr used. This helps - // peformance by avoiding the use of a too complicated regex first. - - // https://github.com/gorhill/httpswitchboard/issues/211 - // "While a hostname may not contain other characters, such as the - // "underscore character (_), other DNS names may contain the underscore" - var reHostPortFromAuthority = /^(?:[^@]*@)?([^:]*)(:\d*)?$/; - var reIPv6PortFromAuthority = /^(?:[^@]*@)?(\[[0-9a-f:]*\])(:\d*)?$/i; - - var reHostFromNakedAuthority = /^[0-9a-z._-]+[0-9a-z]$/i; - var reHostFromAuthority = /^(?:[^@]*@)?([^:]+)(?::\d*)?$/; - var reIPv6FromAuthority = /^(?:[^@]*@)?(\[[0-9a-f:]+\])(?::\d*)?$/i; - - // Coarse (but fast) tests - var reValidHostname = /^([a-z\d]+(-*[a-z\d]+)*)(\.[a-z\d]+(-*[a-z\d])*)*$/; - var reIPAddressNaive = /^\d+\.\d+\.\d+\.\d+$|^\[[\da-zA-Z:]+\]$/; - - // Accurate tests - // Source.: http://stackoverflow.com/questions/5284147/validating-ipv4-addresses-with-regexp/5284410#5284410 - //var reIPv4 = /^((25[0-5]|2[0-4]\d|[01]?\d\d?)(\.|$)){4}/; - - // Source: http://forums.intermapper.com/viewtopic.php?p=1096#1096 - //var reIPv6 = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/; - - /******************************************************************************/ - - var reset = function(o) { - o.scheme = ''; - o.hostname = ''; - o._ipv4 = undefined; - o._ipv6 = undefined; - o.port = ''; - o.path = ''; - o.query = ''; - o.fragment = ''; - return o; - }; - - var resetAuthority = function(o) { - o.hostname = ''; - o._ipv4 = undefined; - o._ipv6 = undefined; - o.port = ''; - return o; - }; - - /******************************************************************************/ - - // This will be exported - - var URI = { - scheme: '', - authority: '', - hostname: '', - _ipv4: undefined, - _ipv6: undefined, - port: '', - domain: undefined, - path: '', - query: '', - fragment: '', - schemeBit: (1 << 0), - userBit: (1 << 1), - passwordBit: (1 << 2), - hostnameBit: (1 << 3), - portBit: (1 << 4), - pathBit: (1 << 5), - queryBit: (1 << 6), - fragmentBit: (1 << 7), - allBits: (0xFFFF) - }; - - URI.authorityBit = (URI.userBit | URI.passwordBit | URI.hostnameBit | URI.portBit); - URI.normalizeBits = (URI.schemeBit | URI.hostnameBit | URI.pathBit | URI.queryBit); - - /******************************************************************************/ - - // See: https://en.wikipedia.org/wiki/URI_scheme#Examples - // URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] - // - // foo://example.com:8042/over/there?name=ferret#nose - // \_/ \______________/\_________/ \_________/ \__/ - // | | | | | - // scheme authority path query fragment - // | _____________________|__ - // / \ / \ - // urn:example:animal:ferret:nose - - URI.set = function(uri) { - if ( uri === undefined ) { - return reset(URI); - } - var matches = reRFC3986.exec(uri); - if ( !matches ) { - return reset(URI); - } - this.scheme = matches[1] !== undefined ? matches[1].slice(0, -1) : ''; - this.authority = matches[2] !== undefined ? matches[2].slice(2).toLowerCase() : ''; - this.path = matches[3] !== undefined ? matches[3] : ''; - - // <http://tools.ietf.org/html/rfc3986#section-6.2.3> - // "In general, a URI that uses the generic syntax for authority - // "with an empty path should be normalized to a path of '/'." - if ( this.authority !== '' && this.path === '' ) { - this.path = '/'; - } - this.query = matches[4] !== undefined ? matches[4].slice(1) : ''; - this.fragment = matches[5] !== undefined ? matches[5].slice(1) : ''; - - // Assume very simple authority, i.e. just a hostname (highest likelihood - // case for ηMatrix) - if ( reHostFromNakedAuthority.test(this.authority) ) { - this.hostname = this.authority; - this.port = ''; - return this; - } - // Authority contains more than just a hostname - matches = reHostPortFromAuthority.exec(this.authority); - if ( !matches ) { - matches = reIPv6PortFromAuthority.exec(this.authority); - if ( !matches ) { - return resetAuthority(URI); - } - } - this.hostname = matches[1] !== undefined ? matches[1] : ''; - // http://en.wikipedia.org/wiki/FQDN - if ( this.hostname.slice(-1) === '.' ) { - this.hostname = this.hostname.slice(0, -1); - } - this.port = matches[2] !== undefined ? matches[2].slice(1) : ''; - return this; - }; - - /******************************************************************************/ - - // URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] - // - // foo://example.com:8042/over/there?name=ferret#nose - // \_/ \______________/\_________/ \_________/ \__/ - // | | | | | - // scheme authority path query fragment - // | _____________________|__ - // / \ / \ - // urn:example:animal:ferret:nose - - URI.assemble = function(bits) { - if ( bits === undefined ) { - bits = this.allBits; - } - var s = []; - if ( this.scheme && (bits & this.schemeBit) ) { - s.push(this.scheme, ':'); - } - if ( this.hostname && (bits & this.hostnameBit) ) { - s.push('//', this.hostname); - } - if ( this.port && (bits & this.portBit) ) { - s.push(':', this.port); - } - if ( this.path && (bits & this.pathBit) ) { - s.push(this.path); - } - if ( this.query && (bits & this.queryBit) ) { - s.push('?', this.query); - } - if ( this.fragment && (bits & this.fragmentBit) ) { - s.push('#', this.fragment); - } - return s.join(''); - }; +/******************************************************************************/ - /******************************************************************************/ +// Favorite regex tool: http://regex101.com/ + +// Ref: <http://tools.ietf.org/html/rfc3986#page-50> +// I removed redundant capture groups: capture less = peform faster. See +// <http://jsperf.com/old-uritools-vs-new-uritools> +// Performance improvements welcomed. +// jsperf: <http://jsperf.com/old-uritools-vs-new-uritools> +var reRFC3986 = /^([^:\/?#]+:)?(\/\/[^\/?#]*)?([^?#]*)(\?[^#]*)?(#.*)?/; + +// Derived +var reSchemeFromURI = /^[^:\/?#]+:/; +var reAuthorityFromURI = /^(?:[^:\/?#]+:)?(\/\/[^\/?#]+)/; +var reOriginFromURI = /^(?:[^:\/?#]+:)?(?:\/\/[^\/?#]+)/; +var reCommonHostnameFromURL = /^https?:\/\/([0-9a-z_][0-9a-z._-]*[0-9a-z])\//; +var rePathFromURI = /^(?:[^:\/?#]+:)?(?:\/\/[^\/?#]*)?([^?#]*)/; +var reMustNormalizeHostname = /[^0-9a-z._-]/; + +// These are to parse authority field, not parsed by above official regex +// IPv6 is seen as an exception: a non-compatible IPv6 is first tried, and +// if it fails, the IPv6 compatible regex istr used. This helps +// peformance by avoiding the use of a too complicated regex first. + +// https://github.com/gorhill/httpswitchboard/issues/211 +// "While a hostname may not contain other characters, such as the +// "underscore character (_), other DNS names may contain the underscore" +var reHostPortFromAuthority = /^(?:[^@]*@)?([^:]*)(:\d*)?$/; +var reIPv6PortFromAuthority = /^(?:[^@]*@)?(\[[0-9a-f:]*\])(:\d*)?$/i; + +var reHostFromNakedAuthority = /^[0-9a-z._-]+[0-9a-z]$/i; +var reHostFromAuthority = /^(?:[^@]*@)?([^:]+)(?::\d*)?$/; +var reIPv6FromAuthority = /^(?:[^@]*@)?(\[[0-9a-f:]+\])(?::\d*)?$/i; + +// Coarse (but fast) tests +var reValidHostname = /^([a-z\d]+(-*[a-z\d]+)*)(\.[a-z\d]+(-*[a-z\d])*)*$/; +var reIPAddressNaive = /^\d+\.\d+\.\d+\.\d+$|^\[[\da-zA-Z:]+\]$/; + +// Accurate tests +// Source.: http://stackoverflow.com/questions/5284147/validating-ipv4-addresses-with-regexp/5284410#5284410 +//var reIPv4 = /^((25[0-5]|2[0-4]\d|[01]?\d\d?)(\.|$)){4}/; + +// Source: http://forums.intermapper.com/viewtopic.php?p=1096#1096 +//var reIPv6 = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/; - URI.originFromURI = function(uri) { - var matches = reOriginFromURI.exec(uri); - return matches !== null ? matches[0].toLowerCase() : ''; - }; +/******************************************************************************/ - /******************************************************************************/ +var reset = function(o) { + o.scheme = ''; + o.hostname = ''; + o._ipv4 = undefined; + o._ipv6 = undefined; + o.port = ''; + o.path = ''; + o.query = ''; + o.fragment = ''; + return o; +}; + +var resetAuthority = function(o) { + o.hostname = ''; + o._ipv4 = undefined; + o._ipv6 = undefined; + o.port = ''; + return o; +}; - URI.schemeFromURI = function(uri) { - var matches = reSchemeFromURI.exec(uri); - if ( matches === null ) { - return ''; - } - return matches[0].slice(0, -1).toLowerCase(); - }; +/******************************************************************************/ - /******************************************************************************/ +// This will be exported + +var URI = { + scheme: '', + authority: '', + hostname: '', + _ipv4: undefined, + _ipv6: undefined, + port: '', + domain: undefined, + path: '', + query: '', + fragment: '', + schemeBit: (1 << 0), + userBit: (1 << 1), + passwordBit: (1 << 2), + hostnameBit: (1 << 3), + portBit: (1 << 4), + pathBit: (1 << 5), + queryBit: (1 << 6), + fragmentBit: (1 << 7), + allBits: (0xFFFF) +}; + +URI.authorityBit = (URI.userBit | URI.passwordBit | URI.hostnameBit | URI.portBit); +URI.normalizeBits = (URI.schemeBit | URI.hostnameBit | URI.pathBit | URI.queryBit); - URI.isNetworkScheme = function(scheme) { - return this.reNetworkScheme.test(scheme); - }; +/******************************************************************************/ - URI.reNetworkScheme = /^(?:https?|wss?|ftps?)\b/; +// See: https://en.wikipedia.org/wiki/URI_scheme#Examples +// URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] +// +// foo://example.com:8042/over/there?name=ferret#nose +// \_/ \______________/\_________/ \_________/ \__/ +// | | | | | +// scheme authority path query fragment +// | _____________________|__ +// / \ / \ +// urn:example:animal:ferret:nose + +URI.set = function(uri) { + if ( uri === undefined ) { + return reset(URI); + } + var matches = reRFC3986.exec(uri); + if ( !matches ) { + return reset(URI); + } + this.scheme = matches[1] !== undefined ? matches[1].slice(0, -1) : ''; + this.authority = matches[2] !== undefined ? matches[2].slice(2).toLowerCase() : ''; + this.path = matches[3] !== undefined ? matches[3] : ''; + + // <http://tools.ietf.org/html/rfc3986#section-6.2.3> + // "In general, a URI that uses the generic syntax for authority + // "with an empty path should be normalized to a path of '/'." + if ( this.authority !== '' && this.path === '' ) { + this.path = '/'; + } + this.query = matches[4] !== undefined ? matches[4].slice(1) : ''; + this.fragment = matches[5] !== undefined ? matches[5].slice(1) : ''; + + // Assume very simple authority, i.e. just a hostname (highest likelihood + // case for ηMatrix) + if ( reHostFromNakedAuthority.test(this.authority) ) { + this.hostname = this.authority; + this.port = ''; + return this; + } + // Authority contains more than just a hostname + matches = reHostPortFromAuthority.exec(this.authority); + if ( !matches ) { + matches = reIPv6PortFromAuthority.exec(this.authority); + if ( !matches ) { + return resetAuthority(URI); + } + } + this.hostname = matches[1] !== undefined ? matches[1] : ''; + // http://en.wikipedia.org/wiki/FQDN + if ( this.hostname.slice(-1) === '.' ) { + this.hostname = this.hostname.slice(0, -1); + } + this.port = matches[2] !== undefined ? matches[2].slice(1) : ''; + return this; +}; - /******************************************************************************/ +/******************************************************************************/ - URI.isSecureScheme = function(scheme) { - return this.reSecureScheme.test(scheme); - }; +// URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] +// +// foo://example.com:8042/over/there?name=ferret#nose +// \_/ \______________/\_________/ \_________/ \__/ +// | | | | | +// scheme authority path query fragment +// | _____________________|__ +// / \ / \ +// urn:example:animal:ferret:nose + +URI.assemble = function(bits) { + if ( bits === undefined ) { + bits = this.allBits; + } + var s = []; + if ( this.scheme && (bits & this.schemeBit) ) { + s.push(this.scheme, ':'); + } + if ( this.hostname && (bits & this.hostnameBit) ) { + s.push('//', this.hostname); + } + if ( this.port && (bits & this.portBit) ) { + s.push(':', this.port); + } + if ( this.path && (bits & this.pathBit) ) { + s.push(this.path); + } + if ( this.query && (bits & this.queryBit) ) { + s.push('?', this.query); + } + if ( this.fragment && (bits & this.fragmentBit) ) { + s.push('#', this.fragment); + } + return s.join(''); +}; - URI.reSecureScheme = /^(?:https|wss|ftps)\b/; +/******************************************************************************/ - /******************************************************************************/ +URI.originFromURI = function(uri) { + var matches = reOriginFromURI.exec(uri); + return matches !== null ? matches[0].toLowerCase() : ''; +}; - URI.authorityFromURI = function(uri) { - var matches = reAuthorityFromURI.exec(uri); - if ( !matches ) { - return ''; - } - return matches[1].slice(2).toLowerCase(); - }; +/******************************************************************************/ - /******************************************************************************/ +URI.schemeFromURI = function(uri) { + var matches = reSchemeFromURI.exec(uri); + if ( matches === null ) { + return ''; + } + return matches[0].slice(0, -1).toLowerCase(); +}; - // The most used function, so it better be fast. +/******************************************************************************/ - // https://github.com/gorhill/uBlock/issues/1559 - // See http://en.wikipedia.org/wiki/FQDN - // https://bugzilla.mozilla.org/show_bug.cgi?id=1360285 - // Revisit punycode dependency when above issue is fixed in Firefox. +URI.isNetworkScheme = function(scheme) { + return this.reNetworkScheme.test(scheme); +}; - URI.hostnameFromURI = function(uri) { - var matches = reCommonHostnameFromURL.exec(uri); - if ( matches !== null ) { return matches[1]; } - matches = reAuthorityFromURI.exec(uri); - if ( matches === null ) { return ''; } - var authority = matches[1].slice(2); - // Assume very simple authority (most common case for ηBlock) - if ( reHostFromNakedAuthority.test(authority) ) { - return authority.toLowerCase(); - } - matches = reHostFromAuthority.exec(authority); - if ( matches === null ) { - matches = reIPv6FromAuthority.exec(authority); - if ( matches === null ) { return ''; } - } - var hostname = matches[1]; - while ( hostname.endsWith('.') ) { - hostname = hostname.slice(0, -1); - } - if ( reMustNormalizeHostname.test(hostname) ) { - hostname = punycode.toASCII(hostname.toLowerCase()); - } - return hostname; - }; +URI.reNetworkScheme = /^(?:https?|wss?|ftps?)\b/; - /******************************************************************************/ +/******************************************************************************/ - URI.domainFromHostname = function(hostname) { - // Try to skip looking up the PSL database - var entry = domainCache.get(hostname); - if ( entry !== undefined ) { - entry.tstamp = Date.now(); - return entry.domain; - } - // Meh.. will have to search it - if ( reIPAddressNaive.test(hostname) === false ) { - return domainCacheAdd(hostname, psl.getDomain(hostname)); - } - return domainCacheAdd(hostname, hostname); - }; +URI.isSecureScheme = function(scheme) { + return this.reSecureScheme.test(scheme); +}; - URI.domain = function() { - return this.domainFromHostname(this.hostname); - }; +URI.reSecureScheme = /^(?:https|wss|ftps)\b/; - // It is expected that there is higher-scoped `publicSuffixList` lingering - // somewhere. Cache it. See <https://github.com/gorhill/publicsuffixlist.js>. - var psl = publicSuffixList; +/******************************************************************************/ - /******************************************************************************/ +URI.authorityFromURI = function(uri) { + var matches = reAuthorityFromURI.exec(uri); + if ( !matches ) { + return ''; + } + return matches[1].slice(2).toLowerCase(); +}; - URI.pathFromURI = function(uri) { - var matches = rePathFromURI.exec(uri); - return matches !== null ? matches[1] : ''; - }; +/******************************************************************************/ - /******************************************************************************/ +// The most used function, so it better be fast. + +// https://github.com/gorhill/uBlock/issues/1559 +// See http://en.wikipedia.org/wiki/FQDN +// https://bugzilla.mozilla.org/show_bug.cgi?id=1360285 +// Revisit punycode dependency when above issue is fixed in Firefox. + +URI.hostnameFromURI = function(uri) { + var matches = reCommonHostnameFromURL.exec(uri); + if ( matches !== null ) { return matches[1]; } + matches = reAuthorityFromURI.exec(uri); + if ( matches === null ) { return ''; } + var authority = matches[1].slice(2); + // Assume very simple authority (most common case for ηBlock) + if ( reHostFromNakedAuthority.test(authority) ) { + return authority.toLowerCase(); + } + matches = reHostFromAuthority.exec(authority); + if ( matches === null ) { + matches = reIPv6FromAuthority.exec(authority); + if ( matches === null ) { return ''; } + } + var hostname = matches[1]; + while ( hostname.endsWith('.') ) { + hostname = hostname.slice(0, -1); + } + if ( reMustNormalizeHostname.test(hostname) ) { + hostname = punycode.toASCII(hostname.toLowerCase()); + } + return hostname; +}; - // Trying to alleviate the worries of looking up too often the domain name from - // a hostname. With a cache, uBlock benefits given that it deals with a - // specific set of hostnames within a narrow time span -- in other words, I - // believe probability of cache hit are high in uBlock. +/******************************************************************************/ - var domainCache = new Map(); - var domainCacheCountLowWaterMark = 75; - var domainCacheCountHighWaterMark = 100; - var domainCacheEntryJunkyard = []; - var domainCacheEntryJunkyardMax = domainCacheCountHighWaterMark - domainCacheCountLowWaterMark; +URI.domainFromHostname = function(hostname) { + // Try to skip looking up the PSL database + var entry = domainCache.get(hostname); + if ( entry !== undefined ) { + entry.tstamp = Date.now(); + return entry.domain; + } + // Meh.. will have to search it + if ( reIPAddressNaive.test(hostname) === false ) { + return domainCacheAdd(hostname, psl.getDomain(hostname)); + } + return domainCacheAdd(hostname, hostname); +}; + +URI.domain = function() { + return this.domainFromHostname(this.hostname); +}; + +// It is expected that there is higher-scoped `publicSuffixList` lingering +// somewhere. Cache it. See <https://github.com/gorhill/publicsuffixlist.js>. +var psl = publicSuffixList; - var DomainCacheEntry = function(domain) { - this.init(domain); - }; +/******************************************************************************/ - DomainCacheEntry.prototype.init = function(domain) { - this.domain = domain; - this.tstamp = Date.now(); - return this; - }; +URI.pathFromURI = function(uri) { + var matches = rePathFromURI.exec(uri); + return matches !== null ? matches[1] : ''; +}; - DomainCacheEntry.prototype.dispose = function() { - this.domain = ''; - if ( domainCacheEntryJunkyard.length < domainCacheEntryJunkyardMax ) { - domainCacheEntryJunkyard.push(this); - } - }; +/******************************************************************************/ - var domainCacheEntryFactory = function(domain) { - var entry = domainCacheEntryJunkyard.pop(); - if ( entry ) { - return entry.init(domain); - } - return new DomainCacheEntry(domain); - }; - - var domainCacheAdd = function(hostname, domain) { - var entry = domainCache.get(hostname); - if ( entry !== undefined ) { - entry.tstamp = Date.now(); - } else { - domainCache.set(hostname, domainCacheEntryFactory(domain)); - if ( domainCache.size === domainCacheCountHighWaterMark ) { - domainCachePrune(); - } - } - return domain; - }; - - var domainCacheEntrySort = function(a, b) { - return domainCache.get(b).tstamp - domainCache.get(a).tstamp; - }; - - var domainCachePrune = function() { - var hostnames = Array.from(domainCache.keys()) - .sort(domainCacheEntrySort) - .slice(domainCacheCountLowWaterMark); - var i = hostnames.length; - var hostname; - while ( i-- ) { - hostname = hostnames[i]; - domainCache.get(hostname).dispose(); - domainCache.delete(hostname); - } - }; + // Trying to alleviate the worries of looking up too often the domain name from +// a hostname. With a cache, uBlock benefits given that it deals with a +// specific set of hostnames within a narrow time span -- in other words, I +// believe probability of cache hit are high in uBlock. + +var domainCache = new Map(); +var domainCacheCountLowWaterMark = 75; +var domainCacheCountHighWaterMark = 100; +var domainCacheEntryJunkyard = []; +var domainCacheEntryJunkyardMax = domainCacheCountHighWaterMark - domainCacheCountLowWaterMark; + +var DomainCacheEntry = function(domain) { + this.init(domain); +}; + +DomainCacheEntry.prototype.init = function(domain) { + this.domain = domain; + this.tstamp = Date.now(); + return this; +}; + +DomainCacheEntry.prototype.dispose = function() { + this.domain = ''; + if ( domainCacheEntryJunkyard.length < domainCacheEntryJunkyardMax ) { + domainCacheEntryJunkyard.push(this); + } +}; + +var domainCacheEntryFactory = function(domain) { + var entry = domainCacheEntryJunkyard.pop(); + if ( entry ) { + return entry.init(domain); + } + return new DomainCacheEntry(domain); +}; + +var domainCacheAdd = function(hostname, domain) { + var entry = domainCache.get(hostname); + if ( entry !== undefined ) { + entry.tstamp = Date.now(); + } else { + domainCache.set(hostname, domainCacheEntryFactory(domain)); + if ( domainCache.size === domainCacheCountHighWaterMark ) { + domainCachePrune(); + } + } + return domain; +}; + +var domainCacheEntrySort = function(a, b) { + return domainCache.get(b).tstamp - domainCache.get(a).tstamp; +}; + +var domainCachePrune = function() { + var hostnames = Array.from(domainCache.keys()) + .sort(domainCacheEntrySort) + .slice(domainCacheCountLowWaterMark); + var i = hostnames.length; + var hostname; + while ( i-- ) { + hostname = hostnames[i]; + domainCache.get(hostname).dispose(); + domainCache.delete(hostname); + } +}; + +var domainCacheReset = function() { + domainCache.clear(); +}; + +psl.onChanged.addListener(domainCacheReset); - var domainCacheReset = function() { - domainCache.clear(); - }; +/******************************************************************************/ - psl.onChanged.addListener(domainCacheReset); +URI.domainFromURI = function(uri) { + if ( !uri ) { + return ''; + } + return this.domainFromHostname(this.hostnameFromURI(uri)); +}; - /******************************************************************************/ +/******************************************************************************/ - URI.domainFromURI = function(uri) { - if ( !uri ) { - return ''; - } - return this.domainFromHostname(this.hostnameFromURI(uri)); - }; +// Normalize the way ηMatrix expects it - /******************************************************************************/ +URI.normalizedURI = function() { + // Will be removed: + // - port + // - user id/password + // - fragment + return this.assemble(this.normalizeBits); +}; - // Normalize the way ηMatrix expects it +/******************************************************************************/ - URI.normalizedURI = function() { - // Will be removed: - // - port - // - user id/password - // - fragment - return this.assemble(this.normalizeBits); - }; +URI.rootURL = function() { + if ( !this.hostname ) { + return ''; + } + return this.assemble(this.schemeBit | this.hostnameBit); +}; - /******************************************************************************/ +/******************************************************************************/ - URI.rootURL = function() { - if ( !this.hostname ) { - return ''; - } - return this.assemble(this.schemeBit | this.hostnameBit); - }; +URI.isValidHostname = function(hostname) { + var r; + try { + r = reValidHostname.test(hostname); + } + catch (e) { + return false; + } + return r; +}; - /******************************************************************************/ +/******************************************************************************/ - URI.isValidHostname = function(hostname) { - var r; - try { - r = reValidHostname.test(hostname); - } - catch (e) { - return false; - } - return r; - }; - - /******************************************************************************/ - - // Return the parent domain. For IP address, there is no parent domain. - - URI.parentHostnameFromHostname = function(hostname) { - // `locahost` => `` - // `example.org` => `example.org` - // `www.example.org` => `example.org` - // `tomato.www.example.org` => `example.org` - var domain = this.domainFromHostname(hostname); - - // `locahost` === `` => bye - // `example.org` === `example.org` => bye - // `www.example.org` !== `example.org` => stay - // `tomato.www.example.org` !== `example.org` => stay - if ( domain === '' || domain === hostname ) { - return undefined; - } +// Return the parent domain. For IP address, there is no parent domain. - // Parent is hostname minus first label - return hostname.slice(hostname.indexOf('.') + 1); - }; +URI.parentHostnameFromHostname = function(hostname) { + // `locahost` => `` + // `example.org` => `example.org` + // `www.example.org` => `example.org` + // `tomato.www.example.org` => `example.org` + var domain = this.domainFromHostname(hostname); - /******************************************************************************/ + // `locahost` === `` => bye + // `example.org` === `example.org` => bye + // `www.example.org` !== `example.org` => stay + // `tomato.www.example.org` !== `example.org` => stay + if ( domain === '' || domain === hostname ) { + return undefined; + } - // Return all possible parent hostnames which can be derived from `hostname`, - // ordered from direct parent up to domain inclusively. + // Parent is hostname minus first label + return hostname.slice(hostname.indexOf('.') + 1); +}; - URI.parentHostnamesFromHostname = function(hostname) { - // TODO: I should create an object which is optimized to receive - // the list of hostnames by making it reusable (junkyard etc.) and which - // has its own element counter property in order to avoid memory - // alloc/dealloc. - var domain = this.domainFromHostname(hostname); - if ( domain === '' || domain === hostname ) { - return []; - } - var nodes = []; - var pos; - for (;;) { - pos = hostname.indexOf('.'); - if ( pos < 0 ) { - break; - } - hostname = hostname.slice(pos + 1); - nodes.push(hostname); - if ( hostname === domain ) { - break; - } - } - return nodes; - }; +/******************************************************************************/ + +// Return all possible parent hostnames which can be derived from `hostname`, +// ordered from direct parent up to domain inclusively. + +URI.parentHostnamesFromHostname = function(hostname) { + // TODO: I should create an object which is optimized to receive + // the list of hostnames by making it reusable (junkyard etc.) and which + // has its own element counter property in order to avoid memory + // alloc/dealloc. + var domain = this.domainFromHostname(hostname); + if ( domain === '' || domain === hostname ) { + return []; + } + var nodes = []; + var pos; + for (;;) { + pos = hostname.indexOf('.'); + if ( pos < 0 ) { + break; + } + hostname = hostname.slice(pos + 1); + nodes.push(hostname); + if ( hostname === domain ) { + break; + } + } + return nodes; +}; - /******************************************************************************/ +/******************************************************************************/ - // Return all possible hostnames which can be derived from `hostname`, - // ordered from self up to domain inclusively. +// Return all possible hostnames which can be derived from `hostname`, +// ordered from self up to domain inclusively. - URI.allHostnamesFromHostname = function(hostname) { - var nodes = this.parentHostnamesFromHostname(hostname); - nodes.unshift(hostname); - return nodes; - }; +URI.allHostnamesFromHostname = function(hostname) { + var nodes = this.parentHostnamesFromHostname(hostname); + nodes.unshift(hostname); + return nodes; +}; - /******************************************************************************/ +/******************************************************************************/ - URI.toString = function() { - return this.assemble(); - }; +URI.toString = function() { + return this.assemble(); +}; - /******************************************************************************/ +/******************************************************************************/ - // Export +// Export - return URI; +return URI; - /******************************************************************************/ +/******************************************************************************/ })(); diff --git a/js/user-rules.js b/js/user-rules.js index ccd15c2..b8933b0 100644 --- a/js/user-rules.js +++ b/js/user-rules.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -27,303 +27,303 @@ // Switches before, rules after let directiveSort = function (a, b) { - let aIsSwitch = a.indexOf(':') !== -1; - let bIsSwitch = b.indexOf(':') !== -1; + let aIsSwitch = a.indexOf(':') !== -1; + let bIsSwitch = b.indexOf(':') !== -1; - if (aIsSwitch === bIsSwitch) { + if (aIsSwitch === bIsSwitch) { return a.localeCompare(b); - } + } - return aIsSwitch ? -1 : 1; + return aIsSwitch ? -1 : 1; }; let processUserRules = function (response) { - let allRules = {}; - let permanentRules = {}; - let temporaryRules = {}; + let allRules = {}; + let permanentRules = {}; + let temporaryRules = {}; - let rules = response.permanentRules.split(/\n+/); - for (let i=rules.length-1; i>=0; --i) { + let rules = response.permanentRules.split(/\n+/); + for (let i=rules.length-1; i>=0; --i) { let rule = rules[i].trim(); if (rule.length !== 0) { - permanentRules[rule] = allRules[rule] = true; + permanentRules[rule] = allRules[rule] = true; } - } + } - rules = response.temporaryRules.split(/\n+/); - for (let i=rules.length-1; i>=0; --i) { + rules = response.temporaryRules.split(/\n+/); + for (let i=rules.length-1; i>=0; --i) { let rule = rules[i].trim(); if (rule.length !== 0) { - temporaryRules[rule] = allRules[rule] = true; + temporaryRules[rule] = allRules[rule] = true; } - } + } - let permanentList = document.createDocumentFragment(); + let permanentList = document.createDocumentFragment(); let temporaryList = document.createDocumentFragment(); let li; - rules = Object.keys(allRules).sort(directiveSort); - for (let i=0; i<rules.length; ++i) { + rules = Object.keys(allRules).sort(directiveSort); + for (let i=0; i<rules.length; ++i) { let rule = rules[i]; let onLeft = permanentRules.hasOwnProperty(rule); let onRight = temporaryRules.hasOwnProperty(rule); - li = document.createElement('li'); + li = document.createElement('li'); if (onLeft && onRight) { - li.textContent = rule; - permanentList.appendChild(li); - li = document.createElement('li'); - li.textContent = rule; - temporaryList.appendChild(li); + li.textContent = rule; + permanentList.appendChild(li); + li = document.createElement('li'); + li.textContent = rule; + temporaryList.appendChild(li); } else if (onLeft) { - li.textContent = rule; - permanentList.appendChild(li); - li = document.createElement('li'); - li.textContent = rule; - li.className = 'notRight toRemove'; - temporaryList.appendChild(li); + li.textContent = rule; + permanentList.appendChild(li); + li = document.createElement('li'); + li.textContent = rule; + li.className = 'notRight toRemove'; + temporaryList.appendChild(li); } else if (onRight) { - li.textContent = '\xA0'; - permanentList.appendChild(li); - li = document.createElement('li'); - li.textContent = rule; - li.className = 'notLeft'; - temporaryList.appendChild(li); + li.textContent = '\xA0'; + permanentList.appendChild(li); + li = document.createElement('li'); + li.textContent = rule; + li.className = 'notLeft'; + temporaryList.appendChild(li); } - } + } - // TODO: build incrementally. + // TODO: build incrementally. - uDom('#diff > .left > ul > li').remove(); - document.querySelector('#diff > .left > ul').appendChild(permanentList); - uDom('#diff > .right > ul > li').remove(); - document.querySelector('#diff > .right > ul').appendChild(temporaryList); - uDom('#diff') - .toggleClass('dirty', - response.temporaryRules !== response.permanentRules); + uDom('#diff > .left > ul > li').remove(); + document.querySelector('#diff > .left > ul').appendChild(permanentList); + uDom('#diff > .right > ul > li').remove(); + document.querySelector('#diff > .right > ul').appendChild(temporaryList); + uDom('#diff') + .toggleClass('dirty', + response.temporaryRules !== response.permanentRules); }; // https://github.com/chrisaljoudi/uBlock/issues/757 // Support RequestPolicy rule syntax let fromRequestPolicy = function (content) { - let matches = /\[origins-to-destinations\]([^\[]+)/.exec(content); - if (matches === null || matches.length !== 2) { + let matches = /\[origins-to-destinations\]([^\[]+)/.exec(content); + if (matches === null || matches.length !== 2) { return; - } - return matches[1].trim() + } + return matches[1].trim() .replace(/\|/g, ' ') .replace(/\n/g, ' * allow\n'); }; // https://github.com/gorhill/uMatrix/issues/270 let fromNoScript = function (content) { - let noscript = null; + let noscript = null; - try { + try { noscript = JSON.parse(content); - } catch (e) { - } - - if (noscript === null - || typeof noscript !== 'object' - || typeof noscript.prefs !== 'object' - || typeof noscript.prefs.clearClick === 'undefined' - || typeof noscript.whitelist !== 'string' - || typeof noscript.V !== 'string') { + } catch (e) { + } + + if (noscript === null + || typeof noscript !== 'object' + || typeof noscript.prefs !== 'object' + || typeof noscript.prefs.clearClick === 'undefined' + || typeof noscript.whitelist !== 'string' + || typeof noscript.V !== 'string') { return; - } + } - let out = new Set(); - let reBad = /[a-z]+:\w*$/; - let reURL = /[a-z]+:\/\/([0-9a-z.-]+)/; - let directives = noscript.whitelist.split(/\s+/); + let out = new Set(); + let reBad = /[a-z]+:\w*$/; + let reURL = /[a-z]+:\/\/([0-9a-z.-]+)/; + let directives = noscript.whitelist.split(/\s+/); - for (let i=directives.length-1; i>=0; --i) { + for (let i=directives.length-1; i>=0; --i) { let directive = directives[i].trim(); if (directive === '') { - continue; + continue; } if (reBad.test(directive)) { - continue; + continue; } let matches = reURL.exec(directive); if (matches !== null) { - directive = matches[1]; + directive = matches[1]; } out.add('* ' + directive + ' * allow'); out.add('* ' + directive + ' script allow'); out.add('* ' + directive + ' frame allow'); - } + } - return Array.from(out).join('\n'); + return Array.from(out).join('\n'); }; let handleImportFilePicker = function () { - let fileReaderOnLoadHandler = function () { + let fileReaderOnLoadHandler = function () { if (typeof this.result !== 'string' || this.result === '') { - return; + return; } let result = fromRequestPolicy(this.result); if (result === undefined) { - result = fromNoScript(this.result); - if (result === undefined) { + result = fromNoScript(this.result); + if (result === undefined) { result = this.result; - } + } } if (this.result === '') { - return; - } + return; + } let request = { - 'what': 'setUserRules', - 'temporaryRules': rulesFromHTML('#diff .right li') - + '\n' + result, + 'what': 'setUserRules', + 'temporaryRules': rulesFromHTML('#diff .right li') + + '\n' + result, }; vAPI.messaging.send('user-rules.js', request, processUserRules); - }; + }; - var file = this.files[0]; - if (file === undefined || file.name === '') { + var file = this.files[0]; + if (file === undefined || file.name === '') { return; - } + } - if (file.type.indexOf('text') !== 0 - && file.type !== 'application/json') { + if (file.type.indexOf('text') !== 0 + && file.type !== 'application/json') { return; - } + } - let fr = new FileReader(); - fr.onload = fileReaderOnLoadHandler; - fr.readAsText(file); + let fr = new FileReader(); + fr.onload = fileReaderOnLoadHandler; + fr.readAsText(file); }; let startImportFilePicker = function () { - let input = document.getElementById('importFilePicker'); - // Reset to empty string, this will ensure an change event is properly - // triggered if the user pick a file, even if it is the same as the last - // one picked. - input.value = ''; - input.click(); + let input = document.getElementById('importFilePicker'); + // Reset to empty string, this will ensure an change event is properly + // triggered if the user pick a file, even if it is the same as the last + // one picked. + input.value = ''; + input.click(); }; function exportUserRulesToFile() { - vAPI.download({ + vAPI.download({ 'url': 'data:text/plain,' - + encodeURIComponent(rulesFromHTML('#diff .left li') + '\n'), + + encodeURIComponent(rulesFromHTML('#diff .left li') + '\n'), 'filename': uDom('[data-i18n="userRulesDefaultFileName"]').text(), - }); + }); } var rulesFromHTML = function(selector) { - let rules = []; - let lis = uDom(selector); + let rules = []; + let lis = uDom(selector); - for (let i=0; i<lis.length; ++i) { + for (let i=0; i<lis.length; ++i) { let li = lis.at(i); if (li.hasClassName('toRemove')) { - rules.push(''); + rules.push(''); } else { - rules.push(li.text()); + rules.push(li.text()); } - } + } - return rules.join('\n'); + return rules.join('\n'); }; let revertHandler = function () { - let request = { + let request = { 'what': 'setUserRules', 'temporaryRules': rulesFromHTML('#diff .left li'), - }; + }; - vAPI.messaging.send('user-rules.js', request, processUserRules); + vAPI.messaging.send('user-rules.js', request, processUserRules); }; let commitHandler = function () { - var request = { + var request = { 'what': 'setUserRules', 'permanentRules': rulesFromHTML('#diff .right li'), - }; + }; - vAPI.messaging.send('user-rules.js', request, processUserRules); + vAPI.messaging.send('user-rules.js', request, processUserRules); }; let editStartHandler = function () { - uDom('#diff .right textarea').val(rulesFromHTML('#diff .right li')); - let parent = uDom(this).ancestors('#diff'); - parent.toggleClass('edit', true); + uDom('#diff .right textarea').val(rulesFromHTML('#diff .right li')); + let parent = uDom(this).ancestors('#diff'); + parent.toggleClass('edit', true); }; let editStopHandler = function () { - let parent = uDom(this).ancestors('#diff'); - parent.toggleClass('edit', false); + let parent = uDom(this).ancestors('#diff'); + parent.toggleClass('edit', false); - let request = { + let request = { 'what': 'setUserRules', 'temporaryRules': uDom('#diff .right textarea').val(), - }; + }; - vAPI.messaging.send('user-rules.js', request, processUserRules); + vAPI.messaging.send('user-rules.js', request, processUserRules); }; let editCancelHandler = function () { - let parent = uDom(this).ancestors('#diff'); - parent.toggleClass('edit', false); + let parent = uDom(this).ancestors('#diff'); + parent.toggleClass('edit', false); }; let temporaryRulesToggler = function() { - var li = uDom(this); - li.toggleClass('toRemove'); + var li = uDom(this); + li.toggleClass('toRemove'); - let request = { + let request = { 'what': 'setUserRules', 'temporaryRules': rulesFromHTML('#diff .right li'), - }; + }; - vAPI.messaging.send('user-rules.js', request, processUserRules); + vAPI.messaging.send('user-rules.js', request, processUserRules); }; self.cloud.onPush = function () { - return rulesFromHTML('#diff .left li'); + return rulesFromHTML('#diff .left li'); }; self.cloud.onPull = function (data, append) { - if (typeof data !== 'string') { - return; - } + if (typeof data !== 'string') { + return; + } - if (append) { + if (append) { data = rulesFromHTML('#diff .right li') + '\n' + data; - } + } - let request = { + let request = { 'what': 'setUserRules', 'temporaryRules': data, - }; + }; - vAPI.messaging.send('user-rules.js', request, processUserRules); + vAPI.messaging.send('user-rules.js', request, processUserRules); }; uDom.onLoad(function () { - // Handle user interaction - uDom('#importButton').on('click', startImportFilePicker); - uDom('#importFilePicker').on('change', handleImportFilePicker); - uDom('#exportButton').on('click', exportUserRulesToFile); - uDom('#revertButton').on('click', revertHandler); - uDom('#commitButton').on('click', commitHandler); - uDom('#editEnterButton').on('click', editStartHandler); - uDom('#editStopButton').on('click', editStopHandler); - uDom('#editCancelButton').on('click', editCancelHandler); - uDom('#diff > .right > ul').on('click', 'li', temporaryRulesToggler); - - vAPI.messaging.send('user-rules.js', { - what: 'getUserRules', - }, processUserRules); + // Handle user interaction + uDom('#importButton').on('click', startImportFilePicker); + uDom('#importFilePicker').on('change', handleImportFilePicker); + uDom('#exportButton').on('click', exportUserRulesToFile); + uDom('#revertButton').on('click', revertHandler); + uDom('#commitButton').on('click', commitHandler); + uDom('#editEnterButton').on('click', editStartHandler); + uDom('#editStopButton').on('click', editStopHandler); + uDom('#editCancelButton').on('click', editCancelHandler); + uDom('#diff > .right > ul').on('click', 'li', temporaryRulesToggler); + + vAPI.messaging.send('user-rules.js', { + what: 'getUserRules', + }, processUserRules); }); })(); diff --git a/js/usersettings.js b/js/usersettings.js index 2dffa5e..0125e10 100644 --- a/js/usersettings.js +++ b/js/usersettings.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ diff --git a/js/utils.js b/js/utils.js index be6ed9c..d545e28 100644 --- a/js/utils.js +++ b/js/utils.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ diff --git a/js/vapi-background.js b/js/vapi-background.js index ff64178..2e79839 100644 --- a/js/vapi-background.js +++ b/js/vapi-background.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -38,53 +38,53 @@ // Icon-related stuff vAPI.setIcon = function (tabId, iconId, badge) { - // If badge is undefined, then setIcon was called from the - // TabSelect event - let win; - if (badge === undefined) { + // If badge is undefined, then setIcon was called from the + // TabSelect event + let win; + if (badge === undefined) { win = iconId; - } else { + } else { win = vAPI.window.getCurrentWindow(); - } + } - let tabBrowser = vAPI.browser.getTabBrowser(win); - if (tabBrowser === null) { + let tabBrowser = vAPI.browser.getTabBrowser(win); + if (tabBrowser === null) { return; - } + } - let curTabId = vAPI.tabs.manager.tabIdFromTarget(tabBrowser.selectedTab); - let tb = vAPI.toolbarButton; + let curTabId = vAPI.tabs.manager.tabIdFromTarget(tabBrowser.selectedTab); + let tb = vAPI.toolbarButton; - // from 'TabSelect' event - if (tabId === undefined) { + // from 'TabSelect' event + if (tabId === undefined) { tabId = curTabId; - } else if (badge !== undefined) { + } else if (badge !== undefined) { tb.tabs[tabId] = { - badge: badge, img: iconId - }; - } + badge: badge, img: iconId + }; + } - if (tabId === curTabId) { + if (tabId === curTabId) { tb.updateState(win, tabId); - } + } }; vAPI.httpObserver = { - classDescription: 'net-channel-event-sinks for ' + location.host, - classID: Components.ID('{5d2e2797-6d68-42e2-8aeb-81ce6ba16b95}'), - contractID: '@' + location.host + '/net-channel-event-sinks;1', - REQDATAKEY: location.host + 'reqdata', - ABORT: Components.results.NS_BINDING_ABORTED, - ACCEPT: Components.results.NS_SUCCEEDED, - // Request types: - // https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIContentPolicy#Constants - // eMatrix: we can just use nsIContentPolicy's built-in - // constants, can we? - frameTypeMap: { + classDescription: 'net-channel-event-sinks for ' + location.host, + classID: Components.ID('{5d2e2797-6d68-42e2-8aeb-81ce6ba16b95}'), + contractID: '@' + location.host + '/net-channel-event-sinks;1', + REQDATAKEY: location.host + 'reqdata', + ABORT: Components.results.NS_BINDING_ABORTED, + ACCEPT: Components.results.NS_SUCCEEDED, + // Request types: + // https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIContentPolicy#Constants + // eMatrix: we can just use nsIContentPolicy's built-in + // constants, can we? + frameTypeMap: { 6: 'main_frame', 7: 'sub_frame' - }, - typeMap: { + }, + typeMap: { 1: 'other', 2: 'script', 3: 'image', @@ -106,434 +106,434 @@ 20: 'xmlhttprequest', 21: 'imageset', 22: 'web_manifest' - }, - mimeTypeMap: { + }, + mimeTypeMap: { 'audio': 15, 'video': 15 - }, - get componentRegistrar () { + }, + get componentRegistrar () { return Components.manager.QueryInterface(Ci.nsIComponentRegistrar); - }, - get categoryManager () { + }, + get categoryManager () { return Cc['@mozilla.org/categorymanager;1'] .getService(Ci.nsICategoryManager); - }, - QueryInterface: (function () { + }, + QueryInterface: (function () { var {XPCOMUtils} = - Cu.import('resource://gre/modules/XPCOMUtils.jsm', null); + Cu.import('resource://gre/modules/XPCOMUtils.jsm', null); return XPCOMUtils.generateQI([ - Ci.nsIFactory, - Ci.nsIObserver, - Ci.nsIChannelEventSink, - Ci.nsISupportsWeakReference + Ci.nsIFactory, + Ci.nsIObserver, + Ci.nsIChannelEventSink, + Ci.nsISupportsWeakReference ]); - })(), - createInstance: function (outer, iid) { + })(), + createInstance: function (outer, iid) { if (outer) { - throw Components.results.NS_ERROR_NO_AGGREGATION; + throw Components.results.NS_ERROR_NO_AGGREGATION; } return this.QueryInterface(iid); - }, - register: function () { + }, + register: function () { Services.obs.addObserver(this, 'http-on-modify-request', true); Services.obs.addObserver(this, 'http-on-examine-response', true); Services.obs.addObserver(this, 'http-on-examine-cached-response', true); // Guard against stale instances not having been unregistered if (this.componentRegistrar.isCIDRegistered(this.classID)) { - try { + try { this.componentRegistrar - .unregisterFactory(this.classID, - Components.manager - .getClassObject(this.classID, - Ci.nsIFactory)); - } catch (ex) { + .unregisterFactory(this.classID, + Components.manager + .getClassObject(this.classID, + Ci.nsIFactory)); + } catch (ex) { console.error('eMatrix> httpObserver > ' - +'unable to unregister stale instance: ', ex); - } + +'unable to unregister stale instance: ', ex); + } } this.componentRegistrar.registerFactory(this.classID, - this.classDescription, - this.contractID, - this); + this.classDescription, + this.contractID, + this); this.categoryManager.addCategoryEntry('net-channel-event-sinks', - this.contractID, - this.contractID, - false, - true); - }, - unregister: function () { + this.contractID, + this.contractID, + false, + true); + }, + unregister: function () { Services.obs.removeObserver(this, 'http-on-modify-request'); Services.obs.removeObserver(this, 'http-on-examine-response'); Services.obs.removeObserver(this, 'http-on-examine-cached-response'); this.componentRegistrar.unregisterFactory(this.classID, this); this.categoryManager.deleteCategoryEntry('net-channel-event-sinks', - this.contractID, - false); - }, - handleRequest: function (channel, URI, tabId, rawType) { + this.contractID, + false); + }, + handleRequest: function (channel, URI, tabId, rawType) { let type = this.typeMap[rawType] || 'other'; let onBeforeRequest = vAPI.net.onBeforeRequest; if (onBeforeRequest.types === null - || onBeforeRequest.types.has(type)) { - let result = onBeforeRequest.callback({ + || onBeforeRequest.types.has(type)) { + let result = onBeforeRequest.callback({ parentFrameId: type === 'main_frame' ? -1 : 0, tabId: tabId, type: type, url: URI.asciiSpec - }); + }); - if (typeof result === 'object') { + if (typeof result === 'object') { channel.cancel(this.ABORT); return true; - } + } } let onBeforeSendHeaders = vAPI.net.onBeforeSendHeaders; if (onBeforeSendHeaders.types === null - || onBeforeSendHeaders.types.has(type)) { - let requestHeaders = HTTPRequestHeaders.factory(channel); - let newHeaders = onBeforeSendHeaders.callback({ + || onBeforeSendHeaders.types.has(type)) { + let requestHeaders = HTTPRequestHeaders.factory(channel); + let newHeaders = onBeforeSendHeaders.callback({ parentFrameId: type === 'main_frame' ? -1 : 0, requestHeaders: requestHeaders.headers, tabId: tabId, type: type, url: URI.asciiSpec, method: channel.requestMethod - }); + }); - if (newHeaders) { + if (newHeaders) { requestHeaders.update(); - } - requestHeaders.dispose(); + } + requestHeaders.dispose(); } return false; - }, - channelDataFromChannel: function (channel) { + }, + channelDataFromChannel: function (channel) { if (channel instanceof Ci.nsIWritablePropertyBag) { - try { + try { return channel.getProperty(this.REQDATAKEY) || null; - } catch (ex) { - // Ignore - } + } catch (ex) { + // Ignore + } } return null; - }, - // https://github.com/gorhill/uMatrix/issues/165 - // https://developer.mozilla.org/en-US/Firefox/Releases/3.5/Updating_extensions#Getting_a_load_context_from_a_request - // Not sure `ematrix:shouldLoad` is still needed, eMatrix does - // not care about embedded frames topography. - // Also: - // https://developer.mozilla.org/en-US/Firefox/Multiprocess_Firefox/Limitations_of_chrome_scripts - tabIdFromChannel: function (channel) { + }, + // https://github.com/gorhill/uMatrix/issues/165 + // https://developer.mozilla.org/en-US/Firefox/Releases/3.5/Updating_extensions#Getting_a_load_context_from_a_request + // Not sure `ematrix:shouldLoad` is still needed, eMatrix does + // not care about embedded frames topography. + // Also: + // https://developer.mozilla.org/en-US/Firefox/Multiprocess_Firefox/Limitations_of_chrome_scripts + tabIdFromChannel: function (channel) { let lc; try { - lc = channel.notificationCallbacks.getInterface(Ci.nsILoadContext); + lc = channel.notificationCallbacks.getInterface(Ci.nsILoadContext); } catch(ex) { - // Ignore + // Ignore } if (!lc) { - try { + try { lc = channel.loadGroup.notificationCallbacks - .getInterface(Ci.nsILoadContext); - } catch(ex) { - // Ignore - } + .getInterface(Ci.nsILoadContext); + } catch(ex) { + // Ignore + } - if (!lc) { + if (!lc) { return vAPI.noTabId; - } + } } if (lc.topFrameElement) { - return vAPI.tabs.manager.tabIdFromTarget(lc.topFrameElement); + return vAPI.tabs.manager.tabIdFromTarget(lc.topFrameElement); } let win; try { - win = lc.associatedWindow; + win = lc.associatedWindow; } catch (ex) { - // Ignore - } + // Ignore + } if (!win) { - return vAPI.noTabId; + return vAPI.noTabId; } if (win.top) { - win = win.top; + win = win.top; } let tabBrowser; try { - tabBrowser = - vAPI.browser.getTabBrowser - (win.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShell).rootTreeItem - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindow)); + tabBrowser = + vAPI.browser.getTabBrowser + (win.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShell).rootTreeItem + .QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindow)); } catch (ex) { - // Ignore - } + // Ignore + } if (!tabBrowser) { - return vAPI.noTabId; + return vAPI.noTabId; } if (tabBrowser.getBrowserForContentWindow) { - return vAPI.tabs.manager - .tabIdFromTarget(tabBrowser.getBrowserForContentWindow(win)); + return vAPI.tabs.manager + .tabIdFromTarget(tabBrowser.getBrowserForContentWindow(win)); } // Falling back onto _getTabForContentWindow to ensure older // versions of Firefox work well. return tabBrowser._getTabForContentWindow - ? vAPI.tabs.manager - .tabIdFromTarget(tabBrowser._getTabForContentWindow(win)) - : vAPI.noTabId; - }, - rawtypeFromContentType: function (channel) { + ? vAPI.tabs.manager + .tabIdFromTarget(tabBrowser._getTabForContentWindow(win)) + : vAPI.noTabId; + }, + rawtypeFromContentType: function (channel) { let mime = channel.contentType; if (!mime) { - return 0; + return 0; } let pos = mime.indexOf('/'); if (pos === -1) { - pos = mime.length; + pos = mime.length; } return this.mimeTypeMap[mime.slice(0, pos)] || 0; - }, - operate: function (channel, URI, topic) { - let channelData = this.channelDataFromChannel(channel); + }, + operate: function (channel, URI, topic) { + let channelData = this.channelDataFromChannel(channel); - if (topic.lastIndexOf('http-on-examine-', 0) === 0) { - if (channelData === null) { + if (topic.lastIndexOf('http-on-examine-', 0) === 0) { + if (channelData === null) { return; - } + } - let type = this.frameTypeMap[channelData[1]]; - if (!type) { + let type = this.frameTypeMap[channelData[1]]; + if (!type) { return; - } - - // topic = ['Content-Security-Policy', - // 'Content-Security-Policy-Report-Only']; - // - // Can send empty responseHeaders as these headers are - // only added to and then merged. - // - // TODO: Find better place for this, needs to be set - // before onHeadersReceived.callback. Web workers not - // blocked in Pale Moon as child-src currently - // unavailable, see: - // - // https://github.com/MoonchildProductions/Pale-Moon/issues/949 - // - // eMatrix: as of Pale Moon 28 it seems child-src is - // available and depracated(?) - if (ηMatrix.cspNoWorker === undefined) { + } + + // topic = ['Content-Security-Policy', + // 'Content-Security-Policy-Report-Only']; + // + // Can send empty responseHeaders as these headers are + // only added to and then merged. + // + // TODO: Find better place for this, needs to be set + // before onHeadersReceived.callback. Web workers not + // blocked in Pale Moon as child-src currently + // unavailable, see: + // + // https://github.com/MoonchildProductions/Pale-Moon/issues/949 + // + // eMatrix: as of Pale Moon 28 it seems child-src is + // available and depracated(?) + if (ηMatrix.cspNoWorker === undefined) { // ηMatrix.cspNoWorker = "child-src 'none'; " - // +"frame-src data: blob: *; " - // +"report-uri about:blank"; - ηMatrix.cspNoWorker = "worker-src 'none'; " - +"frame-src data: blob: *; " - +"report-uri about:blank"; - } - - let result = vAPI.net.onHeadersReceived.callback({ + // +"frame-src data: blob: *; " + // +"report-uri about:blank"; + ηMatrix.cspNoWorker = "worker-src 'none'; " + +"frame-src data: blob: *; " + +"report-uri about:blank"; + } + + let result = vAPI.net.onHeadersReceived.callback({ parentFrameId: type === 'main_frame' ? -1 : 0, responseHeaders: [], tabId: channelData[0], type: type, url: URI.asciiSpec - }); + }); - if (result) { + if (result) { for (let header of result.responseHeaders) { - channel.setResponseHeader(header.name, - header.value, - true); + channel.setResponseHeader(header.name, + header.value, + true); } - } + } - return; + return; } - // http-on-modify-request + // http-on-modify-request // The channel was previously serviced. if (channelData !== null) { - this.handleRequest(channel, URI, - channelData[0], channelData[1]); - return; + this.handleRequest(channel, URI, + channelData[0], channelData[1]); + return; } // The channel was never serviced. let tabId; let pendingRequest = - PendingRequestBuffer.lookupRequest(URI.asciiSpec); + PendingRequestBuffer.lookupRequest(URI.asciiSpec); let rawType = 1; let loadInfo = channel.loadInfo; // https://github.com/gorhill/uMatrix/issues/390#issuecomment-155717004 if (loadInfo) { - rawType = (loadInfo.externalContentPolicyType !== undefined) - ? loadInfo.externalContentPolicyType - : loadInfo.contentPolicyType; - if (!rawType) { + rawType = (loadInfo.externalContentPolicyType !== undefined) + ? loadInfo.externalContentPolicyType + : loadInfo.contentPolicyType; + if (!rawType) { rawType = 1; - } + } } if (pendingRequest !== null) { - tabId = pendingRequest.tabId; - // https://github.com/gorhill/uBlock/issues/654 - // Use the request type from the HTTP observer point of view. - if (rawType !== 1) { + tabId = pendingRequest.tabId; + // https://github.com/gorhill/uBlock/issues/654 + // Use the request type from the HTTP observer point of view. + if (rawType !== 1) { pendingRequest.rawType = rawType; - } else { + } else { rawType = pendingRequest.rawType; - } + } } else { - tabId = this.tabIdFromChannel(channel); + tabId = this.tabIdFromChannel(channel); } if (this.handleRequest(channel, URI, tabId, rawType)) { - return; + return; } if (channel instanceof Ci.nsIWritablePropertyBag === false) { - return; + return; } // Carry data for behind-the-scene redirects channel.setProperty(this.REQDATAKEY, [tabId, rawType]); - }, - observe: function (channel, topic) { + }, + observe: function (channel, topic) { if (channel instanceof Ci.nsIHttpChannel === false) { - return; + return; } let URI = channel.URI; let channelData = this.channelDataFromChannel(channel); - if (ηMatrix.userSettings.resolveCname === true) { - let key = URI.scheme + '://' + URI.host; - if (HostMap.get(key)) { - this.operate(channel, HostMap.get(key), topic); - return; - } - - let CC = Components.classes; - let CI = Components.interfaces; - - let tab = this.tabIdFromChannel(channel); - - let dns = CC['@mozilla.org/network/dns-service;1'] - .createInstance(CI.nsIDNSService); - - let listener = { - onLookupComplete: function (req, rec, stat) { - if (!Components.isSuccessCode(stat)) { - console.error("can't resolve canonical name"); - return; - } - let addr = rec.canonicalName; - - ηMatrix.logger.writeOne(tab, 'info', - URI.host + ' => ' + addr); - - let ios = CC['@mozilla.org/network/io-service;1'] - .createInstance(CI.nsIIOService); - - let uri = ios.newURI(URI.scheme+'://'+addr, null, null); - - HostMap.put(key, uri); - - vAPI.httpObserver.operate(channel, uri, topic); - }, - }; - - dns.asyncResolve(URI.host, - CI.nsIDNSService.RESOLVE_CANONICAL_NAME, - listener, - null); - } else { - this.operate(channel, URI, topic); - } - }, - asyncOnChannelRedirect: function (oldChannel, newChannel, - flags, callback) { - // contentPolicy.shouldLoad doesn't detect redirects, this - // needs to be used + if (ηMatrix.userSettings.resolveCname === true) { + let key = URI.scheme + '://' + URI.host; + if (HostMap.get(key)) { + this.operate(channel, HostMap.get(key), topic); + return; + } + + let CC = Components.classes; + let CI = Components.interfaces; + + let tab = this.tabIdFromChannel(channel); + + let dns = CC['@mozilla.org/network/dns-service;1'] + .createInstance(CI.nsIDNSService); + + let listener = { + onLookupComplete: function (req, rec, stat) { + if (!Components.isSuccessCode(stat)) { + console.error("can't resolve canonical name"); + return; + } + let addr = rec.canonicalName; + + ηMatrix.logger.writeOne(tab, 'info', + URI.host + ' => ' + addr); + + let ios = CC['@mozilla.org/network/io-service;1'] + .createInstance(CI.nsIIOService); + + let uri = ios.newURI(URI.scheme+'://'+addr, null, null); + + HostMap.put(key, uri); + + vAPI.httpObserver.operate(channel, uri, topic); + }, + }; + + dns.asyncResolve(URI.host, + CI.nsIDNSService.RESOLVE_CANONICAL_NAME, + listener, + null); + } else { + this.operate(channel, URI, topic); + } + }, + asyncOnChannelRedirect: function (oldChannel, newChannel, + flags, callback) { + // contentPolicy.shouldLoad doesn't detect redirects, this + // needs to be used // If error thrown, the redirect will fail try { - let URI = newChannel.URI; - if (!URI.schemeIs('http') && !URI.schemeIs('https')) { + let URI = newChannel.URI; + if (!URI.schemeIs('http') && !URI.schemeIs('https')) { return; - } + } - if (newChannel instanceof Ci.nsIWritablePropertyBag === false) { + if (newChannel instanceof Ci.nsIWritablePropertyBag === false) { return; - } + } - let channelData = this.channelDataFromChannel(oldChannel); - if (channelData === null) { + let channelData = this.channelDataFromChannel(oldChannel); + if (channelData === null) { return; - } + } - // Carry the data on in case of multiple redirects - newChannel.setProperty(this.REQDATAKEY, channelData); + // Carry the data on in case of multiple redirects + newChannel.setProperty(this.REQDATAKEY, channelData); } catch (ex) { - // console.error(ex); - // Ignore + // console.error(ex); + // Ignore } finally { - callback.onRedirectVerifyCallback(this.ACCEPT); + callback.onRedirectVerifyCallback(this.ACCEPT); } - } + } }; vAPI.toolbarButton = { - id: location.host + '-button', - type: 'view', - viewId: location.host + '-panel', - label: vAPI.app.name, - tooltiptext: vAPI.app.name, - tabs: {/*tabId: {badge: 0, img: boolean}*/}, - init: null, - codePath: '' + id: location.host + '-button', + type: 'view', + viewId: location.host + '-panel', + label: vAPI.app.name, + tooltiptext: vAPI.app.name, + tabs: {/*tabId: {badge: 0, img: boolean}*/}, + init: null, + codePath: '' }; (function () { - let tbb = vAPI.toolbarButton; - let popupCommittedWidth = 0; - let popupCommittedHeight = 0; + let tbb = vAPI.toolbarButton; + let popupCommittedWidth = 0; + let popupCommittedHeight = 0; - tbb.onViewShowing = function ({target}) { + tbb.onViewShowing = function ({target}) { popupCommittedWidth = popupCommittedHeight = 0; target.firstChild.setAttribute('src', vAPI.getURL('popup.html')); - }; + }; - tbb.onViewHiding = function ({target}) { + tbb.onViewHiding = function ({target}) { target.parentNode.style.maxWidth = ''; target.firstChild.setAttribute('src', 'about:blank'); - }; + }; - tbb.updateState = function (win, tabId) { + tbb.updateState = function (win, tabId) { let button = win.document.getElementById(this.id); if (!button) { - return; + return; } let icon = this.tabs[tabId]; @@ -541,19 +541,19 @@ button.classList.toggle('off', !icon || !icon.img); let iconId = (ηMatrix.userSettings.disableUpdateIcon) ? - icon && icon.img ? '19' : 'off' : - icon && icon.img ? icon.img : 'off'; + icon && icon.img ? '19' : 'off' : + icon && icon.img ? icon.img : 'off'; icon = 'url(' - + vAPI.getURL('img/browsericons/icon19-' - + iconId - + '.png') - + ')'; + + vAPI.getURL('img/browsericons/icon19-' + + iconId + + '.png') + + ')'; - button.style.listStyleImage = icon; - }; + button.style.listStyleImage = icon; + }; - tbb.populatePanel = function (doc, panel) { + tbb.populatePanel = function (doc, panel) { panel.setAttribute('id', this.viewId); let iframe = doc.createElement('iframe'); @@ -562,135 +562,130 @@ panel.appendChild(iframe); let toPx = function (pixels) { - return pixels.toString() + 'px'; + return pixels.toString() + 'px'; }; let scrollBarWidth = 0; let resizeTimer = null; let resizePopupDelayed = function (attempts) { - if (resizeTimer !== null) { + if (resizeTimer !== null) { return false; - } + } - // Sanity check - attempts = (attempts || 0) + 1; - if ( attempts > 1/*000*/ ) { + // Sanity check + attempts = (attempts || 0) + 1; + if ( attempts > 1/*000*/ ) { //console.error('eMatrix> resizePopupDelayed: giving up after too many attempts'); return false; - } + } - resizeTimer = vAPI.setTimeout(resizePopup, 10, attempts); - return true; + resizeTimer = vAPI.setTimeout(resizePopup, 10, attempts); + return true; }; let resizePopup = function (attempts) { - resizeTimer = null; + resizeTimer = null; - panel.parentNode.style.maxWidth = 'none'; - let body = iframe.contentDocument.body; + panel.parentNode.style.maxWidth = 'none'; + let body = iframe.contentDocument.body; - // https://github.com/gorhill/uMatrix/issues/301 - // Don't resize if committed size did not change. - if (popupCommittedWidth === body.clientWidth - && popupCommittedHeight === body.clientHeight) { + // https://github.com/gorhill/uMatrix/issues/301 + // Don't resize if committed size did not change. + if (popupCommittedWidth === body.clientWidth + && popupCommittedHeight === body.clientHeight) { return; - } + } - // We set a limit for height - let height = Math.min(body.clientHeight, 600); + // We set a limit for height + let height = Math.min(body.clientHeight, 600); - // https://github.com/chrisaljoudi/uBlock/issues/730 - // Voodoo programming: this recipe works - panel.style.setProperty('height', toPx(height)); - iframe.style.setProperty('height', toPx(height)); + // https://github.com/chrisaljoudi/uBlock/issues/730 + // Voodoo programming: this recipe works + panel.style.setProperty('height', toPx(height)); + iframe.style.setProperty('height', toPx(height)); - // Adjust width for presence/absence of vertical scroll bar which may - // have appeared as a result of last operation. - let contentWindow = iframe.contentWindow; - let width = body.clientWidth; - if (contentWindow.scrollMaxY !== 0) { + // Adjust width for presence/absence of vertical scroll bar which may + // have appeared as a result of last operation. + let contentWindow = iframe.contentWindow; + let width = body.clientWidth; + if (contentWindow.scrollMaxY !== 0) { width += scrollBarWidth; - } - panel.style.setProperty('width', toPx(width)); + } + panel.style.setProperty('width', toPx(width)); - // scrollMaxX should always be zero once we know the scrollbar width - if (contentWindow.scrollMaxX !== 0) { + // scrollMaxX should always be zero once we know the scrollbar width + if (contentWindow.scrollMaxX !== 0) { scrollBarWidth = contentWindow.scrollMaxX; width += scrollBarWidth; panel.style.setProperty('width', toPx(width)); - } + } - if (iframe.clientHeight !== height - || panel.clientWidth !== width) { + if (iframe.clientHeight !== height + || panel.clientWidth !== width) { if (resizePopupDelayed(attempts)) { - return; + return; } // resizePopupDelayed won't be called again, so commit // dimentsions. - } + } - popupCommittedWidth = body.clientWidth; - popupCommittedHeight = body.clientHeight; + popupCommittedWidth = body.clientWidth; + popupCommittedHeight = body.clientHeight; }; let onResizeRequested = function () { - let body = iframe.contentDocument.body; - if (body.getAttribute('data-resize-popup') !== 'true') { + let body = iframe.contentDocument.body; + if (body.getAttribute('data-resize-popup') !== 'true') { return; - } - body.removeAttribute('data-resize-popup'); - resizePopupDelayed(); + } + body.removeAttribute('data-resize-popup'); + resizePopupDelayed(); }; let onPopupReady = function () { - let win = this.contentWindow; + let win = this.contentWindow; - if (!win || win.location.host !== location.host) { + if (!win || win.location.host !== location.host) { return; - } + } - if (typeof tbb.onBeforePopupReady === 'function') { + if (typeof tbb.onBeforePopupReady === 'function') { tbb.onBeforePopupReady.call(this); - } + } - resizePopupDelayed(); + resizePopupDelayed(); - let body = win.document.body; - body.removeAttribute('data-resize-popup'); + let body = win.document.body; + body.removeAttribute('data-resize-popup'); - let mutationObserver = - new win.MutationObserver(onResizeRequested); + let mutationObserver = + new win.MutationObserver(onResizeRequested); - mutationObserver.observe(body, { + mutationObserver.observe(body, { attributes: true, attributeFilter: [ 'data-resize-popup' ] - }); + }); }; iframe.addEventListener('load', onPopupReady, true); - }; + }; })(); /******************************************************************************/ (function () { - // Add toolbar button for not-Basilisk - if (Services.appinfo.ID === "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}") { + let tbb = vAPI.toolbarButton; + if (tbb.init !== null) { return; - } + } - let tbb = vAPI.toolbarButton; - if (tbb.init !== null) { - return; - } + tbb.codePath = 'legacy'; + tbb.viewId = tbb.id + '-panel'; - tbb.codePath = 'legacy'; - tbb.viewId = tbb.id + '-panel'; + let styleSheetUri = null; - let styleSheetUri = null; - - let createToolbarButton = function (window) { + let createToolbarButton = function (window) { let document = window.document; let toolbarButton = document.createElement('toolbarbutton'); @@ -699,40 +694,40 @@ toolbarButton.setAttribute('type', 'menu'); toolbarButton.setAttribute('removable', 'true'); toolbarButton.setAttribute('class', 'toolbarbutton-1 ' - +'chromeclass-toolbar-additional'); + +'chromeclass-toolbar-additional'); toolbarButton.setAttribute('label', tbb.label); - toolbarButton.setAttribute('tooltiptext', tbb.tooltiptext); + toolbarButton.setAttribute('tooltiptext', tbb.tooltiptext); let toolbarButtonPanel = document.createElement('panel'); // NOTE: Setting level to parent breaks the popup for PaleMoon under // linux (mouse pointer misaligned with content). For some reason. - // eMatrix: TODO check if it's still true + // eMatrix: TODO check if it's still true // toolbarButtonPanel.setAttribute('level', 'parent'); tbb.populatePanel(document, toolbarButtonPanel); toolbarButtonPanel.addEventListener('popupshowing', - tbb.onViewShowing); + tbb.onViewShowing); toolbarButtonPanel.addEventListener('popuphiding', - tbb.onViewHiding); + tbb.onViewHiding); toolbarButton.appendChild(toolbarButtonPanel); - toolbarButtonPanel.setAttribute('tooltiptext', ''); + toolbarButtonPanel.setAttribute('tooltiptext', ''); return toolbarButton; - }; + }; - let addLegacyToolbarButton = function (window) { + let addLegacyToolbarButton = function (window) { // eMatrix's stylesheet lazily added. if (styleSheetUri === null) { - var sss = Cc["@mozilla.org/content/style-sheet-service;1"] + var sss = Cc["@mozilla.org/content/style-sheet-service;1"] .getService(Ci.nsIStyleSheetService); - styleSheetUri = Services.io - .newURI(vAPI.getURL("css/legacy-toolbar-button.css"), - null, null); + styleSheetUri = Services.io + .newURI(vAPI.getURL("css/legacy-toolbar-button.css"), + null, null); - // Register global so it works in all windows, including palette - if (!sss.sheetRegistered(styleSheetUri, sss.AUTHOR_SHEET)) { + // Register global so it works in all windows, including palette + if (!sss.sheetRegistered(styleSheetUri, sss.AUTHOR_SHEET)) { sss.loadAndRegisterSheet(styleSheetUri, sss.AUTHOR_SHEET); - } + } } let document = window.document; @@ -740,21 +735,21 @@ // https://github.com/gorhill/uMatrix/issues/357 // Already installed? if (document.getElementById(tbb.id) !== null) { - return; + return; } let toolbox = document.getElementById('navigator-toolbox') - || document.getElementById('mail-toolbox'); + || document.getElementById('mail-toolbox'); if (toolbox === null) { - return; + return; } let toolbarButton = createToolbarButton(window); let palette = toolbox.palette; if (palette && palette.querySelector('#' + tbb.id) === null) { - palette.appendChild(toolbarButton); + palette.appendChild(toolbarButton); } // Find the place to put the button. @@ -762,75 +757,75 @@ // undefined. Seen while testing popup test number 3: // http://raymondhill.net/ublock/popup.html let toolbars = toolbox.externalToolbars - ? toolbox.externalToolbars.slice() - : []; + ? toolbox.externalToolbars.slice() + : []; for (let child of toolbox.children) { - if (child.localName === 'toolbar') { + if (child.localName === 'toolbar') { toolbars.push(child); - } + } } for (let toolbar of toolbars) { - let currentsetString = toolbar.getAttribute('currentset'); - if (!currentsetString) { + let currentsetString = toolbar.getAttribute('currentset'); + if (!currentsetString) { continue; - } + } - let currentset = currentsetString.split(/\s*,\s*/); - let index = currentset.indexOf(tbb.id); - if (index === -1) { + let currentset = currentsetString.split(/\s*,\s*/); + let index = currentset.indexOf(tbb.id); + if (index === -1) { continue; - } + } - // This can occur with Pale Moon: - // "TypeError: toolbar.insertItem is not a function" - if (typeof toolbar.insertItem !== 'function') { + // This can occur with Pale Moon: + // "TypeError: toolbar.insertItem is not a function" + if (typeof toolbar.insertItem !== 'function') { continue; - } - - // Found our button on this toolbar - but where on it? - let before = null; - for (let i=index+1; i<currentset.length; ++i) { - // The [id=...] notation doesn't work on - // space elements as they get a random ID each session - // (or something like that) - // https://gitlab.com/vannilla/ematrix/issues/5 - // https://gitlab.com/vannilla/ematrix/issues/6 - - // Based on JustOff's snippet from the Pale Moon - // forum. It was reorganized because I find it - // more readable like this, but he did most of the - // work. - let space = /^(spring|spacer|separator)$/.exec(currentset[i]); - if (space !== null) { - let elems = toolbar.querySelectorAll('toolbar'+space[1]); - - let count = currentset.slice(i-currentset.length) - .filter(function (x) {return x == space[1];}) - .length; - - before = - toolbar.querySelector('[id="' - + elems[elems.length-count].id - + '"]'); - } else { - before = toolbar.querySelector('[id="'+currentset[i]+'"]'); - } + } + + // Found our button on this toolbar - but where on it? + let before = null; + for (let i=index+1; i<currentset.length; ++i) { + // The [id=...] notation doesn't work on + // space elements as they get a random ID each session + // (or something like that) + // https://gitlab.com/vannilla/ematrix/issues/5 + // https://gitlab.com/vannilla/ematrix/issues/6 + + // Based on JustOff's snippet from the Pale Moon + // forum. It was reorganized because I find it + // more readable like this, but he did most of the + // work. + let space = /^(spring|spacer|separator)$/.exec(currentset[i]); + if (space !== null) { + let elems = toolbar.querySelectorAll('toolbar'+space[1]); + + let count = currentset.slice(i-currentset.length) + .filter(function (x) {return x == space[1];}) + .length; + + before = + toolbar.querySelector('[id="' + + elems[elems.length-count].id + + '"]'); + } else { + before = toolbar.querySelector('[id="'+currentset[i]+'"]'); + } if ( before !== null ) { - break; + break; } - } + } - toolbar.insertItem(tbb.id, before); - break; + toolbar.insertItem(tbb.id, before); + break; } // https://github.com/gorhill/uBlock/issues/763 // We are done if our toolbar button is already installed // in one of the toolbar. if (palette !== null && toolbarButton.parentElement !== palette) { - return; + return; } // No button yet so give it a default location. If forcing @@ -839,386 +834,200 @@ // available or visible!) let navbar = document.getElementById('nav-bar'); if (navbar !== null - && !vAPI.localStorage.getBool('legacyToolbarButtonAdded')) { - // https://github.com/gorhill/uBlock/issues/264 - // Find a child customizable palette, if any. - navbar = navbar.querySelector('.customization-target') || navbar; - navbar.appendChild(toolbarButton); - navbar.setAttribute('currentset', navbar.currentSet); - document.persist(navbar.id, 'currentset'); - vAPI.localStorage.setBool('legacyToolbarButtonAdded', 'true'); + && !vAPI.localStorage.getBool('legacyToolbarButtonAdded')) { + // https://github.com/gorhill/uBlock/issues/264 + // Find a child customizable palette, if any. + navbar = navbar.querySelector('.customization-target') || navbar; + navbar.appendChild(toolbarButton); + navbar.setAttribute('currentset', navbar.currentSet); + document.persist(navbar.id, 'currentset'); + vAPI.localStorage.setBool('legacyToolbarButtonAdded', 'true'); } - }; + }; - let canAddLegacyToolbarButton = function (window) { + let canAddLegacyToolbarButton = function (window) { let document = window.document; if (!document - || document.readyState !== 'complete' - || document.getElementById('nav-bar') === null) { - return false; + || document.readyState !== 'complete' + || document.getElementById('nav-bar') === null) { + return false; } let toolbox = document.getElementById('navigator-toolbox') - || document.getElementById('mail-toolbox'); + || document.getElementById('mail-toolbox'); return toolbox !== null && !!toolbox.palette; - }; + }; - let onPopupCloseRequested = function ({target}) { + let onPopupCloseRequested = function ({target}) { let document = target.ownerDocument; if (!document) { - return; + return; } let toolbarButtonPanel = document.getElementById(tbb.viewId); if (toolbarButtonPanel === null) { - return; + return; } // `hidePopup` reported as not existing while testing // legacy button on FF 41.0.2. // https://bugzilla.mozilla.org/show_bug.cgi?id=1151796 if (typeof toolbarButtonPanel.hidePopup === 'function') { - toolbarButtonPanel.hidePopup(); + toolbarButtonPanel.hidePopup(); } - }; + }; - let shutdown = function () { + let shutdown = function () { for (let win of vAPI.window.getWindows()) { - let toolbarButton = win.document.getElementById(tbb.id); - if (toolbarButton) { + let toolbarButton = win.document.getElementById(tbb.id); + if (toolbarButton) { toolbarButton.parentNode.removeChild(toolbarButton); - } + } } if (styleSheetUri !== null) { - var sss = Cc["@mozilla.org/content/style-sheet-service;1"] + var sss = Cc["@mozilla.org/content/style-sheet-service;1"] .getService(Ci.nsIStyleSheetService); - if (sss.sheetRegistered(styleSheetUri, sss.AUTHOR_SHEET)) { + if (sss.sheetRegistered(styleSheetUri, sss.AUTHOR_SHEET)) { sss.unregisterSheet(styleSheetUri, sss.AUTHOR_SHEET); - } - styleSheetUri = null; + } + styleSheetUri = null; } vAPI.messaging.globalMessageManager - .removeMessageListener(location.host + ':closePopup', - onPopupCloseRequested); - }; + .removeMessageListener(location.host + ':closePopup', + onPopupCloseRequested); + }; - tbb.attachToNewWindow = function (win) { + tbb.attachToNewWindow = function (win) { vAPI.deferUntil(canAddLegacyToolbarButton.bind(null, win), - addLegacyToolbarButton.bind(null, win)); - }; - - tbb.init = function () { - vAPI.messaging.globalMessageManager - .addMessageListener(location.host + ':closePopup', - onPopupCloseRequested); - - vAPI.addCleanUpTask(shutdown); - }; - })(); - - (function() { - // Add toolbar button for Basilisk - if (Services.appinfo.ID !== "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}") { - return; - } - - let tbb = vAPI.toolbarButton; - if (tbb.init !== null) { - return; - } - // if ( Services.vc.compare(Services.appinfo.version, '36.0') < 0 ) { - // return null; - // } - let CustomizableUI = null; - try { - CustomizableUI = - Cu.import('resource:///modules/CustomizableUI.jsm', null) - .CustomizableUI; - } catch (ex) { - // Ignore - } - if (CustomizableUI === null) { - return null; - } - tbb.codePath = 'australis'; - tbb.CustomizableUI = CustomizableUI; - tbb.defaultArea = CustomizableUI.AREA_NAVBAR; - - let CUIEvents = {}; - - let badgeCSSRules = 'background: #000;color: #fff'; - - let updateBadgeStyle = function () { - for (let win of vAPI.window.getWindows()) { - let button = win.document.getElementById(tbb.id); - if (button === null) { - continue; - } - let badge = button.ownerDocument - .getAnonymousElementByAttribute(button, - 'class', - 'toolbarbutton-badge'); - if (!badge) { - continue; - } - - badge.style.cssText = badgeCSSRules; - } - }; - - let updateBadge = function () { - let wId = tbb.id; - let buttonInPanel = - CustomizableUI.getWidget(wId).areaType - === CustomizableUI.TYPE_MENU_PANEL; - - for (let win of vAPI.window.getWindows()) { - let button = win.document.getElementById(wId); - if (button === null) { - continue; - } - - if (buttonInPanel) { - button.classList.remove('badged-button'); - continue; - } - - button.classList.add('badged-button'); - } - - if (buttonInPanel) { - return; - } - - // Anonymous elements need some time to be reachable - vAPI.setTimeout(updateBadgeStyle, 250); - }.bind(CUIEvents); - - CUIEvents.onCustomizeEnd = updateBadge; - CUIEvents.onWidgetAdded = updateBadge; - CUIEvents.onWidgetUnderflow = updateBadge; - - let onPopupCloseRequested = function ({target}) { - if (typeof tbb.closePopup === 'function') { - tbb.closePopup(target); - } - }; - - let shutdown = function () { - for (let win of vAPI.window.getWindows()) { - let panel = win.document.getElementById(tbb.viewId); - if (panel !== null && panel.parentNode !== null) { - panel.parentNode.removeChild(panel); - } - - win.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils) - .removeSheet(styleURI, 1); - } - - CustomizableUI.removeListener(CUIEvents); - CustomizableUI.destroyWidget(tbb.id); - - vAPI.messaging.globalMessageManager - .removeMessageListener(location.host + ':closePopup', - onPopupCloseRequested); - }; - - let styleURI = null; - - tbb.onBeforeCreated = function (doc) { - let panel = doc.createElement('panelview'); - - this.populatePanel(doc, panel); - - doc.getElementById('PanelUI-multiView').appendChild(panel); - - doc.defaultView.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils) - .loadSheet(styleURI, 1); - }; - - tbb.onCreated = function (button) { - button.setAttribute('badge', ''); - vAPI.setTimeout(updateBadge, 250); - }; - - tbb.onBeforePopupReady = function () { - // https://github.com/gorhill/uBlock/issues/83 - // Add `portrait` class if width is constrained. - try { - this.contentDocument.body - .classList.toggle('portrait', - CustomizableUI.getWidget(tbb.id).areaType - === CustomizableUI.TYPE_MENU_PANEL); - } catch (ex) { - // Ignore - } - }; - - tbb.closePopup = function (tabBrowser) { - CustomizableUI.hidePanelForNode(tabBrowser - .ownerDocument - .getElementById(tbb.viewId)); - }; + addLegacyToolbarButton.bind(null, win)); + }; - tbb.init = function () { + tbb.init = function () { vAPI.messaging.globalMessageManager - .addMessageListener(location.host + ':closePopup', - onPopupCloseRequested); - - CustomizableUI.addListener(CUIEvents); - - var style = [ - '#' + this.id + '.off {', - 'list-style-image: url(', - vAPI.getURL('img/browsericons/icon19-off.png'), - ');', - '}', - '#' + this.id + ' {', - 'list-style-image: url(', - vAPI.getURL('img/browsericons/icon19-19.png'), - ');', - '}', - '#' + this.viewId + ', #' + this.viewId + ' > iframe {', - 'height: 290px;', - 'max-width: none !important;', - 'min-width: 0 !important;', - 'overflow: hidden !important;', - 'padding: 0 !important;', - 'width: 160px;', - '}' - ]; - - styleURI = - Services.io.newURI('data:text/css,' - +encodeURIComponent(style.join('')), - null, - null); - - CustomizableUI.createWidget(this); + .addMessageListener(location.host + ':closePopup', + onPopupCloseRequested); vAPI.addCleanUpTask(shutdown); - }; + }; })(); // No toolbar button. (function () { - // Just to ensure the number of cleanup tasks is as expected: toolbar - // button code is one single cleanup task regardless of platform. - // eMatrix: might not be needed anymore - if (vAPI.toolbarButton.init === null) { + // Just to ensure the number of cleanup tasks is as expected: toolbar + // button code is one single cleanup task regardless of platform. + // eMatrix: might not be needed anymore + if (vAPI.toolbarButton.init === null) { vAPI.addCleanUpTask(function(){}); - } + } })(); if (vAPI.toolbarButton.init !== null) { - vAPI.toolbarButton.init(); + vAPI.toolbarButton.init(); } let optionsObserver = (function () { - let addonId = 'eMatrix@vannilla.org'; + let addonId = 'eMatrix@vannilla.org'; - let commandHandler = function () { + let commandHandler = function () { switch (this.id) { case 'showDashboardButton': - vAPI.tabs.open({ - url: 'dashboard.html', - index: -1, - }); - break; + vAPI.tabs.open({ + url: 'dashboard.html', + index: -1, + }); + break; case 'showLoggerButton': - vAPI.tabs.open({ - url: 'logger-ui.html', - index: -1, - }); - break; + vAPI.tabs.open({ + url: 'logger-ui.html', + index: -1, + }); + break; default: - break; + break; } - }; + }; - let setupOptionsButton = function (doc, id) { + let setupOptionsButton = function (doc, id) { let button = doc.getElementById(id); if (button === null) { - return; + return; } button.addEventListener('command', commandHandler); button.label = vAPI.i18n(id); - }; + }; - let setupOptionsButtons = function (doc) { + let setupOptionsButtons = function (doc) { setupOptionsButton(doc, 'showDashboardButton'); setupOptionsButton(doc, 'showLoggerButton'); - }; + }; - let observer = { + let observer = { observe: function (doc, topic, id) { - if (id !== addonId) { + if (id !== addonId) { return; - } + } - setupOptionsButtons(doc); + setupOptionsButtons(doc); } - }; + }; - var canInit = function() { - // https://github.com/gorhill/uBlock/issues/948 - // Older versions of Firefox can throw here when looking - // up `currentURI`. + var canInit = function() { + // https://github.com/gorhill/uBlock/issues/948 + // Older versions of Firefox can throw here when looking + // up `currentURI`. try { - let tabBrowser = vAPI.tabs.manager.currentBrowser(); - return tabBrowser - && tabBrowser.currentURI - && tabBrowser.currentURI.spec === 'about:addons' - && tabBrowser.contentDocument - && tabBrowser.contentDocument.readyState === 'complete'; + let tabBrowser = vAPI.tabs.manager.currentBrowser(); + return tabBrowser + && tabBrowser.currentURI + && tabBrowser.currentURI.spec === 'about:addons' + && tabBrowser.contentDocument + && tabBrowser.contentDocument.readyState === 'complete'; } catch (ex) { - // Ignore + // Ignore } - }; + }; - // Manually add the buttons if the `about:addons` page is - // already opened. - let init = function () { + // Manually add the buttons if the `about:addons` page is + // already opened. + let init = function () { if (canInit()) { - setupOptionsButtons(vAPI.tabs.manager - .currentBrowser().contentDocument); + setupOptionsButtons(vAPI.tabs.manager + .currentBrowser().contentDocument); } - }; + }; - let unregister = function () { + let unregister = function () { Services.obs.removeObserver(observer, 'addon-options-displayed'); - }; + }; - let register = function () { + let register = function () { Services.obs.addObserver(observer, - 'addon-options-displayed', - false); + 'addon-options-displayed', + false); vAPI.addCleanUpTask(unregister); vAPI.deferUntil(canInit, init, { next: 463 }); - }; + }; - return { + return { register: register, unregister: unregister - }; + }; })(); optionsObserver.register(); vAPI.onLoadAllCompleted = function() { - // This is called only once, when everything has been loaded - // in memory after the extension was launched. It can be used - // to inject content scripts in already opened web pages, to - // remove whatever nuisance could make it to the web pages - // before uBlock was ready. - for (let browser of vAPI.tabs.manager.browsers()) { + // This is called only once, when everything has been loaded + // in memory after the extension was launched. It can be used + // to inject content scripts in already opened web pages, to + // remove whatever nuisance could make it to the web pages + // before uBlock was ready. + for (let browser of vAPI.tabs.manager.browsers()) { browser.messageManager - .sendAsyncMessage(location.host + '-load-completed'); - } + .sendAsyncMessage(location.host + '-load-completed'); + } }; // Likelihood is that we do not have to punycode: given punycode overhead, @@ -1227,16 +1036,16 @@ var isNotASCII = /[^\x21-\x7F]/; vAPI.punycodeHostname = function (hostname) { - return isNotASCII.test(hostname) - ? punycodeHostname(hostname) - : hostname; + return isNotASCII.test(hostname) + ? punycodeHostname(hostname) + : hostname; }; vAPI.punycodeURL = function (url) { - if (isNotASCII.test(url)) { + if (isNotASCII.test(url)) { return Services.io.newURI(url, null, null).asciiSpec; - } + } - return url; + return url; }; })(); diff --git a/js/vapi-browser.js b/js/vapi-browser.js index 48474f9..2d92498 100644 --- a/js/vapi-browser.js +++ b/js/vapi-browser.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -29,48 +29,48 @@ vAPI.browser = {}; vAPI.browser.getTabBrowser = function (win) { - return win && win.gBrowser || null; + return win && win.gBrowser || null; }; vAPI.browser.getOwnerWindow = function (target) { - if (target.ownerDocument) { + if (target.ownerDocument) { return target.ownerDocument.defaultView; - } + } - return null; + return null; }; vAPI.browser.settings = { - // For now, only booleans. - originalValues: {}, + // For now, only booleans. + originalValues: {}, - rememberOriginalValue: function (path, setting) { + rememberOriginalValue: function (path, setting) { let key = path + '.' + setting; if (this.originalValues.hasOwnProperty(key)) { - return; + return; } let hasUserValue; let branch = Services.prefs.getBranch(path + '.'); try { - hasUserValue = branch.prefHasUserValue(setting); + hasUserValue = branch.prefHasUserValue(setting); } catch (ex) { - // Ignore + // Ignore } if (hasUserValue !== undefined) { - this.originalValues[key] = hasUserValue - ? this.getValue(path, setting) - : undefined; + this.originalValues[key] = hasUserValue + ? this.getValue(path, setting) + : undefined; } - }, - clear: function (path, setting) { + }, + clear: function (path, setting) { let key = path + '.' + setting; // Value was not overriden -- nothing to restore if (this.originalValues.hasOwnProperty(key) === false) { - return; + return; } let value = this.originalValues[key]; @@ -82,160 +82,160 @@ // Original value was a default one if (value === undefined) { - try { + try { Services.prefs.getBranch(path + '.').clearUserPref(setting); - } catch (ex) { - // Ignore - } - return; + } catch (ex) { + // Ignore + } + return; } // Reset to original value this.setValue(path, setting, value); - }, - getValue: function (path, setting) { + }, + getValue: function (path, setting) { let branch = Services.prefs.getBranch(path + '.'); - try { - switch (branch.getPrefType(setting)) { - case branch.PREF_INT: - return branch.getIntPref(setting); - case branch.PREF_BOOL: - return branch.getBoolPref(setting); - default: - // not supported - return; - } - } catch (e) { - // Ignore - } - }, - setValue: function (path, setting, value) { - let branch = Services.prefs.getBranch(path + '.'); - - try { - switch (typeof value) { - case 'number': - return branch.setIntPref(setting, value); - case 'boolean': - return branch.setBoolPref(setting, value); - default: - // not supported - return; - } - } catch (e) { - // Ignore - } - }, - setSetting: function (setting, value) { + try { + switch (branch.getPrefType(setting)) { + case branch.PREF_INT: + return branch.getIntPref(setting); + case branch.PREF_BOOL: + return branch.getBoolPref(setting); + default: + // not supported + return; + } + } catch (e) { + // Ignore + } + }, + setValue: function (path, setting, value) { + let branch = Services.prefs.getBranch(path + '.'); + + try { + switch (typeof value) { + case 'number': + return branch.setIntPref(setting, value); + case 'boolean': + return branch.setBoolPref(setting, value); + default: + // not supported + return; + } + } catch (e) { + // Ignore + } + }, + setSetting: function (setting, value) { switch (setting) { case 'prefetching': - this.rememberOriginalValue('network', 'prefetch-next'); - // https://bugzilla.mozilla.org/show_bug.cgi?id=814169 - // Sigh. - // eMatrix: doesn't seem the case for Pale - // Moon/Basilisk, but let's keep this anyway - this.rememberOriginalValue('network.http', 'speculative-parallel-limit'); - - // https://github.com/gorhill/uBlock/issues/292 - // "true" means "do not disable", i.e. leave entry alone - if (value) { + this.rememberOriginalValue('network', 'prefetch-next'); + // https://bugzilla.mozilla.org/show_bug.cgi?id=814169 + // Sigh. + // eMatrix: doesn't seem the case for Pale + // Moon/Basilisk, but let's keep this anyway + this.rememberOriginalValue('network.http', 'speculative-parallel-limit'); + + // https://github.com/gorhill/uBlock/issues/292 + // "true" means "do not disable", i.e. leave entry alone + if (value) { this.clear('network', 'prefetch-next'); this.clear('network.http', 'speculative-parallel-limit'); - } else { + } else { this.setValue('network', 'prefetch-next', false); this.setValue('network.http', - 'speculative-parallel-limit', 0); - } - break; + 'speculative-parallel-limit', 0); + } + break; case 'hyperlinkAuditing': - this.rememberOriginalValue('browser', 'send_pings'); - this.rememberOriginalValue('beacon', 'enabled'); + this.rememberOriginalValue('browser', 'send_pings'); + this.rememberOriginalValue('beacon', 'enabled'); - // https://github.com/gorhill/uBlock/issues/292 - // "true" means "do not disable", i.e. leave entry alone - if (value) { + // https://github.com/gorhill/uBlock/issues/292 + // "true" means "do not disable", i.e. leave entry alone + if (value) { this.clear('browser', 'send_pings'); this.clear('beacon', 'enabled'); - } else { + } else { this.setValue('browser', 'send_pings', false); this.setValue('beacon', 'enabled', false); - } - break; + } + break; case 'webrtcIPAddress': - let prefName; - let prefVal; - - // https://github.com/gorhill/uBlock/issues/894 - // Do not disable completely WebRTC if it can be avoided. FF42+ - // has a `media.peerconnection.ice.default_address_only` pref which - // purpose is to prevent local IP address leakage. - if (this.getValue('media.peerconnection', - 'ice.default_address_only') !== undefined) { + let prefName; + let prefVal; + + // https://github.com/gorhill/uBlock/issues/894 + // Do not disable completely WebRTC if it can be avoided. FF42+ + // has a `media.peerconnection.ice.default_address_only` pref which + // purpose is to prevent local IP address leakage. + if (this.getValue('media.peerconnection', + 'ice.default_address_only') !== undefined) { prefName = 'ice.default_address_only'; prefVal = true; - } else { + } else { prefName = 'enabled'; prefVal = false; - } + } - this.rememberOriginalValue('media.peerconnection', prefName); - if (value) { + this.rememberOriginalValue('media.peerconnection', prefName); + if (value) { this.clear('media.peerconnection', prefName); - } else { + } else { this.setValue('media.peerconnection', prefName, prefVal); - } - break; + } + break; default: - break; + break; } - }, - set: function (details) { + }, + set: function (details) { for (let setting in details) { - if (details.hasOwnProperty(setting) === false) { + if (details.hasOwnProperty(setting) === false) { continue; - } - this.setSetting(setting, !!details[setting]); + } + this.setSetting(setting, !!details[setting]); } - }, - restoreAll: function () { + }, + restoreAll: function () { let pos; for (let key in this.originalValues) { - if (this.originalValues.hasOwnProperty(key) === false) { + if (this.originalValues.hasOwnProperty(key) === false) { continue; - } + } - pos = key.lastIndexOf('.'); - this.clear(key.slice(0, pos), key.slice(pos + 1)); + pos = key.lastIndexOf('.'); + this.clear(key.slice(0, pos), key.slice(pos + 1)); } - }, + }, }; vAPI.addCleanUpTask(vAPI.browser.settings - .restoreAll.bind(vAPI.browser.settings)); + .restoreAll.bind(vAPI.browser.settings)); vAPI.browser.data = {}; vAPI.browser.data.clearCache = function (callback) { - // PURGE_DISK_DATA_ONLY:1 - // PURGE_DISK_ALL:2 - // PURGE_EVERYTHING:3 - // However I verified that no argument does clear the cache data. - // There is no cache2 for older versions of Firefox. - if (Services.cache2) { + // PURGE_DISK_DATA_ONLY:1 + // PURGE_DISK_ALL:2 + // PURGE_EVERYTHING:3 + // However I verified that no argument does clear the cache data. + // There is no cache2 for older versions of Firefox. + if (Services.cache2) { Services.cache2.clear(); - } else if (Services.cache) { + } else if (Services.cache) { Services.cache.evictEntries(Services.cache.STORE_ON_DISK); - } + } - if (typeof callback === 'function') { + if (typeof callback === 'function') { callback(); - } + } }; vAPI.browser.data.clearOrigin = function(/* domain */) { - // TODO - // eMatrix: is this actually needed? I don't really know what - // it's supposed to do anyway. + // TODO + // eMatrix: is this actually needed? I don't really know what + // it's supposed to do anyway. }; })(); diff --git a/js/vapi-client.js b/js/vapi-client.js index 40598b8..4635853 100644 --- a/js/vapi-client.js +++ b/js/vapi-client.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -27,66 +27,66 @@ (function (self) { if (self.vAPI === undefined) { - self.vAPI = {}; + self.vAPI = {}; } let vAPI = self.vAPI; vAPI.setTimeout = vAPI.setTimeout || function (callback, delay, extra) { - return setTimeout(function (a) { - callback(a); - }, delay, extra); + return setTimeout(function (a) { + callback(a); + }, delay, extra); }; vAPI.sessionId = String.fromCharCode(Date.now() % 25 + 97) + - Math.random().toString(36).slice(2); + Math.random().toString(36).slice(2); vAPI.shutdown = (function () { - let jobs = []; + let jobs = []; - let add = function (job) { + let add = function (job) { jobs.push(job); - }; + }; - let exec = function () { + let exec = function () { //console.debug('Shutting down...'); let job; while ((job = jobs.pop())) { - job(); + job(); } - }; + }; - return { + return { add: add, exec: exec - }; + }; })(); vAPI.messaging = { - listeners: new Set(), - pending: new Map(), - requestId: 1, - connected: false, - messageListenerCallback: null, - toggleListenerCallback: null, - - start: function () { + listeners: new Set(), + pending: new Map(), + requestId: 1, + connected: false, + messageListenerCallback: null, + toggleListenerCallback: null, + + start: function () { this.addListener(this.builtinListener); if (this.toggleListenerCallback === null) { - this.toggleListenerCallback = this.toggleListener.bind(this); + this.toggleListenerCallback = this.toggleListener.bind(this); } window.addEventListener('pagehide', - this.toggleListenerCallback, true); + this.toggleListenerCallback, true); window.addEventListener('pageshow', - this.toggleListenerCallback, true); - }, - shutdown: function () { + this.toggleListenerCallback, true); + }, + shutdown: function () { if (this.toggleListenerCallback !== null) { - window.removeEventListener('pagehide', - this.toggleListenerCallback, true); - window.removeEventListener('pageshow', - this.toggleListenerCallback, true); + window.removeEventListener('pagehide', + this.toggleListenerCallback, true); + window.removeEventListener('pageshow', + this.toggleListenerCallback, true); } this.removeAllListeners(); @@ -94,100 +94,100 @@ var pending = this.pending; this.pending.clear(); for (let callback of pending.values()) { - if (typeof callback === 'function') { + if (typeof callback === 'function') { callback(null); - } + } } - }, - connect: function () { + }, + connect: function () { if (!this.connected) { - if (this.messageListenerCallback === null) { + if (this.messageListenerCallback === null) { this.messageListenerCallback = - this.messageListener.bind(this); - } - addMessageListener(this.messageListenerCallback); - this.connected = true; + this.messageListener.bind(this); + } + addMessageListener(this.messageListenerCallback); + this.connected = true; } - }, - disconnect: function () { + }, + disconnect: function () { if (this.connected) { - removeMessageListener(); - this.connected = false; + removeMessageListener(); + this.connected = false; } - }, - messageListener: function (msg) { + }, + messageListener: function (msg) { let details = JSON.parse(msg); if (!details) { - return; + return; } if (details.broadcast) { - this.sendToListeners(details.msg); - return; + this.sendToListeners(details.msg); + return; } if (details.requestId) { - let listener = this.pending.get(details.requestId); - if (listener !== undefined) { + let listener = this.pending.get(details.requestId); + if (listener !== undefined) { this.pending.delete(details.requestId); listener(details.msg); return; - } + } } - }, - builtinListener: function (msg) { + }, + builtinListener: function (msg) { if (typeof msg.cmd === 'string' && msg.cmd === 'injectScript') { - let details = msg.details; - if (!details.allFrames && window !== window.top) { + let details = msg.details; + if (!details.allFrames && window !== window.top) { return; - } - self.injectScript(details.file); + } + self.injectScript(details.file); } - }, - send: function (channelName, message, callback) { + }, + send: function (channelName, message, callback) { this.connect() message = { - channelName: self._sandboxId_ + '|' + channelName, - msg: message + channelName: self._sandboxId_ + '|' + channelName, + msg: message }; if (callback) { - message.requestId = this.requestId++; - this.pending.set(message.requestId, callback); + message.requestId = this.requestId++; + this.pending.set(message.requestId, callback); } sendAsyncMessage('ematrix:background', message); - }, - toggleListener: function ({type, persisted}) { + }, + toggleListener: function ({type, persisted}) { if (type === 'pagehide' && !persisted) { - vAPI.shutdown.exec(); - this.shutdown(); - return; + vAPI.shutdown.exec(); + this.shutdown(); + return; } if (type === 'pagehide') { - this.disconnect(); + this.disconnect(); } else { - this.connect(); + this.connect(); } - }, - sendToListeners: function (msg) { + }, + sendToListeners: function (msg) { for (let listener of this.listeners) { - listener(msg); + listener(msg); } - }, - addListener: function (listener) { + }, + addListener: function (listener) { this.listeners.add(listener); this.connect() - }, - removeListener: function (listener) { + }, + removeListener: function (listener) { this.listeners.delete(listener); - }, - removeAllListeners: function () { + }, + removeAllListeners: function () { this.disconnect(); this.listeners.clear(); - } + } }; vAPI.messaging.start() @@ -197,8 +197,8 @@ // be injected in top window). // Needs more investigating // if ( window !== window.top ) { - // vAPI.shutdown.add(function() { - // vAPI = null; - // }); + // vAPI.shutdown.add(function() { + // vAPI = null; + // }); // } })(this); diff --git a/js/vapi-cloud.js b/js/vapi-cloud.js index 70d7907..c86f351 100644 --- a/js/vapi-cloud.js +++ b/js/vapi-cloud.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -27,130 +27,130 @@ (function () { vAPI.cloud = (function () { - let extensionBranchPath = 'extensions.' + location.host; - let cloudBranchPath = extensionBranchPath + '.cloudStorage'; - - // https://github.com/gorhill/uBlock/issues/80#issuecomment-132081658 - // We must use get/setComplexValue in order to properly handle strings - // with unicode characters. - let iss = Ci.nsISupportsString; - let argstr = Components.classes['@mozilla.org/supports-string;1'] + let extensionBranchPath = 'extensions.' + location.host; + let cloudBranchPath = extensionBranchPath + '.cloudStorage'; + + // https://github.com/gorhill/uBlock/issues/80#issuecomment-132081658 + // We must use get/setComplexValue in order to properly handle strings + // with unicode characters. + let iss = Ci.nsISupportsString; + let argstr = Components.classes['@mozilla.org/supports-string;1'] .createInstance(iss); - let options = { + let options = { defaultDeviceName: '', deviceName: '' - }; + }; - // User-supplied device name. - try { + // User-supplied device name. + try { options.deviceName = Services.prefs .getBranch(extensionBranchPath + '.') .getComplexValue('deviceName', iss) .data; - } catch(ex) { - // Ignore - } + } catch(ex) { + // Ignore + } - var getDefaultDeviceName = function() { + var getDefaultDeviceName = function() { var name = ''; try { - name = Services.prefs + name = Services.prefs .getBranch('services.sync.client.') .getComplexValue('name', iss) .data; } catch(ex) { - // Ignore + // Ignore } return name || window.navigator.platform || window.navigator.oscpu; - }; + }; - let start = function (dataKeys) { + let start = function (dataKeys) { let extensionBranch = - Services.prefs.getBranch(extensionBranchPath + '.'); + Services.prefs.getBranch(extensionBranchPath + '.'); let syncBranch = - Services.prefs.getBranch('services.sync.prefs.sync.'); + Services.prefs.getBranch('services.sync.prefs.sync.'); // Mark config entries as syncable argstr.data = ''; let dataKey; for (let i=0; i<dataKeys.length; ++i) { - dataKey = dataKeys[i]; - if (extensionBranch.prefHasUserValue('cloudStorage.' + dataKey) - === false) { + dataKey = dataKeys[i]; + if (extensionBranch.prefHasUserValue('cloudStorage.' + dataKey) + === false) { extensionBranch.setComplexValue('cloudStorage.' + dataKey, - iss, argstr); - } + iss, argstr); + } - syncBranch.setBoolPref(cloudBranchPath + '.' + dataKey, true); + syncBranch.setBoolPref(cloudBranchPath + '.' + dataKey, true); } - }; + }; - let push = function (datakey, data, callback) { + let push = function (datakey, data, callback) { let branch = Services.prefs.getBranch(cloudBranchPath + '.'); let bin = { - 'source': options.deviceName || getDefaultDeviceName(), - 'tstamp': Date.now(), - 'data': data, - 'size': 0 + 'source': options.deviceName || getDefaultDeviceName(), + 'tstamp': Date.now(), + 'data': data, + 'size': 0 }; bin.size = JSON.stringify(bin).length; argstr.data = JSON.stringify(bin); branch.setComplexValue(datakey, iss, argstr); if (typeof callback === 'function') { - callback(); + callback(); } - }; + }; - let pull = function (datakey, callback) { + let pull = function (datakey, callback) { let result = null; let branch = Services.prefs.getBranch(cloudBranchPath + '.'); try { - let json = branch.getComplexValue(datakey, iss).data; - if (typeof json === 'string') { + let json = branch.getComplexValue(datakey, iss).data; + if (typeof json === 'string') { result = JSON.parse(json); - } + } } catch(ex) { - // Ignore + // Ignore } callback(result); - }; + }; - let getOptions = function (callback) { + let getOptions = function (callback) { if (typeof callback !== 'function') { - return; + return; } options.defaultDeviceName = getDefaultDeviceName(); callback(options); - }; + }; - let setOptions = function (details, callback) { + let setOptions = function (details, callback) { if (typeof details !== 'object' || details === null) { - return; + return; } let branch = Services.prefs.getBranch(extensionBranchPath + '.'); if (typeof details.deviceName === 'string') { - argstr.data = details.deviceName; - branch.setComplexValue('deviceName', iss, argstr); - options.deviceName = details.deviceName; + argstr.data = details.deviceName; + branch.setComplexValue('deviceName', iss, argstr); + options.deviceName = details.deviceName; } getOptions(callback); - }; + }; - return { + return { start: start, push: push, pull: pull, getOptions: getOptions, setOptions: setOptions - }; + }; })(); })(); diff --git a/js/vapi-common.js b/js/vapi-common.js index db48206..d541070 100644 --- a/js/vapi-common.js +++ b/js/vapi-common.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -32,86 +32,86 @@ Cu.import('resource://gre/modules/Services.jsm'); (function (self) { if (self.vAPI === undefined) { - self.vAPI = vAPI; + self.vAPI = vAPI; } vAPI.setTimeout = vAPI.setTimeout || function (callback, delay, extra) { - return setTimeout(function (a) { - callback(a); - }, delay, extra); + return setTimeout(function (a) { + callback(a); + }, delay, extra); }; // http://www.w3.org/International/questions/qa-scripts#directions let setScriptDirection = function(language) { - let dir = - ['ar', 'he', 'fa', 'ps', 'ur'].indexOf(language) !== -1 - ? 'rtl' - : 'ltr'; + let dir = + ['ar', 'he', 'fa', 'ps', 'ur'].indexOf(language) !== -1 + ? 'rtl' + : 'ltr'; - document.body.setAttribute('dir', dir); + document.body.setAttribute('dir', dir); }; vAPI.download = function (details) { - if (!details.url) { + if (!details.url) { return; - } + } - let a = document.createElement('a'); - a.href = details.url; - a.setAttribute('download', details.filename || ''); - a.dispatchEvent(new MouseEvent('click')); + let a = document.createElement('a'); + a.href = details.url; + a.setAttribute('download', details.filename || ''); + a.dispatchEvent(new MouseEvent('click')); }; vAPI.insertHTML = (function () { - const parser = Cc['@mozilla.org/parserutils;1'] + const parser = Cc['@mozilla.org/parserutils;1'] .getService(Ci.nsIParserUtils); - // https://github.com/gorhill/uBlock/issues/845 - // Apparently dashboard pages execute with `about:blank` principal. + // https://github.com/gorhill/uBlock/issues/845 + // Apparently dashboard pages execute with `about:blank` principal. - return function (node, html) { + return function (node, html) { while (node.firstChild) { - node.removeChild(node.firstChild); + node.removeChild(node.firstChild); } - let parsed = - parser.parseFragment(html, - parser.SanitizerAllowStyle, - false, - Services.io.newURI('about:blank', - null, null), - document.documentElement); + let parsed = + parser.parseFragment(html, + parser.SanitizerAllowStyle, + false, + Services.io.newURI('about:blank', + null, null), + document.documentElement); node.appendChild(parsed); - }; + }; })(); vAPI.getURL = function (path) { - return 'chrome://' - + location.host - + '/content/' - + path.replace(/^\/+/, ''); + return 'chrome://' + + location.host + + '/content/' + + path.replace(/^\/+/, ''); }; vAPI.i18n = (function () { - let stringBundle = - Services.strings.createBundle('chrome://' - + location.host - + '/locale/messages.properties'); + let stringBundle = + Services.strings.createBundle('chrome://' + + location.host + + '/locale/messages.properties'); - return function (s) { + return function (s) { try { - return stringBundle.GetStringFromName(s); + return stringBundle.GetStringFromName(s); } catch (ex) { - return ''; + return ''; } - }; + }; })(); setScriptDirection(navigator.language); vAPI.closePopup = function() { - sendAsyncMessage(location.host + ':closePopup'); + sendAsyncMessage(location.host + ':closePopup'); }; // A localStorage-like object which should be accessible from the @@ -119,50 +119,50 @@ Cu.import('resource://gre/modules/Services.jsm'); // This storage is optional, but it is nice to have, for a more polished user // experience. vAPI.localStorage = { - pbName: '', - pb: null, - str: Cc['@mozilla.org/supports-string;1'] + pbName: '', + pb: null, + str: Cc['@mozilla.org/supports-string;1'] .createInstance(Ci.nsISupportsString), - init: function (pbName) { + init: function (pbName) { this.pbName = pbName; this.pb = Services.prefs.getBranch(pbName); - }, - getItem: function (key) { + }, + getItem: function (key) { try { - return this.pb - .getComplexValue(key, - Ci.nsISupportsString).data; + return this.pb + .getComplexValue(key, + Ci.nsISupportsString).data; } catch (ex) { - return null; + return null; } - }, - setItem: function (key, value) { + }, + setItem: function (key, value) { this.str.data = value; this.pb.setComplexValue(key, - Ci.nsISupportsString, - this.str); - }, - getBool: function (key) { + Ci.nsISupportsString, + this.str); + }, + getBool: function (key) { try { - return this.pb.getBoolPref(key); + return this.pb.getBoolPref(key); } catch (ex) { - return null; + return null; } - }, - setBool: function (key, value) { + }, + setBool: function (key, value) { this.pb.setBoolPref(key, value); - }, - setDefaultBool: function (key, defaultValue) { + }, + setDefaultBool: function (key, defaultValue) { Services.prefs.getDefaultBranch(this.pbName) - .setBoolPref(key, defaultValue); - }, - removeItem: function (key) { + .setBoolPref(key, defaultValue); + }, + removeItem: function (key) { this.pb.clearUserPref(key); - }, - clear: function () { + }, + clear: function () { this.pb.deleteBranch(''); - } + } }; vAPI.localStorage.init('extensions.' + location.host + '.'); diff --git a/js/vapi-contextmenu.js b/js/vapi-contextmenu.js index 271e30b..9e20b23 100644 --- a/js/vapi-contextmenu.js +++ b/js/vapi-contextmenu.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -27,73 +27,73 @@ (function () { vAPI.contextMenu = { - contextMap: { + contextMap: { frame: 'inFrame', link: 'onLink', image: 'onImage', audio: 'onAudio', video: 'onVideo', editable: 'onEditableArea' - } + } }; vAPI.contextMenu.displayMenuItem = function ({target}) { - let doc = target.ownerDocument; - let gContextMenu = doc.defaultView.gContextMenu; - if (!gContextMenu.browser) { + let doc = target.ownerDocument; + let gContextMenu = doc.defaultView.gContextMenu; + if (!gContextMenu.browser) { return; - } + } - let menuitem = doc.getElementById(vAPI.contextMenu.menuItemId); - let currentURI = gContextMenu.browser.currentURI; + let menuitem = doc.getElementById(vAPI.contextMenu.menuItemId); + let currentURI = gContextMenu.browser.currentURI; - // https://github.com/chrisaljoudi/uBlock/issues/105 - // TODO: Should the element picker works on any kind of pages? - if (!currentURI.schemeIs('http') && !currentURI.schemeIs('https')) { + // https://github.com/chrisaljoudi/uBlock/issues/105 + // TODO: Should the element picker works on any kind of pages? + if (!currentURI.schemeIs('http') && !currentURI.schemeIs('https')) { menuitem.setAttribute('hidden', true); return; - } + } - let ctx = vAPI.contextMenu.contexts; + let ctx = vAPI.contextMenu.contexts; - if (!ctx) { + if (!ctx) { menuitem.setAttribute('hidden', false); return; - } + } - let ctxMap = vAPI.contextMenu.contextMap; + let ctxMap = vAPI.contextMenu.contextMap; - for (let context of ctx) { + for (let context of ctx) { if (context === 'page' - && !gContextMenu.onLink - && !gContextMenu.onImage - && !gContextMenu.onEditableArea - && !gContextMenu.inFrame - && !gContextMenu.onVideo - && !gContextMenu.onAudio) { - menuitem.setAttribute('hidden', false); - return; + && !gContextMenu.onLink + && !gContextMenu.onImage + && !gContextMenu.onEditableArea + && !gContextMenu.inFrame + && !gContextMenu.onVideo + && !gContextMenu.onAudio) { + menuitem.setAttribute('hidden', false); + return; } if (ctxMap.hasOwnProperty(context) - && gContextMenu[ctxMap[context]]) { - menuitem.setAttribute('hidden', false); - return; + && gContextMenu[ctxMap[context]]) { + menuitem.setAttribute('hidden', false); + return; } - } + } - menuitem.setAttribute('hidden', true); + menuitem.setAttribute('hidden', true); }; vAPI.contextMenu.register = (function () { - let register = function (doc) { + let register = function (doc) { if (!this.menuItemId) { - return; + return; } // Already installed? if (doc.getElementById(this.menuItemId) !== null) { - return; + return; } let contextMenu = doc.getElementById('contentAreaContextMenu'); @@ -107,106 +107,106 @@ contextMenu.addEventListener('popupshowing', this.displayMenuItem); contextMenu.insertBefore(menuitem, doc.getElementById('inspect-separator')); - }; - - let registerSafely = function (doc, tryCount) { - // https://github.com/gorhill/uBlock/issues/906 - // Be sure document.readyState is 'complete': it could happen - // at launch time that we are called by - // vAPI.contextMenu.create() directly before the environment - // is properly initialized. + }; + + let registerSafely = function (doc, tryCount) { + // https://github.com/gorhill/uBlock/issues/906 + // Be sure document.readyState is 'complete': it could happen + // at launch time that we are called by + // vAPI.contextMenu.create() directly before the environment + // is properly initialized. if (doc.readyState === 'complete') { - register.call(this, doc); - return; + register.call(this, doc); + return; } if (typeof tryCount !== 'number') { - tryCount = 0; + tryCount = 0; } tryCount += 1; if (tryCount < 8) { - vAPI.setTimeout(registerSafely.bind(this, doc, tryCount), 200); + vAPI.setTimeout(registerSafely.bind(this, doc, tryCount), 200); } - }; + }; - return registerSafely; + return registerSafely; })(); vAPI.contextMenu.unregister = function (doc) { - if (!this.menuItemId) { + if (!this.menuItemId) { return; - } + } - let menuitem = doc.getElementById(this.menuItemId); - if (menuitem === null) { + let menuitem = doc.getElementById(this.menuItemId); + if (menuitem === null) { return; - } + } - let contextMenu = menuitem.parentNode; - menuitem.removeEventListener('command', this.onCommand); - contextMenu.removeEventListener('popupshowing', this.displayMenuItem); - contextMenu.removeChild(menuitem); + let contextMenu = menuitem.parentNode; + menuitem.removeEventListener('command', this.onCommand); + contextMenu.removeEventListener('popupshowing', this.displayMenuItem); + contextMenu.removeChild(menuitem); }; vAPI.contextMenu.create = function (details, callback) { - this.menuItemId = details.id; - this.menuLabel = details.title; - this.contexts = details.contexts; + this.menuItemId = details.id; + this.menuLabel = details.title; + this.contexts = details.contexts; - if (Array.isArray(this.contexts) && this.contexts.length) { + if (Array.isArray(this.contexts) && this.contexts.length) { this.contexts = this.contexts.indexOf('all') === -1 - ? this.contexts - : null; - } else { + ? this.contexts + : null; + } else { // default in Chrome this.contexts = ['page']; - } + } - this.onCommand = function () { + this.onCommand = function () { let gContextMenu = vAPI.browser.getOwnerWindow(this).gContextMenu; let details = { - menuItemId: this.id + menuItemId: this.id }; if (gContextMenu.inFrame) { - details.tagName = 'iframe'; - // Probably won't work with e10s - // eMatrix: doesn't matter ;) - details.frameUrl = gContextMenu.focusedWindow.location.href; + details.tagName = 'iframe'; + // Probably won't work with e10s + // eMatrix: doesn't matter ;) + details.frameUrl = gContextMenu.focusedWindow.location.href; } else if (gContextMenu.onImage) { - details.tagName = 'img'; - details.srcUrl = gContextMenu.mediaURL; + details.tagName = 'img'; + details.srcUrl = gContextMenu.mediaURL; } else if (gContextMenu.onAudio) { - details.tagName = 'audio'; - details.srcUrl = gContextMenu.mediaURL; + details.tagName = 'audio'; + details.srcUrl = gContextMenu.mediaURL; } else if (gContextMenu.onVideo) { - details.tagName = 'video'; - details.srcUrl = gContextMenu.mediaURL; + details.tagName = 'video'; + details.srcUrl = gContextMenu.mediaURL; } else if (gContextMenu.onLink) { - details.tagName = 'a'; - details.linkUrl = gContextMenu.linkURL; + details.tagName = 'a'; + details.linkUrl = gContextMenu.linkURL; } callback(details, { - id: vAPI.tabs.manager.tabIdFromTarget(gContextMenu.browser), - url: gContextMenu.browser.currentURI.asciiSpec + id: vAPI.tabs.manager.tabIdFromTarget(gContextMenu.browser), + url: gContextMenu.browser.currentURI.asciiSpec }); - }; + }; - for (let win of vAPI.window.getWindows()) { + for (let win of vAPI.window.getWindows()) { this.register(win.document); - } + } }; vAPI.contextMenu.remove = function () { - for (let win of vAPI.window.getWindows()) { + for (let win of vAPI.window.getWindows()) { this.unregister(win.document); - } + } - this.menuItemId = null; - this.menuLabel = null; - this.contexts = null; - this.onCommand = null; + this.menuItemId = null; + this.menuLabel = null; + this.contexts = null; + this.onCommand = null; }; })(); diff --git a/js/vapi-cookies.js b/js/vapi-cookies.js index c694b8d..b6635a5 100644 --- a/js/vapi-cookies.js +++ b/js/vapi-cookies.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -29,90 +29,90 @@ vAPI.cookies = {}; vAPI.cookies.CookieEntry = function (ffCookie) { - this.domain = ffCookie.host; - this.name = ffCookie.name; - this.path = ffCookie.path; - this.secure = ffCookie.isSecure === true; - this.session = ffCookie.expires === 0; - this.value = ffCookie.value; + this.domain = ffCookie.host; + this.name = ffCookie.name; + this.path = ffCookie.path; + this.secure = ffCookie.isSecure === true; + this.session = ffCookie.expires === 0; + this.value = ffCookie.value; }; vAPI.cookies.start = function () { - Services.obs.addObserver(this, 'cookie-changed', false); - Services.obs.addObserver(this, 'private-cookie-changed', false); - vAPI.addCleanUpTask(this.stop.bind(this)); + Services.obs.addObserver(this, 'cookie-changed', false); + Services.obs.addObserver(this, 'private-cookie-changed', false); + vAPI.addCleanUpTask(this.stop.bind(this)); }; vAPI.cookies.stop = function () { - Services.obs.removeObserver(this, 'cookie-changed'); - Services.obs.removeObserver(this, 'private-cookie-changed'); + Services.obs.removeObserver(this, 'cookie-changed'); + Services.obs.removeObserver(this, 'private-cookie-changed'); }; vAPI.cookies.observe = function (subject, topic, reason) { - //if ( topic !== 'cookie-changed' && topic !== 'private-cookie-changed' ) { - // return; - //} - // - if (reason === 'cleared' && typeof this.onAllRemoved === 'function') { + //if ( topic !== 'cookie-changed' && topic !== 'private-cookie-changed' ) { + // return; + //} + // + if (reason === 'cleared' && typeof this.onAllRemoved === 'function') { this.onAllRemoved(); return; - } - if (subject === null) { + } + if (subject === null) { return; - } - if (subject instanceof Ci.nsICookie2 === false) { + } + if (subject instanceof Ci.nsICookie2 === false) { try { - subject = subject.QueryInterface(Ci.nsICookie2); + subject = subject.QueryInterface(Ci.nsICookie2); } catch (ex) { - return; + return; } - } - if (reason === 'deleted') { + } + if (reason === 'deleted') { if (typeof this.onRemoved === 'function') { - this.onRemoved(new this.CookieEntry(subject)); + this.onRemoved(new this.CookieEntry(subject)); } return; - } - if (typeof this.onChanged === 'function') { + } + if (typeof this.onChanged === 'function') { this.onChanged(new this.CookieEntry(subject)); - } + } }; vAPI.cookies.getAll = function(callback) { - // Meant and expected to be asynchronous. - if (typeof callback !== 'function') { + // Meant and expected to be asynchronous. + if (typeof callback !== 'function') { return; - } + } - let onAsync = function () { + let onAsync = function () { let out = []; let enumerator = Services.cookies.enumerator; let ffcookie; while (enumerator.hasMoreElements()) { - ffcookie = enumerator.getNext(); - if (ffcookie instanceof Ci.nsICookie) { + ffcookie = enumerator.getNext(); + if (ffcookie instanceof Ci.nsICookie) { out.push(new this.CookieEntry(ffcookie)); - } + } } callback(out); - }; + }; - vAPI.setTimeout(onAsync.bind(this), 0); + vAPI.setTimeout(onAsync.bind(this), 0); }; vAPI.cookies.remove = function (details, callback) { - let uri = Services.io.newURI(details.url, null, null); - let cookies = Services.cookies; - cookies.remove(uri.asciiHost, details.name, uri.path, false, {}); - cookies.remove( '.' + uri.asciiHost, details.name, uri.path, false, {}); + let uri = Services.io.newURI(details.url, null, null); + let cookies = Services.cookies; + cookies.remove(uri.asciiHost, details.name, uri.path, false, {}); + cookies.remove( '.' + uri.asciiHost, details.name, uri.path, false, {}); - if (typeof callback === 'function') { + if (typeof callback === 'function') { callback({ - domain: uri.asciiHost, - name: details.name, - path: uri.path + domain: uri.asciiHost, + name: details.name, + path: uri.path }); - } + } }; })(); diff --git a/js/vapi-core.js b/js/vapi-core.js index 5d33a60..0a9cc0b 100644 --- a/js/vapi-core.js +++ b/js/vapi-core.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -27,24 +27,24 @@ (function (self) { vAPI.modernFirefox = - Services.appinfo.ID === '{ec8030f7-c20a-464f-9b0e-13a3a9e97384}' - && Services.vc.compare(Services.appinfo.version, '44') > 0; + Services.appinfo.ID === '{ec8030f7-c20a-464f-9b0e-13a3a9e97384}' + && Services.vc.compare(Services.appinfo.version, '44') > 0; vAPI.app = { - name: 'eMatrix', - version: location.hash.slice(1), - - start: function () { - return; - }, - stop: function () { - return; - }, - restart: function () { - Cc['@mozilla.org/childprocessmessagemanager;1'] - .getService(Ci.nsIMessageSender) - .sendAsyncMessage(location.host + '-restart'); - }, + name: 'eMatrix', + version: location.hash.slice(1), + + start: function () { + return; + }, + stop: function () { + return; + }, + restart: function () { + Cc['@mozilla.org/childprocessmessagemanager;1'] + .getService(Ci.nsIMessageSender) + .sendAsyncMessage(location.host + '-restart'); + }, }; // List of things that needs to be destroyed when disabling the extension @@ -57,72 +57,72 @@ let expectedNumberOfCleanups = 7; vAPI.addCleanUpTask = function (task) { - if (typeof task !== 'function') { - return; - } + if (typeof task !== 'function') { + return; + } - cleanupTasks.push(task); + cleanupTasks.push(task); }; vAPI.deferUntil = function (testFn, mainFn, details) { - let dtls = (typeof details !== 'object') ? {} : details; - let now = 0; - let next = dtls.next || 200; - let until = dtls.until || 2000; + let dtls = (typeof details !== 'object') ? {} : details; + let now = 0; + let next = dtls.next || 200; + let until = dtls.until || 2000; - let check = function () { + let check = function () { if (testFn() === true || now >= until) { - mainFn(); - return; + mainFn(); + return; } now += next; vAPI.setTimeout(check, next); - }; + }; - if ('sync' in dtls && dtls.sync === true) { + if ('sync' in dtls && dtls.sync === true) { check(); - } else { + } else { vAPI.setTimeout(check, 1); - } + } }; window.addEventListener('unload', function () { - // if (typeof vAPI.app.onShutdown === 'function') { + // if (typeof vAPI.app.onShutdown === 'function') { // vAPI.app.onShutdown(); - // } - - // IMPORTANT: cleanup tasks must be executed using LIFO order. - for (let i=cleanupTasks.length-1; i>=0; --i) { - try { - cleanupTasks[i](); - } catch (e) { - // Just in case a clean up task ends up throwing for - // no reason - console.error(e); - } - } - - // eMatrix: temporarily disabled - // if (cleanupTasks.length < expectedNumberOfCleanups) { + // } + + // IMPORTANT: cleanup tasks must be executed using LIFO order. + for (let i=cleanupTasks.length-1; i>=0; --i) { + try { + cleanupTasks[i](); + } catch (e) { + // Just in case a clean up task ends up throwing for + // no reason + console.error(e); + } + } + + // eMatrix: temporarily disabled + // if (cleanupTasks.length < expectedNumberOfCleanups) { // console.error - // ('eMatrix> Cleanup tasks performed: %s (out of %s)', + // ('eMatrix> Cleanup tasks performed: %s (out of %s)', // cleanupTasks.length, // expectedNumberOfCleanups); - // } + // } - // frameModule needs to be cleared too - Cu.import('chrome://ematrix/content/lib/FrameModule.jsm'); - contentObserver.unregister(); - Cu.unload('chrome://ematrix/content/lib/FrameModule.jsm'); + // frameModule needs to be cleared too + Cu.import('chrome://ematrix/content/lib/FrameModule.jsm'); + contentObserver.unregister(); + Cu.unload('chrome://ematrix/content/lib/FrameModule.jsm'); }); vAPI.noTabId = '-1'; vAPI.isBehindTheSceneTabId = function (tabId) { - return tabId.toString() === '-1'; + return tabId.toString() === '-1'; }; vAPI.lastError = function () { - return null; + return null; }; })(this); diff --git a/js/vapi-messaging.js b/js/vapi-messaging.js index afc18a1..5fb4b59 100644 --- a/js/vapi-messaging.js +++ b/js/vapi-messaging.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -29,109 +29,109 @@ Cu.import('chrome://ematrix/content/lib/CallbackWrapper.jsm'); vAPI.messaging = { - get globalMessageManager() { + get globalMessageManager() { return Cc['@mozilla.org/globalmessagemanager;1'] .getService(Ci.nsIMessageListenerManager); - }, - frameScript: vAPI.getURL('frameScript.js'), - listeners: {}, - defaultHandler: null, - NOOPFUNC: function(){}, - UNHANDLED: 'vAPI.messaging.notHandled' + }, + frameScript: vAPI.getURL('frameScript.js'), + listeners: {}, + defaultHandler: null, + NOOPFUNC: function(){}, + UNHANDLED: 'vAPI.messaging.notHandled' }; vAPI.messaging.listen = function (listenerName, callback) { - this.listeners[listenerName] = callback; + this.listeners[listenerName] = callback; }; vAPI.messaging.onMessage = function ({target, data}) { - let messageManager = target.messageManager; + let messageManager = target.messageManager; - if (!messageManager) { + if (!messageManager) { // Message came from a popup, and its message manager is // not usable. So instead we broadcast to the parent // window. messageManager = - vAPI.browser. - getOwnerWindow(target.webNavigation - .QueryInterface(Ci.nsIDocShell) - .chromeEventHandler).messageManager; - } - - let channelNameRaw = data.channelName; - let pos = channelNameRaw.indexOf('|'); - let channelName = channelNameRaw.slice(pos + 1); - - let callback = vAPI.messaging.NOOPFUNC; - if (data.requestId !== undefined) { + vAPI.browser. + getOwnerWindow(target.webNavigation + .QueryInterface(Ci.nsIDocShell) + .chromeEventHandler).messageManager; + } + + let channelNameRaw = data.channelName; + let pos = channelNameRaw.indexOf('|'); + let channelName = channelNameRaw.slice(pos + 1); + + let callback = vAPI.messaging.NOOPFUNC; + if (data.requestId !== undefined) { callback = CallbackWrapper.factory(messageManager, - channelName, - channelNameRaw.slice(0, pos), - data.requestId).callback; - } + channelName, + channelNameRaw.slice(0, pos), + data.requestId).callback; + } - let sender = { + let sender = { tab: { - id: vAPI.tabs.manager.tabIdFromTarget(target) + id: vAPI.tabs.manager.tabIdFromTarget(target) } - }; + }; - // Specific handler - let r = vAPI.messaging.UNHANDLED; - let listener = vAPI.messaging.listeners[channelName]; + // Specific handler + let r = vAPI.messaging.UNHANDLED; + let listener = vAPI.messaging.listeners[channelName]; - if (typeof listener === 'function') { + if (typeof listener === 'function') { r = listener(data.msg, sender, callback); - } - if (r !== vAPI.messaging.UNHANDLED) { + } + if (r !== vAPI.messaging.UNHANDLED) { return; - } + } - // Default handler - r = vAPI.messaging.defaultHandler(data.msg, sender, callback); - if (r !== vAPI.messaging.UNHANDLED) { + // Default handler + r = vAPI.messaging.defaultHandler(data.msg, sender, callback); + if (r !== vAPI.messaging.UNHANDLED) { return; - } + } - console.error('eMatrix> messaging > unknown request: %o', data); + console.error('eMatrix> messaging > unknown request: %o', data); - // Unhandled: Need to callback anyways in case caller expected - // an answer, or else there is a memory leak on caller's side - callback(); + // Unhandled: Need to callback anyways in case caller expected + // an answer, or else there is a memory leak on caller's side + callback(); }; vAPI.messaging.setup = function (defaultHandler) { - // Already setup? - if (this.defaultHandler !== null) { + // Already setup? + if (this.defaultHandler !== null) { return; - } + } - if (typeof defaultHandler !== 'function') { + if (typeof defaultHandler !== 'function') { defaultHandler = function () { - return vAPI.messaging.UNHANDLED; - }; - } + return vAPI.messaging.UNHANDLED; + }; + } - this.defaultHandler = defaultHandler; - this.globalMessageManager.addMessageListener(location.host - + ':background', - this.onMessage); - this.globalMessageManager.loadFrameScript(this.frameScript, true); + this.defaultHandler = defaultHandler; + this.globalMessageManager.addMessageListener(location.host + + ':background', + this.onMessage); + this.globalMessageManager.loadFrameScript(this.frameScript, true); - vAPI.addCleanUpTask(function () { + vAPI.addCleanUpTask(function () { let gmm = vAPI.messaging.globalMessageManager; gmm.removeDelayedFrameScript(vAPI.messaging.frameScript); gmm.removeMessageListener(location.host + ':background', - vAPI.messaging.onMessage); - }); + vAPI.messaging.onMessage); + }); }; vAPI.messaging.broadcast = function (message) { - this.globalMessageManager - .broadcastAsyncMessage(location.host + ':broadcast', - JSON.stringify({ - broadcast: true, - msg: message})); + this.globalMessageManager + .broadcastAsyncMessage(location.host + ':broadcast', + JSON.stringify({ + broadcast: true, + msg: message})); }; })(); diff --git a/js/vapi-net.js b/js/vapi-net.js index 41cbc4f..9212c7b 100644 --- a/js/vapi-net.js +++ b/js/vapi-net.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -31,42 +31,42 @@ vAPI.net = {}; vAPI.net.registerListeners = function () { - this.onBeforeRequest.types = this.onBeforeRequest.types - ? new Set(this.onBeforeRequest.types) - : null; + this.onBeforeRequest.types = this.onBeforeRequest.types + ? new Set(this.onBeforeRequest.types) + : null; - this.onBeforeSendHeaders.types = this.onBeforeSendHeaders.types - ? new Set(this.onBeforeSendHeaders.types) - : null; + this.onBeforeSendHeaders.types = this.onBeforeSendHeaders.types + ? new Set(this.onBeforeSendHeaders.types) + : null; - let shouldLoadListenerMessageName = location.host + ':shouldLoad'; - let shouldLoadListener = function (e) { + let shouldLoadListenerMessageName = location.host + ':shouldLoad'; + let shouldLoadListener = function (e) { let details = e.data; let pendingReq = - PendingRequestBuffer.createRequest(details.url); + PendingRequestBuffer.createRequest(details.url); pendingReq.rawType = details.rawType; pendingReq.tabId = vAPI.tabs.manager.tabIdFromTarget(e.target); - }; + }; - // https://github.com/gorhill/uMatrix/issues/200 - // We need this only for Firefox 34 and less: the tab id is derived from - // the origin of the message. - if (!vAPI.modernFirefox) { + // https://github.com/gorhill/uMatrix/issues/200 + // We need this only for Firefox 34 and less: the tab id is derived from + // the origin of the message. + if (!vAPI.modernFirefox) { vAPI.messaging.globalMessageManager - .addMessageListener(shouldLoadListenerMessageName, - shouldLoadListener); - } + .addMessageListener(shouldLoadListenerMessageName, + shouldLoadListener); + } - vAPI.httpObserver.register(); + vAPI.httpObserver.register(); - vAPI.addCleanUpTask(function () { + vAPI.addCleanUpTask(function () { if (!vAPI.modernFirefox) { - vAPI.messaging.globalMessageManager - .removeMessageListener(shouldLoadListenerMessageName, - shouldLoadListener); + vAPI.messaging.globalMessageManager + .removeMessageListener(shouldLoadListenerMessageName, + shouldLoadListener); } vAPI.httpObserver.unregister(); - }); + }); }; })(); diff --git a/js/vapi-popup.js b/js/vapi-popup.js index 0859e81..12280e7 100644 --- a/js/vapi-popup.js +++ b/js/vapi-popup.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ diff --git a/js/vapi-storage.js b/js/vapi-storage.js index 8e46b90..bcc3a9a 100644 --- a/js/vapi-storage.js +++ b/js/vapi-storage.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -29,60 +29,60 @@ // API matches that of chrome.storage.local: // https://developer.chrome.com/extensions/storage vAPI.storage = (function () { - let db = null; - let vacuumTimer = null; + let db = null; + let vacuumTimer = null; - let close = function () { + let close = function () { if (vacuumTimer !== null) { - clearTimeout(vacuumTimer); - vacuumTimer = null; + clearTimeout(vacuumTimer); + vacuumTimer = null; } if (db === null) { - return; + return; } db.asyncClose(); db = null; - }; + }; - let open = function () { + let open = function () { if (db !== null) { - return db; + return db; } // Create path let path = Services.dirsvc.get('ProfD', Ci.nsIFile); path.append('ematrix-data'); if (!path.exists()) { - path.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt('0774', 8)); + path.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt('0774', 8)); } if (!path.isDirectory()) { - throw Error('Should be a directory...'); + throw Error('Should be a directory...'); } - let path2 = Services.dirsvc.get('ProfD', Ci.nsIFile); - path2.append('extension-data'); - path2.append(location.host + '.sqlite'); - if (path2.exists()) { - path2.moveTo(path, location.host+'.sqlite'); - } + let path2 = Services.dirsvc.get('ProfD', Ci.nsIFile); + path2.append('extension-data'); + path2.append(location.host + '.sqlite'); + if (path2.exists()) { + path2.moveTo(path, location.host+'.sqlite'); + } - path.append(location.host + '.sqlite'); + path.append(location.host + '.sqlite'); // Open database try { - db = Services.storage.openDatabase(path); - if (db.connectionReady === false) { + db = Services.storage.openDatabase(path); + if (db.connectionReady === false) { db.asyncClose(); db = null; - } + } } catch (ex) { - // Ignore + // Ignore } if (db === null) { - return null; + return null; } // Database was opened, register cleanup task @@ -90,240 +90,240 @@ // Setup database db.createAsyncStatement('CREATE TABLE IF NOT EXISTS ' - +'"settings" ("name" ' - +'TEXT PRIMARY KEY NOT NULL, ' - +'"value" TEXT);') - .executeAsync(); + +'"settings" ("name" ' + +'TEXT PRIMARY KEY NOT NULL, ' + +'"value" TEXT);') + .executeAsync(); if (vacuum !== null) { - vacuumTimer = vAPI.setTimeout(vacuum, 60000); + vacuumTimer = vAPI.setTimeout(vacuum, 60000); } return db; - }; + }; - // Vacuum only once, and only while idle - let vacuum = function () { + // Vacuum only once, and only while idle + let vacuum = function () { vacuumTimer = null; if (db === null) { - return; + return; } let idleSvc = - Cc['@mozilla.org/widget/idleservice;1'] - .getService(Ci.nsIIdleService); + Cc['@mozilla.org/widget/idleservice;1'] + .getService(Ci.nsIIdleService); if (idleSvc.idleTime < 60000) { - vacuumTimer = vAPI.setTimeout(vacuum, 60000); - return; + vacuumTimer = vAPI.setTimeout(vacuum, 60000); + return; } db.createAsyncStatement('VACUUM').executeAsync(); vacuum = null; - }; + }; - // Execute a query - let runStatement = function (stmt, callback) { + // Execute a query + let runStatement = function (stmt, callback) { let result = {}; stmt.executeAsync({ - handleResult: function (rows) { + handleResult: function (rows) { if (!rows || typeof callback !== 'function') { - return; + return; } let row; while ((row = rows.getNextRow())) { - // we assume that there will be two columns, since we're - // using it only for preferences - // eMatrix: the above comment is obsolete - // (it's not used just for preferences - // anymore), but we still expect two columns. - let res = row.getResultByIndex(0); - result[res] = row.getResultByIndex(1); + // we assume that there will be two columns, since we're + // using it only for preferences + // eMatrix: the above comment is obsolete + // (it's not used just for preferences + // anymore), but we still expect two columns. + let res = row.getResultByIndex(0); + result[res] = row.getResultByIndex(1); } - }, - handleCompletion: function (reason) { + }, + handleCompletion: function (reason) { if (typeof callback === 'function' && reason === 0) { - callback(result); + callback(result); } - }, - handleError: function (error) { + }, + handleError: function (error) { console.error('SQLite error ', error.result, error.message); // Caller expects an answer regardless of failure. if (typeof callback === 'function' ) { - callback(null); + callback(null); } - }, + }, }); - }; + }; - let bindNames = function (stmt, names) { + let bindNames = function (stmt, names) { if (Array.isArray(names) === false || names.length === 0) { - return; + return; } let params = stmt.newBindingParamsArray(); - for (let i=names.length-1; i>=0; --i) { - let bp = params.newBindingParams(); - bp.bindByName('name', names[i]); - params.addParams(bp); + for (let i=names.length-1; i>=0; --i) { + let bp = params.newBindingParams(); + bp.bindByName('name', names[i]); + params.addParams(bp); } stmt.bindParameters(params); - }; + }; - let clear = function (callback) { + let clear = function (callback) { if (open() === null) { - if (typeof callback === 'function') { + if (typeof callback === 'function') { callback(); - } - return; + } + return; } runStatement(db.createAsyncStatement('DELETE FROM "settings";'), - callback); - }; + callback); + }; - let getBytesInUse = function (keys, callback) { + let getBytesInUse = function (keys, callback) { if (typeof callback !== 'function') { - return; + return; } if (open() === null) { - callback(0); - return; + callback(0); + return; } let stmt; if (Array.isArray(keys)) { - stmt = db.createAsyncStatement('SELECT "size" AS "size", ' - +'SUM(LENGTH("value")) ' - +'FROM "settings" WHERE ' - +'"name" = :name'); - bindNames(keys); + stmt = db.createAsyncStatement('SELECT "size" AS "size", ' + +'SUM(LENGTH("value")) ' + +'FROM "settings" WHERE ' + +'"name" = :name'); + bindNames(keys); } else { - stmt = db.createAsyncStatement('SELECT "size" AS "size", ' - +'SUM(LENGTH("value")) ' - +'FROM "settings"'); + stmt = db.createAsyncStatement('SELECT "size" AS "size", ' + +'SUM(LENGTH("value")) ' + +'FROM "settings"'); } runStatement(stmt, function (result) { - callback(result.size); + callback(result.size); }); - }; + }; - let read = function (details, callback) { + let read = function (details, callback) { if (typeof callback !== 'function') { - return; + return; } let prepareResult = function (result) { - for (let key in result) { + for (let key in result) { if (result.hasOwnProperty(key) === false) { - continue; + continue; } result[key] = JSON.parse(result[key]); - } + } - if (typeof details === 'object' && details !== null) { + if (typeof details === 'object' && details !== null) { for (let key in details) { - if (result.hasOwnProperty(key) === false) { + if (result.hasOwnProperty(key) === false) { result[key] = details[key]; - } + } } - } + } - callback(result); + callback(result); }; if (open() === null) { - prepareResult({}); - return; + prepareResult({}); + return; } let names = []; if (details !== null) { - if (Array.isArray(details)) { + if (Array.isArray(details)) { names = details; - } else if (typeof details === 'object') { + } else if (typeof details === 'object') { names = Object.keys(details); - } else { + } else { names = [details.toString()]; - } + } } let stmt; if (names.length === 0) { - stmt = db.createAsyncStatement('SELECT * FROM "settings"'); + stmt = db.createAsyncStatement('SELECT * FROM "settings"'); } else { - stmt = db.createAsyncStatement('SELECT * FROM "settings" ' - +'WHERE "name" = :name'); - bindNames(stmt, names); + stmt = db.createAsyncStatement('SELECT * FROM "settings" ' + +'WHERE "name" = :name'); + bindNames(stmt, names); } runStatement(stmt, prepareResult); - }; + }; - let remove = function (keys, callback) { + let remove = function (keys, callback) { if (open() === null) { - if (typeof callback === 'function') { + if (typeof callback === 'function') { callback(); - } - return; + } + return; } var stmt = db.createAsyncStatement('DELETE FROM "settings" ' - +'WHERE "name" = :name'); + +'WHERE "name" = :name'); bindNames(stmt, typeof keys === 'string' ? [keys] : keys); runStatement(stmt, callback); - }; + }; - let write = function (details, callback) { + let write = function (details, callback) { if (open() === null) { - if (typeof callback === 'function') { + if (typeof callback === 'function') { callback(); - } - return; + } + return; } let stmt = db.createAsyncStatement('INSERT OR REPLACE INTO ' - +'"settings" ("name", "value") ' - +'VALUES(:name, :value)'); + +'"settings" ("name", "value") ' + +'VALUES(:name, :value)'); let params = stmt.newBindingParamsArray(); for (let key in details) { - if (details.hasOwnProperty(key) === false) { + if (details.hasOwnProperty(key) === false) { continue; - } + } - let bp = params.newBindingParams(); - bp.bindByName('name', key); - bp.bindByName('value', JSON.stringify(details[key])); - params.addParams(bp); + let bp = params.newBindingParams(); + bp.bindByName('name', key); + bp.bindByName('value', JSON.stringify(details[key])); + params.addParams(bp); } if (params.length === 0) { - return; + return; } stmt.bindParameters(params); runStatement(stmt, callback); - }; + }; - // Export API - var api = { + // Export API + var api = { QUOTA_BYTES: 100 * 1024 * 1024, clear: clear, get: read, getBytesInUse: getBytesInUse, remove: remove, set: write - }; + }; - return api; + return api; })(); vAPI.cacheStorage = vAPI.storage; diff --git a/js/vapi-tabs.js b/js/vapi-tabs.js index 02c3644..e5eab6b 100644 --- a/js/vapi-tabs.js +++ b/js/vapi-tabs.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -29,548 +29,548 @@ vAPI.tabs = {}; vAPI.tabs.registerListeners = function() { - vAPI.tabs.manager.start(); + vAPI.tabs.manager.start(); }; vAPI.tabs.get = function (tabId, callback) { - // eMatrix: the following might be obsoleted (though probably - // still relevant at least for Pale Moon.) - // - // Firefox: - // - // browser -> ownerDocument -> defaultView -> gBrowser -> browsers --+ - // ^ | - // | | - // +--------------------------------------------------------------+ - // - // browser (browser) - // contentTitle - // currentURI - // ownerDocument (XULDocument) - // defaultView (ChromeWindow) - // gBrowser (tabbrowser OR browser) - // browsers (browser) - // selectedBrowser - // selectedTab - // tabs (tab.tabbrowser-tab) - // - // Fennec: (what I figured so far) - // - // tab -> browser windows -> window -> BrowserApp -> tabs --+ - // ^ window | - // | | - // +-----------------------------------------------------------+ - // - // tab - // browser - // [manual search to go back to tab from list of windows] - let browser; - - if (tabId === null) { + // eMatrix: the following might be obsoleted (though probably + // still relevant at least for Pale Moon.) + // + // Firefox: + // + // browser -> ownerDocument -> defaultView -> gBrowser -> browsers --+ + // ^ | + // | | + // +--------------------------------------------------------------+ + // + // browser (browser) + // contentTitle + // currentURI + // ownerDocument (XULDocument) + // defaultView (ChromeWindow) + // gBrowser (tabbrowser OR browser) + // browsers (browser) + // selectedBrowser + // selectedTab + // tabs (tab.tabbrowser-tab) + // + // Fennec: (what I figured so far) + // + // tab -> browser windows -> window -> BrowserApp -> tabs --+ + // ^ window | + // | | + // +-----------------------------------------------------------+ + // + // tab + // browser + // [manual search to go back to tab from list of windows] + let browser; + + if (tabId === null) { browser = vAPI.tabs.manager.currentBrowser(); tabId = vAPI.tabs.manager.tabIdFromTarget(browser); - } else { + } else { browser = vAPI.tabs.manager.browserFromTabId(tabId); - } + } - // For internal use - if (typeof callback !== 'function') { + // For internal use + if (typeof callback !== 'function') { return browser; - } + } - if (!browser || !browser.currentURI) { + if (!browser || !browser.currentURI) { callback(); return; - } + } - let win = vAPI.browser.getOwnerWindow(browser); - let tabBrowser = vAPI.browser.getTabBrowser(win); + let win = vAPI.browser.getOwnerWindow(browser); + let tabBrowser = vAPI.browser.getTabBrowser(win); - callback({ + callback({ id: tabId, windowId: vAPI.window.idFromWindow(win), active: tabBrowser !== null - && browser === tabBrowser.selectedBrowser, + && browser === tabBrowser.selectedBrowser, url: browser.currentURI.asciiSpec, title: browser.contentTitle - }); + }); }; vAPI.tabs.getAllSync = function (window) { - let win; - let tabs = []; + let win; + let tabs = []; - for (let win of vAPI.window.getWindows()) { + for (let win of vAPI.window.getWindows()) { if (window && window !== win) { - continue; + continue; } let tabBrowser = vAPI.browser.getTabBrowser(win); if (tabBrowser === null) { - continue; + continue; } // This can happens if a tab-less window is currently opened. // Example of a tab-less window: one opened from clicking // "View Page Source". if (!tabBrowser.tabs) { - continue; + continue; } for (let tab of tabBrowser.tabs) { - tabs.push(tab); + tabs.push(tab); } - } + } - return tabs; + return tabs; }; vAPI.tabs.getAll = function (callback) { - let tabs = []; + let tabs = []; - for (let browser of vAPI.tabs.manager.browsers()) { + for (let browser of vAPI.tabs.manager.browsers()) { let tab = vAPI.tabs.manager.tabFromBrowser(browser); if (tab === null) { - continue; + continue; } if (tab.hasAttribute('pending')) { - continue; + continue; } tabs.push({ - id: vAPI.tabs.manager.tabIdFromTarget(browser), - url: browser.currentURI.asciiSpec + id: vAPI.tabs.manager.tabIdFromTarget(browser), + url: browser.currentURI.asciiSpec }); - } + } - callback(tabs); + callback(tabs); }; vAPI.tabs.open = function (details) { - // properties of the details object: - // + url - the address that will be opened - // + tabId:- the tab is used if set, instead of creating a new one - // + index: - undefined: end of the list, -1: following tab, or - // after index - // + active: - opens the tab in background - true and undefined: - // foreground - // + select: - if a tab is already opened with that url, then - // select it instead of opening a new one - if (!details.url) { + // properties of the details object: + // + url - the address that will be opened + // + tabId:- the tab is used if set, instead of creating a new one + // + index: - undefined: end of the list, -1: following tab, or + // after index + // + active: - opens the tab in background - true and undefined: + // foreground + // + select: - if a tab is already opened with that url, then + // select it instead of opening a new one + if (!details.url) { return null; - } + } - // extension pages - if (/^[\w-]{2,}:/.test(details.url) === false) { + // extension pages + if (/^[\w-]{2,}:/.test(details.url) === false) { details.url = vAPI.getURL(details.url); - } + } - if (details.select) { + if (details.select) { let URI = Services.io.newURI(details.url, null, null); for (let tab of this.getAllSync()) { - let browser = vAPI.tabs.manager.browserFromTarget(tab); + let browser = vAPI.tabs.manager.browserFromTarget(tab); - // https://github.com/gorhill/uBlock/issues/2558 - if (browser === null) { - continue; - } + // https://github.com/gorhill/uBlock/issues/2558 + if (browser === null) { + continue; + } - // Or simply .equals if we care about the fragment - if (URI.equalsExceptRef(browser.currentURI) === false) { + // Or simply .equals if we care about the fragment + if (URI.equalsExceptRef(browser.currentURI) === false) { continue; - } + } - this.select(tab); + this.select(tab); - // Update URL if fragment is different - if (URI.equals(browser.currentURI) === false) { + // Update URL if fragment is different + if (URI.equals(browser.currentURI) === false) { browser.loadURI(URI.asciiSpec); - } + } - return; + return; } - } + } - if (details.active === undefined) { + if (details.active === undefined) { details.active = true; - } + } - if (details.tabId) { + if (details.tabId) { let tab = vAPI.tabs.manager.browserFromTabId(details.tabId); if (tab) { - vAPI.tabs.manager.browserFromTarget(tab).loadURI(details.url); - return; + vAPI.tabs.manager.browserFromTarget(tab).loadURI(details.url); + return; } - } + } - // Open in a standalone window - if (details.popup === true) { + // Open in a standalone window + if (details.popup === true) { Services.ww.openWindow(self, - details.url, - null, - 'location=1,menubar=1,personalbar=1,' - +'resizable=1,toolbar=1', - null); + details.url, + null, + 'location=1,menubar=1,personalbar=1,' + +'resizable=1,toolbar=1', + null); return; - } + } - let win = vAPI.window.getCurrentWindow(); - let tabBrowser = vAPI.browser.getTabBrowser(win); + let win = vAPI.window.getCurrentWindow(); + let tabBrowser = vAPI.browser.getTabBrowser(win); - if (tabBrowser === null) { + if (tabBrowser === null) { return; - } + } - if (details.index === -1) { + if (details.index === -1) { details.index = - tabBrowser.browsers.indexOf(tabBrowser.selectedBrowser) + 1; - } + tabBrowser.browsers.indexOf(tabBrowser.selectedBrowser) + 1; + } - let tab = tabBrowser.loadOneTab(details.url, { - inBackground: !details.active - }); + let tab = tabBrowser.loadOneTab(details.url, { + inBackground: !details.active + }); - if (details.index !== undefined) { + if (details.index !== undefined) { tabBrowser.moveTabTo(tab, details.index); - } + } }; vAPI.tabs.replace = function (tabId, url) { - // Replace the URL of a tab. Noop if the tab does not exist. - let targetURL = url; + // Replace the URL of a tab. Noop if the tab does not exist. + let targetURL = url; - // extension pages - if (/^[\w-]{2,}:/.test(targetURL) !== true) { + // extension pages + if (/^[\w-]{2,}:/.test(targetURL) !== true) { targetURL = vAPI.getURL(targetURL); - } + } - let browser = vAPI.tabs.manager.browserFromTabId(tabId); - if (browser) { + let browser = vAPI.tabs.manager.browserFromTabId(tabId); + if (browser) { browser.loadURI(targetURL); - } + } }; function removeInternal(tab, tabBrowser) { - if (tabBrowser) { - tabBrowser.removeTab(tab); - } + if (tabBrowser) { + tabBrowser.removeTab(tab); + } } vAPI.tabs.remove = function (tabId) { - let browser = vAPI.tabs.manager.browserFromTabId(tabId); - if (!browser) { + let browser = vAPI.tabs.manager.browserFromTabId(tabId); + if (!browser) { return; - } + } - let tab = vAPI.tabs.manager.tabFromBrowser(browser); - if (!tab) { + let tab = vAPI.tabs.manager.tabFromBrowser(browser); + if (!tab) { return; - } + } - removeInternal(tab, - vAPI.browser.getTabBrowser - (vAPI.browser.getOwnerWindow(browser))); + removeInternal(tab, + vAPI.browser.getTabBrowser + (vAPI.browser.getOwnerWindow(browser))); }; vAPI.tabs.reload = function (tabId) { - let browser = vAPI.tabs.manager.browserFromTabId(tabId); - if (!browser) { + let browser = vAPI.tabs.manager.browserFromTabId(tabId); + if (!browser) { return; - } + } - browser.webNavigation.reload(Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE); + browser.webNavigation.reload(Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE); }; vAPI.tabs.select = function (tab) { - if (typeof tab !== 'object') { + if (typeof tab !== 'object') { tab = vAPI.tabs.manager - .tabFromBrowser(vAPI.tabs.manager.browserFromTabId(tab)); - } - if (!tab) { + .tabFromBrowser(vAPI.tabs.manager.browserFromTabId(tab)); + } + if (!tab) { return; - } + } - // https://github.com/gorhill/uBlock/issues/470 - let win = vAPI.browser.getOwnerWindow(tab); - win.focus(); + // https://github.com/gorhill/uBlock/issues/470 + let win = vAPI.browser.getOwnerWindow(tab); + win.focus(); - let tabBrowser = vAPI.browser.getTabBrowser(win); - if (tabBrowser) { + let tabBrowser = vAPI.browser.getTabBrowser(win); + if (tabBrowser) { tabBrowser.selectedTab = tab; - } + } }; vAPI.tabs.injectScript = function (tabId, details, callback) { - let browser = vAPI.tabs.manager.browserFromTabId(tabId); - if (!browser) { + let browser = vAPI.tabs.manager.browserFromTabId(tabId); + if (!browser) { return; - } + } - if (typeof details.file !== 'string') { + if (typeof details.file !== 'string') { return; - } - - details.file = vAPI.getURL(details.file); - browser.messageManager.sendAsyncMessage(location.host + ':broadcast', - JSON.stringify({ - broadcast: true, - channelName: 'vAPI', - msg: { - cmd: 'injectScript', - details: details - } - })); - - if (typeof callback === 'function') { + } + + details.file = vAPI.getURL(details.file); + browser.messageManager.sendAsyncMessage(location.host + ':broadcast', + JSON.stringify({ + broadcast: true, + channelName: 'vAPI', + msg: { + cmd: 'injectScript', + details: details + } + })); + + if (typeof callback === 'function') { vAPI.setTimeout(callback, 13); - } + } }; vAPI.tabs.manager = (function () { - // TODO: find out whether we need a janitor to take care of stale entries. + // TODO: find out whether we need a janitor to take care of stale entries. - // https://github.com/gorhill/uMatrix/issues/540 - // Use only weak references to hold onto browser references. - let browserToTabIdMap = new WeakMap(); - let tabIdToBrowserMap = new Map(); - let tabIdGenerator = 1; + // https://github.com/gorhill/uMatrix/issues/540 + // Use only weak references to hold onto browser references. + let browserToTabIdMap = new WeakMap(); + let tabIdToBrowserMap = new Map(); + let tabIdGenerator = 1; - let indexFromBrowser = function (browser) { + let indexFromBrowser = function (browser) { if (!browser) { - return -1; + return -1; } - let win = vAPI.browser.getOwnerWindow(browser); + let win = vAPI.browser.getOwnerWindow(browser); if (!win) { - return -1; + return -1; } let tabBrowser = vAPI.browser.getTabBrowser(win); if (tabBrowser === null) { - return -1; + return -1; } // This can happen, for example, the `view-source:` // window, there is no tabbrowser object, the browser // object sits directly in the window. if (tabBrowser === browser) { - return 0; + return 0; } return tabBrowser.browsers.indexOf(browser); - }; + }; - let indexFromTarget = function (target) { + let indexFromTarget = function (target) { return indexFromBrowser(browserFromTarget(target)); - }; + }; - let tabFromBrowser = function (browser) { + let tabFromBrowser = function (browser) { let i = indexFromBrowser(browser); if (i === -1) { - return null; + return null; } let win = vAPI.browser.getOwnerWindow(browser); if (!win) { - return null; + return null; } let tabBrowser = vAPI.browser.getTabBrowser(win); if (tabBrowser === null) { - return null; + return null; } if (!tabBrowser.tabs || i >= tabBrowser.tabs.length) { - return null; + return null; } return tabBrowser.tabs[i]; - }; + }; - let browserFromTarget = function (target) { + let browserFromTarget = function (target) { if (!target) { - return null; + return null; } if (target.linkedPanel) { - // target is a tab - target = target.linkedBrowser; + // target is a tab + target = target.linkedBrowser; } if (target.localName !== 'browser') { - return null; + return null; } return target; - }; + }; - let tabIdFromTarget = function (target) { + let tabIdFromTarget = function (target) { let browser = browserFromTarget(target); if (browser === null) { - return vAPI.noTabId; + return vAPI.noTabId; } let tabId = browserToTabIdMap.get(browser); if (tabId === undefined) { - tabId = '' + tabIdGenerator++; - browserToTabIdMap.set(browser, tabId); - tabIdToBrowserMap.set(tabId, Cu.getWeakReference(browser)); + tabId = '' + tabIdGenerator++; + browserToTabIdMap.set(browser, tabId); + tabIdToBrowserMap.set(tabId, Cu.getWeakReference(browser)); } return tabId; - }; + }; - let browserFromTabId = function (tabId) { + let browserFromTabId = function (tabId) { let weakref = tabIdToBrowserMap.get(tabId); let browser = weakref && weakref.get(); return browser || null; - }; + }; - let currentBrowser = function () { + let currentBrowser = function () { let win = vAPI.window.getCurrentWindow(); // https://github.com/gorhill/uBlock/issues/399 // getTabBrowser() can return null at browser launch time. let tabBrowser = vAPI.browser.getTabBrowser(win); if (tabBrowser === null) { - return null; + return null; } return browserFromTarget(tabBrowser.selectedTab); - }; + }; - let removeBrowserEntry = function (tabId, browser) { + let removeBrowserEntry = function (tabId, browser) { if (tabId && tabId !== vAPI.noTabId) { - vAPI.tabs.onClosed(tabId); - delete vAPI.toolbarButton.tabs[tabId]; - tabIdToBrowserMap.delete(tabId); + vAPI.tabs.onClosed(tabId); + delete vAPI.toolbarButton.tabs[tabId]; + tabIdToBrowserMap.delete(tabId); } if (browser) { - browserToTabIdMap.delete(browser); + browserToTabIdMap.delete(browser); } - }; + }; - let removeTarget = function (target) { + let removeTarget = function (target) { onClose({ - target: target - }); - }; + target: target + }); + }; - let getAllBrowsers = function () { + let getAllBrowsers = function () { let browsers = []; - for (let [tabId, weakref] of tabIdToBrowserMap) { - let browser = weakref.get(); + for (let [tabId, weakref] of tabIdToBrowserMap) { + let browser = weakref.get(); - // TODO: Maybe call removeBrowserEntry() if the - // browser no longer exists? - if (browser) { + // TODO: Maybe call removeBrowserEntry() if the + // browser no longer exists? + if (browser) { browsers.push(browser); - } + } } return browsers; - }; - - // var onOpen = function (target) { - // var tabId = tabIdFromTarget(target); - // var browser = browserFromTabId(tabId); - // vAPI.tabs.onNavigation({ - // frameId: 0, - // tabId: tabId, - // url: browser.currentURI.asciiSpec, - // }); - // }; - - var onShow = function ({target}) { + }; + + // var onOpen = function (target) { + // var tabId = tabIdFromTarget(target); + // var browser = browserFromTabId(tabId); + // vAPI.tabs.onNavigation({ + // frameId: 0, + // tabId: tabId, + // url: browser.currentURI.asciiSpec, + // }); + // }; + + var onShow = function ({target}) { tabIdFromTarget(target); - }; + }; - var onClose = function ({target}) { + var onClose = function ({target}) { // target is tab in Firefox, browser in Fennec let browser = browserFromTarget(target); let tabId = browserToTabIdMap.get(browser); removeBrowserEntry(tabId, browser); - }; + }; - var onSelect = function ({target}) { - // This is an entry point: when creating a new tab, it is - // not always reported through onLocationChanged... - // Sigh. It is "reported" here however. + var onSelect = function ({target}) { + // This is an entry point: when creating a new tab, it is + // not always reported through onLocationChanged... + // Sigh. It is "reported" here however. let browser = browserFromTarget(target); let tabId = browserToTabIdMap.get(browser); - if (tabId === undefined) { - tabId = tabIdFromTarget(target); - vAPI.tabs.onNavigation({ + if (tabId === undefined) { + tabId = tabIdFromTarget(target); + vAPI.tabs.onNavigation({ frameId: 0, tabId: tabId, url: browser.currentURI.asciiSpec - }); + }); } vAPI.setIcon(tabId, vAPI.browser.getOwnerWindow(target)); - }; + }; - let locationChangedMessageName = location.host + ':locationChanged'; + let locationChangedMessageName = location.host + ':locationChanged'; - let onLocationChanged = function (e) { + let onLocationChanged = function (e) { let details = e.data; // Ignore notifications related to our popup if (details.url.lastIndexOf(vAPI.getURL('popup.html'), 0) === 0) { - return; + return; } let browser = e.target; let tabId = tabIdFromTarget(browser); if (tabId === vAPI.noTabId) { - return; + return; } // LOCATION_CHANGE_SAME_DOCUMENT = "did not load a new document" if (details.flags - & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) { - vAPI.tabs.onUpdated(tabId, {url: details.url}, { + & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) { + vAPI.tabs.onUpdated(tabId, {url: details.url}, { frameId: 0, tabId: tabId, url: browser.currentURI.asciiSpec - }); - return; + }); + return; } // https://github.com/chrisaljoudi/uBlock/issues/105 // Allow any kind of pages vAPI.tabs.onNavigation({ - frameId: 0, - tabId: tabId, - url: details.url + frameId: 0, + tabId: tabId, + url: details.url }); - }; + }; - let attachToTabBrowser = function (window) { + let attachToTabBrowser = function (window) { if (typeof vAPI.toolbarButton.attachToNewWindow === 'function') { - vAPI.toolbarButton.attachToNewWindow(window); + vAPI.toolbarButton.attachToNewWindow(window); } let tabBrowser = vAPI.browser.getTabBrowser(window); if (tabBrowser === null) { - return; + return; } let tabContainer; if (tabBrowser.deck) { // Fennec - tabContainer = tabBrowser.deck; + tabContainer = tabBrowser.deck; } else if (tabBrowser.tabContainer) { - // Firefox - tabContainer = tabBrowser.tabContainer; + // Firefox + tabContainer = tabBrowser.tabContainer; } // https://github.com/gorhill/uBlock/issues/697 @@ -579,20 +579,20 @@ // of session restore -- it is set *after* the event is // fired in such case. if (tabContainer) { - tabContainer.addEventListener('TabShow', onShow); - tabContainer.addEventListener('TabClose', onClose); - // when new window is opened TabSelect doesn't run on - // the selected tab? - tabContainer.addEventListener('TabSelect', onSelect); + tabContainer.addEventListener('TabShow', onShow); + tabContainer.addEventListener('TabClose', onClose); + // when new window is opened TabSelect doesn't run on + // the selected tab? + tabContainer.addEventListener('TabSelect', onSelect); } - }; + }; - var canAttachToTabBrowser = function (window) { - // https://github.com/gorhill/uBlock/issues/906 - // Ensure the environment is ready before trying to attaching. + var canAttachToTabBrowser = function (window) { + // https://github.com/gorhill/uBlock/issues/906 + // Ensure the environment is ready before trying to attaching. let document = window && window.document; if (!document || document.readyState !== 'complete') { - return false; + return false; } // On some platforms, the tab browser isn't immediately @@ -602,28 +602,28 @@ // attaching ourself to the window. let tabBrowser = vAPI.browser.getTabBrowser(window); if (tabBrowser === null) { - return false; + return false; } return vAPI.window.toBrowserWindow(window) !== null; - }; + }; - let onWindowLoad = function (win) { + let onWindowLoad = function (win) { vAPI.deferUntil(canAttachToTabBrowser.bind(null, win), - attachToTabBrowser.bind(null, win)); - }; + attachToTabBrowser.bind(null, win)); + }; - let onWindowUnload = function (win) { + let onWindowUnload = function (win) { let tabBrowser = vAPI.browser.getTabBrowser(win); if (tabBrowser === null) { - return; + return; } let tabContainer = tabBrowser.tabContainer; if (tabContainer) { - tabContainer.removeEventListener('TabShow', onShow); - tabContainer.removeEventListener('TabClose', onClose); - tabContainer.removeEventListener('TabSelect', onSelect); + tabContainer.removeEventListener('TabShow', onShow); + tabContainer.removeEventListener('TabClose', onClose); + tabContainer.removeEventListener('TabSelect', onSelect); } // https://github.com/gorhill/uBlock/issues/574 @@ -631,85 +631,85 @@ // sometimes the window IS the tab. let tabs; if (tabBrowser.tabs) { - tabs = tabBrowser.tabs; + tabs = tabBrowser.tabs; } else if (tabBrowser.localName === 'browser') { - tabs = [tabBrowser]; + tabs = [tabBrowser]; } else { - tabs = []; + tabs = []; } let browser; - let URI; - let tabId; - for (let i=tabs.length-1; i>=0; --i) { - let tab = tabs[i]; - browser = browserFromTarget(tab); - if (browser === null) { + let URI; + let tabId; + for (let i=tabs.length-1; i>=0; --i) { + let tab = tabs[i]; + browser = browserFromTarget(tab); + if (browser === null) { continue; - } + } - URI = browser.currentURI; - // Close extension tabs - if (URI.schemeIs('chrome') && URI.host === location.host) { + URI = browser.currentURI; + // Close extension tabs + if (URI.schemeIs('chrome') && URI.host === location.host) { removeInternal(tab, vAPI.browser.getTabBrowser(win)); - } + } - tabId = browserToTabIdMap.get(browser); - if (tabId !== undefined) { + tabId = browserToTabIdMap.get(browser); + if (tabId !== undefined) { removeBrowserEntry(tabId, browser); tabIdToBrowserMap.delete(tabId); - } - browserToTabIdMap.delete(browser); + } + browserToTabIdMap.delete(browser); } - }; + }; - var start = function () { - // Initialize map with existing active tabs + var start = function () { + // Initialize map with existing active tabs let tabBrowser; - let tabs; + let tabs; for (let win of vAPI.window.getWindows()) { - onWindowLoad(win); + onWindowLoad(win); - tabBrowser = vAPI.browser.getTabBrowser(win); - if (tabBrowser === null) { + tabBrowser = vAPI.browser.getTabBrowser(win); + if (tabBrowser === null) { continue; - } + } - for (let tab of tabBrowser.tabs) { + for (let tab of tabBrowser.tabs) { if (!tab.hasAttribute('pending')) { - tabIdFromTarget(tab); + tabIdFromTarget(tab); } - } + } } vAPI.window.onOpenWindow = onWindowLoad; vAPI.window.onCloseWindow = onWindowUnload; vAPI.messaging.globalMessageManager - .addMessageListener(locationChangedMessageName, - onLocationChanged); - }; + .addMessageListener(locationChangedMessageName, + onLocationChanged); + }; - let stop = function () { + let stop = function () { vAPI.window.onOpenWindow = null; vAPI.window.onCloseWindow = null; vAPI.messaging.globalMessageManager - .removeMessageListener(locationChangedMessageName, - onLocationChanged); + .removeMessageListener(locationChangedMessageName, + onLocationChanged); for (let win of vAPI.window.getWindows()) { - onWindowUnload(win); + onWindowUnload(win); } browserToTabIdMap = new WeakMap(); tabIdToBrowserMap.clear(); - }; + }; - vAPI.addCleanUpTask(stop); + vAPI.addCleanUpTask(stop); - return { + return { browsers: getAllBrowsers, browserFromTabId: browserFromTabId, browserFromTarget: browserFromTarget, @@ -719,6 +719,6 @@ start: start, tabFromBrowser: tabFromBrowser, tabIdFromTarget: tabIdFromTarget - }; + }; })(); })(); diff --git a/js/vapi-window.js b/js/vapi-window.js index 9e35db8..c7baede 100644 --- a/js/vapi-window.js +++ b/js/vapi-window.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -27,157 +27,157 @@ (function () { vAPI.window = (function () { - let windowToIdMap = new Map(); - let windowIdGenerator = 1; - let api = { + let windowToIdMap = new Map(); + let windowIdGenerator = 1; + let api = { onOpenWindow: null, onCloseWindow: null - }; - - // https://github.com/gorhill/uMatrix/issues/586 This is - // necessary hack because on SeaMonkey 2.40, for unknown - // reasons private windows do not have the attribute - // `windowtype` set to `navigator:browser`. As a fallback, the - // code here will also test whether the id attribute is - // `main-window`. - api.toBrowserWindow = function (win) { + }; + + // https://github.com/gorhill/uMatrix/issues/586 This is + // necessary hack because on SeaMonkey 2.40, for unknown + // reasons private windows do not have the attribute + // `windowtype` set to `navigator:browser`. As a fallback, the + // code here will also test whether the id attribute is + // `main-window`. + api.toBrowserWindow = function (win) { let docElement = win && win.document - && win.document.documentElement; + && win.document.documentElement; if (!docElement) { - return null; + return null; } if (vAPI.thunderbird) { - return docElement.getAttribute('windowtype') === 'mail:3pane' - ? win - : null; + return docElement.getAttribute('windowtype') === 'mail:3pane' + ? win + : null; } return docElement.getAttribute('windowtype') === 'navigator:browser' - || docElement.getAttribute('id') === 'main-window' - ? win - : null; - }; + || docElement.getAttribute('id') === 'main-window' + ? win + : null; + }; - api.getWindows = function () { + api.getWindows = function () { return windowToIdMap.keys(); - }; + }; - api.idFromWindow = function (win) { + api.idFromWindow = function (win) { return windowToIdMap.get(win) || 0; - }; + }; - api.getCurrentWindow = function () { + api.getCurrentWindow = function () { return this.toBrowserWindow(Services.wm.getMostRecentWindow(null)); - }; + }; - let addWindow = function (win) { + let addWindow = function (win) { if (!win || windowToIdMap.has(win)) { - return; + return; } windowToIdMap.set(win, windowIdGenerator++); if (typeof api.onOpenWindow === 'function') { - api.onOpenWindow(win); + api.onOpenWindow(win); } - }; + }; - let removeWindow = function (win) { + let removeWindow = function (win) { if (!win || windowToIdMap.delete(win) !== true) { - return; + return; } if (typeof api.onCloseWindow === 'function') { - api.onCloseWindow(win); + api.onCloseWindow(win); } - }; + }; - // https://github.com/gorhill/uMatrix/issues/357 - // Use nsIWindowMediator for being notified of opened/closed windows. - let listeners = { + // https://github.com/gorhill/uMatrix/issues/357 + // Use nsIWindowMediator for being notified of opened/closed windows. + let listeners = { onOpenWindow: function (aWindow) { - let win; - try { + let win; + try { win = aWindow.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIDOMWindow); - } catch (e) { - // Ignore - } + } catch (e) { + // Ignore + } - addWindow(win); + addWindow(win); }, onCloseWindow: function (aWindow) { - let win; - try { + let win; + try { win = aWindow.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIDOMWindow); - } catch (e) { - // Ignore - } + } catch (e) { + // Ignore + } - removeWindow(win); + removeWindow(win); }, observe: function (aSubject, topic) { - let win; - try { + let win; + try { win = aSubject.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIDOMWindow); - } catch (e) { - // Ignore - } - - if (!win) { - return; - } - - switch (topic) { - case 'domwindowopened': - addWindow(win); - break; - case 'domwindowclosed': - removeWindow(win); - break; - default: - console.error('unknown observer topic'); - break; - } + } catch (e) { + // Ignore + } + + if (!win) { + return; + } + + switch (topic) { + case 'domwindowopened': + addWindow(win); + break; + case 'domwindowclosed': + removeWindow(win); + break; + default: + console.error('unknown observer topic'); + break; + } } - }; + }; - (function() { + (function() { let winumerator; winumerator = Services.wm.getEnumerator(null); while (winumerator.hasMoreElements()) { - let win = winumerator.getNext(); + let win = winumerator.getNext(); - if (!win.closed) { + if (!win.closed) { windowToIdMap.set(win, windowIdGenerator++); - } + } } winumerator = Services.ww.getWindowEnumerator(); while (winumerator.hasMoreElements()) { - let win = winumerator.getNext() + let win = winumerator.getNext() .QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIDOMWindow); - if (!win.closed) { + if (!win.closed) { windowToIdMap.set(win, windowIdGenerator++); - } + } } Services.wm.addListener(listeners); Services.ww.registerNotification(listeners); - })(); + })(); - vAPI.addCleanUpTask(function() { + vAPI.addCleanUpTask(function() { Services.wm.removeListener(listeners); Services.ww.unregisterNotification(listeners); windowToIdMap.clear(); - }); + }); - return api; + return api; })(); })(); @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -29,47 +29,47 @@ ηMatrix.XAL = (function(){ - /******************************************************************************/ +/******************************************************************************/ - var exports = {}; - var noopFunc = function(){}; +var exports = {}; +var noopFunc = function(){}; - /******************************************************************************/ +/******************************************************************************/ - exports.keyvalSetOne = function(key, val, callback) { - var bin = {}; - bin[key] = val; - vAPI.storage.set(bin, callback || noopFunc); - }; +exports.keyvalSetOne = function(key, val, callback) { + var bin = {}; + bin[key] = val; + vAPI.storage.set(bin, callback || noopFunc); +}; - /******************************************************************************/ +/******************************************************************************/ - exports.keyvalGetOne = function(key, callback) { - vAPI.storage.get(key, callback); - }; +exports.keyvalGetOne = function(key, callback) { + vAPI.storage.get(key, callback); +}; - /******************************************************************************/ +/******************************************************************************/ - exports.keyvalSetMany = function(dict, callback) { - vAPI.storage.set(dict, callback || noopFunc); - }; +exports.keyvalSetMany = function(dict, callback) { + vAPI.storage.set(dict, callback || noopFunc); +}; - /******************************************************************************/ +/******************************************************************************/ - exports.keyvalRemoveOne = function(key, callback) { - vAPI.storage.remove(key, callback || noopFunc); - }; +exports.keyvalRemoveOne = function(key, callback) { + vAPI.storage.remove(key, callback || noopFunc); +}; - /******************************************************************************/ +/******************************************************************************/ - exports.keyvalRemoveAll = function(callback) { - vAPI.storage.clear(callback || noopFunc); - }; +exports.keyvalRemoveAll = function(callback) { + vAPI.storage.clear(callback || noopFunc); +}; - /******************************************************************************/ +/******************************************************************************/ - return exports; +return exports; - /******************************************************************************/ +/******************************************************************************/ })(); diff --git a/lib/CallbackWrapper.jsm b/lib/CallbackWrapper.jsm index 8c07732..739be97 100644 --- a/lib/CallbackWrapper.jsm +++ b/lib/CallbackWrapper.jsm @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -28,7 +28,7 @@ var EXPORTED_SYMBOLS = ['CallbackWrapper']; var junkyard = []; var CallbackWrapper = function (messageManager, channelName, - listenerId, requestId) { + listenerId, requestId) { // This allows to avoid creating a closure for every single // message which expects an answer. Having a closure created // each time a message is processed has been always bothering @@ -52,7 +52,7 @@ var CallbackWrapper = function (messageManager, channelName, }; CallbackWrapper.factory = function (messageManager, channelName, - listenerId, requestId) { + listenerId, requestId) { let wrapper = junkyard.pop(); if (wrapper) { wrapper.init(messageManager, channelName, listenerId, requestId); @@ -60,11 +60,11 @@ CallbackWrapper.factory = function (messageManager, channelName, } return new CallbackWrapper(messageManager, channelName, - listenerId, requestId); + listenerId, requestId); }; CallbackWrapper.prototype.init = function (messageManager, channelName, - listenerId, requestId) { + listenerId, requestId) { this.messageManager = messageManager; this.channelName = channelName; this.listenerId = listenerId; @@ -86,7 +86,7 @@ CallbackWrapper.prototype.proxy = function (response) { // Mark for reuse this.messageManager = this.channelName = - this.requestId = this.listenerId = null; + this.requestId = this.listenerId = null; junkyard.push(this); }; diff --git a/lib/CookieCache.jsm b/lib/CookieCache.jsm index c3badb4..e925736 100644 --- a/lib/CookieCache.jsm +++ b/lib/CookieCache.jsm @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -61,111 +61,111 @@ CookieEntry.prototype.dispose = function () { var CookieUtils = { keyFromCookie: function (cookie) { - let cb = []; - - cb[0] = cookie.secure ? 'https' : 'http'; - cb[1] = '://'; - cb[2] = cookie.domain.charAt(0) === '.' ? - cookie.domain.slice(1) : - cookie.domain; - cb[3] = cookie.path; - cb[4] = '{'; - cb[5] = cookie.session ? 'session' : 'persistent'; - cb[6] = '-cookie:'; - cb[7] = cookie.name; - cb[8] = '}'; - - return cb.join(''); + let cb = []; + + cb[0] = cookie.secure ? 'https' : 'http'; + cb[1] = '://'; + cb[2] = cookie.domain.charAt(0) === '.' ? + cookie.domain.slice(1) : + cookie.domain; + cb[3] = cookie.path; + cb[4] = '{'; + cb[5] = cookie.session ? 'session' : 'persistent'; + cb[6] = '-cookie:'; + cb[7] = cookie.name; + cb[8] = '}'; + + return cb.join(''); }, keyFromURL: function (url, type, name) { - if (typeof url !== 'object') { - throw new Error('Invalid URL parameter'); - } - - let cb = []; - - cb[0] = url.scheme; - cb[1] = '://'; - cb[2] = url.hostname; - cb[3] = url.path; - cb[4] = '{'; - cb[5] = type; - cb[6] = '-cookie:'; - cb[7] = name; - cb[8] = '}'; - - return cb.join(''); + if (typeof url !== 'object') { + throw new Error('Invalid URL parameter'); + } + + let cb = []; + + cb[0] = url.scheme; + cb[1] = '://'; + cb[2] = url.hostname; + cb[3] = url.path; + cb[4] = '{'; + cb[5] = type; + cb[6] = '-cookie:'; + cb[7] = name; + cb[8] = '}'; + + return cb.join(''); }, urlFromEntry: function (entry) { - if (!entry) { - return ''; - } + if (!entry) { + return ''; + } - return (entry.secure ? 'https://' : 'http://') - + entry.hostname - + entry.path; + return (entry.secure ? 'https://' : 'http://') + + entry.hostname + + entry.path; }, matchDomains: function (key, allHosts) { - let entry = CookieCache.get(key); + let entry = CookieCache.get(key); - if (entry === undefined) { - return false; - } + if (entry === undefined) { + return false; + } - if (allHosts.indexOf(' '+entry.hostname+' ') < 0) { - if (!entry.anySubdomain) { - return false; - } + if (allHosts.indexOf(' '+entry.hostname+' ') < 0) { + if (!entry.anySubdomain) { + return false; + } - if (allHosts.indexOf('.'+entry.hostname+' ') < 0) { - return false; - } - } + if (allHosts.indexOf('.'+entry.hostname+' ') < 0) { + return false; + } + } - return true; + return true; }, }; var CookieCache = { add: function (cookie) { - let key = CookieUtils.keyFromCookie(cookie); - let value = dict.get(key); - - if (value === undefined) { - value = junkyard.pop(); - if (value) { - value.init(cookie); - } else { - value = new CookieEntry(cookie); - } - dict.set(key, value); - } - - return value; + let key = CookieUtils.keyFromCookie(cookie); + let value = dict.get(key); + + if (value === undefined) { + value = junkyard.pop(); + if (value) { + value.init(cookie); + } else { + value = new CookieEntry(cookie); + } + dict.set(key, value); + } + + return value; }, addVector: function (vector) { - for (let i=vector.length-1; i>=0; --i) { - CookieCache.add(vector[i]); - } + for (let i=vector.length-1; i>=0; --i) { + CookieCache.add(vector[i]); + } }, remove: function (cookie) { - let value = dict.get(cookie); - if (value === undefined) { - return false; - } + let value = dict.get(cookie); + if (value === undefined) { + return false; + } - dict.delete(cookie); + dict.delete(cookie); - if (junkyard.length < 25) { - junkyard.push(value.dispose()); - } + if (junkyard.length < 25) { + junkyard.push(value.dispose()); + } - return true; + return true; }, get: function (key) { - return dict.get(key); + return dict.get(key); }, keys: function () { - return dict.keys(); + return dict.keys(); } }; diff --git a/lib/FrameModule.jsm b/lib/FrameModule.jsm index 543013c..7af0e63 100644 --- a/lib/FrameModule.jsm +++ b/lib/FrameModule.jsm @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 The µBlock authors - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -68,10 +68,8 @@ var contentObserver = { cpMessageName: hostName + ':shouldLoad', uniqueSandboxId: 1, modernFirefox: - (Services.appinfo.ID === '{ec8030f7-c20a-464f-9b0e-13a3a9e97384}' - || Services.appinfo.ID === '{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}' - || Services.appinfo.ID === '{9184b6fe-4a5c-484d-8b4b-efbfccbfb514}') - && Services.vc.compare(Services.appinfo.version, '44') > 0, + ((Services.appinfo.ID === '{9184b6fe-4a5c-484d-8b4b-efbfccbfb514}') + && Services.vc.compare(Services.appinfo.version, '44') > 0), get componentRegistrar() { return Components.manager.QueryInterface(Ci.nsIComponentRegistrar); @@ -79,14 +77,14 @@ var contentObserver = { get categoryManager() { return Components.classes['@mozilla.org/categorymanager;1'] - .getService(Ci.nsICategoryManager); + .getService(Ci.nsICategoryManager); }, QueryInterface: XPCOMUtils.generateQI([ - Ci.nsIFactory, - Ci.nsIObserver, - Ci.nsIContentPolicy, - Ci.nsISupportsWeakReference + Ci.nsIFactory, + Ci.nsIObserver, + Ci.nsIContentPolicy, + Ci.nsISupportsWeakReference ]), createInstance: function (outer, iid) { @@ -102,16 +100,16 @@ var contentObserver = { if (!this.modernFirefox) { this.componentRegistrar - .registerFactory(this.classID, - this.classDescription, - this.contractID, - this); + .registerFactory(this.classID, + this.classDescription, + this.contractID, + this); this.categoryManager - .addCategoryEntry('content-policy', - this.contractID, - this.contractID, - false, - true); + .addCategoryEntry('content-policy', + this.contractID, + this.contractID, + false, + true); } }, @@ -120,12 +118,12 @@ var contentObserver = { if (!this.modernFirefox) { this.componentRegistrar - .unregisterFactory(this.classID, - this); + .unregisterFactory(this.classID, + this); this.categoryManager - .deleteCategoryEntry('content-policy', - this.contractID, - false); + .deleteCategoryEntry('content-policy', + this.contractID, + false); } }, @@ -222,17 +220,17 @@ var contentObserver = { }; messager.addMessageListener(sandbox._sandboxId_, - sandbox._messageListener_); + sandbox._messageListener_); messager.addMessageListener(hostName + ':broadcast', - sandbox._messageListener_); + sandbox._messageListener_); }; sandbox.removeMessageListener = function () { try { messager.removeMessageListener(sandbox._sandboxId_, - sandbox._messageListener_); + sandbox._messageListener_); messager.removeMessageListener(hostName + ':broadcast', - sandbox._messageListener_); + sandbox._messageListener_); } catch (ex) { // It throws sometimes, mostly when the popup closes } @@ -262,8 +260,8 @@ var contentObserver = { } if (loc.protocol !== 'http:' - && loc.protocol !== 'https:' - && loc.protocol !== 'file:') { + && loc.protocol !== 'https:' + && loc.protocol !== 'file:') { if (loc.protocol === 'chrome:' && loc.host === hostName) { this.initContentScripts(win); } @@ -294,9 +292,9 @@ var contentObserver = { doc.addEventListener('DOMContentLoaded', docReady, true); } else { docReady({ - target: doc, - type: 'DOMContentLoaded', - }); + target: doc, + type: 'DOMContentLoaded', + }); } } }; @@ -326,13 +324,13 @@ LocationChangeListener.prototype.QueryInterface = XPCOMUtils.generateQI([ LocationChangeListener.prototype.onLocationChange = function (webProgress, request, location, flags) { - if (!webProgress.isTopLevel) { + if (!webProgress.isTopLevel) { return; - } - this.messageManager.sendAsyncMessage(locationChangedMessageName, { + } + this.messageManager.sendAsyncMessage(locationChangedMessageName, { url: location.asciiSpec, flags: flags, - }); + }); }; contentObserver.register(); diff --git a/lib/HostMap.jsm b/lib/HostMap.jsm index fddace9..3665ca9 100644 --- a/lib/HostMap.jsm +++ b/lib/HostMap.jsm @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2020 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -31,22 +31,22 @@ var map = new Map(); var HostMap = { put: function (key, value) { - if (typeof key !== 'string' || !(value instanceof Ci.nsIURI) - || !key || !value) { - throw new Error('invalid argument(s)'); - } + if (typeof key !== 'string' || !(value instanceof Ci.nsIURI) + || !key || !value) { + throw new Error('invalid argument(s)'); + } - if (map.get(key)) { - return; - } + if (map.get(key)) { + return; + } - map.set(key, value); + map.set(key, value); }, get: function (key) { - if (typeof key !== 'string' || !key) { - throw new Error('invalid argument'); - } + if (typeof key !== 'string' || !key) { + throw new Error('invalid argument'); + } - return map.get(key); + return map.get(key); }, }; diff --git a/lib/HttpRequestHeaders.jsm b/lib/HttpRequestHeaders.jsm index 387eabd..757081f 100644 --- a/lib/HttpRequestHeaders.jsm +++ b/lib/HttpRequestHeaders.jsm @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2020-2021 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -34,7 +34,7 @@ var HTTPRequestHeaders = function (channel) { HTTPRequestHeaders.factory = function (channel) { let entry = junkyard.pop(); if (entry) { - return entry.init(channel); + return entry.init(channel); } return new HTTPRequestHeaders(channel); @@ -46,10 +46,10 @@ HTTPRequestHeaders.prototype.init = function (channel) { this.originalHeaderNames = new Array(); channel.visitRequestHeaders({ - visitHeader: function (name, value) { - this.headers.push({name: name, value: value}); - this.originalHeaderNames.push(name); - }.bind(this) + visitHeader: function (name, value) { + this.headers.push({name: name, value: value}); + this.originalHeaderNames.push(name); + }.bind(this) }); return this; @@ -72,7 +72,7 @@ HTTPRequestHeaders.prototype.update = function () { //Clear any headers that were removed for (let name of this.originalHeaderNames) { if (!newHeaderNames.has(name)) { - this.channel.setRequestHeader(name, '', false); + this.channel.setRequestHeader(name, '', false); } } }; @@ -81,7 +81,7 @@ HTTPRequestHeaders.prototype.getHeader = function (name) { try { return this.channel.getRequestHeader(name); } catch (e) { - // Ignore + // Ignore } return ''; diff --git a/lib/LiquidDict.jsm b/lib/LiquidDict.jsm index b45a5d7..c462427 100644 --- a/lib/LiquidDict.jsm +++ b/lib/LiquidDict.jsm @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2020-2021 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -40,13 +40,13 @@ function meltBucket(dict, len, bucket) { --dict.frozenCount; if (bucket.charAt(0) === ' ') { - bucket.trim().split(' ').map(function (e) { - map[e] = true; - }); + bucket.trim().split(' ').map(function (e) { + map[e] = true; + }); } else { - for (let i=0; i<bucket.length; i+=len) { - map[bucket.substring(i, len)] = true; - } + for (let i=0; i<bucket.length; i+=len) { + map[bucket.substring(i, len)] = true; + } } return map; @@ -55,10 +55,10 @@ function meltBucket(dict, len, bucket) { function melt(dict) { let buckets = dict.dict; for (let key in buckets) { - let bucket = buckets[key]; - if (typeof bucket === 'string') { - buckets[key] = meltBucket(dict, key.charCodeAt(0) & 0xFF, bucket); - } + let bucket = buckets[key]; + if (typeof bucket === 'string') { + buckets[key] = meltBucket(dict, key.charCodeAt(0) & 0xFF, bucket); + } } } @@ -69,7 +69,7 @@ function freezeBucket(dict, bucket) { ++dict.frozenCount; if (wlen * words.length < dict.cutoff) { - return ' ' + words.join(' ') + ' '; + return ' ' + words.join(' ') + ' '; } return words.sort().join(''); @@ -78,15 +78,15 @@ function freezeBucket(dict, bucket) { LiquidDict.prototype.makeKey = function (word) { let len = word.length; if (len > 255) { - len = 255; + len = 255; } let i = len >> 2; return String.fromCharCode((word.charCodeAt(0) & 0x03) << 14 - | (word.charCodeAt(i) & 0x03) << 12 - | (word.charCodeAt(i+i) & 0x03) << 10 - | (word.charCodeAt(i+i+i) & 0x03) << 8 - | len); + | (word.charCodeAt(i) & 0x03) << 12 + | (word.charCodeAt(i+i) & 0x03) << 10 + | (word.charCodeAt(i+i+i) & 0x03) << 8 + | len); }; LiquidDict.prototype.test = function (word) { @@ -94,15 +94,15 @@ LiquidDict.prototype.test = function (word) { let bucket = this.dict[key]; if (bucket === undefined) { - return false; + return false; } if (typeof bucket === 'object') { - return bucket[word] !== undefined; + return bucket[word] !== undefined; } if (bucket.charAt(0) === ' ') { - return bucket.indexOf(' ' + word + ' ') >= 0; + return bucket.indexOf(' ' + word + ' ') >= 0; } let len = word.length; @@ -110,16 +110,16 @@ LiquidDict.prototype.test = function (word) { let right = ~~(bucket.length / len + 0.5); while (left < right) { - let i = left + right >> 1; - let needle = bucket.substr(len * i, len); - - if (word < needle) { - right = i; - } else if (word > needle) { - left = i + 1; - } else { - return true; - } + let i = left + right >> 1; + let needle = bucket.substr(len * i, len); + + if (word < needle) { + right = i; + } else if (word > needle) { + left = i + 1; + } else { + return true; + } } return false; @@ -128,26 +128,26 @@ LiquidDict.prototype.test = function (word) { LiquidDict.prototype.add = function (word) { let key = this.makeKey(word); if (key === undefined) { - return false; + return false; } let bucket = this.dict[key]; if (bucket === undefined) { - this.dict[key] = bucket = {}; - ++this.bucketCount; - bucket[word] = true; - ++this.count; + this.dict[key] = bucket = {}; + ++this.bucketCount; + bucket[word] = true; + ++this.count; - return true; + return true; } else if (typeof bucket === 'string') { - this.dict[key] = bucket = meltBucket(this, word.len, bucket); + this.dict[key] = bucket = meltBucket(this, word.len, bucket); } if (bucket[word] === undefined) { - bucket[word] = true; - ++this.count; + bucket[word] = true; + ++this.count; - return true; + return true; } ++this.duplicateCount; @@ -159,10 +159,10 @@ LiquidDict.prototype.freeze = function () { let buckets = this.dict; for (let key in buckets) { - let bucket = buckets[key]; - if (typeof bucket === 'object') { - buckets[key] = freezeBucket(this, bucket); - } + let bucket = buckets[key]; + if (typeof bucket === 'object') { + buckets[key] = freezeBucket(this, bucket); + } } }; diff --git a/lib/PendingRequests.jsm b/lib/PendingRequests.jsm index a3f72e5..fdb62e2 100644 --- a/lib/PendingRequests.jsm +++ b/lib/PendingRequests.jsm @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2020-2021 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -42,55 +42,55 @@ for (let i=0; i<bufferLength; ++i) { var PendingRequestBuffer = { createRequest: function (url) { - // URL to ring buffer index map: - // { k = URL, s = ring buffer indices } - // - // s is a string which character codes map to ring buffer - // indices -- for when the same URL is received multiple times - // by shouldLoadListener() before the existing one is serviced - // by the network request observer. I believe the use of a - // string in lieu of an array reduces memory churning. - let bucket; - let i = writePointer; - writePointer = (i + 1) % bufferLength; - - let req = ringBuffer[i]; - let str = String.fromCharCode(i); - - if (req._key !== '') { - bucket = urlToIndex.get(req._key); - if (bucket.lenght === 1) { - urlToIndex.delete(req._key); - } else { - let pos = bucket.indexOf(str); - urlToIndex.set(req._key, - bucket.slice(0, pos)+bucket.slice(pos+1)); - } - } - - bucket = urlToIndex.get(url); - urlToIndex.set(url, - (bucket === undefined) ? str : bucket + str); - req._key = url; - - return req; + // URL to ring buffer index map: + // { k = URL, s = ring buffer indices } + // + // s is a string which character codes map to ring buffer + // indices -- for when the same URL is received multiple times + // by shouldLoadListener() before the existing one is serviced + // by the network request observer. I believe the use of a + // string in lieu of an array reduces memory churning. + let bucket; + let i = writePointer; + writePointer = (i + 1) % bufferLength; + + let req = ringBuffer[i]; + let str = String.fromCharCode(i); + + if (req._key !== '') { + bucket = urlToIndex.get(req._key); + if (bucket.lenght === 1) { + urlToIndex.delete(req._key); + } else { + let pos = bucket.indexOf(str); + urlToIndex.set(req._key, + bucket.slice(0, pos)+bucket.slice(pos+1)); + } + } + + bucket = urlToIndex.get(url); + urlToIndex.set(url, + (bucket === undefined) ? str : bucket + str); + req._key = url; + + return req; }, lookupRequest: function (url) { - let bucket = urlToIndex.get(url); - if (bucket === undefined) { - return null; - } - - let i = bucket.charCodeAt(0); - if (bucket.length === 1) { - urlToIndex.delete(url); - } else { - urlToIndex.set(url, bucket.slice(1)); - } - - let req = ringBuffer[i]; - req._key = ''; - - return req; + let bucket = urlToIndex.get(url); + if (bucket === undefined) { + return null; + } + + let i = bucket.charCodeAt(0); + if (bucket.length === 1) { + urlToIndex.delete(url); + } else { + urlToIndex.set(url, bucket.slice(1)); + } + + let req = ringBuffer[i]; + req._key = ''; + + return req; }, }; diff --git a/lib/PublicSuffixList.jsm b/lib/PublicSuffixList.jsm index 297ef49..e2ab5b8 100644 --- a/lib/PublicSuffixList.jsm +++ b/lib/PublicSuffixList.jsm @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2020-2021 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -44,41 +44,41 @@ function search(store, hostname) { let remainder; if (pos < 0) { - tld = hostname; - remainder = hostname; + tld = hostname; + remainder = hostname; } else { - tld = hostname.slice(pos+1); - remainder = hostname.slice(0, pos); + tld = hostname.slice(pos+1); + remainder = hostname.slice(0, pos); } let sub = store[tld]; if (!sub) { - return false; + return false; } if (typeof sub === 'string') { - return (sub.indexOf(' '+remainder+' ') >= 0); + return (sub.indexOf(' '+remainder+' ') >= 0); } let l = remainder.length; let val = sub[l]; if (!val) { - return false; + return false; } let left = 0; let right = Math.floor(val.length/l+0.5); while (left < right) { - let i = left+right >> 1; - let key = val.substr(l*i, l); - if (remainder < key) { - right = i; - } else if (remainder > key) { - left = i+1; - } else { - return true; - } + let i = left+right >> 1; + let key = val.substr(l*i, l); + if (remainder < key) { + right = i; + } else if (remainder > key) { + left = i+1; + } else { + return true; + } } return false; @@ -86,47 +86,47 @@ function search(store, hostname) { function getPublicSuffix(hostname) { if (!hostname) { - return ''; + return ''; } while (true) { - let pos = hostname.indexOf('.'); - if (pos < 0) { - return hostname; - } + let pos = hostname.indexOf('.'); + if (pos < 0) { + return hostname; + } - if (search(exceptions, hostname)) { - return hostname.slice(pos+1); - } + if (search(exceptions, hostname)) { + return hostname.slice(pos+1); + } - if (search(rules, hostname)) { - return hostname; - } + if (search(rules, hostname)) { + return hostname; + } - if (search(rules, '*'+hostname.slice(pos))) { - return hostname; - } + if (search(rules, '*'+hostname.slice(pos))) { + return hostname; + } - hostname = hostname.slice(pos+1); + hostname = hostname.slice(pos+1); } } function getDomain(hostname) { if (!hostname || hostname.charAt(0) == '.') { - return ''; + return ''; } hostname = hostname.toLowerCase(); let suffix = getPublicSuffix(hostname); if (suffix === hostname) { - return ''; + return ''; } let len = hostname.length-suffix.length; let pos = hostname.lastIndexOf('.', hostname.lastIndexOf('.', len) - 1); if (pos <= 0) { - return hostname; + return hostname; } return hostname.slice(pos+1); @@ -134,38 +134,38 @@ function getDomain(hostname) { function crystallize(store) { for (let tld in store) { - if (!store.hasOwnProperty(tld)) { - continue; - } - - let suff = store[tld].join(' '); - if (!suff) { - store[tld] = ''; - continue; - } - - if (suff.length < cutoffLength) { - store[tld] = ' ' + suff + ' '; - continue; - } - - suff = []; - for (let i=store[tld].length-1; i>=0; --i) { - let s = store[tld][i]; - let l = s.length; - if (!suff[l]) { - suff[l] = []; - } - suff[l].push(s); - } - - for (let i=suff.length-1; i>=0; --i) { - if (suff[i]) { - suff[i] = suff[i].sort().join(''); - } - } - - store[tld] = suff; + if (!store.hasOwnProperty(tld)) { + continue; + } + + let suff = store[tld].join(' '); + if (!suff) { + store[tld] = ''; + continue; + } + + if (suff.length < cutoffLength) { + store[tld] = ' ' + suff + ' '; + continue; + } + + suff = []; + for (let i=store[tld].length-1; i>=0; --i) { + let s = store[tld][i]; + let l = s.length; + if (!suff[l]) { + suff[l] = []; + } + suff[l].push(s); + } + + for (let i=suff.length-1; i>=0; --i) { + if (suff[i]) { + suff[i] = suff[i].sort().join(''); + } + } + + store[tld] = suff; } return store; @@ -180,61 +180,61 @@ function parse(text, toAscii) { let tend = text.length; while (beg < tend) { - end = text.indexOf('\n', beg); - if (end < 0) { - end = text.indexOf('\r', beg); - if (end < 0) { - end = tend; - } - } - - let line = text.slice(beg, end).trim(); - beg = end+1; - - if (line.length === 0) { - continue; - } - - let pos = line.indexOf('//'); - if (pos >= 0) { - line = line.slice(0, pos); - } - - line = line.trim(); - if (!line) { - continue; - } - - let store; - if (line.charAt(0) == '!') { - store = exceptions; - line = line.slice(1); - } else { - store = rules; - } - - if (reMustPunycode.test(line)) { - line = toAscii(line); - } - - line = line.toLowerCase(); - - let tld; - pos = line.lastIndexOf('.'); - if (pos < 0) { - tld = line; - } else { - tld = line.slice(pos+1); - line = line.slice(0, pos); - } - - if (!store.hasOwnProperty(tld)) { - store[tld] = []; - } - - if (line) { - store[tld].push(line); - } + end = text.indexOf('\n', beg); + if (end < 0) { + end = text.indexOf('\r', beg); + if (end < 0) { + end = tend; + } + } + + let line = text.slice(beg, end).trim(); + beg = end+1; + + if (line.length === 0) { + continue; + } + + let pos = line.indexOf('//'); + if (pos >= 0) { + line = line.slice(0, pos); + } + + line = line.trim(); + if (!line) { + continue; + } + + let store; + if (line.charAt(0) == '!') { + store = exceptions; + line = line.slice(1); + } else { + store = rules; + } + + if (reMustPunycode.test(line)) { + line = toAscii(line); + } + + line = line.toLowerCase(); + + let tld; + pos = line.lastIndexOf('.'); + if (pos < 0) { + tld = line; + } else { + tld = line.slice(pos+1); + line = line.slice(0, pos); + } + + if (!store.hasOwnProperty(tld)) { + store[tld] = []; + } + + if (line) { + store[tld].push(line); + } } crystallize(exceptions); @@ -245,16 +245,16 @@ function parse(text, toAscii) { function toSelfie() { return { - magic: magic, - rules: rules, - exceptions: exception, + magic: magic, + rules: rules, + exceptions: exception, }; } function fromSelfie(selfie) { if (typeof selfie !== 'object' || typeof selfie.magic !== 'string' - || selfie.magic !== magic) { - return false; + || selfie.magic !== magic) { + return false; } rules = selfie.rules; @@ -266,33 +266,33 @@ function fromSelfie(selfie) { var addListener = function (listeners, callback) { if (typeof callback !== 'function') { - return; + return; } if (listeners.indexOf(callback) === -1) { - listeners.push(callback); + listeners.push(callback); } }; var removeListener = function (listeners, callback) { let pos = listeners.indexOf(callback); if (pos !== -1) { - listeners.splice(pos, 1); + listeners.splice(pos, 1); } }; var callListeners = function (listeners) { for (let i=0; i<listeners.length; ++i) { - listeners[i](); + listeners[i](); } }; var onChanged = { addListener: function (callback) { - addListener(onChangedListeners, callback); + addListener(onChangedListeners, callback); }, removeListener: function (callback) { - removeListener(onChangedListeners, callback); + removeListener(onChangedListeners, callback); }, }; diff --git a/lib/Punycode.jsm b/lib/Punycode.jsm index 0927b87..b601903 100644 --- a/lib/Punycode.jsm +++ b/lib/Punycode.jsm @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2020-2021 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -44,8 +44,8 @@ function mapDomain(domain, cb) { let res = ''; if (parts.length > 1) { - res = parts[0] + '@'; - domain = parts[1]; + res = parts[0] + '@'; + domain = parts[1]; } domain = domain.replace(reSeparator, '\x2E'); @@ -62,22 +62,22 @@ function ucs2decode(str) { let len = str.length; while (count < len) { - let val = str.charCodeAt(count); - ++count; - - if (val >= 0xD800 && val <= 0xDBFF && cound < len) { - let extra = str.charCodeAt(count); - ++count; - - if ((extra & 0xFC00) == 0xDC00) { - res.push(((val & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); - } else { - res.push(val); - --count; - } - } else { - res.push(val); - } + let val = str.charCodeAt(count); + ++count; + + if (val >= 0xD800 && val <= 0xDBFF && cound < len) { + let extra = str.charCodeAt(count); + ++count; + + if ((extra & 0xFC00) == 0xDC00) { + res.push(((val & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); + } else { + res.push(val); + --count; + } + } else { + res.push(val); + } } return res; @@ -85,29 +85,29 @@ function ucs2decode(str) { function ucs2encode(array) { return array.map(function (e) { - let res = ''; + let res = ''; - if (e > 0xFFFF) { - e -= 0x10000; - res += String.fromCharCode(e >>> 10 & 0x3FF | 0xD800); - e = 0xDC00 | e & 0x3FF; - } + if (e > 0xFFFF) { + e -= 0x10000; + res += String.fromCharCode(e >>> 10 & 0x3FF | 0xD800); + e = 0xDC00 | e & 0x3FF; + } - res += String.fromCharCode(e); + res += String.fromCharCode(e); - return res; + return res; }).join(''); } function basicToDigit(point) { if (point - 0x30 < 0x0A) { - return point - 0x16; + return point - 0x16; } if (point - 0x41 < 0x1A) { - return point - 0x41; + return point - 0x41; } if (point - 0x61 < 0x1A) { - return point - 0x61; + return point - 0x61; } return base; } @@ -122,7 +122,7 @@ function adapt(delta, num, first) { delta += Math.floor(delta/num); for (; delta>(base - tMin) * tMax >> 1; k+=base) { - delta = Math.floor(delta/(base-tMin)); + delta = Math.floor(delta/(base-tMin)); } return Math.floor(k + (base - tMin + 1) * delta / (delta + skew)); @@ -137,64 +137,64 @@ function decode(input) { let basic = input.lastIndexOf('-'); if (basic < 0) { - basic = 0; + basic = 0; } for (let j=0; j<basic; ++j) { - if (input.charCodeAt(j) >= 0x80) { - throw new Error('not basic code point'); - } + if (input.charCodeAt(j) >= 0x80) { + throw new Error('not basic code point'); + } - res.push(input.charCodeAt(j)); + res.push(input.charCodeAt(j)); } for (let k=(basic > 0) ? basic + 1 : 0; k<len;) { - let old = i; - let t = 0 + let old = i; + let t = 0 - for (let w=1, x=base; ; x+=base) { - if (k >= len) { - throw new Error('invalid input'); - } + for (let w=1, x=base; ; x+=base) { + if (k >= len) { + throw new Error('invalid input'); + } - let digit = basicToDigit(input.charCodeAt(k)); - ++k; + let digit = basicToDigit(input.charCodeAt(k)); + ++k; - if (digit >= base || digit > Math.floor((maxInt-i) / w)) { - throw new Error('overflow'); - } + if (digit >= base || digit > Math.floor((maxInt-i) / w)) { + throw new Error('overflow'); + } - i += digit * w; + i += digit * w; - t = x <= bias ? - tMin : - (x >= bias + tMax ? - tMax : - x - bias); + t = x <= bias ? + tMin : + (x >= bias + tMax ? + tMax : + x - bias); - if (digit < t) { - break; - } + if (digit < t) { + break; + } - if (w > Math.floor(maxInt/(base - t))) { - throw new Error('overflow'); - } + if (w > Math.floor(maxInt/(base - t))) { + throw new Error('overflow'); + } - w *= (base -t); - } + w *= (base -t); + } - let out = res.length+1; - bias = adapt(i-old, out, old==0); + let out = res.length+1; + bias = adapt(i-old, out, old==0); - if (Math.floor(i/out) > maxInt-n) { - throw new Error('overflow'); - } + if (Math.floor(i/out) > maxInt-n) { + throw new Error('overflow'); + } - n += Math.floor(i/out); - i %= out; + n += Math.floor(i/out); + i %= out; - res.splice(i, 0, n); - ++i; + res.splice(i, 0, n); + ++i; } return ucs2encode(res); @@ -212,71 +212,71 @@ function encode(input) { let bias = 72; for (let j=0; j<len; ++j) { - let val = input[j]; - if (val < 0x80) { - res.push(String.fromCharCode(val)); - } + let val = input[j]; + if (val < 0x80) { + res.push(String.fromCharCode(val)); + } } let blen = res.length; let count = blen; if (blen) { - res.push('-'); + res.push('-'); } while (count < len) { - let m = maxInt; - for (let j=0; j<len; ++j) { - let val = input[j]; - if (val >= n && val <= m) { - m = val; - } - } - - if (m - n > Math.floor((maxInt - delta)/(count+1))) { - throw new Error('overflow'); - } - - delta += (m - n) * (count + 1); - n = m; - - for (let j=0; j<len; ++j) { - let val = input[j]; - - if (val < n && ++delta > maxInt) { - throw new Error('overflow'); - } - - if (val == n) { - let q = delta; - for (let k=base; ; k+=base) { - let t = k <= bias ? - tMin : - (k >= bias + tMax ? - tMax: - k - bias); - - if (q < t) { - break; - } - - res.push - (String.fromCharCode - (digitToBasic(t + (q-t) % (base-t), 0))); - - q = Math.floor((q-t)/(base-t)); - } - - res.push(String.fromCharCode(digitToBasic(q, 0))); - bias = adapt(delta, count+1, count==blen); - delta = 0; - ++count; - } - } - - ++delta; - ++n; + let m = maxInt; + for (let j=0; j<len; ++j) { + let val = input[j]; + if (val >= n && val <= m) { + m = val; + } + } + + if (m - n > Math.floor((maxInt - delta)/(count+1))) { + throw new Error('overflow'); + } + + delta += (m - n) * (count + 1); + n = m; + + for (let j=0; j<len; ++j) { + let val = input[j]; + + if (val < n && ++delta > maxInt) { + throw new Error('overflow'); + } + + if (val == n) { + let q = delta; + for (let k=base; ; k+=base) { + let t = k <= bias ? + tMin : + (k >= bias + tMax ? + tMax: + k - bias); + + if (q < t) { + break; + } + + res.push + (String.fromCharCode + (digitToBasic(t + (q-t) % (base-t), 0))); + + q = Math.floor((q-t)/(base-t)); + } + + res.push(String.fromCharCode(digitToBasic(q, 0))); + bias = adapt(delta, count+1, count==blen); + delta = 0; + ++count; + } + } + + ++delta; + ++n; } return res.join(''); @@ -284,20 +284,20 @@ function encode(input) { function toUnicode(input) { return mapDomain(input, function (e) { - return rePuny.test(e) ? decode(e.slice(4).toLowerCase()) : e; + return rePuny.test(e) ? decode(e.slice(4).toLowerCase()) : e; }); } function toASCII(input) { return mapDomain(input, function (e) { - return reNonAscii.test(e) ? 'xn--' + encode(e) : e; + return reNonAscii.test(e) ? 'xn--' + encode(e) : e; }); } var Punycode = { ucs2: { - decode: ucs2decode, - encode: ucs2encode, + decode: ucs2decode, + encode: ucs2encode, }, decode: decode, encode: encode, diff --git a/lib/RowSnapshot.jsm b/lib/RowSnapshot.jsm index 43f20c3..c202183 100644 --- a/lib/RowSnapshot.jsm +++ b/lib/RowSnapshot.jsm @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2020-2021 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lib/Tools.jsm b/lib/Tools.jsm index c57a5eb..4019aa6 100644 --- a/lib/Tools.jsm +++ b/lib/Tools.jsm @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2020-2021 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -33,34 +33,34 @@ var LineIterator = function (text, offset) { LineIterator.prototype = { next: function () { - let end = this.text.indexOf('\n', this.offset); - if (end === -1) { - end = this.text.indexOf('\r', this.offset); - if (end === -1) { - end = this.textLen; - } - } - - let line = this.text.slice(this.offset, end); - this.offset = end + 1; - - return line; + let end = this.text.indexOf('\n', this.offset); + if (end === -1) { + end = this.text.indexOf('\r', this.offset); + if (end === -1) { + end = this.textLen; + } + } + + let line = this.text.slice(this.offset, end); + this.offset = end + 1; + + return line; }, rewind: function () { - if (this.offset <= 1) { - this.offset = 0; - } - - let end = this.text.lastIndexOf('\n', this.offset - 2); - if (end === -1) { - this.offset = end + 1; - } else { - end = this.text.lastIndexOf('\r', this.offset - 2); - this.offset = end !== -1 ? end + 1 : 0; - } + if (this.offset <= 1) { + this.offset = 0; + } + + let end = this.text.lastIndexOf('\n', this.offset - 2); + if (end === -1) { + this.offset = end + 1; + } else { + end = this.text.lastIndexOf('\r', this.offset - 2); + this.offset = end !== -1 ? end + 1 : 0; + } }, eot: function () { - return this.offset >= this.textLen; + return this.offset >= this.textLen; }, }; @@ -69,15 +69,15 @@ if (typeof Array.from === 'function') { setToArray = Array.from; } else { setToArray = function (set) { - let out = []; - let entries = set.values(); + let out = []; + let entries = set.values(); - for (let entry=entries.next(); - !entry||!entry.done; entry=entries.next()) { - out.push(entry.value); - } + for (let entry=entries.next(); + !entry||!entry.done; entry=entries.next()) { + out.push(entry.value); + } - return out; + return out; }; } @@ -86,33 +86,33 @@ var Tools = { setToArray: setToArray, gotoURL: function (context) { - if (typeof context !== 'object') { - throw new TypeError(context); - } + if (typeof context !== 'object') { + throw new TypeError(context); + } - context.api.tabs.open(context.details); + context.api.tabs.open(context.details); }, gotoExtensionURL: function (context) { - if (typeof context !== 'object') { - throw new TypeError(context); - } - - let details = context.details; - let api = context.api; - let matrix = context.matrix; - - if (details.url.startsWith('logger-ui.html')) { - if (details.shiftKey) { - let setting = matrix.userSettings.alwaysDetachLogger; - matrix.changeUserSettings('alwaysDetachLogger', !setting); - } - details.popup = matrix.userSettings.alwaysDetachLogger; - } - - details.select = true; - api.tabs.open(details); + if (typeof context !== 'object') { + throw new TypeError(context); + } + + let details = context.details; + let api = context.api; + let matrix = context.matrix; + + if (details.url.startsWith('logger-ui.html')) { + if (details.shiftKey) { + let setting = matrix.userSettings.alwaysDetachLogger; + matrix.changeUserSettings('alwaysDetachLogger', !setting); + } + details.popup = matrix.userSettings.alwaysDetachLogger; + } + + details.select = true; + api.tabs.open(details); }, setFromArray: function (a) { - return new Set(a); + return new Set(a); }, }; diff --git a/lib/UriTools.jsm b/lib/UriTools.jsm index 892dc44..1c3fa0d 100644 --- a/lib/UriTools.jsm +++ b/lib/UriTools.jsm @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -99,9 +99,9 @@ function URI() { this.fragmentBit = (1 << 7), this.allBits = (0xFFFF), this.authorityBit = - (this.userBit | this.passwordBit | this.hostnameBit | this.portBit); + (this.userBit | this.passwordBit | this.hostnameBit | this.portBit); this.normalizeBits = - (this.schemeBit | this.hostnameBit | this.pathBit | this.queryBit); + (this.schemeBit | this.hostnameBit | this.pathBit | this.queryBit); } var cached = new URI(); @@ -125,14 +125,14 @@ DomainCacheEntry.prototype.init = function (domain) { DomainCacheEntry.prototype.dispose = function () { this.domain = ''; if (cacheJunkyard.length < junkyardMax) { - cacheJunkyard.push(this); + cacheJunkyard.push(this); } }; var domainCacheEntryFactory = function (domain) { let entry = cacheJunkyard.pop(); if (entry) { - return entry.init(domain); + return entry.init(domain); } return new DomainCacheEntry(domain); }; @@ -141,12 +141,12 @@ var domainCacheAdd = function (hostname, domain) { let entry = domainCache.get(hostname); if (entry !== undefined) { - entry.tstamp = Date.now(); + entry.tstamp = Date.now(); } else { - domainCache.set(hostname, domainCacheEntryFactory(domain)); - if (domainCache.size === cacheCountHigh) { - domainCachePrune(); - } + domainCache.set(hostname, domainCacheEntryFactory(domain)); + if (domainCache.size === cacheCountHigh) { + domainCachePrune(); + } } return domain; @@ -158,11 +158,11 @@ var domainCacheSort = function (a, b) { var domainCachePrune = function () { let hostnames = - Array.from(domainCache.keys()).sort(domainCacheSort).slice(cacheCountLow); + Array.from(domainCache.keys()).sort(domainCacheSort).slice(cacheCountLow); for (let i=hostnames.length-1; i>=0; --i) { - domainCache.get(hostnames[i]).dispose(); - domainCache.delete(hostnames[i]); + domainCache.get(hostnames[i]).dispose(); + domainCache.delete(hostnames[i]); } }; @@ -174,232 +174,232 @@ publicSuffixList.onChanged.addListener(domainCacheReset); var UriTools = { set: function (uri) { - if (uri === undefined) { - return reset(cached); - } - - let matches = reRFC3986.exec(uri); - if (!matches) { - return reset(cached); - } - - cached.scheme = matches[1] !== undefined ? - matches[1].slice(0, -1) : - ''; - cached.authority = matches[2] !== undefined ? - matches[2].slice(2).toLowerCase() : - ''; - cached.path = matches[3] !== undefined ? - matches[3] : - ''; - - // As per RFC3986 - if (cached.authority !== '' && cached.path === '') { - cached.path = '/'; - } - - cached.query = matches[4] !== undefined ? - matches[4].slice(1) : - ''; - cached.fragment = matches[5] !== undefined ? - matches[5].slice(1) : - ''; - - if (reHostFromNakedAuthority.test(cached.authority)) { - cached.hostname = cached.authority; - cached.port = ''; - return cached; - } - - matches = reHostPortFromAuthority.exec(cached.authority); - if (!matches) { - matches = reIPv6PortFromAuthority.exec(cached.authority); - if (!matches) { - return resetAuthority(cached); - } - } - - cached.hostname = matches[1] !== undefined ? - matches[1] : - ''; - - if (cached.hostname.slice(-1) === '.') { - cached.hostname = cached.hostname.slice(0, -1); - } - - cached.port = matches[2] !== undefined ? - matches[2].slice(1) : - ''; - - return cached; + if (uri === undefined) { + return reset(cached); + } + + let matches = reRFC3986.exec(uri); + if (!matches) { + return reset(cached); + } + + cached.scheme = matches[1] !== undefined ? + matches[1].slice(0, -1) : + ''; + cached.authority = matches[2] !== undefined ? + matches[2].slice(2).toLowerCase() : + ''; + cached.path = matches[3] !== undefined ? + matches[3] : + ''; + + // As per RFC3986 + if (cached.authority !== '' && cached.path === '') { + cached.path = '/'; + } + + cached.query = matches[4] !== undefined ? + matches[4].slice(1) : + ''; + cached.fragment = matches[5] !== undefined ? + matches[5].slice(1) : + ''; + + if (reHostFromNakedAuthority.test(cached.authority)) { + cached.hostname = cached.authority; + cached.port = ''; + return cached; + } + + matches = reHostPortFromAuthority.exec(cached.authority); + if (!matches) { + matches = reIPv6PortFromAuthority.exec(cached.authority); + if (!matches) { + return resetAuthority(cached); + } + } + + cached.hostname = matches[1] !== undefined ? + matches[1] : + ''; + + if (cached.hostname.slice(-1) === '.') { + cached.hostname = cached.hostname.slice(0, -1); + } + + cached.port = matches[2] !== undefined ? + matches[2].slice(1) : + ''; + + return cached; }, assemble: function (bits) { - if (bits === undefined) { - bits = cached.allBits; - } + if (bits === undefined) { + bits = cached.allBits; + } - let s = []; + let s = []; - if (cached.scheme && (bits && cached.schemeBit)) { - s.push(cached.scheme, ':'); - } - if (cached.hostname && (bits & cached.hostnameBit)) { + if (cached.scheme && (bits && cached.schemeBit)) { + s.push(cached.scheme, ':'); + } + if (cached.hostname && (bits & cached.hostnameBit)) { s.push('//', cached.hostname); - } - if (cached.port && (bits & cached.portBit)) { + } + if (cached.port && (bits & cached.portBit)) { s.push(':', cached.port); - } - if (cached.path && (bits & cached.pathBit)) { + } + if (cached.path && (bits & cached.pathBit)) { s.push(cached.path); - } - if (cached.query && (bits & cached.queryBit)) { + } + if (cached.query && (bits & cached.queryBit)) { s.push('?', cached.query); - } - if (cached.fragment && (bits & cached.fragmentBit)) { + } + if (cached.fragment && (bits & cached.fragmentBit)) { s.push('#', cached.fragment); - } + } - return s.join(''); + return s.join(''); }, isNetworkScheme: function (scheme) { - return reNetworkScheme.test(scheme); + return reNetworkScheme.test(scheme); }, isSecureScheme: function(scheme) { - return reSecureScheme.test(scheme); + return reSecureScheme.test(scheme); }, originFromURI: function (uri) { - let matches = reOriginFromURI.exec(uri); - return matches !== null ? matches[0].toLowerCase() : ''; + let matches = reOriginFromURI.exec(uri); + return matches !== null ? matches[0].toLowerCase() : ''; }, schemeFromURI: function (uri) { - let matches = reSchemeFromURI.exec(uri); - return matches !== null ? matches[0].slice(0, -1).toLowerCase() : ''; + let matches = reSchemeFromURI.exec(uri); + return matches !== null ? matches[0].slice(0, -1).toLowerCase() : ''; }, authorityFromURI: function (uri) { - let matches = reAuthorityFromURI.exec(uri); - return matches !== null ? matches[1].slice(1).toLowerCase() : ''; + let matches = reAuthorityFromURI.exec(uri); + return matches !== null ? matches[1].slice(1).toLowerCase() : ''; }, hostnameFromURI: function (uri) { - let matches = reCommonHostnameFromURL.exec(uri); - if (matches) { - return matches[1]; - } - - matches = reAuthorityFromURI.exec(uri); - if (!matches) { - return ''; - } - - let auth = matches[1].slice(2); - - if (reHostFromNakedAuthority.test(auth)) { - return auth.toLowerCase(); - } - - matches = reHostFromAuthority.exec(auth); - if (!matches) { - matches = reIPv6FromAuthority.exec(auth); - if (!matches) { - return ''; - } - } - - let hostname = matches[1]; - while (hostname.endsWith('.')) { - hostname = hostname.slice(0, -1); - } - - if (reMustNormalizeHostname.test(hostname)) { - Punycode.toASCII(hostname.toLowerCase()); - } - - return hostname; + let matches = reCommonHostnameFromURL.exec(uri); + if (matches) { + return matches[1]; + } + + matches = reAuthorityFromURI.exec(uri); + if (!matches) { + return ''; + } + + let auth = matches[1].slice(2); + + if (reHostFromNakedAuthority.test(auth)) { + return auth.toLowerCase(); + } + + matches = reHostFromAuthority.exec(auth); + if (!matches) { + matches = reIPv6FromAuthority.exec(auth); + if (!matches) { + return ''; + } + } + + let hostname = matches[1]; + while (hostname.endsWith('.')) { + hostname = hostname.slice(0, -1); + } + + if (reMustNormalizeHostname.test(hostname)) { + Punycode.toASCII(hostname.toLowerCase()); + } + + return hostname; }, domainFromHostname: function (hostname) { - let entry = domainCache.get(hostname); - if (entry !== undefined) { - entry.tstamp = Date.now(); - return entry.domain; - } - - if (reIPAddressNaive.test(hostname) == false) { - return domainCacheAdd(hostname, - publicSuffixList.getDomain(hostname)); - } - - return domainCacheAdd(hostname, hostname); + let entry = domainCache.get(hostname); + if (entry !== undefined) { + entry.tstamp = Date.now(); + return entry.domain; + } + + if (reIPAddressNaive.test(hostname) == false) { + return domainCacheAdd(hostname, + publicSuffixList.getDomain(hostname)); + } + + return domainCacheAdd(hostname, hostname); }, domainFromURI: function (uri) { - if (!uri) { - return ''; - } - return UriTools.domainFromHostname(UriTools.hostnameFromURI(uri)); + if (!uri) { + return ''; + } + return UriTools.domainFromHostname(UriTools.hostnameFromURI(uri)); }, domain: function() { - return UriTools.domainFromHostname(cached.hostname); + return UriTools.domainFromHostname(cached.hostname); }, pathFromURI: function (uri) { - let matches = rePathFromURI.exec(uri); - return matches !== null ? matches[1] : ''; + let matches = rePathFromURI.exec(uri); + return matches !== null ? matches[1] : ''; }, normalizedURI: function () { - return UriTools.assemble(cached.normalizeBits); + return UriTools.assemble(cached.normalizeBits); }, rootURL: function () { - if (!cached.hostname) { - return ''; - } - return UriTools.assemble(cached.scemeBit | cached.hostnameBit); + if (!cached.hostname) { + return ''; + } + return UriTools.assemble(cached.scemeBit | cached.hostnameBit); }, isValidHostname: function (hostname) { - try { - let r = reValidHostname.test(hostname); - return r; - } catch (e) { - return false; - } + try { + let r = reValidHostname.test(hostname); + return r; + } catch (e) { + return false; + } }, parentHostnameFromHostname: function (hostname) { - // "locahost" => "" - // "example.org" => "example.org" - // "www.example.org" => "example.org" - // "tomato.www.example.org" => "example.org" - let domain = UriTools.domainFromHostname(hostname); + // "locahost" => "" + // "example.org" => "example.org" + // "www.example.org" => "example.org" + // "tomato.www.example.org" => "example.org" + let domain = UriTools.domainFromHostname(hostname); - if (domain === '' || domain === hostname) { - return undefined; - } + if (domain === '' || domain === hostname) { + return undefined; + } - return hostname.slice(hostname.indexOf('.') + 1); + return hostname.slice(hostname.indexOf('.') + 1); }, parentHostnamesFromHostname: function (hostname) { - let domain = UriTools.domainFromHostname(hostname); - if (domain === '' || domain === hostname) { - return []; - } - - let nodes = []; - for (;;) { - let pos = hostname.indexOf('.'); - if (pos < 0) { - break; - } - - hostname = hostname.slice(pos+1); - nodes.push(hostname); - if (hostname === domain) { - break; - } - } - - return nodes; + let domain = UriTools.domainFromHostname(hostname); + if (domain === '' || domain === hostname) { + return []; + } + + let nodes = []; + for (;;) { + let pos = hostname.indexOf('.'); + if (pos < 0) { + break; + } + + hostname = hostname.slice(pos+1); + nodes.push(hostname); + if (hostname === domain) { + break; + } + } + + return nodes; }, allHostNamesFromHostname: function (hostname) { - let nodes = UriTools.parentHostnamesFromHostname(hostname); - nodes.unshift(hostname); - return nodes; + let nodes = UriTools.parentHostnamesFromHostname(hostname); + nodes.unshift(hostname); + return nodes; }, toString: function () { - return UriTools.assemble(); + return UriTools.assemble(); }, }; diff --git a/lib/publicsuffixlist.js b/lib/publicsuffixlist.js index c0625ab..35b67cd 100644 --- a/lib/publicsuffixlist.js +++ b/lib/publicsuffixlist.js @@ -22,9 +22,9 @@ /*! Home: https://github.com/gorhill/publicsuffixlist.js */ /* - This code is mostly dumb: I consider this to be lower-level code, thus - in order to ensure efficiency, the caller is responsible for sanitizing - the inputs. + This code is mostly dumb: I consider this to be lower-level code, thus + in order to ensure efficiency, the caller is responsible for sanitizing + the inputs. */ /******************************************************************************/ @@ -33,336 +33,336 @@ ;(function(root) { - 'use strict'; +'use strict'; - /******************************************************************************/ - - var exceptions = {}; - var rules = {}; - var selfieMagic = 'iscjsfsaolnm'; +/******************************************************************************/ - // This value dictate how the search will be performed: - // < this.cutoffLength = indexOf() - // >= this.cutoffLength = binary search - var cutoffLength = 256; - var mustPunycode = /[^\w.*-]/; +var exceptions = {}; +var rules = {}; +var selfieMagic = 'iscjsfsaolnm'; - var onChangedListeners = []; +// This value dictate how the search will be performed: +// < this.cutoffLength = indexOf() +// >= this.cutoffLength = binary search +var cutoffLength = 256; +var mustPunycode = /[^\w.*-]/; - /******************************************************************************/ +var onChangedListeners = []; - // In the context of this code, a domain is defined as: - // "{label}.{public suffix}". - // A single standalone label is a public suffix as per - // http://publicsuffix.org/list/: - // "If no rules match, the prevailing rule is '*' " - // This means 'localhost' is not deemed a domain by this - // code, since according to the definition above, it would be - // evaluated as a public suffix. The caller is therefore responsible to - // decide how to further interpret such public suffix. - // - // `hostname` must be a valid ascii-based hostname. +/******************************************************************************/ - function getDomain(hostname) { - // A hostname starting with a dot is not a valid hostname. - if ( !hostname || hostname.charAt(0) === '.' ) { - return ''; - } - hostname = hostname.toLowerCase(); - var suffix = getPublicSuffix(hostname); - if ( suffix === hostname ) { - return ''; - } - var pos = hostname.lastIndexOf('.', hostname.lastIndexOf('.', hostname.length - suffix.length) - 1); - if ( pos <= 0 ) { - return hostname; - } - return hostname.slice(pos + 1); +// In the context of this code, a domain is defined as: +// "{label}.{public suffix}". +// A single standalone label is a public suffix as per +// http://publicsuffix.org/list/: +// "If no rules match, the prevailing rule is '*' " +// This means 'localhost' is not deemed a domain by this +// code, since according to the definition above, it would be +// evaluated as a public suffix. The caller is therefore responsible to +// decide how to further interpret such public suffix. +// +// `hostname` must be a valid ascii-based hostname. + +function getDomain(hostname) { + // A hostname starting with a dot is not a valid hostname. + if ( !hostname || hostname.charAt(0) === '.' ) { + return ''; } - - /******************************************************************************/ - - // Return longest public suffix. - // - // `hostname` must be a valid ascii-based string which respect hostname naming. - - function getPublicSuffix(hostname) { - if ( !hostname ) { - return ''; - } - // Since we slice down the hostname with each pass, the first match - // is the longest, so no need to find all the matching rules. - var pos; - while ( true ) { - pos = hostname.indexOf('.'); - if ( pos < 0 ) { - return hostname; - } - if ( search(exceptions, hostname) ) { - return hostname.slice(pos + 1); - } - if ( search(rules, hostname) ) { - return hostname; - } - if ( search(rules, '*' + hostname.slice(pos)) ) { - return hostname; - } - hostname = hostname.slice(pos + 1); - } - // unreachable + hostname = hostname.toLowerCase(); + var suffix = getPublicSuffix(hostname); + if ( suffix === hostname ) { + return ''; + } + var pos = hostname.lastIndexOf('.', hostname.lastIndexOf('.', hostname.length - suffix.length) - 1); + if ( pos <= 0 ) { + return hostname; } + return hostname.slice(pos + 1); +} - /******************************************************************************/ +/******************************************************************************/ - // Look up a specific hostname. +// Return longest public suffix. +// +// `hostname` must be a valid ascii-based string which respect hostname naming. - function search(store, hostname) { - // Extract TLD - var pos = hostname.lastIndexOf('.'); - var tld, remainder; +function getPublicSuffix(hostname) { + if ( !hostname ) { + return ''; + } + // Since we slice down the hostname with each pass, the first match + // is the longest, so no need to find all the matching rules. + var pos; + while ( true ) { + pos = hostname.indexOf('.'); if ( pos < 0 ) { - tld = hostname; - remainder = hostname; - } else { - tld = hostname.slice(pos + 1); - remainder = hostname.slice(0, pos); - } - var substore = store[tld]; - if ( !substore ) { - return false; + return hostname; } - // If substore is a string, use indexOf() - if ( typeof substore === 'string' ) { - return substore.indexOf(' ' + remainder + ' ') >= 0; + if ( search(exceptions, hostname) ) { + return hostname.slice(pos + 1); } - // It is an array: use binary search. - var l = remainder.length; - var haystack = substore[l]; - if ( !haystack ) { - return false; + if ( search(rules, hostname) ) { + return hostname; } - var left = 0; - var right = Math.floor(haystack.length / l + 0.5); - var i, needle; - while ( left < right ) { - i = left + right >> 1; - needle = haystack.substr( l * i, l ); - if ( remainder < needle ) { - right = i; - } else if ( remainder > needle ) { - left = i + 1; - } else { - return true; - } + if ( search(rules, '*' + hostname.slice(pos)) ) { + return hostname; } - return false; + hostname = hostname.slice(pos + 1); } + // unreachable +} - /******************************************************************************/ - - // Parse and set a UTF-8 text-based suffix list. Format is same as found at: - // http://publicsuffix.org/list/ - // - // `toAscii` is a converter from unicode to punycode. Required since the - // Public Suffix List contains unicode characters. - // Suggestion: use <https://github.com/bestiejs/punycode.js> it's quite good. +/******************************************************************************/ - function parse(text, toAscii) { - exceptions = {}; - rules = {}; +// Look up a specific hostname. + +function search(store, hostname) { + // Extract TLD + var pos = hostname.lastIndexOf('.'); + var tld, remainder; + if ( pos < 0 ) { + tld = hostname; + remainder = hostname; + } else { + tld = hostname.slice(pos + 1); + remainder = hostname.slice(0, pos); + } + var substore = store[tld]; + if ( !substore ) { + return false; + } + // If substore is a string, use indexOf() + if ( typeof substore === 'string' ) { + return substore.indexOf(' ' + remainder + ' ') >= 0; + } + // It is an array: use binary search. + var l = remainder.length; + var haystack = substore[l]; + if ( !haystack ) { + return false; + } + var left = 0; + var right = Math.floor(haystack.length / l + 0.5); + var i, needle; + while ( left < right ) { + i = left + right >> 1; + needle = haystack.substr( l * i, l ); + if ( remainder < needle ) { + right = i; + } else if ( remainder > needle ) { + left = i + 1; + } else { + return true; + } + } + return false; +} - var lineBeg = 0, lineEnd; - var textEnd = text.length; - var line, store, pos, tld; +/******************************************************************************/ - while ( lineBeg < textEnd ) { - lineEnd = text.indexOf('\n', lineBeg); +// Parse and set a UTF-8 text-based suffix list. Format is same as found at: +// http://publicsuffix.org/list/ +// +// `toAscii` is a converter from unicode to punycode. Required since the +// Public Suffix List contains unicode characters. +// Suggestion: use <https://github.com/bestiejs/punycode.js> it's quite good. + +function parse(text, toAscii) { + exceptions = {}; + rules = {}; + + var lineBeg = 0, lineEnd; + var textEnd = text.length; + var line, store, pos, tld; + + while ( lineBeg < textEnd ) { + lineEnd = text.indexOf('\n', lineBeg); + if ( lineEnd < 0 ) { + lineEnd = text.indexOf('\r', lineBeg); if ( lineEnd < 0 ) { - lineEnd = text.indexOf('\r', lineBeg); - if ( lineEnd < 0 ) { - lineEnd = textEnd; - } + lineEnd = textEnd; } - line = text.slice(lineBeg, lineEnd).trim(); - lineBeg = lineEnd + 1; + } + line = text.slice(lineBeg, lineEnd).trim(); + lineBeg = lineEnd + 1; - if ( line.length === 0 ) { - continue; - } + if ( line.length === 0 ) { + continue; + } - // Ignore comments - pos = line.indexOf('//'); - if ( pos >= 0 ) { - line = line.slice(0, pos); - } + // Ignore comments + pos = line.indexOf('//'); + if ( pos >= 0 ) { + line = line.slice(0, pos); + } - // Ignore surrounding whitespaces - line = line.trim(); - if ( !line ) { - continue; - } + // Ignore surrounding whitespaces + line = line.trim(); + if ( !line ) { + continue; + } - // Is this an exception rule? - if ( line.charAt(0) === '!' ) { - store = exceptions; - line = line.slice(1); - } else { - store = rules; - } + // Is this an exception rule? + if ( line.charAt(0) === '!' ) { + store = exceptions; + line = line.slice(1); + } else { + store = rules; + } - if ( mustPunycode.test(line) ) { - line = toAscii(line); - } + if ( mustPunycode.test(line) ) { + line = toAscii(line); + } - // http://publicsuffix.org/list/: - // "... all rules must be canonicalized in the normal way - // for hostnames - lower-case, Punycode ..." - line = line.toLowerCase(); - - // Extract TLD - pos = line.lastIndexOf('.'); - if ( pos < 0 ) { - tld = line; - } else { - tld = line.slice(pos + 1); - line = line.slice(0, pos); - } + // http://publicsuffix.org/list/: + // "... all rules must be canonicalized in the normal way + // for hostnames - lower-case, Punycode ..." + line = line.toLowerCase(); - // Store suffix using tld as key - if ( !store.hasOwnProperty(tld) ) { - store[tld] = []; - } - if ( line ) { - store[tld].push(line); - } + // Extract TLD + pos = line.lastIndexOf('.'); + if ( pos < 0 ) { + tld = line; + } else { + tld = line.slice(pos + 1); + line = line.slice(0, pos); } - crystallize(exceptions); - crystallize(rules); - callListeners(onChangedListeners); + // Store suffix using tld as key + if ( !store.hasOwnProperty(tld) ) { + store[tld] = []; + } + if ( line ) { + store[tld].push(line); + } } + crystallize(exceptions); + crystallize(rules); - /******************************************************************************/ + callListeners(onChangedListeners); +} - // Cristallize the storage of suffixes using optimal internal representation - // for future look up. +/******************************************************************************/ - function crystallize(store) { - var suffixes, suffix, i, l; +// Cristallize the storage of suffixes using optimal internal representation +// for future look up. - for ( var tld in store ) { - if ( !store.hasOwnProperty(tld) ) { - continue; - } - suffixes = store[tld].join(' '); - // No suffix - if ( !suffixes ) { - store[tld] = ''; - continue; - } - // Concatenated list of suffixes less than cutoff length: - // Store as string, lookup using indexOf() - if ( suffixes.length < cutoffLength ) { - store[tld] = ' ' + suffixes + ' '; - continue; - } - // Concatenated list of suffixes greater or equal to cutoff length - // Store as array keyed on suffix length, lookup using binary search. - // I borrowed the idea to key on string length here: - // http://ejohn.org/blog/dictionary-lookups-in-javascript/#comment-392072 - - i = store[tld].length; - suffixes = []; - while ( i-- ) { - suffix = store[tld][i]; - l = suffix.length; - if ( !suffixes[l] ) { - suffixes[l] = []; - } - suffixes[l].push(suffix); +function crystallize(store) { + var suffixes, suffix, i, l; + + for ( var tld in store ) { + if ( !store.hasOwnProperty(tld) ) { + continue; + } + suffixes = store[tld].join(' '); + // No suffix + if ( !suffixes ) { + store[tld] = ''; + continue; + } + // Concatenated list of suffixes less than cutoff length: + // Store as string, lookup using indexOf() + if ( suffixes.length < cutoffLength ) { + store[tld] = ' ' + suffixes + ' '; + continue; + } + // Concatenated list of suffixes greater or equal to cutoff length + // Store as array keyed on suffix length, lookup using binary search. + // I borrowed the idea to key on string length here: + // http://ejohn.org/blog/dictionary-lookups-in-javascript/#comment-392072 + + i = store[tld].length; + suffixes = []; + while ( i-- ) { + suffix = store[tld][i]; + l = suffix.length; + if ( !suffixes[l] ) { + suffixes[l] = []; } - l = suffixes.length; - while ( l-- ) { - if ( suffixes[l] ) { - suffixes[l] = suffixes[l].sort().join(''); - } + suffixes[l].push(suffix); + } + l = suffixes.length; + while ( l-- ) { + if ( suffixes[l] ) { + suffixes[l] = suffixes[l].sort().join(''); } - store[tld] = suffixes; } - return store; + store[tld] = suffixes; } + return store; +} - /******************************************************************************/ +/******************************************************************************/ - function toSelfie() { - return { - magic: selfieMagic, - rules: rules, - exceptions: exceptions - }; - } +function toSelfie() { + return { + magic: selfieMagic, + rules: rules, + exceptions: exceptions + }; +} - function fromSelfie(selfie) { - if ( typeof selfie !== 'object' || typeof selfie.magic !== 'string' || selfie.magic !== selfieMagic ) { - return false; - } - rules = selfie.rules; - exceptions = selfie.exceptions; - callListeners(onChangedListeners); - return true; +function fromSelfie(selfie) { + if ( typeof selfie !== 'object' || typeof selfie.magic !== 'string' || selfie.magic !== selfieMagic ) { + return false; } + rules = selfie.rules; + exceptions = selfie.exceptions; + callListeners(onChangedListeners); + return true; +} - /******************************************************************************/ +/******************************************************************************/ - var addListener = function(listeners, callback) { - if ( typeof callback !== 'function' ) { - return; - } - if ( listeners.indexOf(callback) === -1 ) { - listeners.push(callback); - } - }; +var addListener = function(listeners, callback) { + if ( typeof callback !== 'function' ) { + return; + } + if ( listeners.indexOf(callback) === -1 ) { + listeners.push(callback); + } +}; - var removeListener = function(listeners, callback) { - var pos = listeners.indexOf(callback); - if ( pos !== -1 ) { - listeners.splice(pos, 1); - } - }; +var removeListener = function(listeners, callback) { + var pos = listeners.indexOf(callback); + if ( pos !== -1 ) { + listeners.splice(pos, 1); + } +}; - var callListeners = function(listeners) { - for ( var i = 0; i < listeners.length; i++ ) { - listeners[i](); - } - }; +var callListeners = function(listeners) { + for ( var i = 0; i < listeners.length; i++ ) { + listeners[i](); + } +}; - /******************************************************************************/ +/******************************************************************************/ - var onChanged = { - addListener: function(callback) { - addListener(onChangedListeners, callback); - }, - removeListener: function(callback) { - removeListener(onChangedListeners, callback); - } - }; +var onChanged = { + addListener: function(callback) { + addListener(onChangedListeners, callback); + }, + removeListener: function(callback) { + removeListener(onChangedListeners, callback); + } +}; - /******************************************************************************/ +/******************************************************************************/ - // Public API +// Public API - root = root || window; +root = root || window; - root.publicSuffixList = { - 'version': '1.0', - 'parse': parse, - 'getDomain': getDomain, - 'getPublicSuffix': getPublicSuffix, - 'toSelfie': toSelfie, - 'fromSelfie': fromSelfie, - 'onChanged': onChanged - }; +root.publicSuffixList = { + 'version': '1.0', + 'parse': parse, + 'getDomain': getDomain, + 'getPublicSuffix': getPublicSuffix, + 'toSelfie': toSelfie, + 'fromSelfie': fromSelfie, + 'onChanged': onChanged +}; - /******************************************************************************/ +/******************************************************************************/ })(this); diff --git a/lib/punycode.js b/lib/punycode.js index b66096e..c965f8b 100644 --- a/lib/punycode.js +++ b/lib/punycode.js @@ -23,530 +23,530 @@ /*! https://mths.be/punycode v1.3.2 by @mathias */ ;(function(root) { - /** Detect free variables */ - var freeExports = typeof exports == 'object' && exports && - !exports.nodeType && exports; - var freeModule = typeof module == 'object' && module && - !module.nodeType && module; - var freeGlobal = typeof global == 'object' && global; - if ( - freeGlobal.global === freeGlobal || - freeGlobal.window === freeGlobal || - freeGlobal.self === freeGlobal - ) { - root = freeGlobal; - } - - /** - * The `punycode` object. - * @name punycode - * @type Object - */ - var punycode, - - /** Highest positive signed 32-bit float value */ - maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 - - /** Bootstring parameters */ - base = 36, - tMin = 1, - tMax = 26, - skew = 38, - damp = 700, - initialBias = 72, - initialN = 128, // 0x80 - delimiter = '-', // '\x2D' - - /** Regular expressions */ - regexPunycode = /^xn--/, - regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars - regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators - - /** Error messages */ - errors = { - 'overflow': 'Overflow: input needs wider integers to process', - 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', - 'invalid-input': 'Invalid input' - }, - - /** Convenience shortcuts */ - baseMinusTMin = base - tMin, - floor = Math.floor, - stringFromCharCode = String.fromCharCode, - - /** Temporary variable */ - key; - - /*--------------------------------------------------------------------------*/ - - /** - * A generic error utility function. - * @private - * @param {String} type The error type. - * @returns {Error} Throws a `RangeError` with the applicable error message. - */ - function error(type) { - throw RangeError(errors[type]); - } - - /** - * A generic `Array#map` utility function. - * @private - * @param {Array} array The array to iterate over. - * @param {Function} callback The function that gets called for every array - * item. - * @returns {Array} A new array of values returned by the callback function. - */ - function map(array, fn) { - var length = array.length; - var result = []; - while (length--) { - result[length] = fn(array[length]); - } - return result; - } - - /** - * A simple `Array#map`-like wrapper to work with domain name strings or email - * addresses. - * @private - * @param {String} domain The domain name or email address. - * @param {Function} callback The function that gets called for every - * character. - * @returns {Array} A new string of characters returned by the callback - * function. - */ - function mapDomain(string, fn) { - var parts = string.split('@'); - var result = ''; - if (parts.length > 1) { - // In email addresses, only the domain name should be punycoded. Leave - // the local part (i.e. everything up to `@`) intact. - result = parts[0] + '@'; - string = parts[1]; - } - // Avoid `split(regex)` for IE8 compatibility. See #17. - string = string.replace(regexSeparators, '\x2E'); - var labels = string.split('.'); - var encoded = map(labels, fn).join('.'); - return result + encoded; - } - - /** - * Creates an array containing the numeric code points of each Unicode - * character in the string. While JavaScript uses UCS-2 internally, - * this function will convert a pair of surrogate halves (each of which - * UCS-2 exposes as separate characters) into a single code point, - * matching UTF-16. - * @see `punycode.ucs2.encode` - * @see <https://mathiasbynens.be/notes/javascript-encoding> - * @memberOf punycode.ucs2 - * @name decode - * @param {String} string The Unicode input string (UCS-2). - * @returns {Array} The new array of code points. - */ - function ucs2decode(string) { - var output = [], - counter = 0, - length = string.length, - value, - extra; - while (counter < length) { - value = string.charCodeAt(counter++); - if (value >= 0xD800 && value <= 0xDBFF && counter < length) { - // high surrogate, and there is a next character - extra = string.charCodeAt(counter++); - if ((extra & 0xFC00) == 0xDC00) { // low surrogate - output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); - } else { - // unmatched surrogate; only append this code unit, in case the next - // code unit is the high surrogate of a surrogate pair - output.push(value); - counter--; - } - } else { - output.push(value); - } - } - return output; - } - - /** - * Creates a string based on an array of numeric code points. - * @see `punycode.ucs2.decode` - * @memberOf punycode.ucs2 - * @name encode - * @param {Array} codePoints The array of numeric code points. - * @returns {String} The new Unicode string (UCS-2). - */ - function ucs2encode(array) { - return map(array, function(value) { - var output = ''; - if (value > 0xFFFF) { - value -= 0x10000; - output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); - value = 0xDC00 | value & 0x3FF; - } - output += stringFromCharCode(value); - return output; - }).join(''); - } - - /** - * Converts a basic code point into a digit/integer. - * @see `digitToBasic()` - * @private - * @param {Number} codePoint The basic numeric code point value. - * @returns {Number} The numeric value of a basic code point (for use in - * representing integers) in the range `0` to `base - 1`, or `base` if - * the code point does not represent a value. - */ - function basicToDigit(codePoint) { - if (codePoint - 48 < 10) { - return codePoint - 22; - } - if (codePoint - 65 < 26) { - return codePoint - 65; - } - if (codePoint - 97 < 26) { - return codePoint - 97; - } - return base; - } - - /** - * Converts a digit/integer into a basic code point. - * @see `basicToDigit()` - * @private - * @param {Number} digit The numeric value of a basic code point. - * @returns {Number} The basic code point whose value (when used for - * representing integers) is `digit`, which needs to be in the range - * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is - * used; else, the lowercase form is used. The behavior is undefined - * if `flag` is non-zero and `digit` has no uppercase form. - */ - function digitToBasic(digit, flag) { - // 0..25 map to ASCII a..z or A..Z - // 26..35 map to ASCII 0..9 - return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); - } - - /** - * Bias adaptation function as per section 3.4 of RFC 3492. - * http://tools.ietf.org/html/rfc3492#section-3.4 - * @private - */ - function adapt(delta, numPoints, firstTime) { - var k = 0; - delta = firstTime ? floor(delta / damp) : delta >> 1; - delta += floor(delta / numPoints); - for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { - delta = floor(delta / baseMinusTMin); - } - return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); - } - - /** - * Converts a Punycode string of ASCII-only symbols to a string of Unicode - * symbols. - * @memberOf punycode - * @param {String} input The Punycode string of ASCII-only symbols. - * @returns {String} The resulting string of Unicode symbols. - */ - function decode(input) { - // Don't use UCS-2 - var output = [], - inputLength = input.length, - out, - i = 0, - n = initialN, - bias = initialBias, - basic, - j, - index, - oldi, - w, - k, - digit, - t, - /** Cached calculation results */ - baseMinusT; - - // Handle the basic code points: let `basic` be the number of input code - // points before the last delimiter, or `0` if there is none, then copy - // the first basic code points to the output. - - basic = input.lastIndexOf(delimiter); - if (basic < 0) { - basic = 0; - } - - for (j = 0; j < basic; ++j) { - // if it's not a basic code point - if (input.charCodeAt(j) >= 0x80) { - error('not-basic'); - } - output.push(input.charCodeAt(j)); - } - - // Main decoding loop: start just after the last delimiter if any basic code - // points were copied; start at the beginning otherwise. - - for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { - - // `index` is the index of the next character to be consumed. - // Decode a generalized variable-length integer into `delta`, - // which gets added to `i`. The overflow checking is easier - // if we increase `i` as we go, then subtract off its starting - // value at the end to obtain `delta`. - for (oldi = i, w = 1, k = base; /* no condition */; k += base) { - - if (index >= inputLength) { - error('invalid-input'); - } - - digit = basicToDigit(input.charCodeAt(index++)); - - if (digit >= base || digit > floor((maxInt - i) / w)) { - error('overflow'); - } - - i += digit * w; - t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); - - if (digit < t) { - break; - } - - baseMinusT = base - t; - if (w > floor(maxInt / baseMinusT)) { - error('overflow'); - } - - w *= baseMinusT; - - } - - out = output.length + 1; - bias = adapt(i - oldi, out, oldi == 0); - - // `i` was supposed to wrap around from `out` to `0`, - // incrementing `n` each time, so we'll fix that now: - if (floor(i / out) > maxInt - n) { - error('overflow'); - } - - n += floor(i / out); - i %= out; - - // Insert `n` at position `i` of the output - output.splice(i++, 0, n); - - } - - return ucs2encode(output); - } - - /** - * Converts a string of Unicode symbols (e.g. a domain name label) to a - * Punycode string of ASCII-only symbols. - * @memberOf punycode - * @param {String} input The string of Unicode symbols. - * @returns {String} The resulting Punycode string of ASCII-only symbols. - */ - function encode(input) { - var n, - delta, - handledCPCount, - basicLength, - bias, - j, - m, - q, - k, - t, - currentValue, - output = [], - /** `inputLength` will hold the number of code points in `input`. */ - inputLength, - /** Cached calculation results */ - handledCPCountPlusOne, - baseMinusT, - qMinusT; - - // Convert the input in UCS-2 to Unicode - input = ucs2decode(input); - - // Cache the length - inputLength = input.length; - - // Initialize the state - n = initialN; - delta = 0; - bias = initialBias; - - // Handle the basic code points - for (j = 0; j < inputLength; ++j) { - currentValue = input[j]; - if (currentValue < 0x80) { - output.push(stringFromCharCode(currentValue)); - } - } - - handledCPCount = basicLength = output.length; - - // `handledCPCount` is the number of code points that have been handled; - // `basicLength` is the number of basic code points. - - // Finish the basic string - if it is not empty - with a delimiter - if (basicLength) { - output.push(delimiter); - } - - // Main encoding loop: - while (handledCPCount < inputLength) { - - // All non-basic code points < n have been handled already. Find the next - // larger one: - for (m = maxInt, j = 0; j < inputLength; ++j) { - currentValue = input[j]; - if (currentValue >= n && currentValue < m) { - m = currentValue; - } - } - - // Increase `delta` enough to advance the decoder's <n,i> state to <m,0>, - // but guard against overflow - handledCPCountPlusOne = handledCPCount + 1; - if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { - error('overflow'); - } - - delta += (m - n) * handledCPCountPlusOne; - n = m; - - for (j = 0; j < inputLength; ++j) { - currentValue = input[j]; - - if (currentValue < n && ++delta > maxInt) { - error('overflow'); - } - - if (currentValue == n) { - // Represent delta as a generalized variable-length integer - for (q = delta, k = base; /* no condition */; k += base) { - t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); - if (q < t) { - break; - } - qMinusT = q - t; - baseMinusT = base - t; - output.push( - stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) - ); - q = floor(qMinusT / baseMinusT); - } - - output.push(stringFromCharCode(digitToBasic(q, 0))); - bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); - delta = 0; - ++handledCPCount; - } - } - - ++delta; - ++n; - - } - return output.join(''); - } - - /** - * Converts a Punycode string representing a domain name or an email address - * to Unicode. Only the Punycoded parts of the input will be converted, i.e. - * it doesn't matter if you call it on a string that has already been - * converted to Unicode. - * @memberOf punycode - * @param {String} input The Punycoded domain name or email address to - * convert to Unicode. - * @returns {String} The Unicode representation of the given Punycode - * string. - */ - function toUnicode(input) { - return mapDomain(input, function(string) { - return regexPunycode.test(string) - ? decode(string.slice(4).toLowerCase()) - : string; - }); - } - - /** - * Converts a Unicode string representing a domain name or an email address to - * Punycode. Only the non-ASCII parts of the domain name will be converted, - * i.e. it doesn't matter if you call it with a domain that's already in - * ASCII. - * @memberOf punycode - * @param {String} input The domain name or email address to convert, as a - * Unicode string. - * @returns {String} The Punycode representation of the given domain name or - * email address. - */ - function toASCII(input) { - return mapDomain(input, function(string) { - return regexNonASCII.test(string) - ? 'xn--' + encode(string) - : string; - }); - } - - /*--------------------------------------------------------------------------*/ - - /** Define the public API */ - punycode = { - /** - * A string representing the current Punycode.js version number. - * @memberOf punycode - * @type String - */ - 'version': '1.3.2', - /** - * An object of methods to convert from JavaScript's internal character - * representation (UCS-2) to Unicode code points, and back. - * @see <https://mathiasbynens.be/notes/javascript-encoding> - * @memberOf punycode - * @type Object - */ - 'ucs2': { - 'decode': ucs2decode, - 'encode': ucs2encode - }, - 'decode': decode, - 'encode': encode, - 'toASCII': toASCII, - 'toUnicode': toUnicode - }; - - /** Expose `punycode` */ - // Some AMD build optimizers, like r.js, check for specific condition patterns - // like the following: - if ( - typeof define == 'function' && - typeof define.amd == 'object' && - define.amd - ) { - define('punycode', function() { - return punycode; - }); - } else if (freeExports && freeModule) { - if (module.exports == freeExports) { // in Node.js or RingoJS v0.8.0+ - freeModule.exports = punycode; - } else { // in Narwhal or RingoJS v0.7.0- - for (key in punycode) { - punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]); - } - } - } else { // in Rhino or a web browser - root.punycode = punycode; - } + /** Detect free variables */ + var freeExports = typeof exports == 'object' && exports && + !exports.nodeType && exports; + var freeModule = typeof module == 'object' && module && + !module.nodeType && module; + var freeGlobal = typeof global == 'object' && global; + if ( + freeGlobal.global === freeGlobal || + freeGlobal.window === freeGlobal || + freeGlobal.self === freeGlobal + ) { + root = freeGlobal; + } + + /** + * The `punycode` object. + * @name punycode + * @type Object + */ + var punycode, + + /** Highest positive signed 32-bit float value */ + maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 + + /** Bootstring parameters */ + base = 36, + tMin = 1, + tMax = 26, + skew = 38, + damp = 700, + initialBias = 72, + initialN = 128, // 0x80 + delimiter = '-', // '\x2D' + + /** Regular expressions */ + regexPunycode = /^xn--/, + regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars + regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators + + /** Error messages */ + errors = { + 'overflow': 'Overflow: input needs wider integers to process', + 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', + 'invalid-input': 'Invalid input' + }, + + /** Convenience shortcuts */ + baseMinusTMin = base - tMin, + floor = Math.floor, + stringFromCharCode = String.fromCharCode, + + /** Temporary variable */ + key; + + /*--------------------------------------------------------------------------*/ + + /** + * A generic error utility function. + * @private + * @param {String} type The error type. + * @returns {Error} Throws a `RangeError` with the applicable error message. + */ + function error(type) { + throw RangeError(errors[type]); + } + + /** + * A generic `Array#map` utility function. + * @private + * @param {Array} array The array to iterate over. + * @param {Function} callback The function that gets called for every array + * item. + * @returns {Array} A new array of values returned by the callback function. + */ + function map(array, fn) { + var length = array.length; + var result = []; + while (length--) { + result[length] = fn(array[length]); + } + return result; + } + + /** + * A simple `Array#map`-like wrapper to work with domain name strings or email + * addresses. + * @private + * @param {String} domain The domain name or email address. + * @param {Function} callback The function that gets called for every + * character. + * @returns {Array} A new string of characters returned by the callback + * function. + */ + function mapDomain(string, fn) { + var parts = string.split('@'); + var result = ''; + if (parts.length > 1) { + // In email addresses, only the domain name should be punycoded. Leave + // the local part (i.e. everything up to `@`) intact. + result = parts[0] + '@'; + string = parts[1]; + } + // Avoid `split(regex)` for IE8 compatibility. See #17. + string = string.replace(regexSeparators, '\x2E'); + var labels = string.split('.'); + var encoded = map(labels, fn).join('.'); + return result + encoded; + } + + /** + * Creates an array containing the numeric code points of each Unicode + * character in the string. While JavaScript uses UCS-2 internally, + * this function will convert a pair of surrogate halves (each of which + * UCS-2 exposes as separate characters) into a single code point, + * matching UTF-16. + * @see `punycode.ucs2.encode` + * @see <https://mathiasbynens.be/notes/javascript-encoding> + * @memberOf punycode.ucs2 + * @name decode + * @param {String} string The Unicode input string (UCS-2). + * @returns {Array} The new array of code points. + */ + function ucs2decode(string) { + var output = [], + counter = 0, + length = string.length, + value, + extra; + while (counter < length) { + value = string.charCodeAt(counter++); + if (value >= 0xD800 && value <= 0xDBFF && counter < length) { + // high surrogate, and there is a next character + extra = string.charCodeAt(counter++); + if ((extra & 0xFC00) == 0xDC00) { // low surrogate + output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); + } else { + // unmatched surrogate; only append this code unit, in case the next + // code unit is the high surrogate of a surrogate pair + output.push(value); + counter--; + } + } else { + output.push(value); + } + } + return output; + } + + /** + * Creates a string based on an array of numeric code points. + * @see `punycode.ucs2.decode` + * @memberOf punycode.ucs2 + * @name encode + * @param {Array} codePoints The array of numeric code points. + * @returns {String} The new Unicode string (UCS-2). + */ + function ucs2encode(array) { + return map(array, function(value) { + var output = ''; + if (value > 0xFFFF) { + value -= 0x10000; + output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); + value = 0xDC00 | value & 0x3FF; + } + output += stringFromCharCode(value); + return output; + }).join(''); + } + + /** + * Converts a basic code point into a digit/integer. + * @see `digitToBasic()` + * @private + * @param {Number} codePoint The basic numeric code point value. + * @returns {Number} The numeric value of a basic code point (for use in + * representing integers) in the range `0` to `base - 1`, or `base` if + * the code point does not represent a value. + */ + function basicToDigit(codePoint) { + if (codePoint - 48 < 10) { + return codePoint - 22; + } + if (codePoint - 65 < 26) { + return codePoint - 65; + } + if (codePoint - 97 < 26) { + return codePoint - 97; + } + return base; + } + + /** + * Converts a digit/integer into a basic code point. + * @see `basicToDigit()` + * @private + * @param {Number} digit The numeric value of a basic code point. + * @returns {Number} The basic code point whose value (when used for + * representing integers) is `digit`, which needs to be in the range + * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is + * used; else, the lowercase form is used. The behavior is undefined + * if `flag` is non-zero and `digit` has no uppercase form. + */ + function digitToBasic(digit, flag) { + // 0..25 map to ASCII a..z or A..Z + // 26..35 map to ASCII 0..9 + return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); + } + + /** + * Bias adaptation function as per section 3.4 of RFC 3492. + * http://tools.ietf.org/html/rfc3492#section-3.4 + * @private + */ + function adapt(delta, numPoints, firstTime) { + var k = 0; + delta = firstTime ? floor(delta / damp) : delta >> 1; + delta += floor(delta / numPoints); + for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { + delta = floor(delta / baseMinusTMin); + } + return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); + } + + /** + * Converts a Punycode string of ASCII-only symbols to a string of Unicode + * symbols. + * @memberOf punycode + * @param {String} input The Punycode string of ASCII-only symbols. + * @returns {String} The resulting string of Unicode symbols. + */ + function decode(input) { + // Don't use UCS-2 + var output = [], + inputLength = input.length, + out, + i = 0, + n = initialN, + bias = initialBias, + basic, + j, + index, + oldi, + w, + k, + digit, + t, + /** Cached calculation results */ + baseMinusT; + + // Handle the basic code points: let `basic` be the number of input code + // points before the last delimiter, or `0` if there is none, then copy + // the first basic code points to the output. + + basic = input.lastIndexOf(delimiter); + if (basic < 0) { + basic = 0; + } + + for (j = 0; j < basic; ++j) { + // if it's not a basic code point + if (input.charCodeAt(j) >= 0x80) { + error('not-basic'); + } + output.push(input.charCodeAt(j)); + } + + // Main decoding loop: start just after the last delimiter if any basic code + // points were copied; start at the beginning otherwise. + + for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { + + // `index` is the index of the next character to be consumed. + // Decode a generalized variable-length integer into `delta`, + // which gets added to `i`. The overflow checking is easier + // if we increase `i` as we go, then subtract off its starting + // value at the end to obtain `delta`. + for (oldi = i, w = 1, k = base; /* no condition */; k += base) { + + if (index >= inputLength) { + error('invalid-input'); + } + + digit = basicToDigit(input.charCodeAt(index++)); + + if (digit >= base || digit > floor((maxInt - i) / w)) { + error('overflow'); + } + + i += digit * w; + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + + if (digit < t) { + break; + } + + baseMinusT = base - t; + if (w > floor(maxInt / baseMinusT)) { + error('overflow'); + } + + w *= baseMinusT; + + } + + out = output.length + 1; + bias = adapt(i - oldi, out, oldi == 0); + + // `i` was supposed to wrap around from `out` to `0`, + // incrementing `n` each time, so we'll fix that now: + if (floor(i / out) > maxInt - n) { + error('overflow'); + } + + n += floor(i / out); + i %= out; + + // Insert `n` at position `i` of the output + output.splice(i++, 0, n); + + } + + return ucs2encode(output); + } + + /** + * Converts a string of Unicode symbols (e.g. a domain name label) to a + * Punycode string of ASCII-only symbols. + * @memberOf punycode + * @param {String} input The string of Unicode symbols. + * @returns {String} The resulting Punycode string of ASCII-only symbols. + */ + function encode(input) { + var n, + delta, + handledCPCount, + basicLength, + bias, + j, + m, + q, + k, + t, + currentValue, + output = [], + /** `inputLength` will hold the number of code points in `input`. */ + inputLength, + /** Cached calculation results */ + handledCPCountPlusOne, + baseMinusT, + qMinusT; + + // Convert the input in UCS-2 to Unicode + input = ucs2decode(input); + + // Cache the length + inputLength = input.length; + + // Initialize the state + n = initialN; + delta = 0; + bias = initialBias; + + // Handle the basic code points + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue < 0x80) { + output.push(stringFromCharCode(currentValue)); + } + } + + handledCPCount = basicLength = output.length; + + // `handledCPCount` is the number of code points that have been handled; + // `basicLength` is the number of basic code points. + + // Finish the basic string - if it is not empty - with a delimiter + if (basicLength) { + output.push(delimiter); + } + + // Main encoding loop: + while (handledCPCount < inputLength) { + + // All non-basic code points < n have been handled already. Find the next + // larger one: + for (m = maxInt, j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue >= n && currentValue < m) { + m = currentValue; + } + } + + // Increase `delta` enough to advance the decoder's <n,i> state to <m,0>, + // but guard against overflow + handledCPCountPlusOne = handledCPCount + 1; + if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { + error('overflow'); + } + + delta += (m - n) * handledCPCountPlusOne; + n = m; + + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + + if (currentValue < n && ++delta > maxInt) { + error('overflow'); + } + + if (currentValue == n) { + // Represent delta as a generalized variable-length integer + for (q = delta, k = base; /* no condition */; k += base) { + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + if (q < t) { + break; + } + qMinusT = q - t; + baseMinusT = base - t; + output.push( + stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) + ); + q = floor(qMinusT / baseMinusT); + } + + output.push(stringFromCharCode(digitToBasic(q, 0))); + bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); + delta = 0; + ++handledCPCount; + } + } + + ++delta; + ++n; + + } + return output.join(''); + } + + /** + * Converts a Punycode string representing a domain name or an email address + * to Unicode. Only the Punycoded parts of the input will be converted, i.e. + * it doesn't matter if you call it on a string that has already been + * converted to Unicode. + * @memberOf punycode + * @param {String} input The Punycoded domain name or email address to + * convert to Unicode. + * @returns {String} The Unicode representation of the given Punycode + * string. + */ + function toUnicode(input) { + return mapDomain(input, function(string) { + return regexPunycode.test(string) + ? decode(string.slice(4).toLowerCase()) + : string; + }); + } + + /** + * Converts a Unicode string representing a domain name or an email address to + * Punycode. Only the non-ASCII parts of the domain name will be converted, + * i.e. it doesn't matter if you call it with a domain that's already in + * ASCII. + * @memberOf punycode + * @param {String} input The domain name or email address to convert, as a + * Unicode string. + * @returns {String} The Punycode representation of the given domain name or + * email address. + */ + function toASCII(input) { + return mapDomain(input, function(string) { + return regexNonASCII.test(string) + ? 'xn--' + encode(string) + : string; + }); + } + + /*--------------------------------------------------------------------------*/ + + /** Define the public API */ + punycode = { + /** + * A string representing the current Punycode.js version number. + * @memberOf punycode + * @type String + */ + 'version': '1.3.2', + /** + * An object of methods to convert from JavaScript's internal character + * representation (UCS-2) to Unicode code points, and back. + * @see <https://mathiasbynens.be/notes/javascript-encoding> + * @memberOf punycode + * @type Object + */ + 'ucs2': { + 'decode': ucs2decode, + 'encode': ucs2encode + }, + 'decode': decode, + 'encode': encode, + 'toASCII': toASCII, + 'toUnicode': toUnicode + }; + + /** Expose `punycode` */ + // Some AMD build optimizers, like r.js, check for specific condition patterns + // like the following: + if ( + typeof define == 'function' && + typeof define.amd == 'object' && + define.amd + ) { + define('punycode', function() { + return punycode; + }); + } else if (freeExports && freeModule) { + if (module.exports == freeExports) { // in Node.js or RingoJS v0.8.0+ + freeModule.exports = punycode; + } else { // in Narwhal or RingoJS v0.7.0- + for (key in punycode) { + punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]); + } + } + } else { // in Rhino or a web browser + root.punycode = punycode; + } }(this)); diff --git a/locale/bg/messages.properties b/locale/bg/messages.properties index fbdd06f..050bc7a 100644 --- a/locale/bg/messages.properties +++ b/locale/bg/messages.properties @@ -91,7 +91,7 @@ settingsCloudStorageEnabled=Enable cloud storage support privacyPageTitle=ηMatrix – Поверителност privacyDeleteBlockedCookiesPrompt=Изтриване на блокираните бисквитки. privacyDeleteBlockedCookiesHelp=<p>Blacklisted cookies are not prevented by <i>ηMatrix</i> from entering your browser. However they are prevented from leaving your browser, which is what really matters. Not blocking cookies before they enter your browser gives you the opportunity to be informed that a site tried to use cookies, and furthermore to inspect their contents if you wish.</p><p>Once these blacklisted cookies have been accounted for by <i>ηMatrix</i>, they can be removed from your browser if you wish so.</p><p><b>Important note:</b> Extensions can make web requests during the course of their normal operation. These requests can result in cookies being created in the browser. If the hostname from where a cookie originate is not whitelisted, the cookie will be removed from the browser by <i>ηMatrix</i> if this option is checked. So be sure that the hostname(s) with which an extension communicate is whitelisted.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Изтриване на неблокираните бисквитки за сесията +privacyDeleteNonBlockedSessionCookiesPrompt1=Изтриване на неблокираните бисквитки за сесията privacyDeleteNonBlockedSessionCookiesPrompt2= минути след последната употреба. privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “A session cookie ... is erased when you end the browser session. The session cookie is stored in temporary memory and is not retained after the browser is closed.”</p><p>Except that this <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>might not be happening</a> in some browsers. Also, to some, having to close the browser in order for the session cookies to clear might not be early enough.</p> privacyDeleteBlockedLocalStoragePrompt=Изтрийте съдържанието на <a href='https://ru.wikipedia.org/wiki/Web_storage'>локалното хранилище</a> от блокирани имена на хостове @@ -115,7 +115,7 @@ userRulesEditDicard=Discard userRulesImport=Import from file... userRulesExport=Export to file... userRulesFormatHint=Правилата за синтаксиса можете да видите на тази страница. -userRulesDefaultFileName=my-ematrix-rules.txt +userRulesDefaultFileName=my-umatrix-rules.txt hostsFilesPrompt=Всички сайтове във файла с хостове са заредени като блокирани на глобално ниво. hostsFilesStats={{blockedHostnameCount}} distinct blocked hostnames from: hostsFilesPerFileStats={{used}} използвано от {{total}} @@ -124,7 +124,7 @@ hostsFilesApplyChanges=Прилагане на промените hostsFilesAutoUpdatePrompt=Автообновление на файловете от хостовете. hostsFilesUpdateNow=Обновяване сега hostsFilesPurgeAll=Очистване на всичкия кеш -hostsFilesExternalListsHint=One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored. +hostsFilesExternalListsHint=<p>One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored.</p><p>The inserted URL must point to a hosts file (including local files); do not use the hosts file syntax here.</p> hostsFilesExternalListsParse=Анализиране hostsFilesExternalListPurge=очистване на кеша hostsFilesExternalListNew=налична е нова версия @@ -142,7 +142,7 @@ aboutIssueContributors=Проблеми: aboutTranslationContributors=Преводи: aboutUserDataHeader=Вашите данни aboutBackupButton=Правене на резервно копие... -aboutBackupFilename=my-ematrix-backup.txt +aboutBackupFilename=my-umatrix-backup.txt aboutRestoreButton=Възстановяване от файл... aboutRestoreConfirm=All your settings will be overwritten using data backed up on {{time}}, and ηMatrix will restart.\n\nOverwrite all existing settings using backed up data? aboutRestoreError=Данните не могат да се прочетат или имат грешки @@ -183,4 +183,6 @@ noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can dis settingsUpdateIcon=Do not change the toolbar icon updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +resolveCnameHelp=<p>When resolving an address with DNS, some webistes use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +settingsTextSmaller=Smaller +settingsTextBigger=Bigger diff --git a/locale/cs/messages.properties b/locale/cs/messages.properties index 32cca9a..81ca788 100644 --- a/locale/cs/messages.properties +++ b/locale/cs/messages.properties @@ -91,7 +91,7 @@ settingsCloudStorageEnabled=Zapnout podporu cloudového úložiště privacyPageTitle=ηMatrix – Soukromí privacyDeleteBlockedCookiesPrompt=Mazat zablokované cookies. privacyDeleteBlockedCookiesHelp=<p>Blacklisted cookies are not prevented by <i>eMatrix</i> from entering your browser. However they are prevented from leaving your browser, which is what really matters. Not blocking cookies before they enter your browser gives you the opportunity to be informed that a site tried to use cookies, and furthermore to inspect their contents if you wish.</p><p>Once these blacklisted cookies have been accounted for by <i>eMatrix</i>, they can be removed from your browser if you wish so.</p><p><b>Important note:</b> Extensions can make web requests during the course of their normal operation. These requests can result in cookies being created in the browser. If the hostname from where a cookie originate is not whitelisted, the cookie will be removed from the browser by <i>eMatrix</i> if this option is checked. So be sure that the hostname(s) with which an extension communicate is whitelisted.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Mazat neblokované cookies +privacyDeleteNonBlockedSessionCookiesPrompt1=Mazat neblokované cookies privacyDeleteNonBlockedSessionCookiesPrompt2= minut po posledním použití. privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “A session cookie ... is erased when you end the browser session. The session cookie is stored in temporary memory and is not retained after the browser is closed.”</p><p>Except that this <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>might not be happening</a> in some browsers. Also, to some, having to close the browser in order for the session cookies to clear might not be early enough.</p> privacyDeleteBlockedLocalStoragePrompt=Delete <a href='https://en.wikipedia.org/wiki/Web_storage'>local storage</a> content set by blocked hostnames @@ -115,7 +115,7 @@ userRulesEditDicard=Zrušit userRulesImport=Načíst ze souboru… userRulesExport=Uložit do souboru… userRulesFormatHint=Podívej se na tuto stránku pro syntaxi pravidel. -userRulesDefaultFileName=moje-pravidla-ematrix.txt +userRulesDefaultFileName=moje-pravidla-umatrix.txt hostsFilesPrompt=Všechny jména hostů v souboru hostů jsou načteny jako zakázaná v globálním měřítku. hostsFilesStats={{blockedHostnameCount}} distinct blocked hostnames from: hostsFilesPerFileStats=Použito {{used}} z {{total}} @@ -124,7 +124,7 @@ hostsFilesApplyChanges=Uložit změny hostsFilesAutoUpdatePrompt=Automaticky aktualizovat soubory hostů. hostsFilesUpdateNow=Aktualizovat nyní hostsFilesPurgeAll=Vyčistit všechny cache -hostsFilesExternalListsHint=Jedna URL na řádek. Řádky s prefixem ‘#’ budou ignorovány. Nevalidní URL budou ignorovány. +hostsFilesExternalListsHint=<p>One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored.</p><p>The inserted URL must point to a hosts file (including local files); do not use the hosts file syntax here.</p> hostsFilesExternalListsParse=Načíst hostsFilesExternalListPurge=vyčistit cache hostsFilesExternalListNew=nová verze k dispozici @@ -142,7 +142,7 @@ aboutIssueContributors=Problémy: aboutTranslationContributors=Překlady: aboutUserDataHeader=Vaše data aboutBackupButton=Zálohovat do souboru… -aboutBackupFilename=moje-zaloha-ematrix.txt +aboutBackupFilename=moje-zaloha-umatrix.txt aboutRestoreButton=Obnovit ze zálohy… aboutRestoreConfirm=Všechna vaše nastavení budou přepsány daty zálohovanými v {{time}}, ηMatrix bude restartován.\nPřepsat všechny existující nastavení zálohovanými daty? aboutRestoreError=Data nemohla být načtena nebo jsou neplatná @@ -183,4 +183,6 @@ noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can dis settingsUpdateIcon=Do not change the toolbar icon updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +resolveCnameHelp=<p>When resolving an address with DNS, some webistes use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +settingsTextSmaller=Smaller +settingsTextBigger=Bigger diff --git a/locale/de/messages.properties b/locale/de/messages.properties index 9ba62ce..1651654 100644 --- a/locale/de/messages.properties +++ b/locale/de/messages.properties @@ -39,7 +39,7 @@ statsPageTitle=µMatrix – Statistik statsPageGenericStats=Statistik nach Gattungen statsPageCookieHeadersFoiled=<a href='https://de.wikipedia.org/wiki/HTTP_Cookie'>HTTP Cookie</a> Header blockiert: {{count}} statsPageRefererHeadersFoiled=<a href='https://de.wikipedia.org/wiki/Referrer'>HTTP Referrer</a> Header blockiert: {{count}} -statsPageHyperlinkAuditingFoiled=<a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>Hyperlink auditing</a> Versuche vereitelt: {{count}} +statsPageHyperlinkAuditingFoiled=<a href='https://html.spec.whatwg.org/multipage/linkss.html#hyperlink-auditing'>Hyperlink auditing</a> Versuche vereitelt: {{count}} statsPageCookiesRemoved=Lokale Cookies entfernt: {{count}} statsPageLocalStoragesCleared=<a href='http://diveintohtml5.info/storage.html'>Local Storage</a> geleert: {{count}} statsPageBrowserCacheCleared=Browser Cache geleert: {{count}} @@ -91,7 +91,7 @@ settingsCloudStorageEnabled=Aktiviere die Unterstützung der Speicherung in der privacyPageTitle=ηMatrix – Privatsphäre privacyDeleteBlockedCookiesPrompt=Lösche geblockte Cookies. privacyDeleteBlockedCookiesHelp=<p>Cookies auf der Blacklist werden von <i>ηMatrix</i> nicht daran gehindert, vom Browser empfangen zu werden. Vielmehr werden sie daran gehindert, den Browser wieder zu verlassen - das ist es, worauf es wirklich ankommt. Dass Cookies nicht blockiert werden, bevor sie vom Browser empfangen werden, gibt dir die Gelegenheit, dich zu informieren, welche Seiten Cookies zu verwenden versuchen, und dir den Inhalt der Cookies anzuschauen, wenn du möchtest.</p><p>Sobald diese sich auf der Blacklist befindlichen Cookies von <i>ηMatrix</i> erfasst sind, können sie aus deinem Browser gelöscht werden, falls du möchtest.</p><p><b>Wichtiger Hinweis:</b> Erweiterungen können während ihrer Benutzung Webanfragen tätigen. Diese Anfragen können dazu führen, dass Cookies im Browser erzeugt werden. Falls der Hostname, von dem das Cookie stammt, nicht auf der Whitelist ist, wird das Cookie von <i>ηMatrix</i> aus dem Browser entfernt, sofern dieser Schalter aktiviert ist. Stelle daher sicher, dass Hostnamen, mit denen eine Erweiterung kommuniziert, auf der Whitelist stehen.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Lösche nicht blockierte Sitzungscookies +privacyDeleteNonBlockedSessionCookiesPrompt1=Lösche nicht blockierte Sitzungscookies privacyDeleteNonBlockedSessionCookiesPrompt2= Minuten nach ihrer letzten Benutzung. privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “Ein Sitzungscookie ... wird gelöscht, wenn die Browsersitzung beendet wird. Das Sitzungscookie wird temporär gespeichert und nicht behalten, nachdem der Browser geschlossen wurde.”</p><p>Nur ist das möglicherweise bei einigen Browsern <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>nicht der Fall</a>. Außerdem bevorzugen es manche Benutzer, Sitzungscookies loszuwerden, bevor sie den Browser schließen.</p> privacyDeleteBlockedLocalStoragePrompt=Lösche <a href='http://de.wikipedia.org/wiki/Web_Storage'>Lokaler Speicher-Inhalt (Local Storage)</a> für blockierte Hostnamen @@ -115,7 +115,7 @@ userRulesEditDicard=Verwerfen userRulesImport=Aus Datei importieren... userRulesExport=In eine Datei exportieren ... userRulesFormatHint=Auf dieser Seite findest du die Syntax für die Regeln. -userRulesDefaultFileName=my-ematrix-rules.txt +userRulesDefaultFileName=my-umatrix-rules.txt hostsFilesPrompt=Alle Hostnamen einer Hosts-Datei werden als geblacklistete Hostnamen im globalen Geltungsbereich geladen. hostsFilesStats={{blockedHostnameCount}} eindeutig blockierte Hostnamen aus: hostsFilesPerFileStats={{used}} benutzt aus {{total}} @@ -124,7 +124,7 @@ hostsFilesApplyChanges=Änderungen anwenden hostsFilesAutoUpdatePrompt=Hosts-Dateien automatisch aktualisieren. hostsFilesUpdateNow=Jetzt aktualisieren hostsFilesPurgeAll=Alle Cache-Speicher löschen -hostsFilesExternalListsHint=Eine URL pro Zeile. Zeilen mit vorangestelltem ‘#’ werden ignoriert. Ungültige URLs werden stillschweigend ignoriert. +hostsFilesExternalListsHint=<p>One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored.</p><p>The inserted URL must point to a hosts file (including local files); do not use the hosts file syntax here.</p> hostsFilesExternalListsParse=Anwenden hostsFilesExternalListPurge=Cache löschen hostsFilesExternalListNew=Neue Version verfügbar @@ -142,7 +142,7 @@ aboutIssueContributors=Probleme: aboutTranslationContributors=Übersetzungen: aboutUserDataHeader=Deine Daten aboutBackupButton=Sicherung in eine Datei... -aboutBackupFilename=my-ematrix-backup.txt +aboutBackupFilename=my-umatrix-backup.txt aboutRestoreButton=Wiederherstellung aus einer Datei... aboutRestoreConfirm=Alle deine Einstellungen werden überschrieben mit Sicherungs-Daten vom {{time}}, und ηMatrix wird neu gestartet.\n\nSollen alle existierenden Einstellungen mit Sicherungs-Daten überschrieben werden? aboutRestoreError=Die Daten konnten nicht gelesen werden oder sind ungültig @@ -183,4 +183,6 @@ noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can dis settingsUpdateIcon=Do not change the toolbar icon updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +resolveCnameHelp=<p>When resolving an address with DNS, some webistes use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +settingsTextSmaller=Smaller +settingsTextBigger=Bigger diff --git a/locale/el/messages.properties b/locale/el/messages.properties index 220fc96..122c28b 100644 --- a/locale/el/messages.properties +++ b/locale/el/messages.properties @@ -91,7 +91,7 @@ settingsCloudStorageEnabled=Enable cloud storage support privacyPageTitle=ηMatrix – Privacy privacyDeleteBlockedCookiesPrompt=Διαγραφή μπλοκάρισμένων cookies. privacyDeleteBlockedCookiesHelp=<p>Blacklisted cookies are not prevented by <i>ηMatrix</i> from entering your browser. However they are prevented from leaving your browser, which is what really matters. Not blocking cookies before they enter your browser gives you the opportunity to be informed that a site tried to use cookies, and furthermore to inspect their contents if you wish.</p><p>Once these blacklisted cookies have been accounted for by <i>ηMatrix</i>, they can be removed from your browser if you wish so.</p><p><b>Important note:</b> Extensions can make web requests during the course of their normal operation. These requests can result in cookies being created in the browser. If the hostname from where a cookie originate is not whitelisted, the cookie will be removed from the browser by <i>ηMatrix</i> if this option is checked. So be sure that the hostname(s) with which an extension communicate is whitelisted.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Delete non-blocked session cookies +privacyDeleteNonBlockedSessionCookiesPrompt1=Delete non-blocked session cookies privacyDeleteNonBlockedSessionCookiesPrompt2= minutes after the last time they have been used. privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “A session cookie ... is erased when you end the browser session. The session cookie is stored in temporary memory and is not retained after the browser is closed.”</p><p>Except that this <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>might not be happening</a> in some browsers. Also, to some, having to close the browser in order for the session cookies to clear might not be early enough.</p> privacyDeleteBlockedLocalStoragePrompt=Delete <a href='https://en.wikipedia.org/wiki/Web_storage'>local storage</a> content set by blocked hostnames @@ -115,7 +115,7 @@ userRulesEditDicard=Discard userRulesImport=Import from file... userRulesExport=Export to file... userRulesFormatHint=See this page for rule syntax. -userRulesDefaultFileName=my-ematrix-rules.txt +userRulesDefaultFileName=my-umatrix-rules.txt hostsFilesPrompt=All hostnames in a hosts file are loaded as blacklisted hostnames in the global scope. hostsFilesStats={{blockedHostnameCount}} distinct blocked hostnames from: hostsFilesPerFileStats={{used}} used out of {{total}} @@ -124,7 +124,7 @@ hostsFilesApplyChanges=Apply changes hostsFilesAutoUpdatePrompt=Auto-update hosts files. hostsFilesUpdateNow=Update now hostsFilesPurgeAll=Purge all caches -hostsFilesExternalListsHint=One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored. +hostsFilesExternalListsHint=<p>One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored.</p><p>The inserted URL must point to a hosts file (including local files); do not use the hosts file syntax here.</p> hostsFilesExternalListsParse=Parse hostsFilesExternalListPurge=purge cache hostsFilesExternalListNew=new version available @@ -142,7 +142,7 @@ aboutIssueContributors=Issues: aboutTranslationContributors=Translations: aboutUserDataHeader=Your data aboutBackupButton=Backup to file... -aboutBackupFilename=my-ematrix-backup.txt +aboutBackupFilename=my-umatrix-backup.txt aboutRestoreButton=Restore from file... aboutRestoreConfirm=All your settings will be overwritten using data backed up on {{time}}, and ηMatrix will restart.\n\nOverwrite all existing settings using backed up data? aboutRestoreError=The data could not be read or is invalid @@ -183,4 +183,6 @@ noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can dis settingsUpdateIcon=Do not change the toolbar icon updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +resolveCnameHelp=<p>When resolving an address with DNS, some webistes use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +settingsTextSmaller=Smaller +settingsTextBigger=Bigger diff --git a/locale/en/messages.properties b/locale/en/messages.properties index 5bcbba5..094600d 100644 --- a/locale/en/messages.properties +++ b/locale/en/messages.properties @@ -91,7 +91,7 @@ settingsCloudStorageEnabled=Enable cloud storage support privacyPageTitle=ηMatrix – Privacy privacyDeleteBlockedCookiesPrompt=Delete blocked cookies. privacyDeleteBlockedCookiesHelp=<p>Blacklisted cookies are not prevented by <i>ηMatrix</i> from entering your browser. However they are prevented from leaving your browser, which is what really matters. Not blocking cookies before they enter your browser gives you the opportunity to be informed that a site tried to use cookies, and furthermore to inspect their contents if you wish.</p><p>Once these blacklisted cookies have been accounted for by <i>ηMatrix</i>, they can be removed from your browser if you wish so.</p><p><b>Important note:</b> Extensions can make web requests during the course of their normal operation. These requests can result in cookies being created in the browser. If the hostname from where a cookie originate is not whitelisted, the cookie will be removed from the browser by <i>ηMatrix</i> if this option is checked. So be sure that the hostname(s) with which an extension communicate is whitelisted.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Delete non-blocked session cookies +privacyDeleteNonBlockedSessionCookiesPrompt1=Delete non-blocked session cookies privacyDeleteNonBlockedSessionCookiesPrompt2= minutes after the last time they have been used. privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “A session cookie ... is erased when you end the browser session. The session cookie is stored in temporary memory and is not retained after the browser is closed.”</p><p>Except that this <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>might not be happening</a> in some browsers. Also, to some, having to close the browser in order for the session cookies to clear might not be early enough.</p> privacyDeleteBlockedLocalStoragePrompt=Delete <a href='https://en.wikipedia.org/wiki/Web_storage'>local storage</a> content set by blocked hostnames @@ -115,7 +115,7 @@ userRulesEditDicard=Discard userRulesImport=Import from file... userRulesExport=Export to file... userRulesFormatHint=See this page for rule syntax. -userRulesDefaultFileName=my-ematrix-rules.txt +userRulesDefaultFileName=my-umatrix-rules.txt hostsFilesPrompt=All hostnames in a hosts file are loaded as blacklisted hostnames in the global scope. hostsFilesStats={{blockedHostnameCount}} distinct blocked hostnames from: hostsFilesPerFileStats={{used}} used out of {{total}} @@ -124,7 +124,7 @@ hostsFilesApplyChanges=Apply changes hostsFilesAutoUpdatePrompt=Auto-update hosts files. hostsFilesUpdateNow=Update now hostsFilesPurgeAll=Purge all caches -hostsFilesExternalListsHint=One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored. +hostsFilesExternalListsHint=<p>One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored.</p><p>The inserted URL must point to a hosts file (including local files); do not use the hosts file syntax here.</p> hostsFilesExternalListsParse=Parse hostsFilesExternalListPurge=purge cache hostsFilesExternalListNew=new version available @@ -142,7 +142,7 @@ aboutIssueContributors=Issues: aboutTranslationContributors=Translations: aboutUserDataHeader=Your data aboutBackupButton=Backup to file... -aboutBackupFilename=my-ematrix-backup.txt +aboutBackupFilename=my-umatrix-backup.txt aboutRestoreButton=Restore from file... aboutRestoreConfirm=All your settings will be overwritten using data backed up on {{time}}, and ηMatrix will restart.\n\nOverwrite all existing settings using backed up data? aboutRestoreError=The data could not be read or is invalid @@ -183,4 +183,6 @@ noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can dis settingsUpdateIcon=Do not change the toolbar icon updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +resolveCnameHelp=<p>When resolving an address with DNS, some webistes use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +settingsTextSmaller=Smaller +settingsTextBigger=Bigger diff --git a/locale/eo/messages.properties b/locale/eo/messages.properties deleted file mode 100644 index 42ddf98..0000000 --- a/locale/eo/messages.properties +++ /dev/null @@ -1,186 +0,0 @@ -extName=ηMatrix -dashboardPageName=ηMatrix — Panelo -loggerPageName=ηMatrix — Logger -settingsPageName=Agordoj -privacyPageName=Privateco -statsPageName=Statistics -userRulesPageName=Miaj reguloj -ubiquitousRulesPageName=Hosts files -rawSettingsPageName=More -aboutPageName=Pri -allPrettyName=all -cookiePrettyName=kuketo -cssPrettyName=css -imagePrettyName=bildo -mediaPrettyName=media -pluginPrettyName=kromaĵo -scriptPrettyName=skripto -xhrPrettyName=XHR -framePrettyName=kadro -otherPrettyName=alia -matrixNoNetTrafficPrompt=No net traffic seen for this tab so far. -matrixMtxButtonTip=Disable/enable matrix filtering for this scope. -matrixPersistButtonTip=Save all temporary changes for this scope. -matrixRevertButtonTip=Revert temporary changes for this scope. -matrixReloadButton=Reŝargi la paĝon. -matrixScopeTip=Change to global scope. -matrixSwitchesTip=Dropdown menu with additional settings. -matrix1stPartyLabel=1st-party -matrixBlacklistedHostnames={{count}} blacklisted hostname(s) -matrixSwitchNoMixedContent=Forbid mixed content -matrixSwitchNoWorker=Forbid web workers -matrixSwitchReferrerSpoof=Spoof <code>Referer</code> header -matrixSwitchNoscriptSpoof=Spoof <code><noscript></code> tags -matrixRevertAllEntry=Revert all temporary changes -matrixLoggerMenuEntry=Iri al protokolilo -matrixDashboardMenuEntry=Iri al panelo -matrixNoTabFound=No web page found -statsPageTitle=ηMatrix – Statistics -statsPageGenericStats=Generic statistics -statsPageCookieHeadersFoiled=<a href='https://en.wikipedia.org/wiki/HTTP_cookie'>HTTP cookie</a> headers foiled: {{count}} -statsPageRefererHeadersFoiled=<a href='https://en.wikipedia.org/wiki/HTTP_referer'>HTTP referer</a> headers foiled: {{count}} -statsPageHyperlinkAuditingFoiled=<a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>Hyperlink auditing</a> attempts foiled: {{count}} -statsPageCookiesRemoved=Lokaj kuketoj forigitaj: {{count}} -statsPageLocalStoragesCleared=<a href='http://diveintohtml5.info/storage.html'>Lokaj konservadoj</a> malplenigitaj: {{count}} -statsPageBrowserCacheCleared=Browser caches cleared: {{count}} -statsPageDetailedStats=Detailed statistics -statsPageDetailedAllPages=All -statsPageDetailedBehindTheScenePage=Behind the scene -statsPageOverview=Superrigardo -statsPageRequests=Petoj -statsPageAllowed=Allowed -statsPageBlocked=Blocked -statsPageAll=All -statsPagePages=Paĝoj -statsPageCookies=Kuketoj -statsPageCSS=CSS -statsPageImages=Bildoj -statsPagePlugins=Kromaĵoj -statsPageScripts=Skriptoj -statsPageXHRs=XHR-oj -statsPageFrames=Kadroj -statsPageOthers=Aliaj -statsPageDetailed=Protokolilo -statsPageLogSizePrompt1=Remember the last -statsPageLogSizePrompt2=HTTP requests <b>per page</b>. -statsPageLogSizeHelp=<p>You can inspect details of the most recent raw HTTP requests which have been made by a web page (see below).</p><p>This is mostly useful to advanced users who want to investigate exactly what a web page has been doing. But logging these HTTP requests requires memory, and if you don't care about this technical information, then memory is being wasted.</p><p>Hence this field which lets you adjust the maximum number of the most recent HTTP requests which are to be logged for further inspection.</p><p>Enter “<code>0</code>” to turn off detailed logging (and consequently reduce the memory footprint of <i>ηMatrix</i>).</p> -statsPageRefresh=Aktualigi -settingsPageTitle=ηMatrix – Agordoj -settingsMatrixDisplayHeader=Apero -settingsMatrixDisplayTextSizePrompt=Tekstogrando: -settingsMatrixDisplayTextSizeNormal=Normala -settingsMatrixDisplayTextSizeLarge=Granda -settingsMatrixDisplayColorBlind=Afabla por kolorblinduloj -settingsMatrixConvenienceHeader=Komforto -settingsDefaultScopeLevel=Default scope level: -settingsDefaultScopeLevel0=Global -settingsDefaultScopeLevel1=Domain -settingsDefaultScopeLevel2=Site -settingsMatrixAutoReloadPrompt=When the matrix is closed, smart reload these tabs: -settingsMatrixAutoReloadNone=None -settingsMatrixAutoReloadCurrent=Nuna -settingsMatrixAutoReloadAll=All -settingsMatrixAutoReloadInfo=Whenever you make changes in the matrix which can affect the display and/or behavior of one or more pages, <i>ηMatrix</i> will reload affected pages automatically when you close the matrix. -settingsSubframeColor=Blocked frames: Color -settingsSubframeOpacity=Opakeco -settingsIconBadgeEnabled=Show the number of blocked requests on the icon -settingsCollapseBlocked=Collapse placeholder of blocked elements -settingsCollapseBlacklisted=Collapse placeholder of blacklisted elements -settingsNoscriptTagsSpoofed=Spoof <code><noscript></code> tags when 1st-party scripts are blocked -settingsCloudStorageEnabled=Ŝalti subtenon por nuba konservado -privacyPageTitle=ηMatrix – Privateco -privacyDeleteBlockedCookiesPrompt=Delete blocked cookies. -privacyDeleteBlockedCookiesHelp=<p>Blacklisted cookies are not prevented by <i>ηMatrix</i> from entering your browser. However they are prevented from leaving your browser, which is what really matters. Not blocking cookies before they enter your browser gives you the opportunity to be informed that a site tried to use cookies, and furthermore to inspect their contents if you wish.</p><p>Once these blacklisted cookies have been accounted for by <i>ηMatrix</i>, they can be removed from your browser if you wish so.</p><p><b>Important note:</b> Extensions can make web requests during the course of their normal operation. These requests can result in cookies being created in the browser. If the hostname from where a cookie originate is not whitelisted, the cookie will be removed from the browser by <i>ηMatrix</i> if this option is checked. So be sure that the hostname(s) with which an extension communicate is whitelisted.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Delete non-blocked session cookies -privacyDeleteNonBlockedSessionCookiesPrompt2= minutes after the last time they have been used. -privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “A session cookie ... is erased when you end the browser session. The session cookie is stored in temporary memory and is not retained after the browser is closed.”</p><p>Except that this <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>might not be happening</a> in some browsers. Also, to some, having to close the browser in order for the session cookies to clear might not be early enough.</p> -privacyDeleteBlockedLocalStoragePrompt=Delete <a href='https://en.wikipedia.org/wiki/Web_storage'>local storage</a> content set by blocked hostnames -privacyDeleteBlockedLocalStorageHelp=TODO -privacyClearCachePrompt1=Clear browser cache every -privacyClearCachePrompt2=minutoj. -privacyClearCacheHelp=<p>Some web sites are really bent on tracking you, so much that they will use not-so-nice tricks to work around whatever measures you take in order to not be tracked.</p><p>A few of these tricks rely<sup>[1, 2]</sup> on the <a href='https://en.wikipedia.org/wiki/Web_cache'>browser cache</a>, which content is often long lasting since rarely will users take the time to regularly clear their browser cache.</p><p>There is little inconvenience to clear the browser cache regularly (likelihood is that you won't notice when it happens), and the benefit is to prevent these obnoxious trackers from invading your privacy.</p><p>Check this option to have <i>ηMatrix</i> do it for you, at the interval you wish.</p><p>[1] <a href='https://grepular.com/Preventing_Web_Tracking_via_the_Browser_Cache'>“Preventing Web Tracking via the Browser Cache”</a>\n[2] <a href='http://lucb1e.com/rp/cookielesscookies/'>“Cookieless cookies”</a></p> -privacyProcessRefererPrompt=Spoof <a href='https://en.wikipedia.org/wiki/HTTP_referer'>HTTP referrer</a> string of third-party requests. -privacyProcessRefererHelp=From Wikipedia:<blockquote>HTTP referer is an HTTP header field that identifies the address of the webpage that linked to the resource being requested. ... <b>Because referer information can violate privacy, some web browsers allow the user to disable the sending of referer information.</b></blockquote>If this setting is checked, <i>ηMatrix</i> will spoof the HTTP referrer information if the domain name of the HTTP referrer is third-party to the domain name of net request. -privacyNoMixedContentPrompt=Strict HTTPS: forbid mixed content. -privacyNoMixedContentHelp=<p>From <a href='https://developer.mozilla.org/en-US/docs/Security/MixedContent'>Mozilla Developer Network</a>:</p><blockquote>If [a] HTTPS page includes content retrieved through regular, cleartext HTTP, then the connection is only partially encrypted: the unencrypted content is accessible to sniffers and can be modified by man-in-the-middle attackers, and therefore the connection is not safeguarded anymore. When a webpage exhibits this behavior, it is called a mixed content page.</blockquote> -privacyProcessHyperlinkAuditingPrompt=Block all <a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>hyperlink auditing</a> attempts. -privacyProcessHyperlinkAuditingHelp=<p>Hyperlink auditing is a mechanism which allow a party, <b>any party</b>, to be informed about which link a user clicked on a particular web page. It is essentially a tracking feature: it allows a web site, or any third-party to that web site, to be informed about which link you clicked on which one of its web pages. The sole purpose is to track your browsing activity.</p> -userRulesPermanentHeader=Daŭraj reguloj -userRulesTemporaryHeader=Nedaŭraj reguloj -userRulesRevert=Malfari -userRulesCommit=Konservi -userRulesEdit=Redakti -userRulesEditSave=Konservi -userRulesEditDicard=Ignori -userRulesImport=Importi el dosiero... -userRulesExport=Eksporti al dosiero... -userRulesFormatHint=See this page for rule syntax. -userRulesDefaultFileName=miaj-ematrix-reguloj.txt -hostsFilesPrompt=All hostnames in a hosts file are loaded as blacklisted hostnames in the global scope. -hostsFilesStats={{blockedHostnameCount}} distinct blocked hostnames from: -hostsFilesPerFileStats={{used}} used out of {{total}} -hostsFilesLastUpdate=Lasta ĝisdatigo: {{ago}} -hostsFilesApplyChanges=Apliki ŝanĝojn -hostsFilesAutoUpdatePrompt=Auto-update hosts files. -hostsFilesUpdateNow=Ĝisdatigi nun -hostsFilesPurgeAll=Malplenigi ĉiujn kaŝmemorojn -hostsFilesExternalListsHint=One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored. -hostsFilesExternalListsParse=Analizi -hostsFilesExternalListPurge=malplenigi kaŝmemoron -hostsFilesExternalListNew=nova versio disponebla -hostsFilesExternalListObsolete=neĝisdata -rawSettingsWarning=Warning! Change these raw configuration settings at your own risk. -aboutChangelog=Ŝanĝoprotokolo -aboutStorageUsed=Storage used: {{storageUsed}} bytes -aboutDoc=Documentation -aboutPermissions=Permissions -aboutCode=Fontkodo (GPLv3) -aboutIssues=Cimoj kaj problemoj -aboutContributors=Kontribuantoj -aboutCodeContributors=Kode: -aboutIssueContributors=Problemoj: -aboutTranslationContributors=Tradukoj: -aboutUserDataHeader=Viaj datumoj -aboutBackupButton=Savkopii al dosiero... -aboutBackupFilename=mia-ematrix-savkopio.txt -aboutRestoreButton=Restore from file... -aboutRestoreConfirm=All your settings will be overwritten using data backed up on {{time}}, and ηMatrix will restart.\n\nOverwrite all existing settings using backed up data? -aboutRestoreError=The data could not be read or is invalid -aboutOr=... aŭ ... -aboutResetButton=Reset to default settings -aboutResetConfirm=Caution! this will remove all your custom settings. Are you sure you want to proceed? -loggerFilterInputPlaceholder=filter expression(s) -loggerMaxEntriesTip=Maximum number of entries -loggerEntryCookieDeleted=kuketo forigita: {{value}} -loggerEntryDeleteCookieError=failed to delete cookie: {{value}} -loggerEntryBrowserCacheCleared=browser cache cleared -loggerEntryAssetUpdated=asset updated: {{value}} -mainBlockedPrompt1=ηMatrix has prevented the following page from loading: -mainBlockedPrompt2=Because of the following rule -mainBlockedBack=Reen -mainBlockedClose=Fermi -commandRevertAll=Revert all temporary changes -commandWhitelistPageDomain=Temporarily whitelist page domain -commandWhitelistAll=Temporarily whitelist all -commandOpenDashboard=Malfermi la panelo -elapsedOneMinuteAgo=antaŭ 1 minuto -elapsedManyMinutesAgo=antaŭ {{value}} minutoj -elapsedOneHourAgo=antaŭ 1 horo -elapsedManyHoursAgo=antaŭ {{value}} horoj -elapsedOneDayAgo=antaŭ 1 tago -elapsedManyDaysAgo=antaŭ {{value}} tagoj -showDashboardButton=Panelo -showLoggerButton=Protokolilo -cloudPush=Eksporti al nuba konservado -cloudPull=Importi el nuba konservado -cloudNoData=...\n... -cloudDeviceNamePrompt=Nomo de ĉi tiu aparato: -genericSubmit=Sendi -genericRevert=Malfari -errorCantConnectTo=Reteraro: {{url}} ne konekteblas -genericApplyChanges=Apply changes -noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can display some content by using the <noscript> tag. For example, some websites will redirect users to a “scriptless” version.</p><p>When ηMatrix blocks scripts, the browser will still advertise itself as supporting script execution unless this option is selected.</p><p>When selected, ηMatrix will tell the website that the browser does not support scripts, which is what you definitely want to do if you are blocking 1st-party scripts. As such, the <noscript> tag will work as intended.</p><p>Not selecting this option when 1st-party scripts are blocked means the website will break misteryously in case it is meant to redirect to a scriptless version.</p> -settingsUpdateIcon=Do not change the toolbar icon -updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> -resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> diff --git a/locale/es/messages.properties b/locale/es/messages.properties index 3dd8803..aab78ae 100644 --- a/locale/es/messages.properties +++ b/locale/es/messages.properties @@ -6,7 +6,7 @@ privacyPageName=Privacidad statsPageName=Estadísticas userRulesPageName=Mis reglas ubiquitousRulesPageName=Ficheros hosts -rawSettingsPageName=Más +rawSettingsPageName=More aboutPageName=Acerca de allPrettyName=todo cookiePrettyName=cookie @@ -23,14 +23,14 @@ matrixMtxButtonTip=Deshabilita/habilita el filtrado por matriz en este ámbito. matrixPersistButtonTip=Guardar cambios temporales para este ámbito. matrixRevertButtonTip=Deshacer cambios temporales para este ámbito. matrixReloadButton=Recargar la página. -matrixScopeTip=Cambio a alcance global. -matrixSwitchesTip=Menú desplegable con configuraciones adicionales. +matrixScopeTip=Change to global scope. +matrixSwitchesTip=Dropdown menu with additional settings. matrix1stPartyLabel=dominio actual matrixBlacklistedHostnames={{count}} nombre(s) de <i>host</i> en la lista negra matrixSwitchNoMixedContent=HTTPS estricto -matrixSwitchNoWorker=Prohibir web workers +matrixSwitchNoWorker=Forbid web workers matrixSwitchReferrerSpoof=Falsificar Referer -matrixSwitchNoscriptSpoof=Falsificar etiqueta <code><noscript></code> +matrixSwitchNoscriptSpoof=Spoof <code><noscript></code> tags matrixRevertAllEntry=Deshacer todos los cambios temporales matrixLoggerMenuEntry=Ir al registro de peticiones matrixDashboardMenuEntry=Ir al Panel de control @@ -45,7 +45,7 @@ statsPageLocalStoragesCleared=<a href='http://diveintohtml5.info/storage.html'>A statsPageBrowserCacheCleared=Memorias caché del navegador eliminadas: {{count}} statsPageDetailedStats=Estadísticas detalladas statsPageDetailedAllPages=Todo -statsPageDetailedBehindTheScenePage=Detrás de la escena +statsPageDetailedBehindTheScenePage=Chromium: Behind the scene statsPageOverview=Sumario statsPageRequests=Peticiones statsPageAllowed=Permitidas @@ -83,15 +83,15 @@ settingsMatrixAutoReloadAll=Todas settingsMatrixAutoReloadInfo=Cada vez que se hagan cambios en la matriz que puedan afectar la visualización y/o el comportamiento de una o más páginas, <i>ηMatrix</i> recargará automáticamente las páginas afectadas una vez se cierre la matriz. settingsSubframeColor=<i>Frames</i> bloqueados: Color settingsSubframeOpacity=Opacidad -settingsIconBadgeEnabled=Mostrar el número de solicitudes bloqueadas en el icono +settingsIconBadgeEnabled=Show the number of blocked requests on the icon settingsCollapseBlocked=Colapsar marcadores de posición de los elementos bloqueados -settingsCollapseBlacklisted=Contraer marcador de posición de elementos en la lista negra -settingsNoscriptTagsSpoofed=Falsifica las etiquetas <code><noscript></code> cuando los scripts de terceros están bloqueados +settingsCollapseBlacklisted=Collapse placeholder of blacklisted elements +settingsNoscriptTagsSpoofed=Spoof <code><noscript></code> tags when 1st-party scripts are blocked settingsCloudStorageEnabled=Habilitar soporte de almacenamiento en la nube privacyPageTitle=ηMatrix – Privacidad privacyDeleteBlockedCookiesPrompt=Eliminar <i>cookies</i> bloquedas. privacyDeleteBlockedCookiesHelp=<p><i>ηMatrix</i> no previene la entrada al navegador de <i>cookies</i> en la lista negra, pero sí su salida, que es lo que realmente importa. El hecho de no bloquear las <i>cookies</i> antes de su entrada, da la oportunidad de saber si un sitio intenta usar <i>cookies</i>, e inspeccionar su contenido si se desea.</p><p>Una vez que tales <i>cookies</i> han sido detectadas por <i>ηMatrix</i>, las mismas pueden ser eliminadas del navegador si lo decide.</p><p><b>Nota importante:</b> Las extensiones pueden hacer peticiones web como parte de su normal operación. Estas peticiones pueden resultar en la creación de <i>cookies</i> dentro del navegador. Si el nombre de <i>host</i> a partir del cual se generó la <i>cookie</i> no está en la lista de permitidos, la <i>cookie</i> será eliminada por <i>ηMatrix</i> mientras esta opción esté activa. Así que asegúrese de permitir los nombres de <i>host</i> con los cuales se comunica una extensión determinada.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Elimina las <i>cookies</i> de sesión no bloqueadas +privacyDeleteNonBlockedSessionCookiesPrompt1=Elimina las <i>cookies</i> de sesión no bloqueadas privacyDeleteNonBlockedSessionCookiesPrompt2= minutos a partir de la última vez que fueron usadas. privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “Una <i>cookie</i> de sesión ... es eliminada una vez usted termina la sesión del navegador. La <i>cookie</i> de sesión es almacenada en la memoria temporal y no está disponible luego de cerrar el navegador.”</p><p>Excepto que esto <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>pudiera no estar sucediendo así</a> cuando se usa un navegador basado en Chromium. Además, cerrar el navegador para limpiar las <i>cookies</i> de sesión quizás no sea lo suficientemente rápido para algunos.</p> privacyDeleteBlockedLocalStoragePrompt=Eliminar contenido de los nombres de dominio bloqueados <a href='https://en.wikipedia.org/wiki/Web_storage'>almacenado localmente</a> @@ -115,7 +115,7 @@ userRulesEditDicard=Descartar userRulesImport=Importar desde archivo... userRulesExport=Exportar a archivo... userRulesFormatHint=Consulte esta página para sintaxis de las reglas. -userRulesDefaultFileName=my-ematrix-rules.txt +userRulesDefaultFileName=my-umatrix-rules.txt hostsFilesPrompt=Todos los nombres de dominio en un fichero <i>hosts</i> son cargados como nombres de dominio en lista negra de manera global. hostsFilesStats={{blockedHostnameCount}} nombres de dominios únicos bloqueados a partir de: hostsFilesPerFileStats={{used}} usados de un total de {{total}} @@ -124,12 +124,12 @@ hostsFilesApplyChanges=Aplicar cambios hostsFilesAutoUpdatePrompt=Actualización automática de ficheros <i>hosts</i>. hostsFilesUpdateNow=Actualizar ahora hostsFilesPurgeAll=Vaciar todas las memorias caché -hostsFilesExternalListsHint=Una URL por línea. Las línes con prefijo ‘#’ serán ignoradas. Las URL inválidas serán ignoradas de manera silenciosa. +hostsFilesExternalListsHint=<p>One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored.</p><p>The inserted URL must point to a hosts file (including local files); do not use the hosts file syntax here.</p> hostsFilesExternalListsParse=Analizar hostsFilesExternalListPurge=vaciar caché hostsFilesExternalListNew=nueva versión disponible hostsFilesExternalListObsolete=desactualizado -rawSettingsWarning=¡Advertencia! Cambie estos ajustes de configuración sin formato bajo su propio riesgo. +rawSettingsWarning=Warning! Change these raw configuration settings at your own risk. aboutChangelog=Registro de cambios aboutStorageUsed=Almacenamiento usado: {{storageUsed}} bytes aboutDoc=Documentación @@ -142,7 +142,7 @@ aboutIssueContributors=Problemas: aboutTranslationContributors=Traducciones: aboutUserDataHeader=Sus datos aboutBackupButton=Respaldar en archivo... -aboutBackupFilename=my-ematrix-backup.txt +aboutBackupFilename=my-umatrix-backup.txt aboutRestoreButton=Restaurar desde archivo... aboutRestoreConfirm=Todos sus ajustes serán sobrescritos usando los datos respaldados en {{time}}, y ηMatrix se reiniciará.\n\n¿Sobrescribir todos los ajustes actuales usando los datos de respaldo? aboutRestoreError=Los datos no se pueden leer o son inválidos @@ -178,9 +178,11 @@ cloudDeviceNamePrompt=Nombre de este dispositivo: genericSubmit=Enviar genericRevert=Deshacer errorCantConnectTo=Error de red: Imposible conectar con {{url}} -genericApplyChanges=Aplicar los cambios -noscriptSpoofHelp=<p>Cuando un navegador no admite scripts, una página web puede mostrar algún contenido utilizando la etiqueta <noscript>. Por ejemplo, algunos sitios web redirigen a los usuarios a una versión sin “scriptless”</p><p>Cuando ηMatrix bloquea los scripts, el navegador seguirá publicitándose como compatible con la ejecución de scripts a menos que se seleccione esta opción.</p><p>Cuando se selecciona, ηMatrix le dirá al sitio web que el navegador no admite scripts, que es lo que definitivamente desea hacer si está bloqueando scripts de terceros. Como tal, la etiqueta <noscript> funcionará según lo previsto.</p><p>No seleccionar esta opción cuando los scripts de terceros están bloqueados significa que el sitio web se romperá misteriosamente en caso de que deba redirigirse a una versión sin script.</p> -settingsUpdateIcon=No cambie el ícono de la barra de herramientas -updateIconHelp=<p>Por defecto, la extensión cambiará su ícono en función de cuántas solicitudes estén bloqueadas en la página seleccionada.</p><p>Al seleccionar esta opción, evitará que ηMatrix cambie su icono.</p><p>Cuando la página no tiene solicitudes (por ejemplo, el panel de control de la extensión), el icono seguirá cambiando al estado “deshabilitado”.</p> -resolveCnameLabel=Resolver registros CNAME -resolveCnameHelp=<p>Al resolver una dirección con DNS, algunos sitios web utilizan un registro CNAME para redirigir la resolución a una dirección diferente a la solicitada por el usuario.</p><p>Este mecanismo tiene usos legítimos y es conveniente en varios casos, pero también puede ser abusado por delincuentes sin escrúpulos al “ocultar” (encubierto) la dirección de un rastreador detrás de una dirección legítima.</p><p>Cuando esta configuración está habilitada, ηMatrix consultará el DNS cuando se cumpla una nueva dirección, lo que hará que use el nombre canónico (CNAME) del sitio web.</p><p><b>Tenga en cuenta</b>: Esto romperá su lista blanca. También es experimental y se recomienda alternar esta opción <i>antes</i> de visitar un sitio web. Alternarlo y luego actualizar una página ya cargada puede causar problemas extraños en este momento.</p> +genericApplyChanges=Apply changes +noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can display some content by using the <noscript> tag. For example, some websites will redirect users to a “scriptless” version.</p><p>When ηMatrix blocks scripts, the browser will still advertise itself as supporting script execution unless this option is selected.</p><p>When selected, ηMatrix will tell the website that the browser does not support scripts, which is what you definitely want to do if you are blocking 1st-party scripts. As such, the <noscript> tag will work as intended.</p><p>Not selecting this option when 1st-party scripts are blocked means the website will break misteryously in case it is meant to redirect to a scriptless version.</p> +settingsUpdateIcon=Do not change the toolbar icon +updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> +resolveCnameLabel=Resolve CNAME records +resolveCnameHelp=<p>When resolving an address with DNS, some webistes use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +settingsTextSmaller=Smaller +settingsTextBigger=Bigger diff --git a/locale/et/messages.properties b/locale/et/messages.properties deleted file mode 100644 index bbeeac8..0000000 --- a/locale/et/messages.properties +++ /dev/null @@ -1,186 +0,0 @@ -extName=ηMatrix -dashboardPageName=ηMatrix — Esilehekülg -loggerPageName=ηMatrix — Logger -settingsPageName=Seaded -privacyPageName=Privaatsus -statsPageName=Statistika -userRulesPageName=Minu reeglid -ubiquitousRulesPageName=Host-failid -rawSettingsPageName=More -aboutPageName=Teave -allPrettyName=kõik -cookiePrettyName=küpsis -cssPrettyName=css -imagePrettyName=pilt -mediaPrettyName=media -pluginPrettyName=meedia -scriptPrettyName=skript -xhrPrettyName=XHR -framePrettyName=raam -otherPrettyName=teised -matrixNoNetTrafficPrompt=Selle kaardi kohta pole veel netiliiklust näha. -matrixMtxButtonTip=Selle määratluse puhul keela/luba maatriksiline filtreerimine.\nMaatriksilise filtreerimise blokeeritud ühendused selles portaalis: {{count}}. -matrixPersistButtonTip=Salvesta ajutiselt kõik selle määratluse muudatused. -matrixRevertButtonTip=Eemalda selle määratluse ajutised muudatused. -matrixReloadButton=Värskenda lehekülge. -matrixScopeTip=Change to global scope. -matrixSwitchesTip=Dropdown menu with additional settings. -matrix1stPartyLabel=1. osapool -matrixBlacklistedHostnames={{count}} hosti nimi(e) mustas nimekirjas -matrixSwitchNoMixedContent=Range HTTPS -matrixSwitchNoWorker=Forbid web workers -matrixSwitchReferrerSpoof=Viitaja narritamine -matrixSwitchNoscriptSpoof=Spoof <code><noscript></code> tags -matrixRevertAllEntry=Revert all temporary changes -matrixLoggerMenuEntry=Mine logijasse -matrixDashboardMenuEntry=Mine esilehele -matrixNoTabFound=No web page found -statsPageTitle=ηMatrix – statistika -statsPageGenericStats=Üldstatistika -statsPageCookieHeadersFoiled=<a href='https://et.wikipedia.org/wiki/HTTP-k%C3%BCpsis'>HTTP-küpsise</a> tõrjutud päismik: {{count}} -statsPageRefererHeadersFoiled=<a href='https://en.wikipedia.org/wiki/HTTP_referer'>HTTP referer</a> headers foiled: {{count}} -statsPageHyperlinkAuditingFoiled=<a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>Hyperlink auditing</a> attempts foiled: {{count}} -statsPageCookiesRemoved=Local cookies removed: {{count}} -statsPageLocalStoragesCleared=<a href='http://diveintohtml5.info/storage.html'>Local storages</a> emptied: {{count}} -statsPageBrowserCacheCleared=Browser caches cleared: {{count}} -statsPageDetailedStats=Detailed statistics -statsPageDetailedAllPages=Kõik -statsPageDetailedBehindTheScenePage=Behind the scene -statsPageOverview=Overview -statsPageRequests=Päringud -statsPageAllowed=Lubatud -statsPageBlocked=Blokeeritud -statsPageAll=Kõik -statsPagePages=Leheküljed -statsPageCookies=Küpsised -statsPageCSS=CSS -statsPageImages=Pildid -statsPagePlugins=Liidesed -statsPageScripts=Skriptid -statsPageXHRs=XHRid -statsPageFrames=Raamid -statsPageOthers=Muud -statsPageDetailed=Logija -statsPageLogSizePrompt1=Remember the last -statsPageLogSizePrompt2=HTTP requests <b>per page</b>. -statsPageLogSizeHelp=<p>You can inspect details of the most recent raw HTTP requests which have been made by a web page (see below).</p><p>This is mostly useful to advanced users who want to investigate exactly what a web page has been doing. But logging these HTTP requests requires memory, and if you don't care about this technical information, then memory is being wasted.</p><p>Hence this field which lets you adjust the maximum number of the most recent HTTP requests which are to be logged for further inspection.</p><p>Enter “<code>0</code>” to turn off detailed logging (and consequently reduce the memory footprint of <i>ηMatrix</i>).</p> -statsPageRefresh=Refresh -settingsPageTitle=ηMatrix – Settings -settingsMatrixDisplayHeader=Matrix -settingsMatrixDisplayTextSizePrompt=Text size: -settingsMatrixDisplayTextSizeNormal=Normaalne -settingsMatrixDisplayTextSizeLarge=Suur -settingsMatrixDisplayColorBlind=Color-blind friendly -settingsMatrixConvenienceHeader=Convenience -settingsDefaultScopeLevel=Default scope level: -settingsDefaultScopeLevel0=Global -settingsDefaultScopeLevel1=Domain -settingsDefaultScopeLevel2=Site -settingsMatrixAutoReloadPrompt=When the matrix is closed, smart reload these tabs: -settingsMatrixAutoReloadNone=Pole -settingsMatrixAutoReloadCurrent=Current -settingsMatrixAutoReloadAll=Kõik -settingsMatrixAutoReloadInfo=Whenever you make changes in the matrix which can affect the display and/or behavior of one or more pages, <i>ηMatrix</i> will reload affected pages automatically when you close the matrix. -settingsSubframeColor=Blocked frames: Color -settingsSubframeOpacity=Opacity -settingsIconBadgeEnabled=Show the number of blocked requests on the icon -settingsCollapseBlocked=Collapse placeholder of blocked elements -settingsCollapseBlacklisted=Collapse placeholder of blacklisted elements -settingsNoscriptTagsSpoofed=Spoof <code><noscript></code> tags when 1st-party scripts are blocked -settingsCloudStorageEnabled=Enable cloud storage support -privacyPageTitle=ηMatrix – Privacy -privacyDeleteBlockedCookiesPrompt=Delete blocked cookies. -privacyDeleteBlockedCookiesHelp=<p>Blacklisted cookies are not prevented by <i>ηMatrix</i> from entering your browser. However they are prevented from leaving your browser, which is what really matters. Not blocking cookies before they enter your browser gives you the opportunity to be informed that a site tried to use cookies, and furthermore to inspect their contents if you wish.</p><p>Once these blacklisted cookies have been accounted for by <i>ηMatrix</i>, they can be removed from your browser if you wish so.</p><p><b>Important note:</b> Extensions can make web requests during the course of their normal operation. These requests can result in cookies being created in the browser. If the hostname from where a cookie originate is not whitelisted, the cookie will be removed from the browser by <i>ηMatrix</i> if this option is checked. So be sure that the hostname(s) with which an extension communicate is whitelisted.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Delete non-blocked session cookies -privacyDeleteNonBlockedSessionCookiesPrompt2= minutes after the last time they have been used. -privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “A session cookie ... is erased when you end the browser session. The session cookie is stored in temporary memory and is not retained after the browser is closed.”</p><p>Except that this <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>might not be happening</a> in some browsers. Also, to some, having to close the browser in order for the session cookies to clear might not be early enough.</p> -privacyDeleteBlockedLocalStoragePrompt=Delete <a href='https://en.wikipedia.org/wiki/Web_storage'>local storage</a> content set by blocked hostnames -privacyDeleteBlockedLocalStorageHelp=TODO -privacyClearCachePrompt1=Clear browser cache every -privacyClearCachePrompt2=minutes. -privacyClearCacheHelp=<p>Some web sites are really bent on tracking you, so much that they will use not-so-nice tricks to work around whatever measures you take in order to not be tracked.</p><p>A few of these tricks rely<sup>[1, 2]</sup> on the <a href='https://en.wikipedia.org/wiki/Web_cache'>browser cache</a>, which content is often long lasting since rarely will users take the time to regularly clear their browser cache.</p><p>There is little inconvenience to clear the browser cache regularly (likelihood is that you won't notice when it happens), and the benefit is to prevent these obnoxious trackers from invading your privacy.</p><p>Check this option to have <i>ηMatrix</i> do it for you, at the interval you wish.</p><p>[1] <a href='https://grepular.com/Preventing_Web_Tracking_via_the_Browser_Cache'>“Preventing Web Tracking via the Browser Cache”</a>\n[2] <a href='http://lucb1e.com/rp/cookielesscookies/'>“Cookieless cookies”</a></p> -privacyProcessRefererPrompt=Spoof <a href='https://en.wikipedia.org/wiki/HTTP_referer'>HTTP referrer</a> string of third-party requests. -privacyProcessRefererHelp=From Wikipedia:<blockquote>HTTP referer is an HTTP header field that identifies the address of the webpage that linked to the resource being requested. ... <b>Because referer information can violate privacy, some web browsers allow the user to disable the sending of referer information.</b></blockquote>If this setting is checked, <i>ηMatrix</i> will spoof the HTTP referrer information if the domain name of the HTTP referrer is third-party to the domain name of net request. -privacyNoMixedContentPrompt=Strict HTTPS: forbid mixed content. -privacyNoMixedContentHelp=<p>From <a href='https://developer.mozilla.org/en-US/docs/Security/MixedContent'>Mozilla Developer Network</a>:</p><blockquote>If [a] HTTPS page includes content retrieved through regular, cleartext HTTP, then the connection is only partially encrypted: the unencrypted content is accessible to sniffers and can be modified by man-in-the-middle attackers, and therefore the connection is not safeguarded anymore. When a webpage exhibits this behavior, it is called a mixed content page.</blockquote> -privacyProcessHyperlinkAuditingPrompt=Block all <a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>hyperlink auditing</a> attempts. -privacyProcessHyperlinkAuditingHelp=<p>Hyperlink auditing is a mechanism which allow a party, <b>any party</b>, to be informed about which link a user clicked on a particular web page. It is essentially a tracking feature: it allows a web site, or any third-party to that web site, to be informed about which link you clicked on which one of its web pages. The sole purpose is to track your browsing activity.</p> -userRulesPermanentHeader=Permanent rules -userRulesTemporaryHeader=Temporary rules -userRulesRevert=Revert -userRulesCommit=Commit -userRulesEdit=Edit -userRulesEditSave=Save -userRulesEditDicard=Discard -userRulesImport=Import from file... -userRulesExport=Export to file... -userRulesFormatHint=See this page for rule syntax. -userRulesDefaultFileName=my-ematrix-rules.txt -hostsFilesPrompt=All hostnames in a hosts file are loaded as blacklisted hostnames in the global scope. -hostsFilesStats={{blockedHostnameCount}} distinct blocked hostnames from: -hostsFilesPerFileStats={{used}} used out of {{total}} -hostsFilesLastUpdate=Last update: {{ago}} -hostsFilesApplyChanges=Apply changes -hostsFilesAutoUpdatePrompt=Auto-update hosts files. -hostsFilesUpdateNow=Update now -hostsFilesPurgeAll=Purge all caches -hostsFilesExternalListsHint=One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored. -hostsFilesExternalListsParse=Parse -hostsFilesExternalListPurge=purge cache -hostsFilesExternalListNew=new version available -hostsFilesExternalListObsolete=outdated -rawSettingsWarning=Warning! Change these raw configuration settings at your own risk. -aboutChangelog=Change log -aboutStorageUsed=Storage used: {{storageUsed}} bytes -aboutDoc=Documentation -aboutPermissions=Permissions -aboutCode=Source code (GPLv3) -aboutIssues=Bugs and issues -aboutContributors=Contributors -aboutCodeContributors=Code: -aboutIssueContributors=Issues: -aboutTranslationContributors=Translations: -aboutUserDataHeader=Your data -aboutBackupButton=Backup to file... -aboutBackupFilename=my-ematrix-backup.txt -aboutRestoreButton=Restore from file... -aboutRestoreConfirm=All your settings will be overwritten using data backed up on {{time}}, and ηMatrix will restart.\n\nOverwrite all existing settings using backed up data? -aboutRestoreError=The data could not be read or is invalid -aboutOr=... or ... -aboutResetButton=Reset to default settings -aboutResetConfirm=Caution! this will remove all your custom settings. Are you sure you want to proceed? -loggerFilterInputPlaceholder=filter expression(s) -loggerMaxEntriesTip=Maximum number of entries -loggerEntryCookieDeleted=cookie deleted: {{value}} -loggerEntryDeleteCookieError=failed to delete cookie: {{value}} -loggerEntryBrowserCacheCleared=browser cache cleared -loggerEntryAssetUpdated=asset updated: {{value}} -mainBlockedPrompt1=ηMatrix has prevented the following page from loading: -mainBlockedPrompt2=Because of the following rule -mainBlockedBack=Go back -mainBlockedClose=Close -commandRevertAll=Revert all temporary changes -commandWhitelistPageDomain=Temporarily whitelist page domain -commandWhitelistAll=Temporarily whitelist all -commandOpenDashboard=Open dashboard -elapsedOneMinuteAgo=a minute ago -elapsedManyMinutesAgo={{value}} minutes ago -elapsedOneHourAgo=an hour ago -elapsedManyHoursAgo={{value}} hours ago -elapsedOneDayAgo=a day ago -elapsedManyDaysAgo={{value}} days ago -showDashboardButton=Dashboard -showLoggerButton=Logger -cloudPush=Export to cloud storage -cloudPull=Import from cloud storage -cloudNoData=...\n... -cloudDeviceNamePrompt=This device name: -genericSubmit=Submit -genericRevert=Revert -errorCantConnectTo=Network error: Unable to connect to {{url}} -genericApplyChanges=Apply changes -noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can display some content by using the <noscript> tag. For example, some websites will redirect users to a “scriptless” version.</p><p>When ηMatrix blocks scripts, the browser will still advertise itself as supporting script execution unless this option is selected.</p><p>When selected, ηMatrix will tell the website that the browser does not support scripts, which is what you definitely want to do if you are blocking 1st-party scripts. As such, the <noscript> tag will work as intended.</p><p>Not selecting this option when 1st-party scripts are blocked means the website will break misteryously in case it is meant to redirect to a scriptless version.</p> -settingsUpdateIcon=Do not change the toolbar icon -updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> -resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> diff --git a/locale/fa/messages.properties b/locale/fa/messages.properties deleted file mode 100644 index 1b1b9d0..0000000 --- a/locale/fa/messages.properties +++ /dev/null @@ -1,186 +0,0 @@ -extName=ηMatrix -dashboardPageName=ηMatrix — داشبورد -loggerPageName=ηMatrix — Logger -settingsPageName=تنظیمات -privacyPageName=حریم خصوصی -statsPageName=آمارها -userRulesPageName=قوانین شخصی -ubiquitousRulesPageName=فایلهای هاستها -rawSettingsPageName=More -aboutPageName=درباره -allPrettyName=همه -cookiePrettyName=کوکی -cssPrettyName=css -imagePrettyName=تصویر -mediaPrettyName=media -pluginPrettyName=افزونه -scriptPrettyName=اسکریپت -xhrPrettyName=XHR -framePrettyName=frame -otherPrettyName=سایر -matrixNoNetTrafficPrompt=هیچ ترافیک شبکهای برای این تب تا کنون دیده نشده است. -matrixMtxButtonTip=فعال یا غیرفعال نمودن ماتریس فیلتر برای این محدوده. -matrixPersistButtonTip=ذخیره نمودن همهی تغییرات موقتی برای این محدوده. -matrixRevertButtonTip=بازگرداندن تغییرات موقتی برای این محدوده. -matrixReloadButton=بارگذاری مجدد صفحه. -matrixScopeTip=Change to global scope. -matrixSwitchesTip=Dropdown menu with additional settings. -matrix1stPartyLabel=1st-party -matrixBlacklistedHostnames={{count}} بلاکشده آدرس(های) -matrixSwitchNoMixedContent=فقط HTTPS -matrixSwitchNoWorker=Forbid web workers -matrixSwitchReferrerSpoof=مخفینمودن ارجاعدهنده -matrixSwitchNoscriptSpoof=Spoof <code><noscript></code> tags -matrixRevertAllEntry=بازگرداندن همهی تغییرات موقتی -matrixLoggerMenuEntry=رفتن به logger -matrixDashboardMenuEntry=رفتن به داشبورد -matrixNoTabFound=No web page found -statsPageTitle=ηMatrix – آمارها -statsPageGenericStats=آمارهای کلی -statsPageCookieHeadersFoiled=<a href='https://en.wikipedia.org/wiki/HTTP_cookie'>HTTP کوکی</a> هدرها بیاثر شدند: {{count}} -statsPageRefererHeadersFoiled=<a href='https://en.wikipedia.org/wiki/HTTP_referer'>HTTP ارجاعدهنده</a> هدرها بیاثر شدند: {{count}} -statsPageHyperlinkAuditingFoiled=<a href='http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#hyperlink-auditing'>بررسی لینک</a> تلاشها بیاثر شدند: {{count}} -statsPageCookiesRemoved=کوکیهای محلی پاکشده: {{count}} -statsPageLocalStoragesCleared=<a href='http://diveintohtml5.info/storage.html'>انبارههای محلی</a> خالی شدند: {{count}} -statsPageBrowserCacheCleared=کشهای مرورگر پاک شدند: {{count}} -statsPageDetailedStats=آمارهای جزئی -statsPageDetailedAllPages=همه -statsPageDetailedBehindTheScenePage=پشتصحنه -statsPageOverview=نمای کلی -statsPageRequests=درخواستها -statsPageAllowed=مجاز -statsPageBlocked=مسدود شده -statsPageAll=همه -statsPagePages=صفحات -statsPageCookies=کوکیها -statsPageCSS=CSS -statsPageImages=تصاویر -statsPagePlugins=افزونهها -statsPageScripts=اسکریپتها -statsPageXHRs=XHRها -statsPageFrames=فریمها -statsPageOthers=ساير -statsPageDetailed=Logger -statsPageLogSizePrompt1=به یاد سپردن آخرین -statsPageLogSizePrompt2=درخواستهای HTTP <b>در هر صفحه</b>. -statsPageLogSizeHelp=<p>You can inspect details of the most recent raw HTTP requests which have been made by a web page (see below).</p><p>This is mostly useful to advanced users who want to investigate exactly what a web page has been doing. But logging these HTTP requests requires memory, and if you don't care about this technical information, then memory is being wasted.</p><p>Hence this field which lets you adjust the maximum number of the most recent HTTP requests which are to be logged for further inspection.</p><p>Enter “<code>0</code>” to turn off detailed logging (and consequently reduce the memory footprint of <i>ηMatrix</i>).</p> -statsPageRefresh=تازهسازی -settingsPageTitle=ηMatrix – Settings -settingsMatrixDisplayHeader=ظاهر -settingsMatrixDisplayTextSizePrompt=اندازه متن: -settingsMatrixDisplayTextSizeNormal=عادی -settingsMatrixDisplayTextSizeLarge=بزرگ -settingsMatrixDisplayColorBlind=Color-blind friendly -settingsMatrixConvenienceHeader=راحتی -settingsDefaultScopeLevel=Default scope level: -settingsDefaultScopeLevel0=Global -settingsDefaultScopeLevel1=Domain -settingsDefaultScopeLevel2=Site -settingsMatrixAutoReloadPrompt=وقتی ماتریس بسته شد، تبها را هوشمندانه دوباره بارگذاری کن: -settingsMatrixAutoReloadNone=هیچکدام -settingsMatrixAutoReloadCurrent=کنونی -settingsMatrixAutoReloadAll=همه -settingsMatrixAutoReloadInfo=Whenever you make changes in the matrix which can affect the display and/or behavior of one or more pages, <i>ηMatrix</i> will reload affected pages automatically when you close the matrix. -settingsSubframeColor=Blocked frames: Color -settingsSubframeOpacity=وضوح -settingsIconBadgeEnabled=Show the number of blocked requests on the icon -settingsCollapseBlocked=Collapse placeholder of blocked elements -settingsCollapseBlacklisted=Collapse placeholder of blacklisted elements -settingsNoscriptTagsSpoofed=Spoof <code><noscript></code> tags when 1st-party scripts are blocked -settingsCloudStorageEnabled=Enable cloud storage support -privacyPageTitle=ηMatrix – Privacy -privacyDeleteBlockedCookiesPrompt=Delete blocked cookies. -privacyDeleteBlockedCookiesHelp=<p>Blacklisted cookies are not prevented by <i>ηMatrix</i> from entering your browser. However they are prevented from leaving your browser, which is what really matters. Not blocking cookies before they enter your browser gives you the opportunity to be informed that a site tried to use cookies, and furthermore to inspect their contents if you wish.</p><p>Once these blacklisted cookies have been accounted for by <i>ηMatrix</i>, they can be removed from your browser if you wish so.</p><p><b>Important note:</b> Extensions can make web requests during the course of their normal operation. These requests can result in cookies being created in the browser. If the hostname from where a cookie originate is not whitelisted, the cookie will be removed from the browser by <i>ηMatrix</i> if this option is checked. So be sure that the hostname(s) with which an extension communicate is whitelisted.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Delete non-blocked session cookies -privacyDeleteNonBlockedSessionCookiesPrompt2= minutes after the last time they have been used. -privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “A session cookie ... is erased when you end the browser session. The session cookie is stored in temporary memory and is not retained after the browser is closed.”</p><p>Except that this <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>might not be happening</a> in some browsers. Also, to some, having to close the browser in order for the session cookies to clear might not be early enough.</p> -privacyDeleteBlockedLocalStoragePrompt=Delete <a href='https://en.wikipedia.org/wiki/Web_storage'>local storage</a> content set by blocked hostnames -privacyDeleteBlockedLocalStorageHelp=برایانجام -privacyClearCachePrompt1=پاکنمودن کش مرورگر هر -privacyClearCachePrompt2=دقیقه. -privacyClearCacheHelp=<p>Some web sites are really bent on tracking you, so much that they will use not-so-nice tricks to work around whatever measures you take in order to not be tracked.</p><p>A few of these tricks rely<sup>[1, 2]</sup> on the <a href='https://en.wikipedia.org/wiki/Web_cache'>browser cache</a>, which content is often long lasting since rarely will users take the time to regularly clear their browser cache.</p><p>There is little inconvenience to clear the browser cache regularly (likelihood is that you won't notice when it happens), and the benefit is to prevent these obnoxious trackers from invading your privacy.</p><p>Check this option to have <i>ηMatrix</i> do it for you, at the interval you wish.</p><p>[1] <a href='https://grepular.com/Preventing_Web_Tracking_via_the_Browser_Cache'>“Preventing Web Tracking via the Browser Cache”</a>\n[2] <a href='http://lucb1e.com/rp/cookielesscookies/'>“Cookieless cookies”</a></p> -privacyProcessRefererPrompt=Spoof <a href='https://en.wikipedia.org/wiki/HTTP_referer'>HTTP referrer</a> string of third-party requests. -privacyProcessRefererHelp=From Wikipedia:<blockquote>HTTP referer is an HTTP header field that identifies the address of the webpage that linked to the resource being requested. ... <b>Because referer information can violate privacy, some web browsers allow the user to disable the sending of referer information.</b></blockquote>If this setting is checked, <i>ηMatrix</i> will spoof the HTTP referrer information if the domain name of the HTTP referrer is third-party to the domain name of net request. -privacyNoMixedContentPrompt=Strict HTTPS: forbid mixed content. -privacyNoMixedContentHelp=<p>From <a href='https://developer.mozilla.org/en-US/docs/Security/MixedContent'>Mozilla Developer Network</a>:</p><blockquote>If [a] HTTPS page includes content retrieved through regular, cleartext HTTP, then the connection is only partially encrypted: the unencrypted content is accessible to sniffers and can be modified by man-in-the-middle attackers, and therefore the connection is not safeguarded anymore. When a webpage exhibits this behavior, it is called a mixed content page.</blockquote> -privacyProcessHyperlinkAuditingPrompt=Block all <a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>hyperlink auditing</a> attempts. -privacyProcessHyperlinkAuditingHelp=<p>Hyperlink auditing is a mechanism which allow a party, <b>any party</b>, to be informed about which link a user clicked on a particular web page. It is essentially a tracking feature: it allows a web site, or any third-party to that web site, to be informed about which link you clicked on which one of its web pages. The sole purpose is to track your browsing activity.</p> -userRulesPermanentHeader=قوانین دائم -userRulesTemporaryHeader=قوانین موقت -userRulesRevert=بازگرداندن -userRulesCommit=انجامدادن -userRulesEdit=ويرايش -userRulesEditSave=ذخيره -userRulesEditDicard=صرفنظر -userRulesImport=واردکردن از فایل... -userRulesExport=ذخیره در فایل... -userRulesFormatHint=See this page for rule syntax. -userRulesDefaultFileName=my-ematrix-rules.txt -hostsFilesPrompt=All hostnames in a hosts file are loaded as blacklisted hostnames in the global scope. -hostsFilesStats={{blockedHostnameCount}} distinct blocked hostnames from: -hostsFilesPerFileStats={{used}} used out of {{total}} -hostsFilesLastUpdate=Last update: {{ago}} -hostsFilesApplyChanges=اعمال تغییرات -hostsFilesAutoUpdatePrompt=Auto-update hosts files. -hostsFilesUpdateNow=اکنون بهروزآوری شود -hostsFilesPurgeAll=Purge all caches -hostsFilesExternalListsHint=One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored. -hostsFilesExternalListsParse=تجزیهکردن -hostsFilesExternalListPurge=purge cache -hostsFilesExternalListNew=new version available -hostsFilesExternalListObsolete=منسوخ -rawSettingsWarning=Warning! Change these raw configuration settings at your own risk. -aboutChangelog=Change log -aboutStorageUsed=Storage used: {{storageUsed}} bytes -aboutDoc=Documentation -aboutPermissions=Permissions -aboutCode=Source code (GPLv3) -aboutIssues=مشکلات و مسائل -aboutContributors=مشارکت کنندهها -aboutCodeContributors=کد: -aboutIssueContributors=مسائل: -aboutTranslationContributors=ترجمهها: -aboutUserDataHeader=دادهی شما -aboutBackupButton=پشتیبانگیری در فایل... -aboutBackupFilename=پشتیبان-ematrix-من.txt -aboutRestoreButton=بازگرداندن از فایل... -aboutRestoreConfirm=All your settings will be overwritten using data backed up on {{time}}, and ηMatrix will restart.\n\nOverwrite all existing settings using backed up data? -aboutRestoreError=The data could not be read or is invalid -aboutOr=... یا ... -aboutResetButton=بازگشت به تنظیمات پیشفرض -aboutResetConfirm=هشدار! این عمل تمام تنظیمات سفارشی شما را از بین میبرد. آیا از انجام آن مطمئن هستید؟ -loggerFilterInputPlaceholder=filter expression(s) -loggerMaxEntriesTip=بیشترین تعداد ورودیها -loggerEntryCookieDeleted=کوکی پاکشده: {{value}} -loggerEntryDeleteCookieError=failed to delete cookie: {{value}} -loggerEntryBrowserCacheCleared=کش مروگر پاک شد -loggerEntryAssetUpdated=asset updated: {{value}} -mainBlockedPrompt1=ηMatrix has prevented the following page from loading: -mainBlockedPrompt2=به خاطر قانون زیر -mainBlockedBack=برگرد -mainBlockedClose=بستن -commandRevertAll=بازگرداندن همهی تغییرات موقتی -commandWhitelistPageDomain=Temporarily whitelist page domain -commandWhitelistAll=Temporarily whitelist all -commandOpenDashboard=بازکردن داشبورد -elapsedOneMinuteAgo=یک دقیقه پیش -elapsedManyMinutesAgo={{value}} دقیقه پیش -elapsedOneHourAgo=یک ساعت پیش -elapsedManyHoursAgo={{value}} ساعت پیش -elapsedOneDayAgo=یک روز پیش -elapsedManyDaysAgo={{value}} روز پیش -showDashboardButton=داشبورد -showLoggerButton=Logger -cloudPush=دخیره در فضای ابری -cloudPull=گرفتن از فضای ابری -cloudNoData=... ... -cloudDeviceNamePrompt=نام دستگاه: -genericSubmit=ثبتکردن -genericRevert=بازگرداندن -errorCantConnectTo=Network error: Unable to connect to {{url}} -genericApplyChanges=Apply changes -noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can display some content by using the <noscript> tag. For example, some websites will redirect users to a “scriptless” version.</p><p>When ηMatrix blocks scripts, the browser will still advertise itself as supporting script execution unless this option is selected.</p><p>When selected, ηMatrix will tell the website that the browser does not support scripts, which is what you definitely want to do if you are blocking 1st-party scripts. As such, the <noscript> tag will work as intended.</p><p>Not selecting this option when 1st-party scripts are blocked means the website will break misteryously in case it is meant to redirect to a scriptless version.</p> -settingsUpdateIcon=Do not change the toolbar icon -updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> -resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> diff --git a/locale/fi/messages.properties b/locale/fi/messages.properties deleted file mode 100644 index c83bc3e..0000000 --- a/locale/fi/messages.properties +++ /dev/null @@ -1,186 +0,0 @@ -extName=ηMatrix -dashboardPageName=ηMatrix — Hallintapaneeli -loggerPageName=ηMatrix — Logger -settingsPageName=Asetukset -privacyPageName=Yksityisyys -statsPageName=Tilastot -userRulesPageName=Omat säännöt -ubiquitousRulesPageName=Host tiedostot -rawSettingsPageName=More -aboutPageName=Tietoja -allPrettyName=kaikki -cookiePrettyName=keksi -cssPrettyName=css -imagePrettyName=kuva -mediaPrettyName=A/V-media -pluginPrettyName=lisäosa -scriptPrettyName=komentosarja -xhrPrettyName=XHR -framePrettyName=kehys -otherPrettyName=muut -matrixNoNetTrafficPrompt=Ei dataliikennettä havaittu tällä välilehdellä vielä. -matrixMtxButtonTip=Poista käytöstä/ota käyttöön matrix suodatus tälle alueelle. -matrixPersistButtonTip=Tallenna kaikki väliaikaiset muutokset tälle alueelle. -matrixRevertButtonTip=Palauta tilapäiset muutoksia tälle alueelle. -matrixReloadButton=Lataa sivu uudelleen. -matrixScopeTip=Change to global scope. -matrixSwitchesTip=Dropdown menu with additional settings. -matrix1stPartyLabel=1. osapuoli -matrixBlacklistedHostnames={{count}} mustalistatut isäntänimet -matrixSwitchNoMixedContent=Tiukka HTTPS -matrixSwitchNoWorker=Forbid web workers -matrixSwitchReferrerSpoof=Spoof <code>Referer</code> header -matrixSwitchNoscriptSpoof=Spoof <code><noscript></code> tags -matrixRevertAllEntry=Kumoa kaikki väliaikaiset muutokset -matrixLoggerMenuEntry=Siirry lokiin -matrixDashboardMenuEntry=Siirry hallintapaneeliin -matrixNoTabFound=No web page found -statsPageTitle=ηMatrix – Tilastot -statsPageGenericStats=Yleiset tilastot -statsPageCookieHeadersFoiled=<a href='https://en.wikipedia.org/wiki/HTTP_cookie'>HTTP cookie</a> headers foiled: {{count}} -statsPageRefererHeadersFoiled=<a href='https://en.wikipedia.org/wiki/HTTP_referer'>HTTP referer</a> headers foiled: {{count}} -statsPageHyperlinkAuditingFoiled=<a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>Hyperlink auditing</a> attempts foiled: {{count}} -statsPageCookiesRemoved=Local cookies removed: {{count}} -statsPageLocalStoragesCleared=<a href='http://diveintohtml5.info/storage.html'>Local storages</a> emptied: {{count}} -statsPageBrowserCacheCleared=Browser caches cleared: {{count}} -statsPageDetailedStats=Yksityiskohtaiset tilastot -statsPageDetailedAllPages=Kaikki -statsPageDetailedBehindTheScenePage=Behind the scene -statsPageOverview=Yhteenveto -statsPageRequests=Pyynnöt -statsPageAllowed=Sallittu -statsPageBlocked=Estetty -statsPageAll=Kaikki -statsPagePages=Sivut -statsPageCookies=Evästeet -statsPageCSS=CSS -statsPageImages=Kuvat -statsPagePlugins=Laajennukset -statsPageScripts=Komentosarjat -statsPageXHRs=XHRs -statsPageFrames=Kehykset -statsPageOthers=Muut -statsPageDetailed=Logger -statsPageLogSizePrompt1=Muista viimeiset -statsPageLogSizePrompt2=HTTP pyyntöä <b>sivua kohden</b>. -statsPageLogSizeHelp=<p>You can inspect details of the most recent raw HTTP requests which have been made by a web page (see below).</p><p>This is mostly useful to advanced users who want to investigate exactly what a web page has been doing. But logging these HTTP requests requires memory, and if you don't care about this technical information, then memory is being wasted.</p><p>Hence this field which lets you adjust the maximum number of the most recent HTTP requests which are to be logged for further inspection.</p><p>Enter “<code>0</code>” to turn off detailed logging (and consequently reduce the memory footprint of <i>ηMatrix</i>).</p> -statsPageRefresh=Päivitä -settingsPageTitle=ηMatrix – Settings -settingsMatrixDisplayHeader=Ulkoasu -settingsMatrixDisplayTextSizePrompt=Tekstikoko: -settingsMatrixDisplayTextSizeNormal=Normaali -settingsMatrixDisplayTextSizeLarge=Suuri -settingsMatrixDisplayColorBlind=Color-blind friendly -settingsMatrixConvenienceHeader=Convenience -settingsDefaultScopeLevel=Default scope level: -settingsDefaultScopeLevel0=Global -settingsDefaultScopeLevel1=Domain -settingsDefaultScopeLevel2=Site -settingsMatrixAutoReloadPrompt=When the matrix is closed, smart reload these tabs: -settingsMatrixAutoReloadNone=Ei mitään -settingsMatrixAutoReloadCurrent=Nykyinen -settingsMatrixAutoReloadAll=Kaikki -settingsMatrixAutoReloadInfo=Whenever you make changes in the matrix which can affect the display and/or behavior of one or more pages, <i>ηMatrix</i> will reload affected pages automatically when you close the matrix. -settingsSubframeColor=Blocked frames: Color -settingsSubframeOpacity=Läpinäkyvyys -settingsIconBadgeEnabled=Show the number of blocked requests on the icon -settingsCollapseBlocked=Collapse placeholder of blocked elements -settingsCollapseBlacklisted=Collapse placeholder of blacklisted elements -settingsNoscriptTagsSpoofed=Spoof <code><noscript></code> tags when 1st-party scripts are blocked -settingsCloudStorageEnabled=Enable cloud storage support -privacyPageTitle=ηMatrix – Privacy -privacyDeleteBlockedCookiesPrompt=Delete blocked cookies. -privacyDeleteBlockedCookiesHelp=<p>Blacklisted cookies are not prevented by <i>ηMatrix</i> from entering your browser. However they are prevented from leaving your browser, which is what really matters. Not blocking cookies before they enter your browser gives you the opportunity to be informed that a site tried to use cookies, and furthermore to inspect their contents if you wish.</p><p>Once these blacklisted cookies have been accounted for by <i>ηMatrix</i>, they can be removed from your browser if you wish so.</p><p><b>Important note:</b> Extensions can make web requests during the course of their normal operation. These requests can result in cookies being created in the browser. If the hostname from where a cookie originate is not whitelisted, the cookie will be removed from the browser by <i>ηMatrix</i> if this option is checked. So be sure that the hostname(s) with which an extension communicate is whitelisted.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Delete non-blocked session cookies -privacyDeleteNonBlockedSessionCookiesPrompt2= minutes after the last time they have been used. -privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “A session cookie ... is erased when you end the browser session. The session cookie is stored in temporary memory and is not retained after the browser is closed.”</p><p>Except that this <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>might not be happening</a> in some browsers. Also, to some, having to close the browser in order for the session cookies to clear might not be early enough.</p> -privacyDeleteBlockedLocalStoragePrompt=Delete <a href='https://en.wikipedia.org/wiki/Web_storage'>local storage</a> content set by blocked hostnames -privacyDeleteBlockedLocalStorageHelp=TODO -privacyClearCachePrompt1=Clear browser cache every -privacyClearCachePrompt2=minutes. -privacyClearCacheHelp=<p>Some web sites are really bent on tracking you, so much that they will use not-so-nice tricks to work around whatever measures you take in order to not be tracked.</p><p>A few of these tricks rely<sup>[1, 2]</sup> on the <a href='https://en.wikipedia.org/wiki/Web_cache'>browser cache</a>, which content is often long lasting since rarely will users take the time to regularly clear their browser cache.</p><p>There is little inconvenience to clear the browser cache regularly (likelihood is that you won't notice when it happens), and the benefit is to prevent these obnoxious trackers from invading your privacy.</p><p>Check this option to have <i>ηMatrix</i> do it for you, at the interval you wish.</p><p>[1] <a href='https://grepular.com/Preventing_Web_Tracking_via_the_Browser_Cache'>“Preventing Web Tracking via the Browser Cache”</a>\n[2] <a href='http://lucb1e.com/rp/cookielesscookies/'>“Cookieless cookies”</a></p> -privacyProcessRefererPrompt=Spoof <a href='https://en.wikipedia.org/wiki/HTTP_referer'>HTTP referrer</a> string of third-party requests. -privacyProcessRefererHelp=From Wikipedia:<blockquote>HTTP referer is an HTTP header field that identifies the address of the webpage that linked to the resource being requested. ... <b>Because referer information can violate privacy, some web browsers allow the user to disable the sending of referer information.</b></blockquote>If this setting is checked, <i>ηMatrix</i> will spoof the HTTP referrer information if the domain name of the HTTP referrer is third-party to the domain name of net request. -privacyNoMixedContentPrompt=Strict HTTPS: forbid mixed content. -privacyNoMixedContentHelp=<p>From <a href='https://developer.mozilla.org/en-US/docs/Security/MixedContent'>Mozilla Developer Network</a>:</p><blockquote>If [a] HTTPS page includes content retrieved through regular, cleartext HTTP, then the connection is only partially encrypted: the unencrypted content is accessible to sniffers and can be modified by man-in-the-middle attackers, and therefore the connection is not safeguarded anymore. When a webpage exhibits this behavior, it is called a mixed content page.</blockquote> -privacyProcessHyperlinkAuditingPrompt=Block all <a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>hyperlink auditing</a> attempts. -privacyProcessHyperlinkAuditingHelp=<p>Hyperlink auditing is a mechanism which allow a party, <b>any party</b>, to be informed about which link a user clicked on a particular web page. It is essentially a tracking feature: it allows a web site, or any third-party to that web site, to be informed about which link you clicked on which one of its web pages. The sole purpose is to track your browsing activity.</p> -userRulesPermanentHeader=Permanent rules -userRulesTemporaryHeader=Temporary rules -userRulesRevert=Revert -userRulesCommit=Commit -userRulesEdit=Muokkaa -userRulesEditSave=Tallenna -userRulesEditDicard=Hylkää -userRulesImport=Tuo tiedostosta... -userRulesExport=Vie tiedostoon... -userRulesFormatHint=See this page for rule syntax. -userRulesDefaultFileName=my-ematrix-rules.txt -hostsFilesPrompt=All hostnames in a hosts file are loaded as blacklisted hostnames in the global scope. -hostsFilesStats={{blockedHostnameCount}} distinct blocked hostnames from: -hostsFilesPerFileStats={{used}} used out of {{total}} -hostsFilesLastUpdate=Last update: {{ago}} -hostsFilesApplyChanges=Käytä muutoksia -hostsFilesAutoUpdatePrompt=Auto-update hosts files. -hostsFilesUpdateNow=Päivitä nyt -hostsFilesPurgeAll=Purge all caches -hostsFilesExternalListsHint=One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored. -hostsFilesExternalListsParse=Parsi -hostsFilesExternalListPurge=purge cache -hostsFilesExternalListNew=uusi versio saatavilla -hostsFilesExternalListObsolete=outdated -rawSettingsWarning=Warning! Change these raw configuration settings at your own risk. -aboutChangelog=Change log -aboutStorageUsed=Storage used: {{storageUsed}} bytes -aboutDoc=Documentation -aboutPermissions=Permissions -aboutCode=Lähdekoodi (GPLv3) -aboutIssues=Bugit ja ongelmat -aboutContributors=Kehittäjät ja avustajat -aboutCodeContributors=Koodi: -aboutIssueContributors=Ongelmat: -aboutTranslationContributors=Käännökset: -aboutUserDataHeader=Tietosi -aboutBackupButton=Varmuuskopioi tiedostoon... -aboutBackupFilename=my-ematrix-backup.txt -aboutRestoreButton=Palauta tiedostosta... -aboutRestoreConfirm=All your settings will be overwritten using data backed up on {{time}}, and ηMatrix will restart.\n\nOverwrite all existing settings using backed up data? -aboutRestoreError=The data could not be read or is invalid -aboutOr=... or ... -aboutResetButton=Reset to default settings -aboutResetConfirm=Caution! this will remove all your custom settings. Are you sure you want to proceed? -loggerFilterInputPlaceholder=filter expression(s) -loggerMaxEntriesTip=Maximum number of entries -loggerEntryCookieDeleted=cookie deleted: {{value}} -loggerEntryDeleteCookieError=failed to delete cookie: {{value}} -loggerEntryBrowserCacheCleared=browser cache cleared -loggerEntryAssetUpdated=asset updated: {{value}} -mainBlockedPrompt1=ηMatrix has prevented the following page from loading: -mainBlockedPrompt2=Because of the following rule -mainBlockedBack=Palaa -mainBlockedClose=Close -commandRevertAll=Revert all temporary changes -commandWhitelistPageDomain=Temporarily whitelist page domain -commandWhitelistAll=Temporarily whitelist all -commandOpenDashboard=Open dashboard -elapsedOneMinuteAgo=a minute ago -elapsedManyMinutesAgo={{value}} minutes ago -elapsedOneHourAgo=an hour ago -elapsedManyHoursAgo={{value}} hours ago -elapsedOneDayAgo=a day ago -elapsedManyDaysAgo={{value}} days ago -showDashboardButton=Dashboard -showLoggerButton=Logger -cloudPush=Export to cloud storage -cloudPull=Import from cloud storage -cloudNoData=...\n... -cloudDeviceNamePrompt=This device name: -genericSubmit=Submit -genericRevert=Revert -errorCantConnectTo=Network error: Unable to connect to {{url}} -genericApplyChanges=Apply changes -noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can display some content by using the <noscript> tag. For example, some websites will redirect users to a “scriptless” version.</p><p>When ηMatrix blocks scripts, the browser will still advertise itself as supporting script execution unless this option is selected.</p><p>When selected, ηMatrix will tell the website that the browser does not support scripts, which is what you definitely want to do if you are blocking 1st-party scripts. As such, the <noscript> tag will work as intended.</p><p>Not selecting this option when 1st-party scripts are blocked means the website will break misteryously in case it is meant to redirect to a scriptless version.</p> -settingsUpdateIcon=Do not change the toolbar icon -updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> -resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> diff --git a/locale/fil/messages.properties b/locale/fil/messages.properties deleted file mode 100644 index 05be29d..0000000 --- a/locale/fil/messages.properties +++ /dev/null @@ -1,186 +0,0 @@ -extName=ηMatrix -dashboardPageName=ηMatrix — Dashboard -loggerPageName=ηMatrix — Logger -settingsPageName=Mga Setting -privacyPageName=Privacy -statsPageName=Istatistika -userRulesPageName=Ang aking mga panuntunan -ubiquitousRulesPageName=Mga host file -rawSettingsPageName=More -aboutPageName=Tungkol sa -allPrettyName=lahat -cookiePrettyName=cookie -cssPrettyName=css -imagePrettyName=larawan -mediaPrettyName=media -pluginPrettyName=plugin -scriptPrettyName=script -xhrPrettyName=XHR -framePrettyName=frame -otherPrettyName=iba pa -matrixNoNetTrafficPrompt=Walang nakikitang trapiko sa net para sa tab na ito sa ngayon. -matrixMtxButtonTip=Huwag paganahin / paganahin ang pag-filter ng matris para sa saklaw na ito. -matrixPersistButtonTip=I-save ang lahat ng mga pansamantalang pagbabago para sa saklaw na ito. -matrixRevertButtonTip=Ibalik ang mga pansamantalang pagbabago para sa saklaw na ito. -matrixReloadButton=I-reload ang pahina.\nPindutin ang Shift upang lampasan ang cache ng browser. -matrixScopeTip=Change to global scope. -matrixSwitchesTip=Dropdown menu with additional settings. -matrix1stPartyLabel=1st-party -matrixBlacklistedHostnames={{count}} naka-blacklist na hostname (s) -matrixSwitchNoMixedContent=Ipagbawal ang halo-halong nilalaman -matrixSwitchNoWorker=Ipagbawal ang mga web workers -matrixSwitchReferrerSpoof=Spoof <code>Referer</code> header -matrixSwitchNoscriptSpoof=Spoof <code><noscript></code> tags -matrixRevertAllEntry=Ibalik ang lahat ng mga pansamantalang pagbabago -matrixLoggerMenuEntry=Pumunta sa logger -matrixDashboardMenuEntry=Pumunta sa dashboard -matrixNoTabFound=Walang nakitang pahina ng web -statsPageTitle=ηMatrix – Istatistika -statsPageGenericStats=Generic na istatistika -statsPageCookieHeadersFoiled=<a href='https://en.wikipedia.org/wiki/HTTP_cookie'>HTTP cookie</a> headers foiled: {{count}} -statsPageRefererHeadersFoiled=<a href='https://en.wikipedia.org/wiki/HTTP_referer'>HTTP referer</a> hinabol ang mga header: {{count}} -statsPageHyperlinkAuditingFoiled=<a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>Hyperlink auditing</a> ang mga pagtatangka ay napawalang-saysay:{{count}} -statsPageCookiesRemoved=Inalis na mga lokal na cookies: {{count}} -statsPageLocalStoragesCleared=<a href = 'http: //diveintohtml5.info/storage.html'> Mga lokal na storage </a> ay walang laman: {{count}} -statsPageBrowserCacheCleared=Naka-clear ang mga cache ng browser: {{count}} -statsPageDetailedStats=Detalyadong istatistika -statsPageDetailedAllPages=Lahat -statsPageDetailedBehindTheScenePage=Sa likod ng mga eksena -statsPageOverview=Pangkalahatang-ideya -statsPageRequests=Mga Hiling -statsPageAllowed=Pinayagan -statsPageBlocked=Naka-block -statsPageAll=Lahat -statsPagePages=Mga Pahina -statsPageCookies=Cookies -statsPageCSS=CSS -statsPageImages=Mga Larawan -statsPagePlugins=Mga Plugin -statsPageScripts=Mga Script -statsPageXHRs=Mga XHR -statsPageFrames=Mga Frame -statsPageOthers=Iba pa -statsPageDetailed=Logger -statsPageLogSizePrompt1=Tandaan ang huli -statsPageLogSizePrompt2=Hinihiling ng HTTP sa <b> bawat pahina </ b>. -statsPageLogSizeHelp=<p> Maaari mong siyasatin ang mga detalye ng pinakahuling mga kahilingan sa HTTP na ginawa ng isang web page (tingnan sa ibaba). </p> <p> Ito ay kapaki-pakinabang sa mga advanced na user na nais mag-imbestiga nang eksakto kung ano ang ginagawa ng isang web page. Ngunit ang pag-log ng mga kahilingan sa HTTP ay nangangailangan ng memorya, at kung hindi mo pinapahalagahan ang tungkol sa teknikal na impormasyon, pagkatapos ay ang memory ay nasayang. </p> <p> Samakatuwid ang patlang na ito na nagpapahintulot sa iyo na ayusin ang maximum na bilang ng mga pinakahuling mga kahilingan sa HTTP ay dapat ma-log para sa karagdagang inspeksyon. </p> <p> Ipasok ang “ <code> 0 </code> ” upang patayin ang detalyadong pag-log (at dahil dito ay bawasan ang memory footprint ng <i> ηMatrix </i>). </p> -statsPageRefresh=Refresh -settingsPageTitle=ηMatrix – Settings -settingsMatrixDisplayHeader=Matrix -settingsMatrixDisplayTextSizePrompt=Laki ng teksto: -settingsMatrixDisplayTextSizeNormal=Normal -settingsMatrixDisplayTextSizeLarge=Malaki -settingsMatrixDisplayColorBlind=Color-blind friendly -settingsMatrixConvenienceHeader=Kaginhawaan -settingsDefaultScopeLevel=Pangunahing antas ng saklaw: -settingsDefaultScopeLevel0=Global -settingsDefaultScopeLevel1=Domain -settingsDefaultScopeLevel2=Site -settingsMatrixAutoReloadPrompt=Kapag isinara ang matrix, ang smart na i-reload ang mga tab na ito: -settingsMatrixAutoReloadNone=Wala -settingsMatrixAutoReloadCurrent=Kasalukuyan -settingsMatrixAutoReloadAll=Lahat -settingsMatrixAutoReloadInfo=Sa tuwing gumawa ka ng mga pagbabago sa matrix na maaaring makaapekto sa display at / o pag-uugali ng isa o higit pang mga pahina, awtomatikong i-reload ng <i>ηMatrix</i> ang mga apektadong pahina kapag isinara mo ang matris. -settingsSubframeColor=Blocked frames: Kulay -settingsSubframeOpacity=Opacity -settingsIconBadgeEnabled=Show the number of blocked requests on the icon -settingsCollapseBlocked=I-collapse ang mga placeholder ng mga naka-block na elemento -settingsCollapseBlacklisted=I-collapse ang mga placeholder ng mga naka-blacklist na elemento -settingsNoscriptTagsSpoofed=Spoof <code><noscript></code> na mga tag kapag naka-block ang mga script ng 1st-party -settingsCloudStorageEnabled=Paganahin ang suporta sa cloud storage -privacyPageTitle=ηMatrix – Privacy -privacyDeleteBlockedCookiesPrompt=Tanggalin ang naka-block na cookies. -privacyDeleteBlockedCookiesHelp=<p> Ang mga blacklist na cookies ay hindi napigilan ng <i>ηMatrix</i> mula sa pagpasok ng iyong browser. Gayunpaman, pinigilan sila sa pag-alis ng iyong browser, na kung saan ay talagang mahalaga. Ang hindi pagharang ng mga cookies bago sila ipasok ang iyong browser ay nagbibigay sa iyo ng pagkakataong maabisuhan na sinubukan ng isang site na gumamit ng mga cookies, at higit pa upang siyasatin ang mga nilalaman nito kung nais mo. </p><p> Kapag ang mga naka-blacklist na cookies ay na-accounted sa pamamagitan ng <i>ηMatrix</i>, maaari silang alisin mula sa iyong browser kung nais mo. </p><p><b>Mahalagang paalala: </b> Maaaring gawing mga extension ang mga kahilingan sa web sa panahon ng kanilang normal na operasyon. Ang mga kahilingan na ito ay maaaring magresulta sa mga cookies na nilikha sa browser. Kung ang hostname mula sa kung saan ang isang cookie na nagmula ay hindi whitelisted, ang cookie ay aalisin mula sa browser sa pamamagitan ng <i> ηMatrix </i> kung naka-check ang opsyong ito. Kaya siguraduhin na ang (mga) host na kung saan ang isang extension na nakikipag-ugnay ay whitelisted. </p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Tanggalin ang mga hindi naka-block na cookies ng session -privacyDeleteNonBlockedSessionCookiesPrompt2= ilang minuto pagkatapos ng huling pagkakataon na ginamit na ang mga ito. -privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “Ang session cookie ... ay mabubura kapag tinapos mo ang session ng browser. Ang session cookie ay naka-imbak sa pansamantalang memorya at hindi mananatili pagkatapos na sarado ang browser.”</p><p>Maliban na ito <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>maaaring hindi nangyayari</a>sa ilang mga browser. Gayundin, sa ilang, ang pagkakaroon ng pagsara sa browser upang ang mga cookies ng cookies ay maaring hindi maaaring maagang maaga.</p> -privacyDeleteBlockedLocalStoragePrompt=Tanggalin ang nilalamang <a href='https://en.wikipedia.org/wiki/Web_storage'> lokal na imbakan </a> na itinakda ng mga naka-block na mga hostname -privacyDeleteBlockedLocalStorageHelp=GAGAWIN -privacyClearCachePrompt1=I-clear ang cache ng browser bawat -privacyClearCachePrompt2=minuto. -privacyClearCacheHelp=<p>Ang ilang mga web site ay tunay na baluktot sa pagsubaybay sa iyo, kaya magkano na sila ay gumamit ng hindi-magandang-trick upang gumana sa paligid ng anumang mga panukala mong gawin upang hindi masubaybayan.</p><p>Ang ilan sa mga trick na ito ay umaasa<sup>[1, 2]</sup> sa <a href='https://en.wikipedia.org/wiki/Web_cache'>browser cache</a>, kung aling nilalaman ay madalas na matagal na dahil hindi gaanong magagawa ng mga gumagamit ang oras upang regular na i-clear ang cache ng kanilang browser.</p><p>May kaunting abala na regular na i-clear ang cache ng browser (posibilidad na hindi mo mapansin kapag nangyari ito), at ang benepisyo ay upang maiwasan ang mga kasuklam-suklam na tagasubaybay mula sa pagsalakay sa iyong privacy.</p><p>Suriin ang opsyong ito upang magkaroon ng <i> ηMatrix </i> gawin ito para sa iyo, sa pagitan na nais mo.</p><p>[1] <a href='https://grepular.com/Preventing_Web_Tracking_via_the_Browser_Cache'>“Ppag-iwas sa Pagsubaybay sa Web sa pamamagitan ng Cache Browser”</a>\n[2] <a href='http://lucb1e.com/rp/cookielesscookies/'>“Cookieless cookies”</a></p> -privacyProcessRefererPrompt=Spoof <a href='https://en.wikipedia.org/wiki/HTTP_referer'> HTTP referrer </a> string ng mga kahilingan ng third-party. -privacyProcessRefererHelp=Mula sa Wikipedia:<blockquote> Ang HTTP referer ay isang header ng HTTP na nagpapakilala sa address ng webpage na naka-link sa mapagkukunan na hiniling. ...<b>Dahil ang impormasyon ng referer ay maaaring lumalabag sa privacy, pinapayagan ng ilang mga browser ng web ang gumagamit na huwag paganahin ang pagpapadala ng impormasyon ng referer.</b></blockquote>Kung naka-check ang setting na ito,<i>ηMatrix</i>ay i-spoof ang impormasyon ng HTTP referrer kung ang pangalan ng domain ng HTTP referrer ay third-party sa pangalan ng domain na net request. -privacyNoMixedContentPrompt=Strict HTTPS: pagbawalan ang halo-halong nilalaman. -privacyNoMixedContentHelp=<p>Mula sa <a href='https://developer.mozilla.org/en-US/docs/Security/MixedContent'>Mozilla Developer Network</a>:</p><blockquote>Kung ang [a] pahina ng HTTPS ay kinabibilangan ng nilalaman na nakuha sa pamamagitan ng regular, cleartext HTTP, at pagkatapos ang koneksyon ay bahagyang naka-encrypt lamang: ang hindi naka-encrypt na nilalaman ay naa-access sa mga sniffer at maaaring mabago ng mga man-in-the-middle attackers, at samakatuwid ang koneksyon ay hindi na-safeguarded ngayon. Kapag nagpapakita ang isang webpage ng pag-uugali na ito, ito ay tinatawag na isang halo-halong pahina ng nilalaman.</blockquote> -privacyProcessHyperlinkAuditingPrompt=Harangan ang lahat ng<a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>pag-audit ng hyperlink</a> mga pagtatangka. -privacyProcessHyperlinkAuditingHelp=<p> Ang pag-audit ng hyperlink ay isang mekanismo na nagbibigay-daan sa isang partido, <b> anumang partido </b>, na ipaalam kung anong link ang na-click ng isang user sa isang partikular na web page. Ito ay talagang isang tampok sa pagsubaybay: pinapayagan nito ang isang web site, o anumang ikatlong partido sa web site na iyon, na ipaalam kung aling link ang iyong na-click sa alin sa mga web page nito. Ang tanging layunin ay upang masubaybayan ang iyong aktibidad sa pagba-browse. </p> -userRulesPermanentHeader=Permanenteng panuntunan -userRulesTemporaryHeader=Temporary rules -userRulesRevert=Ibalik -userRulesCommit=Commit -userRulesEdit=I-edit -userRulesEditSave=I-save -userRulesEditDicard=Itapon -userRulesImport=Mag-import mula sa file... -userRulesExport=I-export upang mag-file... -userRulesFormatHint=Tingnan ang pahinang ito para sa syntax ng panuntunan. -userRulesDefaultFileName=my-ematrix-rules.txt -hostsFilesPrompt=Ang lahat ng mga hostname sa isang nagho-host na file ay nai-load bilang naka-blacklist na mga hostname sa global na saklaw. -hostsFilesStats={{blockedHostnameCount}} naiiba ang nai-block na mga hostname mula sa: -hostsFilesPerFileStats={{used}} na ginamit sa {{total}} -hostsFilesLastUpdate=Huling pag-update: {{ago}} -hostsFilesApplyChanges=Mag-apply ng mga pagbabago -hostsFilesAutoUpdatePrompt=I-auto-update ang mga hosts files. -hostsFilesUpdateNow=I-update ngayon -hostsFilesPurgeAll=Tanggalin ang lahat ng mga cache -hostsFilesExternalListsHint=Isang URL sa bawat linya. Mga prefix na linya na may ‘#’ hindi papansinin. Ang di-wastong mga URL ay tahimik na hindi papansinin. -hostsFilesExternalListsParse=Parse -hostsFilesExternalListPurge=purge cache -hostsFilesExternalListNew=mayroong bagong bersyon -hostsFilesExternalListObsolete=outdated -rawSettingsWarning=Warning! Change these raw configuration settings at your own risk. -aboutChangelog=Change log -aboutStorageUsed=Ginamit ang imbakan: {{storageUsed}} bytes -aboutDoc=Dokumentasyon -aboutPermissions=Mga Pahintulot -aboutCode=Source code (GPLv3) -aboutIssues=Mga bug at mga isyu -aboutContributors=Mga kontribyutor -aboutCodeContributors=Code: -aboutIssueContributors=Mga isyu: -aboutTranslationContributors=Mga Pagsasalin: -aboutUserDataHeader=Ang iyong datos -aboutBackupButton=Backup to file... -aboutBackupFilename=my-ematrix-backup.txt -aboutRestoreButton=Ibalik mula sa file... -aboutRestoreConfirm=Ang lahat ng iyong mga setting ay mapapatungan gamit ang data na naka-back up sa {{time}}, at ηMatrix ay muling simulan.\n\nI-overwrite ang lahat ng umiiral na mga setting gamit ang naka-back up na data? -aboutRestoreError=Ang data ay hindi mabasa o hindi wasto -aboutOr=... o ... -aboutResetButton=I-reset sa mga default na setting -aboutResetConfirm=Mag-ingat! aalisin nito ang lahat ng iyong mga pasadyang setting. Sigurado ka bang gusto mong magpatuloy? -loggerFilterInputPlaceholder=(mga) expression ng filter -loggerMaxEntriesTip=Pinakamataas na bilang ng mga entry -loggerEntryCookieDeleted=tinanggal ang cookie: {{value}} -loggerEntryDeleteCookieError=bigo na tanggalin ang cookie: {{value}} -loggerEntryBrowserCacheCleared=naka-clear ang cache ng browser -loggerEntryAssetUpdated=na-update ang asset: {{value}} -mainBlockedPrompt1=Pinigilan ng ηMatrix ang sumusunod na pahina mula sa paglo-load: -mainBlockedPrompt2=Dahil sa sumusunod na tuntunin -mainBlockedBack=Bumalik -mainBlockedClose=Isara -commandRevertAll=Ibalik ang lahat ng mga pansamantalang pagbabago -commandWhitelistPageDomain=Pansamantalang i-whitelist ang domain ng pahina -commandWhitelistAll=Pansamantalang i-whitelist lahat -commandOpenDashboard=Buksan ang dashboard -elapsedOneMinuteAgo=isang minuto ang nakalipas -elapsedManyMinutesAgo={{value}} mga minuto ang nakalipas -elapsedOneHourAgo=isang oras ang nakalipas -elapsedManyHoursAgo={{value}} mga oras na nakalipas -elapsedOneDayAgo=kahapon -elapsedManyDaysAgo={{value}} mga araw na nakalipas -showDashboardButton=Dashboard -showLoggerButton=Logger -cloudPush=I-export sa cloud storage -cloudPull=Mag-import mula sa cloud storage -cloudNoData=...\n... -cloudDeviceNamePrompt=Ang pangalan ng device na ito: -genericSubmit=Ipasa -genericRevert=Ibalik -errorCantConnectTo=Error sa network: Hindi nakakonekta sa {{url}} -genericApplyChanges=Apply changes -noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can display some content by using the <noscript> tag. For example, some websites will redirect users to a “scriptless” version.</p><p>When ηMatrix blocks scripts, the browser will still advertise itself as supporting script execution unless this option is selected.</p><p>When selected, ηMatrix will tell the website that the browser does not support scripts, which is what you definitely want to do if you are blocking 1st-party scripts. As such, the <noscript> tag will work as intended.</p><p>Not selecting this option when 1st-party scripts are blocked means the website will break misteryously in case it is meant to redirect to a scriptless version.</p> -settingsUpdateIcon=Do not change the toolbar icon -updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> -resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> diff --git a/locale/fr/messages.properties b/locale/fr/messages.properties index d47879c..5b6c25f 100644 --- a/locale/fr/messages.properties +++ b/locale/fr/messages.properties @@ -50,16 +50,16 @@ statsPageOverview=Vue d'ensemble statsPageRequests=Requêtes statsPageAllowed=Autorisées statsPageBlocked=Bloquées -statsPageAll=Tout -statsPagePages=Pages -statsPageCookies=Cookies -statsPageCSS=CSS -statsPageImages=Images -statsPagePlugins=Plugins -statsPageScripts=Scripts -statsPageXHRs=XHRs -statsPageFrames=Frames -statsPageOthers=Autres +statsPageAll=Tout +statsPagePages=Pages +statsPageCookies=Cookies +statsPageCSS=CSS +statsPageImages=Images +statsPagePlugins=Plugins +statsPageScripts=Scripts +statsPageXHRs=XHRs +statsPageFrames=Frames +statsPageOthers=Autres statsPageDetailed=Journal statsPageLogSizePrompt1=Se souvenir des statsPageLogSizePrompt2=plus récentes requêtes HTTP <b>par page</b> @@ -91,7 +91,7 @@ settingsCloudStorageEnabled=Activer le stockage des paramètres dans le nuage privacyPageTitle=ηMatrix – Confidentialité privacyDeleteBlockedCookiesPrompt=Supprimer les cookies bloqués privacyDeleteBlockedCookiesHelp=<p><i>ηMatrix</i> n'empêche pas les cookies bloqués d'entrer dans votre navigateur, mais les empêche d'en repartir, et c'est cela qui importe. Laisser venir les cookies vous permet de savoir lorsqu'un site essaye d'en utiliser, ou même d'en inspecter le contenu si vous le désirez.</p><p>Une fois que les cookies bloqués ont été pris en compte par <i>ηMatrix</i>, ils peuvent être supprimés de votre navigateur si vous le souhaitez.</p><p><b>Note importante</b> : Les extensions peuvent faire des requêtes Web au cours de leurs opérations ordinaires. Ces requêtes peuvent entraîner la création de cookies dans le navigateur. Si cette fonctionnalité est activée et que le nom d'hôte originel du cookie n'est pas sur liste blanche, le cookie sera supprimé du navigateur par <i>ηMatrix</i>, alors assurez-vous que le(s) nom(s) d'hôte(s) avec le(s)quel(s) l'extension interagit soit/soient sur liste blanche.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Supprimer les cookies de session non-bloqués et inutilisés depuis plus de +privacyDeleteNonBlockedSessionCookiesPrompt1=Supprimer les cookies de session non-bloqués et inutilisés depuis plus de privacyDeleteNonBlockedSessionCookiesPrompt2= minutes privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>Définition W3C</a> : “Un cookie de session [...] est effacé quand vous avez terminé la session de navigation. Le cookie de session est stocké dans la mémoire temporaire et n'est pas conservé après la fermeture du navigateur.”</p><p>Sauf que cela <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>peut ne pas se produire</a> sur certains navigateurs. De plus, pour certaines personnes, avoir à fermer le navigateur pour nettoyer les cookies de session peut ne pas se révéler suffisant en terme de confidentialité.</p> privacyDeleteBlockedLocalStoragePrompt=Supprimer les <a href='http://fr.wikipedia.org/wiki/Stockage_web_local'>données locales</a> des noms d'hôtes bloqués @@ -115,7 +115,7 @@ userRulesEditDicard=Annuler userRulesImport=Importer à partir du fichier userRulesExport=Exporter vers un fichier userRulesFormatHint=Consultez cette page Web pour connaître la syntaxe des règles. -userRulesDefaultFileName=mes-regles-ematrix.txt +userRulesDefaultFileName=mes-regles-umatrix.txt hostsFilesPrompt=Tout nom de domaine énuméré dans un des fichiers choisis ci-dessous est bloqué dans le contexte global (*). hostsFilesStats={{blockedHostnameCount}} nom(s) de domaine distinct(s) bloqué(s) depuis : hostsFilesPerFileStats={{used}} utilisé(s) sur un total de {{total}} @@ -124,7 +124,7 @@ hostsFilesApplyChanges=Appliquer les modifications hostsFilesAutoUpdatePrompt=Mettre à jour les fichiers hosts automatiquement hostsFilesUpdateNow=Mettre à jour maintenant hostsFilesPurgeAll=Vider tous les caches -hostsFilesExternalListsHint=Une URL par ligne. Les lignes commençant par ‘#’ seront ignorées. Une URL invalide sera automatiquement ignorée. +hostsFilesExternalListsHint=<p>One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored.</p><p>The inserted URL must point to a hosts file (including local files); do not use the hosts file syntax here.</p> hostsFilesExternalListsParse=Valider hostsFilesExternalListPurge=Vider le cache hostsFilesExternalListNew=Nouvelle version disponible @@ -142,7 +142,7 @@ aboutIssueContributors=Problèmes : aboutTranslationContributors=Traductions : aboutUserDataHeader=Vos données aboutBackupButton=Enregistrer dans un fichier -aboutBackupFilename=mes-donnees-ematrix.txt +aboutBackupFilename=mes-donnees-umatrix.txt aboutRestoreButton=Restaurer depuis un fichier aboutRestoreConfirm=Toutes vos données seront remplacées par celles enregistrées le {{time}}, puis ηMatrix redémarrera.\n\nDésirez-vous vraiment effectuer l'opération ? aboutRestoreError=Les données ne peuvent être lues ou sont invalides @@ -183,4 +183,6 @@ noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can dis settingsUpdateIcon=Do not change the toolbar icon updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +resolveCnameHelp=<p>When resolving an address with DNS, some webistes use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +settingsTextSmaller=Smaller +settingsTextBigger=Bigger diff --git a/locale/he/messages.properties b/locale/he/messages.properties deleted file mode 100644 index 1e6680b..0000000 --- a/locale/he/messages.properties +++ /dev/null @@ -1,186 +0,0 @@ -extName=ηMatrix -dashboardPageName=ηMatrix — פאנל הקונפיגורציות -loggerPageName=ηMatrix — מתעד הבקשות -settingsPageName=הגדרות -privacyPageName=פרטיות -statsPageName=סטטיסטיקות -userRulesPageName=החוקים שלי -ubiquitousRulesPageName=קבצי Hosts -rawSettingsPageName=More -aboutPageName=אודות -allPrettyName=הכל -cookiePrettyName=עוגייה -cssPrettyName=CSS -imagePrettyName=תמונה -mediaPrettyName=מדיה -pluginPrettyName=פלאגין -scriptPrettyName=סקריפט -xhrPrettyName=XHR -framePrettyName=מסגרת -otherPrettyName=אחר -matrixNoNetTrafficPrompt=לא נצפו פעולות רשת בלשונית זו עד לעכשיו. -matrixMtxButtonTip=כבה/אפשר מטריצת פילטור עבור טווח זה. -matrixPersistButtonTip=שמור את כל השינויים הזמניים עבור טווח זה. -matrixRevertButtonTip=מחק שינויים זמניים עבור טווח זה. -matrixReloadButton=טען מחדש את העמוד.\nהחזק את מקש ה Shift על מנת להתעלם מזיכרון מטמון של הדפדפן. -matrixScopeTip=Change to global scope. -matrixSwitchesTip=Dropdown menu with additional settings. -matrix1stPartyLabel=צד ראשון -matrixBlacklistedHostnames={{count}} דומיין(ים) חסום(ים) -matrixSwitchNoMixedContent=מצב HTTPS נוקשה -matrixSwitchNoWorker=Forbid web workers -matrixSwitchReferrerSpoof=זיוף מפנה -matrixSwitchNoscriptSpoof=זיוף תגיות <code><noscript></code> -matrixRevertAllEntry=מחק את כל השינויים הזמניים -matrixLoggerMenuEntry=עבור למתעד -matrixDashboardMenuEntry=עבור לפאנל הקונפיגורציות -matrixNoTabFound=לא נמצא עמוד -statsPageTitle=ηMatrix – סטטיסטיקות -statsPageGenericStats=סטטיסטיקות גנריות -statsPageCookieHeadersFoiled=כותרות (Headers) <a href='https://en.wikipedia.org/wiki/HTTP_cookie'>HTTP cookie</a> שסוכלו: {{count}} -statsPageRefererHeadersFoiled=כותרות (Headers) <a href='https://en.wikipedia.org/wiki/HTTP_referer'>HTTP referer</a> שסוכלו: {{count}} -statsPageHyperlinkAuditingFoiled=ניסיונות <a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>Hyperlink auditing</a> שסוכלו: {{count}} -statsPageCookiesRemoved=מחיקות של עוגיות מקומיות: {{count}} -statsPageLocalStoragesCleared=ריקונים של <a href='http://diveintohtml5.info/storage.html'>אחסונים לוקליים</a>: {{count}} -statsPageBrowserCacheCleared=מחיקות של זיכרון מטמון: {{count}} -statsPageDetailedStats=סטטיסטיקות מפורטות -statsPageDetailedAllPages=כל הדפים -statsPageDetailedBehindTheScenePage=מאחורי הקלעים -statsPageOverview=סקירה כללית -statsPageRequests=בקשות -statsPageAllowed=מאופשרות -statsPageBlocked=חסומות -statsPageAll=כולן -statsPagePages=דפים -statsPageCookies=עוגיות -statsPageCSS=CSS -statsPageImages=תמונות -statsPagePlugins=פלאגינים -statsPageScripts=סקריפטים -statsPageXHRs=XHRs -statsPageFrames=מסגרות -statsPageOthers=אחרות -statsPageDetailed=מתעד -statsPageLogSizePrompt1=זכור את -statsPageLogSizePrompt2=בקשות ה HTTP <b>פר עמוד</b>. -statsPageLogSizeHelp=<p>אתה יכול לבדוק את הפרטים של רוב בקשות HTTP הגולמיות האחרונות אשר יצאו מדף אינטרנט (ראה להלן).</p><p>זה שימושי בעיקר למשתמשים מתקדמים שרוצים לחקור בדיוק מה דף האינטרנט עשה. אבל רישום בקשות ה HTTP הללו דורש זיכרון, ואם לא אכפת לך מהמידע הטכני הזה, אז הזיכרון מתבזבז.</p><p>לכן קיימת אפשרות זו המאפשרת לך להתאים את המספר המרבי של בקשות ה HTTP הכי האחרונות שמיועדות להירשם לבדיקה נוספת.</p><p>הזן “<code>0</code>” כדי לכבות את הרישום המפורט (וכתוצאה מכך להפחית את השימוש בזיכרון של <i>ηMatrix</i>).</p> -statsPageRefresh=רענן -settingsPageTitle=ηMatrix – הגדרות -settingsMatrixDisplayHeader=מטריצה -settingsMatrixDisplayTextSizePrompt=גודל טקסט: -settingsMatrixDisplayTextSizeNormal=רגיל -settingsMatrixDisplayTextSizeLarge=גדול -settingsMatrixDisplayColorBlind=ידידותי לעיוורי צבעים -settingsMatrixConvenienceHeader=נוחות -settingsDefaultScopeLevel=רמת הגדרות דיפולטיבית: -settingsDefaultScopeLevel0=גלובלי -settingsDefaultScopeLevel1=דומיין -settingsDefaultScopeLevel2=אתר -settingsMatrixAutoReloadPrompt=לאחר סגירת המטריצה, טען מחדש בצורה חכמה את הלשוניות הבאות: -settingsMatrixAutoReloadNone=ללא -settingsMatrixAutoReloadCurrent=נוכחי -settingsMatrixAutoReloadAll=כולם -settingsMatrixAutoReloadInfo=בכל פעם שאתה עושה שינויים במטריצה אשר יכולים להשפיע על ההצגה ו/או התנהגות של דף או יותר, <i>ηMatrix</i> יטען מחדש את העמודים המושפעים אוטומטית כשתסגור את המטריצה. -settingsSubframeColor=מסגרות חסומות: צבע -settingsSubframeOpacity=אטימות -settingsIconBadgeEnabled=Show the number of blocked requests on the icon -settingsCollapseBlocked=הסתר את המקום שנשאר מחסימה של אלמנטים -settingsCollapseBlacklisted=Collapse placeholder of blacklisted elements -settingsNoscriptTagsSpoofed=זייף תגיות <code><noscript></code> כאשר סקריפטים צד-1 חסומים -settingsCloudStorageEnabled=אפשר תמיכת אחסון ענן -privacyPageTitle=ηMatrix – פרטיות -privacyDeleteBlockedCookiesPrompt=מחק עוגיות חסומות. -privacyDeleteBlockedCookiesHelp=<p>עוגיות ברשימה השחורה לא נמנעות על ידי <i>ηMatrix</i> מלהיכנס לדפדפן שלך. אולם הן כן מנועות מלצאת מהדפדפן שלך, וזה מה שחשוב באמת. לא לחסום עוגיות לפני שהן נכנסות לדפדפן שלך נותן לך את ההזדמנות להיות מודע לכך שאתר ניסה להשתמש בעוגיות, ויתר על כן כדי לבדוק את תוכנם, אם תרצה.</p><p>כאשר <i>ηMatrix</i> נתקל בעוגייה שברשימה השחורה, הן יכולות להיות מוסרות מהדפדפן שלך אם תרצה בכך.</p><p><b>הערה חשובה:</b> תוספים יכולים לבצע בקשות רשת במהלך פעולתם הרגילה. בקשות אלה יכולות לגרום לכך שעוגיות יווצרו בדפדפן. אם הדומיין שממנה העוגייה הגיעה לא ברשימה הלבנה, העוגייה תמחק מהדפדפן על ידי <i>µMatrix</i> אם אפשרות זו מאופשרת. אז תהיה בטוח לגבי זה שהדומיין(ים) אשר איתם התוסף יכול לתקשר נמצא(ים) ברשימה הלבנה.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=מחק עוגיות סשן לא חסומות -privacyDeleteNonBlockedSessionCookiesPrompt2= דקות אחרי הפעם האחרונה שהן היו בשימוש. -privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “עוגיית סשן ... נמחקת כאשר אתה מסיים הסשן של הדפדפן. עוגיית הסשן מאוכסנת בזיכרון זמני ולא נשמרת לאחר שהדפדפן נסגר.”</p><p>אלא שהדבר <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>יכול לא לקרות</a> בדפדפנים מסויימים. כמו כן, לחלק, הפעולה של לסגור את הדפדפן על מנת שעוגיות הסשן יימחקו יכולה להיות פעולה מספיק מוקדמת.</p> -privacyDeleteBlockedLocalStoragePrompt=מחק <a href='https://en.wikipedia.org/wiki/Web_storage'>איחסונים לוקאליים</a> שנרשמו על ידי דומיינים חסומים -privacyDeleteBlockedLocalStorageHelp=לעשות -privacyClearCachePrompt1=מחק את הזיכרון מטמון כל -privacyClearCachePrompt2=דקות. -privacyClearCacheHelp=<p>יש אתרי אינטרנט שממש רוצים לעקוב אחרייך, כל כך שהם ישתמשו בטריקים לא כל כך יפים על מנת לעקוף את כל הדברים שאתה עושה כדי לא להיות במעקב.</p><p>כמה מהטריקים האלה מתבססים<sup>[1, 2]</sup> על <a href='https://en.wikipedia.org/wiki/Web_cache'>הזיכרון מטמון של הדפדפן</a>, אשר תוכנו לרוב נמצא הרבה זמן על המחשב מכיוון שלעיתים רחוקות משתמשים ישקיעו מזמנם לנקות באופן קבוע את הזיכרון מטמון של הדפדפן שלהם.</p><p>יש אי נעימות קלה לנקות את הזיכרון מטמון של הדפדפן באופן קבוע (רוב הסיכויים שלא תשים לב כשזה קורה), והתועלת היא במניעה של העוקבים הנתעבים האלה מחדירה לפרטיות שלך.</p><p>סמן אפשרות זו בשביל ש <i>ηMatrix</i> יעשה זאת בשבילך, כל כמה זמן שתרצה.</p><p>[1] <a href='https://grepular.com/Preventing_Web_Tracking_via_the_Browser_Cache'>“מניעה מעקב אינטרנטי על ידי שימוש בזיכרון מטמון של הדפדפן”</a>\n[2] <a href='http://lucb1e.com/rp/cookielesscookies/'>“עוגיות חסרי העוגיות”</a></p> -privacyProcessRefererPrompt=זייף את ה <a href='https://en.wikipedia.org/wiki/HTTP_referer'>HTTP referer</a> של בקשות צד שלישי. -privacyProcessRefererHelp=מתוך ויקיפדיה:<blockquote>HTTP referer זוהי כותרת (header) של בקשת HTTP אשר מזהה את הכתובת של דף האינטרנט שמקושר למשאב שמבוקש. ... <b>משום שהמידע על המפנה (referer) יכול לפגוע בפרטיות, מספר דפדפנים מאפשרים למשתמש לבטל את השליחה של המידע של המפנה.</b></blockquote>אם אפשרות זו מאופשרת, <i>ηMatrix</i> יזייף את המידע של ה HTTP referrer אם שם הדומיין של ה HTTP referrer הוא צד שלישי לשם הדומיין של בקשת הרשת. -privacyNoMixedContentPrompt=מצב HTTPS נוקשה: אסור על תוכן מעורב. -privacyNoMixedContentHelp=<p>מתוך <a href='https://developer.mozilla.org/en-US/docs/Security/MixedContent'>Mozilla Developer Network</a>:</p>אם דף HTTPS (מאובטח) מכיל בתוכו תוכן שהובא באמצעות בקשת HTTP, אז החיבור מוצפן באופן חלקי בלבד: התוכן הלא מוצפן נגיש להסנפה ותוקפים שנמצאים באמצע יכולים לשנות אותו, ולכן החיבור כבר לא בטוח. כאשר דף אינטרנט מציג התנהגות זו, זה נקרא דף עם תוכן מעורב.</blockquote> -privacyProcessHyperlinkAuditingPrompt=חסום את כל הניסיונות ל<a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>Hyperlink auditing</a>. -privacyProcessHyperlinkAuditingHelp=<p>Hyperlink auditing זהו מנגנון אשר מאפשר לצד, <b>כל צד</b>, להיות מודע על איזה קישור בדיוק המשתמש לחץ בדף אינטרנט ספציפי. במהות שלו זוהי תכונת מעקב: היא מאפשרת לדף אינטרנט, או לכל אתר צד שלישי לדף אינטרנט זה, להיות מודע לגבי איזה קישור לחצת באיזה דף של האתר שלהם. המטרה היחידה היא לעקוב אחר פעילות הגלישה שלך.</p> -userRulesPermanentHeader=חוקים קבועים -userRulesTemporaryHeader=חוקים זמניים -userRulesRevert=החזר למצב הקודם -userRulesCommit=החל -userRulesEdit=ערוך -userRulesEditSave=שמור -userRulesEditDicard=בטל -userRulesImport=ייבא מקובץ... -userRulesExport=ייצא לקובץ... -userRulesFormatHint=ראה דף זה עבור הסינטקס (התחביר) של החוקים. -userRulesDefaultFileName=חוקי-המטריצה-שלי.txt -hostsFilesPrompt=כל הדומיינים בקובץ ה hosts נטענים כחסומים בטווח הגלובלי. -hostsFilesStats={{blockedHostnameCount}} דומיינים שונים חסומים מ: -hostsFilesPerFileStats={{used}} בשימוש מתוך {{total}} -hostsFilesLastUpdate=עדכון אחרון: {{ago}} -hostsFilesApplyChanges=החל שינויים -hostsFilesAutoUpdatePrompt=עדכן אוטומטית את קבצי ה hosts. -hostsFilesUpdateNow=עדכן כעת -hostsFilesPurgeAll=נקה את כל זיכרוני המטמון -hostsFilesExternalListsHint=כתובת אחת בכל שורה. שורות עם קידומת ‘#’ לא יפורשו. כתובות לא חוקיות לא יפורשו ולא תהיה התראה לכך. -hostsFilesExternalListsParse=פרסר -hostsFilesExternalListPurge=נקה זיכרון מטמון -hostsFilesExternalListNew=גרסה חדשה זמינה -hostsFilesExternalListObsolete=לא עדכני -rawSettingsWarning=Warning! Change these raw configuration settings at your own risk. -aboutChangelog=רשימת שינויים -aboutStorageUsed=אחסון בשימוש: {{storageUsed}} בתים -aboutDoc=דוקומנטציה -aboutPermissions=הרשאות -aboutCode=קוד מקור (GPLv3) -aboutIssues=באגים ובעיות -aboutContributors=תורמים -aboutCodeContributors=קוד: -aboutIssueContributors=בעיות: -aboutTranslationContributors=תרגומים: -aboutUserDataHeader=המידע שלך -aboutBackupButton=גבה לקובץ... -aboutBackupFilename=my-ematrix-backup.txt -aboutRestoreButton=שחזר מקובץ... -aboutRestoreConfirm=כל ההגדרות שלך יוחלפו בנתונים שגובו ב {{time}}, ו ηMatrix יופעל מחדש.\n\nהאם להחליף את כל ההגדרות הקיימות בנתונים המגובים? -aboutRestoreError=לא הוצלח לקרוא את המידע או שהינו פגום -aboutOr=... או ... -aboutResetButton=אפס להגדרות ברירת מחדל -aboutResetConfirm=אזהרה! פעולה זו תוביל למחיקה של כל ההגדרות המותאמות אישית שלך. האם אתה בטוח שאתה רוצה להמשיך? -loggerFilterInputPlaceholder=ביטוי(י) פילטור -loggerMaxEntriesTip=מספר רשומות מקסימליות -loggerEntryCookieDeleted=עוגייה נמחקה: {{value}} -loggerEntryDeleteCookieError=נכשל במחיקת העוגייה: {{value}} -loggerEntryBrowserCacheCleared=זיכרון מטמון נמחק -loggerEntryAssetUpdated=הנכס עודכן: {{value}} -mainBlockedPrompt1=ηMatrix מנע מהעמוד הבא מלהיטען: -mainBlockedPrompt2=בגלל החוק הבא -mainBlockedBack=חזור -mainBlockedClose=סגור -commandRevertAll=מחק את כל ההגדרות הזמניות -commandWhitelistPageDomain=זמנית הרשה את דף הדומיין -commandWhitelistAll=זמנית הרשה הכל -commandOpenDashboard=פתח את פאנל הקונפיגורציות -elapsedOneMinuteAgo=לפני דקה -elapsedManyMinutesAgo=לפני {{value}} דקות -elapsedOneHourAgo=לפני שעה -elapsedManyHoursAgo=לפני {{value}} שעות -elapsedOneDayAgo=לפני יום -elapsedManyDaysAgo=לפני {{value}} ימים -showDashboardButton=פאנל הקונפיגורציות -showLoggerButton=מתעד -cloudPush=ייצא לאחסון ענן -cloudPull=ייבא מתוך אחסון ענן -cloudNoData=...\n... -cloudDeviceNamePrompt=שם התקן זה: -genericSubmit=שלח -genericRevert=שחזר -errorCantConnectTo=שגיאת רשת: לא הוצלח להתחבר ל {{url}} -genericApplyChanges=Apply changes -noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can display some content by using the <noscript> tag. For example, some websites will redirect users to a “scriptless” version.</p><p>When ηMatrix blocks scripts, the browser will still advertise itself as supporting script execution unless this option is selected.</p><p>When selected, ηMatrix will tell the website that the browser does not support scripts, which is what you definitely want to do if you are blocking 1st-party scripts. As such, the <noscript> tag will work as intended.</p><p>Not selecting this option when 1st-party scripts are blocked means the website will break misteryously in case it is meant to redirect to a scriptless version.</p> -settingsUpdateIcon=Do not change the toolbar icon -updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> -resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> diff --git a/locale/hi/messages.properties b/locale/hi/messages.properties deleted file mode 100644 index abb4a4e..0000000 --- a/locale/hi/messages.properties +++ /dev/null @@ -1,186 +0,0 @@ -extName=ηMatrix -dashboardPageName=ηMatrix— डैशबोर्ड -loggerPageName=ηMatrix — Logger -settingsPageName=सेटिंग्स -privacyPageName=गोपनीयता -statsPageName=आंकड़े -userRulesPageName=मेरे नियम -ubiquitousRulesPageName=होस्ट फ़ाइलें -rawSettingsPageName=More -aboutPageName=जानकारी -allPrettyName=सभी -cookiePrettyName=कुकीज़ -cssPrettyName=सीएसएस -imagePrettyName=छवि -mediaPrettyName=media -pluginPrettyName=plugin -scriptPrettyName=लिपि -xhrPrettyName=XHR -framePrettyName=ढांचा -otherPrettyName=अन्य -matrixNoNetTrafficPrompt=No net traffic seen for this tab so far. -matrixMtxButtonTip=Disable/enable matrix filtering for this scope. -matrixPersistButtonTip=Save all temporary changes for this scope. -matrixRevertButtonTip=Revert temporary changes for this scope. -matrixReloadButton=Reload the page.\nPress Shift to bypass the browser cache. -matrixScopeTip=Change to global scope. -matrixSwitchesTip=Dropdown menu with additional settings. -matrix1stPartyLabel=1st-party -matrixBlacklistedHostnames={{count}} blacklisted hostname(s) -matrixSwitchNoMixedContent=Forbid mixed content -matrixSwitchNoWorker=Forbid web workers -matrixSwitchReferrerSpoof=Spoof <code>Referer</code> header -matrixSwitchNoscriptSpoof=Spoof <code><noscript></code> tags -matrixRevertAllEntry=Revert all temporary changes -matrixLoggerMenuEntry=Go to logger -matrixDashboardMenuEntry=Go to dashboard -matrixNoTabFound=No web page found -statsPageTitle=ηMatrix – Statistics -statsPageGenericStats=Generic statistics -statsPageCookieHeadersFoiled=<a href='https://en.wikipedia.org/wiki/HTTP_cookie'>HTTP cookie</a> headers foiled: {{count}} -statsPageRefererHeadersFoiled=<a href='https://en.wikipedia.org/wiki/HTTP_referer'>HTTP referer</a> headers foiled: {{count}} -statsPageHyperlinkAuditingFoiled=<a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>Hyperlink auditing</a> attempts foiled: {{count}} -statsPageCookiesRemoved=Local cookies removed: {{count}} -statsPageLocalStoragesCleared=<a href='http://diveintohtml5.info/storage.html'>Local storages</a> emptied: {{count}} -statsPageBrowserCacheCleared=Browser caches cleared: {{count}} -statsPageDetailedStats=Detailed statistics -statsPageDetailedAllPages=सभी -statsPageDetailedBehindTheScenePage=Behind the scene -statsPageOverview=संक्षिप्त अवलोकन -statsPageRequests=Requests -statsPageAllowed=अनुमति है -statsPageBlocked=Blocked -statsPageAll=All -statsPagePages=Pages -statsPageCookies=Cookies -statsPageCSS=CSS -statsPageImages=Images -statsPagePlugins=Plugins -statsPageScripts=Scripts -statsPageXHRs=XHRs -statsPageFrames=Frames -statsPageOthers=Others -statsPageDetailed=अनुरोध प्रवेश -statsPageLogSizePrompt1=पिछले याद रखें -statsPageLogSizePrompt2=HTTP requests <b>per page</b>. -statsPageLogSizeHelp=<p>You can inspect details of the most recent raw HTTP requests which have been made by a web page (see below).</p><p>This is mostly useful to advanced users who want to investigate exactly what a web page has been doing. But logging these HTTP requests requires memory, and if you don't care about this technical information, then memory is being wasted.</p><p>Hence this field which lets you adjust the maximum number of the most recent HTTP requests which are to be logged for further inspection.</p><p>Enter “<code>0</code>” to turn off detailed logging (and consequently reduce the memory footprint of <i>ηMatrix</i>).</p> -statsPageRefresh=रिफ्रेश -settingsPageTitle=µMatrix – सेटिंग्स -settingsMatrixDisplayHeader=दिखावट -settingsMatrixDisplayTextSizePrompt=पाठ का आकार -settingsMatrixDisplayTextSizeNormal=नोर्मल -settingsMatrixDisplayTextSizeLarge=बड़ा -settingsMatrixDisplayColorBlind=Color-blind friendly -settingsMatrixConvenienceHeader=Convenience -settingsDefaultScopeLevel=Default scope level: -settingsDefaultScopeLevel0=Global -settingsDefaultScopeLevel1=Domain -settingsDefaultScopeLevel2=Site -settingsMatrixAutoReloadPrompt=When the matrix is closed, smart reload these tabs: -settingsMatrixAutoReloadNone=कोई नहीं -settingsMatrixAutoReloadCurrent=Current -settingsMatrixAutoReloadAll=All -settingsMatrixAutoReloadInfo=Whenever you make changes in the matrix which can affect the display and/or behavior of one or more pages, <i>ηMatrix</i> will reload affected pages automatically when you close the matrix. -settingsSubframeColor=Blocked frames: Color -settingsSubframeOpacity=Opacity -settingsIconBadgeEnabled=Show the number of blocked requests on the icon -settingsCollapseBlocked=Collapse placeholder of blocked elements -settingsCollapseBlacklisted=Collapse placeholder of blacklisted elements -settingsNoscriptTagsSpoofed=Spoof <code><noscript></code> tags when 1st-party scripts are blocked -settingsCloudStorageEnabled=Enable cloud storage support -privacyPageTitle=ηMatrix – Privacy -privacyDeleteBlockedCookiesPrompt=Delete blocked cookies. -privacyDeleteBlockedCookiesHelp=<p>Blacklisted cookies are not prevented by <i>ηMatrix</i> from entering your browser. However they are prevented from leaving your browser, which is what really matters. Not blocking cookies before they enter your browser gives you the opportunity to be informed that a site tried to use cookies, and furthermore to inspect their contents if you wish.</p><p>Once these blacklisted cookies have been accounted for by <i>ηMatrix</i>, they can be removed from your browser if you wish so.</p><p><b>Important note:</b> Extensions can make web requests during the course of their normal operation. These requests can result in cookies being created in the browser. If the hostname from where a cookie originate is not whitelisted, the cookie will be removed from the browser by <i>ηMatrix</i> if this option is checked. So be sure that the hostname(s) with which an extension communicate is whitelisted.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Delete non-blocked session cookies -privacyDeleteNonBlockedSessionCookiesPrompt2= minutes after the last time they have been used. -privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “A session cookie ... is erased when you end the browser session. The session cookie is stored in temporary memory and is not retained after the browser is closed.”</p><p>Except that this <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>might not be happening</a> in some browsers. Also, to some, having to close the browser in order for the session cookies to clear might not be early enough.</p> -privacyDeleteBlockedLocalStoragePrompt=Delete <a href='https://en.wikipedia.org/wiki/Web_storage'>local storage</a> content set by blocked hostnames -privacyDeleteBlockedLocalStorageHelp=TODO -privacyClearCachePrompt1=Clear browser cache every -privacyClearCachePrompt2=minutes. -privacyClearCacheHelp=<p>Some web sites are really bent on tracking you, so much that they will use not-so-nice tricks to work around whatever measures you take in order to not be tracked.</p><p>A few of these tricks rely<sup>[1, 2]</sup> on the <a href='https://en.wikipedia.org/wiki/Web_cache'>browser cache</a>, which content is often long lasting since rarely will users take the time to regularly clear their browser cache.</p><p>There is little inconvenience to clear the browser cache regularly (likelihood is that you won't notice when it happens), and the benefit is to prevent these obnoxious trackers from invading your privacy.</p><p>Check this option to have <i>ηMatrix</i> do it for you, at the interval you wish.</p><p>[1] <a href='https://grepular.com/Preventing_Web_Tracking_via_the_Browser_Cache'>“Preventing Web Tracking via the Browser Cache”</a>\n[2] <a href='http://lucb1e.com/rp/cookielesscookies/'>“Cookieless cookies”</a></p> -privacyProcessRefererPrompt=Spoof <a href='https://en.wikipedia.org/wiki/HTTP_referer'>HTTP referrer</a> string of third-party requests. -privacyProcessRefererHelp=From Wikipedia:<blockquote>HTTP referer is an HTTP header field that identifies the address of the webpage that linked to the resource being requested. ... <b>Because referer information can violate privacy, some web browsers allow the user to disable the sending of referer information.</b></blockquote>If this setting is checked, <i>ηMatrix</i> will spoof the HTTP referrer information if the domain name of the HTTP referrer is third-party to the domain name of net request. -privacyNoMixedContentPrompt=Strict HTTPS: forbid mixed content. -privacyNoMixedContentHelp=<p>From <a href='https://developer.mozilla.org/en-US/docs/Security/MixedContent'>Mozilla Developer Network</a>:</p><blockquote>If [a] HTTPS page includes content retrieved through regular, cleartext HTTP, then the connection is only partially encrypted: the unencrypted content is accessible to sniffers and can be modified by man-in-the-middle attackers, and therefore the connection is not safeguarded anymore. When a webpage exhibits this behavior, it is called a mixed content page.</blockquote> -privacyProcessHyperlinkAuditingPrompt=Block all <a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>hyperlink auditing</a> attempts. -privacyProcessHyperlinkAuditingHelp=<p>Hyperlink auditing is a mechanism which allow a party, <b>any party</b>, to be informed about which link a user clicked on a particular web page. It is essentially a tracking feature: it allows a web site, or any third-party to that web site, to be informed about which link you clicked on which one of its web pages. The sole purpose is to track your browsing activity.</p> -userRulesPermanentHeader=Permanent rules -userRulesTemporaryHeader=Temporary rules -userRulesRevert=Revert -userRulesCommit=Commit -userRulesEdit=Edit -userRulesEditSave=Save -userRulesEditDicard=Discard -userRulesImport=Import from file... -userRulesExport=Export to file... -userRulesFormatHint=See this page for rule syntax. -userRulesDefaultFileName=my-ematrix-rules.txt -hostsFilesPrompt=All hostnames in a hosts file are loaded as blacklisted hostnames in the global scope. -hostsFilesStats={{blockedHostnameCount}} distinct blocked hostnames from: -hostsFilesPerFileStats={{used}} used out of {{total}} -hostsFilesLastUpdate=Last update: {{ago}} -hostsFilesApplyChanges=Apply changes -hostsFilesAutoUpdatePrompt=Auto-update hosts files. -hostsFilesUpdateNow=Update now -hostsFilesPurgeAll=Purge all caches -hostsFilesExternalListsHint=One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored. -hostsFilesExternalListsParse=Parse -hostsFilesExternalListPurge=purge cache -hostsFilesExternalListNew=new version available -hostsFilesExternalListObsolete=outdated -rawSettingsWarning=Warning! Change these raw configuration settings at your own risk. -aboutChangelog=Change log -aboutStorageUsed=Storage used: {{storageUsed}} bytes -aboutDoc=Documentation -aboutPermissions=Permissions -aboutCode=Source code (GPLv3) -aboutIssues=Bugs and issues -aboutContributors=Contributors -aboutCodeContributors=Code: -aboutIssueContributors=Issues: -aboutTranslationContributors=Translations: -aboutUserDataHeader=Your data -aboutBackupButton=Backup to file... -aboutBackupFilename=my-ematrix-backup.txt -aboutRestoreButton=Restore from file... -aboutRestoreConfirm=All your settings will be overwritten using data backed up on {{time}}, and ηMatrix will restart.\n\nOverwrite all existing settings using backed up data? -aboutRestoreError=The data could not be read or is invalid -aboutOr=... or ... -aboutResetButton=Reset to default settings -aboutResetConfirm=Caution! this will remove all your custom settings. Are you sure you want to proceed? -loggerFilterInputPlaceholder=filter expression(s) -loggerMaxEntriesTip=Maximum number of entries -loggerEntryCookieDeleted=cookie deleted: {{value}} -loggerEntryDeleteCookieError=failed to delete cookie: {{value}} -loggerEntryBrowserCacheCleared=browser cache cleared -loggerEntryAssetUpdated=asset updated: {{value}} -mainBlockedPrompt1=ηMatrix has prevented the following page from loading: -mainBlockedPrompt2=Because of the following rule -mainBlockedBack=Go back -mainBlockedClose=Close -commandRevertAll=Revert all temporary changes -commandWhitelistPageDomain=Temporarily whitelist page domain -commandWhitelistAll=Temporarily whitelist all -commandOpenDashboard=Open dashboard -elapsedOneMinuteAgo=a minute ago -elapsedManyMinutesAgo={{value}} minutes ago -elapsedOneHourAgo=an hour ago -elapsedManyHoursAgo={{value}} hours ago -elapsedOneDayAgo=a day ago -elapsedManyDaysAgo={{value}} days ago -showDashboardButton=Dashboard -showLoggerButton=Logger -cloudPush=Export to cloud storage -cloudPull=Import from cloud storage -cloudNoData=...\n... -cloudDeviceNamePrompt=This device name: -genericSubmit=Submit -genericRevert=Revert -errorCantConnectTo=Network error: Unable to connect to {{url}} -genericApplyChanges=Apply changes -noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can display some content by using the <noscript> tag. For example, some websites will redirect users to a “scriptless” version.</p><p>When ηMatrix blocks scripts, the browser will still advertise itself as supporting script execution unless this option is selected.</p><p>When selected, ηMatrix will tell the website that the browser does not support scripts, which is what you definitely want to do if you are blocking 1st-party scripts. As such, the <noscript> tag will work as intended.</p><p>Not selecting this option when 1st-party scripts are blocked means the website will break misteryously in case it is meant to redirect to a scriptless version.</p> -settingsUpdateIcon=Do not change the toolbar icon -updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> -resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> diff --git a/locale/hu/messages.properties b/locale/hu/messages.properties index 138f91a..74bbd3d 100644 --- a/locale/hu/messages.properties +++ b/locale/hu/messages.properties @@ -91,7 +91,7 @@ settingsCloudStorageEnabled=Felhőszolgáltatások támogatása privacyPageTitle=ηMatrix – Adatvédelem privacyDeleteBlockedCookiesPrompt=Blokkolt sütik törlése. privacyDeleteBlockedCookiesHelp=<p>A <i>ηMatrix</i> a tiltólistás sütik böngészőből való távozását tiltja csak meg, a böngészőbe érkezésüket nem akadályozza meg. Ezúton tudomás szerezhető arról, ha egy oldal sütiket akar tárolni, valamint azok tartalma is megtekinthetővé válik.</p><p>Ezen opció bejelölésével a <i>ηMatrix</i> automatikusan eltávolítja a beérkezett tiltott sütiket.</p><p><b>Fontos:</b> Nemcsak oldalak, hanem kiegészítők is indíthatnak lekérdezéseket működésük során, amelyek sütik létrehozásához vezethetnek. Amennyiben ez az opció engedélyezve van, továbbá a lekérésekhez tartozó hostneveken a sütik blokkolva vannak, akkor azok el lesznek távolítva a <i>ηMatrix</i> által. Ez egyes kiegészítőknél hibás működést eredményezhet, amíg az általuk használt hostnevekről kapott sütik nincsenek engedélyezve.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Nem blokkolt munkamenet sütik törlése +privacyDeleteNonBlockedSessionCookiesPrompt1=Nem blokkolt munkamenet sütik törlése privacyDeleteNonBlockedSessionCookiesPrompt2= perccel az utolsó használatuk után. privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “A munkamenet süti ... eltávolításra kerül a böngészési munkamenettel befejezően. A munkamenet süti ideiglenes memóriában tárolódik és a böngésző bezárásával törlésre kerül.”</p><p>Viszont pár böngészőnél <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>előfordulhat, hogy nem ez történik</a>, valamint nem minden esetben elfogadható megoldás a böngésző csak a munkamenet sütik törléséért való bezárása.</p> privacyDeleteBlockedLocalStoragePrompt=Blokkolt hostnevek által <a href='https://en.wikipedia.org/wiki/Web_storage'>helyileg tárolt</a> adatok törlése @@ -115,7 +115,7 @@ userRulesEditDicard=Elvetés userRulesImport=Importálás fájlból... userRulesExport=Exportálás fájlba... userRulesFormatHint=A szintaktikai szabályok az alábbi oldalon találhatók. -userRulesDefaultFileName=my-ematrix-rules.txt +userRulesDefaultFileName=my-umatrix-rules.txt hostsFilesPrompt=Egy hosts fájlban található összes bejegyzés tiltott hostnév lesz a globális hatáskörre nézve. hostsFilesStats={{blockedHostnameCount}} különböző hostnév blokkolva a következő listák alapján: hostsFilesPerFileStats={{used}} használatban {{total}} közül @@ -124,7 +124,7 @@ hostsFilesApplyChanges=Módosítások alkalmazása hostsFilesAutoUpdatePrompt=Hosts fájlok automatikus frissítése. hostsFilesUpdateNow=Frissítés hostsFilesPurgeAll=Minden gyorsítótár ürítése -hostsFilesExternalListsHint=Soronként egy URL. A ‘#’ karakterrel kezdődő sorok figyelmen kívül lesznek hagyva. Az érvénytelen URL-ek hibaüzenet nélkül figyelmen kívül lesznek hagyva. +hostsFilesExternalListsHint=<p>One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored.</p><p>The inserted URL must point to a hosts file (including local files); do not use the hosts file syntax here.</p> hostsFilesExternalListsParse=Elemzés hostsFilesExternalListPurge=gyorsítótár ürítése hostsFilesExternalListNew=új verzió érhető el @@ -142,7 +142,7 @@ aboutIssueContributors=Problémák: aboutTranslationContributors=Fordítások: aboutUserDataHeader=Beállítások kezelése aboutBackupButton=Mentés fájlba... -aboutBackupFilename=my-ematrix-backup.txt +aboutBackupFilename=my-umatrix-backup.txt aboutRestoreButton=Visszaállítás fájlból... aboutRestoreConfirm=Minden jelenlegi beállítás felülírásra kerül a {{time}} dátumú biztonsági mentésben található beállítással, majd ezt követően a ηMatrix újraindul.\n\nBiztosan felülírjam a jelenlegi beállításokat a megadott biztonsági mentéssel? aboutRestoreError=Nem olvasható vagy érvénytelen adat @@ -183,4 +183,6 @@ noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can dis settingsUpdateIcon=Do not change the toolbar icon updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +resolveCnameHelp=<p>When resolving an address with DNS, some webistes use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +settingsTextSmaller=Smaller +settingsTextBigger=Bigger diff --git a/locale/id/messages.properties b/locale/id/messages.properties deleted file mode 100644 index 70afaca..0000000 --- a/locale/id/messages.properties +++ /dev/null @@ -1,186 +0,0 @@ -extName=ηMatrix -dashboardPageName=ηMatrix — Dasbor -loggerPageName=ηMatrix — Logger -settingsPageName=Pengaturan -privacyPageName=Privasi -statsPageName=Statistik -userRulesPageName=Aturan saya -ubiquitousRulesPageName=Berkas host -rawSettingsPageName=More -aboutPageName=Tentang -allPrettyName=semua -cookiePrettyName=kuki -cssPrettyName=css -imagePrettyName=gmbr -mediaPrettyName=media -pluginPrettyName=plugin -scriptPrettyName=skrip -xhrPrettyName=XHR -framePrettyName=frame -otherPrettyName=lain -matrixNoNetTrafficPrompt=Sejauh ini tidak terlihat lalu lintas jaringan untuk tab ini. -matrixMtxButtonTip=Nonaktif/aktifkan penyaringan matriks untuk lingkup ini. -matrixPersistButtonTip=Simpan semua perubahan sementara untuk lingkup ini. -matrixRevertButtonTip=Kembalikan perubahan sementara untuk lingkup ini. -matrixReloadButton=Muat ulang laman. -matrixScopeTip=Change to global scope. -matrixSwitchesTip=Dropdown menu with additional settings. -matrix1stPartyLabel=pihak pertama -matrixBlacklistedHostnames={{count}} nama host dicekal -matrixSwitchNoMixedContent=HTTPS Ketat -matrixSwitchNoWorker=Forbid web workers -matrixSwitchReferrerSpoof=Pemalsuan perujuk -matrixSwitchNoscriptSpoof=Spoof <code><noscript></code> tags -matrixRevertAllEntry=Kembalikan semua ubahan sementara -matrixLoggerMenuEntry=Kunjungi pencatat -matrixDashboardMenuEntry=Kunjungi dasbor -matrixNoTabFound=No web page found -statsPageTitle=ηMatrix – Statistik -statsPageGenericStats=Statistik umum -statsPageCookieHeadersFoiled=Tajuk <a href='https://id.wikipedia.org/wiki/Kuki_HTTP'>kuki HTTP</a> digagalkan: {{count}} -statsPageRefererHeadersFoiled=Tajuk <a href='https://en.wikipedia.org/wiki/HTTP_referer'>perujuk HTTP</a> digagalkan: {{count}} -statsPageHyperlinkAuditingFoiled=Percobaan <a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>pengauditan pranala</a> digagalkan: {{count}} -statsPageCookiesRemoved=Kuki lokal dibuang: {{count}} -statsPageLocalStoragesCleared=<a href='http://diveintohtml5.info/storage.html'>Penyimpanan lokal</a> dikosongkan: {{count}} -statsPageBrowserCacheCleared=Tembolok peramban dibersihkan: {{count}} -statsPageDetailedStats=Statistik terperinci -statsPageDetailedAllPages=Semua -statsPageDetailedBehindTheScenePage=Di balik layar -statsPageOverview=Tinjauan -statsPageRequests=Permintaan -statsPageAllowed=Diizinkan -statsPageBlocked=Diblokir -statsPageAll=Semua -statsPagePages=Halaman -statsPageCookies=Kuki -statsPageCSS=CSS -statsPageImages=Gambar -statsPagePlugins=Plugin -statsPageScripts=Skrip -statsPageXHRs=XHR -statsPageFrames=Frame -statsPageOthers=Lainnya -statsPageDetailed=Pencatat -statsPageLogSizePrompt1=Ingat -statsPageLogSizePrompt2=permintaan HTTP yang terakhir <b>per halaman</b>. -statsPageLogSizeHelp=<p>Anda dapat memeriksa rincian terkini permintaan mentah HTTP yang telah dibuat oleh halaman web (lihat di bawah).</p><p>Hal ini sangat berguna bagi para pengguna tingkat lanjut yang ingin menyelidiki secara pasti apa yang halaman web telah lakukan. Akan tetapi, mencatat permintaan HTTP ini memerlukan tambahan memori, dan jika anda tidak peduli tentang informasi teknis ini, maka memori terbuang dengan percuma.</p><p>Oleh karena itu, ruas ini memungkinkan anda mengatur jumlah maksimum permintaan HTTP terkini yang akan dicatat untuk pemeriksaan lebih lanjut.</p><p>Masukkan “<code>0</code>” untuk mematikan pencatatan terperinci (dan berarti berkurangnya penggunaan memori <i>ηMatrix</i>).</p> -statsPageRefresh=Segarkan -settingsPageTitle=ηMatrix – Pengaturan -settingsMatrixDisplayHeader=Tampilan -settingsMatrixDisplayTextSizePrompt=Ukuran teks: -settingsMatrixDisplayTextSizeNormal=Normal -settingsMatrixDisplayTextSizeLarge=Besar -settingsMatrixDisplayColorBlind=Ramah buta warna -settingsMatrixConvenienceHeader=Nyaman -settingsDefaultScopeLevel=Default scope level: -settingsDefaultScopeLevel0=Global -settingsDefaultScopeLevel1=Domain -settingsDefaultScopeLevel2=Site -settingsMatrixAutoReloadPrompt=Ketika matriks ditutup, muat ulang dengan cerdas tab berikut: -settingsMatrixAutoReloadNone=Nihil -settingsMatrixAutoReloadCurrent=Saat ini -settingsMatrixAutoReloadAll=Semua -settingsMatrixAutoReloadInfo=Kapanpun anda membuat perubahan pada matriks yang dapat mempengaruhi tampilan dan/atau perilaku satu atau lebih halaman, <i>ηMatrix</i> akan memuat ulang halaman yang terdampak secara otomatis ketika anda menutup matriks. -settingsSubframeColor=Frame diblokir: Warna -settingsSubframeOpacity=Kepekatan -settingsIconBadgeEnabled=Show the number of blocked requests on the icon -settingsCollapseBlocked=Runtuhkan tempat elemen yang diblokir -settingsCollapseBlacklisted=Collapse placeholder of blacklisted elements -settingsNoscriptTagsSpoofed=Spoof <code><noscript></code> tags when 1st-party scripts are blocked -settingsCloudStorageEnabled=Fungsikan dukungan penyimpanan awan -privacyPageTitle=ηMatrix – Privasi -privacyDeleteBlockedCookiesPrompt=Hapus kuki yang diblokir. -privacyDeleteBlockedCookiesHelp=<p>Kuki dalam daftar hitam tidak dicegah oleh <i>ηMatrix</i> untuk masuk ke peramban anda. Namun mereka dicegah untuk meninggalkan peramban anda, dan itulah yang terpenting. Tidak memblokir kuki sebelum mereka masuk ke peramban anda memberikan anda kesempatan mendapatkan informasi bahwa situs tersebut mencoba untuk menggunakan kuki, dan lebih lanjut memeriksa isi kuki tersebut jika anda inginkan.</p><p>Setelah kuki dalam daftar hitam ini dicatat oleh <i>ηMatrix</i>, mereka dapat dibuang dari peramban anda jika anda menginginkannya.</p><p><b>Catatan penting:</b> Ekstensi dapat membuat permintaan web selama operasi normal ekstensi berjalan. Permintaan ini dapat mengakibatkan beberapa kuki dibuat dalam peramban. Jika nama host dari mana kuki berasal tidak dalam daftar putih, kuki akan dibuang dari peramban oleh <i>ηMatrix</i> jika opsi berikut dicentang. Jadi, pastikan nama host dengan yang ekstensi berkomunikasi masuk dalam daftar putih.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Hapus kuki sesi yang tidak diblokir -privacyDeleteNonBlockedSessionCookiesPrompt2= menit setelah terakhir kali mereka digunakan. -privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “Kuki sesi ... dihapus ketika anda mengakhiri sesi peramban. Kuki sesi disimpan di dalam memori sementara dan tidak tinggal setelah peramban ditutup.”</p><p>Kecuali hal tersebut <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>mungkin tidak akan terjadi</a> pada beberapa peramban. Juga, bagi beberapa, menutup peramban agar kuki sesi dibersihkan mungkin tidak cukup cepat.</p> -privacyDeleteBlockedLocalStoragePrompt=Hapus muatan <a href='https://en.wikipedia.org/wiki/Web_storage'>penyimpanan lokal</a> yang disimpan oleh nama host yang diblokir -privacyDeleteBlockedLocalStorageHelp=TODO -privacyClearCachePrompt1=Bersihkan tembolok peramban setiap -privacyClearCachePrompt2=menit. -privacyClearCacheHelp=<p>Beberapa situs sangat lihai dalam melacak anda, amat sangat lihai sampai-sampai mereka akan gunakan cara-cara yang tidak baik untuk menghindari apapun tindakan yang anda lakukan agar tidak dilacak.</p><p>Beberapa cara-cara ini mengandalkan<sup>[1, 2]</sup> <a href='https://en.wikipedia.org/wiki/Web_cache'>tembolok peramban</a>, yang muatannya terkadang bertahan lama karena jarang pengguna menyempatkan waktu secara berkala membersihkan tembolok peramban mereka.</p><p>Ada sedikit ketidaknyamanan untuk membersihkan tembolok peramban secara berkala (kemungkinan adalah anda tidak akan tahu ketika hal tersebut terjadi), dan keuntungannya adalah untuk mencegah pelacak yang menjengkelkan ini melanggar privasi anda.</p><p>Centang opsi berikut untuk membuat <i>ηMatrix</i> melakukannya untuk anda, pada selang waktu yang anda inginkan.</p><p>[1] <a href='https://grepular.com/Preventing_Web_Tracking_via_the_Browser_Cache'>“Mencegah Pelacakan Web melalui Tembolok Web”</a>[2] <a href='http://lucb1e.com/rp/cookielesscookies/'>“Kuki tanpa kuki”</a></p> -privacyProcessRefererPrompt=Palsukan untai <a href='https://en.wikipedia.org/wiki/HTTP_referer'>perujuk HTTP</a> pada permintaan pihak ketiga. -privacyProcessRefererHelp=Dari Wikipedia:<blockquote>Perujuk HTTP adalah sebuah ruas tajuk HTTP yang mengidentifikasi alamat dari halaman web yang bertautan dengan sumber daya yang sedang diminta. ... <b>Karena informasi perujuk dapat melanggar privasi, beberapa peramban memperbolehkan pengguna untuk menonaktifkan pengiriman informasi perujuk.</b></blockquote>Jika aturan ini dicentang, <i>ηMatrix</i> akan memalsukan informasi perujuk HTTP jika nama domain perujuk HTTP adalah pihak ketiga dari nama domain jaringan yang diminta. -privacyNoMixedContentPrompt=HTTPS Ketat: larang konten campuran. -privacyNoMixedContentHelp=<p>Dari <a href='https://developer.mozilla.org/id/docs/Security/MixedContent'>Jaringan Pengembang Mozilla</a>:</p><blockquote>Jika halaman HTTPS mengandung muatan yang diambil melalui HTTP umum / berteks jelas, maka koneksi hanya terenkripsi sebagian: muatan yang tidak terenkripsi tersedia bagi para pengendus jaringan dan dapat diubah oleh serangan orang-ditengah, dan oleh karena itu koneksi menjadi tidak lagi aman. Ketika halaman web memperlihatkan perilaku seperti ini, hal ini disebut “halaman dengan muatan campuran tidak aman”.</blockquote> -privacyProcessHyperlinkAuditingPrompt=Blokir semua percobaan <a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>pengauditan pranala</a>. -privacyProcessHyperlinkAuditingHelp=<p>Pengauditan pranala adalah mekanisme yang memperbolehkan satu pihak, <b>pihak manapun</b>, mendapatkan informasi tentang tautan mana yang pengguna klik pada halaman web tertentu. Hal ini pada dasarnya adalah fitur pelacakan: memperbolehkan sebuah situs web, atau pihak ketiga dari situs web tersebut, mendapatkan informasi tentang tautan mana di halaman yang mana yang anda klik pada situs web tersebut. Tujuannya adalah untuk melacak aktifitas penjelajahan anda.</p> -userRulesPermanentHeader=Aturan permanen -userRulesTemporaryHeader=Aturan sementara -userRulesRevert=Kembalikan -userRulesCommit=Tetapkan -userRulesEdit=Sunting -userRulesEditSave=Simpan -userRulesEditDicard=Batal -userRulesImport=Impor dari berkas... -userRulesExport=Ekspor ke berkas... -userRulesFormatHint=Lihat laman ini untuk aturan sintaksis. -userRulesDefaultFileName=my-ematrix-rules.txt -hostsFilesPrompt=Semua nama host di dalam berkas host dimuat sebagai nama host yang dicekal dalam lingkup global. -hostsFilesStats={{blockedHostnameCount}} nama host yang berbeda diblokir dari: -hostsFilesPerFileStats={{used}} digunakan dari {{total}} -hostsFilesLastUpdate=Terakhir diperbarui: {{ago}} -hostsFilesApplyChanges=Terapkan perubahan -hostsFilesAutoUpdatePrompt=Otomatis perbarui berkas host. -hostsFilesUpdateNow=Perbarui sekarang -hostsFilesPurgeAll=Bersihkan semua tembolok -hostsFilesExternalListsHint=Satu URL per baris. Baris yang diawali dengan ‘#’ akan diabaikan. URL yang tidak valid akan diabaikan tanpa peringatan. -hostsFilesExternalListsParse=Uraikan -hostsFilesExternalListPurge=bersihkan tembolok -hostsFilesExternalListNew=versi baru tersedia -hostsFilesExternalListObsolete=usang -rawSettingsWarning=Warning! Change these raw configuration settings at your own risk. -aboutChangelog=Catatan perubahan -aboutStorageUsed=Penyimpanan digunakan: {{storageUsed}} bita -aboutDoc=Dokumentasi -aboutPermissions=Perizinan -aboutCode=Kode sumber (GPLv3) -aboutIssues=Kutu dan masalah -aboutContributors=Kontributor -aboutCodeContributors=Kode: -aboutIssueContributors=Masalah: -aboutTranslationContributors=Transliterasi: -aboutUserDataHeader=Data anda -aboutBackupButton=Cadangkan ke berkas... -aboutBackupFilename=my-ematrix-backup.txt -aboutRestoreButton=Pulihkan dari berkas... -aboutRestoreConfirm=Semua pengaturan anda akan ditimpa menggunakan data yang dicadangkan pada {{time}}, dan ηMatrix akan memulai ulang.\n\nTimpa semua aturan yang ada menggunakan data yang dicadangkan? -aboutRestoreError=Data tidak dapat dibaca atau tidak valid -aboutOr=... atau ... -aboutResetButton=Kembalikan ke pengaturan bawaan -aboutResetConfirm=Peringatan! ini akan membuang semua pengaturan tersesuai anda. Apakah anda yakin ingin melanjutkan? -loggerFilterInputPlaceholder=ekspresi penyaring -loggerMaxEntriesTip=Jumlah maksimum entri -loggerEntryCookieDeleted=kuki dihapus: {{value}} -loggerEntryDeleteCookieError=gagal menghapus kuki: {{value}} -loggerEntryBrowserCacheCleared=tembolok peramban dibersihkan -loggerEntryAssetUpdated=aset diperbarui: {{value}} -mainBlockedPrompt1=ηMatrix telah mencegah laman berikut dimuat: -mainBlockedPrompt2=Disebabkan oleh aturan berikut -mainBlockedBack=Kembali -mainBlockedClose=Tutup -commandRevertAll=Kembalikan semua perubahan sementara -commandWhitelistPageDomain=Sementara daftar-putihkan ranah halaman -commandWhitelistAll=Sementara daftar-putihkan semua -commandOpenDashboard=Buka dasbor -elapsedOneMinuteAgo=semenit yang lalu -elapsedManyMinutesAgo={{value}} menit yang lalu -elapsedOneHourAgo=sejam yang lalu -elapsedManyHoursAgo={{value}} jam yang lalu -elapsedOneDayAgo=sehari yang lalu -elapsedManyDaysAgo={{value}} hari yang lalu -showDashboardButton=Dasbor -showLoggerButton=Pencatat -cloudPush=Ekspor ke penyimpanan awan -cloudPull=Impor dari penyimpanan awan -cloudNoData=...\n... -cloudDeviceNamePrompt=Nama perangkat ini: -genericSubmit=Kirim -genericRevert=Kembalikan -errorCantConnectTo=Galat jaringan: Tidak bisa terhubung ke {{url}} -genericApplyChanges=Apply changes -noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can display some content by using the <noscript> tag. For example, some websites will redirect users to a “scriptless” version.</p><p>When ηMatrix blocks scripts, the browser will still advertise itself as supporting script execution unless this option is selected.</p><p>When selected, ηMatrix will tell the website that the browser does not support scripts, which is what you definitely want to do if you are blocking 1st-party scripts. As such, the <noscript> tag will work as intended.</p><p>Not selecting this option when 1st-party scripts are blocked means the website will break misteryously in case it is meant to redirect to a scriptless version.</p> -settingsUpdateIcon=Do not change the toolbar icon -updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> -resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> diff --git a/locale/it/messages.properties b/locale/it/messages.properties index c5eca65..c97490a 100644 --- a/locale/it/messages.properties +++ b/locale/it/messages.properties @@ -91,7 +91,7 @@ settingsCloudStorageEnabled=Attiva il supporto all'archiviazione sul cloud privacyPageTitle=ηMatrix – Privacy privacyDeleteBlockedCookiesPrompt=Cancella cookies bloccati. privacyDeleteBlockedCookiesHelp=<p><i>ηMatrix</i> non può impedire ai cookie bloccati di entrare nel tuo browser. Tuttavia impedisce che lascino il tuo browser, che è la cosa che conta. Non bloccare i cookie prima che entrino nel tuo browser ti dà la possibilità di sapere che un sito ha provato ad utilizzare cookie, e anche di ispezionarne il contenuto se lo desideri.</p><p>Quando questi cookie bloccati vengono presi in gestione da <i>ηMatrix</i>, possono essere rimossi dal browser se lo desideri.</p><p><b>Nota importante:</b> Le estensioni possono fare richieste web durante il loro normale funzionamento. Queste richieste possono portare alla creazione di cookie nel browser. Se il nome dell'host da cui proviene un cookie non è presente nella lista bianca, il cookie verrà rimosso dal browser da <i>ηMatrix</i> se l'opzione è selezionata. Assicurati quindi che il/i nome/i dell'host con cui un'estensione comunica sia in lista bianca.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Elimina i cookie di sessione non bloccati +privacyDeleteNonBlockedSessionCookiesPrompt1=Elimina i cookie di sessione non bloccati privacyDeleteNonBlockedSessionCookiesPrompt2= minuti dopo l'ultima volta che sono stati usati. privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “Un cookie di sessione ... viene cancellato al termine della sessione del browser. Il cookie di sessione è memorizzato nella memoria temporanea e non viene conservato dopo la chiusura del browser.”</p><p>A parte il fatto che ciò <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>potrebbe non accadere</a> in alcuni browser. Inoltre, per alcuni, dover chiudere il browser per eliminare i cookie di sessione potrebbe non essere abbastanza presto.</p> privacyDeleteBlockedLocalStoragePrompt=Elimina il contenuto del <a href='https://en.wikipedia.org/wiki/Web_storage'>local storage</a> dei nomi host bloccati @@ -115,7 +115,7 @@ userRulesEditDicard=Annulla userRulesImport=Importa da file... userRulesExport=Esporta in un file... userRulesFormatHint=Vedi questa pagina per la sintassi delle regole. -userRulesDefaultFileName=mie-regole-ematrix.txt +userRulesDefaultFileName=mie-regole-umatrix.txt hostsFilesPrompt=Tutti i nomi in un file hosts vengono caricati come nomi host bloccati in ambito generale. hostsFilesStats={{blockedHostnameCount}} nomi host bloccati da: hostsFilesPerFileStats={{used}} usati su {{total}} @@ -124,7 +124,7 @@ hostsFilesApplyChanges=Salva i cambiamenti hostsFilesAutoUpdatePrompt=Aggiornamento automatico files hosts. hostsFilesUpdateNow=Aggiorna ora hostsFilesPurgeAll=Cancella tutte le cache -hostsFilesExternalListsHint=Un URL per riga. Le righe che cominciano con ‘#’ saranno ignorate. Gli Url non validi saranno silenziosamente ignorati. +hostsFilesExternalListsHint=<p>One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored.</p><p>The inserted URL must point to a hosts file (including local files); do not use the hosts file syntax here.</p> hostsFilesExternalListsParse=Analizza hostsFilesExternalListPurge=elimina cache hostsFilesExternalListNew=nuova versione disponibile @@ -142,7 +142,7 @@ aboutIssueContributors=Problemi: aboutTranslationContributors=Traduzioni: aboutUserDataHeader=Tuoi dati aboutBackupButton=Crea file di backup... -aboutBackupFilename=mio-ematrix-backup.txt +aboutBackupFilename=mio-umatrix-backup.txt aboutRestoreButton=Ripristina dal file... aboutRestoreConfirm=Tutte le impostazioni verranno sovrascritte utilizzando i dati di backup del {{time}}, e ηMatrix sarà riavviato. \n\nSovrascrivere tutte le impostazioni esistenti con quelle del backup? aboutRestoreError=I dati non possono essere letti o sono invalidi @@ -183,4 +183,6 @@ noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can dis settingsUpdateIcon=Do not change the toolbar icon updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +resolveCnameHelp=<p>When resolving an address with DNS, some webistes use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +settingsTextSmaller=Smaller +settingsTextBigger=Bigger diff --git a/locale/ja/messages.properties b/locale/ja/messages.properties deleted file mode 100644 index 0073b35..0000000 --- a/locale/ja/messages.properties +++ /dev/null @@ -1,187 +0,0 @@ -extName=ηMatrix -dashboardPageName=ηMatrix — ダッシュボード -loggerPageName=ηMatrix — Logger -settingsPageName=設定 -privacyPageName=プライバシー -statsPageName=統計 -userRulesPageName=My ルール -ubiquitousRulesPageName=ホストファイル -rawSettingsPageName=詳細 -aboutPageName=ηMatrix について -allPrettyName=すべて -cookiePrettyName=Cookie -cssPrettyName=CSS -imagePrettyName=画像 -mediaPrettyName=Media -pluginPrettyName=Media -scriptPrettyName=Script -xhrPrettyName=XHR -framePrettyName=Frame -otherPrettyName=その他 -matrixNoNetTrafficPrompt=このタブではネットワークトラフィックを検出できません -matrixMtxButtonTip=このスコープの Matrix フィルタの有効/無効を切り替える -matrixPersistButtonTip=このスコープの一時的な変更をすべて保存する -matrixRevertButtonTip=このスコープの一時的な変更を元に戻す -matrixReloadButton=このページを再読み込みする\nShift キーを押しながら実行すると、キャッシュを無視した再読み込みを行います -matrixScopeTip=Change to global scope. -matrixSwitchesTip=Dropdown menu with additional settings. -matrix1stPartyLabel=1st Party -matrixBlacklistedHostnames={{count}} 件がブラックリストと一致 -matrixSwitchNoMixedContent=混在コンテンツをブロック -matrixSwitchNoWorker=Web Worker をブロック -matrixSwitchReferrerSpoof=リファラの偽装 -matrixSwitchNoscriptSpoof=<code><noscript></code> タグの偽装 -matrixRevertAllEntry=すべての一時的な変更を元に戻す -matrixLoggerMenuEntry=Logger を開く -matrixDashboardMenuEntry=ダッシュボードを開く -matrixNoTabFound=ページが見つかりません -statsPageTitle=ηMatrix – 統計 -statsPageGenericStats=一般的な統計 -statsPageCookieHeadersFoiled=拒否した <a href='https://en.wikipedia.org/wiki/HTTP_cookie'>Cookie</a> の数: {{count}} -statsPageRefererHeadersFoiled=拒否した <a href='https://en.wikipedia.org/wiki/HTTP_referer'>リファラ</a> の数: {{count}} -statsPageHyperlinkAuditingFoiled=拒否した <a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>ハイパーリンク監査</a> の数: {{count}} -statsPageCookiesRemoved=削除した Cookie の数: {{count}} -statsPageLocalStoragesCleared=<a href='http://diveintohtml5.info/storage.html'>Local storage</a> を空にした数: {{count}} -statsPageBrowserCacheCleared=ブラウザキャッシュを消去した数: {{count}} -statsPageDetailedStats=詳細な統計 -statsPageDetailedAllPages=すべて -statsPageDetailedBehindTheScenePage=バックグラウンドリクエスト -statsPageOverview=概要 -statsPageRequests=リクエスト -statsPageAllowed=許可 -statsPageBlocked=ブロック中 -statsPageAll=すべて -statsPagePages=ページ -statsPageCookies=Cookie -statsPageCSS=CSS -statsPageImages=画像 -statsPagePlugins=Plugins -statsPageScripts=スクリプト -statsPageXHRs=XHRs -statsPageFrames=フレーム -statsPageOthers=その他 -statsPageDetailed=Logger -statsPageLogSizePrompt1=ページあたり直近の -statsPageLogSizePrompt2=<b>1ページあたり</b> の HTTP 要求 -statsPageLogSizeHelp=<p>Web ページ(下記参照)による直近の HTTP リクエストの詳細を調べることができます。</p><p>これは、Web ページが何をしていたかを正確に調べたい上級ユーザーにとってとても便利です。しかし、これらの HTTP リクエストをログに記録するのは多くのメモリーを必要とします。もしあなたがこの技術情報を必要としない場合、メモリーが浪費されています。</p><p>このフィールドではログに記録される直近の HTTP リクエストの上限を調整することができます。</p><p>ログ記録を無効化したい(そして <i>ηMatrix</i> のメモリー消費量を削減したい)場合は “<code>0</code>” を入力してください。</p> -statsPageRefresh=再読み込み -settingsPageTitle=ηMatrix – 設定 -settingsMatrixDisplayHeader=外観 -settingsMatrixDisplayTextSizePrompt=文字の大きさ: -settingsMatrixDisplayTextSizeNormal=標準 -settingsMatrixDisplayTextSizeLarge=大きい -settingsMatrixDisplayColorBlind=色覚障害の人に見やすい色で表示する -settingsMatrixConvenienceHeader=利便性 -settingsDefaultScopeLevel=デフォルトのスコープレベル: -settingsDefaultScopeLevel0=グローバル -settingsDefaultScopeLevel1=ドメイン -settingsDefaultScopeLevel2=サイト -settingsMatrixAutoReloadPrompt=Matrix を閉じたとき、これらのタブを再読み込みする: -settingsMatrixAutoReloadNone=なし -settingsMatrixAutoReloadCurrent=現在 -settingsMatrixAutoReloadAll=すべて -settingsMatrixAutoReloadInfo=1 ページ以上に影響を与える変更をしてから Matrix を閉じたときは、<i>ηMatrix</i> は影響をうけるページを再読み込みします -settingsSubframeColor=ブロック中のframe: Color -settingsSubframeOpacity=不透明度 -settingsIconBadgeEnabled=Show the number of blocked requests on the icon -settingsCollapseBlocked=ブロックした要素のプレースホルダを表示しない -settingsCollapseBlacklisted=明示的に拒否した要素のプレースホルダを表示しない -settingsNoscriptTagsSpoofed=訪れているサイトのスクリプトがブロックされている場合に <code><noscript></code> タグを偽装する -settingsCloudStorageEnabled=クラウドストレージのサポートを有効にする -privacyPageTitle=ηMatrix – プライバシー -privacyDeleteBlockedCookiesPrompt=ブロックした Cookie を削除する -privacyDeleteBlockedCookiesHelp=<p><i>ηMatrix</i> は、ブロックされる設定の Cookie であってもブラウザに入ってくることは許可し、出て行くことをブロックします(後者が本当に必要なことです)。ブラウザに入ってくるのを許可することで、そのサイトが Cookie を使おうとしていることをユーザが確認でき、さらにその内容を調べることもできます。</p><p><i>ηMatrix</i> でこれらの Cookie について確認したあと、必要であればそれらをブラウザから削除しても構いません。</p><p><b>重要な注意点:</b> ブラウザの拡張機能はその機能の一部として Web リクエストをおこなうことがあり、場合によってはブラウザ内に Cookie が保存されます。このオプションをオンにした場合、該当のホストを許可しておかないと <i>ηMatrix</i> によって Cookie が削除されます。拡張機能が通信するホストを許可しておくことを忘れないでください。</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=ブロックしていないセッション Cookie を削除する ( -privacyDeleteNonBlockedSessionCookiesPrompt2= 分間使用されていない場合) -privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “ブラウザを終了するとセッション Cookie は消去されます。セッション Cookie は一時的に保存され、ブラウザが閉じられた後には保持されません。”</p><p><a href='https://code.google.com/p/chromium/issues/detail?id=128513'>この動きをしない</a> ブラウザもあります。また、セッション Cookie を消去するためだけに、ブラウザを閉じたくないということがあるかもしれません。</p> -privacyDeleteBlockedLocalStoragePrompt=ブロックしているホストが保存した <a href='https://en.wikipedia.org/wiki/Web_storage'>Local storage</a> を削除する -privacyDeleteBlockedLocalStorageHelp=TODO -privacyClearCachePrompt1=ブラウザのキャッシュをクリアする( -privacyClearCachePrompt2=分おき) -privacyClearCacheHelp=<p>ユーザの行動を追跡するのに必死な Web サイトもあります。こうした Web サイトは行儀の悪い方法を使って、追跡されないようにするための対策を回避しようとします。</p><p>こうした手法の一部は、<a href='https://en.wikipedia.org/wiki/Web_cache'>ブラウザのキャッシュ</a>に依存 <sup>[1, 2]</sup> しています。なぜなら、ブラウザのキャッシュを消去する人はまれで、多くの場合に長期間にわたって残り続けるためです。</p><p>定期的にブラウザのキャッシュを消去することによる不都合はほとんどありません(あるとすれば、消去されるときユーザが気づかないということです)。メリットは、こうした不愉快なトラッカーによってあなたのプライバシーが侵害されるのを防げるという点です。</p><p>このオプションを設定することで、任意の間隔で <i>ηMatrix</i> がブラウザのキャッシュを消去するようになります。</p><p>[1] <a href='https://grepular.com/Preventing_Web_Tracking_via_the_Browser_Cache'>“Preventing Web Tracking via the Browser Cache”</a>[2] <a href='http://lucb1e.com/rp/cookielesscookies/'>“Cookieless cookies”</a></p> -privacyProcessRefererPrompt=サードパーティーリクエストの <a href='https://en.wikipedia.org/wiki/HTTP_referer'>HTTP リファラ</a> を偽装する -privacyProcessRefererHelp=Wikipedia から引用:<blockquote>HTTP リファラは、要求しているリソースにリンクしたウェブページのアドレスを識別する HTTP ヘッダのフィールドです。<b>リファラはプライバシーを侵害するおそれがあるため、一部の Web ブラウザでは、ユーザーがリファラの送信を無効にすることができます</b>。</blockquote>この設定をオンにすると、HTTP リファラのドメイン名がアクセスしている Web サイトのドメイン名と異なる場合(サードパーティリクエストである場合)、<i>ηMatrix</i> は HTTP リファラを偽装します。 -privacyNoMixedContentPrompt=厳密な HTTPS: 混在コンテンツをブロックする -privacyNoMixedContentHelp=<p><a href='https://developer.mozilla.org/ja/docs/Security/%E6%B7%B7%E5%9C%A8%E3%82%B3%E3%83%B3%E3%83%86%E3%83%B3%E3%83%84'>Mozilla Developer Network</a> から引用:</p><blockquote>HTTPS のページの中に平文の HTTP で送られてくるコンテンツが含まれている場合、混在コンテンツと呼ばれます。このようなページは部分的にしか暗号化されておらず、盗聴者や中間者攻撃者が暗号化されていないコンテンツにアクセスできてしまいます。つまり、ページは安全ではありません。</blockquote> -privacyProcessHyperlinkAuditingPrompt=すべての <a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>ハイパーリンク監査</a> を拒否する -privacyProcessHyperlinkAuditingHelp=<p>ハイパーリンクの監査は、ユーザーが特定の Web ページ上でどのリンクをクリックしたかを <b>不特定の誰か</b> に通知することを可能にする仕組みです。これは本質的にトラッキングの機能です。あなたがあるリンクをクリックしたとき、それを Web サイト(または第三者)に通知します。この機能の唯一の目的は、あなたのブラウジングを追跡することです。</p> -userRulesPermanentHeader=永続的なルール -userRulesTemporaryHeader=一時的なルール -userRulesRevert=元に戻す -userRulesCommit=コミット -userRulesEdit=編集 -userRulesEditSave=保存 -userRulesEditDicard=破棄 -userRulesImport=ファイルからインポート... -userRulesExport=ファイルへエクスポート... -userRulesFormatHint=ルールの構文については、このページを参照してください。 -userRulesDefaultFileName=my-ematrix-rules.txt -hostsFilesPrompt=ホストファイルに記載されたすべてのホストへの、あらゆるリクエストはブロックされます。 -hostsFilesStats={{blockedHostnameCount}} 件のホストをブロックしています: -hostsFilesPerFileStats={{total}} 件のうち {{used}} 件を使用中 -hostsFilesLastUpdate=最終更新日: {{ago}} -hostsFilesApplyChanges=変更を適用する -hostsFilesAutoUpdatePrompt=ホストファイルを自動で更新する -hostsFilesUpdateNow=今すぐアップデート -hostsFilesPurgeAll=すべてのキャッシュをクリア -hostsFilesExternalListsHint=1 行にひとつずつ記述してください。‘#’ で始まる行は無視されます。無効な URL は警告なしに無視されます。 -hostsFilesExternalListsParse=読み込む -hostsFilesExternalListPurge=キャッシュのクリア -hostsFilesExternalListNew=新しいバージョンを利用できます -hostsFilesExternalListObsolete=古い -rawSettingsWarning=警告! これらの内部設定はご自身のリスクにより変更すること。 -aboutChangelog=変更履歴 -aboutStorageUsed=使用中のストレージ: {{storageUsed}} bytes -aboutDoc=ドキュメント -aboutPermissions=パーミッションについて -aboutCode=ソースコード (GPLv3) -aboutIssues=バグや問題点 -aboutContributors=協力者 -aboutCodeContributors=ソースコード: -aboutIssueContributors=問題点: -aboutTranslationContributors=翻訳: -aboutUserDataHeader=データ -aboutBackupButton=ファイルにバックアップ... -aboutBackupFilename=my-ematrix-backup.txt -aboutRestoreButton=ファイルから復元... -aboutRestoreConfirm=すべての設定は {{time}} のバックアップデータで上書きされ、ηMatrix が再起動します。\n\nバックアップデータで上書きしますか? -aboutRestoreError=データを読み込めなかったか、無効なデータです -aboutOr=... もしくは ... -aboutResetButton=初期設定に戻す -aboutResetConfirm=注意! 設定はすべて削除されます。続行してもよろしいですか? -loggerFilterInputPlaceholder=フィルタする -loggerMaxEntriesTip=エントリの最大数 -loggerEntryCookieDeleted=削除した Cookie:{{value}} -loggerEntryDeleteCookieError=Cookie の削除に失敗しました:{{value}} -loggerEntryBrowserCacheCleared=ブラウザのキャッシュを削除しました -loggerEntryAssetUpdated=リソースを更新しました:{{value}} -mainBlockedPrompt1=ηMatrix はこのページの読み込みをブロックしています: -mainBlockedPrompt2=以下のルールに従う -mainBlockedBack=戻る -mainBlockedClose=閉じる -commandRevertAll=すべての一時的な変更を元に戻す -commandWhitelistPageDomain=このページのドメインを一時的にホワイトリストに登録する -commandWhitelistAll=一時的にすべてホワイトリストに登録 -commandOpenDashboard=ダッシュボードを開く -elapsedOneMinuteAgo=1 分前 -elapsedManyMinutesAgo={{value}} 分前 -elapsedOneHourAgo=1 時間前 -elapsedManyHoursAgo={{value}} 時間前 -elapsedOneDayAgo=1 日前 -elapsedManyDaysAgo={{value}} 日前 -showDashboardButton=ダッシュボード -showLoggerButton=Logger -cloudPush=クラウドストレージにエクスポート -cloudPull=クラウドストレージからインポート -cloudNoData=...\n... -cloudDeviceNamePrompt=このデバイスの名称: -genericSubmit=登録する -genericRevert=元に戻す -errorCantConnectTo=ネットワークエラー: {{url}} に接続できません -genericApplyChanges=変更を適用 -noscriptSpoofHelp=<p>ブラウザーがスクリプトをサポートしていない場合、Webページは <noscript> タグを使用して一部のコンテンツを表示できます。 たとえば、一部のWebサイトはユーザーを “scriptless” バージョンにリダイレクトします</p><p>ηMatrixがスクリプトをブロックしても、このオプションが選択されていない限り、ブラウザーはスクリプト実行をサポートするものとして自身をアドバタイズします。</p><p>ηMatrixを選択すると、ブラウザがスクリプトをサポートしていないことをWebサイトに通知します。これは、ファーストパーティのスクリプトをブロックしている場合に確実に実行したいことです。 そのため、<noscript> タグは意図したとおりに機能します。</p><p>ファーストパーティのスクリプトがブロックされているときにこのオプションを選択しないと、スクリプトレスバージョンにリダイレクトすることを意図している場合、Webサイトが不可解に壊れます。</p> -noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can display some content by using the <noscript> tag. For example, some websites will redirect users to a “scriptless” version.</p><p>When ηMatrix blocks scripts, the browser will still advertise itself as supporting script execution unless this option is selected.</p><p>When selected, ηMatrix will tell the website that the browser does not support scripts, which is what you definitely want to do if you are blocking 1st-party scripts. As such, the <noscript> tag will work as intended.</p><p>Not selecting this option when 1st-party scripts are blocked means the website will break misteryously in case it is meant to redirect to a scriptless version.</p> -settingsUpdateIcon=Do not change the toolbar icon -updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> -resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> diff --git a/locale/ko/messages.properties b/locale/ko/messages.properties index dd926ba..a5d23be 100644 --- a/locale/ko/messages.properties +++ b/locale/ko/messages.properties @@ -91,7 +91,7 @@ settingsCloudStorageEnabled=클라우드 저장소 활성화 privacyPageTitle=ηMatrix – Privacy privacyDeleteBlockedCookiesPrompt=차단된 쿠키 삭제 privacyDeleteBlockedCookiesHelp=<p>Blacklisted cookies are not prevented by <i>ηMatrix</i> from entering your browser. However they are prevented from leaving your browser, which is what really matters. Not blocking cookies before they enter your browser gives you the opportunity to be informed that a site tried to use cookies, and furthermore to inspect their contents if you wish.</p><p>Once these blacklisted cookies have been accounted for by <i>ηMatrix</i>, they can be removed from your browser if you wish so.</p><p><b>Important note:</b> Extensions can make web requests during the course of their normal operation. These requests can result in cookies being created in the browser. If the hostname from where a cookie originate is not whitelisted, the cookie will be removed from the browser by <i>ηMatrix</i> if this option is checked. So be sure that the hostname(s) with which an extension communicate is whitelisted.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=차단되지 않은 세션 쿠키 삭제 +privacyDeleteNonBlockedSessionCookiesPrompt1=차단되지 않은 세션 쿠키 삭제 privacyDeleteNonBlockedSessionCookiesPrompt2= 분 동안 사용되지 않은 경우 privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “A session cookie ... is erased when you end the browser session. The session cookie is stored in temporary memory and is not retained after the browser is closed.”</p><p>Except that this <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>might not be happening</a> in some browsers. Also, to some, having to close the browser in order for the session cookies to clear might not be early enough.</p> privacyDeleteBlockedLocalStoragePrompt=차단 호스트 이름으로 설정된 <a href='https://en.wikipedia.org/wiki/Web_storage'>로컬 저장소</a> 삭제 @@ -115,7 +115,7 @@ userRulesEditDicard=삭제 userRulesImport=파일에서 가져오기 userRulesExport=파일로 내보내기... userRulesFormatHint=See this page for rule syntax. -userRulesDefaultFileName=my-ematrix-rules.txt +userRulesDefaultFileName=my-umatrix-rules.txt hostsFilesPrompt=호스트 파일에있는 도메인은 글로벌 블랙리스트에 포함됩니다. hostsFilesStats=차단된 호스트 네임: {{blockedHostnameCount}} hostsFilesPerFileStats={{total}} 개 중 {{used}} 개 사용 중 @@ -124,7 +124,7 @@ hostsFilesApplyChanges=변경사항 적용 hostsFilesAutoUpdatePrompt=호스트 파일 자동 업데이트 hostsFilesUpdateNow=지금 업데이트하기 hostsFilesPurgeAll=케시 초기화 -hostsFilesExternalListsHint=한 줄에 하나의 URL. 시작이 ‘#’ 일 경우 적용되지 않습니다. 유효하지 않은 URL은 자동으로 무시됩니다. +hostsFilesExternalListsHint=<p>One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored.</p><p>The inserted URL must point to a hosts file (including local files); do not use the hosts file syntax here.</p> hostsFilesExternalListsParse=읽기 hostsFilesExternalListPurge=케시 지우기 hostsFilesExternalListNew=새로운 버전이 나왔습니다 @@ -142,7 +142,7 @@ aboutIssueContributors=이슈: aboutTranslationContributors=번역: aboutUserDataHeader=사용자 데이터 aboutBackupButton=파일로 백업하기... -aboutBackupFilename=my-ematrix-backup.txt +aboutBackupFilename=my-umatrix-backup.txt aboutRestoreButton=파일에서 복원... aboutRestoreConfirm={{time}} 에 백업된 데이터가 모든 설정을 덮어쓰기한 뒤, ηMatrix이 재시작합니다.\n\n존재하는 모든 설정을 백업 데이터로 덮어쓰시겠습니까? aboutRestoreError=데이터를 읽을 수 없거나 유효하지 않습니다. @@ -183,4 +183,6 @@ noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can dis settingsUpdateIcon=Do not change the toolbar icon updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +resolveCnameHelp=<p>When resolving an address with DNS, some webistes use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +settingsTextSmaller=Smaller +settingsTextBigger=Bigger diff --git a/locale/lv/messages.properties b/locale/lv/messages.properties deleted file mode 100644 index d15c215..0000000 --- a/locale/lv/messages.properties +++ /dev/null @@ -1,186 +0,0 @@ -extName=ηMatrix -dashboardPageName=ηMatrix — Vadības panelis -loggerPageName=ηMatrix — Logger -settingsPageName=Iestatījumi -privacyPageName=Konfidencialitāte -statsPageName=Statistika -userRulesPageName=Mani noteikumi -ubiquitousRulesPageName=Hostu faili -rawSettingsPageName=More -aboutPageName=Par -allPrettyName=viss -cookiePrettyName=sīkdatne -cssPrettyName=css -imagePrettyName=attēls -mediaPrettyName=media -pluginPrettyName=spraudnis -scriptPrettyName=skripts -xhrPrettyName=XHR -framePrettyName=kadrs -otherPrettyName=cits -matrixNoNetTrafficPrompt=No net traffic seen for this tab so far. -matrixMtxButtonTip=Disable/enable matrix filtering for this scope. -matrixPersistButtonTip=Save all temporary changes for this scope. -matrixRevertButtonTip=Revert temporary changes for this scope. -matrixReloadButton=Reload the page.\nPress Shift to bypass the browser cache. -matrixScopeTip=Change to global scope. -matrixSwitchesTip=Dropdown menu with additional settings. -matrix1stPartyLabel=1st-party -matrixBlacklistedHostnames={{count}} blacklisted hostname(s) -matrixSwitchNoMixedContent=Forbid mixed content -matrixSwitchNoWorker=Forbid web workers -matrixSwitchReferrerSpoof=Spoof <code>Referer</code> header -matrixSwitchNoscriptSpoof=Spoof <code><noscript></code> tags -matrixRevertAllEntry=Revert all temporary changes -matrixLoggerMenuEntry=Go to logger -matrixDashboardMenuEntry=Go to dashboard -matrixNoTabFound=No web page found -statsPageTitle=ηMatrix – Statistics -statsPageGenericStats=Generic statistics -statsPageCookieHeadersFoiled=<a href='https://en.wikipedia.org/wiki/HTTP_cookie'>HTTP cookie</a> headers foiled: {{count}} -statsPageRefererHeadersFoiled=<a href='https://en.wikipedia.org/wiki/HTTP_referer'>HTTP referer</a> headers foiled: {{count}} -statsPageHyperlinkAuditingFoiled=<a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>Hyperlink auditing</a> attempts foiled: {{count}} -statsPageCookiesRemoved=Local cookies removed: {{count}} -statsPageLocalStoragesCleared=<a href='http://diveintohtml5.info/storage.html'>Local storages</a> emptied: {{count}} -statsPageBrowserCacheCleared=Browser caches cleared: {{count}} -statsPageDetailedStats=Detailed statistics -statsPageDetailedAllPages=Viss -statsPageDetailedBehindTheScenePage=Behind the scene -statsPageOverview=Pārskats -statsPageRequests=Pieprasījumi -statsPageAllowed=Atļauts -statsPageBlocked=Bloķēts -statsPageAll=Viss -statsPagePages=Lapas -statsPageCookies=Sīkdatnes -statsPageCSS=CSS -statsPageImages=Attēli -statsPagePlugins=Spraudņi -statsPageScripts=Skripti -statsPageXHRs=XHRs -statsPageFrames=Rāmji -statsPageOthers=Citi -statsPageDetailed=Pieprasījumu žurnāls -statsPageLogSizePrompt1=Atcerēties pēdējo -statsPageLogSizePrompt2=HTTP pieprasījumi <b>pa lapai</b>. -statsPageLogSizeHelp=<p>You can inspect details of the most recent raw HTTP requests which have been made by a web page (see below).</p><p>This is mostly useful to advanced users who want to investigate exactly what a web page has been doing. But logging these HTTP requests requires memory, and if you don't care about this technical information, then memory is being wasted.</p><p>Hence this field which lets you adjust the maximum number of the most recent HTTP requests which are to be logged for further inspection.</p><p>Enter “<code>0</code>” to turn off detailed logging (and consequently reduce the memory footprint of <i>ηMatrix</i>).</p> -statsPageRefresh=Atjaunot -settingsPageTitle=ηMatrix – Iestatījumi -settingsMatrixDisplayHeader=Izskats -settingsMatrixDisplayTextSizePrompt=Teksta lielums: -settingsMatrixDisplayTextSizeNormal=Normāls -settingsMatrixDisplayTextSizeLarge=Liels -settingsMatrixDisplayColorBlind=Daltoniķiem draudzīgs -settingsMatrixConvenienceHeader=Convenience -settingsDefaultScopeLevel=Default scope level: -settingsDefaultScopeLevel0=Global -settingsDefaultScopeLevel1=Domain -settingsDefaultScopeLevel2=Site -settingsMatrixAutoReloadPrompt=When the matrix is closed, smart reload these tabs: -settingsMatrixAutoReloadNone=Neviens -settingsMatrixAutoReloadCurrent=Current -settingsMatrixAutoReloadAll=All -settingsMatrixAutoReloadInfo=Whenever you make changes in the matrix which can affect the display and/or behavior of one or more pages, <i>ηMatrix</i> will reload affected pages automatically when you close the matrix. -settingsSubframeColor=Blocked frames: Color -settingsSubframeOpacity=Necaurredzamība -settingsIconBadgeEnabled=Show the number of blocked requests on the icon -settingsCollapseBlocked=Collapse placeholder of blocked elements -settingsCollapseBlacklisted=Collapse placeholder of blacklisted elements -settingsNoscriptTagsSpoofed=Spoof <code><noscript></code> tags when 1st-party scripts are blocked -settingsCloudStorageEnabled=Enable cloud storage support -privacyPageTitle=ηMatrix – Konfidencialitāte -privacyDeleteBlockedCookiesPrompt=Delete blocked cookies. -privacyDeleteBlockedCookiesHelp=<p>Blacklisted cookies are not prevented by <i>ηMatrix</i> from entering your browser. However they are prevented from leaving your browser, which is what really matters. Not blocking cookies before they enter your browser gives you the opportunity to be informed that a site tried to use cookies, and furthermore to inspect their contents if you wish.</p><p>Once these blacklisted cookies have been accounted for by <i>ηMatrix</i>, they can be removed from your browser if you wish so.</p><p><b>Important note:</b> Extensions can make web requests during the course of their normal operation. These requests can result in cookies being created in the browser. If the hostname from where a cookie originate is not whitelisted, the cookie will be removed from the browser by <i>ηMatrix</i> if this option is checked. So be sure that the hostname(s) with which an extension communicate is whitelisted.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Delete non-blocked session cookies -privacyDeleteNonBlockedSessionCookiesPrompt2= minutes after the last time they have been used. -privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “A session cookie ... is erased when you end the browser session. The session cookie is stored in temporary memory and is not retained after the browser is closed.”</p><p>Except that this <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>might not be happening</a> in some browsers. Also, to some, having to close the browser in order for the session cookies to clear might not be early enough.</p> -privacyDeleteBlockedLocalStoragePrompt=Delete <a href='https://en.wikipedia.org/wiki/Web_storage'>local storage</a> content set by blocked hostnames -privacyDeleteBlockedLocalStorageHelp=TODO -privacyClearCachePrompt1=Clear browser cache every -privacyClearCachePrompt2=minūtes. -privacyClearCacheHelp=<p>Some web sites are really bent on tracking you, so much that they will use not-so-nice tricks to work around whatever measures you take in order to not be tracked.</p><p>A few of these tricks rely<sup>[1, 2]</sup> on the <a href='https://en.wikipedia.org/wiki/Web_cache'>browser cache</a>, which content is often long lasting since rarely will users take the time to regularly clear their browser cache.</p><p>There is little inconvenience to clear the browser cache regularly (likelihood is that you won't notice when it happens), and the benefit is to prevent these obnoxious trackers from invading your privacy.</p><p>Check this option to have <i>ηMatrix</i> do it for you, at the interval you wish.</p><p>[1] <a href='https://grepular.com/Preventing_Web_Tracking_via_the_Browser_Cache'>“Preventing Web Tracking via the Browser Cache”</a>\n[2] <a href='http://lucb1e.com/rp/cookielesscookies/'>“Cookieless cookies”</a></p> -privacyProcessRefererPrompt=Spoof <a href='https://en.wikipedia.org/wiki/HTTP_referer'>HTTP referrer</a> string of third-party requests. -privacyProcessRefererHelp=From Wikipedia:<blockquote>HTTP referer is an HTTP header field that identifies the address of the webpage that linked to the resource being requested. ... <b>Because referer information can violate privacy, some web browsers allow the user to disable the sending of referer information.</b></blockquote>If this setting is checked, <i>ηMatrix</i> will spoof the HTTP referrer information if the domain name of the HTTP referrer is third-party to the domain name of net request. -privacyNoMixedContentPrompt=Strict HTTPS: forbid mixed content. -privacyNoMixedContentHelp=<p>From <a href='https://developer.mozilla.org/en-US/docs/Security/MixedContent'>Mozilla Developer Network</a>:</p><blockquote>If [a] HTTPS page includes content retrieved through regular, cleartext HTTP, then the connection is only partially encrypted: the unencrypted content is accessible to sniffers and can be modified by man-in-the-middle attackers, and therefore the connection is not safeguarded anymore. When a webpage exhibits this behavior, it is called a mixed content page.</blockquote> -privacyProcessHyperlinkAuditingPrompt=Block all <a href='https://html.spec.whatwg.org/multipage/semantics.html#hyperlink-auditing'>hyperlink auditing</a> attempts. -privacyProcessHyperlinkAuditingHelp=<p>Hyperlink auditing is a mechanism which allow a party, <b>any party</b>, to be informed about which link a user clicked on a particular web page. It is essentially a tracking feature: it allows a web site, or any third-party to that web site, to be informed about which link you clicked on which one of its web pages. The sole purpose is to track your browsing activity.</p> -userRulesPermanentHeader=Permanent rules -userRulesTemporaryHeader=Temporary rules -userRulesRevert=Atgriezt -userRulesCommit=Commit -userRulesEdit=Rediģēt -userRulesEditSave=Saglabāt -userRulesEditDicard=Atcelt -userRulesImport=Import from file... -userRulesExport=Eksportēt uz failu... -userRulesFormatHint=Apskatīt šo lapu priekš noteikumu sintakses. -userRulesDefaultFileName=mani-ematriksa-noteikumi.txt -hostsFilesPrompt=All hostnames in a hosts file are loaded as blacklisted hostnames in the global scope. -hostsFilesStats={{blockedHostnameCount}} distinct blocked hostnames from: -hostsFilesPerFileStats={{used}} izmantoti no kopējiem {{total}} -hostsFilesLastUpdate=Last update: {{ago}} -hostsFilesApplyChanges=Lietot izmaiņas -hostsFilesAutoUpdatePrompt=Automātiski atjaunot resursdatora failus. -hostsFilesUpdateNow=Atjaunināt tagad -hostsFilesPurgeAll=Iztīrīt visas kešatmiņas -hostsFilesExternalListsHint=One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored. -hostsFilesExternalListsParse=Parsēt -hostsFilesExternalListPurge=Iztīrīt kešatmiņu -hostsFilesExternalListNew=pieejama jauna versija -hostsFilesExternalListObsolete=novecojis -rawSettingsWarning=Warning! Change these raw configuration settings at your own risk. -aboutChangelog=Izmaiņu žurnāls -aboutStorageUsed=Izmantotā atmiņa: {{storageUsed}} baiti -aboutDoc=Dokumentācija -aboutPermissions=Atļaujas -aboutCode=Pirmkods (GPLv3) -aboutIssues=Kļūdas un problēmas -aboutContributors=Atbalstītāji -aboutCodeContributors=Kods: -aboutIssueContributors=Problēmas: -aboutTranslationContributors=Tulkojumi: -aboutUserDataHeader=Jūsu dati -aboutBackupButton=Dublēt uz failu... -aboutBackupFilename=mana-ematriksa-rezerves-kopija.txt -aboutRestoreButton=Atjaunot no faila... -aboutRestoreConfirm=Visi jūsu iestatījumi tiks pārrakstīti izmantojot rezerves kopijas datus {{time}} and µMatriks tiks restartēts.\n\nPārrakstīt visus esošos iestatījumus izmantojot rezerves kopijas datus? -aboutRestoreError=Datus nevarēja nolasīt vai tie ir nederīgi -aboutOr=... vai ... -aboutResetButton=Atgriezt noklusējuma iestatījumus -aboutResetConfirm=Uzmanību! tiks atcelti visi jūsu izveidotie iestatījumi. Vai vēlaties turpināt? -loggerFilterInputPlaceholder=filter expression(s) -loggerMaxEntriesTip=Maximum number of entries -loggerEntryCookieDeleted=cookie deleted: {{value}} -loggerEntryDeleteCookieError=failed to delete cookie: {{value}} -loggerEntryBrowserCacheCleared=browser cache cleared -loggerEntryAssetUpdated=asset updated: {{value}} -mainBlockedPrompt1=ηMatrix has prevented the following page from loading: -mainBlockedPrompt2=Because of the following rule -mainBlockedBack=Go back -mainBlockedClose=Close -commandRevertAll=Atcelt visas pagaidu izmaiņas -commandWhitelistPageDomain=Uz laiku atļaut web lapas domēnu -commandWhitelistAll=Uz laiku atļaut visu -commandOpenDashboard=Atvērt vadības paneli -elapsedOneMinuteAgo=a minute ago -elapsedManyMinutesAgo={{value}} minutes ago -elapsedOneHourAgo=an hour ago -elapsedManyHoursAgo={{value}} hours ago -elapsedOneDayAgo=a day ago -elapsedManyDaysAgo={{value}} days ago -showDashboardButton=Dashboard -showLoggerButton=Logger -cloudPush=Export to cloud storage -cloudPull=Import from cloud storage -cloudNoData=...\n... -cloudDeviceNamePrompt=This device name: -genericSubmit=Submit -genericRevert=Revert -errorCantConnectTo=Tīkla kļūda: Nespēja savienoties ar {{url}} -genericApplyChanges=Apply changes -noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can display some content by using the <noscript> tag. For example, some websites will redirect users to a “scriptless” version.</p><p>When ηMatrix blocks scripts, the browser will still advertise itself as supporting script execution unless this option is selected.</p><p>When selected, ηMatrix will tell the website that the browser does not support scripts, which is what you definitely want to do if you are blocking 1st-party scripts. As such, the <noscript> tag will work as intended.</p><p>Not selecting this option when 1st-party scripts are blocked means the website will break misteryously in case it is meant to redirect to a scriptless version.</p> -settingsUpdateIcon=Do not change the toolbar icon -updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> -resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> diff --git a/locale/ml/messages.properties b/locale/ml/messages.properties deleted file mode 100644 index 5790d17..0000000 --- a/locale/ml/messages.properties +++ /dev/null @@ -1,186 +0,0 @@ -extName=ηMatrix -dashboardPageName=യുമാട്രിക്സ് — ഡാഷ്ബോര്ഡ് -loggerPageName=ηMatrix — Logger -settingsPageName=സെറ്റിംഗ്സ് -privacyPageName=പ്രൈവസി -statsPageName=സ്റ്ററ്റിസ്റ്റിക്സ് -userRulesPageName=എന്റെ നിയമങ്ങള് -ubiquitousRulesPageName=ഹോസ്റ്റ് ഫയലുകള് -rawSettingsPageName=More -aboutPageName=യുമാട്രിക്സിനെ കുറിച്ച് -allPrettyName=എല്ലാം -cookiePrettyName=കുക്കി -cssPrettyName=സിഎസ്എസ് -imagePrettyName=ചിത്രം -mediaPrettyName=media -pluginPrettyName=പ്ലഗ്ഗിന് -scriptPrettyName=സ്ക്രിപ്റ്റ് -xhrPrettyName=എക്സ്എച്ച്ആര് -framePrettyName=ഫ്രെയിം -otherPrettyName=മറ്റുള്ളവ -matrixNoNetTrafficPrompt=ഈ ടാബില് ഇതുവരെ ഒരു ഗതാഗതവും ഉണ്ടായിട്ടില്ല. -matrixMtxButtonTip=ഈ സ്കോപ്പില് മാട്രിക്സ് ഫില്ട്ടറിംഗ് എനേബിള്/ഡിസേബിള് ചെയ്യുക. -matrixPersistButtonTip=ഈ സ്കോപ്പിലെ എല്ലാ താത്കാലിക മാറ്റങ്ങളും സൂക്ഷിക്കുക. -matrixRevertButtonTip=ഈ സ്കോപ്പിലെ എല്ലാ താത്കാലിക മാറ്റങ്ങളും ഉപേക്ഷിക്കുക. -matrixReloadButton=പേജ് ഒന്നു കൂടി ലോഡ് ചെയ്യുക. -matrixScopeTip=Change to global scope. -matrixSwitchesTip=Dropdown menu with additional settings. -matrix1stPartyLabel=ഒന്നാം കക്ഷി -matrixBlacklistedHostnames={{count}} കരിംപട്ടികയില് ഉള്ള ഹോസ്റ്റുകള് -matrixSwitchNoMixedContent=സ്ട്രിക്റ്റ് എച്ച്ടിടിപിഎസ് -matrixSwitchNoWorker=Forbid web workers -matrixSwitchReferrerSpoof=റഫറര് അനുകരണം -matrixSwitchNoscriptSpoof=Spoof <code><noscript></code> tags -matrixRevertAllEntry=എല്ലാ താത്കാലിക മാറ്റങ്ങളും ഉപേക്ഷിക്കുക -matrixLoggerMenuEntry=ലോഗ്ഗറിലേക്ക് പോകുക -matrixDashboardMenuEntry=ഡാഷ്ബോര്ഡിലേക്ക് പോകുക -matrixNoTabFound=No web page found -statsPageTitle=യുമാട്രിക്സ് – സ്റ്ററ്റിസ്റ്റിക്സ് -statsPageGenericStats=ജനറിക്ക് സ്റ്ററ്റിസ്റ്റിക്സ് -statsPageCookieHeadersFoiled=<a href='https://en.wikipedia.org/wiki/HTTP_cookie'>എച്ച്റ്റിറ്റിപി കുക്കി</a> തടഞ്ഞ ഹെഡറുകള്: {{count}} -statsPageRefererHeadersFoiled=തടഞ്ഞ <a href='https://en.wikipedia.org/wiki/HTTP_referer'>എച്ച്റ്റിറ്റിപി</a> ഹെഡറുകള്:{{count}} -statsPageHyperlinkAuditingFoiled=തടഞ്ഞ <a href='http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#hyperlink-auditing'>ഹൈപ്പര്ലിങ്ക് ഓടിറ്റിംഗ്</a> ശ്രമങ്ങള്: {{count}} -statsPageCookiesRemoved=തുടച്ചുനീക്കിയ ലോക്കല് കുക്കികള്: {{count}} -statsPageLocalStoragesCleared=കാലിയാക്കപ്പെട്ട<a href='http://diveintohtml5.info/storage.html'>ലോക്കല് സ്റ്റോറെജ്</a>:{{count}} -statsPageBrowserCacheCleared=ക്ലിയര് ചെയ്യപ്പെട്ട ബ്രൌസര് കാഷ്: {{count}} -statsPageDetailedStats=വിശദമായ സ്റ്ററ്റിസ്റ്റിക്സ് -statsPageDetailedAllPages=എല്ലാം -statsPageDetailedBehindTheScenePage=സീനിനു പിന്നില് -statsPageOverview=ഓവര്വ്യൂ -statsPageRequests=അപേക്ഷകള് -statsPageAllowed=അനുവദനീയമായവ -statsPageBlocked=തടഞ്ഞിരിക്കുന്നവ -statsPageAll=എല്ലാം -statsPagePages=പേജുകള് -statsPageCookies=കുക്കികള് -statsPageCSS=സിഎസ്എസ് -statsPageImages=ചിത്രങ്ങള് -statsPagePlugins=പ്ലഗ്ഗിന്നുകള് -statsPageScripts=സ്ക്രിപ്റ്റുകള് -statsPageXHRs=എക്സ്എച്ച്ആറുകള് -statsPageFrames=ഫ്രെയിമുകള് -statsPageOthers=മറ്റുള്ളവ -statsPageDetailed=ലോഗ്ഗര് -statsPageLogSizePrompt1=Remember the last -statsPageLogSizePrompt2=HTTP requests <b>per page</b>. -statsPageLogSizeHelp=<p>You can inspect details of the most recent raw HTTP requests which have been made by a web page (see below).</p><p>This is mostly useful to advanced users who want to investigate exactly what a web page has been doing. But logging these HTTP requests requires memory, and if you don't care about this technical information, then memory is being wasted.</p><p>Hence this field which lets you adjust the maximum number of the most recent HTTP requests which are to be logged for further inspection.</p><p>Enter “<code>0</code>” to turn off detailed logging (and consequently reduce the memory footprint of <i>ηMatrix</i>).</p> -statsPageRefresh=Refresh -settingsPageTitle=ηMatrix – Settings -settingsMatrixDisplayHeader=Matrix -settingsMatrixDisplayTextSizePrompt=Text size: -settingsMatrixDisplayTextSizeNormal=Normal -settingsMatrixDisplayTextSizeLarge=Large -settingsMatrixDisplayColorBlind=Color-blind friendly -settingsMatrixConvenienceHeader=Convenience -settingsDefaultScopeLevel=Default scope level: -settingsDefaultScopeLevel0=Global -settingsDefaultScopeLevel1=Domain -settingsDefaultScopeLevel2=Site -settingsMatrixAutoReloadPrompt=When the matrix is closed, smart reload these tabs: -settingsMatrixAutoReloadNone=ഒന്നും അല്ല -settingsMatrixAutoReloadCurrent=ഇപ്പോഴത്തെത് -settingsMatrixAutoReloadAll=എല്ലാം -settingsMatrixAutoReloadInfo=Whenever you make changes in the matrix which can affect the display and/or behavior of one or more pages, <i>ηMatrix</i> will reload affected pages automatically when you close the matrix. -settingsSubframeColor=Blocked frames: Color -settingsSubframeOpacity=ഒപ്പാസിറ്റി -settingsIconBadgeEnabled=Show the number of blocked requests on the icon -settingsCollapseBlocked=Collapse placeholder of blocked elements -settingsCollapseBlacklisted=Collapse placeholder of blacklisted elements -settingsNoscriptTagsSpoofed=Spoof <code><noscript></code> tags when 1st-party scripts are blocked -settingsCloudStorageEnabled=Enable cloud storage support -privacyPageTitle=ηMatrix – Privacy -privacyDeleteBlockedCookiesPrompt=Delete blocked cookies. -privacyDeleteBlockedCookiesHelp=<p>Blacklisted cookies are not prevented by <i>ηMatrix</i> from entering your browser. However they are prevented from leaving your browser, which is what really matters. Not blocking cookies before they enter your browser gives you the opportunity to be informed that a site tried to use cookies, and furthermore to inspect their contents if you wish.</p><p>Once these blacklisted cookies have been accounted for by <i>ηMatrix</i>, they can be removed from your browser if you wish so.</p><p><b>Important note:</b> Extensions can make web requests during the course of their normal operation. These requests can result in cookies being created in the browser. If the hostname from where a cookie originate is not whitelisted, the cookie will be removed from the browser by <i>ηMatrix</i> if this option is checked. So be sure that the hostname(s) with which an extension communicate is whitelisted.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Delete non-blocked session cookies -privacyDeleteNonBlockedSessionCookiesPrompt2= minutes after the last time they have been used. -privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “A session cookie ... is erased when you end the browser session. The session cookie is stored in temporary memory and is not retained after the browser is closed.”</p><p>Except that this <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>might not be happening</a> in some browsers. Also, to some, having to close the browser in order for the session cookies to clear might not be early enough.</p> -privacyDeleteBlockedLocalStoragePrompt=Delete <a href='https://en.wikipedia.org/wiki/Web_storage'>local storage</a> content set by blocked hostnames -privacyDeleteBlockedLocalStorageHelp=ചെയ്യാനുള്ളവ -privacyClearCachePrompt1=Clear browser cache every -privacyClearCachePrompt2=മിനിറ്റുകള്. -privacyClearCacheHelp=<p>Some web sites are really bent on tracking you, so much that they will use not-so-nice tricks to work around whatever measures you take in order to not be tracked.</p><p>A few of these tricks rely<sup>[1, 2]</sup> on the <a href='https://en.wikipedia.org/wiki/Web_cache'>browser cache</a>, which content is often long lasting since rarely will users take the time to regularly clear their browser cache.</p><p>There is little inconvenience to clear the browser cache regularly (likelihood is that you won't notice when it happens), and the benefit is to prevent these obnoxious trackers from invading your privacy.</p><p>Check this option to have <i>ηMatrix</i> do it for you, at the interval you wish.</p><p>[1] <a href='https://grepular.com/Preventing_Web_Tracking_via_the_Browser_Cache'>“Preventing Web Tracking via the Browser Cache”</a>\n[2] <a href='http://lucb1e.com/rp/cookielesscookies/'>“Cookieless cookies”</a></p> -privacyProcessRefererPrompt=Spoof <a href='https://en.wikipedia.org/wiki/HTTP_referer'>HTTP referrer</a> string of third-party requests. -privacyProcessRefererHelp=From Wikipedia:<blockquote>HTTP referer is an HTTP header field that identifies the address of the webpage that linked to the resource being requested. ... <b>Because referer information can violate privacy, some web browsers allow the user to disable the sending of referer information.</b></blockquote>If this setting is checked, <i>ηMatrix</i> will spoof the HTTP referrer information if the domain name of the HTTP referrer is third-party to the domain name of net request. -privacyNoMixedContentPrompt=Strict HTTPS: forbid mixed content. -privacyNoMixedContentHelp=<p>From <a href='https://developer.mozilla.org/en-US/docs/Security/MixedContent'>Mozilla Developer Network</a>:</p><blockquote>If [a] HTTPS page includes content retrieved through regular, cleartext HTTP, then the connection is only partially encrypted: the unencrypted content is accessible to sniffers and can be modified by man-in-the-middle attackers, and therefore the connection is not safeguarded anymore. When a webpage exhibits this behavior, it is called a mixed content page.</blockquote> -privacyProcessHyperlinkAuditingPrompt=Block all <a href='https://html.spec.whatwg.org/multipage/semantics.html#hyperlink-auditing'>hyperlink auditing</a> attempts. -privacyProcessHyperlinkAuditingHelp=<p>Hyperlink auditing is a mechanism which allow a party, <b>any party</b>, to be informed about which link a user clicked on a particular web page. It is essentially a tracking feature: it allows a web site, or any third-party to that web site, to be informed about which link you clicked on which one of its web pages. The sole purpose is to track your browsing activity.</p> -userRulesPermanentHeader=സ്ഥിര നിയമങ്ങള് -userRulesTemporaryHeader=താത്കാലിക നിയമങ്ങള് -userRulesRevert=റിവേര്ട്ട് -userRulesCommit=കമ്മിറ്റ് -userRulesEdit=എഡിറ്റ് -userRulesEditSave=സൂക്ഷിക്കുക -userRulesEditDicard=കളയുക -userRulesImport=ഫയലില് നിന്നും ഇമ്പോര്ട്ട് ചെയ്യുക... -userRulesExport=Export to file... -userRulesFormatHint=See this page for rule syntax. -userRulesDefaultFileName=my-ematrix-rules.txt -hostsFilesPrompt=All hostnames in a hosts file are loaded as blacklisted hostnames in the global scope. -hostsFilesStats={{blockedHostnameCount}} distinct blocked hostnames from: -hostsFilesPerFileStats={{used}} used out of {{total}} -hostsFilesLastUpdate=Last update: {{ago}} -hostsFilesApplyChanges=Apply changes -hostsFilesAutoUpdatePrompt=Auto-update hosts files. -hostsFilesUpdateNow=Update now -hostsFilesPurgeAll=Purge all caches -hostsFilesExternalListsHint=One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored. -hostsFilesExternalListsParse=പാര്സ് ചെയ്യുക -hostsFilesExternalListPurge=കാഷ് നശിപ്പിക്കുക -hostsFilesExternalListNew=പുതിയ വെര്ഷന് ലഭ്യമാണ് -hostsFilesExternalListObsolete=കാലഹരണപ്പെട്ടത് -rawSettingsWarning=Warning! Change these raw configuration settings at your own risk. -aboutChangelog=മാറ്റത്തിന്റെ കുറിപ്പുകള് -aboutStorageUsed=Storage used: {{storageUsed}} bytes -aboutDoc=Documentation -aboutPermissions=അനുവാദങ്ങള് -aboutCode=സോര്സ് കോഡ് (ജിപിഎല് വി3) -aboutIssues=ബഗ്ഗുകളും പ്രശ്നങ്ങളും -aboutContributors=സംഭാവന ചെയ്തവര് -aboutCodeContributors=കോഡ്: -aboutIssueContributors=പ്രശ്നങ്ങള്: -aboutTranslationContributors=പരിഭാഷകള്: -aboutUserDataHeader=നിങ്ങളുടെ ഡാറ്റ -aboutBackupButton=ഫയലിലേക്ക് ബാക്ക് അപ് ചെയ്യുക... -aboutBackupFilename=my-ematrix-backup.txt -aboutRestoreButton=ഫയലില് നിന്നും റീസ്റ്റോര് ചെയ്യുക... -aboutRestoreConfirm=All your settings will be overwritten using data backed up on {{time}}, and ηMatrix will restart.\n\nOverwrite all existing settings using backed up data? -aboutRestoreError=The data could not be read or is invalid -aboutOr=... അല്ലെങ്കില് ... -aboutResetButton=ഡീഫാള്ട്ട് സെറ്റിംഗ്സിലേക്ക് റീസ്റ്റോര് ചെയ്യുക -aboutResetConfirm=Caution! this will remove all your custom settings. Are you sure you want to proceed? -loggerFilterInputPlaceholder=filter expression(s) -loggerMaxEntriesTip=Maximum number of entries -loggerEntryCookieDeleted=cookie deleted: {{value}} -loggerEntryDeleteCookieError=failed to delete cookie: {{value}} -loggerEntryBrowserCacheCleared=browser cache cleared -loggerEntryAssetUpdated=asset updated: {{value}} -mainBlockedPrompt1=ηMatrix has prevented the following page from loading: -mainBlockedPrompt2=Because of the following rule -mainBlockedBack=പിന്നിലേക്ക് പോകുക -mainBlockedClose=അടയ്ക്കുക -commandRevertAll=Revert all temporary changes -commandWhitelistPageDomain=Temporarily whitelist page domain -commandWhitelistAll=Temporarily whitelist all -commandOpenDashboard=ഡാഷ്ബോര്ഡ് തുറക്കുക -elapsedOneMinuteAgo=ഒരു മിനിറ്റ് മുന്പ് -elapsedManyMinutesAgo={{value}} മിനിറ്റുകള് മുന്പ് -elapsedOneHourAgo=ഒരു മണിക്കൂര് മുന്പ് -elapsedManyHoursAgo={{value}} മണിക്കൂറുകള് മുന്പ് -elapsedOneDayAgo=ഒരു ദിവസം മുന്പ് -elapsedManyDaysAgo={{value}} ദിവസങ്ങള്ക്ക്മുന്പ് -showDashboardButton=ഡാഷ്ബോര്ഡ് -showLoggerButton=ലോഗ്ഗര് -cloudPush=ക്ലൌഡ് സ്റ്റോറേജിലേക്ക് എക്സ്പോര്ട്ട് ചെയ്യുക -cloudPull=ക്ലൌഡ് സ്റ്റോറേജില് നിന്ന് ഇമ്പോര്ട്ട് ചെയ്യുക -cloudNoData=...\n... -cloudDeviceNamePrompt=ഈ ഉപകരണത്തിന്റെ പേര്: -genericSubmit=സബ്മിറ്റ് -genericRevert=റിവേര്ട്ട് -errorCantConnectTo=നെറ്റ്വര്ക്ക് പ്രശ്നം: {{url}} ലേക്ക് കണക്റ്റ് ചെയ്യാന് ഒക്കുന്നില്ല -genericApplyChanges=Apply changes -noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can display some content by using the <noscript> tag. For example, some websites will redirect users to a “scriptless” version.</p><p>When ηMatrix blocks scripts, the browser will still advertise itself as supporting script execution unless this option is selected.</p><p>When selected, ηMatrix will tell the website that the browser does not support scripts, which is what you definitely want to do if you are blocking 1st-party scripts. As such, the <noscript> tag will work as intended.</p><p>Not selecting this option when 1st-party scripts are blocked means the website will break misteryously in case it is meant to redirect to a scriptless version.</p> -settingsUpdateIcon=Do not change the toolbar icon -updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> -resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> diff --git a/locale/nb/messages.properties b/locale/nb/messages.properties deleted file mode 100644 index 4a71033..0000000 --- a/locale/nb/messages.properties +++ /dev/null @@ -1,186 +0,0 @@ -extName=ηMatrix -dashboardPageName=ηMatrix - Instrumentpanel -loggerPageName=ηMatrix — Logger -settingsPageName=Innstillinger -privacyPageName=Personvern -statsPageName=Statistikk -userRulesPageName=Mine regelsett -ubiquitousRulesPageName=Vertsfiler -rawSettingsPageName=More -aboutPageName=Om -allPrettyName=alt -cookiePrettyName=kake -cssPrettyName=CSS -imagePrettyName=bilde -mediaPrettyName=medie -pluginPrettyName=tillegg -scriptPrettyName=skript -xhrPrettyName=XHR -framePrettyName=ramme -otherPrettyName=annet -matrixNoNetTrafficPrompt=Ingen nettverkstrafikk oppdaget for denne fanen så langt. -matrixMtxButtonTip=Skru på/av matrisefiltrering for dette virkefeltet. -matrixPersistButtonTip=Lagre alle midlertidige endringer for dette virkefeltet. -matrixRevertButtonTip=Tilbakestill midlertidige endringer for dette virkefeltet. -matrixReloadButton=Gjeninnlast denne siden. -matrixScopeTip=Change to global scope. -matrixSwitchesTip=Dropdown menu with additional settings. -matrix1stPartyLabel=førsteparts -matrixBlacklistedHostnames={{count}} svartelistede vertsnavn -matrixSwitchNoMixedContent=Streng HTTPS -matrixSwitchNoWorker=Forbid web workers -matrixSwitchReferrerSpoof=Lurendreiing av referent -matrixSwitchNoscriptSpoof=Spoof <code><noscript></code> tags -matrixRevertAllEntry=Tilbakestill alle midlertidige endringer -matrixLoggerMenuEntry=Gå til loggføring -matrixDashboardMenuEntry=Gå til instrumentpanel -matrixNoTabFound=No web page found -statsPageTitle=ηMatrix – Statistikk -statsPageGenericStats=Alminnelig statistikk -statsPageCookieHeadersFoiled=<a href='https://no.wikipedia.org/wiki/Informasjonskapsel'>HTTP-kake</a> hoder lurt: {{count}} -statsPageRefererHeadersFoiled=<a href='https://en.wikipedia.org/wiki/HTTP_referer'>HTTP-referent</a>hoder lurt: {{count}} -statsPageHyperlinkAuditingFoiled=<a href='http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#hyperlink-auditing'>Hyperlenke-revisjon</a>forsøk lurt:{{count}} -statsPageCookiesRemoved={{count}} lokale kaker fjernet -statsPageLocalStoragesCleared={{count}} <a href='http://diveintohtml5.info/storage.html'>lokallager</a>tømt -statsPageBrowserCacheCleared={{count}} nettlesermellomlager tømt -statsPageDetailedStats=Detaljert statistikk -statsPageDetailedAllPages=Alt -statsPageDetailedBehindTheScenePage=Bak sceneteppet -statsPageOverview=Oversikt -statsPageRequests=Forespørsler -statsPageAllowed=Tillatt -statsPageBlocked=Blokkert -statsPageAll=Alt -statsPagePages=Sider -statsPageCookies=Kaker -statsPageCSS=CSS -statsPageImages=Bilder -statsPagePlugins=Tillegg -statsPageScripts=Skript -statsPageXHRs=XHR-er -statsPageFrames=Rammer -statsPageOthers=Annet -statsPageDetailed=Logger -statsPageLogSizePrompt1=Husket de siste -statsPageLogSizePrompt2=HTTP-forespørsler <b>per side</b>. -statsPageLogSizeHelp=<p>You can inspect details of the most recent raw HTTP requests which have been made by a web page (see below).</p><p>This is mostly useful to advanced users who want to investigate exactly what a web page has been doing. But logging these HTTP requests requires memory, and if you don't care about this technical information, then memory is being wasted.</p><p>Hence this field which lets you adjust the maximum number of the most recent HTTP requests which are to be logged for further inspection.</p><p>Enter “<code>0</code>” to turn off detailed logging (and consequently reduce the memory footprint of <i>ηMatrix</i>).</p> -statsPageRefresh=Gjenoppfrisk -settingsPageTitle=ηMatrix – innstillinger -settingsMatrixDisplayHeader=Utseende -settingsMatrixDisplayTextSizePrompt=Tekststørrelse: -settingsMatrixDisplayTextSizeNormal=Normal -settingsMatrixDisplayTextSizeLarge=Stor -settingsMatrixDisplayColorBlind=Fargeblindhets-vennlig -settingsMatrixConvenienceHeader=Bekvemmelighet -settingsDefaultScopeLevel=Default scope level: -settingsDefaultScopeLevel0=Global -settingsDefaultScopeLevel1=Domain -settingsDefaultScopeLevel2=Site -settingsMatrixAutoReloadPrompt=Ved lukking av matrisen, utfør smart gjeninnlasting av disse fanene: -settingsMatrixAutoReloadNone=Ingen -settingsMatrixAutoReloadCurrent=Gjeldende -settingsMatrixAutoReloadAll=Alle -settingsMatrixAutoReloadInfo=Når du gjør endringer i matrisen som kan ha innvirkning på visningen og/eller oppførselen til én eller flere sider vil <i>ηMatrix</i> gjeninnlaste sider som omfattes av dette når du lukker matrisen. -settingsSubframeColor=Blokkerte rammer: Farge -settingsSubframeOpacity=Dekkevne -settingsIconBadgeEnabled=Show the number of blocked requests on the icon -settingsCollapseBlocked=Fold sammen plassholderen tilhørende blokkerte elementer -settingsCollapseBlacklisted=Collapse placeholder of blacklisted elements -settingsNoscriptTagsSpoofed=Spoof <code><noscript></code> tags when 1st-party scripts are blocked -settingsCloudStorageEnabled=Skru på støtte for sky-lagring -privacyPageTitle=ηMatrix – personvern -privacyDeleteBlockedCookiesPrompt=Slettede blokkerte kaker. -privacyDeleteBlockedCookiesHelp=<p>Blacklisted cookies are not prevented by <i>ηMatrix</i> from entering your browser. However they are prevented from leaving your browser, which is what really matters. Not blocking cookies before they enter your browser gives you the opportunity to be informed that a site tried to use cookies, and furthermore to inspect their contents if you wish.</p><p>Once these blacklisted cookies have been accounted for by <i>ηMatrix</i>, they can be removed from your browser if you wish so.</p><p><b>Important note:</b> Extensions can make web requests during the course of their normal operation. These requests can result in cookies being created in the browser. If the hostname from where a cookie originate is not whitelisted, the cookie will be removed from the browser by <i>ηMatrix</i> if this option is checked. So be sure that the hostname(s) with which an extension communicate is whitelisted.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Slett ikke-blokkerte kaker for denne økta -privacyDeleteNonBlockedSessionCookiesPrompt2= minutter etter sist gang de ble brukt. -privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “A session cookie ... is erased when you end the browser session. The session cookie is stored in temporary memory and is not retained after the browser is closed.”</p><p>Except that this <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>might not be happening</a> in some browsers. Also, to some, having to close the browser in order for the session cookies to clear might not be early enough.</p> -privacyDeleteBlockedLocalStoragePrompt=Slett <a href='https://en.wikipedia.org/wiki/Web_storage'>lokalt innhold</a> satt av blokkerte vertsnavn -privacyDeleteBlockedLocalStorageHelp=Skal gjøres -privacyClearCachePrompt1=Tøm nettleserens mellomlager hvert -privacyClearCachePrompt2=minutt. -privacyClearCacheHelp=<p>Some web sites are really bent on tracking you, so much that they will use not-so-nice tricks to work around whatever measures you take in order to not be tracked.</p><p>A few of these tricks rely<sup>[1, 2]</sup> on the <a href='https://en.wikipedia.org/wiki/Web_cache'>browser cache</a>, which content is often long lasting since rarely will users take the time to regularly clear their browser cache.</p><p>There is little inconvenience to clear the browser cache regularly (likelihood is that you won't notice when it happens), and the benefit is to prevent these obnoxious trackers from invading your privacy.</p><p>Check this option to have <i>ηMatrix</i> do it for you, at the interval you wish.</p><p>[1] <a href='https://grepular.com/Preventing_Web_Tracking_via_the_Browser_Cache'>“Preventing Web Tracking via the Browser Cache”</a>\n[2] <a href='http://lucb1e.com/rp/cookielesscookies/'>“Cookieless cookies”</a></p> -privacyProcessRefererPrompt=Lur <a href='https://en.wikipedia.org/wiki/HTTP_referer'>HTTP-referent</a> strengen til tredjeparts-forespørsler. -privacyProcessRefererHelp=From Wikipedia:<blockquote>HTTP referer is an HTTP header field that identifies the address of the webpage that linked to the resource being requested. ... <b>Because referer information can violate privacy, some web browsers allow the user to disable the sending of referer information.</b></blockquote>If this setting is checked, <i>ηMatrix</i> will spoof the HTTP referrer information if the domain name of the HTTP referrer is third-party to the domain name of net request. -privacyNoMixedContentPrompt=Streng HTTPS: forby blandet innhold. -privacyNoMixedContentHelp=<p>From <a href='https://developer.mozilla.org/en-US/docs/Security/MixedContent'>Mozilla Developer Network</a>:</p><blockquote>If [a] HTTPS page includes content retrieved through regular, cleartext HTTP, then the connection is only partially encrypted: the unencrypted content is accessible to sniffers and can be modified by man-in-the-middle attackers, and therefore the connection is not safeguarded anymore. When a webpage exhibits this behavior, it is called a mixed content page.</blockquote> -privacyProcessHyperlinkAuditingPrompt=Block all <a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>hyperlink auditing</a> attempts. -privacyProcessHyperlinkAuditingHelp=<p>Hyperlink auditing is a mechanism which allow a party, <b>any party</b>, to be informed about which link a user clicked on a particular web page. It is essentially a tracking feature: it allows a web site, or any third-party to that web site, to be informed about which link you clicked on which one of its web pages. The sole purpose is to track your browsing activity.</p> -userRulesPermanentHeader=Permanente regelsett -userRulesTemporaryHeader=Midlertidige regler -userRulesRevert=Tilbakestill -userRulesCommit=Send inn -userRulesEdit=Rediger -userRulesEditSave=Lagre -userRulesEditDicard=Avvis -userRulesImport=Importer fra fil… -userRulesExport=Eksporter til fil… -userRulesFormatHint=Vis siden for regel-syntaks. -userRulesDefaultFileName=mine-ematrix-regler.txt -hostsFilesPrompt=Alle vertsnavn i en vertsnavnsfil blir innlastet som svartelistede vertsnavn i det globale virkefeltet. -hostsFilesStats={{blockedHostnameCount}} entydig blokkerte vertsnavn fra: -hostsFilesPerFileStats={{used}} brukt av {{total}} -hostsFilesLastUpdate={{ago}} siste oppdatering -hostsFilesApplyChanges=Bruk -hostsFilesAutoUpdatePrompt=Auto-oppdatering av vertsfiler. -hostsFilesUpdateNow=Oppdater nå -hostsFilesPurgeAll=Rens alle mellomlager -hostsFilesExternalListsHint=Én nettadresse per linje. Linjes innledet med ‘#’ vil bli ignorert. Ugyldige nettadresser vil bli ignorert i all stillhet. -hostsFilesExternalListsParse=Fortolk -hostsFilesExternalListPurge=rens mellomlager -hostsFilesExternalListNew=ny versjon tilgjengelig -hostsFilesExternalListObsolete=utdatert -rawSettingsWarning=Warning! Change these raw configuration settings at your own risk. -aboutChangelog=Endringslogg -aboutStorageUsed={{storageUsed}} Byte lagringsplass brukt -aboutDoc=Dokumentasjon -aboutPermissions=Tillatelser -aboutCode=Kildekode (GPLv3) -aboutIssues=Feil og mangler -aboutContributors=Bidragsytere -aboutCodeContributors=Kode: -aboutIssueContributors=Mangler: -aboutTranslationContributors=Oversettelser: -aboutUserDataHeader=Din data -aboutBackupButton=Sikkerhetskopier til fil… -aboutBackupFilename=min-ematrix-sikkerhetskopi.txt -aboutRestoreButton=Gjenopprett fra fil… -aboutRestoreConfirm=Alle dine innstillinger vil bli overskrevet ved bruk av data sikkerhetskopiert {{time}}, og ηMatrix vil starte på ny.\n\nOverskriv alle eksisterende innstillinger med sikkerhetskopiert data? -aboutRestoreError=Dataen kunne ikke leses eller er ugyldig -aboutOr=… eller … -aboutResetButton=Tilbakestill til forvalgte innstillinger -aboutResetConfirm=Advarsel! Dette vil fjerne alle dine egenkomponerte innstillinger. Bekreft at du vil fortsette. -loggerFilterInputPlaceholder=filter-uttrykk -loggerMaxEntriesTip=Maksimalt antall oppføringer -loggerEntryCookieDeleted=kake slettet: {{value}} -loggerEntryDeleteCookieError=kunne ikke slette kake: {{value}} -loggerEntryBrowserCacheCleared=nettlesermellomlager tømt -loggerEntryAssetUpdated=verdigjenstand oppdatert: {{value}} -mainBlockedPrompt1=ηMatrix har forhindret innlasting av følgende side: -mainBlockedPrompt2=I kraft av følgende regel -mainBlockedBack=Gå tilbake -mainBlockedClose=Lukk -commandRevertAll=Omgjør alle midlertidige endringer -commandWhitelistPageDomain=Midlertidig hvitlist sidens domene -commandWhitelistAll=Midlertidig hvitlisting av alt -commandOpenDashboard=Åpne instrumentpanel -elapsedOneMinuteAgo=ett minutt siden -elapsedManyMinutesAgo={{value}} minutter siden -elapsedOneHourAgo=en time siden -elapsedManyHoursAgo={{value}} timer siden -elapsedOneDayAgo=en dag siden -elapsedManyDaysAgo={{value}} dager siden -showDashboardButton=Instrumentpanel -showLoggerButton=Loggføring -cloudPush=Eksporter til skylager -cloudPull=Importer fra skylager -cloudNoData=…\n… -cloudDeviceNamePrompt=Enhetens navn: -genericSubmit=Send inn -genericRevert=Tilbakestill -errorCantConnectTo=Nettverksfeil: Kan ikke koble til {{url}} -genericApplyChanges=Apply changes -noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can display some content by using the <noscript> tag. For example, some websites will redirect users to a “scriptless” version.</p><p>When ηMatrix blocks scripts, the browser will still advertise itself as supporting script execution unless this option is selected.</p><p>When selected, ηMatrix will tell the website that the browser does not support scripts, which is what you definitely want to do if you are blocking 1st-party scripts. As such, the <noscript> tag will work as intended.</p><p>Not selecting this option when 1st-party scripts are blocked means the website will break misteryously in case it is meant to redirect to a scriptless version.</p> -settingsUpdateIcon=Do not change the toolbar icon -updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> -resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> diff --git a/locale/nl/messages.properties b/locale/nl/messages.properties index 6503984..d4b0295 100644 --- a/locale/nl/messages.properties +++ b/locale/nl/messages.properties @@ -91,7 +91,7 @@ settingsCloudStorageEnabled=Ondersteuning voor cloudopslag inschakelen privacyPageTitle=ηMatrix – Privacy privacyDeleteBlockedCookiesPrompt=Geblokkeerde cookies verwijderen privacyDeleteBlockedCookiesHelp=<p><i>ηMatrix</i> voorkomt niet dat geblackliste cookies door uw browser worden ontvangen. Er wordt echter wel voorkomen dat ze uw browser verlaten, wat het belangrijkste is. Het niet blokkeren van cookies voordat ze door uw browser worden ontvangen biedt de mogelijkheid te worden geïnformeerd wanneer een website cookies probeerde te gebruiken, en daarnaast eventueel de inhoud ervan te inspecteren.</p><p>Als deze geblackliste cookies eenmaal door <i>ηMatrix</i> zijn verwerkt, kunnen ze desgewenst uit uw browser worden verwijderd.</p><p><b>Belangrijke opmerking:</b> extensies kunnen tijdens hun normale werking webaanvragen doen. Door deze aanvragen kunnen cookies in de browser worden aangemaakt. Als de hostnaam waarvan een cookie afkomstig is zich niet op de whitelist bevindt, zal het cookie als deze optie is aangevinkt door <i>ηMatrix</i> uit de browser worden verwijderd. Zorg er daarom voor dat de namen van de hosts waarmee een extensie communiceert zich op de whitelist bevinden.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Niet-geblokkeerde sessiecookies +privacyDeleteNonBlockedSessionCookiesPrompt1=Niet-geblokkeerde sessiecookies privacyDeleteNonBlockedSessionCookiesPrompt2= minuten na de laatste keer dat ze zijn gebruikt verwijderen privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “Een sessiecookie wordt gewist zodra u de browsersessie beëindigt. Een sessiecookie wordt in tijdelijk geheugen opgeslagen en niet behouden nadat de browser wordt gesloten.”</p><p>Het is mogelijk dat dit <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>niet in alle browsers gebeurt</a>. Ook vinden sommige gebruikers het moeten sluiten van de browser om sessiecookies te wissen misschien niet vroeg genoeg. privacyDeleteBlockedLocalStoragePrompt=Inhoud van <a href='https://en.wikipedia.org/wiki/Web_storage'>lokale opslag</a> die door geblokkeerde hostnamen is ingesteld verwijderen @@ -115,7 +115,7 @@ userRulesEditDicard=Annuleren userRulesImport=Importeren uit bestand... userRulesExport=Exporteren naar bestand... userRulesFormatHint=Bekijk deze pagina voor regelsyntaxis. -userRulesDefaultFileName=mijn-ematrix-regels.txt +userRulesDefaultFileName=mijn-umatrix-regels.txt hostsFilesPrompt=Alle hostnamen in een hosts-bestand worden in het globale bereik als geblackliste hostnamen geladen. hostsFilesStats={{blockedHostnameCount}} afzonderlijke geblokkeerde hostnamen van: hostsFilesPerFileStats={{used}} van {{total}} gebruikt @@ -124,7 +124,7 @@ hostsFilesApplyChanges=Wijzigingen toepassen hostsFilesAutoUpdatePrompt=Hosts-bestanden automatisch bijwerken hostsFilesUpdateNow=Nu bijwerken hostsFilesPurgeAll=Alle caches legen -hostsFilesExternalListsHint=Eén URL per regel. Regels beginnend met ‘#’ worden genegeerd. Ongeldige URL’s worden zonder mededeling genegeerd. +hostsFilesExternalListsHint=<p>One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored.</p><p>The inserted URL must point to a hosts file (including local files); do not use the hosts file syntax here.</p> hostsFilesExternalListsParse=Toepassen hostsFilesExternalListPurge=cache legen hostsFilesExternalListNew=nieuwe versie beschikbaar @@ -142,7 +142,7 @@ aboutIssueContributors=Problemen: aboutTranslationContributors=Vertalingen: aboutUserDataHeader=Uw gegevens aboutBackupButton=Back-up maken naar bestand... -aboutBackupFilename=mijn-ematrix-back-up.txt +aboutBackupFilename=mijn-umatrix-back-up.txt aboutRestoreButton=Terugzetten uit bestand... aboutRestoreConfirm=Al uw instelling zullen met back-upgegevens van {{time}} worden overschreven, en ηMatrix zal worden herstart.\n\nWilt u alle bestaande instellingen met back-upgegevens overschrijven? aboutRestoreError=De gegevens konden niet worden gelezen of zijn ongeldig @@ -183,4 +183,6 @@ noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can dis settingsUpdateIcon=Do not change the toolbar icon updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +resolveCnameHelp=<p>When resolving an address with DNS, some webistes use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +settingsTextSmaller=Smaller +settingsTextBigger=Bigger diff --git a/locale/pl/messages.properties b/locale/pl/messages.properties index 22543ba..f0e5f80 100644 --- a/locale/pl/messages.properties +++ b/locale/pl/messages.properties @@ -91,7 +91,7 @@ settingsCloudStorageEnabled=Włącz możliwość zapisywania ustawień w chmurze privacyPageTitle=ηMatrix – Prywatność privacyDeleteBlockedCookiesPrompt=Usuń zablokowane ciasteczka. privacyDeleteBlockedCookiesHelp=<p><i>ηMatrix</i>nie zapobiega dostawaniu się ciasteczek z czarnej listy do twojej przeglądarki. Jednakże zapobiega opuszczaniu jej przez nie, co ostatecznie się liczy. Nieblokowanie ciasteczek zanim dotrą do twojej przeglądarki, daje możliwość poinformowania cię gdy strona próbuje używać ciastek, a nawet pozwala przejrzeć ich zawartość gdy tego chcesz.</p><p>Kiedy te czarnolistowane ciasteczka zostaną sklasyfikowane przez <i>ηMatrix</i>, mogą, jeśli sobie tego życzysz, zostać usunięte z przeglądarki.</p><p><b>Ważna informacja:</b> Rozszerzenia mogą wykonywać żądania sieciowe podczas ich normalnej pracy. Te żądania mogą spowodować zapisanie ciasteczek w przeglądarce. Jeśli nazwa hosta z której pochodzi ciasteczko nie jest na białej liście, ciasteczko zostanie usunięte z przeglądarki przez <i>ηMatrix</i> jeśli ta opcja jest zaznaczona. Upewnij się, że nazwy hostów z którymi komunikuje się rozszerzenie są na białej liście.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Usuń nie zablokowane ciasteczka sesyjne +privacyDeleteNonBlockedSessionCookiesPrompt1=Usuń nie zablokowane ciasteczka sesyjne privacyDeleteNonBlockedSessionCookiesPrompt2= minut od ostatniego użycia. privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C [ang.]</a>: “Ciasteczko sesyjne ... jest usuwane kiedy kończysz sesję przeglądarki. Ciasteczko sesyjne przechowywane jest w pamięci tymczasowej i nie jest zachowywane po zamknięciu przeglądarki.”</p><p>Poza tym, że <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>nie zawsze to działa</a> w niektórych przeglądarkach. Również, dla niektórych użytkowników, zamknięcie przeglądarki by usunąć ciasteczka może nie być wystarczająco szybkie.</p> privacyDeleteBlockedLocalStoragePrompt=Usuwaj zawartość <a href='https://en.wikipedia.org/wiki/Web_storage'>local storage</a> ustawioną przez zablokowane hosty @@ -115,7 +115,7 @@ userRulesEditDicard=Odrzuć userRulesImport=Importuj z pliku... userRulesExport=Eksportuj do pliku... userRulesFormatHint=Składnię reguł znajdziesz tutaj. -userRulesDefaultFileName=ematrix-moje-reguly.txt +userRulesDefaultFileName=umatrix-moje-reguly.txt hostsFilesPrompt=Wszystkie nazwy hostów z plików hosts są traktowane jako czarno-listowane globalnie. hostsFilesStats={{blockedHostnameCount}} blokowanych unikalnych hostów z: hostsFilesPerFileStats=użytych {{used}} z {{total}} @@ -124,7 +124,7 @@ hostsFilesApplyChanges=Zastosuj zmiany hostsFilesAutoUpdatePrompt=Automatycznie aktualizuj pliki hosts. hostsFilesUpdateNow=Aktualizuj teraz hostsFilesPurgeAll=Przeczyść całą pamięć podręczną -hostsFilesExternalListsHint=Jeden URL na linię. Linie zaczynające się od ‘#’ będą traktowane jak komentarz. Niepoprawne URLe będą ignorowane. +hostsFilesExternalListsHint=<p>One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored.</p><p>The inserted URL must point to a hosts file (including local files); do not use the hosts file syntax here.</p> hostsFilesExternalListsParse=Przetwórz hostsFilesExternalListPurge=wyczyść pamięć podręczną hostsFilesExternalListNew=dostępna nowsza wersja @@ -142,7 +142,7 @@ aboutIssueContributors=Problemy: aboutTranslationContributors=Tłumaczenia: aboutUserDataHeader=Twoje dane aboutBackupButton=Zapisz kopię zapasową... -aboutBackupFilename=ematrix-kopia-zapasowa.txt +aboutBackupFilename=umatrix-kopia-zapasowa.txt aboutRestoreButton=Przywróć kopię zapasową... aboutRestoreConfirm=Wszystkie ustawienia zostaną nadpisane danymi z kopii z {{time}}, a następnie ηMatrix zostanie zrestartowany.\n\nNadpisać aktualne ustawienia używając danych z kopii? aboutRestoreError=Dane nie mogą być odczytane lub są niepoprawne @@ -183,4 +183,6 @@ noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can dis settingsUpdateIcon=Do not change the toolbar icon updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +resolveCnameHelp=<p>When resolving an address with DNS, some webistes use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +settingsTextSmaller=Smaller +settingsTextBigger=Bigger diff --git a/locale/pt-BR/messages.properties b/locale/pt-BR/messages.properties index c88ed97..4449e96 100644 --- a/locale/pt-BR/messages.properties +++ b/locale/pt-BR/messages.properties @@ -91,7 +91,7 @@ settingsCloudStorageEnabled=Habilitar suporte à armazenagem em nuvem privacyPageTitle=ηMatrix – Privacidade privacyDeleteBlockedCookiesPrompt=Apagar os cookies bloqueados. privacyDeleteBlockedCookiesHelp=<p>Cookies na lista negra não são impedidos pelo <i>ηMatrix</i> de entrar em seu navegador. No entanto, eles estão impedidos de ficar no seu navegador, que é o que realmente importa. Não bloquear os cookies antes de introduzir o seu navegador lhe dá a oportunidade de ser informado de que um site tentou usar cookies, e além disso, para inspecionar o seu conteúdo, se desejar.</p><p>Uma vez que esses cookies lista negra foram contabilizados por <i>ηMatrix</i>, eles podem ser removidos do seu navegador, se assim o desejar.</p><p><b>Nota importante:</b> As extensões podem fazer solicitações da web durante o curso de sua operação normal. Estes pedidos podem resultar em cookies que está sendo criado no navegador. Se o nome da máquina a partir de onde se originam um biscoito não está na lista branca, o cookie será removido a partir do navegador pelo <i>ηMatrix</i> se esta opção estiver marcada. Então não se esqueça que o nome da máquina (s) com que uma extensão comunicar está na lista branca.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Excluir cookies da sessão não-bloqueados +privacyDeleteNonBlockedSessionCookiesPrompt1=Excluir cookies da sessão não-bloqueados privacyDeleteNonBlockedSessionCookiesPrompt2= minutos após a última vez que eles tenham sido utilizados. privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “Um cookie de sessão ... é apagado quando você termina a sessão do navegador. O cookie de sessão é armazenado na memória temporária e não é mantido após o navegador for fechado.”</p><p>Exceto para este <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>não pode estar acontecendo</a> quando utilizar um navegador baseado em Chromium. Além disso, para alguns, é necessário fechar o navegador para limpar os cookies da sessão pode não ser suficientemente cedo.</p> privacyDeleteBlockedLocalStoragePrompt=Apagar <a href='https://en.wikipedia.org/wiki/Web_storage'>armazenamento local</a> conteúdo definido por hostnames bloqueadas @@ -115,7 +115,7 @@ userRulesEditDicard=Descartar userRulesImport=Importar do arquivo... userRulesExport=Exportar para arquivo... userRulesFormatHint=Veja está página para regras de sintaxe. -userRulesDefaultFileName=minhas-regras-ematrix.txt +userRulesDefaultFileName=minhas-regras-umatrix.txt hostsFilesPrompt=Todos os hostnames no arquivo de hosts são carregados como hostnames da lista negra no escopo global. hostsFilesStats={{blockedHostnameCount}} hostnames distintos bloqueados de: hostsFilesPerFileStats={{used}} usado do total de {{total}} @@ -124,7 +124,7 @@ hostsFilesApplyChanges=Aplicar mudanças hostsFilesAutoUpdatePrompt=Auto-atualizar os arquivos hosts. hostsFilesUpdateNow=Atualizar agora hostsFilesPurgeAll=Limpar todos caches -hostsFilesExternalListsHint=Uma URL por linha. Linhas pré-fixadas com ‘#’ irão ser ignoradas. URLs inválidas irão ser silenciosamente ignoradas. +hostsFilesExternalListsHint=<p>One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored.</p><p>The inserted URL must point to a hosts file (including local files); do not use the hosts file syntax here.</p> hostsFilesExternalListsParse=Analisar hostsFilesExternalListPurge=limpar cache hostsFilesExternalListNew=nova versão disponível @@ -142,7 +142,7 @@ aboutIssueContributors=Problemas: aboutTranslationContributors=Traduções: aboutUserDataHeader=Seus dados aboutBackupButton=Salvar em arquivo... -aboutBackupFilename=meu-backup-ematrix.txt +aboutBackupFilename=meu-backup-umatrix.txt aboutRestoreButton=Restaurar do arquivo... aboutRestoreConfirm=Todas as suas definições irão ser sobrescritas pelos dados salvos em {{time}}, e o ηMatrix irá reiniciar.\n\nSubstituir todas a configuração atual usando dados de backup? aboutRestoreError=Os dados não podem ser lidos ou são inválidos @@ -179,8 +179,10 @@ genericSubmit=Enviar genericRevert=Reverter errorCantConnectTo=Erro na rede: Não foi possível conectar ao {{url}} genericApplyChanges=Aplicar mudanças -noscriptSpoofHelp=<p>Quando um navegador não suporta scripts, uma página da Web pode exibir algum conteúdo usando a tag <noscript>. Por exemplo, alguns sites redirecionam os usuários para uma versão sem “scriptless”.</p><p>Quando o ηMatrix bloqueia scripts, o navegador ainda se anuncia como suporte à execução de scripts, a menos que esta opção esteja selecionada.</p><p>Quando selecionado, o ηMatrix informa ao site que o navegador não suporta scripts, o que você definitivamente deseja fazer se estiver bloqueando scripts de terceiros. Como tal, a tag <noscript> funcionará como pretendido.</p><p>Não selecionar esta opção quando os scripts de terceiros estiverem bloqueados significa que o site será interrompido misteriosamente caso seja destinado a redirecionar para uma versão sem script.</p> +noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can display some content by using the <noscript> tag. For example, some websites will redirect users to a “scriptless” version.</p><p>When ηMatrix blocks scripts, the browser will still advertise itself as supporting script execution unless this option is selected.</p><p>When selected, ηMatrix will tell the website that the browser does not support scripts, which is what you definitely want to do if you are blocking 1st-party scripts. As such, the <noscript> tag will work as intended.</p><p>Not selecting this option when 1st-party scripts are blocked means the website will break misteryously in case it is meant to redirect to a scriptless version.</p> settingsUpdateIcon=Do not change the toolbar icon updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +resolveCnameHelp=<p>When resolving an address with DNS, some webistes use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +settingsTextSmaller=Smaller +settingsTextBigger=Bigger diff --git a/locale/pt-PT/messages.properties b/locale/pt-PT/messages.properties index 4bc64d7..37c6dd0 100644 --- a/locale/pt-PT/messages.properties +++ b/locale/pt-PT/messages.properties @@ -84,14 +84,14 @@ settingsMatrixAutoReloadInfo=Quando fizer modificações na matriz que podem afe settingsSubframeColor=Frames bloqueadas: Cor settingsSubframeOpacity=Opacidade settingsIconBadgeEnabled=Show the number of blocked requests on the icon -settingsCollapseBlocked=Colapsar espaço reservado dos elementos bloqueados +settingsCollapseBlocked=Colapsar espaço reservado dos elementos bloqueados settingsCollapseBlacklisted=Collapse placeholder of blacklisted elements settingsNoscriptTagsSpoofed=Spoof <code><noscript></code> tags when 1st-party scripts are blocked settingsCloudStorageEnabled=Ativar suporte para armazenamento na nuvem privacyPageTitle=ηMatrix – Privacidade privacyDeleteBlockedCookiesPrompt=Apagar cookies bloqueados. privacyDeleteBlockedCookiesHelp=<p>Cookies na lista negra não são proibídos pelo <i>ηMatrix</i> de entrar no seu browser. No entanto, são proibídos de sair do seu browser, que é o que realmente importa. Não proibir cookies de entrarem no seu browser dá-lhe a oportunidade de ser informado que um site tentou usá-los, e poderá inspeccionar os seus conteúdos, se assim o quiser.</p><p>Uma vez que estes cookies da lista negra tenham sido registados pelo <i>ηMatrix</i>, podem ser removidos do seu browser, se assim o desejar.</p><p><b>Nota importante:</b> Extensões podem fazer pedidos web durante o seu decurso normal de operação. Estes pedidos podem resultar na criação de cookies no seu browser. Se o domínio de onde o cookie provém estiver na lista negra, este será removido do browser pelo <i>ηMatrix</i>, se esta opção estiver seleccionada. Portanto confirme que o nome do(s) site(s) com o(s) quais a extensão comunica não está(ão) na lista negra.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Apagar cookies não bloqueados desta sessão +privacyDeleteNonBlockedSessionCookiesPrompt1=Apagar cookies não bloqueados desta sessão privacyDeleteNonBlockedSessionCookiesPrompt2= minutos após a última vez que foram usados. privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “Um cookie da sessão ... é apagado quando fecha o browser. O cookie da sessão é guardado em memória temporária e não é mantido após o browser ter sido fechado.”</p><p>Excepto que isto <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>poderá não acontecer</a> em alguns browsers. No entanto, para alguns, ter de fechar o browser, para que os cookies da sessão sejam eliminados, pode não ser cedo suficiente.</p> privacyDeleteBlockedLocalStoragePrompt=Apagar <a href='https://en.wikipedia.org/wiki/Web_storage'>armazenamento local</a> de conteúdo guardado por domínios bloqueados @@ -115,7 +115,7 @@ userRulesEditDicard=Rejeitar userRulesImport=Importar do ficheiro... userRulesExport=Exportar para ficheiro... userRulesFormatHint=Veja esta página para a sintaxe das regras. -userRulesDefaultFileName=my-ematrix-rules.txt +userRulesDefaultFileName=my-umatrix-rules.txt hostsFilesPrompt=Todos os nomes dos hosts num ficheiro hosts são carregados como domínios de lista negra no escopo global. hostsFilesStats={{blockedHostnameCount}} sites distintos bloqueados: hostsFilesPerFileStats={{used}} utilizados de {{total}} @@ -124,7 +124,7 @@ hostsFilesApplyChanges=Aplicar alterações hostsFilesAutoUpdatePrompt=Actualiza automaticamente os ficheiros hosts. hostsFilesUpdateNow=Actualizar agora hostsFilesPurgeAll=Limpar todas as caches -hostsFilesExternalListsHint=Um URL por linha. Linhas prefixadas com ‘#’ serão ignoradas. URLs invalidos serão ignorados silenciosamente. +hostsFilesExternalListsHint=<p>One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored.</p><p>The inserted URL must point to a hosts file (including local files); do not use the hosts file syntax here.</p> hostsFilesExternalListsParse=Analisar hostsFilesExternalListPurge=limpar cache hostsFilesExternalListNew=nova versão disponível @@ -142,7 +142,7 @@ aboutIssueContributors=Problemas: aboutTranslationContributors=Traduções: aboutUserDataHeader=Os seus dados aboutBackupButton=Guardar cópia de segurança para um ficheiro... -aboutBackupFilename=my-ematrix-backup.txt +aboutBackupFilename=my-umatrix-backup.txt aboutRestoreButton=Restaurar a partir de um ficheiro... aboutRestoreConfirm=Todas as suas definições irão ser substituídas usando a cópia de segurança guardada em {{time}}, e o ηMatrix irá-se reiniciar.\n\nSubstituir configuração existente usando dados da cópia de segurança? aboutRestoreError=Os dados não puderam ser lidos ou são inválidos @@ -179,8 +179,10 @@ genericSubmit=Submeter genericRevert=Desfazer errorCantConnectTo=Erro de rede: Incapaz de se conectar a {{url}} genericApplyChanges=Apply changes -noscriptSpoofHelp=<p>Quando um navegador não suporta scripts, uma página da Web pode exibir algum conteúdo usando a tag <noscript>. Por exemplo, alguns sites redirecionam os usuários para uma versão sem “scriptless”.</p><p>Quando o ηMatrix bloqueia scripts, o navegador ainda se anuncia como suporte à execução de scripts, a menos que esta opção esteja selecionada.</p><p>Quando selecionado, o ηMatrix informa ao site que o navegador não suporta scripts, o que você definitivamente deseja fazer se estiver bloqueando scripts de terceiros. Como tal, a tag <noscript> funcionará como pretendido.</p><p>Não selecionar esta opção quando os scripts de terceiros estiverem bloqueados significa que o site será interrompido misteriosamente caso seja destinado a redirecionar para uma versão sem script.</p> +noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can display some content by using the <noscript> tag. For example, some websites will redirect users to a “scriptless” version.</p><p>When ηMatrix blocks scripts, the browser will still advertise itself as supporting script execution unless this option is selected.</p><p>When selected, ηMatrix will tell the website that the browser does not support scripts, which is what you definitely want to do if you are blocking 1st-party scripts. As such, the <noscript> tag will work as intended.</p><p>Not selecting this option when 1st-party scripts are blocked means the website will break misteryously in case it is meant to redirect to a scriptless version.</p> settingsUpdateIcon=Do not change the toolbar icon updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +resolveCnameHelp=<p>When resolving an address with DNS, some webistes use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +settingsTextSmaller=Smaller +settingsTextBigger=Bigger diff --git a/locale/ro/messages.properties b/locale/ro/messages.properties deleted file mode 100644 index 058ee38..0000000 --- a/locale/ro/messages.properties +++ /dev/null @@ -1,186 +0,0 @@ -extName=ηMatrix -dashboardPageName=ηMatrix — Panou de control -loggerPageName=ηMatrix — Logger -settingsPageName=Opțiuni -privacyPageName=Intimitate -statsPageName=Statistici -userRulesPageName=Regulile mele -ubiquitousRulesPageName=Fișiere de gazde -rawSettingsPageName=More -aboutPageName=Despre -allPrettyName=tot -cookiePrettyName=cookie -cssPrettyName=css -imagePrettyName=imagine -mediaPrettyName=media -pluginPrettyName=modul -scriptPrettyName=script -xhrPrettyName=XHR -framePrettyName=cadru -otherPrettyName=altele -matrixNoNetTrafficPrompt=Deocamdată nu a fost detectat trafic pentru această filă. -matrixMtxButtonTip=Dezactivează/activează filtrarea matriceală pentru acest context. -matrixPersistButtonTip=Salvează toate modificările temporare pentru acest context. -matrixRevertButtonTip=Anulează modificările temporare pentru acest context. -matrixReloadButton=Reîncarcă pagina. -matrixScopeTip=Change to global scope. -matrixSwitchesTip=Dropdown menu with additional settings. -matrix1stPartyLabel=sait primar -matrixBlacklistedHostnames={{count}} gazde blocate -matrixSwitchNoMixedContent=HTTPS strict -matrixSwitchNoWorker=Forbid web workers -matrixSwitchReferrerSpoof=Alterare referent -matrixSwitchNoscriptSpoof=Spoof <code><noscript></code> tags -matrixRevertAllEntry=Elimină toate modificările temporare -matrixLoggerMenuEntry=Mergi la jurnal -matrixDashboardMenuEntry=Mergi la panoul de control -matrixNoTabFound=No web page found -statsPageTitle=ηMatrix – Statistici -statsPageGenericStats=Statistici generice -statsPageCookieHeadersFoiled=<a href='https://en.wikipedia.org/wiki/HTTP_cookie'>HTTP cookie</a> headers foiled: {{count}} -statsPageRefererHeadersFoiled=<a href='https://en.wikipedia.org/wiki/HTTP_referer'>HTTP referer</a> headers foiled: {{count}} -statsPageHyperlinkAuditingFoiled=<a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>Hyperlink auditing</a> attempts foiled: {{count}} -statsPageCookiesRemoved=Cookie-uri locale șterse: {{count}} -statsPageLocalStoragesCleared=<a href='http://diveintohtml5.info/storage.html'>Local storages</a> emptied: {{count}} -statsPageBrowserCacheCleared=Browser caches cleared: {{count}} -statsPageDetailedStats=Statistici detaliate -statsPageDetailedAllPages=Tot -statsPageDetailedBehindTheScenePage=În spatele scenei -statsPageOverview=Privire de ansamblu -statsPageRequests=Cereri -statsPageAllowed=Permis -statsPageBlocked=Blocat -statsPageAll=Tot -statsPagePages=Pagini -statsPageCookies=Cookie -statsPageCSS=CSS -statsPageImages=Imagini -statsPagePlugins=Module -statsPageScripts=Scripturi -statsPageXHRs=XHR -statsPageFrames=Cadre -statsPageOthers=Altele -statsPageDetailed=Jurnal -statsPageLogSizePrompt1=Remember the last -statsPageLogSizePrompt2=Cereri HTTP <b>per pagină</b>. -statsPageLogSizeHelp=<p>You can inspect details of the most recent raw HTTP requests which have been made by a web page (see below).</p><p>This is mostly useful to advanced users who want to investigate exactly what a web page has been doing. But logging these HTTP requests requires memory, and if you don't care about this technical information, then memory is being wasted.</p><p>Hence this field which lets you adjust the maximum number of the most recent HTTP requests which are to be logged for further inspection.</p><p>Enter “<code>0</code>” to turn off detailed logging (and consequently reduce the memory footprint of <i>ηMatrix</i>).</p> -statsPageRefresh=Reîncarcă -settingsPageTitle=ηMatrix – Settings -settingsMatrixDisplayHeader=Aspect -settingsMatrixDisplayTextSizePrompt=Dimensiunea textului: -settingsMatrixDisplayTextSizeNormal=Normal -settingsMatrixDisplayTextSizeLarge=Mare -settingsMatrixDisplayColorBlind=Accesibil pentru daltonism -settingsMatrixConvenienceHeader=Comoditate -settingsDefaultScopeLevel=Default scope level: -settingsDefaultScopeLevel0=Global -settingsDefaultScopeLevel1=Domain -settingsDefaultScopeLevel2=Site -settingsMatrixAutoReloadPrompt=When the matrix is closed, smart reload these tabs: -settingsMatrixAutoReloadNone=Nimic -settingsMatrixAutoReloadCurrent=Current -settingsMatrixAutoReloadAll=Tot -settingsMatrixAutoReloadInfo=Whenever you make changes in the matrix which can affect the display and/or behavior of one or more pages, <i>ηMatrix</i> will reload affected pages automatically when you close the matrix. -settingsSubframeColor=Cadre blocate: Culoare -settingsSubframeOpacity=Opacitate -settingsIconBadgeEnabled=Show the number of blocked requests on the icon -settingsCollapseBlocked=Collapse placeholder of blocked elements -settingsCollapseBlacklisted=Collapse placeholder of blacklisted elements -settingsNoscriptTagsSpoofed=Spoof <code><noscript></code> tags when 1st-party scripts are blocked -settingsCloudStorageEnabled=Enable cloud storage support -privacyPageTitle=ηMatrix – Privacy -privacyDeleteBlockedCookiesPrompt=Șterge cookie-urile blocate. -privacyDeleteBlockedCookiesHelp=<p>Blacklisted cookies are not prevented by <i>ηMatrix</i> from entering your browser. However they are prevented from leaving your browser, which is what really matters. Not blocking cookies before they enter your browser gives you the opportunity to be informed that a site tried to use cookies, and furthermore to inspect their contents if you wish.</p><p>Once these blacklisted cookies have been accounted for by <i>ηMatrix</i>, they can be removed from your browser if you wish so.</p><p><b>Important note:</b> Extensions can make web requests during the course of their normal operation. These requests can result in cookies being created in the browser. If the hostname from where a cookie originate is not whitelisted, the cookie will be removed from the browser by <i>ηMatrix</i> if this option is checked. So be sure that the hostname(s) with which an extension communicate is whitelisted.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Șterge cookie-urile de sesiune neblocate -privacyDeleteNonBlockedSessionCookiesPrompt2= minutes after the last time they have been used. -privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “A session cookie ... is erased when you end the browser session. The session cookie is stored in temporary memory and is not retained after the browser is closed.”</p><p>Except that this <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>might not be happening</a> in some browsers. Also, to some, having to close the browser in order for the session cookies to clear might not be early enough.</p> -privacyDeleteBlockedLocalStoragePrompt=Delete <a href='https://en.wikipedia.org/wiki/Web_storage'>local storage</a> content set by blocked hostnames -privacyDeleteBlockedLocalStorageHelp=DE FĂCUT -privacyClearCachePrompt1=Șterge memoria tampon a navigatorului la fiecare -privacyClearCachePrompt2=minute. -privacyClearCacheHelp=<p>Some web sites are really bent on tracking you, so much that they will use not-so-nice tricks to work around whatever measures you take in order to not be tracked.</p><p>A few of these tricks rely<sup>[1, 2]</sup> on the <a href='https://en.wikipedia.org/wiki/Web_cache'>browser cache</a>, which content is often long lasting since rarely will users take the time to regularly clear their browser cache.</p><p>There is little inconvenience to clear the browser cache regularly (likelihood is that you won't notice when it happens), and the benefit is to prevent these obnoxious trackers from invading your privacy.</p><p>Check this option to have <i>ηMatrix</i> do it for you, at the interval you wish.</p><p>[1] <a href='https://grepular.com/Preventing_Web_Tracking_via_the_Browser_Cache'>“Preventing Web Tracking via the Browser Cache”</a>\n[2] <a href='http://lucb1e.com/rp/cookielesscookies/'>“Cookieless cookies”</a></p> -privacyProcessRefererPrompt=Spoof <a href='https://en.wikipedia.org/wiki/HTTP_referer'>HTTP referrer</a> string of third-party requests. -privacyProcessRefererHelp=From Wikipedia:<blockquote>HTTP referer is an HTTP header field that identifies the address of the webpage that linked to the resource being requested. ... <b>Because referer information can violate privacy, some web browsers allow the user to disable the sending of referer information.</b></blockquote>If this setting is checked, <i>ηMatrix</i> will spoof the HTTP referrer information if the domain name of the HTTP referrer is third-party to the domain name of net request. -privacyNoMixedContentPrompt=HTTPS strict: interzice conținut mixt. -privacyNoMixedContentHelp=<p>From <a href='https://developer.mozilla.org/en-US/docs/Security/MixedContent'>Mozilla Developer Network</a>:</p><blockquote>If [a] HTTPS page includes content retrieved through regular, cleartext HTTP, then the connection is only partially encrypted: the unencrypted content is accessible to sniffers and can be modified by man-in-the-middle attackers, and therefore the connection is not safeguarded anymore. When a webpage exhibits this behavior, it is called a mixed content page.</blockquote> -privacyProcessHyperlinkAuditingPrompt=Block all <a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>hyperlink auditing</a> attempts. -privacyProcessHyperlinkAuditingHelp=<p>Hyperlink auditing is a mechanism which allow a party, <b>any party</b>, to be informed about which link a user clicked on a particular web page. It is essentially a tracking feature: it allows a web site, or any third-party to that web site, to be informed about which link you clicked on which one of its web pages. The sole purpose is to track your browsing activity.</p> -userRulesPermanentHeader=Reguli permanente -userRulesTemporaryHeader=Reguli temporare -userRulesRevert=Înlătură -userRulesCommit=Aplică -userRulesEdit=Modifică -userRulesEditSave=Salvează -userRulesEditDicard=Elimină -userRulesImport=Încarcă din fișier... -userRulesExport=Exportă în fișier... -userRulesFormatHint=Vizitează această pagină pentru sintaxa regulilor. -userRulesDefaultFileName=regulile-mele-ematrix.txt -hostsFilesPrompt=All hostnames in a hosts file are loaded as blacklisted hostnames in the global scope. -hostsFilesStats={{blockedHostnameCount}} distinct blocked hostnames from: -hostsFilesPerFileStats={{used}} used out of {{total}} -hostsFilesLastUpdate=Last update: {{ago}} -hostsFilesApplyChanges=Aplică modificările -hostsFilesAutoUpdatePrompt=Actualizează automat fișierele de gazde. -hostsFilesUpdateNow=Actualizează acum -hostsFilesPurgeAll=Șterge tot din memoria tampon -hostsFilesExternalListsHint=One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored. -hostsFilesExternalListsParse=Analizează -hostsFilesExternalListPurge=șterge memoria tampon -hostsFilesExternalListNew=o nouă versiune disponibilă -hostsFilesExternalListObsolete=învechit -rawSettingsWarning=Warning! Change these raw configuration settings at your own risk. -aboutChangelog=Jurnalul de modificări -aboutStorageUsed=Spațiu de stocare utilizat: {{storageUsed}} octeți -aboutDoc=Documentație -aboutPermissions=Permisiuni -aboutCode=Cod sursă (GPLv3) -aboutIssues=Bugs and issues -aboutContributors=Contribuitori -aboutCodeContributors=Cod: -aboutIssueContributors=Issues: -aboutTranslationContributors=Traduceri: -aboutUserDataHeader=Datele tale -aboutBackupButton=Salvează în fișier... -aboutBackupFilename=my-ematrix-backup.txt -aboutRestoreButton=Restore from file... -aboutRestoreConfirm=All your settings will be overwritten using data backed up on {{time}}, and ηMatrix will restart.\n\nOverwrite all existing settings using backed up data? -aboutRestoreError=The data could not be read or is invalid -aboutOr=... sau ... -aboutResetButton=Reset to default settings -aboutResetConfirm=Caution! this will remove all your custom settings. Are you sure you want to proceed? -loggerFilterInputPlaceholder=filter expression(s) -loggerMaxEntriesTip=Maximum number of entries -loggerEntryCookieDeleted=cookie șters: {{value}} -loggerEntryDeleteCookieError=failed to delete cookie: {{value}} -loggerEntryBrowserCacheCleared=browser cache cleared -loggerEntryAssetUpdated=asset updated: {{value}} -mainBlockedPrompt1=ηMatrix has prevented the following page from loading: -mainBlockedPrompt2=Because of the following rule -mainBlockedBack=Înapoi -mainBlockedClose=Închide -commandRevertAll=Revert all temporary changes -commandWhitelistPageDomain=Temporarily whitelist page domain -commandWhitelistAll=Temporarily whitelist all -commandOpenDashboard=Deschide panoul de control -elapsedOneMinuteAgo=acum un minut -elapsedManyMinutesAgo=acum {{value}} minute -elapsedOneHourAgo=acum o oră -elapsedManyHoursAgo=acum {{value}} ore -elapsedOneDayAgo=acum o zi -elapsedManyDaysAgo=acum {{value}} zile -showDashboardButton=Panou de control -showLoggerButton=Jurnal -cloudPush=Export to cloud storage -cloudPull=Import from cloud storage -cloudNoData=...\n... -cloudDeviceNamePrompt=This device name: -genericSubmit=Submit -genericRevert=Revert -errorCantConnectTo=Network error: Unable to connect to {{url}} -genericApplyChanges=Apply changes -noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can display some content by using the <noscript> tag. For example, some websites will redirect users to a “scriptless” version.</p><p>When ηMatrix blocks scripts, the browser will still advertise itself as supporting script execution unless this option is selected.</p><p>When selected, ηMatrix will tell the website that the browser does not support scripts, which is what you definitely want to do if you are blocking 1st-party scripts. As such, the <noscript> tag will work as intended.</p><p>Not selecting this option when 1st-party scripts are blocked means the website will break misteryously in case it is meant to redirect to a scriptless version.</p> -settingsUpdateIcon=Do not change the toolbar icon -updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> -resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> diff --git a/locale/ru/messages.properties b/locale/ru/messages.properties index 3f6ba34..d8dc25f 100644 --- a/locale/ru/messages.properties +++ b/locale/ru/messages.properties @@ -91,7 +91,7 @@ settingsCloudStorageEnabled=Включить поддержку облачног privacyPageTitle=ηMatrix – Приватность privacyDeleteBlockedCookiesPrompt=Удалять заблокированные куки. privacyDeleteBlockedCookiesHelp=<p>Запрещенные куки не блокируются <i>ηMatrix</i> при входе в ваш браузер. Однако их передача из браузера предотвращается - вот что действительно важно. Неблокировка куки файлов до того, как они сохраняются браузером дает вам возможность узнать, что сайт пытался использовать куки, и потом изучить их содержимое, если вы хотите.</p><p>Как только эти запрещенные куки составлены <i>ηMatrix</i>, они могут быть удалены из браузера, по вашему желанию.</p><p><b>Важное замечание:</b> Расширения могут осуществлять веб-запросы во время своей обычной работы. Эти запросы могут порождать создание куки файлов в браузере. Если имя хоста (сайта), от которого создается куки не в белом списке, то <i>ηMatrix</i> удалит эти куки из браузера, если эта опция включена. Поэтому убедитесь, что имена хостов (сайтов) с которыми соединяется расширение добавлено в белый список.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Удалять незаблокированные сессионные куки через +privacyDeleteNonBlockedSessionCookiesPrompt1=Удалять незаблокированные сессионные куки через privacyDeleteNonBlockedSessionCookiesPrompt2= минут после последнего использования. privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “Сеансовые файлы cookie... удаляются при завершении сеанса браузера. Они хранятся во временной памяти и не сохраняются после закрытия браузера.”</p><p>Однако в некоторых браузерах этого <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>может не произойти</a>. Кроме того, может возникнуть потребность в удалении сеансовых файлов cookie до закрытия браузера.</p> privacyDeleteBlockedLocalStoragePrompt=Удалять содержимое <a href='https://ru.wikipedia.org/wiki/Web_storage'>локального хранилища</a> заблокированных сайтов. @@ -115,7 +115,7 @@ userRulesEditDicard=Сбросить userRulesImport=Импорт из файла... userRulesExport=Экспорт в файл... userRulesFormatHint=Синтаксис правил можно посмотреть на этой странице. -userRulesDefaultFileName=my-ematrix-rules.txt +userRulesDefaultFileName=my-umatrix-rules.txt hostsFilesPrompt=Каждый список содержит перечень сайтов, запрещённых на глобальном уровне. hostsFilesStats={{blockedHostnameCount}} отдельных хостов заблокировано из: hostsFilesPerFileStats={{used}} использовано из {{total}} @@ -124,7 +124,7 @@ hostsFilesApplyChanges=Применить изменения hostsFilesAutoUpdatePrompt=Автообновление списков сайтов. hostsFilesUpdateNow=Обновить сейчас hostsFilesPurgeAll=Очистить все кэши -hostsFilesExternalListsHint=Один URL на строку. Строки, начинающиеся с символа ‘#’, будут проигнорированы. Некорректные ссылки будут пропущены. +hostsFilesExternalListsHint=<p>One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored.</p><p>The inserted URL must point to a hosts file (including local files); do not use the hosts file syntax here.</p> hostsFilesExternalListsParse=Обработать hostsFilesExternalListPurge=очистить кэш hostsFilesExternalListNew=доступна новая версия @@ -142,7 +142,7 @@ aboutIssueContributors=Проблемы: aboutTranslationContributors=Переводы: aboutUserDataHeader=Ваши данные aboutBackupButton=Сделать резервный файл... -aboutBackupFilename=my-ematrix-backup.txt +aboutBackupFilename=my-umatrix-backup.txt aboutRestoreButton=Восстановить из файла... aboutRestoreConfirm=Все ваши настройки будут перезаписаны резервными данными от {{time}}, и ηMatrix перезагрузится.\n\nИзменить все настройки, используя эту резервную копию? aboutRestoreError=Данные не могут быть прочитаны или содержат ошибки @@ -183,4 +183,6 @@ noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can dis settingsUpdateIcon=Do not change the toolbar icon updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +resolveCnameHelp=<p>When resolving an address with DNS, some webistes use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +settingsTextSmaller=Smaller +settingsTextBigger=Bigger diff --git a/locale/sl/messages.properties b/locale/sl/messages.properties deleted file mode 100644 index 35cce00..0000000 --- a/locale/sl/messages.properties +++ /dev/null @@ -1,186 +0,0 @@ -extName=ηMatrix -dashboardPageName=ηMatrix — Nadzorna plošča -loggerPageName=ηMatrix — Logger -settingsPageName=Nastavitve -privacyPageName=Zasebnost -statsPageName=Statistika -userRulesPageName=Moja pravila -ubiquitousRulesPageName=Hosts files -rawSettingsPageName=More -aboutPageName=O razširitvi -allPrettyName=vse -cookiePrettyName=piškotek -cssPrettyName=css -imagePrettyName=slika -mediaPrettyName=media -pluginPrettyName=vtičnik -scriptPrettyName=skript -xhrPrettyName=XHR -framePrettyName=okvir -otherPrettyName=ostalo -matrixNoNetTrafficPrompt=No net traffic seen for this tab so far. -matrixMtxButtonTip=Disable/enable matrix filtering for this scope. -matrixPersistButtonTip=Save all temporary changes for this scope. -matrixRevertButtonTip=Revert temporary changes for this scope. -matrixReloadButton=Reload the page.\nPress Shift to bypass the browser cache. -matrixScopeTip=Change to global scope. -matrixSwitchesTip=Dropdown menu with additional settings. -matrix1stPartyLabel=1st-party -matrixBlacklistedHostnames={{count}} blacklisted hostname(s) -matrixSwitchNoMixedContent=Strog HTTPS -matrixSwitchNoWorker=Forbid web workers -matrixSwitchReferrerSpoof=Spoof <code>Referer</code> header -matrixSwitchNoscriptSpoof=Spoof <code><noscript></code> tags -matrixRevertAllEntry=Revert all temporary changes -matrixLoggerMenuEntry=Go to logger -matrixDashboardMenuEntry=Go to dashboard -matrixNoTabFound=No web page found -statsPageTitle=ηMatrix – Statistics -statsPageGenericStats=Generic statistics -statsPageCookieHeadersFoiled=<a href='https://en.wikipedia.org/wiki/HTTP_cookie'>HTTP cookie</a> headers foiled: {{count}} -statsPageRefererHeadersFoiled=<a href='https://en.wikipedia.org/wiki/HTTP_referer'>HTTP referer</a> headers foiled: {{count}} -statsPageHyperlinkAuditingFoiled=<a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>Hyperlink auditing</a> attempts foiled: {{count}} -statsPageCookiesRemoved=Local cookies removed: {{count}} -statsPageLocalStoragesCleared=<a href='http://diveintohtml5.info/storage.html'>Local storages</a> emptied: {{count}} -statsPageBrowserCacheCleared=Browser caches cleared: {{count}} -statsPageDetailedStats=Detailed statistics -statsPageDetailedAllPages=All -statsPageDetailedBehindTheScenePage=Behind the scene -statsPageOverview=Overview -statsPageRequests=Requests -statsPageAllowed=Allowed -statsPageBlocked=Blocked -statsPageAll=Vse -statsPagePages=Strani -statsPageCookies=Piškotki -statsPageCSS=CSS -statsPageImages=Images -statsPagePlugins=Plugins -statsPageScripts=Scripts -statsPageXHRs=XHRs -statsPageFrames=Frames -statsPageOthers=Others -statsPageDetailed=Logger -statsPageLogSizePrompt1=Remember the last -statsPageLogSizePrompt2=HTTP requests <b>per page</b>. -statsPageLogSizeHelp=<p>You can inspect details of the most recent raw HTTP requests which have been made by a web page (see below).</p><p>This is mostly useful to advanced users who want to investigate exactly what a web page has been doing. But logging these HTTP requests requires memory, and if you don't care about this technical information, then memory is being wasted.</p><p>Hence this field which lets you adjust the maximum number of the most recent HTTP requests which are to be logged for further inspection.</p><p>Enter “<code>0</code>” to turn off detailed logging (and consequently reduce the memory footprint of <i>ηMatrix</i>).</p> -statsPageRefresh=Refresh -settingsPageTitle=ηMatrix – Settings -settingsMatrixDisplayHeader=Matrix -settingsMatrixDisplayTextSizePrompt=Text size: -settingsMatrixDisplayTextSizeNormal=Normal -settingsMatrixDisplayTextSizeLarge=Large -settingsMatrixDisplayColorBlind=Color-blind friendly -settingsMatrixConvenienceHeader=Convenience -settingsDefaultScopeLevel=Default scope level: -settingsDefaultScopeLevel0=Global -settingsDefaultScopeLevel1=Domain -settingsDefaultScopeLevel2=Site -settingsMatrixAutoReloadPrompt=When the matrix is closed, smart reload these tabs: -settingsMatrixAutoReloadNone=None -settingsMatrixAutoReloadCurrent=Current -settingsMatrixAutoReloadAll=All -settingsMatrixAutoReloadInfo=Whenever you make changes in the matrix which can affect the display and/or behavior of one or more pages, <i>ηMatrix</i> will reload affected pages automatically when you close the matrix. -settingsSubframeColor=Blocked frames: Color -settingsSubframeOpacity=Opacity -settingsIconBadgeEnabled=Show the number of blocked requests on the icon -settingsCollapseBlocked=Collapse placeholder of blocked elements -settingsCollapseBlacklisted=Collapse placeholder of blacklisted elements -settingsNoscriptTagsSpoofed=Spoof <code><noscript></code> tags when 1st-party scripts are blocked -settingsCloudStorageEnabled=Enable cloud storage support -privacyPageTitle=ηMatrix – Privacy -privacyDeleteBlockedCookiesPrompt=Delete blocked cookies. -privacyDeleteBlockedCookiesHelp=<p>Blacklisted cookies are not prevented by <i>ηMatrix</i> from entering your browser. However they are prevented from leaving your browser, which is what really matters. Not blocking cookies before they enter your browser gives you the opportunity to be informed that a site tried to use cookies, and furthermore to inspect their contents if you wish.</p><p>Once these blacklisted cookies have been accounted for by <i>ηMatrix</i>, they can be removed from your browser if you wish so.</p><p><b>Important note:</b> Extensions can make web requests during the course of their normal operation. These requests can result in cookies being created in the browser. If the hostname from where a cookie originate is not whitelisted, the cookie will be removed from the browser by <i>ηMatrix</i> if this option is checked. So be sure that the hostname(s) with which an extension communicate is whitelisted.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Delete non-blocked session cookies -privacyDeleteNonBlockedSessionCookiesPrompt2= minutes after the last time they have been used. -privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “A session cookie ... is erased when you end the browser session. The session cookie is stored in temporary memory and is not retained after the browser is closed.”</p><p>Except that this <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>might not be happening</a> in some browsers. Also, to some, having to close the browser in order for the session cookies to clear might not be early enough.</p> -privacyDeleteBlockedLocalStoragePrompt=Delete <a href='https://en.wikipedia.org/wiki/Web_storage'>local storage</a> content set by blocked hostnames -privacyDeleteBlockedLocalStorageHelp=TODO -privacyClearCachePrompt1=Clear browser cache every -privacyClearCachePrompt2=minutes. -privacyClearCacheHelp=<p>Some web sites are really bent on tracking you, so much that they will use not-so-nice tricks to work around whatever measures you take in order to not be tracked.</p><p>A few of these tricks rely<sup>[1, 2]</sup> on the <a href='https://en.wikipedia.org/wiki/Web_cache'>browser cache</a>, which content is often long lasting since rarely will users take the time to regularly clear their browser cache.</p><p>There is little inconvenience to clear the browser cache regularly (likelihood is that you won't notice when it happens), and the benefit is to prevent these obnoxious trackers from invading your privacy.</p><p>Check this option to have <i>ηMatrix</i> do it for you, at the interval you wish.</p><p>[1] <a href='https://grepular.com/Preventing_Web_Tracking_via_the_Browser_Cache'>“Preventing Web Tracking via the Browser Cache”</a>\n[2] <a href='http://lucb1e.com/rp/cookielesscookies/'>“Cookieless cookies”</a></p> -privacyProcessRefererPrompt=Spoof <a href='https://en.wikipedia.org/wiki/HTTP_referer'>HTTP referrer</a> string of third-party requests. -privacyProcessRefererHelp=From Wikipedia:<blockquote>HTTP referer is an HTTP header field that identifies the address of the webpage that linked to the resource being requested. ... <b>Because referer information can violate privacy, some web browsers allow the user to disable the sending of referer information.</b></blockquote>If this setting is checked, <i>ηMatrix</i> will spoof the HTTP referrer information if the domain name of the HTTP referrer is third-party to the domain name of net request. -privacyNoMixedContentPrompt=Strict HTTPS: forbid mixed content. -privacyNoMixedContentHelp=<p>From <a href='https://developer.mozilla.org/en-US/docs/Security/MixedContent'>Mozilla Developer Network</a>:</p><blockquote>If [a] HTTPS page includes content retrieved through regular, cleartext HTTP, then the connection is only partially encrypted: the unencrypted content is accessible to sniffers and can be modified by man-in-the-middle attackers, and therefore the connection is not safeguarded anymore. When a webpage exhibits this behavior, it is called a mixed content page.</blockquote> -privacyProcessHyperlinkAuditingPrompt=Block all <a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>hyperlink auditing</a> attempts. -privacyProcessHyperlinkAuditingHelp=<p>Hyperlink auditing is a mechanism which allow a party, <b>any party</b>, to be informed about which link a user clicked on a particular web page. It is essentially a tracking feature: it allows a web site, or any third-party to that web site, to be informed about which link you clicked on which one of its web pages. The sole purpose is to track your browsing activity.</p> -userRulesPermanentHeader=Permanent rules -userRulesTemporaryHeader=Temporary rules -userRulesRevert=Revert -userRulesCommit=Commit -userRulesEdit=Edit -userRulesEditSave=Save -userRulesEditDicard=Discard -userRulesImport=Import from file... -userRulesExport=Export to file... -userRulesFormatHint=See this page for rule syntax. -userRulesDefaultFileName=my-ematrix-rules.txt -hostsFilesPrompt=All hostnames in a hosts file are loaded as blacklisted hostnames in the global scope. -hostsFilesStats={{blockedHostnameCount}} distinct blocked hostnames from: -hostsFilesPerFileStats={{used}} used out of {{total}} -hostsFilesLastUpdate=Last update: {{ago}} -hostsFilesApplyChanges=Apply changes -hostsFilesAutoUpdatePrompt=Auto-update hosts files. -hostsFilesUpdateNow=Update now -hostsFilesPurgeAll=Purge all caches -hostsFilesExternalListsHint=One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored. -hostsFilesExternalListsParse=Parse -hostsFilesExternalListPurge=purge cache -hostsFilesExternalListNew=new version available -hostsFilesExternalListObsolete=outdated -rawSettingsWarning=Warning! Change these raw configuration settings at your own risk. -aboutChangelog=Change log -aboutStorageUsed=Storage used: {{storageUsed}} bytes -aboutDoc=Documentation -aboutPermissions=Permissions -aboutCode=Source code (GPLv3) -aboutIssues=Bugs and issues -aboutContributors=Contributors -aboutCodeContributors=Code: -aboutIssueContributors=Issues: -aboutTranslationContributors=Translations: -aboutUserDataHeader=Your data -aboutBackupButton=Backup to file... -aboutBackupFilename=my-ematrix-backup.txt -aboutRestoreButton=Restore from file... -aboutRestoreConfirm=All your settings will be overwritten using data backed up on {{time}}, and ηMatrix will restart.\n\nOverwrite all existing settings using backed up data? -aboutRestoreError=The data could not be read or is invalid -aboutOr=... or ... -aboutResetButton=Reset to default settings -aboutResetConfirm=Caution! this will remove all your custom settings. Are you sure you want to proceed? -loggerFilterInputPlaceholder=filter expression(s) -loggerMaxEntriesTip=Maximum number of entries -loggerEntryCookieDeleted=cookie deleted: {{value}} -loggerEntryDeleteCookieError=failed to delete cookie: {{value}} -loggerEntryBrowserCacheCleared=browser cache cleared -loggerEntryAssetUpdated=asset updated: {{value}} -mainBlockedPrompt1=ηMatrix has prevented the following page from loading: -mainBlockedPrompt2=Because of the following rule -mainBlockedBack=Go back -mainBlockedClose=Close -commandRevertAll=Revert all temporary changes -commandWhitelistPageDomain=Temporarily whitelist page domain -commandWhitelistAll=Temporarily whitelist all -commandOpenDashboard=Open dashboard -elapsedOneMinuteAgo=a minute ago -elapsedManyMinutesAgo={{value}} minutes ago -elapsedOneHourAgo=an hour ago -elapsedManyHoursAgo={{value}} hours ago -elapsedOneDayAgo=a day ago -elapsedManyDaysAgo={{value}} days ago -showDashboardButton=Dashboard -showLoggerButton=Logger -cloudPush=Export to cloud storage -cloudPull=Import from cloud storage -cloudNoData=...\n... -cloudDeviceNamePrompt=This device name: -genericSubmit=Submit -genericRevert=Revert -errorCantConnectTo=Network error: Unable to connect to {{url}} -genericApplyChanges=Apply changes -noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can display some content by using the <noscript> tag. For example, some websites will redirect users to a “scriptless” version.</p><p>When ηMatrix blocks scripts, the browser will still advertise itself as supporting script execution unless this option is selected.</p><p>When selected, ηMatrix will tell the website that the browser does not support scripts, which is what you definitely want to do if you are blocking 1st-party scripts. As such, the <noscript> tag will work as intended.</p><p>Not selecting this option when 1st-party scripts are blocked means the website will break misteryously in case it is meant to redirect to a scriptless version.</p> -settingsUpdateIcon=Do not change the toolbar icon -updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> -resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> diff --git a/locale/sr/messages.properties b/locale/sr/messages.properties deleted file mode 100644 index e918101..0000000 --- a/locale/sr/messages.properties +++ /dev/null @@ -1,186 +0,0 @@ -extName=ηMatrix -dashboardPageName=ηMatrix — Контролна табла -loggerPageName=ηMatrix — Евиденција -settingsPageName=Подешавања -privacyPageName=Приватност -statsPageName=Статистика -userRulesPageName=Моја правила -ubiquitousRulesPageName=Хост датотеке -rawSettingsPageName=Више -aboutPageName=О програму -allPrettyName=све -cookiePrettyName=колачић -cssPrettyName=css -imagePrettyName=слика -mediaPrettyName=медији -pluginPrettyName=прикључак -scriptPrettyName=скрипта -xhrPrettyName=XHR -framePrettyName=оквир -otherPrettyName=остало -matrixNoNetTrafficPrompt=Нема мрежних активности на овој картици. -matrixMtxButtonTip=Омогући/онемогући матрично филтрирање за ову област. -matrixPersistButtonTip=Сачувај све привремене измене за ову област. -matrixRevertButtonTip=Врати привремене измене за ову област. -matrixReloadButton=Поново учитај страницу. -matrixScopeTip=Change to global scope. -matrixSwitchesTip=Dropdown menu with additional settings. -matrix1stPartyLabel=Тренутни домен -matrixBlacklistedHostnames=забрањених сајтова: {{count}} -matrixSwitchNoMixedContent=Забрани мешовити садржај -matrixSwitchNoWorker=Забрани веб радне скрипте -matrixSwitchReferrerSpoof=Referrer лажирање -matrixSwitchNoscriptSpoof=Лажирање <code><noscript></code> тагова -matrixRevertAllEntry=Врати све привремене измене -matrixLoggerMenuEntry=Иди на евиденцију -matrixDashboardMenuEntry=Иди на контролну таблу -matrixNoTabFound=Ниједна веб страница није пронађена -statsPageTitle=ηMatrix – Статистика -statsPageGenericStats=Општа статистика -statsPageCookieHeadersFoiled=<a href='https://en.wikipedia.org/wiki/HTTP_cookie'>HTTP cookie</a> блокираних заглавља: {{count}} -statsPageRefererHeadersFoiled=<a href='https://en.wikipedia.org/wiki/HTTP_referer'>HTTP referer</a> блокираних заглавља: {{count}} -statsPageHyperlinkAuditingFoiled=Блокираних покушаја <a href='http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#hyperlink-auditing'>надгледања хипервеза</a>: {{count}} -statsPageCookiesRemoved=Уклоњено локалних колачића: {{count}} -statsPageLocalStoragesCleared=<a href='http://diveintohtml5.info/storage.html'>Локалних складишта</a> испражњено: {{count}} -statsPageBrowserCacheCleared=Очишћено кеша прегледача: {{count}} -statsPageDetailedStats=Детаљна статистика -statsPageDetailedAllPages=Све -statsPageDetailedBehindTheScenePage=Скривени захтеви -statsPageOverview=Преглед -statsPageRequests=Захтеви -statsPageAllowed=Дозвољено -statsPageBlocked=Блокирано -statsPageAll=Све -statsPagePages=Странице -statsPageCookies=Колачићи -statsPageCSS=CSS -statsPageImages=Слике -statsPagePlugins=Прикључци -statsPageScripts=Скрипте -statsPageXHRs=XHR -statsPageFrames=Оквири -statsPageOthers=Остало -statsPageDetailed=Евиденција -statsPageLogSizePrompt1=Запамти последње -statsPageLogSizePrompt2=HTTP захтеви <b>по страници</b>. -statsPageLogSizeHelp=<p>Можете прегледати детаље најновијих HTTP захтева креираних од стране веб странице (видети испод).</p><p>Ово је нарочито корисно напредним корисницима који желе да сазнају шта је тачно страница радила. Али за евидентирање ових HTTP захтева потребна је меморија, па ако вам није битна ова техничка информација, то значи повећање заузећа меморије.</p><p>Дакле, ово поље вам омогућава да подесите максимални број најновијих HTTP захтева које треба да се евидентирају ради даљег испитивања.</p><p>Унесите “<code>0</code>” за искључивање детаљног евидентирања (и смањења заузећа меморије од стране додатка <i>ηMatrix</i>).</p> -statsPageRefresh=Освежи -settingsPageTitle=ηMatrix – Подешавања -settingsMatrixDisplayHeader=Изглед -settingsMatrixDisplayTextSizePrompt=Величина текста: -settingsMatrixDisplayTextSizeNormal=Нормалан -settingsMatrixDisplayTextSizeLarge=Велики -settingsMatrixDisplayColorBlind=Шема боја за далтонисте -settingsMatrixConvenienceHeader=Погодност -settingsDefaultScopeLevel=Подразумевани ниво опсега: -settingsDefaultScopeLevel0=Глобално -settingsDefaultScopeLevel1=Домен -settingsDefaultScopeLevel2=Сајт -settingsMatrixAutoReloadPrompt=Приликом затварања матрице, паметно обнови ове картице: -settingsMatrixAutoReloadNone=Ниједан -settingsMatrixAutoReloadCurrent=Тренутни -settingsMatrixAutoReloadAll=Све -settingsMatrixAutoReloadInfo=Када год начините измене у матрици које могу утицати на приказ и/или понашање једне или више страница, <i>ηMatrix</i> ће аутоматски поново учитати погођене странице када будете затворили матрицу. -settingsSubframeColor=Блокираних оквира: Боја -settingsSubframeOpacity=Непрозирност -settingsIconBadgeEnabled=Show the number of blocked requests on the icon -settingsCollapseBlocked=Скупи држач блокираних елемената -settingsCollapseBlacklisted=Скупи држач елемената на црној листи -settingsNoscriptTagsSpoofed=Лажирај <code><noscript></code> тагове када су скрипте прве стране блокиране -settingsCloudStorageEnabled=Омогући подршку складиштења у облаку -privacyPageTitle=ηMatrix – Приватност -privacyDeleteBlockedCookiesPrompt=Избриши блокиране колачиће. -privacyDeleteBlockedCookiesHelp=<p><i>ηMatrix</i> не спречава улазак блокираних колачића у ваш прегледач али их спречава да га напусте и то је оно што је у ствари важно. Неблокирање колачића пре него што уђу у прегледач вам даје могућност да будете упознати са тим да сајт покушава да користи колачиће, као и да испитујете њихов садржај, уколико то желите.</p><p>Чим <i>ηMatrix</i> обрачуна ове колачиће, можете их уклонити ако то желите.</p><p><b>Важна напомена</b>Проширења могу креирати веб захтеве током свог нормалног рада. Ови захтеви могу довести до креирања колачића у прегледачу. Ако сајт одакле потиче колачић није на белој листи, онда ће <i>ηMatrix</i> уклонити колачић из прегледача ако је ова опција омогућена. Зато будите сигурни да сајт са којим проширење комуницира буде на белој листи.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Избриши неблокиране колачиће сесије -privacyDeleteNonBlockedSessionCookiesPrompt2= минута након последњег коришћења. -privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “Колачић сесије ... се брише када завршите сесију прегледача. Колачић сесије се чува у привременој меморији и не задржава се после затварања прегледача.”</p><p>С тим да се ово<a href='https://code.google.com/p/chromium/issues/detail?id=128513'>можда неће десити</a> у појединим прегледачима. Такође, затварање прегледача због брисања колачића сесије можда неће бити довољно брзо.</p> -privacyDeleteBlockedLocalStoragePrompt=Избриши садржај <a href='https://ru.wikipedia.org/wiki/Web_storage'>локалног складишта</a> блокираних сајтова -privacyDeleteBlockedLocalStorageHelp=Листа задатака -privacyClearCachePrompt1=Очисти кеш прегледача сваких -privacyClearCachePrompt2=минута. -privacyClearCacheHelp=<p>Неки веб сајтови су стварно решени да вас прате, толико да ће користити не баш лепе трикове да би заобишли све мере које предузимате да бисте избегли праћење.</p><p>Неко од ових трикова се заснивају<sup style='font-size:smaller'>[1, 2]</sup>на<a href='https://en.wikipedia.org/wiki/Web_cache'>кешу прегледача</a>,чији је садржај често дуготрајан, пошто корисници ретко одвајају мало времена да редовно чисте кеш прегледача.</p><p>Мало је непријатно редовно чистити кеш прегледача, а корист се огледа у томе да се спрече ови одвратни трагачи да упадају у вашу приватност.</p><p>Омогућите ову опцију да <i>ηMatrix</i> то ради уместо вас, у временском интервалу који желите.</p><p style='font-size:smaller'>[1] <a href='https://grepular.com/Preventing_Web_Tracking_via_the_Browser_Cache'>“Спречавање веб праћења преко кеша прегледача”</a><br>[2] <a href='http://lucb1e.com/rp/cookielesscookies/'>“Cookieless cookies”</a></p> -privacyProcessRefererPrompt=Лажирај низ <a href='https://ru.wikipedia.org/wiki/HTTP_referer'>HTTP referrer</a> за захтеве трећих страна. -privacyProcessRefererHelp=<p>Са Википедије</p><blockquote>HTTP referer је HTTP заглавље које идентификује адресу веб странице који је повезан са извором који се тражи. ... <b>Пошто ове информације могу нарушити приватност, неки прегледачи дозвољавају корисницима да онемогуће слање ових информација.</b></blockquote><p>Ако је ова опција омогућена, <i>ηMatrix</i> ће лажирати информацију ако је сајт, наведен у HTTP referrer, трећа страна у односу на захтевани. -privacyNoMixedContentPrompt=Само HTTPS: забрани мешани садржај. -privacyNoMixedContentHelp=<p>Са<a href='https://developer.mozilla.org/en-US/docs/Security/MixedContent'>Mozilla Developer Network</a>:</p><blockquote>Ако [a] HTTPS страница укључује садржај који се преузима преко редовног,отвореног HTTP, веза је делимично кодирана: некодираном садржају се може приступити и може бити мењан, тако да веза више није безбедна. Таква веб страница се зове страница са мешаним садржајем.</blockquote> -privacyProcessHyperlinkAuditingPrompt=Блокирај све покушаје <a href='http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#hyperlink-auditing'>надгледања хипервеза</a>. -privacyProcessHyperlinkAuditingHelp=<p>Надгледање хипервеза је механизам који дозвољава страни, <b>било којој страни</b>, да се информише о томе коју везу је корисник отворио на одређеној страници. То је у суштини функција праћења: дозвољава веб сајту или некој трећој страни да се информише о томе коју везу сте отворили на којој веб страници. Једина сврха је праћење активности корисника.</p> -userRulesPermanentHeader=Трајна правила -userRulesTemporaryHeader=Привремена правила -userRulesRevert=Врати -userRulesCommit=Потврди -userRulesEdit=Уреди -userRulesEditSave=Сачувај -userRulesEditDicard=Одбаци -userRulesImport=Увези из датотеке... -userRulesExport=Извези као датотеку... -userRulesFormatHint=Правила синтаксе можете погледати на овој страници. -userRulesDefaultFileName=my-ematrix-rules.txt -hostsFilesPrompt=Сви сајтови у хост датотеци су учитани као блокирани на глобалном нивоу. -hostsFilesStats={{blockedHostnameCount}} појединачних блокираних хостова из: -hostsFilesPerFileStats={{used}} искоришћено од {{total}} -hostsFilesLastUpdate=Последње ажурирање: {{ago}} -hostsFilesApplyChanges=Примени измене -hostsFilesAutoUpdatePrompt=Аутоматски обнови хост датотеке. -hostsFilesUpdateNow=Ажурирај сада -hostsFilesPurgeAll=Очисти сав кеш -hostsFilesExternalListsHint=Један URL по линији. Линије које почињу симболом ‘#’ ће бити игнорисане. Неважеће адресе ће бити тихо игнорисане. -hostsFilesExternalListsParse=Анализирај -hostsFilesExternalListPurge=очисти кеш -hostsFilesExternalListNew=доступна нова верзија -hostsFilesExternalListObsolete=застарело -rawSettingsWarning=Упозорење! Мењате ова конфигурацијска подешавања на сопствени ризик. -aboutChangelog=Списак измена -aboutStorageUsed=Искоришћеност складишта: {{storageUsed}} бајтова -aboutDoc=Документација -aboutPermissions=Дозволе -aboutCode=Изворни код (GPLv3) -aboutIssues=Грешке и проблеми -aboutContributors=Сарадници -aboutCodeContributors=Код: -aboutIssueContributors=Проблеми: -aboutTranslationContributors=Преводи: -aboutUserDataHeader=Ваши подаци -aboutBackupButton=Сачувај резервну копију... -aboutBackupFilename=my-ematrix-backup.txt -aboutRestoreButton=Обнови из датотеке... -aboutRestoreConfirm=Сва ваша подешавања ће бити замењена резервном копијом од {{time}}, и ηMatrix ће бити поново покренут.\n\nЗаменити сва постојећа подешавања резервном копијом? -aboutRestoreError=Подаци се не могу прочитати или су неважећи -aboutOr=... или ... -aboutResetButton=Врати на подразумевана подешавања -aboutResetConfirm=Пажња! Ово ће уклонити ваша прилагођена подешавања. Да ли сте сигурни да желите да наставите? -loggerFilterInputPlaceholder=филтрирање израза -loggerMaxEntriesTip=Највећи број уноса -loggerEntryCookieDeleted=колачића избрисано: {{value}} -loggerEntryDeleteCookieError=неуспелих брисања колачића: {{value}} -loggerEntryBrowserCacheCleared=кеш прегледача очишћен -loggerEntryAssetUpdated=ажурираних средстава: {{value}} -mainBlockedPrompt1=ηMatrix је спречио учитавање следеће странице: -mainBlockedPrompt2=Због следећег правила -mainBlockedBack=Назад -mainBlockedClose=Затвори -commandRevertAll=Врати све привремене измене -commandWhitelistPageDomain=Привремено дозволи домен странице -commandWhitelistAll=Привремено дозволи све -commandOpenDashboard=Отвори контролну таблу -elapsedOneMinuteAgo=пре једног минута -elapsedManyMinutesAgo=пре {{value}} минута -elapsedOneHourAgo=пре сат времена -elapsedManyHoursAgo=пре {{value}} сата/и -elapsedOneDayAgo=пре једног дана -elapsedManyDaysAgo=пре {{value}} дана -showDashboardButton=Контролна табла -showLoggerButton=Евиденција -cloudPush=Извези у складиште у облаку -cloudPull=Увези из складишта у облаку -cloudNoData=...\n... -cloudDeviceNamePrompt=Име овог уређаја: -genericSubmit=Проследи -genericRevert=Врати -errorCantConnectTo=Грешка на мрежи: Ни може се повезати на {{url}} -genericApplyChanges=Примени промене -noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can display some content by using the <noscript> tag. For example, some websites will redirect users to a “scriptless” version.</p><p>When ηMatrix blocks scripts, the browser will still advertise itself as supporting script execution unless this option is selected.</p><p>When selected, ηMatrix will tell the website that the browser does not support scripts, which is what you definitely want to do if you are blocking 1st-party scripts. As such, the <noscript> tag will work as intended.</p><p>Not selecting this option when 1st-party scripts are blocked means the website will break misteryously in case it is meant to redirect to a scriptless version.</p> -settingsUpdateIcon=Do not change the toolbar icon -updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> -resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> diff --git a/locale/sv/messages.properties b/locale/sv/messages.properties index 731cdfe..850de0f 100644 --- a/locale/sv/messages.properties +++ b/locale/sv/messages.properties @@ -91,7 +91,7 @@ settingsCloudStorageEnabled=Stöd för lagring i molnet privacyPageTitle=ηMatrix – Integritet privacyDeleteBlockedCookiesPrompt=Ta bort blockerade kakor. privacyDeleteBlockedCookiesHelp=<p>Svartlistade kakor hindras inte från att hamna i din webbläsare av <i>ηMatrix</i>. De är dock skyddade från att lämna webbläsaren, vilket är det som räknas. Genom att inte blockera kakor från att hamna i din webbläsare får du möjligheten att se om en sida försökt att använda sig av kakor och du kan undersöka kakornas innehåll.</p><p>När kakorna har passerat <i>ηMatrix</i>, kan de raderas om du så önskar.</p><p><b>Viktigt:</b> Webbläsartillägg kan göra förfrågningar till webben medan de arbetar. Dessa förfrågningar kan resultera i att kakor skapas i webbläsaren. Om värdnamnet för vilken en kaka kommer ifrån inte är vitlistat kommer kakan att tas bort av <i>ηMatrix</i> om det är så inställt. Därför är det viktigt att kontrollera att värdnamnen som tillägg använder för att kommunicera är vitlistade.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Ta bort icke-blockerade sessionskakor +privacyDeleteNonBlockedSessionCookiesPrompt1=Ta bort icke-blockerade sessionskakor privacyDeleteNonBlockedSessionCookiesPrompt2= minuter efter att de senast användes. privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “En sessionskaka ... raderas efter webbläsarens session avslutas. Sessionskakan lagras i ett temporärt minne och sparas inte när webbläsaren stängs.”</p><p>Förutom att det <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>kanske inte alltid fungerar så</a> i vissa webbläsare. För vissa personer är det inte tidigt nog att rensa kakorna när webbläsaren stängs.</p> privacyDeleteBlockedLocalStoragePrompt=Radera <a href='https://en.wikipedia.org/wiki/Web_storage'>lokala lagringar</a> för blockerade värdar @@ -115,7 +115,7 @@ userRulesEditDicard=Avbryt userRulesImport=Importera från fil... userRulesExport=Exportera till fil... userRulesFormatHint=Läs denna sida för regelsyntax. -userRulesDefaultFileName=mina-ematrix-regler.txt +userRulesDefaultFileName=mina-umatrix-regler.txt hostsFilesPrompt=Alla värdnamn i värdnamnsfilen är laddade för att svartlista värdnamn i det globala tillämpningsområdet. hostsFilesStats={{blockedHostnameCount}} distinkt blockerade värdnamn från: hostsFilesPerFileStats={{used}} använda av {{total}} @@ -124,7 +124,7 @@ hostsFilesApplyChanges=Verkställ ändringar hostsFilesAutoUpdatePrompt=Uppdatera värdnamsfiler automatiskt. hostsFilesUpdateNow=Uppdatera nu hostsFilesPurgeAll=Töm alla cachar -hostsFilesExternalListsHint=En adress per rad. Rader som börjar med ‘#’ ignoreras. Inkorrekta adresser ignoreras utan varning. +hostsFilesExternalListsHint=<p>One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored.</p><p>The inserted URL must point to a hosts file (including local files); do not use the hosts file syntax here.</p> hostsFilesExternalListsParse=Läs in hostsFilesExternalListPurge=rensa cache hostsFilesExternalListNew=ny version tillgänglig @@ -142,7 +142,7 @@ aboutIssueContributors=Problem: aboutTranslationContributors=Översättningar: aboutUserDataHeader=Din data aboutBackupButton=Säkerhetskopia till fil... -aboutBackupFilename=min-ematrix-säkerhetskopia.txt +aboutBackupFilename=min-umatrix-säkerhetskopia.txt aboutRestoreButton=Återställ från fil... aboutRestoreConfirm=Alla dina inställningar kommer att skrivas över med data från {{time}} och ηMatrix kommer att startas om.\n\nVill du skriva över de existerande inställningarna med data från säkerhetskopian? aboutRestoreError=Data kunde inte läsas in ordentligt @@ -183,4 +183,6 @@ noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can dis settingsUpdateIcon=Do not change the toolbar icon updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +resolveCnameHelp=<p>When resolving an address with DNS, some webistes use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +settingsTextSmaller=Smaller +settingsTextBigger=Bigger diff --git a/locale/te/messages.properties b/locale/te/messages.properties deleted file mode 100644 index 2f88024..0000000 --- a/locale/te/messages.properties +++ /dev/null @@ -1,186 +0,0 @@ -extName=ηMatrix -dashboardPageName=ηMatrix — Dashboard -loggerPageName=ηMatrix — Logger -settingsPageName=ఐచ్చికాలు -privacyPageName=గోప్యత -statsPageName=గణాంకాలు -userRulesPageName=నా నియమాలు -ubiquitousRulesPageName=హోస్ట్ ఫైల్లు -rawSettingsPageName=More -aboutPageName=మా గురించి -allPrettyName=అన్ని -cookiePrettyName=కుక్కి -cssPrettyName=సిఎస్ఎస్ -imagePrettyName=చిత్రం -mediaPrettyName=media -pluginPrettyName=పొడిగింపు -scriptPrettyName=స్క్రిప్ట్ -xhrPrettyName=XHR -framePrettyName=ఫ్రేమ్ -otherPrettyName=ఇతర -matrixNoNetTrafficPrompt=No net traffic seen for this tab so far. -matrixMtxButtonTip=Disable/enable matrix filtering for this scope. -matrixPersistButtonTip=Save all temporary changes for this scope. -matrixRevertButtonTip=Revert temporary changes for this scope. -matrixReloadButton=Reload the page.\nPress Shift to bypass the browser cache. -matrixScopeTip=Change to global scope. -matrixSwitchesTip=Dropdown menu with additional settings. -matrix1stPartyLabel=1st-party -matrixBlacklistedHostnames={{count}} blacklisted hostname(s) -matrixSwitchNoMixedContent=Forbid mixed content -matrixSwitchNoWorker=Forbid web workers -matrixSwitchReferrerSpoof=Spoof <code>Referer</code> header -matrixSwitchNoscriptSpoof=Spoof <code><noscript></code> tags -matrixRevertAllEntry=Revert all temporary changes -matrixLoggerMenuEntry=Go to logger -matrixDashboardMenuEntry=Go to dashboard -matrixNoTabFound=No web page found -statsPageTitle=ηMatrix – Statistics -statsPageGenericStats=Generic statistics -statsPageCookieHeadersFoiled=<a href='https://en.wikipedia.org/wiki/HTTP_cookie'>HTTP cookie</a> headers foiled: {{count}} -statsPageRefererHeadersFoiled=<a href='https://en.wikipedia.org/wiki/HTTP_referer'>HTTP referer</a> headers foiled: {{count}} -statsPageHyperlinkAuditingFoiled=<a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>Hyperlink auditing</a> attempts foiled: {{count}} -statsPageCookiesRemoved=Local cookies removed: {{count}} -statsPageLocalStoragesCleared=<a href='http://diveintohtml5.info/storage.html'>Local storages</a> emptied: {{count}} -statsPageBrowserCacheCleared=Browser caches cleared: {{count}} -statsPageDetailedStats=Detailed statistics -statsPageDetailedAllPages=All -statsPageDetailedBehindTheScenePage=Behind the scene -statsPageOverview=Overview -statsPageRequests=Requests -statsPageAllowed=Allowed -statsPageBlocked=Blocked -statsPageAll=అన్ని -statsPagePages=పేజీలు -statsPageCookies=కుక్కీలు -statsPageCSS=సిఎస్ఎస్ -statsPageImages=Images -statsPagePlugins=Plugins -statsPageScripts=Scripts -statsPageXHRs=XHRs -statsPageFrames=Frames -statsPageOthers=ఇతరులు -statsPageDetailed=Logger -statsPageLogSizePrompt1=Remember the last -statsPageLogSizePrompt2=HTTP requests <b>per page</b>. -statsPageLogSizeHelp=<p>You can inspect details of the most recent raw HTTP requests which have been made by a web page (see below).</p><p>This is mostly useful to advanced users who want to investigate exactly what a web page has been doing. But logging these HTTP requests requires memory, and if you don't care about this technical information, then memory is being wasted.</p><p>Hence this field which lets you adjust the maximum number of the most recent HTTP requests which are to be logged for further inspection.</p><p>Enter “<code>0</code>” to turn off detailed logging (and consequently reduce the memory footprint of <i>ηMatrix</i>).</p> -statsPageRefresh=Refresh -settingsPageTitle=ηMatrix – Settings -settingsMatrixDisplayHeader=Matrix -settingsMatrixDisplayTextSizePrompt=Text size: -settingsMatrixDisplayTextSizeNormal=Normal -settingsMatrixDisplayTextSizeLarge=Large -settingsMatrixDisplayColorBlind=Color-blind friendly -settingsMatrixConvenienceHeader=Convenience -settingsDefaultScopeLevel=Default scope level: -settingsDefaultScopeLevel0=Global -settingsDefaultScopeLevel1=Domain -settingsDefaultScopeLevel2=Site -settingsMatrixAutoReloadPrompt=When the matrix is closed, smart reload these tabs: -settingsMatrixAutoReloadNone=ఏదీకాదు -settingsMatrixAutoReloadCurrent=ప్రస్తుత -settingsMatrixAutoReloadAll=అన్ని -settingsMatrixAutoReloadInfo=Whenever you make changes in the matrix which can affect the display and/or behavior of one or more pages, <i>ηMatrix</i> will reload affected pages automatically when you close the matrix. -settingsSubframeColor=Blocked frames: Color -settingsSubframeOpacity=స్పష్టత -settingsIconBadgeEnabled=Show the number of blocked requests on the icon -settingsCollapseBlocked=నిరోధించబడిన అంశాలయోక్క సంగ్రాహకాలను దాచుము -settingsCollapseBlacklisted=Collapse placeholder of blacklisted elements -settingsNoscriptTagsSpoofed=Spoof <code><noscript></code> tags when 1st-party scripts are blocked -settingsCloudStorageEnabled=Enable cloud storage support -privacyPageTitle=ηMatrix – Privacy -privacyDeleteBlockedCookiesPrompt=Delete blocked cookies. -privacyDeleteBlockedCookiesHelp=<p>Blacklisted cookies are not prevented by <i>ηMatrix</i> from entering your browser. However they are prevented from leaving your browser, which is what really matters. Not blocking cookies before they enter your browser gives you the opportunity to be informed that a site tried to use cookies, and furthermore to inspect their contents if you wish.</p><p>Once these blacklisted cookies have been accounted for by <i>ηMatrix</i>, they can be removed from your browser if you wish so.</p><p><b>Important note:</b> Extensions can make web requests during the course of their normal operation. These requests can result in cookies being created in the browser. If the hostname from where a cookie originate is not whitelisted, the cookie will be removed from the browser by <i>ηMatrix</i> if this option is checked. So be sure that the hostname(s) with which an extension communicate is whitelisted.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Delete non-blocked session cookies -privacyDeleteNonBlockedSessionCookiesPrompt2= minutes after the last time they have been used. -privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “A session cookie ... is erased when you end the browser session. The session cookie is stored in temporary memory and is not retained after the browser is closed.”</p><p>Except that this <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>might not be happening</a> in some browsers. Also, to some, having to close the browser in order for the session cookies to clear might not be early enough.</p> -privacyDeleteBlockedLocalStoragePrompt=Delete <a href='https://en.wikipedia.org/wiki/Web_storage'>local storage</a> content set by blocked hostnames -privacyDeleteBlockedLocalStorageHelp=TODO -privacyClearCachePrompt1=Clear browser cache every -privacyClearCachePrompt2=నిమిషాలు. -privacyClearCacheHelp=<p>Some web sites are really bent on tracking you, so much that they will use not-so-nice tricks to work around whatever measures you take in order to not be tracked.</p><p>A few of these tricks rely<sup>[1, 2]</sup> on the <a href='https://en.wikipedia.org/wiki/Web_cache'>browser cache</a>, which content is often long lasting since rarely will users take the time to regularly clear their browser cache.</p><p>There is little inconvenience to clear the browser cache regularly (likelihood is that you won't notice when it happens), and the benefit is to prevent these obnoxious trackers from invading your privacy.</p><p>Check this option to have <i>ηMatrix</i> do it for you, at the interval you wish.</p><p>[1] <a href='https://grepular.com/Preventing_Web_Tracking_via_the_Browser_Cache'>“Preventing Web Tracking via the Browser Cache”</a>\n[2] <a href='http://lucb1e.com/rp/cookielesscookies/'>“Cookieless cookies”</a></p> -privacyProcessRefererPrompt=Spoof <a href='https://en.wikipedia.org/wiki/HTTP_referer'>HTTP referrer</a> string of third-party requests. -privacyProcessRefererHelp=From Wikipedia:<blockquote>HTTP referer is an HTTP header field that identifies the address of the webpage that linked to the resource being requested. ... <b>Because referer information can violate privacy, some web browsers allow the user to disable the sending of referer information.</b></blockquote>If this setting is checked, <i>ηMatrix</i> will spoof the HTTP referrer information if the domain name of the HTTP referrer is third-party to the domain name of net request. -privacyNoMixedContentPrompt=Strict HTTPS: forbid mixed content. -privacyNoMixedContentHelp=<p>From <a href='https://developer.mozilla.org/en-US/docs/Security/MixedContent'>Mozilla Developer Network</a>:</p><blockquote>If [a] HTTPS page includes content retrieved through regular, cleartext HTTP, then the connection is only partially encrypted: the unencrypted content is accessible to sniffers and can be modified by man-in-the-middle attackers, and therefore the connection is not safeguarded anymore. When a webpage exhibits this behavior, it is called a mixed content page.</blockquote> -privacyProcessHyperlinkAuditingPrompt=Block all <a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>hyperlink auditing</a> attempts. -privacyProcessHyperlinkAuditingHelp=<p>Hyperlink auditing is a mechanism which allow a party, <b>any party</b>, to be informed about which link a user clicked on a particular web page. It is essentially a tracking feature: it allows a web site, or any third-party to that web site, to be informed about which link you clicked on which one of its web pages. The sole purpose is to track your browsing activity.</p> -userRulesPermanentHeader=శాశ్వత నియమాలు -userRulesTemporaryHeader=తాత్కాలిక నియమాలు -userRulesRevert=Revert -userRulesCommit=భద్రపరచు -userRulesEdit=సవరించు -userRulesEditSave=భద్రపరచు -userRulesEditDicard=వదిలివేయు -userRulesImport=Import from file... -userRulesExport=Export to file... -userRulesFormatHint=See this page for rule syntax. -userRulesDefaultFileName=my-ematrix-rules.txt -hostsFilesPrompt=All hostnames in a hosts file are loaded as blacklisted hostnames in the global scope. -hostsFilesStats={{blockedHostnameCount}} distinct blocked hostnames from: -hostsFilesPerFileStats={{used}} used out of {{total}} -hostsFilesLastUpdate=Last update: {{ago}} -hostsFilesApplyChanges=మార్పులను అమలుపరచు -hostsFilesAutoUpdatePrompt=Auto-update hosts files. -hostsFilesUpdateNow=ఇప్పుడే నవీకరించు -hostsFilesPurgeAll=Purge all caches -hostsFilesExternalListsHint=One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored. -hostsFilesExternalListsParse=Parse -hostsFilesExternalListPurge=purge cache -hostsFilesExternalListNew=new version available -hostsFilesExternalListObsolete=outdated -rawSettingsWarning=Warning! Change these raw configuration settings at your own risk. -aboutChangelog=Change log -aboutStorageUsed=Storage used: {{storageUsed}} bytes -aboutDoc=Documentation -aboutPermissions=Permissions -aboutCode=Source code (GPLv3) -aboutIssues=Bugs and issues -aboutContributors=Contributors -aboutCodeContributors=Code: -aboutIssueContributors=Issues: -aboutTranslationContributors=Translations: -aboutUserDataHeader=Your data -aboutBackupButton=Backup to file... -aboutBackupFilename=my-ematrix-backup.txt -aboutRestoreButton=Restore from file... -aboutRestoreConfirm=All your settings will be overwritten using data backed up on {{time}}, and ηMatrix will restart.\n\nOverwrite all existing settings using backed up data? -aboutRestoreError=The data could not be read or is invalid -aboutOr=... or ... -aboutResetButton=Reset to default settings -aboutResetConfirm=Caution! this will remove all your custom settings. Are you sure you want to proceed? -loggerFilterInputPlaceholder=filter expression(s) -loggerMaxEntriesTip=Maximum number of entries -loggerEntryCookieDeleted=cookie deleted: {{value}} -loggerEntryDeleteCookieError=failed to delete cookie: {{value}} -loggerEntryBrowserCacheCleared=browser cache cleared -loggerEntryAssetUpdated=asset updated: {{value}} -mainBlockedPrompt1=ηMatrix has prevented the following page from loading: -mainBlockedPrompt2=Because of the following rule -mainBlockedBack=Go back -mainBlockedClose=Close -commandRevertAll=Revert all temporary changes -commandWhitelistPageDomain=Temporarily whitelist page domain -commandWhitelistAll=Temporarily whitelist all -commandOpenDashboard=Open dashboard -elapsedOneMinuteAgo=a minute ago -elapsedManyMinutesAgo={{value}} minutes ago -elapsedOneHourAgo=an hour ago -elapsedManyHoursAgo={{value}} hours ago -elapsedOneDayAgo=ఒక రోజు క్రితం -elapsedManyDaysAgo={{value}} days ago -showDashboardButton=Dashboard -showLoggerButton=Logger -cloudPush=Export to cloud storage -cloudPull=Import from cloud storage -cloudNoData=...\n... -cloudDeviceNamePrompt=This device name: -genericSubmit=Submit -genericRevert=Revert -errorCantConnectTo=Network error: Unable to connect to {{url}} -genericApplyChanges=Apply changes -noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can display some content by using the <noscript> tag. For example, some websites will redirect users to a “scriptless” version.</p><p>When ηMatrix blocks scripts, the browser will still advertise itself as supporting script execution unless this option is selected.</p><p>When selected, ηMatrix will tell the website that the browser does not support scripts, which is what you definitely want to do if you are blocking 1st-party scripts. As such, the <noscript> tag will work as intended.</p><p>Not selecting this option when 1st-party scripts are blocked means the website will break misteryously in case it is meant to redirect to a scriptless version.</p> -settingsUpdateIcon=Do not change the toolbar icon -updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> -resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> diff --git a/locale/tr/messages.properties b/locale/tr/messages.properties index 2e54752..21d86b9 100644 --- a/locale/tr/messages.properties +++ b/locale/tr/messages.properties @@ -91,7 +91,7 @@ settingsCloudStorageEnabled=Bulut depo desteğini etkinleştir privacyPageTitle=ηMatrix – Gizlilik privacyDeleteBlockedCookiesPrompt=Engellenmiş çerezleri sil. privacyDeleteBlockedCookiesHelp=<p>Kara listelenmiş çerezlerin tarayıcınıza girmesi <i>ηMatrix</i> tarafından önlenmez. Ancak tarayıcınızdan çıkışları önlenir, önemli olan da budur. Çerezlerin tarayıcınıza girişi önlenmeyerek sitenin çerez kullanımı hakkında bilgi sahibi olma fırsatını elde edersiniz ve üstelik dilerseniz içeriklerini de denetleyebilirsiniz.</p><p>Bu engellenmiş çerezler bir kere <i>ηMatrix</i> tarafından raporlandıktan sonra eğer isterseniz tabi tarayıcınızdan kaldırılabilir.</p><p><b>Önemli not:</b> Eklentiler normal işleyişleri sırasında web isteği yapabilir. Bu istekler tarayıcınızda çerez oluşumuna neden olur. Bu seçenek işaretli ve çerezin geldiği alan adı beyaz listede değilse bu çerez <i>ηMatrix</i> tarafından tarayıcınızdan kaldırılacaktır. Bu yüzden eklentilerin iletişim kurduğu alan ad(lar)ının beyaz listede bulunduğundan emin olunuz.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Engellenmemiş oturum çerezlerini son kullanımlarından +privacyDeleteNonBlockedSessionCookiesPrompt1=Engellenmemiş oturum çerezlerini son kullanımlarından privacyDeleteNonBlockedSessionCookiesPrompt2= dakika sonra sil. privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “Bir oturum çerezi ... tarayıcı oturumu sonlandığında silinir. Oturum çerezi geçici bellekte depolanır ve tarayıcı kapandıktan sonra muhafaza edilmez.”</p><p>Bazı tarayıcıları kullanırken <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>bu durum gerçekleşmeyebilir.</a> Ayrıca, bazılarımız için, oturum çerezlerinin temizlenmesi için tarayıcının kapatılması yeteri kadar erken olmayabilir.</p> privacyDeleteBlockedLocalStoragePrompt=Engellenmiş alan adları tarafından oluşturulmuş <a href='https://en.wikipedia.org/wiki/Web_storage'>Yerel depolama</a> içeriğini sil @@ -115,7 +115,7 @@ userRulesEditDicard=İptal et userRulesImport=Dosyadan içe aktar... userRulesExport=Dosyaya aktar... userRulesFormatHint=Kural sözdizimi için bu sayfaya bakın. -userRulesDefaultFileName=ematrix-kurallarim.txt +userRulesDefaultFileName=umatrix-kurallarim.txt hostsFilesPrompt=Alan adı dosyasındaki tüm alan adları genel kapsamda kara listeye yüklenir. hostsFilesStats={{blockedHostnameCount}} farklı engellenmiş alan adı: hostsFilesPerFileStats={{total}} süzgecin {{used}} adedi kullanıldı @@ -124,7 +124,7 @@ hostsFilesApplyChanges=Değişiklikleri uygula hostsFilesAutoUpdatePrompt=Alan adı dosyalarını otomatik olarak güncelle. hostsFilesUpdateNow=Şimdi güncelle hostsFilesPurgeAll=Tüm önbellekleri temizle -hostsFilesExternalListsHint=Satır başına tek URL. ‘#’ işareti ile başlayan satırlar yok sayılacaktır. Geçersiz URL'ler sessizcene yok sayılacaktır. +hostsFilesExternalListsHint=<p>One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored.</p><p>The inserted URL must point to a hosts file (including local files); do not use the hosts file syntax here.</p> hostsFilesExternalListsParse=Çözümle hostsFilesExternalListPurge=önbelleği temizle hostsFilesExternalListNew=yeni sürüm mevcut @@ -142,7 +142,7 @@ aboutIssueContributors=Sorunlar: aboutTranslationContributors=Çeviriler: aboutUserDataHeader=Verileriniz aboutBackupButton=Dosyaya yedekle... -aboutBackupFilename=ematrix-yedeklerim.txt +aboutBackupFilename=umatrix-yedeklerim.txt aboutRestoreButton=Dosyadan geri yükle... aboutRestoreConfirm={{time}} zamanında yedeklenmiş veri kullanılarak tüm ayarlarınızın üzerine yazılacak ve ηMatrix yeniden başlayacak.\n\nYedeklenmiş veri kullanılarak ayarlarınızın üzerine yazılsın mı? aboutRestoreError=Veri okunamadı veya geçersiz @@ -183,4 +183,6 @@ noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can dis settingsUpdateIcon=Do not change the toolbar icon updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +resolveCnameHelp=<p>When resolving an address with DNS, some webistes use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +settingsTextSmaller=Smaller +settingsTextBigger=Bigger diff --git a/locale/uk/messages.properties b/locale/uk/messages.properties index 9e03731..ef3b9c7 100644 --- a/locale/uk/messages.properties +++ b/locale/uk/messages.properties @@ -91,7 +91,7 @@ settingsCloudStorageEnabled=Увімкнути хмарне зберігання privacyPageTitle=ηMatrix – Приватність privacyDeleteBlockedCookiesPrompt=Видаляти заблоковані кукі. privacyDeleteBlockedCookiesHelp=<p>Blacklisted cookies are not prevented by <i>ηMatrix</i> from entering your browser. However they are prevented from leaving your browser, which is what really matters. Not blocking cookies before they enter your browser gives you the opportunity to be informed that a site tried to use cookies, and furthermore to inspect their contents if you wish.</p><p>Once these blacklisted cookies have been accounted for by <i>ηMatrix</i>, they can be removed from your browser if you wish so.</p><p><b>Important note:</b> Extensions can make web requests during the course of their normal operation. These requests can result in cookies being created in the browser. If the hostname from where a cookie originate is not whitelisted, the cookie will be removed from the browser by <i>ηMatrix</i> if this option is checked. So be sure that the hostname(s) with which an extension communicate is whitelisted.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Видаляти незаблоковані кукі сесій через +privacyDeleteNonBlockedSessionCookiesPrompt1=Видаляти незаблоковані кукі сесій через privacyDeleteNonBlockedSessionCookiesPrompt2= хвилин простою. privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “A session cookie ... is erased when you end the browser session. The session cookie is stored in temporary memory and is not retained after the browser is closed.”</p><p>Except that this <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>might not be happening</a> in some browsers. Also, to some, having to close the browser in order for the session cookies to clear might not be early enough.</p> privacyDeleteBlockedLocalStoragePrompt=Delete <a href='https://en.wikipedia.org/wiki/Web_storage'>local storage</a> content set by blocked hostnames @@ -115,7 +115,7 @@ userRulesEditDicard=Відхилити userRulesImport=Імпортувати з файлу... userRulesExport=Експортувати в файл... userRulesFormatHint=Дивися цю сторінку з правилами синтаксису. -userRulesDefaultFileName=my-ematrix-rules.txt +userRulesDefaultFileName=my-umatrix-rules.txt hostsFilesPrompt=Всі імена з файлу hosts були занесені до чорного списку у глобальному діапазоні. hostsFilesStats={{blockedHostnameCount}} унікальних імен заблоковано з: hostsFilesPerFileStats={{used}} використано з {{total}} @@ -124,7 +124,7 @@ hostsFilesApplyChanges=Застосувати зміни hostsFilesAutoUpdatePrompt=Автоматичне оновлення файлів hosts. hostsFilesUpdateNow=Оновити зараз hostsFilesPurgeAll=Відмінити усі зміни -hostsFilesExternalListsHint=Один URL на рядок. Рядки що починаються з ‘#’ будуть проігноровані. Неправильні URL будуть проігноровані. +hostsFilesExternalListsHint=<p>One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored.</p><p>The inserted URL must point to a hosts file (including local files); do not use the hosts file syntax here.</p> hostsFilesExternalListsParse=Обробити hostsFilesExternalListPurge=очистити кеш hostsFilesExternalListNew=є нова версія @@ -142,7 +142,7 @@ aboutIssueContributors=Проблеми: aboutTranslationContributors=Переклади: aboutUserDataHeader=Ваші дані aboutBackupButton=Зберегти резервну копію... -aboutBackupFilename=my-ematrix-backup.txt +aboutBackupFilename=my-umatrix-backup.txt aboutRestoreButton=Відновити з файлу... aboutRestoreConfirm=Усі налаштування будуть замінені даними з резервної копії від {{time}}, і ηMatrix буде перезавантажено.\n\nЗамінити усі існуючі дані? aboutRestoreError=Дані неправильні або недоступні @@ -183,4 +183,6 @@ noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can dis settingsUpdateIcon=Do not change the toolbar icon updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +resolveCnameHelp=<p>When resolving an address with DNS, some webistes use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +settingsTextSmaller=Smaller +settingsTextBigger=Bigger diff --git a/locale/vi/messages.properties b/locale/vi/messages.properties deleted file mode 100644 index 64a31fc..0000000 --- a/locale/vi/messages.properties +++ /dev/null @@ -1,186 +0,0 @@ -extName=ηMatrix -dashboardPageName=ηMatrix — Bảng điều khiển -loggerPageName=ηMatrix — Logger -settingsPageName=Cài đặt -privacyPageName=Riêng tư -statsPageName=Thống kê -userRulesPageName=Quy tắc riêng -ubiquitousRulesPageName=Tập tin máy chủ -rawSettingsPageName=More -aboutPageName=Thông tin -allPrettyName=tất cả -cookiePrettyName=cookie -cssPrettyName=css -imagePrettyName=ảnh -mediaPrettyName=media -pluginPrettyName=plugin -scriptPrettyName=script -xhrPrettyName=XHR -framePrettyName=frame -otherPrettyName=khác -matrixNoNetTrafficPrompt=Chưa phát hiện lưu lượng mạng trong thẻ này. -matrixMtxButtonTip=Vô hiệu/kích hoạt lọc ma trận cho phạm vi này.\nYêu cầu đã chặn thông qua lọc ma trận trên trang này: {{count}}. -matrixPersistButtonTip=Lưu tất cả thay đổi tạm thời cho phạm vi này. -matrixRevertButtonTip=Xoá thay đổi tạm thời của phạm vị này. -matrixReloadButton=Tải lại trang. -matrixScopeTip=Change to global scope. -matrixSwitchesTip=Dropdown menu with additional settings. -matrix1stPartyLabel=bên thứ nhất -matrixBlacklistedHostnames={{count}} tên máy chủ trong danh sách đen -matrixSwitchNoMixedContent=HTTPS nghiêm ngặt -matrixSwitchNoWorker=Forbid web workers -matrixSwitchReferrerSpoof=Giả tham chiếu -matrixSwitchNoscriptSpoof=Spoof <code><noscript></code> tags -matrixRevertAllEntry=Hủy các thay đổi tạm thời -matrixLoggerMenuEntry=Đến nhật ký -matrixDashboardMenuEntry=Đến bảng điều khiển -matrixNoTabFound=No web page found -statsPageTitle=Thống kê ηMatrix -statsPageGenericStats=Thống kê tổng quát -statsPageCookieHeadersFoiled=<a href='https://en.wikipedia.org/wiki/HTTP_cookie'>Đầu mục cookie HTTP</a> bị chặn: {{count}} -statsPageRefererHeadersFoiled=<a href='https://en.wikipedia.org/wiki/HTTP_cookie'>Đầu mục tham chiếu HTTP</a> bị chặn: {{count}} -statsPageHyperlinkAuditingFoiled=<a href='http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#hyperlink-auditing'>Cố gắng kiểm tra siêu liên kết</a> bị chặn: {{count}} -statsPageCookiesRemoved=Cookie trên máy đã xoá: {{count}} -statsPageLocalStoragesCleared=<a href='http://diveintohtml5.info/storage.html'>Lưu trữ trên máy</a> đã làm rỗng: {{count}} -statsPageBrowserCacheCleared=Bộ nhớ đệm trình duyệt đã xoá: {{count}} -statsPageDetailedStats=Thống kê chi tiết -statsPageDetailedAllPages=Tất cả -statsPageDetailedBehindTheScenePage=Yêu cầu ẩn -statsPageOverview=Tổng quan -statsPageRequests=Yêu cầu -statsPageAllowed=Đã cho phép -statsPageBlocked=Đã chặn -statsPageAll=Tất cả -statsPagePages=Trang -statsPageCookies=Cookie -statsPageCSS=CSS -statsPageImages=Ảnh -statsPagePlugins=Plugin -statsPageScripts=Script -statsPageXHRs=XHR -statsPageFrames=Frame -statsPageOthers=Khác -statsPageDetailed=Nhật ký yêu cầu -statsPageLogSizePrompt1=Nhớ mục cuối -statsPageLogSizePrompt2=Yêu cầu HTTP <b>mỗi trang</b>. -statsPageLogSizeHelp=<p>You can inspect details of the most recent raw HTTP requests which have been made by a web page (see below).</p><p>This is mostly useful to advanced users who want to investigate exactly what a web page has been doing. But logging these HTTP requests requires memory, and if you don't care about this technical information, then memory is being wasted.</p><p>Hence this field which lets you adjust the maximum number of the most recent HTTP requests which are to be logged for further inspection.</p><p>Enter “<code>0</code>” to turn off detailed logging (and consequently reduce the memory footprint of <i>ηMatrix</i>).</p> -statsPageRefresh=Tải lại -settingsPageTitle=Cài đặt ηMatrix -settingsMatrixDisplayHeader=Diện mạo -settingsMatrixDisplayTextSizePrompt=Cỡ chữ: -settingsMatrixDisplayTextSizeNormal=Thường -settingsMatrixDisplayTextSizeLarge=Lớn -settingsMatrixDisplayColorBlind=Thân thiện với người mù màu -settingsMatrixConvenienceHeader=Tiện lợi -settingsDefaultScopeLevel=Default scope level: -settingsDefaultScopeLevel0=Global -settingsDefaultScopeLevel1=Domain -settingsDefaultScopeLevel2=Site -settingsMatrixAutoReloadPrompt=Khi đã đóng ma trận, tải lại thông minh những thẻ này: -settingsMatrixAutoReloadNone=Không có -settingsMatrixAutoReloadCurrent=Hiện tại -settingsMatrixAutoReloadAll=Tất cả -settingsMatrixAutoReloadInfo=Bất cứ khi nào bạn tạo ra thay đổi trong ma trận có thể ảnh hưởng đến việc hiển thị và/hoặc hành vi của một hoặc nhiều trang, <i>ηMatrix</i> sẽ tự tải lại trang được ảnh hưởng khi bạn đóng ma trận. -settingsSubframeColor=Đã chặn frame: Màu -settingsSubframeOpacity=Độ mờ -settingsIconBadgeEnabled=Show the number of blocked requests on the icon -settingsCollapseBlocked=Collapse placeholder of blocked elements -settingsCollapseBlacklisted=Collapse placeholder of blacklisted elements -settingsNoscriptTagsSpoofed=Spoof <code><noscript></code> tags when 1st-party scripts are blocked -settingsCloudStorageEnabled=Enable cloud storage support -privacyPageTitle=ηMatrix – Riêng tư -privacyDeleteBlockedCookiesPrompt=Xoá cookie đã chặn. -privacyDeleteBlockedCookiesHelp=<p>Blacklisted cookies are not prevented by <i>ηMatrix</i> from entering your browser. However they are prevented from leaving your browser, which is what really matters. Not blocking cookies before they enter your browser gives you the opportunity to be informed that a site tried to use cookies, and furthermore to inspect their contents if you wish.</p><p>Once these blacklisted cookies have been accounted for by <i>ηMatrix</i>, they can be removed from your browser if you wish so.</p><p><b>Important note:</b> Extensions can make web requests during the course of their normal operation. These requests can result in cookies being created in the browser. If the hostname from where a cookie originate is not whitelisted, the cookie will be removed from the browser by <i>ηMatrix</i> if this option is checked. So be sure that the hostname(s) with which an extension communicate is whitelisted.</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=Xoá cookie phiên làm việc không được chặn -privacyDeleteNonBlockedSessionCookiesPrompt2= phút sau lần cuối chúng được dùng. -privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>: “A session cookie ... is erased when you end the browser session. The session cookie is stored in temporary memory and is not retained after the browser is closed.”</p><p>Except that this <a href='https://code.google.com/p/chromium/issues/detail?id=128513'>might not be happening</a> in some browsers. Also, to some, having to close the browser in order for the session cookies to clear might not be early enough.</p> -privacyDeleteBlockedLocalStoragePrompt=Delete <a href='https://en.wikipedia.org/wiki/Web_storage'>local storage</a> content set by blocked hostnames -privacyDeleteBlockedLocalStorageHelp=TODO -privacyClearCachePrompt1=Xoá bộ đệm trình duyệt mỗi -privacyClearCachePrompt2=phút. -privacyClearCacheHelp=<p>Some web sites are really bent on tracking you, so much that they will use not-so-nice tricks to work around whatever measures you take in order to not be tracked.</p><p>A few of these tricks rely<sup>[1, 2]</sup> on the <a href='https://en.wikipedia.org/wiki/Web_cache'>browser cache</a>, which content is often long lasting since rarely will users take the time to regularly clear their browser cache.</p><p>There is little inconvenience to clear the browser cache regularly (likelihood is that you won't notice when it happens), and the benefit is to prevent these obnoxious trackers from invading your privacy.</p><p>Check this option to have <i>ηMatrix</i> do it for you, at the interval you wish.</p><p>[1] <a href='https://grepular.com/Preventing_Web_Tracking_via_the_Browser_Cache'>“Preventing Web Tracking via the Browser Cache”</a>\n[2] <a href='http://lucb1e.com/rp/cookielesscookies/'>“Cookieless cookies”</a></p> -privacyProcessRefererPrompt=Spoof <a href='https://en.wikipedia.org/wiki/HTTP_referer'>HTTP referrer</a> string of third-party requests. -privacyProcessRefererHelp=From Wikipedia:<blockquote>HTTP referer is an HTTP header field that identifies the address of the webpage that linked to the resource being requested. ... <b>Because referer information can violate privacy, some web browsers allow the user to disable the sending of referer information.</b></blockquote>If this setting is checked, <i>ηMatrix</i> will spoof the HTTP referrer information if the domain name of the HTTP referrer is third-party to the domain name of net request. -privacyNoMixedContentPrompt=HTTPS nghiêm ngặt: chặn nội dung hỗn hợp. -privacyNoMixedContentHelp=<p>From <a href='https://developer.mozilla.org/en-US/docs/Security/MixedContent'>Mozilla Developer Network</a>:</p><blockquote>If [a] HTTPS page includes content retrieved through regular, cleartext HTTP, then the connection is only partially encrypted: the unencrypted content is accessible to sniffers and can be modified by man-in-the-middle attackers, and therefore the connection is not safeguarded anymore. When a webpage exhibits this behavior, it is called a mixed content page.</blockquote> -privacyProcessHyperlinkAuditingPrompt=Block all <a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>hyperlink auditing</a> attempts. -privacyProcessHyperlinkAuditingHelp=<p>Hyperlink auditing is a mechanism which allow a party, <b>any party</b>, to be informed about which link a user clicked on a particular web page. It is essentially a tracking feature: it allows a web site, or any third-party to that web site, to be informed about which link you clicked on which one of its web pages. The sole purpose is to track your browsing activity.</p> -userRulesPermanentHeader=Quy tắc vĩnh viễn -userRulesTemporaryHeader=Quy tắc tạm thời -userRulesRevert=Phục hồi -userRulesCommit=Xác nhận -userRulesEdit=Sửa -userRulesEditSave=Lưu -userRulesEditDicard=Huỷ -userRulesImport=Nhập từ tập tin... -userRulesExport=Xuất ra tập tin... -userRulesFormatHint=Xem trang này để biết quy tắc cú pháp. -userRulesDefaultFileName=my-ematrix-rules.txt -hostsFilesPrompt=Tất cả tên máy chủ trong tập tin máy chủ được nạp là tên máy chủ trong danh sách đen trong phạm vi chung. -hostsFilesStats={{blockedHostnameCount}} tên máy chủ đã chặn khác biệt từ: -hostsFilesPerFileStats={{used}} được dùng trên tổng {{total}} -hostsFilesLastUpdate=Cập nhật: {{ago}} -hostsFilesApplyChanges=Áp dụng thay đổi -hostsFilesAutoUpdatePrompt=Tự động cập nhật tập tin máy chủ. -hostsFilesUpdateNow=Cập nhật ngay -hostsFilesPurgeAll=Dọn tất cả bộ nhớ đệm -hostsFilesExternalListsHint=Một URL mỗi dòng. Các dòng bắt đầu với ‘#’ sẽ được bỏ qua. URL không hợp lệ sẽ được tự bỏ qua. -hostsFilesExternalListsParse=Phân tích -hostsFilesExternalListPurge=dọn bộ nhớ đệm -hostsFilesExternalListNew=có phiên bản mới -hostsFilesExternalListObsolete=đã cũ -rawSettingsWarning=Warning! Change these raw configuration settings at your own risk. -aboutChangelog=Thay đổi -aboutStorageUsed=Lưu trữ đã dùng: {{storageUsed}} byte -aboutDoc=Tài liệu -aboutPermissions=Quyền -aboutCode=Mã nguồn (GPLv3) -aboutIssues=Lỗi và vấn đề -aboutContributors=Những người đóng góp -aboutCodeContributors=Mã: -aboutIssueContributors=Vấn đề: -aboutTranslationContributors=Bản dịch: -aboutUserDataHeader=Dữ liệu của bạn -aboutBackupButton=Sao lưu ra tập tin... -aboutBackupFilename=my-ematrix-backup.txt -aboutRestoreButton=Phục hồi từ tập tin... -aboutRestoreConfirm=Mọi cấu hình của bạn sẽ được thay thế bằng dữ liệu đã sao lưu vào {{time}}, và ηMatrix sẽ khởi động lại.\n\nGhi đè tất cả cấu hình hiện tại bằng dữ liệu đã sao lưu? -aboutRestoreError=Không thể đọc dữ liệu hoặc dữ liệu không hợp lệ -aboutOr=... hoặc ... -aboutResetButton=Phục hồi cấu hình mặc định -aboutResetConfirm=Cẩn trọng! Điều này sẽ xoá tất cả cấu hình tuỳ chỉnh của bạn. Bạn chắc muốn tiến hành? -loggerFilterInputPlaceholder=diễn tả bộ lọc -loggerMaxEntriesTip=Số mục tối đa -loggerEntryCookieDeleted=đã xoá cookie: {{value}} -loggerEntryDeleteCookieError=không thể xoá cookie: {{value}} -loggerEntryBrowserCacheCleared=đã xoá bộ đệm trình duyệt -loggerEntryAssetUpdated=đã cập nhật tài nguyên: {{value}} -mainBlockedPrompt1=ηMatrix đã chặn truy cập trang này: -mainBlockedPrompt2=Bởi vì các luật sau -mainBlockedBack=Trở về -mainBlockedClose=Đóng -commandRevertAll=Xoá tất cả thay đổi tạm thời -commandWhitelistPageDomain=Tạm thời thêm tên miền trang vào danh sách an toàn -commandWhitelistAll=Tạm thời thêm tất cả vào danh sách an toàn -commandOpenDashboard=Mở bảng điều khiển -elapsedOneMinuteAgo=một phút trước -elapsedManyMinutesAgo=phút trước -elapsedOneHourAgo=một giờ trước -elapsedManyHoursAgo=giờ trước -elapsedOneDayAgo=một ngày trước -elapsedManyDaysAgo=ngày trước -showDashboardButton=Bảng điều khiển -showLoggerButton=Ghi dữ liệu -cloudPush=Xuất sang lưu trữ trên mây -cloudPull=Nhập từ lưu trữ trên mây -cloudNoData=...\n... -cloudDeviceNamePrompt=Tên thiết bị: -genericSubmit=Xác nhận -genericRevert=Phục hồi -errorCantConnectTo=Lỗi mạng: Không thể kết nối đến {{url}} -genericApplyChanges=Apply changes -noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can display some content by using the <noscript> tag. For example, some websites will redirect users to a “scriptless” version.</p><p>When ηMatrix blocks scripts, the browser will still advertise itself as supporting script execution unless this option is selected.</p><p>When selected, ηMatrix will tell the website that the browser does not support scripts, which is what you definitely want to do if you are blocking 1st-party scripts. As such, the <noscript> tag will work as intended.</p><p>Not selecting this option when 1st-party scripts are blocked means the website will break misteryously in case it is meant to redirect to a scriptless version.</p> -settingsUpdateIcon=Do not change the toolbar icon -updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> -resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> diff --git a/locale/zh-CN/messages.properties b/locale/zh-CN/messages.properties index 7c13661..011ddde 100644 --- a/locale/zh-CN/messages.properties +++ b/locale/zh-CN/messages.properties @@ -91,12 +91,12 @@ settingsCloudStorageEnabled=启用浏览器自带云储存功能 privacyPageTitle=ηMatrix – 隐私 privacyDeleteBlockedCookiesPrompt=删除已屏蔽的 Cookie privacyDeleteBlockedCookiesHelp=<p><i>ηMatrix</i> 默认不阻止黑名单中的 Cookie 进入您的浏览器,而是阻止它们离开您的浏览器,是因后者更具有意义。不在 Cookie 进入浏览器之前阻止它们将使您有机会得知网站正尝试使用 Cookie,以便您有需要时进一步查看。</p><p>若黑名单中的 Cookie 被 <i>ηMatrix</i> 所计入则可如愿将其移除。</p><p><b>重要提示:</b>浏览器扩展在其运作期间发出网络请求时可能会产生 Cookie。如果 Cookie 所在域名尚未被列入白名单,则 <i>ηMatrix</i> 会于该选项开启之时移除这些 Cookie。请确保用于扩展通信的域名处于白名单内。</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=于 +privacyDeleteNonBlockedSessionCookiesPrompt1=于 privacyDeleteNonBlockedSessionCookiesPrompt2= 分钟后删除未屏蔽的闲置会话 Cookie privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>W3C</a>:“会话 Cookie……将在您结束浏览器会话时被清除。会话 Cookie 被存储于临时内存中,浏览器关闭后将不再保留。”</p><p>不过在使用某些浏览器时,这一行为<a href='https://code.google.com/p/chromium/issues/detail?id=128513'>有可能并不会发生</a>。另外,对某些人而言,必须在浏览器关闭后才能清除会话 Cookie 可能有些过迟。</p> privacyDeleteBlockedLocalStoragePrompt=连同被屏蔽的 Cookie 一並删除相关域名下的<a href='https://zh.wikipedia.org/wiki/%E7%BD%91%E9%A1%B5%E5%AD%98%E5%82%A8#.E6.9C.AC.E5.9C.B0.E5.8F.8A.E6.9C.83.E8.A9.B1.E5.AD.98.E5.84.B2'>本地存储</a>数据 privacyDeleteBlockedLocalStorageHelp=待完成 -privacyClearCachePrompt1=每隔 +privacyClearCachePrompt1=每隔 privacyClearCachePrompt2= 分钟清理浏览器缓存 privacyClearCacheHelp=<p>某些网站特别热衷于跟踪,以至于为规避您的反跟踪举措,会使用一些不太光彩的手段。</p><p>一部分诡计利用了<a href='https://zh.wikipedia.org/wiki/%E7%BD%91%E9%A1%B5%E5%BF%AB%E7%85%A7'>浏览器缓存</a><sup>[1, 2]</sup>,因为缓存内容通常会长期储留,用户也基本不会去亲自清理。</p><p>定期清理浏览器缓存其实并不怎么麻烦(甚至很可能不会被注意到),且贵在可以保护您的隐私免受跟踪者侵犯。</p><p>启用该设置将容许 <i>ηMatrix</i> 依您指定的时间定期为您完成该项工作。</p><p>[1] <a href='https://grepular.com/Preventing_Web_Tracking_via_the_Browser_Cache'>“阻止利用浏览器缓存进行网络追踪”</a>\n[2] <a href='http://lucb1e.com/rp/cookielesscookies/'>“Cookieless Cookies”</a></p> privacyProcessRefererPrompt=伪造网页第三方请求中的 <a href='https://zh.wikipedia.org/wiki/HTTP%E5%8F%83%E7%85%A7%E4%BD%8D%E5%9D%80'>HTTP 来源地址</a> @@ -115,7 +115,7 @@ userRulesEditDicard=撤销 userRulesImport=从文件导入... userRulesExport=导出至文件... userRulesFormatHint=在此页面查看规则语法。 -userRulesDefaultFileName=my-ematrix-rules.txt +userRulesDefaultFileName=my-umatrix-rules.txt hostsFilesPrompt=Hosts 文件中的域名将被列入全局黑名单。 hostsFilesStats=共有 {{blockedHostnameCount}} 个域名被列入以下黑名单: hostsFilesPerFileStats={{used}}/{{total}} 使用中 @@ -124,7 +124,7 @@ hostsFilesApplyChanges=应用变更 hostsFilesAutoUpdatePrompt=自动更新 hosts 文件 hostsFilesUpdateNow=立即更新 hostsFilesPurgeAll=清理所有缓存 -hostsFilesExternalListsHint=每行一条URL。以‘#’开头的行将被忽略。无效的URL将被忽略。 +hostsFilesExternalListsHint=<p>One URL per line. Lines prefixed with ‘#’ will be ignored. Invalid URLs will be silently ignored.</p><p>The inserted URL must point to a hosts file (including local files); do not use the hosts file syntax here.</p> hostsFilesExternalListsParse=解析 hostsFilesExternalListPurge=清理缓存 hostsFilesExternalListNew=有新版本 @@ -142,7 +142,7 @@ aboutIssueContributors=问题报告: aboutTranslationContributors=翻译: aboutUserDataHeader=您的数据 aboutBackupButton=备份至文件... -aboutBackupFilename=my-ematrix-backup.txt +aboutBackupFilename=my-umatrix-backup.txt aboutRestoreButton=从文件恢复... aboutRestoreConfirm=您的所有设置将被 {{time}} 的备份数据所覆盖,接着 ηMatrix 将会重启。\n\n是否要用备份数据覆盖现有设置? aboutRestoreError=数据读取失败或格式有误 @@ -183,4 +183,6 @@ noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can dis settingsUpdateIcon=Do not change the toolbar icon updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +resolveCnameHelp=<p>When resolving an address with DNS, some webistes use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> +settingsTextSmaller=Smaller +settingsTextBigger=Bigger diff --git a/locale/zh-TW/messages.properties b/locale/zh-TW/messages.properties deleted file mode 100644 index 4f89a0a..0000000 --- a/locale/zh-TW/messages.properties +++ /dev/null @@ -1,186 +0,0 @@ -extName=ηMatrix -dashboardPageName=ηMatrix — 控制台 -loggerPageName=ηMatrix — 日誌記錄 -settingsPageName=設定 -privacyPageName=隱私 -statsPageName=統計 -userRulesPageName=過濾規則 -ubiquitousRulesPageName=Hosts檔案 -rawSettingsPageName=更多 -aboutPageName=關於 -allPrettyName=全部 -cookiePrettyName=Cookie -cssPrettyName=樣式 -imagePrettyName=圖像 -mediaPrettyName=影音 -pluginPrettyName=插件 -scriptPrettyName=指令 -xhrPrettyName=XHR -framePrettyName=框架 -otherPrettyName=其他 -matrixNoNetTrafficPrompt=該頁面暫無網路傳輸。 -matrixMtxButtonTip=停用或啟用於該域名下的過濾。 -matrixPersistButtonTip=儲存該域名下的所有臨時變更。 -matrixRevertButtonTip=撤銷該域名下的所有臨時變更。 -matrixReloadButton=重新載入此頁。\n同時按下 Shift 鍵以棄用瀏覽器快取。 -matrixScopeTip=Change to global scope. -matrixSwitchesTip=Dropdown menu with additional settings. -matrix1stPartyLabel=第一方 -matrixBlacklistedHostnames={{count}} 個黑名單域名 -matrixSwitchNoMixedContent=禁止混合內容 -matrixSwitchNoWorker=禁用 Web Worker -matrixSwitchReferrerSpoof=偽造參照位址 -matrixSwitchNoscriptSpoof=模擬 <code><noscript></code> 元素 -matrixRevertAllEntry=撤銷所有臨時變更 -matrixLoggerMenuEntry=查看日誌 -matrixDashboardMenuEntry=前往控制臺 -matrixNoTabFound=沒有找到網頁 -statsPageTitle=ηMatrix – 統計 -statsPageGenericStats=大致統計 -statsPageCookieHeadersFoiled=已阻止<a href='https://zh.wikipedia.org/wiki/Cookie'>Cookie</a>檔頭請求:{{count}}次 -statsPageRefererHeadersFoiled=已阻止<a href='https://zh.wikipedia.org/wiki/HTTP%E5%8F%83%E7%85%A7%E4%BD%8D%E5%9D%80'>HTTP參照位址</a>檔頭請求:{{count}}次 -statsPageHyperlinkAuditingFoiled=已阻止<a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>超連結審查</a>:{{count}}次 -statsPageCookiesRemoved=本地Cookie移除次數:{{count}} -statsPageLocalStoragesCleared=<a href='http://diveintohtml5.info/storage.html'>本地儲存</a>清空次數:{{count}} -statsPageBrowserCacheCleared=瀏覽器快取清除次數:{{count}} -statsPageDetailedStats=詳細統計 -statsPageDetailedAllPages=全部 -statsPageDetailedBehindTheScenePage=頁面後臺 -statsPageOverview=概覽 -statsPageRequests=請求 -statsPageAllowed=容許 -statsPageBlocked=阻擋 -statsPageAll=全部 -statsPagePages=頁面 -statsPageCookies=Cookie -statsPageCSS=樣式 -statsPageImages=圖像 -statsPagePlugins=外掛程式 -statsPageScripts=指令碼 -statsPageXHRs=XHR -statsPageFrames=嵌套 -statsPageOthers=其他 -statsPageDetailed=過濾日誌 -statsPageLogSizePrompt1=記住<b>每頁</b>最近 -statsPageLogSizePrompt2=次HTTP請求。 -statsPageLogSizeHelp=<p>您可以查看最近期網絡頁面所發出的請求之詳情(見下)。</p><p>這對於想了解網絡頁面的確切行為的進階使用者較為實用,惟記錄HTTP請求將耗用記憶體,如您並不在意技術細節則等同浪費記憶體。</p><p>故此欄將容許閣下調整用作進一歲檢查的近期HTTP請求之記錄數字。</p><p>輸入「<code>0</code>」將禁用詳細日誌(從而減少<i>ηMatrix</i>所佔用之記憶體)。</p> -statsPageRefresh=重新整理 -settingsPageTitle=ηMatrix – 設定 -settingsMatrixDisplayHeader=界面外觀 -settingsMatrixDisplayTextSizePrompt=文字大小: -settingsMatrixDisplayTextSizeNormal=標準 -settingsMatrixDisplayTextSizeLarge=大 -settingsMatrixDisplayColorBlind=適合色盲人士 -settingsMatrixConvenienceHeader=便捷功能 -settingsDefaultScopeLevel=預設域名層級 -settingsDefaultScopeLevel0=全域 -settingsDefaultScopeLevel1=主站域名 -settingsDefaultScopeLevel2=網頁域名 -settingsMatrixAutoReloadPrompt=關閉矩陣時重新載入以下分頁: -settingsMatrixAutoReloadNone=無 -settingsMatrixAutoReloadCurrent=現有 -settingsMatrixAutoReloadAll=全部 -settingsMatrixAutoReloadInfo=當你更改矩陣以致其將影響分頁之外觀或行為之時,<i>ηMatrix</i>將於關閉矩陣時自動重新載入。 -settingsSubframeColor=已封鎖之框架: 颜色 -settingsSubframeOpacity=不透明度 -settingsIconBadgeEnabled=Show the number of blocked requests on the icon -settingsCollapseBlocked=隱藏已阻擋請求所關聯的頁面內容 -settingsCollapseBlacklisted=隱藏因域名黑名單而遭遮蔽的內容 -settingsNoscriptTagsSpoofed=當第一方指令碼被阻擋時嘗試模擬還原 <code><noscript></code> 網頁元素 -settingsCloudStorageEnabled=啟用瀏覽器自帶雲端儲存 -privacyPageTitle=ηMatrix – 隱私 -privacyDeleteBlockedCookiesPrompt=刪除已屏蔽的 Cookie -privacyDeleteBlockedCookiesHelp=<p><i>ηMatrix</i> 預設不會阻止黑名單中的 Cookie 進入您的瀏覽器,而是阻止它们離開开您的瀏覽器,因後者更具有意義。不於 Cookie 進入瀏覽器之前阻止它們將使您有機會得知網站正嘗試使用 Cookie,以便您有需要時進一步查看。</p><p>若黑名單中的 Cookie 被 <i>ηMatrix</i> 所計入則可按閱下意願將其移除。</p><p><b>重要提示:</b>附加元件於其運作期間作出網絡請求之時將可能產生 Cookie。如果 Cookie 所在域名並未被列入白名單,則 <i>ηMatrix</i> 會於該選項開啟之時移除這些 Cookie。請確保用於附加元件通訊的域名處於白名單內。</p> -privacyDeleteNonBlockedSessionCookiesPrompt1=於 -privacyDeleteNonBlockedSessionCookiesPrompt2= 分鐘後刪除未屏蔽的閒置會話 Cookie -privacyDeleteNonBlockedSessionCookiesHelp=<p><a href='http://www.w3.org/2001/tag/2010/09/ClientSideStorage.html'>萬維網聯盟</a> 告知:「會話 Cookie……將於瀏覽器會話結束時被清除。會話 Cookie 儲存於記憶體中,瀏覽器關閉後將不再保留。」</p><p>不過在使用某些瀏覽器時,此行為<a href='https://code.google.com/p/chromium/issues/detail?id=128513'>未必發生</a>。另外,對某些人而言,於瀏覽器將閉後才清除會話 Cookie 可能太遲。</p> -privacyDeleteBlockedLocalStoragePrompt=連同被屏蔽的 Cookie 一並刪除相關域名下的<a href='https://zh.wikipedia.org/wiki/%E7%BD%91%E9%A1%B5%E5%AD%98%E5%82%A8#.E6.9C.AC.E5.9C.B0.E5.8F.8A.E6.9C.83.E8.A9.B1.E5.AD.98.E5.84.B2'>本地存储</a>數據 -privacyDeleteBlockedLocalStorageHelp=待完成 -privacyClearCachePrompt1=每隔 -privacyClearCachePrompt2= 分鐘清除瀏覽器快取 -privacyClearCacheHelp=<p>某些網站特别熱衷於追蹤,以至於為規避您的反跟蹤舉措,會使用一些不太光彩的手段。</p><p>一部分詭計利用了<a href='https://zh.wikipedia.org/wiki/%E7%BD%91%E9%A1%B5%E5%BF%AB%E7%85%A7'>瀏覽器快取</a><sup>[1, 2]</sup>,因為快取內容通常會長期儲留,用戶也基本不會去親自清理。</p><p>定期清理瀏覽器快取其實並不怎麼麻煩(甚至很可能不會被注意到),且貴在可以保護您的隱私免受追蹤者侵犯。</p><p>啟用該設定將容許 <i>ηMatrix</i> 依您指定的時間定期為您完成此項工作。</p><p>[1] <a href='https://grepular.com/Preventing_Web_Tracking_via_the_Browser_Cache'>「阻止利用瀏覽器快取進行網絡追蹤」</a>\n[2] <a href='http://lucb1e.com/rp/cookielesscookies/'>「Cookieless Cookies」</a></p> -privacyProcessRefererPrompt=偽造網頁第三方請求中的 <a href='https://zh.wikipedia.org/wiki/HTTP%E5%8F%83%E7%85%A7%E4%BD%8D%E5%9D%80'>HTTP 參照位址</a> -privacyProcessRefererHelp=維基百科:<blockquote>HTTP 位址參照是一個用於辨識請求來源網頁網址的內容標識。……<b>由於位址參照可能會洩漏隱私,某些瀏覽器容許使用者禁止傳送位址參照。</b></blockquote>若啟用該設定,<i>ηMatrix</i> 則會於來源網頁請求的 HTTP 位址參照中包含的域名與請求資源所在域名有差別時偽造位址參照。 -privacyNoMixedContentPrompt=嚴格遵守 HTTPS 協議:禁止混合内容 -privacyNoMixedContentHelp=<p><a href='https://developer.mozilla.org/docs/Security/MixedContent'>Mozilla 開發者網絡</a>告知:</p><blockquote>若 HTTPS 頁面包含未經加密的普通 HTTP 網頁內容,則當前連結只是部分加密;未加密的部分或會遭他人窺視甚至篡改內容,故連結並非完全安全。當此情況發生時,該頁面即為混合內容頁面。</blockquote> -privacyProcessHyperlinkAuditingPrompt=禁止<a href='https://html.spec.whatwg.org/multipage/links.html#hyperlink-auditing'>超連結審查</a> -privacyProcessHyperlinkAuditingHelp=<p>超連結審查容許<b>任何人</b>獲知用戶於特定網頁上點擊了某個連結。其本質為一種追蹤手段:經由容許網站或任何第三方獲告知您於哪個頁面點擊了哪個連結,以達到追蹤您的瀏覽動向此一特定目的。</p> -userRulesPermanentHeader=永久規則 -userRulesTemporaryHeader=臨時規則 -userRulesRevert=還原 -userRulesCommit=提交 -userRulesEdit=編輯 -userRulesEditSave=儲存 -userRulesEditDicard=撤銷 -userRulesImport=從檔案導入... -userRulesExport=導出至檔案... -userRulesFormatHint=於此頁面查閱規則語法。 -userRulesDefaultFileName=my-ematrix-rules.txt -hostsFilesPrompt=Hosts 檔案中的域名將被列入全域黑名單。 -hostsFilesStats=總共 {{blockedHostnameCount}} 個域名被列入以下黑名單: -hostsFilesPerFileStats={{used}}/{{total}} 使用中 -hostsFilesLastUpdate=上次更新:{{ago}} -hostsFilesApplyChanges=套用變更 -hostsFilesAutoUpdatePrompt=自動更新 hosts 檔案 -hostsFilesUpdateNow=立即更新 -hostsFilesPurgeAll=清除所有快取 -hostsFilesExternalListsHint=每行一條網址。以「#」開始的行將被忽略。無效網址亦將忽略。 -hostsFilesExternalListsParse=解析 -hostsFilesExternalListPurge=清除快取 -hostsFilesExternalListNew=有新版本 -hostsFilesExternalListObsolete=已過期 -rawSettingsWarning=警告!若要自行編輯原始設定數據則後果自負。 -aboutChangelog=更新日誌 -aboutStorageUsed=佔用儲存空間:{{storageUsed}} 位元組 -aboutDoc=幫助文檔 -aboutPermissions=權限說明 -aboutCode=原始程式碼(GPLv3) -aboutIssues=問題與報告 -aboutContributors=貢獻者 -aboutCodeContributors=程式碼: -aboutIssueContributors=問題報告: -aboutTranslationContributors=翻譯: -aboutUserDataHeader=您的數據 -aboutBackupButton=備份至檔案... -aboutBackupFilename=my-ematrix-backup.txt -aboutRestoreButton=從檔案還原... -aboutRestoreConfirm=您的所有設定將由 {{time}} 的備份數據所覆蓋,接著 ηMatrix 將會重新啟動。\n\n是否要用備份數據覆蓋現有設定? -aboutRestoreError=數據讀取失敗或格式有誤 -aboutOr=...或者... -aboutResetButton=重置為預設值 -aboutResetConfirm=小心!這將移除您的所有設定。確定要繼續? -loggerFilterInputPlaceholder=規則過濾表達式 -loggerMaxEntriesTip=日誌條數限制 -loggerEntryCookieDeleted=已刪除 Cookie:{{value}} -loggerEntryDeleteCookieError=無法刪除 Cookie:{{value}} -loggerEntryBrowserCacheCleared=瀏覽器快取清除完畢 -loggerEntryAssetUpdated=已更新資料:{{value}} -mainBlockedPrompt1=ηMatrix 已阻止載入以下頁面: -mainBlockedPrompt2=因以下規則 -mainBlockedBack=返回 -mainBlockedClose=關閉 -commandRevertAll=撤銷所有臨時變更 -commandWhitelistPageDomain=暫時將頁面域名列入白名單 -commandWhitelistAll=暫時將一切列入白名單 -commandOpenDashboard=開啟控制臺 -elapsedOneMinuteAgo=1 分鐘前 -elapsedManyMinutesAgo={{value}} 分鐘前 -elapsedOneHourAgo=1 小時前 -elapsedManyHoursAgo={{value}} 小時前 -elapsedOneDayAgo=1 日前 -elapsedManyDaysAgo={{value}} 日前 -showDashboardButton=控制臺 -showLoggerButton=日誌 -cloudPush=導出至雲端儲存 -cloudPull=從雲端儲存導入 -cloudNoData=...\n... -cloudDeviceNamePrompt=該設備名稱: -genericSubmit=提交 -genericRevert=還原 -errorCantConnectTo=網絡錯誤:無法連接至 {{url}} -genericApplyChanges=應用變更 -noscriptSpoofHelp=<p>When a browser does not support scripts, a web page can display some content by using the <noscript> tag. For example, some websites will redirect users to a “scriptless” version.</p><p>When ηMatrix blocks scripts, the browser will still advertise itself as supporting script execution unless this option is selected.</p><p>When selected, ηMatrix will tell the website that the browser does not support scripts, which is what you definitely want to do if you are blocking 1st-party scripts. As such, the <noscript> tag will work as intended.</p><p>Not selecting this option when 1st-party scripts are blocked means the website will break misteryously in case it is meant to redirect to a scriptless version.</p> -settingsUpdateIcon=Do not change the toolbar icon -updateIconHelp=<p>By default, the extension will change its icon based on how many requests are blocked on the selected page.</p><p>Selecting this option will prevent ηMatrix from changing its icon.</p><p>When the page does not have requests (e.g. the extension‘s dashboard) the icon will still be changed to the “disabled” state.</p> -resolveCnameLabel=Resolve CNAME records -resolveCnameHelp=<p>When resolving an address with DNS, some websites use a CNAME record to redirect the resolution to a different address than the one asked for by the user.</p><p>This mechanism has legitimate uses and is convenient in a number of cases, but it can also be abused by unscrupolous criminals by “hiding” (cloaking) the address of a tracker behind a legitimate address.</p><p>When this setting is enabled, ηMatrix will query the DNS when a new address is met, resulting in it using the canonical name (CNAME) of the website.</p><p><b>Please note</b>: this will break your whitelist. It is also experimental and you are recommended to toggle this option <i>before</i> visiting a website. Toggling it and then refreshing an already loaded page might cause strange issues right now.</p> diff --git a/options.xul b/options.xul index 4e67281..2630c02 100644 --- a/options.xul +++ b/options.xul @@ -2,7 +2,7 @@ <!-- *************************************************************************** ηMatrix - a browser extension to black/white list requests. - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2020-2021 Alessio Vanni This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see {http://www.gnu.org/licenses/}. - Home: https://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix --> <vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> |