diff --git a/admin/api.php b/admin/api.php index 34ffe65..b986a65 100644 --- a/admin/api.php +++ b/admin/api.php @@ -18,28 +18,9 @@ $data = array(); // Common API functions -if (isset($_GET['status'])) -{ - $pistatus = pihole_execute('status web'); - if(isset($pistatus[0])) - { - $pistatus = $pistatus[0]; - } - else - { - $pistatus = null; - } - if ($pistatus === "1") - { - $data = array_merge($data, array("status" => "enabled")); - } - else - { - $data = array_merge($data, array("status" => "disabled")); - } -} -elseif (isset($_GET['enable']) && $auth) -{ +if (isset($_GET['status'])) { + $data = array_merge($data, array("status" => piholeStatusAPI())); +} elseif (isset($_GET['enable']) && $auth) { if(isset($_GET["auth"])) { if($_GET["auth"] !== $pwhash) @@ -160,17 +141,64 @@ return; } +elseif(isset($_GET['customdns']) && $auth) +{ + if (isset($_GET["auth"])) { + if ($_GET["auth"] !== $pwhash) { + die("Not authorized!"); + } + } else { + // Skip token validation if explicit auth string is given + check_csrf($_GET['token']); + } + + switch ($_GET["action"]) { + case 'get': + $_POST['action'] = 'get'; + break; + case 'add': + $_POST['action'] = 'add'; + break; + case 'delete': + $_POST['action'] = 'delete'; + break; + } + + require("scripts/pi-hole/php/customdns.php"); +} +elseif(isset($_GET['customcname']) && $auth) +{ + if (isset($_GET["auth"])) { + if ($_GET["auth"] !== $pwhash) { + die("Not authorized!"); + } + } else { + // Skip token validation if explicit auth string is given + check_csrf($_GET['token']); + } + + switch ($_GET["action"]) { + case 'get': + $_POST['action'] = 'get'; + break; + case 'add': + $_POST['action'] = 'add'; + break; + case 'delete': + $_POST['action'] = 'delete'; + break; + } + + require("scripts/pi-hole/php/customcname.php"); +} // Other API functions require("api_FTL.php"); header('Content-type: application/json'); -if(isset($_GET["jsonForceObject"])) -{ - echo json_encode($data, JSON_FORCE_OBJECT); -} -else -{ - echo json_encode($data); +if(isset($_GET["jsonForceObject"])) { + echo json_encode($data, JSON_FORCE_OBJECT); +} else { + echo json_encode($data); } ?> diff --git a/admin/api_FTL.php b/admin/api_FTL.php index 13177a7..b7bcf9f 100644 --- a/admin/api_FTL.php +++ b/admin/api_FTL.php @@ -29,26 +29,48 @@ $data["version"] = 3; } - if (isset($_GET['summary']) || isset($_GET['summaryRaw']) || !count($_GET)) - { + if (isset($_GET['summary']) || isset($_GET['summaryRaw']) || !count($_GET)) { require_once("scripts/pi-hole/php/gravity.php"); sendRequestFTL("stats"); $return = getResponseFTL(); $stats = []; - foreach($return as $line) - { + foreach($return as $line) { $tmp = explode(" ",$line); - if(($tmp[0] === "domains_being_blocked" && !is_numeric($tmp[1])) || $tmp[0] === "status") - $stats[$tmp[0]] = $tmp[1]; // Expect string response - else - $stats[$tmp[0]] = floatval($tmp[1]); // Expect float response + if($tmp[0] === "domains_being_blocked" && !is_numeric($tmp[1])) { + // Expect string response + $stats[$tmp[0]] = $tmp[1]; + } elseif ($tmp[0] === "status") { + // Expect string response + $stats[$tmp[0]] = piholeStatusAPI(); + } elseif (isset($_GET['summary'])) { + // "summary" expects a formmated string response + if($tmp[0] !== "ads_percentage_today") { + $stats[$tmp[0]] = number_format($tmp[1]); + } else { + $stats[$tmp[0]] = number_format($tmp[1], 1, '.', ''); + } + } else { + // Expect float response + $stats[$tmp[0]] = floatval($tmp[1]); + } + } $stats['gravity_last_updated'] = gravity_last_update(true); $data = array_merge($data,$stats); } + if (isset($_GET["getMaxlogage"]) && $auth) { + sendRequestFTL("maxlogage"); + // Convert seconds to hours and rounds to one decimal place. + $ret = round(intval(getResponseFTL()[0]) / 3600, 1); + // Return 24h if value is 0, empty, null or non numeric. + $ret = $ret ?: 24; + + $data = array_merge($data, array("maxlogage" => $ret)); + } + if (isset($_GET['overTimeData10mins'])) { sendRequestFTL("overTime"); diff --git a/admin/api_db.php b/admin/api_db.php index a861cbd..e5340ff 100644 --- a/admin/api_db.php +++ b/admin/api_db.php @@ -87,17 +87,36 @@ $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()) - { - // Convert query type ID to name + if (!is_bool($results)) { + // Start the JSON string + echo '{"data":['; + + $first = true; + while ($row = $results->fetchArray()) { + // Insert a comma before the next record (except on the first one) + if (!$first) { + echo ","; + } else { + $first = false; + } + + // Convert query type ID to name, encode domain, encode destination $query_type = getQueryTypeStr($row[1]); + $domain = utf8_encode(str_replace("~"," ",$row[2])); + $destination = utf8_encode($row[5]); - // Insert into array - // array: time type domain client status upstream destination - $allQueries[] = [$row[0], $query_type, utf8_encode(str_replace("~"," ",$row[2])), $row[3], $row[4], utf8_encode($row[5])]; + // Insert into array and output it in JSON format + // array: time type domain client status upstream destination + echo json_encode([$row[0], $query_type, $domain, $row[3], $row[4], $destination]); } + + // Finish the JSON string + echo ']}'; + } + // exit at the end + exit(); } + // only used if getAllQueries==empty $result = array('data' => $allQueries); $data = array_merge($data, $result); } diff --git a/admin/groups-adlists.php b/admin/groups-adlists.php index 1fb0417..04ec729 100644 --- a/admin/groups-adlists.php +++ b/admin/groups-adlists.php @@ -67,7 +67,7 @@ Status Comment Group assignment - Action +   diff --git a/admin/groups-clients.php b/admin/groups-clients.php index e562013..420ce5c 100644 --- a/admin/groups-clients.php +++ b/admin/groups-clients.php @@ -73,7 +73,7 @@ Client Comment Group assignment - Action +   diff --git a/admin/groups-domains.php b/admin/groups-domains.php index b1aca18..25f86ee 100644 --- a/admin/groups-domains.php +++ b/admin/groups-domains.php @@ -126,7 +126,7 @@ Status Comment Group assignment - Action +   diff --git a/admin/groups.php b/admin/groups.php index 64b957a..0cf970f 100644 --- a/admin/groups.php +++ b/admin/groups.php @@ -64,7 +64,7 @@ Name Status Description - Action +   diff --git a/admin/index.php b/admin/index.php index b6d1fa8..ace5f70 100644 --- a/admin/index.php +++ b/admin/index.php @@ -1,26 +1,14 @@ - @@ -72,7 +60,7 @@ function getinterval()
-

