Version 1.9.0

- Added #284
- Added #56
- Fixed #241
- Possible fix & workaround for #203
- Fixed bug in "history tracking injection protection". This option was not disabled, when the global filter switch are on off
- Added an option to im-/export the log (requires the `downloads` permission)
- Added an option to im-/export the settings (requires the `downloads` permission)
- Added information page for blocked sites, when they are called in the `main_frame`
- Added "multiple times URL encodes" recognition
- Refactoring
- Changed background script loading sequence to prevent that required functions are not yet loaded.
This commit is contained in:
Kevin Röbert 2019-10-23 01:16:12 +02:00
parent 9df322a49a
commit d064537c07
23 changed files with 839 additions and 272 deletions

View File

@ -4,6 +4,29 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.9.0] - 2019-10-22
### Compatibility note
- Require Firefox >= 55
- Require Chrome >= 22
### Fixed
- Fixed bug in "history tracking injection protection". This option was not disabled, when the global filter switch are on off
- Fixed [#241](https://gitlab.com/KevinRoebert/ClearUrls/issues/241)
- Possible fix for [#203](https://gitlab.com/KevinRoebert/ClearUrls/issues/203)
## Changed
- Refactoring
- Changed background script loading sequence to prevent that required functions are not yet loaded.
### Added
- Added an option to im-/export the log (requires the `downloads` permission)
- Added an option to im-/export the settings (requires the `downloads` permission)
- Added information page for blocked sites, when they are called in the `main_frame`
- Added option to allow referral marketing ([#284](https://gitlab.com/KevinRoebert/ClearUrls/issues/284))
- Added "multiple times URL encodes" recognition
- Added an option to limit the log entries ([#56](https://gitlab.com/KevinRoebert/ClearUrls/issues/56))
## [1.8.5] - 2019-09-29
### Compatibility note

View File

@ -4,11 +4,20 @@
**ClearURLs** is an add-on based on the new WebExtensions technology and is optimized for *Firefox* and *Chrome* based browsers.
This add-on will remove the tracking fields from all URLs which are visited by the browser and use a rule file, namely `data.min.json`,
to protects your privacy.
This add-on will remove the tracking fields from all URLs, which are visited by the browser, with the help of an external rule file,
which is regularly updated by us and can be found [here](https://gitlab.com/KevinRoebert/ClearUrls/raw/master/data/data.min.json),
to protect your privacy.
## Application
Large (and small) webpages use elements in the URL, e.g.: https://example.com?source=thisIstheSiteIvisitedBefore to track your online activities. In this example, the source field tells the provider which page you visited before. The add-on will remove these tracking fields from the URL.
Large (and small) websites use elements in the URL, e.g.: `https://example.com?utm_source=newsletter1&utm_medium=email&utm_campaign=sale`
to track your online activities. In this example, the `utm` fields used to track a custom campaign, managed by Google. It tells the provider, and also Google,
the source, the medium (e.g. email or web) and the specific campaign of the link. All these tracking fields are not necessary for a website to be displayed
or work correctly and can therefore be removed - that is exactly what ClearURLs does, so you can think of it as an *URL clean maid*.
Another common example are Amazon URLs. If you search for a product on Amazon you will get a very long URL for this product, e.g.
`https://www.amazon.com/dp/exampleProduct/ref=sxin_0_pb?__mk_de_DE=ÅMÅŽÕÑ&keywords=tea&pd_rd_i=exampleProduct&pd_rd_r=8d39e4cd-1e4f-43db-b6e7-72e969a84aa5&pd_rd_w=1pcKM&pd_rd_wg=hYrNl&pf_rd_p=50bbfd25-5ef7-41a2-68d6-74d854b30e30&pf_rd_r=0GMWD0YYKA7XFGX55ADP&qid=1517757263&rnid=2914120011`,
the most of this URL is available for tracking and is not needed. After ClearURLs has cleaned this URL, it looks like this:
`https://www.amazon.com/dp/exampleProduct`
## Screenshot
![Interface (version 1.8.5)](https://gitlab.com/KevinRoebert/ClearUrls/raw/master/promotion/screens/Popup_1.8.5.png)
@ -31,7 +40,8 @@ You want to help translating ClearURLs into many languages? Nice
You can choose between two options to contribute. You can create a merge request, or you can use the POEditor to translate ClearURLs.
*Hint*: The description field in the translation files are only an information for what the translation is used. It is not necessary to translate the description field; in the most cases it is empty.
*Hint: The description field in the translation files are only an information for what the translation is used.
It is not necessary to translate the description field; in the most cases it is empty.*
#### Merge request
If you want to create a merge request, you must open the path [`_locales/en/messages.json`](https://github.com/KevinRoebert/ClearUrls/blob/master/_locales/en/messages.json) in the ClearURLs repo

View File

@ -59,6 +59,22 @@
"message": "Setzt das globale Protokoll zurück",
"description": "Diese Zeichenfolge wird als Titel für die Schaltfläche zum Zurücksetzen auf der Protokollseite verwendet."
},
"log_html_export_button": {
"message": "Exportieren",
"description": "Diese Zeichenfolge wird für die Schaltfläche zum Exportieren auf der Protokollseite verwendet."
},
"log_html_export_button_title": {
"message": "Exportieren des globalen Protokolls",
"description": "Diese Zeichenfolge wird als Titel für die Schaltfläche zum Exportieren auf der Protokollseite verwendet."
},
"log_html_import_button": {
"message": "Importieren",
"description": "Diese Zeichenfolge wird für die Schaltfläche zum Importieren auf der Protokollseite verwendet."
},
"log_html_import_button_title": {
"message": "Importieren des globalen Protokolls",
"description": "Diese Zeichenfolge wird als Titel für die Schaltfläche zum Importieren auf der Protokollseite verwendet."
},
"popup_html_configs_head": {
"message": "Einstellungen",
"description": "Diese Zeichenfolge wird als Titel für die Konfigurationen auf der Popup-Seite verwendet."
@ -163,10 +179,36 @@
"message": "Setzt alle Einstellungen zurück",
"description": "Diese Zeichenfolge wird als Titel für die Schaltfläche zum Zurücksetzen auf der Einstellungsseite verwendet."
},
"setting_html_export_button": {
"message": "Exportieren",
"description": "Diese Zeichenfolge wird als Name für die Schaltfläche zum Exportieren auf der Einstellungsseite verwendet."
},
"setting_html_export_button_title": {
"message": "Exportiert alle Einstellungen",
"description": "Diese Zeichenfolge wird als Titel für die Schaltfläche zum Exportieren auf der Einstellungsseite verwendet."
},
"setting_html_import_button": {
"message": "Importieren",
"description": "Diese Zeichenfolge wird als Name für die Schaltfläche zum Importieren auf der Einstellungsseite verwendet."
},
"setting_html_import_button_title": {
"message": "Importiert alle Einstellungen inkl. Regeln und Protokoll",
"description": "Diese Zeichenfolge wird als Titel für die Schaltfläche zum Importieren auf der Einstellungsseite verwendet."
},
"setting_rule_url_label": {
"message": "Die Url zu der data.json Datei (Regeln)",
"description": "Diese Zeichenfolge wird als Name für die Regel-URL-Bezeichnung verwendet."
},
"setting_log_limit_label": {
"message": "Limitiert das Protokoll auf $LIMIT$ Einträge. (-1 := ∞)",
"description": "Diese Zeichenfolge wird als Name für das Protokolllimit verwendet.",
"placeholders": {
"limit": {
"content": "$1",
"example": "100"
}
}
},
"settings_html_save_button": {
"message": "Speichern & Addon neustarten",
"description": "Diese Zeichenfolge wird als Name für die Schaltfläche zum Speichern und erneuten Laden auf der Einstellungsseite verwendet."
@ -238,5 +280,29 @@
"local_hosts_skipping_title": {
"message": "Auslassen von lokalen URLs",
"description": "Diese Zeichenkette wird als Titel für das Auslassen von lokalen URLs verwendet."
},
"blocked_html_title": {
"message": "Diese Seite wurde von <b>ClearURLs</b> blockiert.",
"description": "Diese Zeichenfolge wird als Titel auf der Hinweisseite für blockierte Seiten verwendet."
},
"blocked_html_body": {
"message": "Diese Seite wurde vom <b>ClearURLs</b> Add-On blockiert, weil wir sie als Werbe- bzw. Trackingservice identifiziert haben. Um diese Seite zu besuchen, müssen Sie das Add-On temporär deaktivieren. Dann können Sie auf den untenstehenden Button klicken, um die Seite aufzurufen.",
"description": "Diese Zeichenfolge wird als Mengentext auf der Hinweisseite für blockierte Seiten verwendet."
},
"blocked_html_button": {
"message": "Seite besuchen",
"description": "Diese Zeichenfolge wird als Buttontext auf der Hinweisseite für blockierte Seiten verwendet."
},
"referral_marketing_enabled": {
"message": "Erlaube Referral-Marketing",
"description": "Diese Zeichenkette wird als Beschreibung für das Referral-Marketing verwendet."
},
"referral_marketing_enabled_title": {
"message": "Erlaubt Referral-Marketing",
"description": "Diese Zeichenkette wird als Titel für das Referral-Marketing verwendet."
},
"watchdog": {
"message": "[ClearURLs]: Der Watchdog hat ein Problem festgestellt. ClearURLs wird neugestartet.",
"description": "Diese Zeichenkette wird als Text für den Watchdog verwendet."
}
}

View File

@ -59,6 +59,22 @@
"message": "Reset the global log",
"description": "This string is used as title for the reset button on the log page."
},
"log_html_export_button": {
"message": "Export",
"description": "This string is used for the export button on the log page."
},
"log_html_export_button_title": {
"message": "Export the global log",
"description": "This string is used as title for the export button on the log page."
},
"log_html_import_button": {
"message": "Import",
"description": "This string is used for the import button on the log page."
},
"log_html_import_button_title": {
"message": "Import the global log",
"description": "This string is used as title for the import button on the log page."
},
"popup_html_configs_head": {
"message": "Configs",
"description": "This string is used as title for the configs on the popup page."
@ -163,10 +179,36 @@
"message": "Reset everything",
"description": "This string is used as title for the reset button on the settings page."
},
"setting_html_export_button": {
"message": "Export",
"description": "This string is used as name for the export button on the settings page."
},
"setting_html_export_button_title": {
"message": "Export everything",
"description": "This string is used as title for the export button on the settings page."
},
"setting_html_import_button": {
"message": "Import",
"description": "This string is used as name for the reset button on the settings page."
},
"setting_html_import_button_title": {
"message": "Import everything",
"description": "This string is used as title for the import button on the settings page."
},
"setting_rule_url_label": {
"message": "The url to the data.json file (rules)",
"description": "This string is used as name for the rule url label."
},
"setting_log_limit_label": {
"message": "Limits the log to $LIMIT$ entries. (-1 := ∞)",
"description": "This string is used as name for the log limit label.",
"placeholders": {
"limit": {
"content": "$1",
"example": "100"
}
}
},
"settings_html_save_button": {
"message": "Save & reload addon",
"description": "This string is used as name for the save&reload button on the settings page."
@ -238,5 +280,29 @@
"local_hosts_skipping_title": {
"message": "Skipping URLs on local hosts",
"description": "This string is used as title for the local host skipping switch"
},
"blocked_html_title": {
"message": "This site was blocked by <b>ClearURLs</b>",
"description": "This string is used as title on the blocked site page."
},
"blocked_html_body": {
"message": "This site was blocked by the <b>ClearURLs</b> Add-on, because we identify this site as an advertising and/or tracking service. To visit this site, you must temporarily deactivate the Add-on. After deactivating ClearURLs you can click on the button below to load the page.",
"description": "This string is used as body on the blocked site page."
},
"blocked_html_button": {
"message": "Visit page",
"description": "This string is used as button on the blocked site page."
},
"referral_marketing_enabled": {
"message": "Allow referral marketing",
"description": "This string is used as label for the referral marketing switch"
},
"referral_marketing_enabled_title": {
"message": "Allows referral marketing",
"description": "This string is used as title for the referral marketing switch"
},
"watchdog": {
"message": "[ClearURLs]: The watchdog has detected a problem. ClearURLs is restarted.",
"description": "This string is used as text for the watchdog"
}
}

View File

@ -31,22 +31,24 @@ var os;
var currentURL;
/**
* Helper function which remove the tracking fields
* for each provider given as parameter.
*
* @param {Provider} provider Provider-Object
* @return {Array} Array with changes and url fields
*/
function removeFieldsFormURL(provider, pureUrl)
* Helper function which remove the tracking fields
* for each provider given as parameter.
*
* @param {Provider} provider Provider-Object
* @param pureUrl URL as String
* @param {boolean} quiet if the action should be displayed in log and statistics
* @return {Array} Array with changes and url fields
*/
function removeFieldsFormURL(provider, pureUrl, quiet = false)
{
var url = pureUrl;
var domain = "";
var fragments = "";
var fields = "";
var rules = provider.getRules();
var changes = false;
var cancel = false;
var rawRules = provider.getRawRules();
let url = pureUrl;
let domain = "";
let fragments = "";
let fields = "";
let rules = provider.getRules();
let changes = false;
let cancel = false;
let rawRules = provider.getRawRules();
if(storage.localHostsSkipping && checkLocalURL(pureUrl)) {
return {
@ -60,19 +62,19 @@ function removeFieldsFormURL(provider, pureUrl)
* Apply raw rules to the URL.
*/
rawRules.forEach(function(rawRule) {
var beforReplace = url;
let beforeReplace = url;
url = url.replace(new RegExp(rawRule, "gi"), "");
if(beforReplace !== url) {
if(beforeReplace !== url) {
//Log the action
if(storage.loggingStatus)
if(storage.loggingStatus && !quiet)
{
pushToLog(beforReplace, url, rawRule);
pushToLog(beforeReplace, url, rawRule);
}
if(badges[tabid] == null) badges[tabid] = 0;
increaseURLCounter();
if(!quiet) increaseURLCounter();
checkOSAndroid().then((res) => {
if(!res) {
@ -102,12 +104,13 @@ function removeFieldsFormURL(provider, pureUrl)
* Expand the url by provider redirections. So no tracking on
* url redirections form sites to sites.
*/
var re = provider.getRedirection(url);
let re = provider.getRedirection(url);
if(re !== null)
{
url = decodeURIComponent(re);
url = decodeURL(re);
//Log the action
pushToLog(pureUrl, url, translate('log_redirect'));
if(!quiet) pushToLog(pureUrl, url, translate('log_redirect'));
return {
"redirect": true,
@ -129,30 +132,30 @@ function removeFieldsFormURL(provider, pureUrl)
if(fields !== "" || fragments !== "")
{
rules.forEach(function(rule) {
var beforReplace = fields;
var beforReplaceFragments = fragments;
let beforeReplace = fields;
let beforeReplaceFragments = fragments;
fields = fields.replace(new RegExp(rule, "gi"), "");
fragments = fragments.replace(new RegExp(rule, "gi"), "");
if(beforReplace !== fields || beforReplaceFragments !== fragments)
if(beforeReplace !== fields || beforeReplaceFragments !== fragments)
{
//Log the action
if(storage.loggingStatus)
{
var tempURL = domain;
var tempBeforeURL = domain;
let tempURL = domain;
let tempBeforeURL = domain;
if(fields !== "") tempURL += "?"+fields.replace("?&", "?").replace("?", "");
if(fragments !== "") tempURL += "#"+fragments.replace("#&","#").replace("#", "");
if(beforReplace !== "") tempBeforeURL += "?"+beforReplace.replace("?&", "?").replace("?", "");
if(beforReplaceFragments !== "") tempBeforeURL += "#"+beforReplaceFragments.replace("#&","#").replace("#", "");
if(beforeReplace !== "") tempBeforeURL += "?"+beforeReplace.replace("?&", "?").replace("?", "");
if(beforeReplaceFragments !== "") tempBeforeURL += "#"+beforeReplaceFragments.replace("#&","#").replace("#", "");
pushToLog(tempBeforeURL, tempURL, rule);
if(!quiet) pushToLog(tempBeforeURL, tempURL, rule);
}
if(badges[tabid] == null) badges[tabid] = 0;
increaseURLCounter();
if(!quiet) increaseURLCounter();
checkOSAndroid().then((res) => {
if(!res) {
@ -171,7 +174,7 @@ function removeFieldsFormURL(provider, pureUrl)
}
});
var finalURL = domain;
let finalURL = domain;
if(fields !== "") finalURL += "?"+fields.replace("?", "");
if(fragments !== "") finalURL += "#"+fragments.replace("#", "");
@ -180,13 +183,13 @@ function removeFieldsFormURL(provider, pureUrl)
}
if(provider.isCaneling()){
pushToLog(pureUrl, pureUrl, translate('log_domain_blocked'));
if(!quiet) pushToLog(pureUrl, pureUrl, translate('log_domain_blocked'));
if(badges[tabid] == null)
{
badges[tabid] = 0;
}
increaseURLCounter();
if(!quiet) increaseURLCounter();
checkOSAndroid().then((res) => {
if(!res) {
@ -218,7 +221,7 @@ function start()
* @param {JSON Object} obj
*/
function getKeys(obj){
for(var key in obj){
for(const key in obj){
prvKeys.push(key);
}
}
@ -229,9 +232,9 @@ function start()
*/
function createProviders()
{
data = storage.ClearURLsData;
let data = storage.ClearURLsData;
for(var p = 0; p < prvKeys.length; p++)
for(let p = 0; p < prvKeys.length; p++)
{
//Create new provider
providers.push(new Provider(prvKeys[p], data.providers[prvKeys[p]].completeProvider,
@ -241,25 +244,31 @@ function start()
providers[p].setURLPattern(data.providers[prvKeys[p]].urlPattern);
//Add rules to provider
for(var r = 0; r < data.providers[prvKeys[p]].rules.length; r++)
for(let r = 0; r < data.providers[prvKeys[p]].rules.length; r++)
{
providers[p].addRule(data.providers[prvKeys[p]].rules[r]);
}
//Add raw rules to provider
for(var raw = 0; raw < data.providers[prvKeys[p]].rawRules.length; raw++)
for(let raw = 0; raw < data.providers[prvKeys[p]].rawRules.length; raw++)
{
providers[p].addRawRule(data.providers[prvKeys[p]].rawRules[raw]);
}
//Add referral marketing rules to provider
for(let referralMarketing = 0; referralMarketing < data.providers[prvKeys[p]].referralMarketing.length; referralMarketing++)
{
providers[p].addReferralMarketing(data.providers[prvKeys[p]].referralMarketing[referralMarketing]);
}
//Add exceptions to provider
for(var e = 0; e < data.providers[prvKeys[p]].exceptions.length; e++)
for(let e = 0; e < data.providers[prvKeys[p]].exceptions.length; e++)
{
providers[p].addException(data.providers[prvKeys[p]].exceptions[e]);
}
//Add redirections to provider
for(var re = 0; re < data.providers[prvKeys[p]].redirections.length; re++)
for(let re = 0; re < data.providers[prvKeys[p]].redirections.length; re++)
{
providers[p].addRedirection(data.providers[prvKeys[p]].redirections[re]);
}
@ -288,22 +297,18 @@ function start()
//Get the target hash from github
fetch(storage.hashURL)
.then(function(response){
var responseTextHash = response.clone().text().then(function(responseTextHash){
if(response.ok && $.trim(responseTextHash))
{
const responseTextHash = response.clone().text().then(function (responseTextHash) {
if (response.ok && $.trim(responseTextHash)) {
dataHash = responseTextHash;
if($.trim(dataHash) !== $.trim(localDataHash))
{
if ($.trim(dataHash) !== $.trim(localDataHash)) {
fetchFromURL();
}
else {
} else {
toObject(storage.ClearURLsData);
storeHashStatus(1);
saveOnDisk(['hashStatus']);
}
}
else {
} else {
dataHash = false;
}
});
@ -322,18 +327,15 @@ function start()
function checkResponse(response)
{
var responseText = response.clone().text().then(function(responseText){
if(response.ok && $.trim(responseText))
{
var downloadedFileHash = $.sha256(responseText);
const responseText = response.clone().text().then(function (responseText) {
if (response.ok && $.trim(responseText)) {
const downloadedFileHash = $.sha256(responseText);
if($.trim(downloadedFileHash) === $.trim(dataHash))
{
if ($.trim(downloadedFileHash) === $.trim(dataHash)) {
storage.ClearURLsData = responseText;
storage.dataHash = downloadedFileHash;
storeHashStatus(2);
}
else {
} else {
storeHashStatus(3);
}
storage.ClearURLsData = JSON.parse(storage.ClearURLsData);
@ -360,18 +362,20 @@ function start()
* @param {boolean} _isActive Is the provider active?
*/
function Provider(_name, _completeProvider = false, _forceRedirection = false, _isActive = true){
var name = _name;
var urlPattern;
var enabled_rules = {};
var disabled_rules = {};
var enabled_exceptions = {};
var disabled_exceptions = {};
var canceling = _completeProvider;
var enabled_redirections = {};
var disabled_redirections = {};
var active = _isActive;
var enabled_rawRules = {};
var disabled_rawRules = {};
let name = _name;
let urlPattern;
let enabled_rules = {};
let disabled_rules = {};
let enabled_exceptions = {};
let disabled_exceptions = {};
let canceling = _completeProvider;
let enabled_redirections = {};
let disabled_redirections = {};
let active = _isActive;
let enabled_rawRules = {};
let disabled_rawRules = {};
let enabled_referralMarketing = {};
let disabled_referralMarketing = {};
if(_completeProvider){
enabled_rules[".*"] = true;
@ -419,6 +423,33 @@ function start()
return urlPattern.test(url) && !(this.matchException(url));
};
/**
* Apply a rule to a given tuple of rule array.
* @param enabledRuleArray array for enabled rules
* @param disabledRulesArray array for disabled rules
* @param {String} rule RegExp as string
* @param {boolean} isActive Is this rule active?
*/
this.applyRule = (enabledRuleArray, disabledRulesArray, rule, isActive = true) => {
if(isActive)
{
enabledRuleArray[rule] = true;
if(disabledRulesArray[rule] !== undefined)
{
delete disabledRulesArray[rule];
}
}
else {
disabledRulesArray[rule] = true;
if(enabledRuleArray[rule] !== undefined)
{
delete enabledRuleArray[rule];
}
}
};
/**
* Add a rule to the rule array
* and replace old rule with new rule.
@ -429,23 +460,7 @@ function start()
this.addRule = function(rule, isActive = true) {
rule = "([\\/|\\?|#]|(&|&amp;))+("+rule+"=[^\\/|\\?|&]*)";
if(isActive)
{
enabled_rules[rule] = true;
if(disabled_rules[rule] !== undefined)
{
delete disabled_rules[rule];
}
}
else {
disabled_rules[rule] = true;
if(enabled_rules[rule] !== undefined)
{
delete enabled_rules[rule];
}
}
this.applyRule(enabled_rules, disabled_rules, rule, isActive);
};
/**
@ -465,23 +480,7 @@ function start()
* @param {boolean} isActive Is this rule active?
*/
this.addRawRule = function(rule, isActive = true) {
if(isActive)
{
enabled_rawRules[rule] = true;
if(disabled_rawRules[rule] !== undefined)
{
delete disabled_rawRules[rule];
}
}
else {
disabled_rawRules[rule] = true;
if(enabled_rawRules[rule] !== undefined)
{
delete enabled_rawRules[rule];
}
}
this.applyRule(enabled_rawRules, disabled_rawRules, rule, isActive);
};
/**
@ -490,9 +489,24 @@ function start()
* @return Array RegExp strings
*/
this.getRawRules = function() {
if(!storage.referralMarketing) {
return Object.keys(Object.assign(enabled_rawRules, enabled_referralMarketing));
}
return Object.keys(enabled_rawRules);
};
/**
* Add a referral marketing rule to the referral marketing array
* and replace old referral marketing rule with new referral marketing rule.
*
* @param {String} rule RegExp as string
* @param {boolean} isActive Is this rule active?
*/
this.addReferralMarketing = function(rule, isActive = true) {
this.applyRule(enabled_referralMarketing, disabled_referralMarketing, rule, isActive);
};
/**
* Add a exception to the exceptions array
* and replace old with new exception.
@ -528,15 +542,15 @@ function start()
* @return {boolean} if matching? true: false
*/
this.matchException = function(url) {
var result = false;
let result = false;
//Add the site blocked alert to every exception
if(url == siteBlockedAlert) return true;
if(url === siteBlockedAlert) return true;
for(var exception in enabled_exceptions) {
for(const exception in enabled_exceptions) {
if(result) break;
exception_regex = new RegExp(exception, "i");
let exception_regex = new RegExp(exception, "i");
result = exception_regex.test(url);
}
@ -576,10 +590,10 @@ function start()
* @return url
*/
this.getRedirection = function(url) {
var re = null;
let re = null;
for(var redirection in enabled_redirections) {
result = (url.match(new RegExp(redirection, "i")));
for(const redirection in enabled_redirections) {
let result = (url.match(new RegExp(redirection, "i")));
if (result && result.length > 0 && redirection)
{
@ -603,13 +617,13 @@ function start()
*/
function clearUrl(request)
{
var URLbeforeReplaceCount = countFields(request.url);
const URLbeforeReplaceCount = countFields(request.url);
//Add Fields form Request to global url counter
increaseGlobalURLCounter(URLbeforeReplaceCount);
if(storage.globalStatus){
var result = {
let result = {
"changes": false,
"url": "",
"redirect": false,
@ -619,7 +633,7 @@ function start()
/*
* Call for every provider the removeFieldsFormURL method.
*/
for (var i = 0; i < providers.length; i++) {
for (let i = 0; i < providers.length; i++) {
if(providers[i].matchURL(request.url))
{
@ -648,9 +662,16 @@ function start()
* to inform the user about the full url blocking.
*/
if(result.cancel){
return {
redirectUrl: siteBlockedAlert
};
if(request.type === 'main_frame') {
const blockingPage = browser.extension.getURL("html/siteBlockedAlert.html?source="+encodeURIComponent(request.url));
browser.tabs.update(request.tabId, {url: blockingPage});
return {cancel: true};
} else {
return {
redirectUrl: siteBlockedAlert
};
}
}
/*
@ -719,8 +740,7 @@ function start()
return {};
}
else {
var ret = clearUrl(requestDetails);
return ret;
return clearUrl(requestDetails);
}
}
@ -732,9 +752,9 @@ function start()
* @return {boolean}
*/
function isDataURL(requestDetails) {
var s = requestDetails.url;
const s = requestDetails.url;
return s.substring(0,4) == "data";
return s.substring(0,4) === "data";
}
/**
@ -761,8 +781,15 @@ function start()
*/
function pushToLog(beforeProcessing, afterProcessing, rule)
{
if(storage.loggingStatus)
const limit = storage.logLimit;
if(storage.loggingStatus && limit !== 0)
{
if(limit > 0 && !isNaN(limit)) {
while(storage.log.log.length >= limit) {
storage.log.log.shift();
}
}
storage.log.log.push(
{
"before": beforeProcessing,

View File

@ -33,9 +33,9 @@ $(document).ready(function(){
* This function cleans all URLs line by line in the textarea.
*/
function cleanURLs() {
var cleanTArea = $('#cleanURLs');
var dirtyTArea = $('#dirtyURLs');
var urls = dirtyTArea.val().split('\n');
const cleanTArea = $('#cleanURLs');
const dirtyTArea = $('#dirtyURLs');
const urls = dirtyTArea.val().split('\n');
cleanedURLs = [];
length = urls.length;

View File

@ -25,8 +25,8 @@
"use strict";
function injectFunction() {
var ele = document.createElement('script');
var s = document.getElementsByTagName('script')[0];
let ele = document.createElement('script');
let s = document.getElementsByTagName('script')[0];
ele.type = 'text/javascript';
ele.textContent = "Object.defineProperty(window, 'rwt', {" +
@ -46,13 +46,13 @@
injectFunction();
document.addEventListener('mouseover', function (event) {
var a = event.target, depth = 1;
let a = event.target, depth = 1;
while (a && a.tagName != 'A' && depth-- > 0) {
while (a && a.tagName !== 'A' && depth-- > 0) {
a = a.parentNode;
}
if (a && a.tagName == 'A') {
if (a && a.tagName === 'A') {
try {
a.removeAttribute('data-cthref');
delete a.dataset.cthref;

View File

@ -37,14 +37,16 @@ function historyListenerStart() {
* which is associated with the new history entry created by replaceState()
*/
function historyCleaner(details) {
var urlBefore = details.url;
var urlAfter = pureCleaning(details.url);
if(storage.globalStatus) {
const urlBefore = details.url;
const urlAfter = pureCleaning(details.url);
if(urlBefore != urlAfter) {
browser.tabs.executeScript(details.tabId, {
frameId: details.frameId,
code: 'history.replaceState({state: "cleaned_history"},"",'+JSON.stringify(urlAfter)+');'
}).then(() => {}, onError);
if(urlBefore !== urlAfter) {
browser.tabs.executeScript(details.tabId, {
frameId: details.frameId,
code: 'history.replaceState({state: "cleaned_history"},"",'+JSON.stringify(urlAfter)+');'
}).then(() => {}, onError);
}
}
}

View File

@ -26,7 +26,7 @@ var log = {};
* Reset the global log
*/
function resetGlobalLog(){
obj = {"log": []};
let obj = {"log": []};
browser.runtime.sendMessage({
function: "setData",
@ -53,11 +53,11 @@ function getLog()
return b.timestamp - a.timestamp;
});
var length = Object.keys(log.log).length;
var row;
if(length != 0)
const length = Object.keys(log.log).length;
let row;
if(length !== 0)
{
for(var i=0; i<length;i++)
for(let i=0; i<length;i++)
{
row = "<tr>" +
"<td>"+log.log[i].before+"</td>" +
@ -81,11 +81,9 @@ function getLog()
*/
function getDataTableTranslation()
{
var lang = browser.i18n.getUILanguage();
let lang = browser.i18n.getUILanguage();
lang = lang.substring(0,2);
var file = browser.extension.getURL('./external_js/dataTables/i18n/'+lang+'.lang');
return file;
return browser.extension.getURL('./external_js/dataTables/i18n/' + lang + '.lang');
}
/**
@ -96,6 +94,42 @@ function toDate(time)
return new Date(time).toLocaleString();
}
/**
* This function export the global log as json file.
*/
function exportGlobalLog() {
browser.runtime.sendMessage({
function: "getData",
params: ['log']
}).then((data) => {
let blob = new Blob([JSON.stringify(data.response)], {type: 'application/json'});
browser.downloads.download({
'url': URL.createObjectURL(blob),
'filename': 'ClearURLsLogExport.json',
'saveAs': true
});
});
}
/**
* This function imports an exported global log and overwrites the old one.
*/
function importGlobalLog(evt) {
let file = evt.target.files[0];
let fileReader = new FileReader();
fileReader.onload = function(e) {
browser.runtime.sendMessage({
function: "setData",
params: ["log", e.target.result]
}).then(() => {
location.reload();
}, handleError);
};
fileReader.readAsText(file);
}
/**
* Load only when document is ready
*/
@ -103,6 +137,8 @@ $(document).ready(function(){
setText();
getLog();
$('#reset_log_btn').on("click", resetGlobalLog);
$('#export_log_btn').on("click", exportGlobalLog);
$('#importLog').on("change", importGlobalLog);
});
/**
@ -122,12 +158,16 @@ function setText()
{
document.title = translate('log_html_page_title');
$('#page_title').text(translate('log_html_page_title'));
$('#reset_log_btn').text(translate('log_html_reset_button'));
$('#log_html_reset_button').prop('title', translate('log_html_reset_button_title'));
$('#reset_log_btn').text(translate('log_html_reset_button'))
.prop('title', translate('log_html_reset_button_title'));
$('#head_1').text(translate('log_html_table_head_1'));
$('#head_2').text(translate('log_html_table_head_2'));
$('#head_3').text(translate('log_html_table_head_3'));
$('#head_4').text(translate('log_html_table_head_4'));
$('#export_log_btn_text').text(translate('log_html_export_button'));
$('#export_log_btn').prop('title', translate('log_html_export_button_title'));
$('#import_log_btn_text').text(translate('log_html_import_button'));
$('#import_log_btn').prop('title', translate('log_html_import_button_title'));
}
function handleError(error) {

View File

@ -29,11 +29,11 @@
*/
function handleMessage(request, sender, sendResponse)
{
var fn = window[request.function];
let fn = window[request.function];
if(typeof fn === "function")
{
var response = fn.apply(null, request.params);
let response = fn.apply(null, request.params);
return Promise.resolve({response});
}

View File

@ -107,7 +107,6 @@ function init()
/**
* Get the globalCounter and globalurlcounter value from the storage
* @param {(data){} Return value form storage
*/
function changeStatistics()
{
@ -127,7 +126,7 @@ function changeStatistics()
*/
function setHashStatus()
{
var element = $('#hashStatus');
let element = $('#hashStatus');
if(hashStatus)
{
@ -146,7 +145,7 @@ function setHashStatus()
*/
function changeSwitchButton(id, storageID)
{
var element = $('#'+id);
let element = $('#'+id);
changeVisibility(id, storageID);
@ -155,7 +154,7 @@ function changeSwitchButton(id, storageID)
function: "setData",
params: [storageID, element.is(':checked')]
}).then((data) => {
if(storageID == "globalStatus"){
if(storageID === "globalStatus"){
browser.runtime.sendMessage({
function: "changeIcon",
params: []
@ -176,7 +175,7 @@ function changeSwitchButton(id, storageID)
*/
function changeVisibility(id, storageID)
{
var element;
let element;
switch(storageID)
{
@ -190,7 +189,7 @@ function changeVisibility(id, storageID)
element = "undefine";
}
if(element != "undefine")
if(element !== "undefine")
{
if($('#'+id).is(':checked'))
{
@ -211,7 +210,7 @@ function changeVisibility(id, storageID)
*/
function setSwitchButton(id, varname)
{
var element = $('#'+id);
let element = $('#'+id);
element.prop('checked', this[varname]);
}
@ -281,11 +280,11 @@ function setText()
*
* @param {string} id ID of the HTML element
* @param {string} attribute Name of the attribute used for localization
* @param {boolean} tooltip
* @param {string} tooltip
*/
function injectText(id, attribute, tooltip)
function injectText(id, attribute, tooltip = "")
{
object = $('#'+id);
let object = $('#'+id);
object.text(translate(attribute));
/*
@ -294,7 +293,7 @@ function injectText(id, attribute, tooltip)
*/
tooltip = translate(attribute+"_title");
if(tooltip != "")
if(tooltip !== "")
{
object.prop('title', tooltip);
}

View File

@ -19,20 +19,23 @@
/*jshint esversion: 6 */
/**
* Cleans given links. Also do automatic redirection.
*
* @param {[type]} url url as string
* @return {Array} redirectUrl or none
*/
function pureCleaning(url) {
var cleanURL = url;
var URLbeforeReplaceCount = countFields(url);
* Cleans given links. Also do automatic redirection.
*
* @param {String} url url as string
* @param {boolean} quiet if the action should be displayed in log and statistics
* @return {String} redirectUrl or none
*/
function pureCleaning(url, quiet = false) {
let cleanURL = url;
const URLbeforeReplaceCount = countFields(url);
//Add Fields form Request to global url counter
increaseGlobalURLCounter(URLbeforeReplaceCount);
if(!quiet) {
//Add Fields form Request to global url counter
increaseGlobalURLCounter(URLbeforeReplaceCount);
}
for (var i = 0; i < providers.length; i++) {
var result = {
for (let i = 0; i < providers.length; i++) {
let result = {
"changes": false,
"url": "",
"redirect": false,
@ -41,7 +44,7 @@ function pureCleaning(url) {
if(providers[i].matchURL(cleanURL))
{
result = removeFieldsFormURL(providers[i], cleanURL);
result = removeFieldsFormURL(providers[i], cleanURL, quiet);
cleanURL = result.url;
}

View File

@ -27,6 +27,8 @@ $(document).ready(function(){
setText();
$(".pick-a-color").pickAColor();
$('#reset_settings_btn').on("click", reset);
$('#export_settings_btn').on("click", exportSettings);
$('#importSettings').on("change", importSettings);
$('#save_settings_btn').on("click", save);
$("#badged_color input").on("change", function () {
@ -101,6 +103,11 @@ function save()
params: ["types", $('input[name=types]').val()]
}).then(handleResponse, handleError);
browser.runtime.sendMessage({
function: "setData",
params: ["logLimit", $('input[name=logLimit]').val()]
}).then(handleResponse, handleError);
browser.runtime.sendMessage({
function: "saveOnExit",
params: []
@ -113,13 +120,14 @@ function save()
}
/**
* Translate a string with the i18n API.
*
* @param {string} string Name of the attribute used for localization
* Translate a string with the i18n API.
*
* @param {string} string Name of the attribute used for localization
* @param {string[]} placeholders Array of placeholders
*/
function translate(string)
function translate(string, ...placeholders)
{
return browser.i18n.getMessage(string);
return browser.i18n.getMessage(string, placeholders);
}
/**
@ -147,6 +155,18 @@ function getData()
params: ["types"]
}).then((data) => handleResponseData(data, "types", "types"), handleError);
browser.runtime.sendMessage({
function: "getData",
params: ["logLimit"]
}).then((data) => {
handleResponseData(data, "logLimit", "logLimit");
if(data.response === undefined || data.response === -1) {
$('#logLimit_label').text(translate('setting_log_limit_label', "∞"));
} else {
$('#logLimit_label').text(translate('setting_log_limit_label', data.response));
}
}, handleError);
browser.runtime.sendMessage({
function: "getData",
params: ["contextMenuEnabled"]
@ -162,9 +182,16 @@ function getData()
params: ["localHostsSkipping"]
}).then((data) => {
handleResponseData(data, "localHostsSkipping", "localHostsSkipping");
changeSwitchButton("contextMenuEnabled", "contextMenuEnabled");
changeSwitchButton("historyListenerEnabled", "historyListenerEnabled");
changeSwitchButton("localHostsSkipping", "localHostsSkipping");
browser.runtime.sendMessage({
function: "getData",
params: ["referralMarketing"]
}).then((data) => {
handleResponseData(data, "referralMarketing", "referralMarketing");
changeSwitchButton("contextMenuEnabled", "contextMenuEnabled");
changeSwitchButton("historyListenerEnabled", "historyListenerEnabled");
changeSwitchButton("localHostsSkipping", "localHostsSkipping");
changeSwitchButton("referralMarketing", "referralMarketing");
}, handleError);
}, handleError);
}, handleError);
}, handleError);
@ -178,22 +205,74 @@ function setText()
document.title = translate('settings_html_page_title');
$('#page_title').text(translate('settings_html_page_title'));
$('#badged_color_label').text(translate('badged_color_label'));
$('#reset_settings_btn').text(translate('setting_html_reset_button'));
$('#reset_settings_btn').prop('title', translate('setting_html_reset_button_title'));
$('#reset_settings_btn').text(translate('setting_html_reset_button'))
.prop('title', translate('setting_html_reset_button_title'));
$('#rule_url_label').text(translate('setting_rule_url_label'));
$('#hash_url_label').text(translate('setting_hash_url_label'));
$('#types_label').html(translate('setting_types_label'));
$('#save_settings_btn').text(translate('settings_html_save_button'));
$('#save_settings_btn').prop('title', translate('settings_html_save_button_title'));
$('#save_settings_btn').text(translate('settings_html_save_button'))
.prop('title', translate('settings_html_save_button_title'));
injectText("context_menu_enabled", "context_menu_enabled");
$('#history_listener_enabled').html(translate('history_listener_enabled'));
injectText("local_hosts_skipping", "local_hosts_skipping");
$('#export_settings_btn_text').text(translate('setting_html_export_button'));
$('#export_settings_btn').prop('title', translate('setting_html_export_button_title'));
$('#import_settings_btn_text').text(translate('setting_html_import_button'));
$('#import_settings_btn').prop('title', translate('setting_html_import_button_title'));
injectText("referral_marketing_enabled", "referral_marketing_enabled");
}
/**
* Handle the response from the storage and saves the data.
* @param {JSON-Object} data Data JSON-Object
*/
* This function exports all ClearURLs settings with statistics and rules.
*/
function exportSettings() {
browser.runtime.sendMessage({
function: "storageAsJSON",
params: []
}).then((data) => {
let blob = new Blob([JSON.stringify(data.response)], {type: 'application/json'});
browser.downloads.download({
'url': URL.createObjectURL(blob),
'filename': 'ClearURLs.conf',
'saveAs': true
});
});
}
/**
* This function imports an exported ClearURLs setting and overwrites the old one.
*/
function importSettings(evt) {
let file = evt.target.files[0];
let fileReader = new FileReader();
fileReader.onload = function(e) {
let data = JSON.parse(e.target.result);
const length = Object.keys(data).length;
let i=0;
Object.entries(data).forEach(([key, value]) => {
browser.runtime.sendMessage({
function: "setData",
params: [key, value]
}).then(() => {
i++;
if(i === length) {
location.reload();
}
}, handleError);
});
};
fileReader.readAsText(file);
}
/**
* Handle the response from the storage and saves the data.
* @param {JSON-Object} data Data JSON-Object
* @param varName
* @param inputID
*/
function handleResponseData(data, varName, inputID)
{
settings[varName] = data.response;
@ -215,14 +294,14 @@ function handleError(error) {
*/
function changeSwitchButton(id, storageID)
{
var element = $('#'+id);
let element = $('#'+id);
element.on('change', function(){
browser.runtime.sendMessage({
function: "setData",
params: [storageID, element.is(':checked')]
}).then((data) => {
if(storageID == "globalStatus"){
if(storageID === "globalStatus"){
browser.runtime.sendMessage({
function: "changeIcon",
params: []
@ -245,9 +324,9 @@ function changeSwitchButton(id, storageID)
* @param {string} attribute Name of the attribute used for localization
* @param {boolean} tooltip
*/
function injectText(id, attribute, tooltip)
function injectText(id, attribute, tooltip = "")
{
object = $('#'+id);
let object = $('#'+id);
object.text(translate(attribute));
/*
@ -256,7 +335,7 @@ function injectText(id, attribute, tooltip)
*/
tooltip = translate(attribute+"_title");
if(tooltip != "")
if(tooltip !== "")
{
object.prop('title', tooltip);
}
@ -269,6 +348,6 @@ function injectText(id, attribute, tooltip)
*/
function setSwitchButton(id, varname)
{
var element = $('#'+id);
let element = $('#'+id);
element.prop('checked', settings[varname]);
}

View File

@ -0,0 +1,51 @@
/*
* ClearURLs
* Copyright (c) 2017-2019 Kevin Röbert
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*jshint esversion: 6 */
/*
* This script is responsible for the blocked alert page.
*/
/**
* Set the text for the UI.
*/
function setText()
{
document.title = translate('blocked_html_title');
$('#title').html(translate('blocked_html_title'));
$('#body').html(translate('blocked_html_body'));
$('#page').text(translate('blocked_html_button'));
}
$(document).ready(function(){
setText();
let source = new URLSearchParams(window.location.search).get("source");
$('#page').attr('href', decodeURIComponent(source));
});
/**
* Translate a string with the i18n API.
*
* @param {string} string Name of the attribute used for localization
*/
function translate(string)
{
return browser.i18n.getMessage(string);
}

View File

@ -29,23 +29,39 @@ var pendingSaves = new Set();
*/
function saveOnExit()
{
var json = {};
saveOnDisk(Object.keys(storage));
}
/**
* Returns the storage as JSON.
*/
function storageAsJSON() {
let json = {};
Object.entries(storage).forEach(([key, value]) => {
switch (key) {
case "ClearURLsData":
case "log":
json[key] = JSON.stringify(value);
break;
case "types":
json[key] = value.toString();
break;
default:
json[key] = value;
}
json[key] = storageDataAsString(key);
});
console.log(translate('core_save_on_disk'));
browser.storage.local.set(json);
return json;
}
/**
* Converts a given storage data to its string representation.
* @param key key of the storage data
* @returns {string} string representation
*/
function storageDataAsString(key) {
let value = storage[key];
switch (key) {
case "ClearURLsData":
case "log":
return JSON.stringify(value);
case "types":
return value.toString();
default:
return value;
}
}
/**
@ -54,22 +70,12 @@ function saveOnExit()
*/
function saveOnDisk(keys)
{
var json = {};
let json = {};
keys.forEach(function(key) {
var value = storage[key];
switch (key) {
case "ClearURLsData":
case "log":
json[key] = JSON.stringify(value);
break;
case "types":
json[key] = value.toString();
break;
default:
json[key] = value;
}
json[key] = storageDataAsString(key);
});
console.log(translate('core_save_on_disk'));
browser.storage.local.set(json);
}
@ -145,17 +151,20 @@ function setData(key, value)
switch (key) {
case "ClearURLsData":
case "log":
storage[key] = JSON.parse(value);
break;
storage[key] = JSON.parse(value);
break;
case "hashURL":
case "ruleURL":
storage[key] = replaceOldURLs(value);
break;
storage[key] = replaceOldURLs(value);
break;
case "types":
storage[key] = value.split(',');
break;
storage[key] = value.split(',');
break;
case "logLimit":
storage[key] = Number(value);
break;
default:
storage[key] = value;
storage[key] = value;
}
}
@ -204,6 +213,8 @@ function initSettings()
storage.contextMenuEnabled = true;
storage.historyListenerEnabled = true;
storage.localHostsSkipping = true;
storage.referralMarketing = false;
storage.logLimit = -1;
if(getBrowser() === "Firefox") {
storage.types = ["font", "image", "imageset", "main_frame", "media", "object", "object_subrequest", "other", "script", "stylesheet", "sub_frame", "websocket", "xbl", "xml_dtd", "xmlhttprequest", "xslt"];

View File

@ -75,19 +75,13 @@ async function checkOSAndroid()
});
}
if(os == "android")
{
return true;
}
else{
return false;
}
return os === "android";
}
/**
* Extract the host without port from an url.
* @param {String} url URL as String
* @return {Array} host as string
* @return {String} host as string
*/
function extractHost(url) {
let parsed_url = new URL(url);
@ -126,8 +120,8 @@ function countFields(url)
*/
function existsFields(url)
{
var matches = (url.match(/\?.+/i) || []);
var count = matches.length;
let matches = (url.match(/\?.+/i) || []);
let count = matches.length;
return (count > 0);
}
@ -140,7 +134,7 @@ function existsFields(url)
function extractFileds(url)
{
if(existsFields(url)) {
var fields = url.replace(new RegExp(".*?\\?", "i"), "");
let fields = url.replace(new RegExp(".*?\\?", "i"), "");
if(existsFragments(url)) {
fields = fields.replace(new RegExp("#.*", "i"), "");
}
@ -169,7 +163,7 @@ function countFragments(url)
function extractFragments(url)
{
if(existsFragments(url)) {
var fragments = url.replace(new RegExp(".*?#", "i"), "");
let fragments = url.replace(new RegExp(".*?#", "i"), "");
return (fragments.match(/[^&]+=?[^&]*/gi) || []);
}
@ -183,8 +177,8 @@ function extractFragments(url)
*/
function existsFragments(url)
{
var matches = (url.match(/\#.+/i) || []);
var count = matches.length;
let matches = (url.match(/\#.+/i) || []);
let count = matches.length;
return (count > 0);
}
@ -298,3 +292,16 @@ function getBrowser() {
return "Chrome";
}
}
/**
* Decodes an URL, also one that is encoded multiple times.
* @param url the url, that should be decoded
*/
function decodeURL(url) {
const rtn = decodeURIComponent(url);
if(rtn.indexOf("http://") === -1 && rtn.indexOf("https://") === -1) {
return decodeURL(rtn);
}
return rtn;
}

38
core_js/watchdog.js Normal file
View File

@ -0,0 +1,38 @@
/*
* ClearURLs
* Copyright (c) 2017-2019 Kevin Röbert
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*jshint esversion: 6 */
/*
* This script is responsible to check in fixed intervals, that ClearURLs works properly.
* In issue #203, some users reported, that ClearURLs filter function doesn't work after
* some time, but without any recognizable reason.
*
* This watchdog restarts the whole Add-on, when the check fails.
*/
const CHECK_INTERVAL = 15000;
setInterval(function() {
const dirtyURL = "https://clearurls.roebert.eu?utm_source=addon";
const cleanURL = "https://clearurls.roebert.eu";
if(pureCleaning(dirtyURL, true) !== cleanURL) {
console.log(translate('watchdog'));
saveOnExit();
reload();
}
}, CHECK_INTERVAL);

View File

@ -20,5 +20,5 @@
* This file writes only the version into every page.
* @return version
*/
var version = browser.runtime.getManifest().version;
const version = browser.runtime.getManifest().version;
$('#version').text(version);

View File

@ -28,12 +28,15 @@
"keywords",
"cv_ct_[a-zA-Z]+",
"linkCode",
"tag",
"creativeASIN",
"ascsubtag",
"aaxitk",
"hsa_cr_id",
"sb-ci-[a-zA-Z]+"
"sb-ci-[a-zA-Z]+",
"rnid"
],
"referralMarketing": [
"([\\/|\\?|#]|(&|&amp;))+(tag=[^\\/|\\?|&]*)"
],
"exceptions": [
".*(amazon\\.).*(\\/gp).*\\/redirector.html\\/.*",
@ -50,6 +53,7 @@
"urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(fls-na\\.amazon)(\\.[a-zA-Z]{2,}).*",
"completeProvider": true,
"rules": [],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -92,6 +96,7 @@
"sourceid",
"sxsrf"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [
".*(mail\\.google\\.).*(\\/mail\\/u\\/0).*",
@ -119,15 +124,17 @@
"urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(googlesyndication)(\\.[a-zA-Z]{2,}).*",
"completeProvider": true,
"rules": [],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
"forceRedirection": false
},
"doubleclick": {
"urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(doubleclick)(\\.[a-zA-Z]{2,}).*",
"urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-\\.]*)?(doubleclick)(\\.[a-zA-Z]{2,}).*",
"completeProvider": true,
"rules": [],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [
@ -139,6 +146,7 @@
"urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(googleadservices)(\\.[a-zA-Z]{2,}).*",
"completeProvider": false,
"rules": [],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [
@ -178,6 +186,7 @@
"(%3F)?cmpid",
"(%3F)?os_ehash"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [
".*([\\.]?matrix\\.org)(\\/_matrix)\\/.*",
@ -206,6 +215,7 @@
"urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(adtech)(\\.[a-zA-Z]{2,}).*",
"completeProvider": true,
"rules": [],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -215,6 +225,7 @@
"urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(contentpass\\.(net|de)).*",
"completeProvider": true,
"rules": [],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -224,6 +235,7 @@
"urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(bf-ad)(\\.[a-zA-Z]{2,}).*",
"completeProvider": true,
"rules": [],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -233,6 +245,7 @@
"urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(amazon-adsystem)(\\.[a-zA-Z]{2,}).*",
"completeProvider": true,
"rules": [],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [
@ -244,6 +257,7 @@
"urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(adsensecustomsearchads)(\\.[a-zA-Z]{2,}).*",
"completeProvider": true,
"rules": [],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -257,6 +271,7 @@
"gclid",
"kw"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [
@ -268,6 +283,7 @@
"urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(youtube)(\\.[a-zA-Z]{2,})\\/pagead",
"completeProvider": true,
"rules": [],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -277,6 +293,7 @@
"urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(youtube)(\\.[a-zA-Z]{2,})\\/api\\/stats\\/ads",
"completeProvider": true,
"rules": [],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -303,6 +320,7 @@
"action_history",
"fbid"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [
".*(facebook\\.)\\w{2,}.*(\\/plugins\\/).*",
@ -325,6 +343,7 @@
"cn",
"ref_url"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -334,6 +353,7 @@
"urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(reddit)(\\.[a-zA-Z]{2,}).*",
"completeProvider": false,
"rules": [],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [
@ -350,6 +370,7 @@
"tctx",
"jb[a-zA-Z]*"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -363,6 +384,7 @@
"sr",
"sr_share"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -380,6 +402,7 @@
"qs",
"qp"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -392,6 +415,7 @@
"nb",
"u"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -404,6 +428,7 @@
"tt_medium",
"tt_content"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -416,6 +441,7 @@
"pk_campaign",
"pk_kwd"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -429,6 +455,7 @@
"alid",
"[a-zA-Z]*tk"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -447,6 +474,7 @@
"exp",
"plim"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -461,6 +489,7 @@
"_from",
"hash"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -472,6 +501,7 @@
"rules": [
"ftag"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -484,6 +514,7 @@
"ref_",
"pf_rd_[a-zA-Z]*"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -493,6 +524,7 @@
"urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(govdelivery\\.com).*",
"completeProvider": false,
"rules": [],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [
@ -508,6 +540,7 @@
"u1",
"ath[a-zA-Z]*"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -519,6 +552,7 @@
"rules": [
"pl"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -530,6 +564,7 @@
"rules": [
"xid"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -542,6 +577,7 @@
"spm",
"tpa"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -553,6 +589,7 @@
"rules": [
"smid"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -564,6 +601,7 @@
"rules": [
"wbdcd"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -575,6 +613,7 @@
"rules": [
"snr"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -584,6 +623,7 @@
"urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(steamcommunity\\.com).*",
"completeProvider": false,
"rules": [],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [
@ -595,6 +635,7 @@
"urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(disq\\.us).*",
"completeProvider": false,
"rules": [],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [
@ -606,6 +647,7 @@
"urlPattern": "https?:\\/\\/outgoing\\.prod\\.mozaws\\.net/.*",
"completeProvider": false,
"rules": [],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [
@ -619,6 +661,7 @@
"rules": [
"src"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -631,6 +674,7 @@
"src",
"platform"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [
".*mozilla.org\\/api.*"
@ -644,6 +688,7 @@
"rules": [
"ref"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -655,6 +700,7 @@
"rules": [
"email"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -667,6 +713,7 @@
"email_token",
"email_source"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -676,6 +723,7 @@
"urlPattern": "https?:\\/\\/([a-zA-Z0-9-]*\\.)?(deviantart\\.com).*",
"completeProvider": false,
"rules": [],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [
@ -687,6 +735,7 @@
"urlPattern": "https?:\\/\\/([a-zA-Z0-9-]*\\.)?(site2\\.com).*",
"completeProvider": false,
"rules": [],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [
@ -698,6 +747,7 @@
"urlPattern": "https?:\\/\\/([a-zA-Z0-9-]*\\.)?(site\\.com).*",
"completeProvider": false,
"rules": [],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [
@ -709,6 +759,7 @@
"urlPattern": "https?:\\/\\/([a-zA-Z0-9-]*\\.)?(site3\\.com).*",
"completeProvider": false,
"rules": [],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [
@ -729,6 +780,7 @@
"scm[_a-zA-Z\\-]*",
"pvid"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -740,6 +792,7 @@
"rules": [
"sid"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -751,6 +804,7 @@
"rules": [
"ref"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [
".*(comment-cdn\\.9gag\\.com).*(\\/comment-list.json\\?).*"
@ -762,6 +816,7 @@
"urlPattern": "https?:\\/\\/([a-zA-Z0-9-]*\\.)?(linksynergy\\.com).*",
"completeProvider": false,
"rules": [],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [
@ -775,6 +830,7 @@
"rules": [
"ref"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -784,6 +840,7 @@
"urlPattern": "https?:\\/\\/([a-zA-Z0-9-]*\\.)?(gate\\.sc).*",
"completeProvider": false,
"rules": [],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [
@ -795,6 +852,7 @@
"urlPattern": "https?:\\/\\/([a-zA-Z0-9-]*\\.)?(vk\\.com).*",
"completeProvider": false,
"rules": [],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [
@ -808,6 +866,7 @@
"rules": [
"ref_?"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -824,6 +883,7 @@
"sd",
"bi"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -833,6 +893,7 @@
"urlPattern": "https?:\\/\\/([a-zA-Z0-9-]*\\.)?(curseforge\\.com).*",
"completeProvider": false,
"rules": [],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [
@ -844,6 +905,7 @@
"urlPattern": "https?:\\/\\/([a-zA-Z0-9-]*\\.)?(messenger\\.com).*",
"completeProvider": false,
"rules": [],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [
@ -857,6 +919,7 @@
"rules": [
"__twitter_impression"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -868,6 +931,7 @@
"rules": [
"partner"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -883,6 +947,7 @@
"email_referrer",
"email_subject"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],
@ -896,6 +961,7 @@
"trk",
"li[a-zA-Z]{2}"
],
"referralMarketing": [],
"rawRules": [],
"exceptions": [],
"redirections": [],

View File

@ -32,10 +32,27 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<link rel="stylesheet" href="../css/dataTables.bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="../css/core.css">
<style>
td {
word-wrap: break-word;
max-width: 200px;
}
td {
word-wrap: break-word;
max-width: 200px;
}
.fileinput-button {
position: relative;
overflow: hidden;
display: inline-block;
}
.fileinput-button input {
position: absolute;
top: 0;
right: 0;
margin: 0;
opacity: 0;
-ms-filter: 'alpha(opacity=0)';
direction: ltr;
cursor: pointer;
}
</style>
</head>
<body>
@ -58,7 +75,23 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<div class="col-md-10 col-md-offset-1">
<p class="text-center">
<button type="button" id="reset_log_btn"
class="btn btn-danger" title="Reset the global log"></button>
class="btn btn-danger" title="Reset the global log">
</button>
<button type="button" id="export_log_btn"
class="btn btn-success" title="Export the global log">
<i class="glyphicon glyphicon-save"></i>
<span id="export_log_btn_text"></span>
</button>
<span id="import_log_btn"
class="btn btn-success fileinput-button" title="Import the global log">
<i class="glyphicon glyphicon-open"></i>
<span id="import_log_btn_text"></span>
<input type="file" name="file" id="importLog"/>
</span>
</p>
<div class="table-responsive">
<table class="table table-striped table-bordered"

View File

@ -37,6 +37,23 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
word-wrap: break-word;
max-width: 200px;
}
.fileinput-button {
position: relative;
overflow: hidden;
display: inline-block;
}
.fileinput-button input {
position: absolute;
top: 0;
right: 0;
margin: 0;
opacity: 0;
-ms-filter: 'alpha(opacity=0)';
direction: ltr;
cursor: pointer;
}
</style>
</head>
<body>
@ -60,6 +77,19 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<p class="text-center">
<button type="button" id="reset_settings_btn"
class="btn btn-danger" title="Reset everything settings"></button>
<button type="button" id="export_settings_btn"
class="btn btn-success" title="Export the settings">
<i class="glyphicon glyphicon-save"></i>
<span id="export_settings_btn_text"></span>
</button>
<span id="import_settings_btn"
class="btn btn-success fileinput-button" title="Import the settings">
<i class="glyphicon glyphicon-open"></i>
<span id="import_settings_btn_text"></span>
<input type="file" name="file" id="importSettings"/>
</span>
</p>
<br />
<p>
@ -80,9 +110,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<p>
<label id="types_label"></label><br />
<input type="text" id="types" value="" name="types" class="form-control" />
<br />
</p>
<br />
<p>
<label id="logLimit_label"></label><br />
<input type="number" id="logLimit" value="" name="logLimit" class="form-control" min="-1">
</p>
<br />
<p>
<label id="context_menu_enabled" style="font-weight: bold;"></label><br />
<label class="switch">
<input type="checkbox" id="contextMenuEnabled">
@ -106,6 +141,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
</label>
</p>
<br />
<p>
<label id="referral_marketing_enabled" style="font-weight: bold;"></label><br />
<label class="switch">
<input type="checkbox" id="referralMarketing">
<span class="slider round"></span>
</label>
</p>
<br />
<p class="text-center">
<button type="button" id="save_settings_btn"
class="btn btn-success" title="Save the settings"></button>

View File

@ -20,7 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<!DOCTYPE html>
<html lang="en">
<head>
<title>This site or element was blocked by ClearURLs Add-on</title>
<title>This site was blocked by ClearURLs Add-on</title>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
@ -53,12 +53,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<div class="container content">
<div class="row">
<div class="col-sm-10 col-sm-offset-1">
<h1 class="text-center">This site or element was blocked by <b>ClearURLs</b> Add-on</h1>
<h1 class="text-center" id="title"></h1>
<p class="text-center" id="body"></p>
<p class="text-center">
This site or element was blocked by <b>ClearURLs</b> Add-on, because we identify this site as an
advertising and/or tracking service.
<br>
To visit this site, you must temporarily deactivate the Add-on.
<a class="btn btn-warning" id="page"></a>
</p>
</div>
</div>
@ -66,13 +64,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<footer class="navbar-fixed-bottom">
<div class="navbar-inverse text-center">
<small class="text-muted">Version 1.1.2.5</small>
<small class="text-muted">v.<span id="version"></span></small>
</div>
</footer>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="../browser-polyfill.js"></script>
<script src="../external_js/jquery-3.2.1.min.js"></script>
<script src="../external_js/bootstrap.min.js"></script>
<script src="../core_js/siteBlockedAlert.js"></script>
<script src="../core_js/write_version.js"></script>
</body>
</html>

View File

@ -1,7 +1,7 @@
{
"manifest_version": 2,
"name": "ClearURLs",
"version": "1.8.5",
"version": "1.9.0",
"author": "Kevin Röbert",
"description": "Remove tracking elements from URLs.",
"homepage_url": "https://gitlab.com/KevinRoebert/ClearUrls",
@ -52,7 +52,8 @@
"contextMenus",
"clipboardWrite",
"webNavigation",
"tabs"
"tabs",
"downloads"
],
"background": {
"scripts": [
@ -60,13 +61,14 @@
"external_js/jquery-3.2.1.min.js",
"external_js/sha256.jquery.js",
"core_js/message_handler.js",
"external_js/ip-range-check.js",
"core_js/tools.js",
"core_js/storage.js",
"clearurls.js",
"core_js/pureCleaning.js",
"core_js/context_menu.js",
"core_js/historyListener.js",
"external_js/ip-range-check.js"
"clearurls.js",
"core_js/storage.js",
"core_js/watchdog.js"
]
},
"content_scripts": [