From b2a8ea7fee9a319d102b3138a8d8b73c57cfcd3a Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sat, 22 Apr 2017 01:44:26 +0200 Subject: [PATCH 01/71] Add first version of Audit log --- api_FTL.php | 6 ++- auditlog.php | 78 ++++++++++++++++++++++++++++ scripts/pi-hole/js/auditlog.js | 94 ++++++++++++++++++++++++++++++++++ scripts/pi-hole/php/header.php | 8 ++- 4 files changed, 184 insertions(+), 2 deletions(-) create mode 100644 auditlog.php create mode 100644 scripts/pi-hole/js/auditlog.js diff --git a/api_FTL.php b/api_FTL.php index 0e0a2637..c367d153 100644 --- a/api_FTL.php +++ b/api_FTL.php @@ -71,7 +71,11 @@ if (isset($_GET['overTimeData10mins'])) if (isset($_GET['topItems']) && $auth) { - if(is_numeric($_GET['topItems'])) + if($_GET['topItems'] === "audit") + { + sendRequestFTL("top-domains for audit"); + } + else if(is_numeric($_GET['topItems'])) { sendRequestFTL("top-domains (".$_GET['topItems'].")"); } diff --git a/auditlog.php b/auditlog.php new file mode 100644 index 00000000..d0ae4c44 --- /dev/null +++ b/auditlog.php @@ -0,0 +1,78 @@ + + + + + + +
+
+
+
+

Allowed queries

+
+ +
+
+ + + + + + + + +
DomainHitsAction
+
+
+
+ +
+ +
+ +
+ +
+
+
+

Blocked queries

+
+ +
+
+ + + + + + + + +
DomainHitsAction
+
+
+
+ +
+ +
+ +
+ +
+ + + + diff --git a/scripts/pi-hole/js/auditlog.js b/scripts/pi-hole/js/auditlog.js new file mode 100644 index 00000000..3cd2c680 --- /dev/null +++ b/scripts/pi-hole/js/auditlog.js @@ -0,0 +1,94 @@ +/* Pi-hole: A black hole for Internet advertisements +* (c) 2017 Pi-hole, LLC (https://pi-hole.net) +* Network-wide ad blocking via your own hardware. +* +* This file is copyright under the latest version of the EUPL. +* Please see LICENSE file for your rights under this license. */ +// Define global variables +var timeLineChart, queryTypeChart, forwardDestinationChart; + +function padNumber(num) { + return ("00" + num).substr(-2,2); +} + +// Helper function needed for converting the Objects to Arrays + +function objectToArray(p){ + var keys = Object.keys(p); + keys.sort(function(a, b) { + return a - b; + }); + + var arr = [], idx = []; + for (var i = 0; i < keys.length; i++) { + arr.push(p[keys[i]]); + idx.push(keys[i]); + } + return [idx,arr]; +} + +// Functions to update data in page + +var failures = 0; + +// Credit: http://stackoverflow.com/questions/1787322/htmlspecialchars-equivalent-in-javascript/4835406#4835406 +function escapeHtml(text) { + var map = { + "&": "&", + "<": "<", + ">": ">", + "\"": """, + "\'": "'" + }; + + return text.replace(/[&<>"']/g, function(m) { return map[m]; }); +} + +function updateTopLists() { + $.getJSON("api.php?topItems=audit", function(data) { + + if("FTLnotrunning" in data) + { + return; + } + + // Clear tables before filling them with data + $("#domain-frequency td").parent().remove(); + $("#ad-frequency td").parent().remove(); + var domaintable = $("#domain-frequency").find("tbody:last"); + var adtable = $("#ad-frequency").find("tbody:last"); + var url, domain, percentage; + for (domain in data.top_queries) { + if ({}.hasOwnProperty.call(data.top_queries,domain)){ + // Sanitize domain + domain = escapeHtml(domain); + url = ""+domain+""; + percentage = data.top_queries[domain] / data.dns_queries_today * 100; + domaintable.append(" " + url + + " " + data.top_queries[domain] + " Buttons ... "); + } + } + + for (domain in data.top_ads) { + if ({}.hasOwnProperty.call(data.top_ads,domain)){ + // Sanitize domain + domain = escapeHtml(domain); + url = ""+domain+""; + percentage = data.top_ads[domain] / data.ads_blocked_today * 100; + adtable.append(" " + url + + " " + data.top_ads[domain] + " Buttons ... "); + } + } + + $("#domain-frequency .overlay").hide(); + $("#ad-frequency .overlay").hide(); + // Update top lists data every 10 seconds + setTimeout(updateTopLists, 10000); + }); +} + +$(document).ready(function() { + + // Pull in data via AJAX + updateTopLists(); + }); diff --git a/scripts/pi-hole/php/header.php b/scripts/pi-hole/php/header.php index 0c49b724..594a5be1 100644 --- a/scripts/pi-hole/php/header.php +++ b/scripts/pi-hole/php/header.php @@ -459,7 +459,7 @@ if($auth) { Enable    -
  • active"> +
  • active"> Tools @@ -479,6 +479,12 @@ if($auth) { Query adlists
  • + + class="active"> + + Audit log + + class="active"> From 349faac0482dbe569ff09b8727963c2026b83c7f Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sat, 22 Apr 2017 16:09:56 +0200 Subject: [PATCH 02/71] Implemented also actions for audit log --- api_FTL.php | 11 ++++- auditlog.php | 9 ++-- scripts/pi-hole/js/auditlog.js | 80 ++++++++++++++++++++-------------- scripts/pi-hole/php/add.php | 26 +++++++++-- 4 files changed, 86 insertions(+), 40 deletions(-) diff --git a/api_FTL.php b/api_FTL.php index c367d153..04988f28 100644 --- a/api_FTL.php +++ b/api_FTL.php @@ -92,7 +92,11 @@ if (isset($_GET['topItems']) && $auth) $top_queries[$tmp[2]] = intval($tmp[1]); } - if(is_numeric($_GET['topItems'])) + if($_GET['topItems'] === "audit") + { + sendRequestFTL("top-ads for audit"); + } + else if(is_numeric($_GET['topItems'])) { sendRequestFTL("top-ads (".$_GET['topItems'].")"); } @@ -106,7 +110,10 @@ if (isset($_GET['topItems']) && $auth) foreach($return as $line) { $tmp = explode(" ",$line); - $top_ads[$tmp[2]] = intval($tmp[1]); + if(count($tmp) === 4) + $top_ads[$tmp[2]." (".$tmp[3].")"] = intval($tmp[1]); + else + $top_ads[$tmp[2]] = intval($tmp[1]); } $result = array('top_queries' => $top_queries, diff --git a/auditlog.php b/auditlog.php index d0ae4c44..96d74577 100644 --- a/auditlog.php +++ b/auditlog.php @@ -11,7 +11,7 @@
    @@ -28,7 +28,7 @@ Domain Hits - Action + Actions @@ -55,7 +55,7 @@ Domain Hits - Action + Actions @@ -68,6 +68,9 @@
    +
    diff --git a/scripts/pi-hole/js/auditlog.js b/scripts/pi-hole/js/auditlog.js index 3cd2c680..85aee673 100644 --- a/scripts/pi-hole/js/auditlog.js +++ b/scripts/pi-hole/js/auditlog.js @@ -7,30 +7,6 @@ // Define global variables var timeLineChart, queryTypeChart, forwardDestinationChart; -function padNumber(num) { - return ("00" + num).substr(-2,2); -} - -// Helper function needed for converting the Objects to Arrays - -function objectToArray(p){ - var keys = Object.keys(p); - keys.sort(function(a, b) { - return a - b; - }); - - var arr = [], idx = []; - for (var i = 0; i < keys.length; i++) { - arr.push(p[keys[i]]); - idx.push(keys[i]); - } - return [idx,arr]; -} - -// Functions to update data in page - -var failures = 0; - // Credit: http://stackoverflow.com/questions/1787322/htmlspecialchars-equivalent-in-javascript/4835406#4835406 function escapeHtml(text) { var map = { @@ -65,18 +41,29 @@ function updateTopLists() { url = ""+domain+""; percentage = data.top_queries[domain] / data.dns_queries_today * 100; domaintable.append(" " + url + - " " + data.top_queries[domain] + " Buttons ... "); + " " + data.top_queries[domain] + " "); } } for (domain in data.top_ads) { if ({}.hasOwnProperty.call(data.top_ads,domain)){ // Sanitize domain - domain = escapeHtml(domain); - url = ""+domain+""; - percentage = data.top_ads[domain] / data.ads_blocked_today * 100; - adtable.append(" " + url + - " " + data.top_ads[domain] + " Buttons ... "); + console.log(domain); + console.log(); + var input = domain.split(" "); + var printdomain = escapeHtml(input[0]); + if(input.length > 1) + { + url = ""+printdomain+" (wildcard blocked)"; + adtable.append(" " + url + + " " + data.top_ads[domain] + " "); + } + else + { + url = ""+printdomain+""; + adtable.append(" " + url + + " " + data.top_ads[domain] + " "); + } } } @@ -87,8 +74,37 @@ function updateTopLists() { }); } + +function add(domain,list) { + var token = $("#token").html(); + $.ajax({ + url: "scripts/pi-hole/php/add.php", + method: "post", + data: {"domain":domain, "list":list, "token":token, "auditlog":1}, + success: function(response) { + setTimeout(updateTopLists, 300); + } + }); +} + $(document).ready(function() { - // Pull in data via AJAX - updateTopLists(); + // Pull in data via AJAX + updateTopLists(); + + $("#domain-frequency tbody").on( "click", "button", function () { + var url = ($(this).parents("tr"))[0].innerText.split(" ")[0]; + if($(this).context.innerText === "Blacklist") + add(url,"black"); + else + add(url,"audit"); }); + + $("#ad-frequency tbody").on( "click", "button", function () { + var url = ($(this).parents("tr"))[0].innerText.split(" ")[0].split(" ")[0]; + if($(this).context.innerText === "Whitelist") + add(url,"white"); + else + add(url,"audit"); + }); +}); diff --git a/scripts/pi-hole/php/add.php b/scripts/pi-hole/php/add.php index d4ca64db..a19aae7a 100644 --- a/scripts/pi-hole/php/add.php +++ b/scripts/pi-hole/php/add.php @@ -16,13 +16,33 @@ list_verify($type); switch($type) { case "white": - echo exec("sudo pihole -w -q ${_POST['domain']}"); + if(!isset($_POST["auditlog"])) + echo exec("sudo pihole -w -q ${_POST['domain']}"); + else + { + echo exec("sudo pihole -w -q -n ${_POST['domain']}"); + echo exec("sudo pihole -a audit ${_POST['domain']}"); + } break; case "black": - echo exec("sudo pihole -b -q ${_POST['domain']}"); + if(!isset($_POST["auditlog"])) + echo exec("sudo pihole -b -q ${_POST['domain']}"); + else + { + echo exec("sudo pihole -b -q -n ${_POST['domain']}"); + echo exec("sudo pihole -a audit ${_POST['domain']}"); + } break; case "wild": - echo exec("sudo pihole -wild -q ${_POST['domain']}"); + if(!isset($_POST["auditlog"])) + echo exec("sudo pihole -wild -q ${_POST['domain']}"); + else + { + echo exec("sudo pihole -wild -q -n ${_POST['domain']}"); + echo exec("sudo pihole -a audit ${_POST['domain']}"); + } + case "audit": + echo exec("sudo pihole -a audit ${_POST['domain']}"); break; } From 870959026b7a605fcc94e646f95d6d782f32ed02 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sat, 22 Apr 2017 16:19:19 +0200 Subject: [PATCH 03/71] Codacy fixes --- scripts/pi-hole/js/auditlog.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/scripts/pi-hole/js/auditlog.js b/scripts/pi-hole/js/auditlog.js index 85aee673..db904b91 100644 --- a/scripts/pi-hole/js/auditlog.js +++ b/scripts/pi-hole/js/auditlog.js @@ -47,10 +47,8 @@ function updateTopLists() { for (domain in data.top_ads) { if ({}.hasOwnProperty.call(data.top_ads,domain)){ - // Sanitize domain - console.log(domain); - console.log(); var input = domain.split(" "); + // Sanitize domain var printdomain = escapeHtml(input[0]); if(input.length > 1) { @@ -95,16 +93,24 @@ $(document).ready(function() { $("#domain-frequency tbody").on( "click", "button", function () { var url = ($(this).parents("tr"))[0].innerText.split(" ")[0]; if($(this).context.innerText === "Blacklist") + { add(url,"black"); + } else + { add(url,"audit"); + } }); $("#ad-frequency tbody").on( "click", "button", function () { var url = ($(this).parents("tr"))[0].innerText.split(" ")[0].split(" ")[0]; if($(this).context.innerText === "Whitelist") - add(url,"white"); + { + add(url,"white"); + } else + { add(url,"audit"); + } }); }); From 8fa40923beb7e72d3c878648d9e19dfed4c412b4 Mon Sep 17 00:00:00 2001 From: Mcat12 Date: Mon, 1 May 2017 20:02:09 -0400 Subject: [PATCH 04/71] Escape tail output Fixes #486 --- scripts/pi-hole/php/tailLog.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/pi-hole/php/tailLog.php b/scripts/pi-hole/php/tailLog.php index bf23941a..ce572f01 100644 --- a/scripts/pi-hole/php/tailLog.php +++ b/scripts/pi-hole/php/tailLog.php @@ -30,7 +30,7 @@ if(isset($_GET["offset"])) fseek($file, $offset); $lines = []; while (!feof($file)) - array_push($lines,fgets($file)); + array_push($lines, htmlspecialchars(fgets($file))); die(json_encode(array("offset" => ftell($file), "lines" => $lines))); } } From 8e26274a3e8eb33b661d1cc5c836671190eec48d Mon Sep 17 00:00:00 2001 From: WaLLy3K Date: Wed, 3 May 2017 20:54:00 +1000 Subject: [PATCH 05/71] Change wording for "Queries over Time" As suggested per https://redd.it/68ziwx --- index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.php b/index.php index 470c5180..a40d5713 100644 --- a/index.php +++ b/index.php @@ -68,7 +68,7 @@
    -

    Queries over Time

    +

    Queries over last 24 hours

    From 2db45f806bc91d1c8ded394cdf198f0620907226 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Fri, 5 May 2017 23:29:25 +0200 Subject: [PATCH 06/71] Remove double click handler --- scripts/pi-hole/js/gravity.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/scripts/pi-hole/js/gravity.js b/scripts/pi-hole/js/gravity.js index 84b26b73..7ba64775 100644 --- a/scripts/pi-hole/js/gravity.js +++ b/scripts/pi-hole/js/gravity.js @@ -45,11 +45,6 @@ $("#gravityBtn").on("click", function(){ eventsource(); }); -$("#gravityBtn").on("click", () => { - $("#gravityBtn").attr("disabled", true); - eventsource(); -}); - // Handle hiding of alerts $(function(){ $("[data-hide]").on("click", function(){ From 2db905a9da49fa7389f999843e7f9672ccb15f8d Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Fri, 5 May 2017 22:50:03 +0100 Subject: [PATCH 07/71] ~Today~ Over Last 24 Hours --- index.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/index.php b/index.php index a40d5713..2cb4d3b0 100644 --- a/index.php +++ b/index.php @@ -15,7 +15,7 @@

    ---

    -

    DNS Queries Blocked Today

    +

    DNS Queries Blocked Over Last 24 Hours

    @@ -28,7 +28,7 @@

    ---

    -

    DNS Queries Today

    +

    DNS Queries Over Last 24 Hours

    @@ -41,7 +41,7 @@

    ---

    -

    Of Today's Queries Were Blocked

    +

    Queries Were Blocked Over Last 24 Hours

    From 9cf967eb0b2cdc3422c4fd2281ad07569946b924 Mon Sep 17 00:00:00 2001 From: Mcat12 Date: Tue, 9 May 2017 17:35:46 -0400 Subject: [PATCH 08/71] Rename Top Advertisers to Top Blocked Domains --- index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.php b/index.php index 2cb4d3b0..dd975b78 100644 --- a/index.php +++ b/index.php @@ -164,7 +164,7 @@ else
    -

    Top Advertisers

    +

    Top Blocked Domains

    From f46a1c166ff3cbeff665a3b5e5751be77cf813a0 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 10 May 2017 21:02:02 +0200 Subject: [PATCH 09/71] percentage should be a float instead of an integer --- api_FTL.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api_FTL.php b/api_FTL.php index 0e0a2637..2738e700 100644 --- a/api_FTL.php +++ b/api_FTL.php @@ -45,7 +45,7 @@ if (isset($_GET['summary']) || isset($_GET['summaryRaw']) || !count($_GET)) } else { - $stats[$tmp[0]] = intval($tmp[1]); + $stats[$tmp[0]] = floatval($tmp[1]); } } $data = array_merge($data,$stats); From 915ec26547bc4e4793d2371ca18f5ea36ce982dc Mon Sep 17 00:00:00 2001 From: DL6ER Date: Fri, 12 May 2017 18:11:55 +0200 Subject: [PATCH 10/71] Define $over_time as array. Fixes #501 --- api_FTL.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api_FTL.php b/api_FTL.php index 2738e700..bed84b5d 100644 --- a/api_FTL.php +++ b/api_FTL.php @@ -233,6 +233,7 @@ if (isset($_GET['overTimeDataForwards']) && $auth) { sendRequestFTL("ForwardedoverTime"); $return = getResponseFTL(); + $over_time = array(); foreach($return as $line) { @@ -271,6 +272,7 @@ if (isset($_GET['overTimeDataQueryTypes']) && $auth) { sendRequestFTL("QueryTypesoverTime"); $return = getResponseFTL(); + $over_time = array(); foreach($return as $line) { From b49a7b57c531ab95a835446229ec38bf43dd767d Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sat, 13 May 2017 17:20:18 +0200 Subject: [PATCH 11/71] Add hover/hit radius for Forward Destinations over Time graph --- scripts/pi-hole/js/index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/pi-hole/js/index.js b/scripts/pi-hole/js/index.js index 6aabe866..0bb3c02d 100644 --- a/scripts/pi-hole/js/index.js +++ b/scripts/pi-hole/js/index.js @@ -186,11 +186,13 @@ function updateForwardedOverTime() { // Collect values and colors, and labels forwardDestinationChart.data.datasets[0].backgroundColor = colors[0]; forwardDestinationChart.data.datasets[0].pointRadius = 0; + forwardDestinationChart.data.datasets[0].pointHitRadius = 5; + forwardDestinationChart.data.datasets[0].pointHoverRadius = 5; forwardDestinationChart.data.datasets[0].label = labels[0]; for (i = forwardDestinationChart.data.datasets.length; i < plotdata[0].length; i++) { - forwardDestinationChart.data.datasets.push({data: [], backgroundColor: colors[i], pointRadius: 0, label: labels[i]}); + forwardDestinationChart.data.datasets.push({data: [], backgroundColor: colors[i], pointRadius: 0, pointHitRadius: 5, pointHoverRadius: 5, label: labels[i]}); } // Add data for each dataset that is available From 7d4bf08853a49d518c2e3a3c067a9b24707c5313 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sat, 13 May 2017 17:32:00 +0200 Subject: [PATCH 12/71] Add custom callback for tooltips and disable legend for Forward Destinations over Time graph --- scripts/pi-hole/js/index.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/scripts/pi-hole/js/index.js b/scripts/pi-hole/js/index.js index 0bb3c02d..8545fa3f 100644 --- a/scripts/pi-hole/js/index.js +++ b/scripts/pi-hole/js/index.js @@ -548,6 +548,27 @@ $(document).ready(function() { datasets: [{ data: [] }] }, options: { + tooltips: { + enabled: true, + mode: "x-axis", + callbacks: { + title: function(tooltipItem, data) { + var label = tooltipItem[0].xLabel; + var time = label.match(/(\d?\d):?(\d?\d?)/); + var h = parseInt(time[1], 10); + var m = parseInt(time[2], 10) || 0; + var from = padNumber(h)+":"+padNumber(m-5)+":00"; + var to = padNumber(h)+":"+padNumber(m+4)+":59"; + return "Forward destinations from "+from+" to "+to; + }, + label: function(tooltipItems, data) { + return data.datasets[tooltipItems.datasetIndex].label + ": " + (100.0*tooltipItems.yLabel).toFixed(1) + "%"; + } + } + }, + legend: { + display: false + }, scales: { xAxes: [{ type: "time", From e659d79da974c57ac872061ea2d05f85b6264b9a Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sat, 13 May 2017 17:34:36 +0200 Subject: [PATCH 13/71] Remove legend, add tooltips and increase hit/hover radius for Query Types over Time graph. Fixes #502 --- scripts/pi-hole/js/index.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/scripts/pi-hole/js/index.js b/scripts/pi-hole/js/index.js index 8545fa3f..ad641238 100644 --- a/scripts/pi-hole/js/index.js +++ b/scripts/pi-hole/js/index.js @@ -612,16 +612,41 @@ $(document).ready(function() { { label: "A: IPv4 queries", pointRadius: 0, + pointHitRadius: 5, + pointHoverRadius: 5, data: [] }, { label: "AAAA: IPv6 queries", pointRadius: 0, + pointHitRadius: 5, + pointHoverRadius: 5, data: [] } ] }, options: { + tooltips: { + enabled: true, + mode: "x-axis", + callbacks: { + title: function(tooltipItem, data) { + var label = tooltipItem[0].xLabel; + var time = label.match(/(\d?\d):?(\d?\d?)/); + var h = parseInt(time[1], 10); + var m = parseInt(time[2], 10) || 0; + var from = padNumber(h)+":"+padNumber(m-5)+":00"; + var to = padNumber(h)+":"+padNumber(m+4)+":59"; + return "Query types from "+from+" to "+to; + }, + label: function(tooltipItems, data) { + return data.datasets[tooltipItems.datasetIndex].label + ": " + (100.0*tooltipItems.yLabel).toFixed(1) + "%"; + } + } + }, + legend: { + display: false + }, scales: { xAxes: [{ type: "time", From 62f2f1939bdb3c8fe2551e723ee645d9c41dbcc8 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sat, 13 May 2017 17:44:06 +0200 Subject: [PATCH 14/71] Don't hide detailed graphs on small screens any longer --- index.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.php b/index.php index dd975b78..61f590ca 100644 --- a/index.php +++ b/index.php @@ -89,7 +89,7 @@ // a password if($auth){ ?>
    -