Domains on Blocklist

+

Domains on Adlists

---

@@ -87,7 +75,7 @@ function getinterval()
-

Total queries over last hours

+

Total queries over last 24 hours

@@ -112,7 +100,7 @@ function getinterval()
-

Client activity over last hours

+

Client activity over last 24 hours

diff --git a/admin/queries.php b/admin/queries.php index da68b19..f40a54b 100644 --- a/admin/queries.php +++ b/admin/queries.php @@ -50,9 +50,9 @@ } else if(isset($_GET["forwarddest"])) { - if($_GET["forwarddest"] === "blocklist") - $showing .= " queries answered from blocklists"; - elseif($_GET["forwarddest"] === "cache") + if($_GET["forwarddest"] === "blocked") + $showing .= " queries blocked by Pi-hole"; + elseif($_GET["forwarddest"] === "cached") $showing .= " queries answered from cache"; else $showing .= " queries for upstream destination ".htmlentities($_GET["forwarddest"]); diff --git a/admin/scripts/pi-hole/js/footer.js b/admin/scripts/pi-hole/js/footer.js index 763e8ae..5e38662 100644 --- a/admin/scripts/pi-hole/js/footer.js +++ b/admin/scripts/pi-hole/js/footer.js @@ -58,7 +58,9 @@ function countDown() { } else { ena.text("Enable"); piholeChanged("enabled"); - localStorage.removeItem("countDownTarget"); + if (localStorage) { + localStorage.removeItem("countDownTarget"); + } } } @@ -148,7 +150,7 @@ function initCheckboxRadioStyle() { } // Read from local storage, initialize if needed - var chkboxStyle = localStorage.getItem("theme_icheck"); + var chkboxStyle = localStorage ? localStorage.getItem("theme_icheck") : null; if (chkboxStyle === null) { chkboxStyle = "primary"; } @@ -172,7 +174,10 @@ function initCheckboxRadioStyle() { function initCPUtemp() { function setCPUtemp(unit) { - localStorage.setItem("tempunit", tempunit); + if (localStorage) { + localStorage.setItem("tempunit", tempunit); + } + var temperature = parseFloat($("#rawtemp").text()); var displaytemp = $("#tempdisplay"); if (!isNaN(temperature)) { @@ -195,7 +200,7 @@ function initCPUtemp() { } // Read from local storage, initialize if needed - var tempunit = localStorage.getItem("tempunit"); + var tempunit = localStorage ? localStorage.getItem("tempunit") : null; if (tempunit === null) { tempunit = "C"; } diff --git a/admin/scripts/pi-hole/js/groups-adlists.js b/admin/scripts/pi-hole/js/groups-adlists.js index 501ec2f..1ff87a0 100644 --- a/admin/scripts/pi-hole/js/groups-adlists.js +++ b/admin/scripts/pi-hole/js/groups-adlists.js @@ -122,7 +122,7 @@ function initTable() { { data: "enabled", searchable: false }, { data: "comment" }, { data: "groups", searchable: false }, - { data: null, width: "80px", orderable: false }, + { data: null, width: "22px", orderable: false }, ], columnDefs: [ { @@ -291,7 +291,8 @@ function initTable() { $("td:eq(5)", row).html(button); }, dom: - "<'row'<'col-sm-4'l><'col-sm-8'f>>" + + "<'row'<'col-sm-12'f>>" + + "<'row'<'col-sm-4'l><'col-sm-8'p>>" + "<'row'<'col-sm-12'<'table-responsive'tr>>>" + "<'row'<'col-sm-5'i><'col-sm-7'p>>", lengthMenu: [ diff --git a/admin/scripts/pi-hole/js/groups-clients.js b/admin/scripts/pi-hole/js/groups-clients.js index 171a939..a290742 100644 --- a/admin/scripts/pi-hole/js/groups-clients.js +++ b/admin/scripts/pi-hole/js/groups-clients.js @@ -95,7 +95,7 @@ function initTable() { { data: "ip", type: "ip-address" }, { data: "comment" }, { data: "groups", searchable: false }, - { data: "name", width: "80px", orderable: false }, + { data: "name", width: "22px", orderable: false }, ], columnDefs: [ { @@ -215,7 +215,8 @@ function initTable() { $("td:eq(3)", row).html(button); }, dom: - "<'row'<'col-sm-4'l><'col-sm-8'f>>" + + "<'row'<'col-sm-12'f>>" + + "<'row'<'col-sm-4'l><'col-sm-8'p>>" + "<'row'<'col-sm-12'<'table-responsive'tr>>>" + "<'row'<'col-sm-5'i><'col-sm-7'p>>", lengthMenu: [ diff --git a/admin/scripts/pi-hole/js/groups-domains.js b/admin/scripts/pi-hole/js/groups-domains.js index e70286d..2faa9a8 100644 --- a/admin/scripts/pi-hole/js/groups-domains.js +++ b/admin/scripts/pi-hole/js/groups-domains.js @@ -74,7 +74,7 @@ function initTable() { { data: "enabled", searchable: false }, { data: "comment" }, { data: "groups", searchable: false, visible: showtype === "all" }, - { data: null, width: "80px", orderable: false }, + { data: null, width: "22px", orderable: false }, ], columnDefs: [ { @@ -244,7 +244,8 @@ function initTable() { } }, dom: - "<'row'<'col-sm-4'l><'col-sm-8'f>>" + + "<'row'<'col-sm-12'f>>" + + "<'row'<'col-sm-4'l><'col-sm-8'p>>" + "<'row'<'col-sm-12'<'table-responsive'tr>>>" + "<'row'<'col-sm-5'i><'col-sm-7'p>>", lengthMenu: [ diff --git a/admin/scripts/pi-hole/js/groups.js b/admin/scripts/pi-hole/js/groups.js index 417dd9f..8b7e3b6 100644 --- a/admin/scripts/pi-hole/js/groups.js +++ b/admin/scripts/pi-hole/js/groups.js @@ -25,7 +25,7 @@ $(function () { { data: "name" }, { data: "enabled", searchable: false }, { data: "description" }, - { data: null, width: "60px", orderable: false }, + { data: null, width: "22px", orderable: false }, ], columnDefs: [ { @@ -84,7 +84,8 @@ $(function () { } }, dom: - "<'row'<'col-sm-4'l><'col-sm-8'f>>" + + "<'row'<'col-sm-12'f>>" + + "<'row'<'col-sm-4'l><'col-sm-8'p>>" + "<'row'<'col-sm-12'<'table-responsive'tr>>>" + "<'row'<'col-sm-5'i><'col-sm-7'p>>", lengthMenu: [ diff --git a/admin/scripts/pi-hole/js/index.js b/admin/scripts/pi-hole/js/index.js index d0f5d96..d7cce8e 100644 --- a/admin/scripts/pi-hole/js/index.js +++ b/admin/scripts/pi-hole/js/index.js @@ -319,24 +319,71 @@ function updateQueryTypesPie() { queryTypePieChart.update(); // Don't use rotation animation for further updates queryTypePieChart.options.animation.duration = 0; + queryTypePieChart.options.legendCallback = customLegend; + // Generate legend in separate div $("#query-types-legend").html(queryTypePieChart.generateLegend()); - $("#query-types-legend > ul > li").prepend(createEyeConElement()); $("#query-types-legend > ul > li").click(function (e) { - if (isEyeCon(e.target)) { + if (iscolorBox(e.target)) { return false; } window.location.href = "queries.php?querytype=" + querytypeids[$(this).index()]; }); + $("#query-types-legend .colorBoxWrapper").click(function (e) { + hidePieSlice(e); + }); }).done(function () { // Reload graph after minute setTimeout(updateQueryTypesPie, 60000); }); } +function customLegend(chart) { + var text = []; + var data = chart.data; + var datasets = data.datasets; + var labels = data.labels; + + text.push('
    '); + + if (datasets.length > 0) { + for (var i = 0; i < datasets[0].data.length; ++i) { + var color = datasets[0].backgroundColor[i]; + + var txt = ""; + + // legend box icon + txt = + '' + + '' + + ""; + + // color block + txt += ''; + + // label + if (labels[i]) { + txt += + '' + + labels[i] + + ""; + } + + text.push("
  • " + txt + "
  • "); + } + } + + text.push("
