From 6f64682067b374430afca8adf63d31f4cb57ccd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kevin=20R=C3=B6bert?= Date: Sat, 18 Nov 2017 01:34:01 +0100 Subject: [PATCH] Version 1.1.2.5 + Add log feature + Add user request #9 --- clearurls.js | 231 ++++++++++++++++--- data/rules.hash | 1 + dataTables.bootstrap.min.css | 1 + dataTables.bootstrap.min.js | 8 + fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 45404 bytes fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23424 bytes fonts/glyphicons-halflings-regular.woff2 | Bin 0 -> 18028 bytes jquery.dataTables.min.js | 164 +++++++++++++ log.html | 79 +++++++ log.js | 64 ++++++ manifest.json | 7 +- popup_new.html | 129 ++++++----- popup_new.js | 280 ++++++++++++++--------- sha256.jquery.js | 247 ++++++++++++++++++++ 14 files changed, 1008 insertions(+), 203 deletions(-) create mode 100644 data/rules.hash create mode 100644 dataTables.bootstrap.min.css create mode 100644 dataTables.bootstrap.min.js create mode 100644 fonts/glyphicons-halflings-regular.ttf create mode 100644 fonts/glyphicons-halflings-regular.woff create mode 100644 fonts/glyphicons-halflings-regular.woff2 create mode 100644 jquery.dataTables.min.js create mode 100644 log.html create mode 100644 log.js create mode 100644 sha256.jquery.js diff --git a/clearurls.js b/clearurls.js index f75cefe..f201043 100644 --- a/clearurls.js +++ b/clearurls.js @@ -8,11 +8,16 @@ var providers = []; var prvKeys = []; var globalStatus; var badges = []; +var log = []; +var logging = false; var badgedStatus; var tabid = 0; var globalCounter; var globalurlcounter; -var siteBlockedAlert = browser.extension.getURL ('./siteBlockedAlert.html'); +var siteBlockedAlert = browser.extension.getURL('./siteBlockedAlert.html'); +var dataHash; +var localDataHash; + /** * Initialize the JSON provider object keys. @@ -74,44 +79,102 @@ function toJSON(retrievedText) { /** * Load local saved data, if the browser is offline or * some other network trouble. -* */ function loadOldDataFromStore() { - browser.storage.local.get('ClearURLsData', function(data){ - if(data.ClearURLsData){ - data = data.ClearURLsData; + browser.storage.local.get('ClearURLsData', function(localData){ + if(localData.ClearURLsData){ + data = localData.ClearURLsData; } else { data = ""; } - toJSON(data); + localDataHash = $.sha256(data); + }); } /** -* Fetch the Rules & Exception github. -* + * Save the hash status to the local storage. + * The status can have the following values: + * 1 "unchanged" + * 2 "authorized, changed" + * 3 "unauthorized, changed" + * @param status_code the number for the status + */ +function storeHashStatus(status_code) +{ + switch(status_code) + { + case 1: status_code = "unchanged"; + break; + case 2: status_code = "authorized, changed"; + break; + case 3: status_code = "unauthorized, changed"; + break; + default: status_code = "error"; + } + browser.storage.local.set({"hashStatus": status_code}); +} + +/** + * Get the hash for the rule file on github. + * Check the hash with the hash form the local file. + * If the hash has changed, then download the new rule file. + * Else do nothing. + */ +function getHash() +{ + //Get the target hash from github + fetch("https://raw.githubusercontent.com/KevinRoebert/ClearUrls/master/data/rules.hash?flush_cache=true") + .then(function(response){ + var responseTextHash = response.clone().text().then(function(responseTextHash){ + if(response.ok) + { + dataHash = responseTextHash; + + if($.trim(dataHash) !== $.trim(localDataHash)) + { + fetchFromURL(); + } + else { + toJSON(data); + storeHashStatus(1); + } + } + else { + dataHash = false; + } + }); + }); +} + +/** +* Fetch the Rules & Exception from github. */ function fetchFromURL() { fetch("https://raw.githubusercontent.com/KevinRoebert/ClearUrls/master/data/data.json?flush_cache=true") - .then(checkResponse) - .catch(function(error){ - loadOldDataFromStore(); - }); + .then(checkResponse); function checkResponse(response) { var responseText = response.clone().text().then(function(responseText){ if(response.ok) { - browser.storage.local.set({"ClearURLsData": responseText}); - toJSON(responseText); - } - else { - loadOldDataFromStore(); + var downloadedFileHash = $.sha256(responseText); + + if($.trim(downloadedFileHash) === $.trim(dataHash)) + { + data = responseText; + browser.storage.local.set({"ClearURLsData": responseText}); + storeHashStatus(2); + } + else { + storeHashStatus(3); + } + toJSON(data); } }); } @@ -269,13 +332,15 @@ function removeFieldsFormURL(provider, request) if(provider.matchURL(url)) { /* - * Expand the url by provider redirections. So no tracking on - * url redirections form sites to sites. - */ + * Expand the url by provider redirections. So no tracking on + * url redirections form sites to sites. + */ var re = provider.getRedirection(url); if(re !== null) { url = decodeURIComponent(re); + //Log the action + pushToLog(request.url, re, "This url is redirected."); return { "redirect": true, @@ -284,12 +349,15 @@ function removeFieldsFormURL(provider, request) } for (var i = 0; i < rules.length; i++) { - var bevorReplace = url; + var beforReplace = url; url = url.replace(new RegExp(rules[i], "gi"), ""); - if(bevorReplace != url) + if(beforReplace != url) { + //Log the action + pushToLog(beforReplace, url, rules[i]); + if(badges[tabid] == null) { badges[tabid] = 0; @@ -309,6 +377,7 @@ function removeFieldsFormURL(provider, request) } if(provider.isCaneling()){ + pushToLog(request.url, request.url, "This domain is blocked."); if(badges[tabid] == null) { badges[tabid] = 0; @@ -423,9 +492,9 @@ function clearUrl(request) result = removeFieldsFormURL(providers[i], request); /* - * Expand urls and bypass tracking. - * Cancel the active request. - */ + * Expand urls and bypass tracking. + * Cancel the active request. + */ if(result.redirect) { browser.tabs.update(request.tabId, {url: result.url}); @@ -456,6 +525,100 @@ function clearUrl(request) } } +/** +* This function get the log on start and load the +* json data in to the log variable. +* If no log in the local storage, this function +* create a foundation json variable. +*/ +function getLogOnStart() +{ + browser.storage.local.get('log', function(data) { + if(data.log) + { + log = JSON.parse(data.log); + } + else{ + //Create foundation for log variable + log = {"log": []}; + } + }); +} + +/** +* Function to log all activities from ClearUrls. +* Only logging when activated. +* The log is only temporary saved in the cache and will +* permanently saved with the saveLogOnClose function. +* +* @param beforeProcessing the url before the clear process +* @param afterProcessing the url after the clear process +* @param rule the rule that triggered the process +*/ +function pushToLog(beforeProcessing, afterProcessing, rule) +{ + if(logging) + { + log.log.push( + { + "before": beforeProcessing, + "after": afterProcessing, + "rule": rule, + "timestamp": Date.now() + } + ); + } +} + +/** +* This function is triggered by the event windows.onRemoved and tabs.onCreated +* and will save the log permanently to the local storage. +* We only save the log anticyclically based on performance. +*/ +function saveLog() +{ + if(logging) + { + browser.storage.local.get('resetLog', function(data) { + if(data.resetLog) + { + log = {"log": []}; // Delete the old log + browser.storage.local.set({"resetLog": false}); + } + else + { + browser.storage.local.set({"log": JSON.stringify(log)}); + } + }); + } +} + +/** +* Check if the status from logging has changed. +* +* The default value is false (off). +*/ +function getLoggingStatus() +{ + browser.storage.local.get('loggingStatus', function(data) { + if(data.loggingStatus) { + logging = data.loggingStatus; + } + else if(data.loggingStatus === null || typeof(data.loggingStatus) == "undefined"){ + logging = false; + } + else { + logging = false; + } + }); +} + +/** +* Call by each windows is closed or created. +*/ +browser.windows.onRemoved.addListener(saveLog); +browser.tabs.onCreated.addListener(saveLog); + /** * Call by each tab is closed. */ @@ -463,6 +626,15 @@ function handleRemoved(tabId, removeInfo) { delete badges[tabId]; } +/** +* Function that calls some function on storage change. +*/ +function reactToStorageChange() +{ + setBadgedStatus(); + getLoggingStatus(); +} + /** * Get the badged status from the browser storage and put the value * into a local variable. @@ -486,15 +658,18 @@ function setBadgedStatus() { } /** -* Call the fetch, counter and status functions +* Call loadOldDataFromStore, getHash, counter, status and log functions */ -fetchFromURL(); + +loadOldDataFromStore(); +getHash(); setBadgedStatus(); +getLogOnStart(); /** * Call by each change in the browser storage. */ -browser.storage.onChanged.addListener(setBadgedStatus); +browser.storage.onChanged.addListener(reactToStorageChange); /** * Call by each tab is closed. diff --git a/data/rules.hash b/data/rules.hash new file mode 100644 index 0000000..3a1b6fe --- /dev/null +++ b/data/rules.hash @@ -0,0 +1 @@ +863046278544f80968b1d4f2c49b5f30f442044eac6b7ec34625bf8cafbd8d56 \ No newline at end of file diff --git a/dataTables.bootstrap.min.css b/dataTables.bootstrap.min.css new file mode 100644 index 0000000..af6ecfe --- /dev/null +++ b/dataTables.bootstrap.min.css @@ -0,0 +1 @@ +table.dataTable{clear:both;margin-top:6px !important;margin-bottom:6px !important;max-width:none !important;border-collapse:separate !important}table.dataTable td,table.dataTable th{-webkit-box-sizing:content-box;box-sizing:content-box}table.dataTable td.dataTables_empty,table.dataTable th.dataTables_empty{text-align:center}table.dataTable.nowrap th,table.dataTable.nowrap td{white-space:nowrap}div.dataTables_wrapper div.dataTables_length label{font-weight:normal;text-align:left;white-space:nowrap}div.dataTables_wrapper div.dataTables_length select{width:75px;display:inline-block}div.dataTables_wrapper div.dataTables_filter{text-align:right}div.dataTables_wrapper div.dataTables_filter label{font-weight:normal;white-space:nowrap;text-align:left}div.dataTables_wrapper div.dataTables_filter input{margin-left:0.5em;display:inline-block;width:auto}div.dataTables_wrapper div.dataTables_info{padding-top:8px;white-space:nowrap}div.dataTables_wrapper div.dataTables_paginate{margin:0;white-space:nowrap;text-align:right}div.dataTables_wrapper div.dataTables_paginate ul.pagination{margin:2px 0;white-space:nowrap}div.dataTables_wrapper div.dataTables_processing{position:absolute;top:50%;left:50%;width:200px;margin-left:-100px;margin-top:-26px;text-align:center;padding:1em 0}table.dataTable thead>tr>th.sorting_asc,table.dataTable thead>tr>th.sorting_desc,table.dataTable thead>tr>th.sorting,table.dataTable thead>tr>td.sorting_asc,table.dataTable thead>tr>td.sorting_desc,table.dataTable thead>tr>td.sorting{padding-right:30px}table.dataTable thead>tr>th:active,table.dataTable thead>tr>td:active{outline:none}table.dataTable thead .sorting,table.dataTable thead .sorting_asc,table.dataTable thead .sorting_desc,table.dataTable thead .sorting_asc_disabled,table.dataTable thead .sorting_desc_disabled{cursor:pointer;position:relative}table.dataTable thead .sorting:after,table.dataTable thead .sorting_asc:after,table.dataTable thead .sorting_desc:after,table.dataTable thead .sorting_asc_disabled:after,table.dataTable thead .sorting_desc_disabled:after{position:absolute;bottom:8px;right:8px;display:block;font-family:'Glyphicons Halflings';opacity:0.5}table.dataTable thead .sorting:after{opacity:0.2;content:"\e150"}table.dataTable thead .sorting_asc:after{content:"\e155"}table.dataTable thead .sorting_desc:after{content:"\e156"}table.dataTable thead .sorting_asc_disabled:after,table.dataTable thead .sorting_desc_disabled:after{color:#eee}div.dataTables_scrollHead table.dataTable{margin-bottom:0 !important}div.dataTables_scrollBody>table{border-top:none;margin-top:0 !important;margin-bottom:0 !important}div.dataTables_scrollBody>table>thead .sorting:after,div.dataTables_scrollBody>table>thead .sorting_asc:after,div.dataTables_scrollBody>table>thead .sorting_desc:after{display:none}div.dataTables_scrollBody>table>tbody>tr:first-child>th,div.dataTables_scrollBody>table>tbody>tr:first-child>td{border-top:none}div.dataTables_scrollFoot>.dataTables_scrollFootInner{box-sizing:content-box}div.dataTables_scrollFoot>.dataTables_scrollFootInner>table{margin-top:0 !important;border-top:none}@media screen and (max-width: 767px){div.dataTables_wrapper div.dataTables_length,div.dataTables_wrapper div.dataTables_filter,div.dataTables_wrapper div.dataTables_info,div.dataTables_wrapper div.dataTables_paginate{text-align:center}}table.dataTable.table-condensed>thead>tr>th{padding-right:20px}table.dataTable.table-condensed .sorting:after,table.dataTable.table-condensed .sorting_asc:after,table.dataTable.table-condensed .sorting_desc:after{top:6px;right:6px}table.table-bordered.dataTable th,table.table-bordered.dataTable td{border-left-width:0}table.table-bordered.dataTable th:last-child,table.table-bordered.dataTable th:last-child,table.table-bordered.dataTable td:last-child,table.table-bordered.dataTable td:last-child{border-right-width:0}table.table-bordered.dataTable tbody th,table.table-bordered.dataTable tbody td{border-bottom-width:0}div.dataTables_scrollHead table.table-bordered{border-bottom-width:0}div.table-responsive>div.dataTables_wrapper>div.row{margin:0}div.table-responsive>div.dataTables_wrapper>div.row>div[class^="col-"]:first-child{padding-left:0}div.table-responsive>div.dataTables_wrapper>div.row>div[class^="col-"]:last-child{padding-right:0} diff --git a/dataTables.bootstrap.min.js b/dataTables.bootstrap.min.js new file mode 100644 index 0000000..98661c6 --- /dev/null +++ b/dataTables.bootstrap.min.js @@ -0,0 +1,8 @@ +/*! + DataTables Bootstrap 3 integration + ©2011-2015 SpryMedia Ltd - datatables.net/license +*/ +(function(b){"function"===typeof define&&define.amd?define(["jquery","datatables.net"],function(a){return b(a,window,document)}):"object"===typeof exports?module.exports=function(a,d){a||(a=window);if(!d||!d.fn.dataTable)d=require("datatables.net")(a,d).$;return b(d,a,a.document)}:b(jQuery,window,document)})(function(b,a,d,m){var f=b.fn.dataTable;b.extend(!0,f.defaults,{dom:"<'row'<'col-sm-6'l><'col-sm-6'f>><'row'<'col-sm-12'tr>><'row'<'col-sm-5'i><'col-sm-7'p>>",renderer:"bootstrap"});b.extend(f.ext.classes, +{sWrapper:"dataTables_wrapper form-inline dt-bootstrap",sFilterInput:"form-control input-sm",sLengthSelect:"form-control input-sm",sProcessing:"dataTables_processing panel panel-default"});f.ext.renderer.pageButton.bootstrap=function(a,h,r,s,j,n){var o=new f.Api(a),t=a.oClasses,k=a.oLanguage.oPaginate,u=a.oLanguage.oAria.paginate||{},e,g,p=0,q=function(d,f){var l,h,i,c,m=function(a){a.preventDefault();!b(a.currentTarget).hasClass("disabled")&&o.page()!=a.data.action&&o.page(a.data.action).draw("page")}; +l=0;for(h=f.length;l",{"class":t.sPageButton+" "+g,id:0===r&&"string"===typeof c?a.sTableId+"_"+c:null}).append(b("",{href:"#", +"aria-controls":a.sTableId,"aria-label":u[c],"data-dt-idx":p,tabindex:a.iTabIndex}).html(e)).appendTo(d),a.oApi._fnBindAction(i,{action:c},m),p++)}},i;try{i=b(h).find(d.activeElement).data("dt-idx")}catch(v){}q(b(h).empty().html('