aboutsummaryrefslogtreecommitdiffstats
path: root/js/hosts-files.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/hosts-files.js')
-rw-r--r--js/hosts-files.js340
1 files changed, 171 insertions, 169 deletions
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);