"); + return text.join(""); +} + function hidePieSlice(event) { - toggleEyeCon(event.target); + togglecolorBox(event.target); var legendID = $(event.target).closest(".chart-legend").attr("id"); var ci = @@ -360,19 +407,19 @@ function hidePieSlice(event) { ci.update(); } -function toggleEyeCon(target) { +function togglecolorBox(target) { var parentListItem = $(target).closest("li"); - var eyeCon = $(parentListItem).find(".fa-eye, .fa-eye-slash"); + var colorBox = $(parentListItem).find(".fa-check-square, .fa-square"); - if (eyeCon) { - $(eyeCon).toggleClass("fa-eye"); - $(eyeCon).toggleClass("fa-eye-slash"); + if (colorBox) { + $(colorBox).toggleClass("fa-check-square"); + $(colorBox).toggleClass("fa-square"); } } -function isEyeCon(target) { - // See if click happened on eyeConWrapper or child SVG - if ($(target).closest(".eyeConWrapper")[0]) { +function iscolorBox(target) { + // See if click happened on colorBoxWrapper or child SVG + if ($(target).closest(".colorBoxWrapper")[0]) { return true; } @@ -468,16 +515,6 @@ function updateClientsOverTime() { }); } -function createEyeConElement() { - var eyeConWrapper = $("") - .addClass("eyeConWrapper") - .click(function (e) { - hidePieSlice(e); - }); - eyeConWrapper.append($("")); - return eyeConWrapper; -} - function updateForwardDestinationsPie() { $.getJSON("api.php?getForwardDestinations", function (data) { if ("FTLnotrunning" in data) { @@ -519,11 +556,12 @@ function updateForwardDestinationsPie() { forwardDestinationPieChart.update(); // Don't use rotation animation for further updates forwardDestinationPieChart.options.animation.duration = 0; + forwardDestinationPieChart.options.legendCallback = customLegend; + // Generate legend in separate div $("#forward-destinations-legend").html(forwardDestinationPieChart.generateLegend()); - $("#forward-destinations-legend > ul > li").prepend(createEyeConElement()); $("#forward-destinations-legend > ul > li").click(function (e) { - if (isEyeCon(e.target)) { + if (iscolorBox(e.target)) { return false; } @@ -532,6 +570,9 @@ function updateForwardDestinationsPie() { window.location.href = "queries.php?forwarddest=" + obj; } }); + $("#forward-destinations-legend .colorBoxWrapper").click(function (e) { + hidePieSlice(e); + }); }).done(function () { // Reload graph after one minute setTimeout(updateForwardDestinationsPie, 60000); @@ -723,7 +764,7 @@ function updateSummaryData(runOnce) { } }; - $.getJSON("api.php?summary", function (data) { + $.getJSON("api.php?summaryRaw", function (data) { updateSessionTimer(); if ("FTLnotrunning" in data) { @@ -795,7 +836,7 @@ function updateSummaryData(runOnce) { function doughnutTooltip(tooltipItems, data) { var dataset = data.datasets[tooltipItems.datasetIndex]; - var label = data.labels[tooltipItems.index]; + var label = " " + data.labels[tooltipItems.index]; // Compute share of total and of displayed var scale = 0, total = 0; @@ -813,16 +854,28 @@ function doughnutTooltip(tooltipItems, data) { return label + ": " + dataset.data[tooltipItems.index].toFixed(1) + "%"; return ( label + - ":
- " + + ":
• " + dataset.data[tooltipItems.index].toFixed(1) + - "% of all queries
- " + + "% of all queries
• " + ((dataset.data[tooltipItems.index] * 100) / (total - scale)).toFixed(1) + "% of shown items" ); } +var maxlogage = "24"; +function getMaxlogage() { + $.getJSON("api.php?getMaxlogage", function (data) { + if (!("FTLnotrunning" in data)) { + maxlogage = data.maxlogage; + } + }).done(function () { + $(".maxlogage-interval").html(maxlogage); + }); +} + $(function () { // Pull in data via AJAX + getMaxlogage(); updateSummaryData(); var gridColor = $(".graphs-grid").css("background-color"); diff --git a/admin/scripts/pi-hole/js/messages.js b/admin/scripts/pi-hole/js/messages.js index bd0f01f..fead56f 100644 --- a/admin/scripts/pi-hole/js/messages.js +++ b/admin/scripts/pi-hole/js/messages.js @@ -174,7 +174,8 @@ $(function () { $("td:eq(3)", row).html(button); }, dom: - "<'row'<'col-sm-4'l><'col-sm-8'f>>" + + "<'row'<'col-sm-12'f>>" + + "<'row'<'col-sm-4'l><'col-sm-8'p>>" + "<'row'<'col-sm-12'<'table-responsive'tr>>>" + "<'row'<'col-sm-5'i><'col-sm-7'p>>", lengthMenu: [ diff --git a/admin/scripts/pi-hole/js/settings.js b/admin/scripts/pi-hole/js/settings.js index 3733a7e..d0d7a1e 100644 --- a/admin/scripts/pi-hole/js/settings.js +++ b/admin/scripts/pi-hole/js/settings.js @@ -213,9 +213,15 @@ function loadCacheInfo() { var cachelivefreed = parseInt(data.cacheinfo["cache-live-freed"], 10); $("#cache-live-freed").text(cachelivefreed); if (cachelivefreed > 0) { - $("#cache-live-freed").parent("tr").addClass("lookatme"); + $("#cache-live-freed").parent("tr").children("th").children("span").addClass("lookatme"); + $("#cache-live-freed").parent("tr").children("td").addClass("lookatme"); + $("#cache-live-freed") + .parent("tr") + .children("td") + .attr("lookatme-text", cachelivefreed.toString()); } else { - $("#cache-live-freed").parent("tr").removeClass("lookatme"); + $("#cache-live-freed").parent("tr").children("th").children("span").removeClass("lookatme"); + $("#cache-live-freed").parent("tr").children("td").removeClass("lookatme"); } // Update cache info every 10 seconds @@ -228,7 +234,8 @@ $(function () { if (document.getElementById("DHCPLeasesTable")) { leasetable = $("#DHCPLeasesTable").DataTable({ dom: - "<'row'<'col-sm-4'l><'col-sm-8'f>>" + + "<'row'<'col-sm-12'f>>" + + "<'row'<'col-sm-4'l><'col-sm-8'p>>" + "<'row'<'col-sm-12'<'table-responsive'tr>>>" + "<'row'<'col-sm-5'i><'col-sm-7'p>>", lengthMenu: [ @@ -238,9 +245,23 @@ $(function () { columnDefs: [ { bSortable: false, orderable: false, targets: -1 }, { - targets: [0, 1, 2], + targets: [0, 1], render: $.fn.dataTable.render.text(), }, + { + targets: 2, + render: function (data) { + // Show "unknown", when host is "*" + var str; + if (data === "*") { + str = "unknown"; + } else { + str = typeof data === "string" ? utils.escapeHtml(data) : data; + } + + return str; + }, + }, ], paging: true, order: [[2, "asc"]], @@ -258,7 +279,8 @@ $(function () { if (document.getElementById("DHCPStaticLeasesTable")) { staticleasetable = $("#DHCPStaticLeasesTable").DataTable({ dom: - "<'row'<'col-sm-4'l><'col-sm-8'f>>" + + "<'row'<'col-sm-12'f>>" + + "<'row'<'col-sm-4'l><'col-sm-8'p>>" + "<'row'<'col-sm-12'<'table-responsive'tr>>>" + "<'row'<'col-sm-5'i><'col-sm-7'p>>", lengthMenu: [ @@ -342,7 +364,7 @@ $(".nav-tabs a").on("shown.bs.tab", function (e) { // Bar/Smooth chart toggle $(function () { var bargraphs = $("#bargraphs"); - var chkboxData = localStorage.getItem("barchart_chkbox"); + var chkboxData = localStorage ? localStorage.getItem("barchart_chkbox") : null; if (chkboxData !== null) { // Restore checkbox state @@ -350,7 +372,9 @@ $(function () { } else { // Initialize checkbox bargraphs.prop("checked", true); - localStorage.setItem("barchart_chkbox", true); + if (localStorage) { + localStorage.setItem("barchart_chkbox", true); + } } bargraphs.click(function () { @@ -360,15 +384,17 @@ $(function () { $(function () { var colorfulQueryLog = $("#colorfulQueryLog"); - var chkboxData = localStorage.getItem("colorfulQueryLog_chkbox"); + var chkboxData = localStorage ? localStorage.getItem("colorfulQueryLog_chkbox") : null; if (chkboxData !== null) { // Restore checkbox state colorfulQueryLog.prop("checked", chkboxData === "true"); } else { // Initialize checkbox - colorfulQueryLog.prop("checked", true); - localStorage.setItem("colorfulQueryLog_chkbox", true); + colorfulQueryLog.prop("checked", false); + if (localStorage) { + localStorage.setItem("colorfulQueryLog_chkbox", true); + } } colorfulQueryLog.click(function () { diff --git a/admin/scripts/pi-hole/js/utils.js b/admin/scripts/pi-hole/js/utils.js index 7229231..b9e1a57 100644 --- a/admin/scripts/pi-hole/js/utils.js +++ b/admin/scripts/pi-hole/js/utils.js @@ -229,13 +229,25 @@ function setBsSelectDefaults() { }; } +var backupStorage = {}; function stateSaveCallback(itemName, data) { - localStorage.setItem(itemName, JSON.stringify(data)); + if (localStorage === null) { + backupStorage[itemName] = JSON.stringify(data); + } else { + localStorage.setItem(itemName, JSON.stringify(data)); + } } function stateLoadCallback(itemName) { + var data; // Receive previous state from client's local storage area - var data = localStorage.getItem(itemName); + if (localStorage === null) { + var item = backupStorage[itemName]; + data = typeof item === "undefined" ? null : item; + } else { + data = localStorage.getItem(itemName); + } + // Return if not available if (data === null) { return null; @@ -259,7 +271,7 @@ function stateLoadCallback(itemName) { function getGraphType() { // Only return line if `barchart_chkbox` is explicitly set to false. Else return bar - return localStorage.getItem("barchart_chkbox") === "false" ? "line" : "bar"; + return localStorage && localStorage.getItem("barchart_chkbox") === "false" ? "line" : "bar"; } function addFromQueryLog(domain, list) { diff --git a/admin/scripts/pi-hole/php/auth.php b/admin/scripts/pi-hole/php/auth.php index 673bd48..fbf6b76 100644 --- a/admin/scripts/pi-hole/php/auth.php +++ b/admin/scripts/pi-hole/php/auth.php @@ -73,7 +73,7 @@ function check_cors() { $server_host = str_replace(array("[","]"), array("",""), $server_host); if(isset($_SERVER['HTTP_HOST']) && !in_array($server_host, $AUTHORIZED_HOSTNAMES)) { - log_and_die("Failed Host Check: " . $server_host .' vs '. join(', ', $AUTHORIZED_HOSTNAMES)); + log_and_die("Failed Host Check: " . $server_host .' vs '. htmlspecialchars(join(', ', $AUTHORIZED_HOSTNAMES))); } if(isset($_SERVER['HTTP_ORIGIN'])) { @@ -88,7 +88,7 @@ function check_cors() { $server_origin = str_replace(array("[","]","http://","https://"), array("","","",""), $server_origin); if(!in_array($server_origin, $AUTHORIZED_HOSTNAMES)) { - log_and_die("Failed CORS: " . htmlspecialchars($server_origin) .' vs '. join(', ', $AUTHORIZED_HOSTNAMES)); + log_and_die("Failed CORS: " . htmlspecialchars($server_origin) .' vs '. htmlspecialchars(join(', ', $AUTHORIZED_HOSTNAMES))); } header("Access-Control-Allow-Origin: ${_SERVER['HTTP_ORIGIN']}"); } diff --git a/admin/scripts/pi-hole/php/customcname.php b/admin/scripts/pi-hole/php/customcname.php index 060799e..a34a891 100644 --- a/admin/scripts/pi-hole/php/customcname.php +++ b/admin/scripts/pi-hole/php/customcname.php @@ -5,11 +5,13 @@ require_once('auth.php'); // Authentication checks - if (isset($_POST['token'])) { - check_cors(); - check_csrf($_POST['token']); - } else { - log_and_die('Not allowed (login session invalid or expired, please relogin on the Pi-hole dashboard)!'); + if (!isset($api)) { + if (isset($_POST['token'])) { + check_cors(); + check_csrf($_POST['token']); + } else { + log_and_die('Not allowed (login session invalid or expired, please relogin on the Pi-hole dashboard)!'); + } } diff --git a/admin/scripts/pi-hole/php/customdns.php b/admin/scripts/pi-hole/php/customdns.php index 196ca28..bfa2fd8 100644 --- a/admin/scripts/pi-hole/php/customdns.php +++ b/admin/scripts/pi-hole/php/customdns.php @@ -5,11 +5,13 @@ require_once('auth.php'); // Authentication checks - if (isset($_POST['token'])) { - check_cors(); - check_csrf($_POST['token']); - } else { - log_and_die('Not allowed (login session invalid or expired, please relogin on the Pi-hole dashboard)!'); + if (!isset($api)) { + if (isset($_POST['token'])) { + check_cors(); + check_csrf($_POST['token']); + } else { + log_and_die('Not allowed (login session invalid or expired, please relogin on the Pi-hole dashboard)!'); + } } diff --git a/admin/scripts/pi-hole/php/footer.php b/admin/scripts/pi-hole/php/footer.php index 34ee322..6a5aef5 100644 --- a/admin/scripts/pi-hole/php/footer.php +++ b/admin/scripts/pi-hole/php/footer.php @@ -41,7 +41,7 @@
diff --git a/admin/scripts/pi-hole/php/func.php b/admin/scripts/pi-hole/php/func.php index 754277b..10ad633 100644 --- a/admin/scripts/pi-hole/php/func.php +++ b/admin/scripts/pi-hole/php/func.php @@ -483,4 +483,31 @@ function getQueryTypeStr($querytype) return "TYPE".($qtype - 100); } +// Returns an integer representing pihole blocking status +function piholeStatus() +{ + // Receive the return of "pihole status web" + $pistatus = pihole_execute('status web'); + return isset($pistatus[0]) ? intval($pistatus[0]) : -2; +} + +// Returns pihole status, using only valid API responses (enabled/disabled) +function piholeStatusAPI() +{ + // Receive the return of "pihole status web" + $pistatus = piholeStatus(); + + switch ($pistatus) { + case -2: // Unkown + case -1: // DNS service not running" + case 0: // Offline + $response = "disabled"; + break; + + default: + // DNS service running on port $returncode + $response = "enabled"; + } + return $response; +} ?> diff --git a/admin/scripts/pi-hole/php/gravity.php b/admin/scripts/pi-hole/php/gravity.php index 6daa603..4852190 100644 --- a/admin/scripts/pi-hole/php/gravity.php +++ b/admin/scripts/pi-hole/php/gravity.php @@ -47,15 +47,15 @@ function gravity_last_update($raw = false) if($gravitydiff->d > 1) { // String output (more than one day ago) - return $gravitydiff->format("Blocking list updated %a days, %H:%I (hh:mm) ago"); + return $gravitydiff->format("Adlists updated %a days, %H:%I (hh:mm) ago"); } elseif($gravitydiff->d == 1) { // String output (one day ago) - return $gravitydiff->format("Blocking list updated one day, %H:%I (hh:mm) ago"); + return $gravitydiff->format("Adlists updated one day, %H:%I (hh:mm) ago"); } // String output (less than one day ago) - return $gravitydiff->format("Blocking list updated %H:%I (hh:mm) ago"); + return $gravitydiff->format("Adlists updated %H:%I (hh:mm) ago"); } ?> diff --git a/admin/scripts/pi-hole/php/header.php b/admin/scripts/pi-hole/php/header.php index 8b310cb..89c1bea 100644 --- a/admin/scripts/pi-hole/php/header.php +++ b/admin/scripts/pi-hole/php/header.php @@ -9,6 +9,7 @@ require "scripts/pi-hole/php/auth.php"; require "scripts/pi-hole/php/password.php"; require_once "scripts/pi-hole/php/FTL.php"; + require_once "scripts/pi-hole/php/func.php"; require "scripts/pi-hole/php/theme.php"; $scriptname = basename($_SERVER['SCRIPT_FILENAME']); $hostname = $_SERVER["SERVER_NAME"]; @@ -66,6 +67,8 @@ // Nothing can be colder than -273.15 degree Celsius (= 0 Kelvin) // This is the minimum temperature possible (AKA absolute zero) $celsius = -273.16; + // Set templimit to null if no tempsensor was found + $temperaturelimit = null; } // Get load @@ -314,19 +317,14 @@ function pidofFTL()

