aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhackademix <giorgio@maone.net>2019-03-26 22:45:37 +0100
committerhackademix <giorgio@maone.net>2019-03-26 22:45:37 +0100
commit9884643742b54b88f94111d62f5e89a12a60e604 (patch)
treef367f5b7aa7ae3b950c26a946b54b737e6014a5c
parent55469c349c3c47c882ee21348ba67780c8291003 (diff)
Subdomain wildcard support.
-rw-r--r--bg/ListManager.js35
-rw-r--r--html/display_panel/content/main_panel.js6
-rw-r--r--html/preferences_panel/pref.js3
-rw-r--r--html/preferences_panel/preferences_panel.html4
-rw-r--r--main_background.js16
5 files changed, 47 insertions, 17 deletions
diff --git a/bg/ListManager.js b/bg/ListManager.js
index 2f5f74e..745e599 100644
--- a/bg/ListManager.js
+++ b/bg/ListManager.js
@@ -36,13 +36,13 @@ class ListManager {
}
async whitelist(...keys) {
- ListManager.move(this.lists.blacklist, this.lists.whitelist, ...keys);
+ await ListManager.move(this.lists.blacklist, this.lists.whitelist, ...keys);
}
async blacklist(...keys) {
- ListManager.move(this.lists.whitelist, this.lists.blacklist, ...keys);
+ await ListManager.move(this.lists.whitelist, this.lists.blacklist, ...keys);
}
async forget(...keys) {
- await Promise.all(Object.values(this.lists).map(l => l.remove(...keys)));
+ await Promise.all(Object.values(this.lists).map(async l => await l.remove(...keys)));
}
/* key is a string representing either a URL or an optional path
with a trailing (hash).
@@ -62,10 +62,11 @@ class ListManager {
if (!match) {
let url = ListStore.urlItem(key);
let site = ListStore.siteItem(key);
- return (blacklist.contains(url) || blacklist.contains(site))
+ return (blacklist.contains(url) || ListManager.siteMatch(site, blacklist)
? "blacklisted"
- : whitelist.contains(url) || whitelist.contains(site)
- ? "whitelisted" : defValue;
+ : whitelist.contains(url) || ListManager.siteMatch(site, whitelist)
+ ? "whitelisted" : defValue
+ );
}
let [hashItem, srcHash] = match; // (hash), hash
@@ -74,6 +75,28 @@ class ListManager {
? "whitelisted"
: defValue;
}
+
+ /*
+ Matches by whole site ("http://some.domain.com/*") supporting also
+ wildcarded subdomains ("https://*.domain.com/*").
+ */
+ static siteMatch(url, list) {
+ let site = ListStore.siteItem(url);
+ if (list.contains(site)) {
+ return site;
+ }
+ site = site.replace(/^([\w-]+:\/\/)?(\w)/, "$1*.$2");
+ for (;;) {
+ if (list.contains(site)) {
+ return site;
+ }
+ let oldKey = site;
+ site = site.replace(/(?:\*\.)*\w+(?=\.)/, "*");
+ if (site === oldKey) {
+ return null;
+ }
+ }
+ }
}
module.exports = { ListManager };
diff --git a/html/display_panel/content/main_panel.js b/html/display_panel/content/main_panel.js
index 83c3a6b..9172265 100644
--- a/html/display_panel/content/main_panel.js
+++ b/html/display_panel/content/main_panel.js
@@ -59,6 +59,7 @@ document.querySelector("#info").addEventListener("click", e => {
setTimeout(close, 100);
return;
}
+ if (!button.tagName === "BUTTON") button = button.closest("button");
if (button.matches(".toggle-source")) {
let parent = button.parentNode;
if (!parent.querySelector(".source").textContent) {
@@ -69,10 +70,13 @@ document.querySelector("#info").addEventListener("click", e => {
return;
}
if (!button.matches(".buttons > button")) return;
+ let domain = button.querySelector(".domain");
+
let li = button.closest("li");
let entry = li && li._scriptEntry || [currentReport.url, "Page's site"];
let action = button.className;
- let site = button.name === "*";
+ let site = domain ? domain.textContent : button.name === "*" ? currentReport.site : "";
+
if (site) {
([action] = action.split("-"));
}
diff --git a/html/preferences_panel/pref.js b/html/preferences_panel/pref.js
index 9cecbb6..debb468 100644
--- a/html/preferences_panel/pref.js
+++ b/html/preferences_panel/pref.js
@@ -40,6 +40,9 @@
error = "Only one single trailing path wildcard (/*) allowed";
}
} catch (e) {
+ if (/^https?:\/\/\*\./.test(url)) {
+ return this.malformedUrl(url.replace("*.", ""));
+ }
error = "Invalid URL";
if (url && !url.includes("://")) error += ": missing protocol, either http:// or https://";
else if (url.endsWith("://")) error += ": missing domain name";
diff --git a/html/preferences_panel/preferences_panel.html b/html/preferences_panel/preferences_panel.html
index 3a0ad7a..081ae07 100644
--- a/html/preferences_panel/preferences_panel.html
+++ b/html/preferences_panel/preferences_panel.html
@@ -45,10 +45,10 @@
<h3>Settings</h3>
</div>
<div id="widgets">
- <fieldset id="section-lists"><legend>Allow or block scripts matching the following URLs ("*" matches any path)</legend>
+ <fieldset id="section-lists"><legend>Allow or block scripts matching the following URLs ("*."" matches any subdomain, "/*" matches any path)</legend>
<label>Type a new whitelist / blacklist entry:</label>
<div id="new-site">
- <input type="text" id="site" value="" placeholder="https://www.gnu.org/*">
+ <input type="text" id="site" value="" placeholder="https://*.gnu.org/*">
<button id="cmd-whitelist-site" class="white" title="Whitelist this site" default>Whitelist</button>
<button id="cmd-blacklist-site" class="red" title="Blacklist this site">Blacklist</button>
</div>
diff --git a/main_background.js b/main_background.js
index 8060ebd..f1c7f09 100644
--- a/main_background.js
+++ b/main_background.js
@@ -326,7 +326,7 @@ async function connected(p) {
if (m[action]) {
let [key] = m[action];
if (m.site) {
- key = ListStore.siteItem(key);
+ key = ListStore.siteItem(m.site);
} else {
key = ListStore.inlineItem(key) || key;
}
@@ -745,12 +745,12 @@ async function get_script(response, url, tabId = -1, whitelisted = false, index
let scriptName = url.split("/").pop();
if (whitelisted) {
if (tabId !== -1) {
- let site = ListStore.siteItem(url);
+ let site = ListManager.siteMatch(url, whitelist);
// Accept without reading script, it was explicitly whitelisted
- let reason = whitelist.contains(site)
+ let reason = site
? `All ${site} whitelisted by user`
: "Address whitelisted by user";
- addReportEntry(tabId, url, {"whitelisted": [url, reason], url});
+ addReportEntry(tabId, url, {"whitelisted": [site, reason], url});
}
if (response.startsWith("javascript:"))
return result(response);
@@ -855,7 +855,7 @@ var ResponseHandler = {
url = ListStore.urlItem(url);
let site = ListStore.siteItem(url);
- let blacklistedSite = blacklist.contains(site);
+ let blacklistedSite = ListManager.siteMatch(site, blacklist);
let blacklisted = blacklistedSite || blacklist.contains(url);
let topUrl = request.frameAncestors && request.frameAncestors.pop() || documentUrl;
@@ -863,7 +863,7 @@ var ResponseHandler = {
if (type === "script") {
// abort the request before the response gets fetched
addReportEntry(tabId, url, {url: topUrl,
- "blacklisted": [url, blacklistedSite ? `User blacklisted ${site}` : "Blacklisted by user"]});
+ "blacklisted": [url, blacklistedSite ? `User blacklisted ${blacklistedSite}` : "Blacklisted by user"]});
return ResponseProcessor.REJECT;
}
// use CSP to restrict JavaScript execution in the page
@@ -872,13 +872,13 @@ var ResponseHandler = {
value: `script-src '${blacklistedSite ? 'self' : 'none'}';`
});
} else {
- let whitelistedSite = whitelist.contains(site);
+ let whitelistedSite = ListManager.siteMatch(site, whitelist);
let whitelisted = response.whitelisted = whitelistedSite || whitelist.contains(url);
if (type === "script") {
if (whitelisted) {
// accept the script and stop processing
addReportEntry(tabId, url, {url: topUrl,
- "whitelisted": [url, whitelistedSite ? `User whitelisted ${site}` : "Whitelisted by user"]});
+ "whitelisted": [url, whitelistedSite ? `User whitelisted ${whitelistedSite}` : "Whitelisted by user"]});
return ResponseProcessor.ACCEPT;
} else {
let scriptInfo = await ExternalLicenses.check({url: fullUrl, tabId, frameId, documentUrl});