diff --git a/api_db.php b/api_db.php
index e624296c..21f1106d 100644
--- a/api_db.php
+++ b/api_db.php
@@ -12,6 +12,9 @@ require("scripts/pi-hole/php/password.php");
require("scripts/pi-hole/php/auth.php");
check_cors();
+// Set maximum execution time to 10 minutes
+ini_set("max_execution_time","600");
+
$data = array();
// Get posible non-standard location of FTL's database
@@ -62,20 +65,20 @@ if(!$db)
if (isset($_GET['getAllQueries']) && $auth)
{
- if($_GET['getAllQueries'] === "empty")
- {
- $allQueries = array();
- }
- else
+ $allQueries = array();
+ if($_GET['getAllQueries'] !== "empty")
{
$from = intval($_GET["from"]);
$until = intval($_GET["until"]);
- $results = $db->query('SELECT timestamp,type,domain,client,status FROM queries WHERE timestamp >= '.$from.' AND timestamp <= '.$until.' ORDER BY timestamp ASC');
- $allQueries = array();
- while ($row = $results->fetchArray())
- {
- $allQueries[] = [$row[0],$row[1] == 1 ? "IPv4" : "IPv6",$row[2],$row[3],$row[4]];
- }
+ $stmt = $db->prepare("SELECT timestamp, type, domain, client, status FROM queries WHERE timestamp >= :from AND timestamp <= :until ORDER BY timestamp ASC");
+ $stmt->bindValue(":from", intval($from), SQLITE3_INTEGER);
+ $stmt->bindValue(":until", intval($until), SQLITE3_INTEGER);
+ $results = $stmt->execute();
+ if(!is_bool($results))
+ while ($row = $results->fetchArray())
+ {
+ $allQueries[] = [$row[0],$row[1] == 1 ? "IPv4" : "IPv6",$row[2],$row[3],$row[4]];
+ }
}
$result = array('data' => $allQueries);
$data = array_merge($data, $result);
@@ -87,23 +90,46 @@ if (isset($_GET['topClients']) && $auth)
$limit = "";
if(isset($_GET["from"]) && isset($_GET["until"]))
{
- $limit = "WHERE timestamp >= ".$_GET["from"]." AND timestamp <= ".$_GET["until"];
+ $limit = "WHERE timestamp >= :from AND timestamp <= :until";
}
elseif(isset($_GET["from"]) && !isset($_GET["until"]))
{
- $limit = "WHERE timestamp >= ".$_GET["from"];
+ $limit = "WHERE timestamp >= :from";
}
elseif(!isset($_GET["from"]) && isset($_GET["until"]))
{
- $limit = "WHERE timestamp <= ".$_GET["until"];
+ $limit = "WHERE timestamp <= :until";
}
- $results = $db->query('SELECT client,count(client) FROM queries '.$limit.' GROUP by client order by count(client) desc limit 10');
+ $stmt = $db->prepare('SELECT client,count(client) FROM queries '.$limit.' GROUP by client order by count(client) desc limit 20');
+ $stmt->bindValue(":from", intval($_GET['from']), SQLITE3_INTEGER);
+ $stmt->bindValue(":until", intval($_GET['until']), SQLITE3_INTEGER);
+ $results = $stmt->execute();
+
$clients = array();
- while ($row = $results->fetchArray())
- {
- $clients[$row[0]] = intval($row[1]);
- // var_dump($row);
- }
+
+ if(!is_bool($results))
+ while ($row = $results->fetchArray())
+ {
+ // Convert client to lower case
+ $c = strtolower($row[0]);
+ if(array_key_exists($c, $clients))
+ {
+ // Entry already exists, add to it (might appear multiple times due to mixed capitalization in the database)
+ $clients[$c] += intval($row[1]);
+ }
+ else
+ {
+ // Entry does not yet exist
+ $clients[$c] = intval($row[1]);
+ }
+ }
+
+ // Sort by number of hits
+ arsort($clients);
+
+ // Extract only the first ten entries
+ $clients = array_slice($clients, 0, 10);
+
$result = array('top_sources' => $clients);
$data = array_merge($data, $result);
}
@@ -114,22 +140,46 @@ if (isset($_GET['topDomains']) && $auth)
if(isset($_GET["from"]) && isset($_GET["until"]))
{
- $limit = " AND timestamp >= ".$_GET["from"]." AND timestamp <= ".$_GET["until"];
+ $limit = " AND timestamp >= :from AND timestamp <= :until";
}
elseif(isset($_GET["from"]) && !isset($_GET["until"]))
{
- $limit = " AND timestamp >= ".$_GET["from"];
+ $limit = " AND timestamp >= :from";
}
elseif(!isset($_GET["from"]) && isset($_GET["until"]))
{
- $limit = " AND timestamp <= ".$_GET["until"];
+ $limit = " AND timestamp <= :until";
}
- $results = $db->query('SELECT domain,count(domain) FROM queries WHERE (STATUS == 2 OR STATUS == 3)'.$limit.' GROUP by domain order by count(domain) desc limit 10');
+ $stmt = $db->prepare('SELECT domain,count(domain) FROM queries WHERE (STATUS == 2 OR STATUS == 3)'.$limit.' GROUP by domain order by count(domain) desc limit 20');
+ $stmt->bindValue(":from", intval($_GET['from']), SQLITE3_INTEGER);
+ $stmt->bindValue(":until", intval($_GET['until']), SQLITE3_INTEGER);
+ $results = $stmt->execute();
+
$domains = array();
- while ($row = $results->fetchArray())
- {
- $domains[$row[0]] = intval($row[1]);
- }
+
+ if(!is_bool($results))
+ while ($row = $results->fetchArray())
+ {
+ // Convert client to lower case
+ $c = strtolower($row[0]);
+ if(array_key_exists($c, $domains))
+ {
+ // Entry already exists, add to it (might appear multiple times due to mixed capitalization in the database)
+ $domains[$c] += intval($row[1]);
+ }
+ else
+ {
+ // Entry does not yet exist
+ $domains[$c] = intval($row[1]);
+ }
+ }
+
+ // Sort by number of hits
+ arsort($domains);
+
+ // Extract only the first ten entries
+ $domains = array_slice($domains, 0, 10);
+
$result = array('top_domains' => $domains);
$data = array_merge($data, $result);
}
@@ -140,22 +190,28 @@ if (isset($_GET['topAds']) && $auth)
if(isset($_GET["from"]) && isset($_GET["until"]))
{
- $limit = " AND timestamp >= ".$_GET["from"]." AND timestamp <= ".$_GET["until"];
+ $limit = " AND timestamp >= :from AND timestamp <= :until";
}
elseif(isset($_GET["from"]) && !isset($_GET["until"]))
{
- $limit = " AND timestamp >= ".$_GET["from"];
+ $limit = " AND timestamp >= :from";
}
elseif(!isset($_GET["from"]) && isset($_GET["until"]))
{
- $limit = " AND timestamp <= ".$_GET["until"];
+ $limit = " AND timestamp <= :until";
}
- $results = $db->query('SELECT domain,count(domain) FROM queries WHERE (STATUS == 1 OR STATUS == 4)'.$limit.' GROUP by domain order by count(domain) desc limit 10');
+ $stmt = $db->prepare('SELECT domain,count(domain) FROM queries WHERE (STATUS == 1 OR STATUS == 4)'.$limit.' GROUP by domain order by count(domain) desc limit 10');
+ $stmt->bindValue(":from", intval($_GET['from']), SQLITE3_INTEGER);
+ $stmt->bindValue(":until", intval($_GET['until']), SQLITE3_INTEGER);
+ $results = $stmt->execute();
+
$addomains = array();
- while ($row = $results->fetchArray())
- {
- $addomains[$row[0]] = intval($row[1]);
- }
+
+ if(!is_bool($results))
+ while ($row = $results->fetchArray())
+ {
+ $addomains[$row[0]] = intval($row[1]);
+ }
$result = array('top_ads' => $addomains);
$data = array_merge($data, $result);
}
@@ -163,21 +219,36 @@ if (isset($_GET['topAds']) && $auth)
if (isset($_GET['getMinTimestamp']) && $auth)
{
$results = $db->query('SELECT MIN(timestamp) FROM queries');
- $result = array('mintimestamp' => $results->fetchArray()[0]);
+
+ if(!is_bool($results))
+ $result = array('mintimestamp' => $results->fetchArray()[0]);
+ else
+ $result = array();
+
$data = array_merge($data, $result);
}
if (isset($_GET['getMaxTimestamp']) && $auth)
{
$results = $db->query('SELECT MAX(timestamp) FROM queries');
- $result = array('maxtimestamp' => $results->fetchArray()[0]);
+
+ if(!is_bool($results))
+ $result = array('maxtimestamp' => $results->fetchArray()[0]);
+ else
+ $result = array();
+
$data = array_merge($data, $result);
}
if (isset($_GET['getQueriesCount']) && $auth)
{
$results = $db->query('SELECT COUNT(timestamp) FROM queries');
- $result = array('count' => $results->fetchArray()[0]);
+
+ if(!is_bool($results))
+ $result = array('count' => $results->fetchArray()[0]);
+ else
+ $result = array();
+
$data = array_merge($data, $result);
}
@@ -194,15 +265,15 @@ if (isset($_GET['getGraphData']) && $auth)
if(isset($_GET["from"]) && isset($_GET["until"]))
{
- $limit = " AND timestamp >= ".intval($_GET["from"])." AND timestamp <= ".intval($_GET["until"]);
+ $limit = " AND timestamp >= :from AND timestamp <= :until";
}
elseif(isset($_GET["from"]) && !isset($_GET["until"]))
{
- $limit = " AND timestamp >= ".intval($_GET["from"]);
+ $limit = " AND timestamp >= :from";
}
elseif(!isset($_GET["from"]) && isset($_GET["until"]))
{
- $limit = " AND timestamp <= ".intval($_GET["until"]);
+ $limit = " AND timestamp <= :until";
}
$interval = 600;
@@ -215,22 +286,36 @@ if (isset($_GET['getGraphData']) && $auth)
}
// Count permitted queries in intervals
- $results = $db->query('SELECT (timestamp/'.$interval.')*'.$interval.' interval, COUNT(*) FROM queries WHERE (status == 2 OR status == 3)'.$limit.' GROUP by interval ORDER by interval');
+ $stmt = $db->prepare('SELECT (timestamp/:interval)*:interval interval, COUNT(*) FROM queries WHERE (status != 0 )'.$limit.' GROUP by interval ORDER by interval');
+ $stmt->bindValue(":from", intval($_GET['from']), SQLITE3_INTEGER);
+ $stmt->bindValue(":until", intval($_GET['until']), SQLITE3_INTEGER);
+ $stmt->bindValue(":interval", $interval, SQLITE3_INTEGER);
+ $results = $stmt->execute();
+
$domains = array();
- while ($row = $results->fetchArray())
- {
- $domains[$row[0]] = intval($row[1]);
- }
+
+ if(!is_bool($results))
+ while ($row = $results->fetchArray())
+ {
+ $domains[$row[0]] = intval($row[1]);
+ }
$result = array('domains_over_time' => $domains);
$data = array_merge($data, $result);
// Count blocked queries in intervals
- $results = $db->query('SELECT (timestamp/'.$interval.')*'.$interval.' interval, COUNT(*) FROM queries WHERE (status == 1 OR status == 4 OR status == 5)'.$limit.' GROUP by interval ORDER by interval');
+ $stmt = $db->prepare('SELECT (timestamp/:interval)*:interval interval, COUNT(*) FROM queries WHERE (status == 1 OR status == 4 OR status == 5)'.$limit.' GROUP by interval ORDER by interval');
+ $stmt->bindValue(":from", intval($_GET['from']), SQLITE3_INTEGER);
+ $stmt->bindValue(":until", intval($_GET['until']), SQLITE3_INTEGER);
+ $stmt->bindValue(":interval", $interval, SQLITE3_INTEGER);
+ $results = $stmt->execute();
+
$addomains = array();
- while ($row = $results->fetchArray())
- {
- $addomains[$row[0]] = intval($row[1]);
- }
+
+ if(!is_bool($results))
+ while ($row = $results->fetchArray())
+ {
+ $addomains[$row[0]] = intval($row[1]);
+ }
$result = array('ads_over_time' => $addomains);
$data = array_merge($data, $result);
}
diff --git a/db_graph.php b/db_graph.php
index 9dbdba73..2642bf14 100644
--- a/db_graph.php
+++ b/db_graph.php
@@ -22,7 +22,6 @@ $token = $_SESSION['token'];
Compute graphical statistics from the Pi-hole query database
-
@@ -39,6 +38,11 @@ $token = $_SESSION['token'];
+
+
+ Depending on how large of a range you specified, the request may time out while Pi-hole tries to retrieve all the data.
+
+
diff --git a/db_lists.php b/db_lists.php
index 0ddc9dda..c0e39408 100644
--- a/db_lists.php
+++ b/db_lists.php
@@ -39,6 +39,11 @@ $token = $_SESSION['token'];
+
+
+ Depending on how large of a range you specified, the request may time out while Pi-hole tries to retrieve all the data.
+
+
+
+
+ Depending on how large of a range you specified, the request may time out while Pi-hole tries to retrieve all the data.
+
+
@@ -103,31 +108,29 @@ $token = $_SESSION['token'];
-
-
-
-
- | Time |
- Type |
- Domain |
- Client |
- Status |
- Action |
-
-
-
-
- | Time |
- Type |
- Domain |
- Client |
- Status |
- Action |
-
-
-
-
-
+
+
+
+ | Time |
+ Type |
+ Domain |
+ Client |
+ Status |
+ Action |
+
+
+
+
+ | Time |
+ Type |
+ Domain |
+ Client |
+ Status |
+ Action |
+
+
+
+
diff --git a/queries.php b/queries.php
index f511f8d1..89ed91d7 100644
--- a/queries.php
+++ b/queries.php
@@ -88,18 +88,35 @@ if(strlen($showing) > 0)
-->
-
-
-
- Adding to the ...
-
-
-
- Success!
-
-
-
- Failure! Something went wrong.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Adding to the ...
+
successfully added to the
+
+ Timeout or Network Connection Error!
+
+
+
+
+
+
@@ -110,33 +127,33 @@ if(strlen($showing) > 0)
-
-
-
-
- | Time |
- Type |
- Domain |
- Client |
- Status |
- Action |
-
-
-
-
- | Time |
- Type |
- Domain |
- Client |
- Status |
- Action |
-
-
-
-
-
-
-
+
+
+
+ | Time |
+ Type |
+ Domain |
+ Client |
+ Status |
+ DNSSEC |
+ Action |
+
+
+
+
+ | Time |
+ Type |
+ Domain |
+ Client |
+ Status |
+ DNSSEC |
+ Action |
+
+
+
+
+
+
diff --git a/scripts/pi-hole/js/db_graph.js b/scripts/pi-hole/js/db_graph.js
index d543f16b..8da24ad6 100644
--- a/scripts/pi-hole/js/db_graph.js
+++ b/scripts/pi-hole/js/db_graph.js
@@ -14,6 +14,8 @@ var from = moment(start__).utc().valueOf()/1000;
var end__ = moment();
var until = moment(end__).utc().valueOf()/1000;
+var timeoutWarning = $("#timeoutWarning");
+
$(function () {
$("#querytime").daterangepicker(
{
@@ -80,6 +82,7 @@ function compareNumbers(a, b) {
function updateQueriesOverTime() {
$("#queries-over-time .overlay").show();
+ timeoutWarning.show();
$.getJSON("api_db.php?getGraphData&from="+from+"&until="+until, function(data) {
// convert received objects to arrays
@@ -135,6 +138,7 @@ function updateQueriesOverTime() {
timeLineChart.options.scales.xAxes[0].display=true;
$("#queries-over-time .overlay").hide();
+ timeoutWarning.hide();
timeLineChart.update();
});
}
diff --git a/scripts/pi-hole/js/db_lists.js b/scripts/pi-hole/js/db_lists.js
index 75a21746..43e569f7 100644
--- a/scripts/pi-hole/js/db_lists.js
+++ b/scripts/pi-hole/js/db_lists.js
@@ -14,6 +14,9 @@ var from = moment(start__).utc().valueOf()/1000;
var end__ = moment();
var until = moment(end__).utc().valueOf()/1000;
+var timeoutWarning = $("#timeoutWarning");
+var listsStillLoading = 0;
+
$(function () {
$("#querytime").daterangepicker(
{
@@ -97,6 +100,10 @@ function updateTopClientsChart() {
}
$("#client-frequency .overlay").hide();
+
+ listsStillLoading--;
+ if(listsStillLoading === 0)
+ timeoutWarning.hide();
});
}
@@ -135,6 +142,10 @@ function updateTopDomainsChart() {
}
$("#domain-frequency .overlay").hide();
+
+ listsStillLoading--;
+ if(listsStillLoading === 0)
+ timeoutWarning.hide();
});
}
@@ -171,10 +182,16 @@ function updateTopAdsChart() {
}
$("#ad-frequency .overlay").hide();
+
+ listsStillLoading--;
+ if(listsStillLoading === 0)
+ timeoutWarning.hide();
});
}
$("#querytime").on("apply.daterangepicker", function(ev, picker) {
+ timeoutWarning.show();
+ listsStillLoading = 3;
updateTopClientsChart();
updateTopDomainsChart();
updateTopAdsChart();
diff --git a/scripts/pi-hole/js/db_queries.js b/scripts/pi-hole/js/db_queries.js
index 8551e9dc..751081d4 100644
--- a/scripts/pi-hole/js/db_queries.js
+++ b/scripts/pi-hole/js/db_queries.js
@@ -16,6 +16,8 @@ var until = moment(end__).utc().valueOf()/1000;
var instantquery = false;
var daterange;
+var timeoutWarning = $("#timeoutWarning");
+
// Do we want to filter queries?
var GETDict = {};
location.search.substr(1).split("&").forEach(function(item) {GETDict[item.split("=")[0]] = item.split("=")[1];});
@@ -141,6 +143,7 @@ function handleAjaxError( xhr, textStatus, error ) {
var reloadCallback = function()
{
+ timeoutWarning.hide();
statistics = [0,0,0,0];
var data = tableApi.rows().data();
for (var i = 0; i < data.length; i++) {
@@ -171,6 +174,7 @@ var reloadCallback = function()
};
function refreshTableData() {
+ timeoutWarning.show();
var APIstring = "api_db.php?getAllQueries&from="+from+"&until="+until;
statistics = [0,0,0];
tableApi.ajax.url(APIstring).load(reloadCallback);
@@ -201,13 +205,13 @@ $(document).ready(function() {
else if (data[4] === 2)
{
$(row).css("color","green");
- $("td:eq(4)", row).html( "OK (forwarded)" );
+ $("td:eq(4)", row).html( "OK
(forwarded)" );
$("td:eq(5)", row).html( "" );
}
else if (data[4] === 3)
{
$(row).css("color","green");
- $("td:eq(4)", row).html( "OK (cached)" );
+ $("td:eq(4)", row).html( "OK
(cached)" );
$("td:eq(5)", row).html( "" );
// statistics[1]++;
@@ -215,20 +219,20 @@ $(document).ready(function() {
else if (data[4] === 4)
{
$(row).css("color","red");
- $("td:eq(4)", row).html( "Pi-holed (wildcard)" );
+ $("td:eq(4)", row).html( "Pi-holed
(wildcard)" );
$("td:eq(5)", row).html( "" );
// statistics[3]++;
}
else
{
- $("td:eq(4)", row).html( "Unknown ("+data[4]+")" );
+ $("td:eq(4)", row).html( "Unknown
("+data[4]+")" );
$("td:eq(5)", row).html( "" );
}
// statistics[0]++;
},
dom: "<'row'<'col-sm-12'f>>" +
"<'row'<'col-sm-4'l><'col-sm-8'p>>" +
- "<'row'<'col-sm-12'tr>>" +
+ "<'row'<'col-sm-12'<'table-responsive'tr>>>" +
"<'row'<'col-sm-5'i><'col-sm-7'p>>",
"ajax": {"url": APIstring, "error": handleAjaxError },
"autoWidth" : false,
@@ -236,12 +240,12 @@ $(document).ready(function() {
"deferRender": true,
"order" : [[0, "desc"]],
"columns": [
- { "width" : "20%", "render": function (data, type, full, meta) { if(type === "display"){return moment.unix(data).format("Y-MM-DD HH:mm:ss z");}else{return data;} }},
+ { "width" : "15%", "render": function (data, type, full, meta) { if(type === "display"){return moment.unix(data).format("Y-MM-DD [
]HH:mm:ss z");}else{return data;} }},
{ "width" : "10%" },
{ "width" : "40%" },
+ { "width" : "20%" },
{ "width" : "10%" },
- { "width" : "10%" },
- { "width" : "10%" },
+ { "width" : "5%" },
],
"lengthMenu": [[10, 25, 50, 100, -1], [10, 25, 50, 100, "All"]],
"columnDefs": [ {
diff --git a/scripts/pi-hole/js/queries.js b/scripts/pi-hole/js/queries.js
index 984215bc..722f8543 100644
--- a/scripts/pi-hole/js/queries.js
+++ b/scripts/pi-hole/js/queries.js
@@ -22,62 +22,76 @@ function refreshData() {
function add(domain,list) {
var token = $("#token").html();
- var alInfo = $("#alInfo");
- var alList = $("#alList");
- var alDomain = $("#alDomain");
- alDomain.html(domain);
- var alSuccess = $("#alSuccess");
- var alFailure = $("#alFailure");
- var err = $("#err");
+ var alertModal = $("#alertModal");
+ var alProcessing = alertModal.find(".alProcessing");
+ var alSuccess = alertModal.find(".alSuccess");
+ var alFailure = alertModal.find(".alFailure");
+ var alNetworkErr = alertModal.find(".alFailure #alNetErr");
+ var alCustomErr = alertModal.find(".alFailure #alCustomErr");
+ var alList = "#alList";
+ var alDomain = "#alDomain";
- if(list === "white")
- {
- alList.html("Whitelist");
- }
- else
- {
- alList.html("Blacklist");
+ // Exit the function here if the Modal is already shown (multiple running interlock)
+ if (alertModal.css("display") !== "none") {
+ return;
}
- alInfo.show();
- alSuccess.hide();
- alFailure.hide();
- $.ajax({
- url: "scripts/pi-hole/php/add.php",
- method: "post",
- data: {"domain":domain, "list":list, "token":token},
- success: function(response) {
- if (response.indexOf("not a valid argument") >= 0 || response.indexOf("is not a valid domain") >= 0)
- {
- alFailure.show();
- err.html(response);
- alFailure.delay(4000).fadeOut(2000, function() { alFailure.hide(); });
+ var listtype;
+ if (list === "white") {
+ listtype = "Whitelist";
+ } else {
+ listtype = "Blacklist";
+ }
+ alProcessing.children(alDomain).html(domain);
+ alProcessing.children(alList).html(listtype);
+ alertModal.modal("show");
+
+ // add Domain to List after Modal has faded in
+ alertModal.one("shown.bs.modal", function() {
+ $.ajax({
+ url: "scripts/pi-hole/php/add.php",
+ method: "post",
+ data: {"domain":domain, "list":list, "token":token},
+ success: function(response) {
+ alProcessing.hide();
+ if (response.indexOf("not a valid argument") >= 0 ||
+ response.indexOf("is not a valid domain") >= 0 ||
+ response.indexOf("Wrong token") >= 0)
+ {
+ // Failure
+ alNetworkErr.hide();
+ alCustomErr.html(response.replace("[✗]", ""));
+ alFailure.fadeIn(1000);
+ setTimeout(function() { alertModal.modal("hide"); }, 3000);
+ }
+ else
+ {
+ // Success
+ alSuccess.children(alDomain).html(domain);
+ alSuccess.children(alList).html(listtype);
+ alSuccess.fadeIn(1000);
+ setTimeout(function() { alertModal.modal("hide"); }, 2000);
+ }
+ },
+ error: function(jqXHR, exception) {
+ // Network Error
+ alProcessing.hide();
+ alNetworkErr.show();
+ alFailure.fadeIn(1000);
+ setTimeout(function() { alertModal.modal("hide"); }, 3000);
}
- else
- {
- alSuccess.show();
- alSuccess.delay(1000).fadeOut(2000, function() { alSuccess.hide(); });
- }
- alInfo.delay(1000).fadeOut(2000, function() {
- alInfo.hide();
- alList.html("");
- alDomain.html("");
- });
- },
- error: function(jqXHR, exception) {
- alFailure.show();
- err.html("");
- alFailure.delay(1000).fadeOut(2000, function() {
- alFailure.hide();
- });
- alInfo.delay(1000).fadeOut(2000, function() {
- alInfo.hide();
- alList.html("");
- alDomain.html("");
- });
- }
+ });
+ });
+
+ // Reset Modal after it has faded out
+ alertModal.one("hidden.bs.modal", function() {
+ alProcessing.show();
+ alSuccess.add(alFailure).hide();
+ alProcessing.add(alSuccess).children(alDomain).html("").end().children(alList).html("");
+ alCustomErr.html("");
});
}
+
function handleAjaxError( xhr, textStatus, error ) {
if ( textStatus === "timeout" )
{
@@ -135,54 +149,84 @@ $(document).ready(function() {
{
$(row).css("color","red");
$("td:eq(4)", row).html( "Pi-holed" );
- $("td:eq(5)", row).html( "" );
+ $("td:eq(6)", row).html( "" );
}
else if (data[4] === "2")
{
$(row).css("color","green");
- $("td:eq(4)", row).html( "OK (forwarded)" );
- $("td:eq(5)", row).html( "" );
+ $("td:eq(4)", row).html( "OK
(forwarded)" );
+ $("td:eq(6)", row).html( "" );
}
else if (data[4] === "3")
{
$(row).css("color","green");
- $("td:eq(4)", row).html( "OK (cached)" );
- $("td:eq(5)", row).html( "" );
-
+ $("td:eq(4)", row).html( "OK
(cached)" );
+ $("td:eq(6)", row).html( "" );
}
else if (data[4] === "4")
{
$(row).css("color","red");
- $("td:eq(4)", row).html( "Pi-holed (wildcard)" );
- $("td:eq(5)", row).html( "" );
+ $("td:eq(4)", row).html( "Pi-holed
(wildcard)" );
+ $("td:eq(6)", row).html( "" );
}
else if (data[4] === "5")
{
$(row).css("color","red");
- $("td:eq(4)", row).html( "Pi-holed (blacklist)" );
- $("td:eq(5)", row).html( "" );
+ $("td:eq(4)", row).html( "Pi-holed
(blacklist)" );
+ $("td:eq(6)", row).html( "" );
}
else
{
$("td:eq(4)", row).html( "Unknown" );
- $("td:eq(5)", row).html( "" );
+ $("td:eq(6)", row).html( "" );
+ }
+ if (data[5] === "1")
+ {
+ $("td:eq(5)", row).css("color","green");
+ $("td:eq(5)", row).html( "SECURE" );
+ }
+ else if (data[5] === "2")
+ {
+ $("td:eq(5)", row).css("color","orange");
+ $("td:eq(5)", row).html( "INSECURE" );
+ }
+ else if (data[5] === "3")
+ {
+ $("td:eq(5)", row).css("color","red");
+ $("td:eq(5)", row).html( "BOGUS" );
+ }
+ else if (data[5] === "4")
+ {
+ $("td:eq(5)", row).css("color","red");
+ $("td:eq(5)", row).html( "ABANDONED" );
+ }
+ else if (data[5] === "5")
+ {
+ $("td:eq(5)", row).css("color","red");
+ $("td:eq(5)", row).html( "?" );
+ }
+ else
+ {
+ $("td:eq(5)", row).css("color","black");
+ $("td:eq(5)", row).html( "-" );
}
},
dom: "<'row'<'col-sm-12'f>>" +
"<'row'<'col-sm-4'l><'col-sm-8'p>>" +
- "<'row'<'col-sm-12'tr>>" +
+ "<'row'<'col-sm-12'<'table-responsive'tr>>>" +
"<'row'<'col-sm-5'i><'col-sm-7'p>>",
"ajax": {"url": APIstring, "error": handleAjaxError },
"autoWidth" : false,
"processing": true,
"order" : [[0, "desc"]],
"columns": [
- { "width" : "20%", "render": function (data, type, full, meta) { if(type === "display"){return moment.unix(data).format("Y-MM-DD HH:mm:ss z");}else{return data;} }},
- { "width" : "10%" },
- { "width" : "40%", "render": $.fn.dataTable.render.text() },
- { "width" : "10%", "render": $.fn.dataTable.render.text() },
+ { "width" : "15%", "render": function (data, type, full, meta) { if(type === "display"){return moment.unix(data).format("Y-MM-DD [
]HH:mm:ss z");}else{return data;} }},
{ "width" : "10%" },
+ { "width" : "37%", "render": $.fn.dataTable.render.text() },
+ { "width" : "8%", "render": $.fn.dataTable.render.text() },
{ "width" : "10%" },
+ { "width" : "5%" },
+ { "width" : "10%" }
],
"lengthMenu": [[10, 25, 50, 100, -1], [10, 25, 50, 100, "All"]],
"columnDefs": [ {
diff --git a/scripts/pi-hole/js/settings.js b/scripts/pi-hole/js/settings.js
index 0edae1bc..257ab7d4 100644
--- a/scripts/pi-hole/js/settings.js
+++ b/scripts/pi-hole/js/settings.js
@@ -85,7 +85,7 @@ $(".confirm-flushlogs").confirm({
});
$(".confirm-disablelogging").confirm({
- text: "Note that disabling query logging will render graphs on the web user interface useless. Are you sure you want to disable your logging?",
+ text: "Note that disabling query logging will render graphs on the web user interface useless. Are you sure you want to disable logging and flush your Pi-hole logs?",
title: "Confirmation required",
confirm(button) {
$("#disablelogsform").submit();
@@ -93,7 +93,7 @@ $(".confirm-disablelogging").confirm({
cancel(button) {
// nothing to do
},
- confirmButton: "Yes, disable logs",
+ confirmButton: "Yes, disable logs and flush my logs",
cancelButton: "No, go back",
post: true,
confirmButtonClass: "btn-danger",
@@ -101,6 +101,23 @@ $(".confirm-disablelogging").confirm({
dialogClass: "modal-dialog modal-mg"
});
+$(".confirm-disablelogging-noflush").confirm({
+ text: "Note that disabling query logging will render graphs on the web user interface useless after this point. Are you sure you want to disable logging?",
+ title: "Confirmation required",
+ confirm(button) {
+ $("#disablelogsform-noflush").submit();
+ },
+ cancel(button) {
+ // nothing to do
+ },
+ confirmButton: "Yes, disable logs",
+ cancelButton: "No, go back",
+ post: true,
+ confirmButtonClass: "btn-warning",
+ cancelButtonClass: "btn-success",
+ dialogClass: "modal-dialog modal-mg"
+});
+
$(".api-token").confirm({
text: "Make sure that nobody else can scan this code around you. They will have full access to the API without having to know the password. Note that the generation of the QR code will take some time.",
title: "Confirmation required",
diff --git a/scripts/pi-hole/php/auth.php b/scripts/pi-hole/php/auth.php
index 85d38f8f..0b32c732 100644
--- a/scripts/pi-hole/php/auth.php
+++ b/scripts/pi-hole/php/auth.php
@@ -6,7 +6,7 @@
* This file is copyright under the latest version of the EUPL.
* Please see LICENSE file for your rights under this license. */
-require('func.php');
+require_once('func.php');
$ERRORLOG = getenv('PHP_ERROR_LOG');
if (empty($ERRORLOG)) {
$ERRORLOG = '/var/log/lighttpd/error.log';
@@ -92,26 +92,6 @@ function check_csrf($token) {
session_start();
}
- // Credit: http://php.net/manual/en/function.hash-equals.php#119576
- if(!function_exists('hash_equals')) {
- function hash_equals($known_string, $user_string) {
- $ret = 0;
-
- if (strlen($known_string) !== strlen($user_string)) {
- $user_string = $known_string;
- $ret = 1;
- }
-
- $res = $known_string ^ $user_string;
-
- for ($i = strlen($res) - 1; $i >= 0; --$i) {
- $ret |= ord($res[$i]);
- }
-
- return !$ret;
- }
- }
-
if(!isset($_SESSION['token']) || empty($token) || !hash_equals($_SESSION['token'], $token)) {
log_and_die("Wrong token");
}
@@ -119,7 +99,7 @@ function check_csrf($token) {
function check_domain() {
if(isset($_POST['domain'])){
- $domains = preg_split('\s+', $_POST['domain']);
+ $domains = preg_split('/\s+/', $_POST['domain']);
foreach($domains as $domain)
{
$validDomain = is_valid_domain_name($domain);
@@ -146,7 +126,7 @@ function list_verify($type) {
require("password.php");
if($wrongpassword || !$auth)
{
- log_and_die("Wrong password - ".htmlspecialchars($type)."listing of ${_POST['domain']} not permitted");
+ log_and_die("Wrong password - ".htmlspecialchars($type)."listing of ".htmlspecialchars($_POST['domain'])." not permitted");
}
}
else
diff --git a/scripts/pi-hole/php/debug.php b/scripts/pi-hole/php/debug.php
index 39d5c8ea..27a23545 100644
--- a/scripts/pi-hole/php/debug.php
+++ b/scripts/pi-hole/php/debug.php
@@ -18,10 +18,12 @@ $token = isset($_GET["token"]) ? $_GET["token"] : "";
check_csrf($token);
function echoEvent($datatext) {
+ $data = htmlspecialchars($datatext);
+
if(!isset($_GET["IE"]))
- echo "data: ".implode("\ndata: ", explode("\n", $datatext))."\n\n";
+ echo "data: ".implode("\ndata: ", explode("\n", $data))."\n\n";
else
- echo $datatext;
+ echo $data;
}
if(isset($_GET["upload"]))
diff --git a/scripts/pi-hole/php/func.php b/scripts/pi-hole/php/func.php
index f3beaf9e..bc353218 100644
--- a/scripts/pi-hole/php/func.php
+++ b/scripts/pi-hole/php/func.php
@@ -25,4 +25,24 @@ function checkfile($filename) {
}
}
+// Credit: http://php.net/manual/en/function.hash-equals.php#119576
+if(!function_exists('hash_equals')) {
+ function hash_equals($known_string, $user_string) {
+ $ret = 0;
+
+ if (strlen($known_string) !== strlen($user_string)) {
+ $user_string = $known_string;
+ $ret = 1;
+ }
+
+ $res = $known_string ^ $user_string;
+
+ for ($i = strlen($res) - 1; $i >= 0; --$i) {
+ $ret |= ord($res[$i]);
+ }
+
+ return !$ret;
+ }
+}
+
?>
diff --git a/scripts/pi-hole/php/password.php b/scripts/pi-hole/php/password.php
index 77ee2863..ad8cbd08 100644
--- a/scripts/pi-hole/php/password.php
+++ b/scripts/pi-hole/php/password.php
@@ -6,6 +6,8 @@
* This file is copyright under the latest version of the EUPL.
* Please see LICENSE file for your rights under this license. */
+ require_once('func.php');
+
// Start a new PHP session (or continue an existing one)
session_start();
@@ -37,7 +39,7 @@
if(isset($_POST["pw"]))
{
$postinput = hash('sha256',hash('sha256',$_POST["pw"]));
- if($postinput == $pwhash)
+ if(hash_equals($pwhash, $postinput))
{
$_SESSION["hash"] = $pwhash;
@@ -57,13 +59,13 @@
// Compare auth hash with saved hash
else if (isset($_SESSION["hash"]))
{
- if($_SESSION["hash"] == $pwhash)
+ if(hash_equals($pwhash, $_SESSION["hash"]))
$auth = true;
}
// API can use the hash to get data without logging in via plain-text password
else if (isset($api) && isset($_GET["auth"]))
{
- if($_GET["auth"] == $pwhash)
+ if(hash_equals($pwhash, $_GET["auth"]))
$auth = true;
}
else
diff --git a/scripts/pi-hole/php/savesettings.php b/scripts/pi-hole/php/savesettings.php
index ad1b0eae..64914e77 100644
--- a/scripts/pi-hole/php/savesettings.php
+++ b/scripts/pi-hole/php/savesettings.php
@@ -123,7 +123,7 @@ function isinserverlist($addr) {
"Norton" => ["v4_1" => "199.85.126.10", "v4_2" => "199.85.127.10"],
"Comodo" => ["v4_1" => "8.26.56.26", "v4_2" => "8.20.247.20"],
"DNS.WATCH" => ["v4_1" => "84.200.69.80", "v4_2" => "84.200.70.40", "v6_1" => "2001:1608:10:25:0:0:1c04:b12f", "v6_2" => "2001:1608:10:25:0:0:9249:d69b"],
- "Quad9" => ["v4_1" => "9.9.9.9", "v6_1" => "2620:fe::fe"]
+ "Quad9" => ["v4_1" => "9.9.9.9", "v4_2" => "149.112.112.112", "v6_1" => "2620:fe::fe"]
];
$adlist = [];
@@ -278,7 +278,12 @@ function readAdlists()
if($_POST["action"] === "Disable")
{
exec("sudo pihole -l off");
- $success .= "Logging has been disabled";
+ $success .= "Logging has been disabled and logs have been flushed";
+ }
+ elseif($_POST["action"] === "Disable-noflush")
+ {
+ exec("sudo pihole -l off noflush");
+ $success .= "Logging has been disabled, your logs have not been flushed";
}
else
{
@@ -320,9 +325,9 @@ function readAdlists()
$first = true;
foreach($clients as $client)
{
- if(!validDomainWildcard($client))
+ if(!validDomainWildcard($client) && !validIP($client))
{
- $error .= "Top Clients entry ".htmlspecialchars($client)." is invalid (use only IP addresses)!
";
+ $error .= "Top Clients entry ".htmlspecialchars($client)." is invalid (use only host names and IP addresses)!
";
}
if(!$first)
{
diff --git a/scripts/pi-hole/php/teleporter.php b/scripts/pi-hole/php/teleporter.php
index 0427b7c0..9efe7fd1 100644
--- a/scripts/pi-hole/php/teleporter.php
+++ b/scripts/pi-hole/php/teleporter.php
@@ -176,6 +176,7 @@ else
archive_add_file("/etc/pihole/","blacklist.txt");
archive_add_file("/etc/pihole/","adlists.list");
archive_add_file("/etc/pihole/","setupVars.conf");
+ archive_add_file("/etc/pihole/","auditlog.list");
archive_add_directory("/etc/dnsmasq.d/");
$archive["wildcardblocking.txt"] = getWildcardListContent();
diff --git a/scripts/pi-hole/php/update_checker.php b/scripts/pi-hole/php/update_checker.php
index 9bd4ab06..d479318a 100644
--- a/scripts/pi-hole/php/update_checker.php
+++ b/scripts/pi-hole/php/update_checker.php
@@ -44,12 +44,12 @@ else
/********** Get Pi-hole FTL (not a git repository) **********/
$FTL_branch = $branches[2];
- if($FTL_branch !== "master") {
+ if(substr($versions[2], 0, 4) === "vDev") {
$FTL_current = "vDev";
$FTL_commit = $versions[2];
}
else {
- $FTL_current = explode("-",$versions[2])[0];
+ $FTL_current = $versions[2];
}
// Get data from GitHub
diff --git a/settings.php b/settings.php
index a032c9ee..372f9393 100644
--- a/settings.php
+++ b/settings.php
@@ -288,6 +288,7 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "blocklists"
@@ -344,7 +345,7 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "blocklists"
if (isset($setupVars["PIHOLE_DOMAIN"])) {
$piHoleDomain = $setupVars["PIHOLE_DOMAIN"];
} else {
- $piHoleDomain = "local";
+ $piHoleDomain = "lan";
}
?>