Status

Active'; } elseif ($pistatus == 0) { echo ' Offline'; } elseif ($pistatus == -1) { echo ' DNS service not running'; - } elseif ($pistatus == -2 || is_null($pistatus)) { + } elseif ($pistatus == -2) { echo ' Unknown'; } else { echo ' DNS service on port '.$pistatus.''; @@ -358,18 +356,16 @@ function pidofFTL() ?>
$temperaturelimit) { - $tempcolor = "text-red"; - } - echo ' '; - - if ($celsius >= -273.15) { + if ($celsius >= -273.15) { + // Only show temp info if any data is available --> + $tempcolor = "text-vivid-blue"; + if (isset($temperaturelimit) && $celsius > $temperaturelimit) { + $tempcolor = "text-red"; + } + echo ' '; echo 'Temp: '; - } else { - echo "No temp sensor found"; - } - echo ''; + echo ''; + } ?>
diff --git a/admin/scripts/pi-hole/php/queryads.php b/admin/scripts/pi-hole/php/queryads.php index 38d4e8d..535dc14 100644 --- a/admin/scripts/pi-hole/php/queryads.php +++ b/admin/scripts/pi-hole/php/queryads.php @@ -17,7 +17,7 @@ function echoEvent($datatext) { if(!isset($_GET["IE"])) - echo "data: ".implode("\ndata: ", explode("\n", $datatext))."\n\n"; + echo "data:".implode("\ndata:", explode("\n", $datatext))."\n\n"; else echo $datatext; } diff --git a/admin/scripts/pi-hole/php/teleporter.php b/admin/scripts/pi-hole/php/teleporter.php index d25f050..774d10c 100644 --- a/admin/scripts/pi-hole/php/teleporter.php +++ b/admin/scripts/pi-hole/php/teleporter.php @@ -84,11 +84,15 @@ function archive_restore_table($file, $table, $flush=false) if(is_null($contents)) return 0; - // Flush table if requested, only flush each table once + // Flush table if requested. Only flush each table once, and only if it exists if($flush && !in_array($table, $flushed_tables)) { - $db->exec("DELETE FROM \"".$table."\""); - array_push($flushed_tables, $table); + $tableExists = $db->querySingle("SELECT name FROM sqlite_master WHERE type='table' AND name='".$table."';"); + if ($tableExists) + { + $db->exec("DELETE FROM \"".$table."\""); + array_push($flushed_tables, $table); + } } // Prepare fields depending on the table we restore to @@ -337,18 +341,15 @@ function noun($num) $source = $_FILES["zip_file"]["tmp_name"]; $type = mime_content_type($source); - $name = explode(".", $filename); + // verify the file mime type $accepted_types = array('application/gzip', 'application/tar', 'application/x-compressed', 'application/x-gzip'); - $okay = false; - foreach($accepted_types as $mime_type) { - if($mime_type == $type) { - $okay = true; - break; - } - } + $mime_valid = in_array($type, $accepted_types); + + // verify the file extension (Looking for ".tar.gz" at the end of the file name) + $ext = array_slice(explode(".", $filename), -2, 2); + $ext_valid = strtolower($ext[0]) == "tar" && strtolower($ext[1]) == "gz" ? true : false; - $continue = strtolower($name[1]) == 'tar' && strtolower($name[2]) == 'gz' ? true : false; - if(!$continue || !$okay) { + if(!$ext_valid || !$mime_valid) { die("The file you are trying to upload is not a .tar.gz file (filename: ".htmlentities($filename).", type: ".htmlentities($type)."). Please try again."); } diff --git a/admin/settings.php b/admin/settings.php index 13018ea..e59b135 100644 --- a/admin/settings.php +++ b/admin/settings.php @@ -19,6 +19,12 @@ $error .= "There was a problem applying your settings.
Debugging information:
PHP error (".htmlspecialchars($last_error["type"])."): ".htmlspecialchars($last_error["message"])." in ".htmlspecialchars($last_error["file"]).":".htmlspecialchars($last_error["line"]); } +# Timezone is set in docker via ENV otherwise get it from commandline +$timezone=htmlspecialchars(getenv("TZ")); +if (empty($timezone)) { + $timezone=shell_exec("date +'%Z'"); +} + ?>