From 322d9207eb311c194e971d3e028acbc1b17e6e04 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Fri, 3 Jan 2020 19:52:58 +0000 Subject: [PATCH] Run phpcs to have Pi-hole's PHP code match the PSR-12 standard. Signed-off-by: DL6ER --- api.php | 198 ++-- api_FTL.php | 720 ++++++------- api_db.php | 654 ++++++------ db_graph.php | 2 +- db_lists.php | 13 +- db_queries.php | 2 +- debug.php | 2 +- help.php | 25 +- index.php | 39 +- list.php | 13 +- network.php | 2 +- queries.php | 93 +- queryads.php | 4 +- scripts/pi-hole/php/FTL.php | 84 +- scripts/pi-hole/php/add.php | 55 +- scripts/pi-hole/php/api_token.php | 28 +- scripts/pi-hole/php/auth.php | 81 +- scripts/pi-hole/php/customdns.php | 209 ++-- scripts/pi-hole/php/database.php | 428 ++++---- scripts/pi-hole/php/debug.php | 26 +- scripts/pi-hole/php/footer.php | 30 +- scripts/pi-hole/php/func.php | 25 +- scripts/pi-hole/php/get.php | 87 +- scripts/pi-hole/php/gravity.php | 83 +- scripts/pi-hole/php/gravity.sh.php | 17 +- scripts/pi-hole/php/groups.php | 6 +- scripts/pi-hole/php/header.php | 445 ++++---- scripts/pi-hole/php/loginpage.php | 26 +- scripts/pi-hole/php/password.php | 131 +-- scripts/pi-hole/php/queryads.php | 36 +- scripts/pi-hole/php/savesettings.php | 1363 +++++++++++------------- scripts/pi-hole/php/sub.php | 31 +- scripts/pi-hole/php/tailLog.php | 47 +- scripts/pi-hole/php/teleporter.php | 709 ++++++------ scripts/pi-hole/php/update_checker.php | 150 ++- settings.php | 347 ++++-- taillog-FTL.php | 2 +- taillog.php | 2 +- 38 files changed, 2952 insertions(+), 3263 deletions(-) diff --git a/api.php b/api.php index dff1ae297..8753bfcde 100644 --- a/api.php +++ b/api.php @@ -18,124 +18,98 @@ $data = array(); // Common API functions -if (isset($_GET['status'])) -{ - $pistatus = exec('sudo pihole status web'); - 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["auth"])) - { - if($_GET["auth"] !== $pwhash) - die("Not authorized!"); - } - else - { - // Skip token validation if explicit auth string is given - check_csrf($_GET['token']); - } - exec('sudo pihole enable'); - $data = array_merge($data, array("status" => "enabled")); - unlink("../custom_disable_timer"); -} -elseif (isset($_GET['disable']) && $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']); - } - $disable = intval($_GET['disable']); - // intval returns the integer value on success, or 0 on failure - if($disable > 0) - { - $timestamp = time(); - exec("sudo pihole disable ".$disable."s"); - file_put_contents("../custom_disable_timer",($timestamp+$disable)*1000); - } - else - { - exec('sudo pihole disable'); - unlink("../custom_disable_timer"); - } - $data = array_merge($data, array("status" => "disabled")); -} -elseif (isset($_GET['versions'])) -{ - // Determine if updates are available for Pi-hole - // using the same script that we use for the footer - // on the dashboard (update notifications are - // suppressed if on development branches) - require "scripts/pi-hole/php/update_checker.php"; - $updates = array("core_update" => $core_update, - "web_update" => $web_update, - "FTL_update" => $FTL_update); - $current = array("core_current" => $core_current, - "web_current" => $web_current, - "FTL_current" => $FTL_current); - $latest = array("core_latest" => $core_latest, - "web_latest" => $web_latest, - "FTL_latest" => $FTL_latest); - $branches = array("core_branch" => $core_branch, - "web_branch" => $web_branch, - "FTL_branch" => $FTL_branch); - $data = array_merge($data, $updates); - $data = array_merge($data, $current); - $data = array_merge($data, $latest); - $data = array_merge($data, $branches); -} -elseif (isset($_GET['list'])) -{ - if (isset($_GET['add'])) - { - if (!$auth) - die("Not authorized!"); +if (isset($_GET['status'])) { + $pistatus = exec('sudo pihole status web'); + 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["auth"])) { + if ($_GET["auth"] !== $pwhash) { + die("Not authorized!"); + } + } else { + // Skip token validation if explicit auth string is given + check_csrf($_GET['token']); + } + exec('sudo pihole enable'); + $data = array_merge($data, array("status" => "enabled")); + unlink("../custom_disable_timer"); +} elseif (isset($_GET['disable']) && $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']); + } + $disable = intval($_GET['disable']); + // intval returns the integer value on success, or 0 on failure + if ($disable > 0) { + $timestamp = time(); + exec("sudo pihole disable " . $disable . "s"); + file_put_contents("../custom_disable_timer", ($timestamp + $disable) * 1000); + } else { + exec('sudo pihole disable'); + unlink("../custom_disable_timer"); + } + $data = array_merge($data, array("status" => "disabled")); +} elseif (isset($_GET['versions'])) { + // Determine if updates are available for Pi-hole + // using the same script that we use for the footer + // on the dashboard (update notifications are + // suppressed if on development branches) + require "scripts/pi-hole/php/update_checker.php"; + $updates = array("core_update" => $core_update, + "web_update" => $web_update, + "FTL_update" => $FTL_update); + $current = array("core_current" => $core_current, + "web_current" => $web_current, + "FTL_current" => $FTL_current); + $latest = array("core_latest" => $core_latest, + "web_latest" => $web_latest, + "FTL_latest" => $FTL_latest); + $branches = array("core_branch" => $core_branch, + "web_branch" => $web_branch, + "FTL_branch" => $FTL_branch); + $data = array_merge($data, $updates); + $data = array_merge($data, $current); + $data = array_merge($data, $latest); + $data = array_merge($data, $branches); +} elseif (isset($_GET['list'])) { + if (isset($_GET['add'])) { + if (!$auth) { + die("Not authorized!"); + } - // Set POST parameters and invoke script to add domain to list - $_POST['domain'] = $_GET['add']; - $_POST['list'] = $_GET['list']; - require("scripts/pi-hole/php/add.php"); - } - elseif (isset($_GET['sub'])) - { - if (!$auth) - die("Not authorized!"); + // Set POST parameters and invoke script to add domain to list + $_POST['domain'] = $_GET['add']; + $_POST['list'] = $_GET['list']; + require("scripts/pi-hole/php/add.php"); + } elseif (isset($_GET['sub'])) { + if (!$auth) { + die("Not authorized!"); + } - // Set POST parameters and invoke script to remove domain from list - $_POST['domain'] = $_GET['sub']; - $_POST['list'] = $_GET['list']; - require("scripts/pi-hole/php/sub.php"); - } - else - { - require("scripts/pi-hole/php/get.php"); - } + // Set POST parameters and invoke script to remove domain from list + $_POST['domain'] = $_GET['sub']; + $_POST['list'] = $_GET['list']; + require("scripts/pi-hole/php/sub.php"); + } else { + require("scripts/pi-hole/php/get.php"); + } - return; + return; } // Other API functions require("api_FTL.php"); -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/api_FTL.php b/api_FTL.php index f1a882d66..8bb0edc7e 100644 --- a/api_FTL.php +++ b/api_FTL.php @@ -7,410 +7,328 @@ * Please see LICENSE file for your rights under this license */ -if(!isset($api)) -{ - die("Direct call to api_FTL.php is not allowed!"); +if (!isset($api)) { + die("Direct call to api_FTL.php is not allowed!"); } // $FTL_IP is defined in api.php $socket = connectFTL($FTL_IP); -if(!is_resource($socket)) -{ - $data = array_merge($data, array("FTLnotrunning" => true)); +if (!is_resource($socket)) { + $data = array_merge($data, array("FTLnotrunning" => true)); +} else { + if (isset($_GET['type'])) { + $data["type"] = "FTL"; + } + + if (isset($_GET['version'])) { + $data["version"] = 3; + } + + 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) { + $tmp = explode(" ", $line); + + if (($tmp[0] === "domains_being_blocked" && !is_numeric($tmp[1])) || $tmp[0] === "status") { + $stats[$tmp[0]] = $tmp[1]; + continue; + } + + if (isset($_GET['summary'])) { + if ($tmp[0] !== "ads_percentage_today") { + $stats[$tmp[0]] = number_format($tmp[1]); + } else { + $stats[$tmp[0]] = number_format($tmp[1], 1, '.', ''); + } + } else { + $stats[$tmp[0]] = floatval($tmp[1]); + } + } + $stats['gravity_last_updated'] = gravity_last_update(true); + $data = array_merge($data, $stats); + } + + if (isset($_GET['overTimeData10mins'])) { + sendRequestFTL("overTime"); + $return = getResponseFTL(); + + $domains_over_time = array(); + $ads_over_time = array(); + foreach ($return as $line) { + $tmp = explode(" ", $line); + $domains_over_time[intval($tmp[0])] = intval($tmp[1]); + $ads_over_time[intval($tmp[0])] = intval($tmp[2]); + } + $result = array('domains_over_time' => $domains_over_time, + 'ads_over_time' => $ads_over_time); + $data = array_merge($data, $result); + } + + if (isset($_GET['topItems']) && $auth) { + if ($_GET['topItems'] === "audit") { + sendRequestFTL("top-domains for audit"); + } elseif (is_numeric($_GET['topItems'])) { + sendRequestFTL("top-domains (" . $_GET['topItems'] . ")"); + } else { + sendRequestFTL("top-domains"); + } + + $return = getResponseFTL(); + $top_queries = array(); + foreach ($return as $line) { + $tmp = explode(" ", $line); + $domain = utf8_encode($tmp[2]); + $top_queries[$domain] = intval($tmp[1]); + } + + if ($_GET['topItems'] === "audit") { + sendRequestFTL("top-ads for audit"); + } elseif (is_numeric($_GET['topItems'])) { + sendRequestFTL("top-ads (" . $_GET['topItems'] . ")"); + } else { + sendRequestFTL("top-ads"); + } + + $return = getResponseFTL(); + $top_ads = array(); + foreach ($return as $line) { + $tmp = explode(" ", $line); + $domain = utf8_encode($tmp[2]); + if (count($tmp) > 3) { + $top_ads[$domain . " (" . $tmp[3] . ")"] = intval($tmp[1]); + } else { + $top_ads[$domain] = intval($tmp[1]); + } + } + + $result = array('top_queries' => $top_queries, + 'top_ads' => $top_ads); + + $data = array_merge($data, $result); + } + + if ((isset($_GET['topClients']) || isset($_GET['getQuerySources'])) && $auth) { + if (isset($_GET['topClients'])) { + $number = $_GET['topClients']; + } elseif (isset($_GET['getQuerySources'])) { + $number = $_GET['getQuerySources']; + } + + if (is_numeric($number)) { + sendRequestFTL("top-clients (" . $number . ")"); + } else { + sendRequestFTL("top-clients"); + } + + $return = getResponseFTL(); + $top_clients = array(); + foreach ($return as $line) { + $tmp = explode(" ", $line); + $clientip = utf8_encode($tmp[2]); + if (count($tmp) > 3 && strlen($tmp[3]) > 0) { + $clientname = utf8_encode($tmp[3]); + $top_clients[$clientname . "|" . $clientip] = intval($tmp[1]); + } else { + $top_clients[$clientip] = intval($tmp[1]); + } + } + + $result = array('top_sources' => $top_clients); + $data = array_merge($data, $result); + } + + if (isset($_GET['topClientsBlocked']) && $auth) { + if (isset($_GET['topClientsBlocked'])) { + $number = $_GET['topClientsBlocked']; + } + + if (is_numeric($number)) { + sendRequestFTL("top-clients blocked (" . $number . ")"); + } else { + sendRequestFTL("top-clients blocked"); + } + + $return = getResponseFTL(); + $top_clients = array(); + foreach ($return as $line) { + $tmp = explode(" ", $line); + $clientip = utf8_encode($tmp[2]); + if (count($tmp) > 3 && strlen($tmp[3]) > 0) { + $clientname = utf8_encode($tmp[3]); + $top_clients[$clientname . "|" . $clientip] = intval($tmp[1]); + } else { + $top_clients[$clientip] = intval($tmp[1]); + } + } + + $result = array('top_sources_blocked' => $top_clients); + $data = array_merge($data, $result); + } + + if (isset($_GET['getForwardDestinations']) && $auth) { + if ($_GET['getForwardDestinations'] === "unsorted") { + sendRequestFTL("forward-dest unsorted"); + } else { + sendRequestFTL("forward-dest"); + } + $return = getResponseFTL(); + $forward_dest = array(); + foreach ($return as $line) { + $tmp = explode(" ", $line); + $forwardip = utf8_encode($tmp[2]); + if (count($tmp) > 3 && strlen($tmp[3]) > 0) { + $forwardname = utf8_encode($tmp[3]); + $forward_dest[$forwardname . "|" . $forwardip] = floatval($tmp[1]); + } else { + $forward_dest[$forwardip] = floatval($tmp[1]); + } + } + + $result = array('forward_destinations' => $forward_dest); + $data = array_merge($data, $result); + } + + if (isset($_GET['getQueryTypes']) && $auth) { + sendRequestFTL("querytypes"); + $return = getResponseFTL(); + $querytypes = array(); + foreach ($return as $ret) { + $tmp = explode(": ", $ret); + // Reply cannot contain non-ASCII characters + $querytypes[$tmp[0]] = floatval($tmp[1]); + } + + $result = array('querytypes' => $querytypes); + $data = array_merge($data, $result); + } + + if (isset($_GET['getCacheInfo']) && $auth) { + sendRequestFTL("cacheinfo"); + $return = getResponseFTL(); + $cacheinfo = array(); + foreach ($return as $ret) { + $tmp = explode(": ", $ret); + // Reply cannot contain non-ASCII characters + $cacheinfo[$tmp[0]] = floatval($tmp[1]); + } + + $result = array('cacheinfo' => $cacheinfo); + $data = array_merge($data, $result); + } + + if (isset($_GET['getAllQueries']) && $auth) { + if (isset($_GET['from']) && isset($_GET['until'])) { + // Get limited time interval + sendRequestFTL("getallqueries-time " . $_GET['from'] . " " . $_GET['until']); + } elseif (isset($_GET['domain'])) { + // Get specific domain only + sendRequestFTL("getallqueries-domain " . $_GET['domain']); + } elseif (isset($_GET['client'])) { + // Get specific client only + sendRequestFTL("getallqueries-client " . $_GET['client']); + } elseif (isset($_GET['querytype'])) { + // Get specific query type only + sendRequestFTL("getallqueries-qtype " . $_GET['querytype']); + } elseif (isset($_GET['forwarddest'])) { + // Get specific forward destination only + sendRequestFTL("getallqueries-forward " . $_GET['forwarddest']); + } elseif (is_numeric($_GET['getAllQueries'])) { + sendRequestFTL("getallqueries (" . $_GET['getAllQueries'] . ")"); + } else { + // Get all queries + sendRequestFTL("getallqueries"); + } + $return = getResponseFTL(); + $allQueries = array(); + foreach ($return as $line) { + $tmp = explode(" ", $line); + // UTF-8 encode domain + $tmp[2] = utf8_encode($tmp[2]); + // UTF-8 encode client host name + $tmp[3] = utf8_encode($tmp[3]); + ; + array_push($allQueries, $tmp); + } + + $result = array('data' => $allQueries); + $data = array_merge($data, $result); + } + + if (isset($_GET["recentBlocked"])) { + sendRequestFTL("recentBlocked"); + die(utf8_encode(getResponseFTL()[0])); + unset($data); + } + + if (isset($_GET['getForwardDestinationNames']) && $auth) { + sendRequestFTL("forward-names"); + $return = getResponseFTL(); + $forward_dest = array(); + foreach ($return as $line) { + $tmp = explode(" ", $line); + $forwardip = utf8_encode($tmp[2]); + if (count($tmp) > 3) { + $forwardname = utf8_encode($tmp[3]); + $forward_dest[$forwardname . "|" . $forwardip] = floatval($tmp[1]); + } else { + $forward_dest[$forwardip] = floatval($tmp[1]); + } + } + + $result = array('forward_destinations' => $forward_dest); + $data = array_merge($data, $result); + } + + if (isset($_GET['overTimeDataQueryTypes']) && $auth) { + sendRequestFTL("QueryTypesoverTime"); + $return = getResponseFTL(); + $over_time = array(); + + foreach ($return as $line) { + $tmp = explode(" ", $line); + for ($i = 0; $i < count($tmp) - 1; $i++) { + $over_time[intval($tmp[0])][$i] = floatval($tmp[$i + 1]); + } + } + $result = array('over_time' => $over_time); + $data = array_merge($data, $result); + } + + if (isset($_GET['getClientNames']) && $auth) { + sendRequestFTL("client-names"); + $return = getResponseFTL(); + $client_names = array(); + foreach ($return as $line) { + $tmp = explode(" ", $line); + $client_names[] = array( + "name" => utf8_encode($tmp[0]), + "ip" => utf8_encode($tmp[1]) + ); + } + + $result = array('clients' => $client_names); + $data = array_merge($data, $result); + } + + if (isset($_GET['overTimeDataClients']) && $auth) { + sendRequestFTL("ClientsoverTime"); + $return = getResponseFTL(); + $over_time = array(); + + foreach ($return as $line) { + $tmp = explode(" ", $line); + for ($i = 0; $i < count($tmp) - 1; $i++) { + $over_time[intval($tmp[0])][$i] = floatval($tmp[$i + 1]); + } + } + $result = array('over_time' => $over_time); + $data = array_merge($data, $result); + } + + disconnectFTL(); } -else -{ - if (isset($_GET['type'])) { - $data["type"] = "FTL"; - } - - if (isset($_GET['version'])) { - $data["version"] = 3; - } - - 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) - { - $tmp = explode(" ",$line); - - if(($tmp[0] === "domains_being_blocked" && !is_numeric($tmp[1])) || $tmp[0] === "status") - { - $stats[$tmp[0]] = $tmp[1]; - continue; - } - - if(isset($_GET['summary'])) - { - if($tmp[0] !== "ads_percentage_today") - { - $stats[$tmp[0]] = number_format($tmp[1]); - } - else - { - $stats[$tmp[0]] = number_format($tmp[1], 1, '.', ''); - } - } - else - { - $stats[$tmp[0]] = floatval($tmp[1]); - } - } - $stats['gravity_last_updated'] = gravity_last_update(true); - $data = array_merge($data,$stats); - } - - if (isset($_GET['overTimeData10mins'])) - { - sendRequestFTL("overTime"); - $return = getResponseFTL(); - - $domains_over_time = array(); - $ads_over_time = array(); - foreach($return as $line) - { - $tmp = explode(" ",$line); - $domains_over_time[intval($tmp[0])] = intval($tmp[1]); - $ads_over_time[intval($tmp[0])] = intval($tmp[2]); - } - $result = array('domains_over_time' => $domains_over_time, - 'ads_over_time' => $ads_over_time); - $data = array_merge($data, $result); - } - - if (isset($_GET['topItems']) && $auth) - { - if($_GET['topItems'] === "audit") - { - sendRequestFTL("top-domains for audit"); - } - else if(is_numeric($_GET['topItems'])) - { - sendRequestFTL("top-domains (".$_GET['topItems'].")"); - } - else - { - sendRequestFTL("top-domains"); - } - - $return = getResponseFTL(); - $top_queries = array(); - foreach($return as $line) - { - $tmp = explode(" ",$line); - $domain = utf8_encode($tmp[2]); - $top_queries[$domain] = intval($tmp[1]); - } - - if($_GET['topItems'] === "audit") - { - sendRequestFTL("top-ads for audit"); - } - else if(is_numeric($_GET['topItems'])) - { - sendRequestFTL("top-ads (".$_GET['topItems'].")"); - } - else - { - sendRequestFTL("top-ads"); - } - - $return = getResponseFTL(); - $top_ads = array(); - foreach($return as $line) - { - $tmp = explode(" ",$line); - $domain = utf8_encode($tmp[2]); - if(count($tmp) > 3) - $top_ads[$domain." (".$tmp[3].")"] = intval($tmp[1]); - else - $top_ads[$domain] = intval($tmp[1]); - } - - $result = array('top_queries' => $top_queries, - 'top_ads' => $top_ads); - - $data = array_merge($data, $result); - } - - if ((isset($_GET['topClients']) || isset($_GET['getQuerySources'])) && $auth) - { - - if(isset($_GET['topClients'])) - { - $number = $_GET['topClients']; - } - elseif(isset($_GET['getQuerySources'])) - { - $number = $_GET['getQuerySources']; - } - - if(is_numeric($number)) - { - sendRequestFTL("top-clients (".$number.")"); - } - else - { - sendRequestFTL("top-clients"); - } - - $return = getResponseFTL(); - $top_clients = array(); - foreach($return as $line) - { - $tmp = explode(" ",$line); - $clientip = utf8_encode($tmp[2]); - if(count($tmp) > 3 && strlen($tmp[3]) > 0) - { - $clientname = utf8_encode($tmp[3]); - $top_clients[$clientname."|".$clientip] = intval($tmp[1]); - } - else - $top_clients[$clientip] = intval($tmp[1]); - } - - $result = array('top_sources' => $top_clients); - $data = array_merge($data, $result); - } - - if (isset($_GET['topClientsBlocked']) && $auth) - { - - if(isset($_GET['topClientsBlocked'])) - { - $number = $_GET['topClientsBlocked']; - } - - if(is_numeric($number)) - { - sendRequestFTL("top-clients blocked (".$number.")"); - } - else - { - sendRequestFTL("top-clients blocked"); - } - - $return = getResponseFTL(); - $top_clients = array(); - foreach($return as $line) - { - $tmp = explode(" ",$line); - $clientip = utf8_encode($tmp[2]); - if(count($tmp) > 3 && strlen($tmp[3]) > 0) - { - $clientname = utf8_encode($tmp[3]); - $top_clients[$clientname."|".$clientip] = intval($tmp[1]); - } - else - $top_clients[$clientip] = intval($tmp[1]); - } - - $result = array('top_sources_blocked' => $top_clients); - $data = array_merge($data, $result); - } - - if (isset($_GET['getForwardDestinations']) && $auth) - { - if($_GET['getForwardDestinations'] === "unsorted") - { - sendRequestFTL("forward-dest unsorted"); - } - else - { - sendRequestFTL("forward-dest"); - } - $return = getResponseFTL(); - $forward_dest = array(); - foreach($return as $line) - { - $tmp = explode(" ",$line); - $forwardip = utf8_encode($tmp[2]); - if(count($tmp) > 3 && strlen($tmp[3]) > 0) - { - $forwardname = utf8_encode($tmp[3]); - $forward_dest[$forwardname."|".$forwardip] = floatval($tmp[1]); - } - else - $forward_dest[$forwardip] = floatval($tmp[1]); - } - - $result = array('forward_destinations' => $forward_dest); - $data = array_merge($data, $result); - } - - if (isset($_GET['getQueryTypes']) && $auth) - { - sendRequestFTL("querytypes"); - $return = getResponseFTL(); - $querytypes = array(); - foreach($return as $ret) - { - $tmp = explode(": ",$ret); - // Reply cannot contain non-ASCII characters - $querytypes[$tmp[0]] = floatval($tmp[1]); - } - - $result = array('querytypes' => $querytypes); - $data = array_merge($data, $result); - } - - if (isset($_GET['getCacheInfo']) && $auth) - { - sendRequestFTL("cacheinfo"); - $return = getResponseFTL(); - $cacheinfo = array(); - foreach($return as $ret) - { - $tmp = explode(": ",$ret); - // Reply cannot contain non-ASCII characters - $cacheinfo[$tmp[0]] = floatval($tmp[1]); - } - - $result = array('cacheinfo' => $cacheinfo); - $data = array_merge($data, $result); - } - - if (isset($_GET['getAllQueries']) && $auth) - { - if(isset($_GET['from']) && isset($_GET['until'])) - { - // Get limited time interval - sendRequestFTL("getallqueries-time ".$_GET['from']." ".$_GET['until']); - } - else if(isset($_GET['domain'])) - { - // Get specific domain only - sendRequestFTL("getallqueries-domain ".$_GET['domain']); - } - else if(isset($_GET['client'])) - { - // Get specific client only - sendRequestFTL("getallqueries-client ".$_GET['client']); - } - else if(isset($_GET['querytype'])) - { - // Get specific query type only - sendRequestFTL("getallqueries-qtype ".$_GET['querytype']); - } - else if(isset($_GET['forwarddest'])) - { - // Get specific forward destination only - sendRequestFTL("getallqueries-forward ".$_GET['forwarddest']); - } - else if(is_numeric($_GET['getAllQueries'])) - { - sendRequestFTL("getallqueries (".$_GET['getAllQueries'].")"); - } - else - { - // Get all queries - sendRequestFTL("getallqueries"); - } - $return = getResponseFTL(); - $allQueries = array(); - foreach($return as $line) - { - $tmp = explode(" ",$line); - // UTF-8 encode domain - $tmp[2] = utf8_encode($tmp[2]); - // UTF-8 encode client host name - $tmp[3] = utf8_encode($tmp[3]);; - array_push($allQueries,$tmp); - } - - $result = array('data' => $allQueries); - $data = array_merge($data, $result); - } - - if(isset($_GET["recentBlocked"])) - { - sendRequestFTL("recentBlocked"); - die(utf8_encode(getResponseFTL()[0])); - unset($data); - } - - if (isset($_GET['getForwardDestinationNames']) && $auth) - { - sendRequestFTL("forward-names"); - $return = getResponseFTL(); - $forward_dest = array(); - foreach($return as $line) - { - $tmp = explode(" ",$line); - $forwardip = utf8_encode($tmp[2]); - if(count($tmp) > 3) - { - $forwardname = utf8_encode($tmp[3]); - $forward_dest[$forwardname."|".$forwardip] = floatval($tmp[1]); - } - else - { - $forward_dest[$forwardip] = floatval($tmp[1]); - } - } - - $result = array('forward_destinations' => $forward_dest); - $data = array_merge($data, $result); - } - - if (isset($_GET['overTimeDataQueryTypes']) && $auth) - { - sendRequestFTL("QueryTypesoverTime"); - $return = getResponseFTL(); - $over_time = array(); - - foreach($return as $line) - { - $tmp = explode(" ",$line); - for ($i=0; $i < count($tmp)-1; $i++) { - $over_time[intval($tmp[0])][$i] = floatval($tmp[$i+1]); - } - } - $result = array('over_time' => $over_time); - $data = array_merge($data, $result); - } - - if (isset($_GET['getClientNames']) && $auth) - { - sendRequestFTL("client-names"); - $return = getResponseFTL(); - $client_names = array(); - foreach($return as $line) - { - $tmp = explode(" ", $line); - $client_names[] = array( - "name" => utf8_encode($tmp[0]), - "ip" => utf8_encode($tmp[1]) - ); - } - - $result = array('clients' => $client_names); - $data = array_merge($data, $result); - } - - if (isset($_GET['overTimeDataClients']) && $auth) - { - sendRequestFTL("ClientsoverTime"); - $return = getResponseFTL(); - $over_time = array(); - - foreach($return as $line) - { - $tmp = explode(" ",$line); - for ($i=0; $i < count($tmp)-1; $i++) { - $over_time[intval($tmp[0])][$i] = floatval($tmp[$i+1]); - } - } - $result = array('over_time' => $over_time); - $data = array_merge($data, $result); - } - - disconnectFTL(); -} -?> diff --git a/api_db.php b/api_db.php index a0247402f..68a9b82a7 100644 --- a/api_db.php +++ b/api_db.php @@ -14,39 +14,35 @@ check_cors(); // Set maximum execution time to 10 minutes -ini_set("max_execution_time","600"); +ini_set("max_execution_time", "600"); $data = array(); $clients = array(); function resolveHostname($clientip, $printIP) { - global $clients; - $ipaddr = strtolower($clientip); - if(array_key_exists($clientip, $clients)) - { - // Entry already exists - $clientname = $clients[$ipaddr]; - if($printIP) - return $clientname."|".$clientip; - return $clientname; - } - - else if(filter_var($clientip, FILTER_VALIDATE_IP)) - { - // Get host name of client and convert to lower case - $clientname = strtolower(gethostbyaddr($ipaddr)); - } - else - { - // This is already a host name - $clientname = $ipaddr; - } - // Buffer result - $clients[$ipaddr] = $clientname; - - if($printIP) - return $clientname."|".$clientip; - return $clientname; + global $clients; + $ipaddr = strtolower($clientip); + if (array_key_exists($clientip, $clients)) { + // Entry already exists + $clientname = $clients[$ipaddr]; + if ($printIP) { + return $clientname . "|" . $clientip; + } + return $clientname; + } elseif (filter_var($clientip, FILTER_VALIDATE_IP)) { + // Get host name of client and convert to lower case + $clientname = strtolower(gethostbyaddr($ipaddr)); + } else { + // This is already a host name + $clientname = $ipaddr; + } + // Buffer result + $clients[$ipaddr] = $clientname; + + if ($printIP) { + return $clientname . "|" . $clientip; + } + return $clientname; } // Needs package php5-sqlite, e.g. @@ -55,351 +51,311 @@ function resolveHostname($clientip, $printIP) $QUERYDB = getQueriesDBFilename(); $db = SQLite3_connect($QUERYDB); -if(isset($_GET["network"]) && $auth) -{ - $network = array(); - $results = $db->query('SELECT * FROM network'); - - while($results !== false && $res = $results->fetchArray(SQLITE3_ASSOC)) - { - $id = $res["id"]; - // Empty array for holding the IP addresses - $res["ip"] = array(); - // Get IP addresses for this device - $network_addresses = $db->query("SELECT ip FROM network_addresses WHERE network_id = $id ORDER BY lastSeen DESC"); - while($network_addresses !== false && $ip = $network_addresses->fetchArray(SQLITE3_ASSOC)) - array_push($res["ip"],$ip["ip"]); - // UTF-8 encode host name and vendor - $res["name"] = utf8_encode($res["name"]); - $res["macVendor"] = utf8_encode($res["macVendor"]); - array_push($network, $res); - } - - $data = array_merge($data, array('network' => $network)); +if (isset($_GET["network"]) && $auth) { + $network = array(); + $results = $db->query('SELECT * FROM network'); + + while ($results !== false && $res = $results->fetchArray(SQLITE3_ASSOC)) { + $id = $res["id"]; + // Empty array for holding the IP addresses + $res["ip"] = array(); + // Get IP addresses for this device + $network_addresses = $db->query("SELECT ip FROM network_addresses WHERE network_id = $id ORDER BY lastSeen DESC"); + while ($network_addresses !== false && $ip = $network_addresses->fetchArray(SQLITE3_ASSOC)) { + array_push($res["ip"], $ip["ip"]); + } + // UTF-8 encode host name and vendor + $res["name"] = utf8_encode($res["name"]); + $res["macVendor"] = utf8_encode($res["macVendor"]); + array_push($network, $res); + } + + $data = array_merge($data, array('network' => $network)); } -if (isset($_GET['getAllQueries']) && $auth) -{ - $allQueries = array(); - if($_GET['getAllQueries'] !== "empty") - { - $from = intval($_GET["from"]); - $until = intval($_GET["until"]); - $dbquery = "SELECT timestamp, type, domain, client, status FROM queries WHERE timestamp >= :from AND timestamp <= :until "; - if(isset($_GET["types"])) - { - $types = $_GET["types"]; - if(preg_match("/^[0-9]+(?:,[0-9]+)*$/", $types) === 1) - { - // Append selector to DB query. The used regex ensures - // that only numbers, separated by commas are accepted - // to avoid code injection and other malicious things - // We accept only valid lists like "1,2,3" - // We reject ",2,3", "1,2," and similar arguments - $dbquery .= "AND status IN (".$types.") "; - } - else - { - die("Error. Selector types specified using an invalid format."); - } - } - $dbquery .= "ORDER BY timestamp ASC"; - $stmt = $db->prepare($dbquery); - $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()) - { - $c = resolveHostname($row[3],false); - - // Convert query type ID to name - // Names taken from FTL's query type names - switch($row[1]) { - case 1: - $query_type = "A"; - break; - case 2: - $query_type = "AAAA"; - break; - case 3: - $query_type = "ANY"; - break; - case 4: - $query_type = "SRV"; - break; - case 5: - $query_type = "SOA"; - break; - case 6: - $query_type = "PTR"; - break; - case 7: - $query_type = "TXT"; - break; - default: - $query_type = "UNKN"; - break; - } - // array: time type domain client status - $allQueries[] = [$row[0], $query_type, utf8_encode($row[2]), utf8_encode($c), $row[4]]; - } - } - $result = array('data' => $allQueries); - $data = array_merge($data, $result); +if (isset($_GET['getAllQueries']) && $auth) { + $allQueries = array(); + if ($_GET['getAllQueries'] !== "empty") { + $from = intval($_GET["from"]); + $until = intval($_GET["until"]); + $dbquery = "SELECT timestamp, type, domain, client, status FROM queries WHERE timestamp >= :from AND timestamp <= :until "; + if (isset($_GET["types"])) { + $types = $_GET["types"]; + if (preg_match("/^[0-9]+(?:,[0-9]+)*$/", $types) === 1) { + // Append selector to DB query. The used regex ensures + // that only numbers, separated by commas are accepted + // to avoid code injection and other malicious things + // We accept only valid lists like "1,2,3" + // We reject ",2,3", "1,2," and similar arguments + $dbquery .= "AND status IN (" . $types . ") "; + } else { + die("Error. Selector types specified using an invalid format."); + } + } + $dbquery .= "ORDER BY timestamp ASC"; + $stmt = $db->prepare($dbquery); + $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()) { + $c = resolveHostname($row[3], false); + + // Convert query type ID to name + // Names taken from FTL's query type names + switch ($row[1]) { + case 1: + $query_type = "A"; + break; + case 2: + $query_type = "AAAA"; + break; + case 3: + $query_type = "ANY"; + break; + case 4: + $query_type = "SRV"; + break; + case 5: + $query_type = "SOA"; + break; + case 6: + $query_type = "PTR"; + break; + case 7: + $query_type = "TXT"; + break; + default: + $query_type = "UNKN"; + break; + } + // array: time type domain client status + $allQueries[] = [$row[0], $query_type, utf8_encode($row[2]), utf8_encode($c), $row[4]]; + } + } + } + $result = array('data' => $allQueries); + $data = array_merge($data, $result); } -if (isset($_GET['topClients']) && $auth) -{ - // $from = intval($_GET["from"]); - $limit = ""; - if(isset($_GET["from"]) && isset($_GET["until"])) - { - $limit = "WHERE timestamp >= :from AND timestamp <= :until"; - } - elseif(isset($_GET["from"]) && !isset($_GET["until"])) - { - $limit = "WHERE timestamp >= :from"; - } - elseif(!isset($_GET["from"]) && isset($_GET["until"])) - { - $limit = "WHERE timestamp <= :until"; - } - $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(); - - $clientnums = array(); - - if(!is_bool($results)) - while ($row = $results->fetchArray()) - { - // Try to resolve host name and convert to UTF-8 - $c = utf8_encode(resolveHostname($row[0],false)); - - if(array_key_exists($c, $clientnums)) - { - // Entry already exists, add to it (might appear multiple times due to mixed capitalization in the database) - $clientnums[$c] += intval($row[1]); - } - else - { - // Entry does not yet exist - $clientnums[$c] = intval($row[1]); - } - } - - // Sort by number of hits - arsort($clientnums); - - // Extract only the first ten entries - $clientnums = array_slice($clientnums, 0, 10); - - $result = array('top_sources' => $clientnums); - $data = array_merge($data, $result); +if (isset($_GET['topClients']) && $auth) { + // $from = intval($_GET["from"]); + $limit = ""; + if (isset($_GET["from"]) && isset($_GET["until"])) { + $limit = "WHERE timestamp >= :from AND timestamp <= :until"; + } elseif (isset($_GET["from"]) && !isset($_GET["until"])) { + $limit = "WHERE timestamp >= :from"; + } elseif (!isset($_GET["from"]) && isset($_GET["until"])) { + $limit = "WHERE timestamp <= :until"; + } + $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(); + + $clientnums = array(); + + if (!is_bool($results)) { + while ($row = $results->fetchArray()) { + // Try to resolve host name and convert to UTF-8 + $c = utf8_encode(resolveHostname($row[0], false)); + + if (array_key_exists($c, $clientnums)) { + // Entry already exists, add to it (might appear multiple times due to mixed capitalization in the database) + $clientnums[$c] += intval($row[1]); + } else { + // Entry does not yet exist + $clientnums[$c] = intval($row[1]); + } + } + } + + // Sort by number of hits + arsort($clientnums); + + // Extract only the first ten entries + $clientnums = array_slice($clientnums, 0, 10); + + $result = array('top_sources' => $clientnums); + $data = array_merge($data, $result); } -if (isset($_GET['topDomains']) && $auth) -{ - $limit = ""; - - if(isset($_GET["from"]) && isset($_GET["until"])) - { - $limit = " AND timestamp >= :from AND timestamp <= :until"; - } - elseif(isset($_GET["from"]) && !isset($_GET["until"])) - { - $limit = " AND timestamp >= :from"; - } - elseif(!isset($_GET["from"]) && isset($_GET["until"])) - { - $limit = " AND timestamp <= :until"; - } - $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(); - - if(!is_bool($results)) - while ($row = $results->fetchArray()) - { - // Convert domain to lower case UTF-8 - $c = utf8_encode(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); +if (isset($_GET['topDomains']) && $auth) { + $limit = ""; + + if (isset($_GET["from"]) && isset($_GET["until"])) { + $limit = " AND timestamp >= :from AND timestamp <= :until"; + } elseif (isset($_GET["from"]) && !isset($_GET["until"])) { + $limit = " AND timestamp >= :from"; + } elseif (!isset($_GET["from"]) && isset($_GET["until"])) { + $limit = " AND timestamp <= :until"; + } + $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(); + + if (!is_bool($results)) { + while ($row = $results->fetchArray()) { + // Convert domain to lower case UTF-8 + $c = utf8_encode(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); } -if (isset($_GET['topAds']) && $auth) -{ - $limit = ""; - - if(isset($_GET["from"]) && isset($_GET["until"])) - { - $limit = " AND timestamp >= :from AND timestamp <= :until"; - } - elseif(isset($_GET["from"]) && !isset($_GET["until"])) - { - $limit = " AND timestamp >= :from"; - } - elseif(!isset($_GET["from"]) && isset($_GET["until"])) - { - $limit = " AND timestamp <= :until"; - } - $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(); - - if(!is_bool($results)) - while ($row = $results->fetchArray()) - { - $addomains[utf8_encode($row[0])] = intval($row[1]); - } - $result = array('top_ads' => $addomains); - $data = array_merge($data, $result); +if (isset($_GET['topAds']) && $auth) { + $limit = ""; + + if (isset($_GET["from"]) && isset($_GET["until"])) { + $limit = " AND timestamp >= :from AND timestamp <= :until"; + } elseif (isset($_GET["from"]) && !isset($_GET["until"])) { + $limit = " AND timestamp >= :from"; + } elseif (!isset($_GET["from"]) && isset($_GET["until"])) { + $limit = " AND timestamp <= :until"; + } + $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(); + + if (!is_bool($results)) { + while ($row = $results->fetchArray()) { + $addomains[utf8_encode($row[0])] = intval($row[1]); + } + } + $result = array('top_ads' => $addomains); + $data = array_merge($data, $result); } -if (isset($_GET['getMinTimestamp']) && $auth) -{ - $results = $db->query('SELECT MIN(timestamp) FROM queries'); +if (isset($_GET['getMinTimestamp']) && $auth) { + $results = $db->query('SELECT MIN(timestamp) FROM queries'); - if(!is_bool($results)) - $result = array('mintimestamp' => $results->fetchArray()[0]); - else - $result = array(); + if (!is_bool($results)) { + $result = array('mintimestamp' => $results->fetchArray()[0]); + } else { + $result = array(); + } - $data = array_merge($data, $result); + $data = array_merge($data, $result); } -if (isset($_GET['getMaxTimestamp']) && $auth) -{ - $results = $db->query('SELECT MAX(timestamp) FROM queries'); +if (isset($_GET['getMaxTimestamp']) && $auth) { + $results = $db->query('SELECT MAX(timestamp) FROM queries'); - if(!is_bool($results)) - $result = array('maxtimestamp' => $results->fetchArray()[0]); - else - $result = array(); + if (!is_bool($results)) { + $result = array('maxtimestamp' => $results->fetchArray()[0]); + } else { + $result = array(); + } - $data = array_merge($data, $result); + $data = array_merge($data, $result); } -if (isset($_GET['getQueriesCount']) && $auth) -{ - $results = $db->query('SELECT COUNT(timestamp) FROM queries'); +if (isset($_GET['getQueriesCount']) && $auth) { + $results = $db->query('SELECT COUNT(timestamp) FROM queries'); - if(!is_bool($results)) - $result = array('count' => $results->fetchArray()[0]); - else - $result = array(); + if (!is_bool($results)) { + $result = array('count' => $results->fetchArray()[0]); + } else { + $result = array(); + } - $data = array_merge($data, $result); + $data = array_merge($data, $result); } -if (isset($_GET['getDBfilesize']) && $auth) -{ - $filesize = filesize("/etc/pihole/pihole-FTL.db"); - $result = array('filesize' => $filesize); - $data = array_merge($data, $result); +if (isset($_GET['getDBfilesize']) && $auth) { + $filesize = filesize("/etc/pihole/pihole-FTL.db"); + $result = array('filesize' => $filesize); + $data = array_merge($data, $result); } -if (isset($_GET['getGraphData']) && $auth) -{ - $limit = ""; - - if(isset($_GET["from"]) && isset($_GET["until"])) - { - $limit = " AND timestamp >= :from AND timestamp <= :until"; - } - elseif(isset($_GET["from"]) && !isset($_GET["until"])) - { - $limit = " AND timestamp >= :from"; - } - elseif(!isset($_GET["from"]) && isset($_GET["until"])) - { - $limit = " AND timestamp <= :until"; - } - - $interval = 600; - - if(isset($_GET["interval"])) - { - $q = intval($_GET["interval"]); - if($q > 10) - $interval = $q; - } - - // Round $from and $until to match the requested $interval - $from = intval((intval($_GET['from'])/$interval)*$interval); - $until = intval((intval($_GET['until'])/$interval)*$interval); - - // Count permitted queries in intervals - $stmt = $db->prepare('SELECT (timestamp/:interval)*:interval interval, COUNT(*) FROM queries WHERE (status != 0 )'.$limit.' GROUP by interval ORDER by interval'); - $stmt->bindValue(":from", $from, SQLITE3_INTEGER); - $stmt->bindValue(":until", $until, SQLITE3_INTEGER); - $stmt->bindValue(":interval", $interval, SQLITE3_INTEGER); - $results = $stmt->execute(); - - // Parse the DB result into graph data, filling in missing interval sections with zero - function parseDBData($results, $interval, $from, $until) { - $data = array(); - - if(!is_bool($results)) { - // Read in the data - while($row = $results->fetchArray()) { - // $data[timestamp] = value_in_this_interval - $data[$row[0]] = intval($row[1]); - } - } - - return $data; - } - - $domains = parseDBData($results, $interval, $from, $until); - - $result = array('domains_over_time' => $domains); - $data = array_merge($data, $result); - - // Count blocked queries in intervals - $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", $from, SQLITE3_INTEGER); - $stmt->bindValue(":until", $until, SQLITE3_INTEGER); - $stmt->bindValue(":interval", $interval, SQLITE3_INTEGER); - $results = $stmt->execute(); - - $addomains = parseDBData($results, $interval, $from, $until); - - $result = array('ads_over_time' => $addomains); - $data = array_merge($data, $result); +if (isset($_GET['getGraphData']) && $auth) { + $limit = ""; + + if (isset($_GET["from"]) && isset($_GET["until"])) { + $limit = " AND timestamp >= :from AND timestamp <= :until"; + } elseif (isset($_GET["from"]) && !isset($_GET["until"])) { + $limit = " AND timestamp >= :from"; + } elseif (!isset($_GET["from"]) && isset($_GET["until"])) { + $limit = " AND timestamp <= :until"; + } + + $interval = 600; + + if (isset($_GET["interval"])) { + $q = intval($_GET["interval"]); + if ($q > 10) { + $interval = $q; + } + } + + // Round $from and $until to match the requested $interval + $from = intval((intval($_GET['from']) / $interval) * $interval); + $until = intval((intval($_GET['until']) / $interval) * $interval); + + // Count permitted queries in intervals + $stmt = $db->prepare('SELECT (timestamp/:interval)*:interval interval, COUNT(*) FROM queries WHERE (status != 0 )' . $limit . ' GROUP by interval ORDER by interval'); + $stmt->bindValue(":from", $from, SQLITE3_INTEGER); + $stmt->bindValue(":until", $until, SQLITE3_INTEGER); + $stmt->bindValue(":interval", $interval, SQLITE3_INTEGER); + $results = $stmt->execute(); + + // Parse the DB result into graph data, filling in missing interval sections with zero + function parseDBData($results, $interval, $from, $until) + { + $data = array(); + + if (!is_bool($results)) { + // Read in the data + while ($row = $results->fetchArray()) { + // $data[timestamp] = value_in_this_interval + $data[$row[0]] = intval($row[1]); + } + } + + return $data; + } + + $domains = parseDBData($results, $interval, $from, $until); + + $result = array('domains_over_time' => $domains); + $data = array_merge($data, $result); + + // Count blocked queries in intervals + $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", $from, SQLITE3_INTEGER); + $stmt->bindValue(":until", $until, SQLITE3_INTEGER); + $stmt->bindValue(":interval", $interval, SQLITE3_INTEGER); + $results = $stmt->execute(); + + $addomains = parseDBData($results, $interval, $from, $until); + + $result = array('ads_over_time' => $addomains); + $data = array_merge($data, $result); } -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/db_graph.php b/db_graph.php index 9a7030e09..8e2f0d7ac 100644 --- a/db_graph.php +++ b/db_graph.php @@ -8,7 +8,7 @@ require "scripts/pi-hole/php/header.php"; // Generate CSRF token -if(empty($_SESSION['token'])) { +if (empty($_SESSION['token'])) { $_SESSION['token'] = base64_encode(openssl_random_pseudo_bytes(32)); } $token = $_SESSION['token']; diff --git a/db_lists.php b/db_lists.php index 137922775..5839be380 100644 --- a/db_lists.php +++ b/db_lists.php @@ -8,7 +8,7 @@ require "scripts/pi-hole/php/header.php"; // Generate CSRF token -if(empty($_SESSION['token'])) { +if (empty($_SESSION['token'])) { $_SESSION['token'] = base64_encode(openssl_random_pseudo_bytes(32)); } $token = $_SESSION['token']; @@ -45,13 +45,10 @@
diff --git a/db_queries.php b/db_queries.php index 601b56ad1..525236ff9 100644 --- a/db_queries.php +++ b/db_queries.php @@ -8,7 +8,7 @@ require "scripts/pi-hole/php/header.php"; // Generate CSRF token -if(empty($_SESSION['token'])) { +if (empty($_SESSION['token'])) { $_SESSION['token'] = base64_encode(openssl_random_pseudo_bytes(32)); } $token = $_SESSION['token']; diff --git a/debug.php b/debug.php index 9840331fc..040aad7a1 100644 --- a/debug.php +++ b/debug.php @@ -1,4 +1,4 @@ - 0) - { - $authenticationsystem = true; - } - else - { - $authenticationsystem = false; - } +if (strlen($pwhash) > 0) { + $authenticationsystem = true; +} else { + $authenticationsystem = false; +} ?>
@@ -35,7 +32,7 @@
  • Details: Link to Jacob Salmela's blog with some more details, describing also the concept of the Pi-hole
  • Updates: Link to list of releases
  • Update notifications: If updates are available, a link will be shown here.
  • - +
  • Session timer: Shows the time remaining until the current login session expires.
  • @@ -55,7 +52,7 @@
  • Top Clients: Ranking of how many DNS requests each client has made on the local network.
  • The Top Domains and Top Advertisers lists may be hidden depending on the privacy Settings on the settings page

    - +

    Note that the login session does not expire on the dashboard, as the summary is updated every 10 seconds which refreshes the session.

    @@ -120,11 +117,15 @@
    -

    Authentication system (currently enableddisabled)

    +

    Authentication system (currently enableddisabled)

    Using the command

    sudo pihole -a -p
    and entering a password to be set, one can enable the authentication system of this web interface. Thereafter, a login is required for most pages (the dashboard will show a limited amount of statistics). Note that the authentication system may be disabled again, by setting an empty password using the command shown above. The Help center will show more details concerning the authentication system only if it is enabled

    - +

    Login / Logout

    diff --git a/index.php b/index.php index 78c1a4648..fc46b9755 100644 --- a/index.php +++ b/index.php @@ -9,18 +9,15 @@ require "scripts/pi-hole/php/header.php"; require_once("scripts/pi-hole/php/gravity.php"); - function getinterval() - { - global $piholeFTLConf; - if(isset($piholeFTLConf["MAXLOGAGE"])) - { - return round(floatval($piholeFTLConf["MAXLOGAGE"]), 1); - } - else - { - return "24"; - } +function getinterval() +{ + global $piholeFTLConf; + if (isset($piholeFTLConf["MAXLOGAGE"])) { + return round(floatval($piholeFTLConf["MAXLOGAGE"]), 1); + } else { + return "24"; } +} ?>
    @@ -101,8 +98,7 @@ function getinterval() // Even if we would include them here anyhow, there would be nothing to // show since the API will respect the privacy of the user if he defines // a password - if($auth){ ?> - +if ($auth) { ?>
    @@ -163,16 +159,13 @@ function getinterval()
    - +
    diff --git a/list.php b/list.php index 3f24c07cf..24bce7dcb 100644 --- a/list.php +++ b/list.php @@ -10,19 +10,14 @@ $list = $_GET['l'] ?? ''; -if ($list == "white") -{ +if ($list == "white") { $listtitle = "Whitelist"; $heading = "whitelisting"; -} -elseif ($list == "black") -{ +} elseif ($list == "black") { $listtitle = "Blacklist"; $heading = "blocking"; -} -else -{ - echo "Invalid list parameter ".$list; +} else { + echo "Invalid list parameter " . $list; require "scripts/pi-hole/php/footer.php"; die(); } diff --git a/network.php b/network.php index 7c1f9b026..d54538620 100644 --- a/network.php +++ b/network.php @@ -8,7 +8,7 @@ require "scripts/pi-hole/php/header.php"; // Generate CSRF token -if(empty($_SESSION['token'])) { +if (empty($_SESSION['token'])) { $_SESSION['token'] = base64_encode(openssl_random_pseudo_bytes(32)); } $token = $_SESSION['token']; diff --git a/queries.php b/queries.php index 51c543e6a..5a3eccbe2 100644 --- a/queries.php +++ b/queries.php @@ -8,76 +8,55 @@ require "scripts/pi-hole/php/header.php"; // Generate CSRF token -if(empty($_SESSION['token'])) { +if (empty($_SESSION['token'])) { $_SESSION['token'] = base64_encode(openssl_random_pseudo_bytes(32)); } $token = $_SESSION['token']; $showing = ""; -if(isset($setupVars["API_QUERY_LOG_SHOW"])) -{ - if($setupVars["API_QUERY_LOG_SHOW"] === "all") - { - $showing = "showing"; - } - elseif($setupVars["API_QUERY_LOG_SHOW"] === "permittedonly") - { - $showing = "showing permitted"; - } - elseif($setupVars["API_QUERY_LOG_SHOW"] === "blockedonly") - { - $showing = "showing blocked"; - } - elseif($setupVars["API_QUERY_LOG_SHOW"] === "nothing") - { - $showing = "showing no queries (due to setting)"; - } -} -else -{ - // If filter variable is not set, we - // automatically show all queries - $showing = "showing"; +if (isset($setupVars["API_QUERY_LOG_SHOW"])) { + if ($setupVars["API_QUERY_LOG_SHOW"] === "all") { + $showing = "showing"; + } elseif ($setupVars["API_QUERY_LOG_SHOW"] === "permittedonly") { + $showing = "showing permitted"; + } elseif ($setupVars["API_QUERY_LOG_SHOW"] === "blockedonly") { + $showing = "showing blocked"; + } elseif ($setupVars["API_QUERY_LOG_SHOW"] === "nothing") { + $showing = "showing no queries (due to setting)"; + } +} else { + // If filter variable is not set, we + // automatically show all queries + $showing = "showing"; } $showall = false; -if(isset($_GET["all"])) -{ - $showing .= " all queries within the Pi-hole log"; -} -else if(isset($_GET["client"])) -{ - $showing .= " queries for client ".htmlentities($_GET["client"]); -} -else if(isset($_GET["domain"])) -{ - $showing .= " queries for domain ".htmlentities($_GET["domain"]); -} -else if(isset($_GET["from"]) || isset($_GET["until"])) -{ - $showing .= " queries within specified time interval"; -} -else -{ - $showing .= " up to 100 queries"; - $showall = true; +if (isset($_GET["all"])) { + $showing .= " all queries within the Pi-hole log"; +} elseif (isset($_GET["client"])) { + $showing .= " queries for client " . htmlentities($_GET["client"]); +} elseif (isset($_GET["domain"])) { + $showing .= " queries for domain " . htmlentities($_GET["domain"]); +} elseif (isset($_GET["from"]) || isset($_GET["until"])) { + $showing .= " queries within specified time interval"; +} else { + $showing .= " up to 100 queries"; + $showall = true; } -if(isset($setupVars["API_PRIVACY_MODE"])) -{ - if($setupVars["API_PRIVACY_MODE"]) - { - // Overwrite string from above - $showing .= ", privacy mode enabled"; - } +if (isset($setupVars["API_PRIVACY_MODE"])) { + if ($setupVars["API_PRIVACY_MODE"]) { + // Overwrite string from above + $showing .= ", privacy mode enabled"; + } } -if(strlen($showing) > 0) -{ - $showing = "(".$showing.")"; - if($showall) - $showing .= ", show all"; +if (strlen($showing) > 0) { + $showing = "(" . $showing . ")"; + if ($showall) { + $showing .= ", show all"; + } } ?> diff --git a/queryads.php b/queryads.php index 3c14765bd..028b9a475 100644 --- a/queryads.php +++ b/queryads.php @@ -1,4 +1,4 @@ -
    - + diff --git a/scripts/pi-hole/php/FTL.php b/scripts/pi-hole/php/FTL.php index c33e061a1..8289c0ffa 100644 --- a/scripts/pi-hole/php/FTL.php +++ b/scripts/pi-hole/php/FTL.php @@ -6,58 +6,60 @@ * This file is copyright under the latest version of the EUPL. * Please see LICENSE file for your rights under this license. */ -function connectFTL($address, $port=4711) +function connectFTL($address, $port = 4711) { - if($address == "127.0.0.1") - { - // Read port - $portfile = file_get_contents("/var/run/pihole-FTL.port"); - if(is_numeric($portfile)) - $port = intval($portfile); - } - - // Open Internet socket connection - $socket = @fsockopen($address, $port, $errno, $errstr, 1.0); - - return $socket; + if ($address == "127.0.0.1") { + // Read port + $portfile = file_get_contents("/var/run/pihole-FTL.port"); + if (is_numeric($portfile)) { + $port = intval($portfile); + } + } + + // Open Internet socket connection + $socket = @fsockopen($address, $port, $errno, $errstr, 1.0); + + return $socket; } function sendRequestFTL($requestin) { - global $socket; + global $socket; - $request = ">".$requestin; - fwrite($socket, $request) or die('{"error":"Could not send data to server"}'); + $request = ">" . $requestin; + fwrite($socket, $request) or die('{"error":"Could not send data to server"}'); } function getResponseFTL() { - global $socket; - - $response = []; - - $errCount = 0; - while(true) - { - $out = fgets($socket); - if ($out == "") $errCount++; - if ($errCount > 100) { - // Tried 100 times, but never got proper reply, fail to prevent busy loop - die('{"error":"Tried 100 times to connect to FTL server, but never got proper reply. Please check Port and logs!"}'); - } - if(strrpos($out,"---EOM---") !== false) - break; - - $out = rtrim($out); - if(strlen($out) > 0) - $response[] = $out; - } - - return $response; + global $socket; + + $response = []; + + $errCount = 0; + while (true) { + $out = fgets($socket); + if ($out == "") { + $errCount++; + } + if ($errCount > 100) { + // Tried 100 times, but never got proper reply, fail to prevent busy loop + die('{"error":"Tried 100 times to connect to FTL server, but never got proper reply. Please check Port and logs!"}'); + } + if (strrpos($out, "---EOM---") !== false) { + break; + } + + $out = rtrim($out); + if (strlen($out) > 0) { + $response[] = $out; + } + } + + return $response; } function disconnectFTL() { - global $socket; - fclose($socket); + global $socket; + fclose($socket); } -?> diff --git a/scripts/pi-hole/php/add.php b/scripts/pi-hole/php/add.php index d6059a515..35ea9b06e 100644 --- a/scripts/pi-hole/php/add.php +++ b/scripts/pi-hole/php/add.php @@ -19,7 +19,7 @@ // Only check domains we add to the exact lists. // Regex are validated by FTL during import $check_lists = ["white","black","audit"]; -if(in_array($list, $check_lists)) { +if (in_array($list, $check_lists)) { check_domain(); } @@ -32,41 +32,40 @@ $GRAVITYDB = getGravityDBFilename(); $db = SQLite3_connect($GRAVITYDB, SQLITE3_OPEN_READWRITE); -switch($list) { - case "white": - $domains = array_map('strtolower', $domains); - echo add_to_table($db, "domainlist", $domains, $comment, false, false, ListType::whitelist); - break; +switch ($list) { + case "white": + $domains = array_map('strtolower', $domains); + echo add_to_table($db, "domainlist", $domains, $comment, false, false, ListType::whitelist); + break; - case "black": - $domains = array_map('strtolower', $domains); - echo add_to_table($db, "domainlist", $domains, $comment, false, false, ListType::blacklist); - break; + case "black": + $domains = array_map('strtolower', $domains); + echo add_to_table($db, "domainlist", $domains, $comment, false, false, ListType::blacklist); + break; - case "white_regex": - echo add_to_table($db, "domainlist", $domains, $comment, false, false, ListType::regex_whitelist); - break; + case "white_regex": + echo add_to_table($db, "domainlist", $domains, $comment, false, false, ListType::regex_whitelist); + break; - case "white_wild": - echo add_to_table($db, "domainlist", $domains, $comment, true, false, ListType::regex_whitelist); - break; + case "white_wild": + echo add_to_table($db, "domainlist", $domains, $comment, true, false, ListType::regex_whitelist); + break; - case "black_regex": - echo add_to_table($db, "domainlist", $domains, $comment, false, false, ListType::regex_blacklist); - break; + case "black_regex": + echo add_to_table($db, "domainlist", $domains, $comment, false, false, ListType::regex_blacklist); + break; - case "black_wild": - echo add_to_table($db, "domainlist", $domains, $comment, true, false, ListType::regex_blacklist); - break; + case "black_wild": + echo add_to_table($db, "domainlist", $domains, $comment, true, false, ListType::regex_blacklist); + break; - case "audit": - echo add_to_table($db, "domain_audit", $domains, $comment); - break; + case "audit": + echo add_to_table($db, "domain_audit", $domains, $comment); + break; - default: - die("Invalid list!"); + default: + die("Invalid list!"); } // Reload lists in pihole-FTL after having added something echo shell_exec("sudo pihole restartdns reload"); -?> diff --git a/scripts/pi-hole/php/api_token.php b/scripts/pi-hole/php/api_token.php index f24d9e541..a85ec48c4 100644 --- a/scripts/pi-hole/php/api_token.php +++ b/scripts/pi-hole/php/api_token.php @@ -4,23 +4,17 @@ require "password.php"; check_cors(); -if($auth) -{ - if(strlen($pwhash) > 0) - { - require_once("../../vendor/qrcode.php"); - $qr = QRCode::getMinimumQRCode($pwhash, QR_ERROR_CORRECT_LEVEL_Q); - $qr->printHTML("10px"); - echo "
    Raw API Token: " . $pwhash . ""; - } - else - { - ?>

    No password set

    Not authorized!

    0) { + require_once("../../vendor/qrcode.php"); + $qr = QRCode::getMinimumQRCode($pwhash, QR_ERROR_CORRECT_LEVEL_Q); + $qr->printHTML("10px"); + echo "
    Raw API Token: " . $pwhash . ""; + } else { + ?>

    No password set

    Not authorized!

    diff --git a/scripts/pi-hole/php/auth.php b/scripts/pi-hole/php/auth.php index 56f845203..99868dc60 100644 --- a/scripts/pi-hole/php/auth.php +++ b/scripts/pi-hole/php/auth.php @@ -12,24 +12,27 @@ $ERRORLOG = '/var/log/lighttpd/error.log'; if (!file_exists($ERRORLOG) || !is_writable($ERRORLOG)) { - $ERRORLOG = '/var/log/apache2/error.log'; + $ERRORLOG = '/var/log/apache2/error.log'; - if (!file_exists($ERRORLOG) || !is_writable($ERRORLOG)) { - $ERRORLOG = '/tmp/pi-hole-error.log'; - } + if (!file_exists($ERRORLOG) || !is_writable($ERRORLOG)) { + $ERRORLOG = '/tmp/pi-hole-error.log'; + } } } -function pi_log($message) { +function pi_log($message) +{ error_log(date('Y-m-d H:i:s') . ': ' . $message . "\n", 3, $GLOBALS['ERRORLOG']); } -function log_and_die($message) { +function log_and_die($message) +{ pi_log($message); die($message); } -function check_cors() { +function check_cors() +{ $setupVars = parse_ini_file("/etc/pihole/setupVars.conf"); $ipv4 = isset($setupVars["IPV4_ADDRESS"]) ? explode("/", $setupVars["IPV4_ADDRESS"])[0] : $_SERVER['SERVER_ADDR']; $ipv6 = isset($setupVars["IPV6_ADDRESS"]) ? explode("/", $setupVars["IPV6_ADDRESS"])[0] : $_SERVER['SERVER_ADDR']; @@ -45,8 +48,9 @@ function check_cors() { # Allow user set virtual hostnames $virtual_host = getenv('VIRTUAL_HOST'); - if (! empty($virtual_host)) + if (! empty($virtual_host)) { array_push($AUTHORIZED_HOSTNAMES, $virtual_host); + } // Since the Host header is easily manipulated, we can only check if it's wrong and can't use it // to validate that the client is authorized, only unauthorized. @@ -60,94 +64,87 @@ function check_cors() { // Don't use parse_url for IPv6 addresses, since it does not support them // see PHP bug report: https://bugs.php.net/bug.php?id=72811 - if(strpos($server_host, ":") && !strpos($server_host, "[") && !strpos($server_host, "]")) - { + if (strpos($server_host, ":") && !strpos($server_host, "[") && !strpos($server_host, "]")) { $server_host = parse_url($_SERVER['HTTP_HOST'], PHP_URL_HOST); } // Remove "[" ... "]" $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)); + if (isset($_SERVER['HTTP_HOST']) && !in_array($server_host, $AUTHORIZED_HOSTNAMES)) { + log_and_die("Failed Host Check: " . $server_host . ' vs ' . join(', ', $AUTHORIZED_HOSTNAMES)); } - if(isset($_SERVER['HTTP_ORIGIN'])) { + if (isset($_SERVER['HTTP_ORIGIN'])) { $server_origin = $_SERVER['HTTP_ORIGIN']; // Detect colon in $_SERVER['HTTP_ORIGIN'] (see comment above) - if(strpos($server_origin, ":") && !strpos($server_origin, "[") && !strpos($server_origin, "]")) - { + if (strpos($server_origin, ":") && !strpos($server_origin, "[") && !strpos($server_origin, "]")) { $server_origin = parse_url($_SERVER['HTTP_ORIGIN'], PHP_URL_HOST); } // Remove "[", "]","http://", and "https://" $server_origin = str_replace(array("[","]","http://","https://"), array("","","",""), $server_origin); - if(!in_array($server_origin, $AUTHORIZED_HOSTNAMES)) { - log_and_die("Failed CORS: " . $server_origin .' vs '. join(', ', $AUTHORIZED_HOSTNAMES)); + if (!in_array($server_origin, $AUTHORIZED_HOSTNAMES)) { + log_and_die("Failed CORS: " . $server_origin . ' vs ' . join(', ', $AUTHORIZED_HOSTNAMES)); } header("Access-Control-Allow-Origin: ${_SERVER['HTTP_ORIGIN']}"); } // If there's no HTTP_ORIGIN, CORS should not be used } -function check_csrf($token) { +function check_csrf($token) +{ // Check CSRF token $session_started = function_exists("session_status") ? session_status() == PHP_SESSION_ACTIVE : session_id() == ""; - if(!$session_started) { + if (!$session_started) { session_start(); } - if(!isset($_SESSION['token'])) { + if (!isset($_SESSION['token'])) { log_and_die("Session expired! Please re-login on the Pi-hole dashboard."); } - if(empty($token)) { + if (empty($token)) { log_and_die("Empty token! Check if cookies are enabled on your system."); } - if(!hash_equals($_SESSION['token'], $token)) { + if (!hash_equals($_SESSION['token'], $token)) { log_and_die("Wrong token! Please re-login on the Pi-hole dashboard."); } } -function check_domain() { - if(isset($_POST['domain'])){ +function check_domain() +{ + if (isset($_POST['domain'])) { $domains = preg_split('/\s+/', $_POST['domain']); - foreach($domains as $domain) - { + foreach ($domains as $domain) { $validDomain = is_valid_domain_name($domain); - if(!$validDomain){ - log_and_die(htmlspecialchars($domain. ' is not a valid domain')); + if (!$validDomain) { + log_and_die(htmlspecialchars($domain . ' is not a valid domain')); } } } } -function list_verify($type) { +function list_verify($type) +{ global $pwhash, $wrongpassword, $auth; - if(!isset($_POST['domain']) || !isset($_POST['list']) || !(isset($_POST['pw']) || isset($_POST['token']))) { + if (!isset($_POST['domain']) || !isset($_POST['list']) || !(isset($_POST['pw']) || isset($_POST['token']))) { log_and_die("Missing POST variables"); } - if(isset($_POST['token'])) - { + if (isset($_POST['token'])) { check_cors(); check_csrf($_POST['token']); - } - elseif(isset($_POST['pw'])) - { + } elseif (isset($_POST['pw'])) { require("password.php"); - if($wrongpassword || !$auth) - { - log_and_die("Wrong password - ".htmlspecialchars($type)."listing of ".htmlspecialchars($_POST['domain'])." not permitted"); + if ($wrongpassword || !$auth) { + log_and_die("Wrong password - " . htmlspecialchars($type) . "listing of " . htmlspecialchars($_POST['domain']) . " not permitted"); } - } - else - { + } else { log_and_die("Not allowed!"); } } -?> diff --git a/scripts/pi-hole/php/customdns.php b/scripts/pi-hole/php/customdns.php index 982981e2c..f5428092f 100644 --- a/scripts/pi-hole/php/customdns.php +++ b/scripts/pi-hole/php/customdns.php @@ -4,136 +4,147 @@ $customDNSFile = "/etc/pihole/custom.list"; - switch ($_REQUEST['action']) - { - case 'get': echo json_encode(echoCustomDNSEntries()); break; - case 'add': echo json_encode(addCustomDNSEntry()); break; - case 'delete': echo json_encode(deleteCustomDNSEntry()); break; - default: - die("Wrong action"); +switch ($_REQUEST['action']) { + case 'get': + echo json_encode(echoCustomDNSEntries()); + break; + case 'add': + echo json_encode(addCustomDNSEntry()); + break; + case 'delete': + echo json_encode(deleteCustomDNSEntry()); + break; + default: + die("Wrong action"); +} + +function echoCustomDNSEntries() +{ + $entries = getCustomDNSEntries(); + + $data = []; + foreach ($entries as $entry) { + $data[] = [ $entry->domain, $entry->ip ]; } - function echoCustomDNSEntries() - { - $entries = getCustomDNSEntries(); + return [ "data" => $data ]; +} - $data = []; - foreach ($entries as $entry) - $data[] = [ $entry->domain, $entry->ip ]; +function getCustomDNSEntries() +{ + global $customDNSFile; - return [ "data" => $data ]; - } - - function getCustomDNSEntries() - { - global $customDNSFile; - - $entries = []; + $entries = []; - $handle = fopen($customDNSFile, "r"); - if ($handle) - { - while (($line = fgets($handle)) !== false) { - $line = str_replace("\r","", $line); - $line = str_replace("\n","", $line); - $explodedLine = explode (" ", $line); + $handle = fopen($customDNSFile, "r"); + if ($handle) { + while (($line = fgets($handle)) !== false) { + $line = str_replace("\r", "", $line); + $line = str_replace("\n", "", $line); + $explodedLine = explode(" ", $line); - if (count($explodedLine) != 2) - continue; - - $data = new \stdClass(); - $data->ip = $explodedLine[0]; - $data->domain = $explodedLine[1]; - $entries[] = $data; + if (count($explodedLine) != 2) { + continue; } - fclose($handle); + $data = new \stdClass(); + $data->ip = $explodedLine[0]; + $data->domain = $explodedLine[1]; + $entries[] = $data; } - return $entries; + fclose($handle); } - function addCustomDNSEntry() - { - try - { - $ip = !empty($_REQUEST['ip']) ? $_REQUEST['ip']: ""; - $domain = !empty($_REQUEST['domain']) ? $_REQUEST['domain']: ""; - - if (empty($ip)) - return errorJsonResponse("IP must be set"); + return $entries; +} - $ipType = get_ip_type($ip); +function addCustomDNSEntry() +{ + try { + $ip = !empty($_REQUEST['ip']) ? $_REQUEST['ip'] : ""; + $domain = !empty($_REQUEST['domain']) ? $_REQUEST['domain'] : ""; - if (!$ipType) - return errorJsonResponse("IP must be valid"); + if (empty($ip)) { + return errorJsonResponse("IP must be set"); + } - if (empty($domain)) - return errorJsonResponse("Domain must be set"); + $ipType = get_ip_type($ip); - if (!is_valid_domain_name($domain)) - return errorJsonResponse("Domain must be valid"); + if (!$ipType) { + return errorJsonResponse("IP must be valid"); + } - $existingEntries = getCustomDNSEntries(); + if (empty($domain)) { + return errorJsonResponse("Domain must be set"); + } - foreach ($existingEntries as $entry) - if ($entry->domain == $domain) - if (get_ip_type($entry->ip) == $ipType) - return errorJsonResponse("This domain already has a custom DNS entry for an IPv" . $ipType); + if (!is_valid_domain_name($domain)) { + return errorJsonResponse("Domain must be valid"); + } - exec("sudo pihole -a addcustomdns ".$ip." ".$domain); + $existingEntries = getCustomDNSEntries(); - return successJsonResponse(); - } - catch (\Exception $ex) - { - return errorJsonResponse($ex->getMessage()); + foreach ($existingEntries as $entry) { + if ($entry->domain == $domain) { + if (get_ip_type($entry->ip) == $ipType) { + return errorJsonResponse("This domain already has a custom DNS entry for an IPv" . $ipType); + } + } } + + exec("sudo pihole -a addcustomdns " . $ip . " " . $domain); + + return successJsonResponse(); + } catch (\Exception $ex) { + return errorJsonResponse($ex->getMessage()); } +} - function deleteCustomDNSEntry() - { - try - { - $ip = !empty($_REQUEST['ip']) ? $_REQUEST['ip']: ""; - $domain = !empty($_REQUEST['domain']) ? $_REQUEST['domain']: ""; +function deleteCustomDNSEntry() +{ + try { + $ip = !empty($_REQUEST['ip']) ? $_REQUEST['ip'] : ""; + $domain = !empty($_REQUEST['domain']) ? $_REQUEST['domain'] : ""; - if (empty($ip)) - return errorJsonResponse("IP must be set"); + if (empty($ip)) { + return errorJsonResponse("IP must be set"); + } - if (empty($domain)) - return errorJsonResponse("Domain must be set"); + if (empty($domain)) { + return errorJsonResponse("Domain must be set"); + } - $existingEntries = getCustomDNSEntries(); + $existingEntries = getCustomDNSEntries(); - $found = false; - foreach ($existingEntries as $entry) - if ($entry->domain == $domain) - if ($entry->ip == $ip) { - $found = true; - break; - } + $found = false; + foreach ($existingEntries as $entry) { + if ($entry->domain == $domain) { + if ($entry->ip == $ip) { + $found = true; + break; + } + } + } - if (!$found) - return errorJsonResponse("This domain/ip association does not exist"); + if (!$found) { + return errorJsonResponse("This domain/ip association does not exist"); + } - exec("sudo pihole -a removecustomdns ".$ip." ".$domain); + exec("sudo pihole -a removecustomdns " . $ip . " " . $domain); return successJsonResponse(); - } - catch (\Exception $ex) - { - return errorJsonResponse($ex->getMessage()); - } + } catch (\Exception $ex) { + return errorJsonResponse($ex->getMessage()); } +} - function successJsonResponse($message = "") - { - return [ "success" => true, "message" => $message ]; - } +function successJsonResponse($message = "") +{ + return [ "success" => true, "message" => $message ]; +} - function errorJsonResponse($message = "") - { - return [ "success" => false, "message" => $message ]; - } -?> +function errorJsonResponse($message = "") +{ + return [ "success" => false, "message" => $message ]; +} diff --git a/scripts/pi-hole/php/database.php b/scripts/pi-hole/php/database.php index 2bad73db0..a450f11eb 100644 --- a/scripts/pi-hole/php/database.php +++ b/scripts/pi-hole/php/database.php @@ -8,75 +8,59 @@ function getGravityDBFilename() { - // Get possible non-standard location of FTL's database - $FTLsettings = parse_ini_file("/etc/pihole/pihole-FTL.conf"); - if(isset($FTLsettings["GRAVITYDB"])) - { - return $FTLsettings["GRAVITYDB"]; - } - else - { - return "/etc/pihole/gravity.db"; - } + // Get possible non-standard location of FTL's database + $FTLsettings = parse_ini_file("/etc/pihole/pihole-FTL.conf"); + if (isset($FTLsettings["GRAVITYDB"])) { + return $FTLsettings["GRAVITYDB"]; + } else { + return "/etc/pihole/gravity.db"; + } } function getQueriesDBFilename() { - // Get possible non-standard location of FTL's database - $FTLsettings = parse_ini_file("/etc/pihole/pihole-FTL.conf"); - if(isset($FTLsettings["DBFILE"])) - { - return $FTLsettings["DBFILE"]; - } - else - { - return "/etc/pihole/pihole-FTL.db"; - } + // Get possible non-standard location of FTL's database + $FTLsettings = parse_ini_file("/etc/pihole/pihole-FTL.conf"); + if (isset($FTLsettings["DBFILE"])) { + return $FTLsettings["DBFILE"]; + } else { + return "/etc/pihole/pihole-FTL.db"; + } } function SQLite3_connect_try($filename, $mode, $trytoreconnect) { - try - { - // connect to database - return new SQLite3($filename, $mode); - } - catch (Exception $exception) - { - // sqlite3 throws an exception when it is unable to connect, try to reconnect after 3 seconds - if($trytoreconnect) - { - sleep(3); - return SQLite3_connect_try($filename, $mode, false); - } - else - { - // If we should not try again (or are already trying again!), we return the exception string - // so the user gets it on the dashboard - return $filename.": ".$exception->getMessage(); - } - } + try { + // connect to database + return new SQLite3($filename, $mode); + } catch (Exception $exception) { + // sqlite3 throws an exception when it is unable to connect, try to reconnect after 3 seconds + if ($trytoreconnect) { + sleep(3); + return SQLite3_connect_try($filename, $mode, false); + } else { + // If we should not try again (or are already trying again!), we return the exception string + // so the user gets it on the dashboard + return $filename . ": " . $exception->getMessage(); + } + } } -function SQLite3_connect($filename, $mode=SQLITE3_OPEN_READONLY) +function SQLite3_connect($filename, $mode = SQLITE3_OPEN_READONLY) { - if(strlen($filename) > 0) - { - $db = SQLite3_connect_try($filename, $mode, true); - } - else - { - die("No database available"); - } - if(is_string($db)) - { - die("Error connecting to database\n".$db); - } + if (strlen($filename) > 0) { + $db = SQLite3_connect_try($filename, $mode, true); + } else { + die("No database available"); + } + if (is_string($db)) { + die("Error connecting to database\n" . $db); + } - // Add busy timeout so methods don't fail immediately when, e.g., FTL is currently reading from the DB - $db->busyTimeout(5000); + // Add busy timeout so methods don't fail immediately when, e.g., FTL is currently reading from the DB + $db->busyTimeout(5000); - return $db; + return $db; } @@ -91,113 +75,103 @@ function SQLite3_connect($filename, $mode=SQLITE3_OPEN_READONLY) * @param $type integer The target type (0 = exact whitelist, 1 = exact blacklist, 2 = regex whitelist, 3 = regex blacklist) * @return string Success/error and number of processed domains */ -function add_to_table($db, $table, $domains, $comment, $wildcardstyle=false, $returnnum=false, $type=-1) +function add_to_table($db, $table, $domains, $comment, $wildcardstyle = false, $returnnum = false, $type = -1) { - if(!is_int($type)) - { - return "Error: Argument type has to be of type integer (is ".gettype($type).")"; - } + if (!is_int($type)) { + return "Error: Argument type has to be of type integer (is " . gettype($type) . ")"; + } - // Begin transaction - if(!$db->exec("BEGIN TRANSACTION;")) - { - if($returnnum) - return 0; - else - return "Error: Unable to begin transaction for $table table."; - } + // Begin transaction + if (!$db->exec("BEGIN TRANSACTION;")) { + if ($returnnum) { + return 0; + } else { + return "Error: Unable to begin transaction for $table table."; + } + } - // Get initial count of domains in this table - if($type === -1) - { - $countquery = "SELECT COUNT(*) FROM $table;"; - } - else - { - $countquery = "SELECT COUNT(*) FROM $table WHERE type = $type;"; - } - $initialcount = intval($db->querySingle($countquery)); + // Get initial count of domains in this table + if ($type === -1) { + $countquery = "SELECT COUNT(*) FROM $table;"; + } else { + $countquery = "SELECT COUNT(*) FROM $table WHERE type = $type;"; + } + $initialcount = intval($db->querySingle($countquery)); - // Prepare INSERT SQLite statememt - if($type === -1) - { - $querystr = "INSERT OR IGNORE INTO $table (domain,comment) VALUES (:domain, :comment);"; - } - else - { - $querystr = "INSERT OR IGNORE INTO $table (domain,comment,type) VALUES (:domain, :comment, $type);"; - } - $stmt = $db->prepare($querystr); + // Prepare INSERT SQLite statememt + if ($type === -1) { + $querystr = "INSERT OR IGNORE INTO $table (domain,comment) VALUES (:domain, :comment);"; + } else { + $querystr = "INSERT OR IGNORE INTO $table (domain,comment,type) VALUES (:domain, :comment, $type);"; + } + $stmt = $db->prepare($querystr); - // Return early if we failed to prepare the SQLite statement - if(!$stmt) - { - if($returnnum) - return 0; - else - return "Error: Failed to prepare statement for $table table (type = $type)."; - } + // Return early if we failed to prepare the SQLite statement + if (!$stmt) { + if ($returnnum) { + return 0; + } else { + return "Error: Failed to prepare statement for $table table (type = $type)."; + } + } - // Loop over domains and inject the lines into the database - $num = 0; - foreach($domains as $domain) - { - // Limit max length for a domain entry to 253 chars - if(strlen($domain) > 253) - continue; + // Loop over domains and inject the lines into the database + $num = 0; + foreach ($domains as $domain) { + // Limit max length for a domain entry to 253 chars + if (strlen($domain) > 253) { + continue; + } - if($wildcardstyle) - $domain = "(\\.|^)".str_replace(".","\\.",$domain)."$"; + if ($wildcardstyle) { + $domain = "(\\.|^)" . str_replace(".", "\\.", $domain) . "$"; + } - $stmt->bindValue(":domain", $domain, SQLITE3_TEXT); - $stmt->bindValue(":comment", $comment, SQLITE3_TEXT); + $stmt->bindValue(":domain", $domain, SQLITE3_TEXT); + $stmt->bindValue(":comment", $comment, SQLITE3_TEXT); - if($stmt->execute() && $stmt->reset()) - $num++; - else - { - $stmt->close(); - if($returnnum) - return $num; - else - { - if($num === 1) - $plural = ""; - else - $plural = "s"; - return "Error: ".$db->lastErrorMsg().", added ".$num." domain".$plural; - } - } - } + if ($stmt->execute() && $stmt->reset()) { + $num++; + } else { + $stmt->close(); + if ($returnnum) { + return $num; + } else { + if ($num === 1) { + $plural = ""; + } else { + $plural = "s"; + } + return "Error: " . $db->lastErrorMsg() . ", added " . $num . " domain" . $plural; + } + } + } - // Close prepared statement and return number of processed rows - $stmt->close(); - $db->exec("COMMIT;"); + // Close prepared statement and return number of processed rows + $stmt->close(); + $db->exec("COMMIT;"); - if($returnnum) - return $num; - else - { - $finalcount = intval($db->querySingle($countquery)); - $modified = $finalcount - $initialcount; + if ($returnnum) { + return $num; + } else { + $finalcount = intval($db->querySingle($countquery)); + $modified = $finalcount - $initialcount; - // If we add less domains than the user specified, then they wanted to add duplicates - if($modified !== $num) - { - $delta = $num - $modified; - $extra = " (skipped ".$delta." duplicates)"; - } - else - { - $extra = ""; - } + // If we add less domains than the user specified, then they wanted to add duplicates + if ($modified !== $num) { + $delta = $num - $modified; + $extra = " (skipped " . $delta . " duplicates)"; + } else { + $extra = ""; + } - if($num === 1) - $plural = ""; - else - $plural = "s"; - return "Success, added ".$modified." of ".$num." domain".$plural.$extra; - } + if ($num === 1) { + $plural = ""; + } else { + $plural = "s"; + } + return "Success, added " . $modified . " of " . $num . " domain" . $plural . $extra; + } } /** @@ -210,96 +184,88 @@ function add_to_table($db, $table, $domains, $comment, $wildcardstyle=false, $re * @param $type integer The target type (0 = exact whitelist, 1 = exact blacklist, 2 = regex whitelist, 3 = regex blacklist) * @return string Success/error and number of processed domains */ -function remove_from_table($db, $table, $domains, $returnnum=false, $type=-1) +function remove_from_table($db, $table, $domains, $returnnum = false, $type = -1) { - if(!is_int($type)) - { - return "Error: Argument type has to be of type integer (is ".gettype($type).")"; - } + if (!is_int($type)) { + return "Error: Argument type has to be of type integer (is " . gettype($type) . ")"; + } - // Begin transaction - if(!$db->exec("BEGIN TRANSACTION;")) - { - if($returnnum) - return 0; - else - return "Error: Unable to begin transaction for domainlist table."; - } + // Begin transaction + if (!$db->exec("BEGIN TRANSACTION;")) { + if ($returnnum) { + return 0; + } else { + return "Error: Unable to begin transaction for domainlist table."; + } + } - // Get initial count of domains in this table - if($type === -1) - { - $countquery = "SELECT COUNT(*) FROM $table;"; - } - else - { - $countquery = "SELECT COUNT(*) FROM $table WHERE type = $type;"; - } - $initialcount = intval($db->querySingle($countquery)); + // Get initial count of domains in this table + if ($type === -1) { + $countquery = "SELECT COUNT(*) FROM $table;"; + } else { + $countquery = "SELECT COUNT(*) FROM $table WHERE type = $type;"; + } + $initialcount = intval($db->querySingle($countquery)); - // Prepare SQLite statememt - if($type === -1) - { - $querystr = "DELETE FROM $table WHERE domain = :domain AND type = $type;"; - } - else - { - $querystr = "DELETE FROM $table WHERE domain = :domain;"; - } - $stmt = $db->prepare($querystr); + // Prepare SQLite statememt + if ($type === -1) { + $querystr = "DELETE FROM $table WHERE domain = :domain AND type = $type;"; + } else { + $querystr = "DELETE FROM $table WHERE domain = :domain;"; + } + $stmt = $db->prepare($querystr); - // Return early if we failed to prepare the SQLite statement - if(!$stmt) - { - if($returnnum) - return 0; - else - return "Error: Failed to prepare statement for ".$table." table (type = ".$type.")."; - } + // Return early if we failed to prepare the SQLite statement + if (!$stmt) { + if ($returnnum) { + return 0; + } else { + return "Error: Failed to prepare statement for " . $table . " table (type = " . $type . ")."; + } + } - // Loop over domains and remove the lines from the database - $num = 0; - foreach($domains as $domain) - { - $stmt->bindValue(":domain", $domain, SQLITE3_TEXT); + // Loop over domains and remove the lines from the database + $num = 0; + foreach ($domains as $domain) { + $stmt->bindValue(":domain", $domain, SQLITE3_TEXT); - if($stmt->execute() && $stmt->reset()) - $num++; - else - { - $stmt->close(); - if($returnnum) - return $num; - else - { - if($num === 1) - $plural = ""; - else - $plural = "s"; - return "Error: ".$db->lastErrorMsg().", removed ".$num." domain".$plural; - } - } - } + if ($stmt->execute() && $stmt->reset()) { + $num++; + } else { + $stmt->close(); + if ($returnnum) { + return $num; + } else { + if ($num === 1) { + $plural = ""; + } else { + $plural = "s"; + } + return "Error: " . $db->lastErrorMsg() . ", removed " . $num . " domain" . $plural; + } + } + } - // Close prepared statement and return number or processed rows - $stmt->close(); - $db->exec("COMMIT;"); + // Close prepared statement and return number or processed rows + $stmt->close(); + $db->exec("COMMIT;"); - if($returnnum) - return $num; - else - { - if($num === 1) - $plural = ""; - else - $plural = "s"; - return "Success, removed ".$num." domain".$plural; - } + if ($returnnum) { + return $num; + } else { + if ($num === 1) { + $plural = ""; + } else { + $plural = "s"; + } + return "Success, removed " . $num . " domain" . $plural; + } } -class ListType{ - const whitelist = 0; - const blacklist = 1; - const regex_whitelist = 2; - const regex_blacklist = 3; +class ListType +{ + const whitelist = 0; + const blacklist = 1; + const regex_whitelist = 2; + const regex_blacklist = 3; } diff --git a/scripts/pi-hole/php/debug.php b/scripts/pi-hole/php/debug.php index 27a23545c..1442870d0 100644 --- a/scripts/pi-hole/php/debug.php +++ b/scripts/pi-hole/php/debug.php @@ -8,7 +8,7 @@ require "password.php"; require "auth.php"; -if(!$auth) { +if (!$auth) { die("Unauthorized"); } @@ -17,24 +17,22 @@ $token = isset($_GET["token"]) ? $_GET["token"] : ""; check_csrf($token); -function echoEvent($datatext) { +function echoEvent($datatext) +{ $data = htmlspecialchars($datatext); - if(!isset($_GET["IE"])) - echo "data: ".implode("\ndata: ", explode("\n", $data))."\n\n"; - else - echo $data; + if (!isset($_GET["IE"])) { + echo "data: " . implode("\ndata: ", explode("\n", $data)) . "\n\n"; + } else { + echo $data; + } } -if(isset($_GET["upload"])) -{ - $proc = popen("sudo pihole -d -a -w", "r"); -} -else -{ - $proc = popen("sudo pihole -d -w", "r"); +if (isset($_GET["upload"])) { + $proc = popen("sudo pihole -d -a -w", "r"); +} else { + $proc = popen("sudo pihole -d -w", "r"); } while (!feof($proc)) { echoEvent(fread($proc, 4096)); } -?> diff --git a/scripts/pi-hole/php/footer.php b/scripts/pi-hole/php/footer.php index 834b82733..c3c0a9afe 100644 --- a/scripts/pi-hole/php/footer.php +++ b/scripts/pi-hole/php/footer.php @@ -47,20 +47,34 @@ ?> diff --git a/scripts/pi-hole/php/func.php b/scripts/pi-hole/php/func.php index 269fce7fa..16d1aa566 100644 --- a/scripts/pi-hole/php/func.php +++ b/scripts/pi-hole/php/func.php @@ -20,36 +20,33 @@ function get_ip_type($ip) 0); } -function checkfile($filename) { - if(is_readable($filename)) - { +function checkfile($filename) +{ + if (is_readable($filename)) { return $filename; - } - else - { + } else { // substitute dummy file return "/dev/null"; } } // Credit: http://php.net/manual/en/function.hash-equals.php#119576 -if(!function_exists('hash_equals')) { - function hash_equals($known_string, $user_string) { +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; + $user_string = $known_string; + $ret = 1; } $res = $known_string ^ $user_string; for ($i = strlen($res) - 1; $i >= 0; --$i) { - $ret |= ord($res[$i]); + $ret |= ord($res[$i]); } return !$ret; - } + } } - -?> diff --git a/scripts/pi-hole/php/get.php b/scripts/pi-hole/php/get.php index f47f2c84a..a680c88a7 100644 --- a/scripts/pi-hole/php/get.php +++ b/scripts/pi-hole/php/get.php @@ -6,8 +6,9 @@ * This file is copyright under the latest version of the EUPL. * Please see LICENSE file for your rights under this license. */ -if(!isset($_GET['list'])) +if (!isset($_GET['list'])) { die("Missing parameter"); +} $listtype = $_GET['list']; @@ -17,58 +18,54 @@ $GRAVITYDB = getGravityDBFilename(); $db = SQLite3_connect($GRAVITYDB); -function getTableContent($type) { - global $db; - $entries = array(); - $querystr = implode(" ",array("SELECT domainlist.*,\"group\".enabled as group_enabled", - "FROM domainlist", - "LEFT JOIN domainlist_by_group ON domainlist_by_group.domainlist_id = domainlist.id", - "LEFT JOIN \"group\" ON \"group\".id = domainlist_by_group.group_id", - "WHERE type = $type", - "GROUP BY domain;")); - $results = $db->query($querystr); +function getTableContent($type) +{ + global $db; + $entries = array(); + $querystr = implode(" ", array("SELECT domainlist.*,\"group\".enabled as group_enabled", + "FROM domainlist", + "LEFT JOIN domainlist_by_group ON domainlist_by_group.domainlist_id = domainlist.id", + "LEFT JOIN \"group\" ON \"group\".id = domainlist_by_group.group_id", + "WHERE type = $type", + "GROUP BY domain;")); + $results = $db->query($querystr); - while($results !== false && $res = $results->fetchArray(SQLITE3_ASSOC)) - { - array_push($entries, $res); - } + while ($results !== false && $res = $results->fetchArray(SQLITE3_ASSOC)) { + array_push($entries, $res); + } - return $entries; + return $entries; } -function filterArray(&$inArray) { - $outArray = array(); - foreach ($inArray as $key => $value) - { - if (is_array($value)) - { - $outArray[htmlspecialchars($key)] = filterArray($value); - } - else - { - $outArray[htmlspecialchars($key)] = htmlspecialchars($value); - } - } - return $outArray; +function filterArray(&$inArray) +{ + $outArray = array(); + foreach ($inArray as $key => $value) { + if (is_array($value)) { + $outArray[htmlspecialchars($key)] = filterArray($value); + } else { + $outArray[htmlspecialchars($key)] = htmlspecialchars($value); + } + } + return $outArray; } -switch ($listtype) -{ - case "white": - $exact = array("whitelist" => getTableContent(ListType::whitelist)); - $regex = array("regex_whitelist" => getTableContent(ListType::regex_whitelist)); - $list = array_merge($exact, $regex); - break; +switch ($listtype) { + case "white": + $exact = array("whitelist" => getTableContent(ListType::whitelist)); + $regex = array("regex_whitelist" => getTableContent(ListType::regex_whitelist)); + $list = array_merge($exact, $regex); + break; - case "black": - $exact = array("blacklist" => getTableContent(ListType::blacklist)); - $regex = array("regex_blacklist" => getTableContent(ListType::regex_blacklist)); - $list = array_merge($exact, $regex); - break; + case "black": + $exact = array("blacklist" => getTableContent(ListType::blacklist)); + $regex = array("regex_blacklist" => getTableContent(ListType::regex_blacklist)); + $list = array_merge($exact, $regex); + break; - default: - die("Invalid list parameter"); - break; + default: + die("Invalid list parameter"); + break; } // Protect against XSS attacks $output = filterArray($list); diff --git a/scripts/pi-hole/php/gravity.php b/scripts/pi-hole/php/gravity.php index fbd729e3a..9b9f9a1b8 100644 --- a/scripts/pi-hole/php/gravity.php +++ b/scripts/pi-hole/php/gravity.php @@ -10,52 +10,43 @@ function gravity_last_update($raw = false) { - $db = SQLite3_connect(getGravityDBFilename()); - $date_file_created_unix = $db->querySingle("SELECT value FROM info WHERE property = 'updated';"); - if($date_file_created_unix === false) - { - if($raw) - { - // Array output - return array("file_exists" => false); - } - else - { - // String output - return "Gravity database not available"; - } - } - // Now that we know that $date_file_created_unix is a valid response, we can convert it to an integer - $date_file_created_unix = intval($date_file_created_unix); - $date_file_created = date_create("@".$date_file_created_unix); - $date_now = date_create("now"); - $gravitydiff = date_diff($date_file_created,$date_now); - if($raw) - { - // Array output - return array( - "file_exists"=> true, - "absolute" => $date_file_created_unix, - "relative" => array( - "days" => intval($gravitydiff->format("%a")), - "hours" => intval($gravitydiff->format("%H")), - "minutes" => intval($gravitydiff->format("%I")), - ) - ); - } + $db = SQLite3_connect(getGravityDBFilename()); + $date_file_created_unix = $db->querySingle("SELECT value FROM info WHERE property = 'updated';"); + if ($date_file_created_unix === false) { + if ($raw) { + // Array output + return array("file_exists" => false); + } else { + // String output + return "Gravity database not available"; + } + } + // Now that we know that $date_file_created_unix is a valid response, we can convert it to an integer + $date_file_created_unix = intval($date_file_created_unix); + $date_file_created = date_create("@" . $date_file_created_unix); + $date_now = date_create("now"); + $gravitydiff = date_diff($date_file_created, $date_now); + if ($raw) { + // Array output + return array( + "file_exists" => true, + "absolute" => $date_file_created_unix, + "relative" => array( + "days" => intval($gravitydiff->format("%a")), + "hours" => intval($gravitydiff->format("%H")), + "minutes" => intval($gravitydiff->format("%I")), + ) + ); + } - if($gravitydiff->d > 1) - { - // String output (more than one day ago) - return $gravitydiff->format("Blocking list 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"); - } + if ($gravitydiff->d > 1) { + // String output (more than one day ago) + return $gravitydiff->format("Blocking list 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"); + } - // String output (less than one day ago) - return $gravitydiff->format("Blocking list updated %H:%I (hh:mm) ago"); + // String output (less than one day ago) + return $gravitydiff->format("Blocking list updated %H:%I (hh:mm) ago"); } -?> diff --git a/scripts/pi-hole/php/gravity.sh.php b/scripts/pi-hole/php/gravity.sh.php index 4504e6eb3..54e52acc1 100644 --- a/scripts/pi-hole/php/gravity.sh.php +++ b/scripts/pi-hole/php/gravity.sh.php @@ -7,7 +7,9 @@ * Please see LICENSE file for your rights under this license. */ require "password.php"; -if(!$auth) die("Not authorized"); +if (!$auth) { + die("Not authorized"); +} ob_end_flush(); ini_set("output_buffering", "0"); @@ -15,23 +17,22 @@ header('Content-Type: text/event-stream'); header('Cache-Control: no-cache'); -function echoEvent($datatext) { +function echoEvent($datatext) +{ // Detect ${OVER} and replace it with something we can safely transmit - $datatext = str_replace("\r","<------",$datatext); - $pos = strpos($datatext,"<------"); + $datatext = str_replace("\r", "<------", $datatext); + $pos = strpos($datatext, "<------"); // Detect if the ${OVER} line is within this line, e.g. // "Pending: String to replace${OVER}Done: String has been replaced" // If this is the case, we have to remove everything before ${OVER} // and return only the text thereafter - if($pos !== false && $pos !== 0) - { + if ($pos !== false && $pos !== 0) { $datatext = substr($datatext, $pos); } - echo "data: ".implode("\ndata: ", explode("\n",$datatext))."\n\n"; + echo "data: " . implode("\ndata: ", explode("\n", $datatext)) . "\n\n"; } $proc = popen("sudo pihole -g", 'r'); while (!feof($proc)) { echoEvent(fread($proc, 4096)); } -?> diff --git a/scripts/pi-hole/php/groups.php b/scripts/pi-hole/php/groups.php index ff6f7aa52..0cb8ed6cd 100644 --- a/scripts/pi-hole/php/groups.php +++ b/scripts/pi-hole/php/groups.php @@ -365,12 +365,10 @@ function JSON_error($message = null) $type = intval($_POST['type']); $domain = $_POST['domain']; - if($type === ListType::whitelist || $type === ListType::blacklist) - { + if ($type === ListType::whitelist || $type === ListType::blacklist) { // If adding to the exact lists, we convert the domain lower case and check whether it is valid $domain = strtolower($domain); - if(filter_var($domain, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME) === false) - { + if (filter_var($domain, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME) === false) { throw new Exception('Domain ' . htmlentities(utf8_encode($domain)) . 'is not a valid domain.'); } } diff --git a/scripts/pi-hole/php/header.php b/scripts/pi-hole/php/header.php index 6491aa28c..e1a5cbbcf 100644 --- a/scripts/pi-hole/php/header.php +++ b/scripts/pi-hole/php/header.php @@ -13,164 +13,131 @@ check_cors(); // Generate CSRF token - if(empty($_SESSION['token'])) { - $_SESSION['token'] = base64_encode(openssl_random_pseudo_bytes(32)); - } +if (empty($_SESSION['token'])) { + $_SESSION['token'] = base64_encode(openssl_random_pseudo_bytes(32)); +} $token = $_SESSION['token']; // Try to get temperature value from different places (OS dependent) - if(file_exists("/sys/class/thermal/thermal_zone0/temp")) - { - $output = rtrim(file_get_contents("/sys/class/thermal/thermal_zone0/temp")); - } - elseif (file_exists("/sys/class/hwmon/hwmon0/temp1_input")) - { - $output = rtrim(file_get_contents("/sys/class/hwmon/hwmon0/temp1_input")); - } - else - { - $output = ""; - } +if (file_exists("/sys/class/thermal/thermal_zone0/temp")) { + $output = rtrim(file_get_contents("/sys/class/thermal/thermal_zone0/temp")); +} elseif (file_exists("/sys/class/hwmon/hwmon0/temp1_input")) { + $output = rtrim(file_get_contents("/sys/class/hwmon/hwmon0/temp1_input")); +} else { + $output = ""; +} // Test if we succeeded in getting the temperature - if(is_numeric($output)) - { - // $output could be either 4-5 digits or 2-3, and we only divide by 1000 if it's 4-5 - // ex. 39007 vs 39 - $celsius = intVal($output); +if (is_numeric($output)) { + // $output could be either 4-5 digits or 2-3, and we only divide by 1000 if it's 4-5 + // ex. 39007 vs 39 + $celsius = intVal($output); - // If celsius is greater than 1 degree and is in the 4-5 digit format - if($celsius > 1000) { - // Use multiplication to get around the division-by-zero error - $celsius *= 1e-3; - } + // If celsius is greater than 1 degree and is in the 4-5 digit format + if ($celsius > 1000) { + // Use multiplication to get around the division-by-zero error + $celsius *= 1e-3; + } - $kelvin = $celsius + 273.15; - $fahrenheit = ($celsius*9./5)+32.0; + $kelvin = $celsius + 273.15; + $fahrenheit = ($celsius * 9. / 5) + 32.0; - if(isset($setupVars['TEMPERATUREUNIT'])) - { - $temperatureunit = $setupVars['TEMPERATUREUNIT']; - } - else - { - $temperatureunit = "C"; - } - // Override temperature unit setting if it is changed via Settings page - if(isset($_POST["tempunit"])) - { - $temperatureunit = $_POST["tempunit"]; - } - // Get user-defined temperature limit if set - if(isset($setupVars['TEMPERATURE_LIMIT'])) - { - $temperaturelimit = intval($setupVars['TEMPERATURE_LIMIT']); - } - else - { - $temperaturelimit = 60; - } + if (isset($setupVars['TEMPERATUREUNIT'])) { + $temperatureunit = $setupVars['TEMPERATUREUNIT']; + } else { + $temperatureunit = "C"; + } + // Override temperature unit setting if it is changed via Settings page + if (isset($_POST["tempunit"])) { + $temperatureunit = $_POST["tempunit"]; } - else - { - // Nothing can be colder than -273.15 degree Celsius (= 0 Kelvin) - // This is the minimum temperature possible (AKA absolute zero) - $celsius = -273.16; + // Get user-defined temperature limit if set + if (isset($setupVars['TEMPERATURE_LIMIT'])) { + $temperaturelimit = intval($setupVars['TEMPERATURE_LIMIT']); + } else { + $temperaturelimit = 60; } +} else { + // Nothing can be colder than -273.15 degree Celsius (= 0 Kelvin) + // This is the minimum temperature possible (AKA absolute zero) + $celsius = -273.16; +} // Get load $loaddata = sys_getloadavg(); - foreach ($loaddata as $key => $value) { - $loaddata[$key] = round($value, 2); - } +foreach ($loaddata as $key => $value) { + $loaddata[$key] = round($value, 2); +} // Get number of processing units available to PHP // (may be less than the number of online processors) $nproc = shell_exec('nproc'); - if(!is_numeric($nproc)) - { - $cpuinfo = file_get_contents('/proc/cpuinfo'); - preg_match_all('/^processor/m', $cpuinfo, $matches); - $nproc = count($matches[0]); - } +if (!is_numeric($nproc)) { + $cpuinfo = file_get_contents('/proc/cpuinfo'); + preg_match_all('/^processor/m', $cpuinfo, $matches); + $nproc = count($matches[0]); +} // Get memory usage $data = explode("\n", file_get_contents("/proc/meminfo")); $meminfo = array(); - if(count($data) > 0) - { - foreach ($data as $line) { - $expl = explode(":", trim($line)); - if(count($expl) == 2) - { - // remove " kB" from the end of the string and make it an integer - $meminfo[$expl[0]] = intVal(substr($expl[1],0, -3)); - } +if (count($data) > 0) { + foreach ($data as $line) { + $expl = explode(":", trim($line)); + if (count($expl) == 2) { + // remove " kB" from the end of the string and make it an integer + $meminfo[$expl[0]] = intVal(substr($expl[1], 0, -3)); } - $memory_used = $meminfo["MemTotal"]-$meminfo["MemFree"]-$meminfo["Buffers"]-$meminfo["Cached"]; - $memory_total = $meminfo["MemTotal"]; - $memory_usage = $memory_used/$memory_total; - } - else - { - $memory_usage = -1; } + $memory_used = $meminfo["MemTotal"] - $meminfo["MemFree"] - $meminfo["Buffers"] - $meminfo["Cached"]; + $memory_total = $meminfo["MemTotal"]; + $memory_usage = $memory_used / $memory_total; +} else { + $memory_usage = -1; +} - if($auth) { - // For session timer - $maxlifetime = ini_get("session.gc_maxlifetime"); +if ($auth) { + // For session timer + $maxlifetime = ini_get("session.gc_maxlifetime"); - // Generate CSRF token - if(empty($_SESSION['token'])) { - $_SESSION['token'] = base64_encode(openssl_random_pseudo_bytes(32)); - } - $token = $_SESSION['token']; + // Generate CSRF token + if (empty($_SESSION['token'])) { + $_SESSION['token'] = base64_encode(openssl_random_pseudo_bytes(32)); } + $token = $_SESSION['token']; +} - if(isset($setupVars['WEBUIBOXEDLAYOUT'])) - { - if($setupVars['WEBUIBOXEDLAYOUT'] === "boxed") - { - $boxedlayout = true; - } - else - { - $boxedlayout = false; - } - } - else - { +if (isset($setupVars['WEBUIBOXEDLAYOUT'])) { + if ($setupVars['WEBUIBOXEDLAYOUT'] === "boxed") { $boxedlayout = true; + } else { + $boxedlayout = false; } +} else { + $boxedlayout = true; +} // Override layout setting if layout is changed via Settings page - if(isset($_POST["field"])) - { - if($_POST["field"] === "webUI" && isset($_POST["boxedlayout"])) - { - $boxedlayout = true; - } - elseif($_POST["field"] === "webUI" && !isset($_POST["boxedlayout"])) - { - $boxedlayout = false; - } +if (isset($_POST["field"])) { + if ($_POST["field"] === "webUI" && isset($_POST["boxedlayout"])) { + $boxedlayout = true; + } elseif ($_POST["field"] === "webUI" && !isset($_POST["boxedlayout"])) { + $boxedlayout = false; } +} - function pidofFTL() - { - return shell_exec("pidof pihole-FTL"); - } +function pidofFTL() +{ + return shell_exec("pidof pihole-FTL"); +} $FTLpid = intval(pidofFTL()); $FTL = ($FTLpid !== 0 ? true : false); $piholeFTLConfFile = "/etc/pihole/pihole-FTL.conf"; - if(is_readable($piholeFTLConfFile)) - { - $piholeFTLConf = parse_ini_file($piholeFTLConfFile); - } - else - { - $piholeFTLConf = array(); - } +if (is_readable($piholeFTLConfFile)) { + $piholeFTLConf = parse_ini_file($piholeFTLConfFile); +} else { + $piholeFTLConf = array(); +} ?> @@ -221,7 +188,7 @@ function pidofFTL() - + @@ -233,7 +200,9 @@ function pidofFTL() - +
    -
  • hidden="true"> +
  • hidden="true"> Enable   
  • -
  • active"> +
  • active"> @@ -576,37 +563,49 @@ function pidofFTL()
  • - class="active"> + class="active"> Network - class="active"> + class="active"> Settings - class="active"> + class="active"> Custom DNS - 0) { ?> + if (strlen($pwhash) > 0) { ?>
  • Logout
  • - + 0 && !$auth) { ?> - class="active"> + if (strlen($pwhash) > 0 && !$auth) { ?> + class="active"> Login @@ -658,9 +665,11 @@ function pidofFTL() Donate - + - class="active"> + class="active"> Help @@ -684,9 +693,9 @@ function pidofFTL() // // If auth is required and not set, i.e. no successfully logged in, // we show the reduced version of the summary (index) page - if(!$auth && (!isset($indexpage) || isset($_GET['login']))){ - require "scripts/pi-hole/php/loginpage.php"; - require "footer.php"; - exit(); - } +if (!$auth && (!isset($indexpage) || isset($_GET['login']))) { + require "scripts/pi-hole/php/loginpage.php"; + require "footer.php"; + exit(); +} ?> diff --git a/scripts/pi-hole/php/loginpage.php b/scripts/pi-hole/php/loginpage.php index fcd225dcd..bee9763da 100644 --- a/scripts/pi-hole/php/loginpage.php +++ b/scripts/pi-hole/php/loginpage.php @@ -10,7 +10,11 @@
    - +

    @@ -26,7 +30,9 @@
    -
    +
    @@ -47,14 +53,24 @@
    -
    +

    Forgot password

    diff --git a/scripts/pi-hole/php/password.php b/scripts/pi-hole/php/password.php index ed95ca318..ab8723f5b 100644 --- a/scripts/pi-hole/php/password.php +++ b/scripts/pi-hole/php/password.php @@ -14,94 +14,75 @@ // Read setupVars.conf file $setupVars = parse_ini_file("/etc/pihole/setupVars.conf"); // Try to read password hash from setupVars.conf - if(isset($setupVars['WEBPASSWORD'])) - { - $pwhash = $setupVars['WEBPASSWORD']; - } - else - { - $pwhash = ""; - } +if (isset($setupVars['WEBPASSWORD'])) { + $pwhash = $setupVars['WEBPASSWORD']; +} else { + $pwhash = ""; +} // If the user wants to log out, we free all session variables currently registered // and delete any persistent cookie. - if(isset($_GET["logout"])) - { - session_unset(); - setcookie('persistentlogin', ''); - header('Location: index.php'); - exit(); - } +if (isset($_GET["logout"])) { + session_unset(); + setcookie('persistentlogin', ''); + header('Location: index.php'); + exit(); +} $wrongpassword = false; $auth = false; // Test if password is set - if(strlen($pwhash) > 0) - { - // Check for and authorize from persistent cookie - if (isset($_COOKIE["persistentlogin"])) - { - if ($pwhash === $_COOKIE["persistentlogin"]) - { - $auth = true; - // Refresh cookie with new expiry - setcookie('persistentlogin', $pwhash, time()+60*60*24*7); - } - else - { - // Invalid cookie - $auth = false; - setcookie('persistentlogin', ''); - } +if (strlen($pwhash) > 0) { + // Check for and authorize from persistent cookie + if (isset($_COOKIE["persistentlogin"])) { + if ($pwhash === $_COOKIE["persistentlogin"]) { + $auth = true; + // Refresh cookie with new expiry + setcookie('persistentlogin', $pwhash, time() + 60 * 60 * 24 * 7); + } else { + // Invalid cookie + $auth = false; + setcookie('persistentlogin', ''); } - // Compare doubly hashes password input with saved hash - else if(isset($_POST["pw"])) - { - $postinput = hash('sha256',hash('sha256',$_POST["pw"])); - if(hash_equals($pwhash, $postinput)) - { - $_SESSION["hash"] = $pwhash; + } + // Compare doubly hashes password input with saved hash + elseif (isset($_POST["pw"])) { + $postinput = hash('sha256', hash('sha256', $_POST["pw"])); + if (hash_equals($pwhash, $postinput)) { + $_SESSION["hash"] = $pwhash; - // Login successful, redirect the user to the homepage to discard the POST request - if ($_SERVER['REQUEST_METHOD'] === 'POST' && $_SERVER['QUERY_STRING'] === 'login') { - // Set persistent cookie if selected - if (isset($_POST['persistentlogin'])) - { - setcookie('persistentlogin', $pwhash, time()+60*60*24*7); - } - header('Location: index.php'); - exit(); + // Login successful, redirect the user to the homepage to discard the POST request + if ($_SERVER['REQUEST_METHOD'] === 'POST' && $_SERVER['QUERY_STRING'] === 'login') { + // Set persistent cookie if selected + if (isset($_POST['persistentlogin'])) { + setcookie('persistentlogin', $pwhash, time() + 60 * 60 * 24 * 7); } - - $auth = true; + header('Location: index.php'); + exit(); } - else - { - $wrongpassword = true; - } - } - // Compare auth hash with saved hash - else if (isset($_SESSION["hash"])) - { - 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(hash_equals($pwhash, $_GET["auth"])) - $auth = true; + + $auth = true; + } else { + $wrongpassword = true; } - else - { - // Password or hash wrong - $auth = false; + } + // Compare auth hash with saved hash + elseif (isset($_SESSION["hash"])) { + if (hash_equals($pwhash, $_SESSION["hash"])) { + $auth = true; } } - else - { - // No password set - $auth = true; + // API can use the hash to get data without logging in via plain-text password + elseif (isset($api) && isset($_GET["auth"])) { + if (hash_equals($pwhash, $_GET["auth"])) { + $auth = true; + } + } else { + // Password or hash wrong + $auth = false; } -?> +} else { + // No password set + $auth = true; +} diff --git a/scripts/pi-hole/php/queryads.php b/scripts/pi-hole/php/queryads.php index f247c87a3..063dd27c6 100644 --- a/scripts/pi-hole/php/queryads.php +++ b/scripts/pi-hole/php/queryads.php @@ -14,11 +14,13 @@ header('Content-Type: text/event-stream'); header('Cache-Control: no-cache'); -function echoEvent($datatext) { - if(!isset($_GET["IE"])) - echo "data: ".implode("\ndata: ", explode("\n", $datatext))."\n\n"; - else - echo $datatext; +function echoEvent($datatext) +{ + if (!isset($_GET["IE"])) { + echo "data: " . implode("\ndata: ", explode("\n", $datatext)) . "\n\n"; + } else { + echo $datatext; + } } // Credit: http://stackoverflow.com/a/4694816/2087442 @@ -32,37 +34,27 @@ function is_valid_domain_name($domain_name) } // Test if domain is set -if(isset($_GET["domain"])) -{ +if (isset($_GET["domain"])) { // Is this a valid domain? $url = $_GET["domain"]; - if(!is_valid_domain_name($url)) - { + if (!is_valid_domain_name($url)) { echoEvent("Invalid domain!"); die(); } -} -else -{ +} else { echoEvent("No domain provided"); die(); } -if(isset($_GET["exact"])) -{ +if (isset($_GET["exact"])) { $exact = "-exact"; -} -elseif(isset($_GET["bp"])) -{ +} elseif (isset($_GET["bp"])) { $exact = "-bp"; -} -else -{ +} else { $exact = ""; } -$proc = popen("sudo pihole -q -adlist ".$url." ".$exact, 'r'); +$proc = popen("sudo pihole -q -adlist " . $url . " " . $exact, 'r'); while (!feof($proc)) { echoEvent(fread($proc, 4096)); } -?> diff --git a/scripts/pi-hole/php/savesettings.php b/scripts/pi-hole/php/savesettings.php index a7524b774..1da577734 100644 --- a/scripts/pi-hole/php/savesettings.php +++ b/scripts/pi-hole/php/savesettings.php @@ -6,811 +6,662 @@ * This file is copyright under the latest version of the EUPL. * Please see LICENSE file for your rights under this license. */ -if(!in_array(basename($_SERVER['SCRIPT_FILENAME']), ["settings.php", "teleporter.php"], true)) -{ - die("Direct access to this script is forbidden!"); +if (!in_array(basename($_SERVER['SCRIPT_FILENAME']), ["settings.php", "teleporter.php"], true)) { + die("Direct access to this script is forbidden!"); } -function validIP($address){ - if (preg_match('/[.:0]/', $address) && !preg_match('/[1-9a-f]/', $address)) { - // Test if address contains either `:` or `0` but not 1-9 or a-f - return false; - } - return !filter_var($address, FILTER_VALIDATE_IP) === false; +function validIP($address) +{ + if (preg_match('/[.:0]/', $address) && !preg_match('/[1-9a-f]/', $address)) { + // Test if address contains either `:` or `0` but not 1-9 or a-f + return false; + } + return !filter_var($address, FILTER_VALIDATE_IP) === false; } // Check for existance of variable // and test it only if it exists -function istrue(&$argument) { - if(isset($argument)) - { - if($argument) - { - return true; - } - } - return false; +function istrue(&$argument) +{ + if (isset($argument)) { + if ($argument) { + return true; + } + } + return false; } // Credit: http://stackoverflow.com/a/4694816/2087442 function validDomain($domain_name) { - $validChars = preg_match("/^([_a-z\d](-*[_a-z\d])*)(\.([_a-z\d](-*[a-z\d])*))*(\.([a-z\d])*)*$/i", $domain_name); - $lengthCheck = preg_match("/^.{1,253}$/", $domain_name); - $labelLengthCheck = preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name); - return ( $validChars && $lengthCheck && $labelLengthCheck ); //length of each label + $validChars = preg_match("/^([_a-z\d](-*[_a-z\d])*)(\.([_a-z\d](-*[a-z\d])*))*(\.([a-z\d])*)*$/i", $domain_name); + $lengthCheck = preg_match("/^.{1,253}$/", $domain_name); + $labelLengthCheck = preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name); + return ( $validChars && $lengthCheck && $labelLengthCheck ); //length of each label } function validDomainWildcard($domain_name) { - // There has to be either no or at most one "*" at the beginning of a line - $validChars = preg_match("/^((\*.)?[_a-z\d](-*[_a-z\d])*)(\.([_a-z\d](-*[a-z\d])*))*(\.([a-z\d])*)*$/i", $domain_name); - $lengthCheck = preg_match("/^.{1,253}$/", $domain_name); - $labelLengthCheck = preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name); - return ( $validChars && $lengthCheck && $labelLengthCheck ); //length of each label + // There has to be either no or at most one "*" at the beginning of a line + $validChars = preg_match("/^((\*.)?[_a-z\d](-*[_a-z\d])*)(\.([_a-z\d](-*[a-z\d])*))*(\.([a-z\d])*)*$/i", $domain_name); + $lengthCheck = preg_match("/^.{1,253}$/", $domain_name); + $labelLengthCheck = preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name); + return ( $validChars && $lengthCheck && $labelLengthCheck ); //length of each label } function validMAC($mac_addr) { // Accepted input format: 00:01:02:1A:5F:FF (characters may be lower case) - return !filter_var($mac_addr, FILTER_VALIDATE_MAC) === false; + return !filter_var($mac_addr, FILTER_VALIDATE_MAC) === false; } function formatMAC($mac_addr) { - preg_match("/([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})/", $mac_addr, $matches); - if(count($matches) > 0) - return $matches[0]; - return null; + preg_match("/([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})/", $mac_addr, $matches); + if (count($matches) > 0) { + return $matches[0]; + } + return null; } function validEmail($email) { - return filter_var($email, FILTER_VALIDATE_EMAIL) - // Make sure that the email does not contain special characters which - // may be used to execute shell commands, even though they may be valid - // in an email address. If the escaped email does not equal the original - // email, it is not safe to store in setupVars. - && escapeshellcmd($email) === $email; + return filter_var($email, FILTER_VALIDATE_EMAIL) + // Make sure that the email does not contain special characters which + // may be used to execute shell commands, even though they may be valid + // in an email address. If the escaped email does not equal the original + // email, it is not safe to store in setupVars. + && escapeshellcmd($email) === $email; } $dhcp_static_leases = array(); -function readStaticLeasesFile($origin_file="/etc/dnsmasq.d/04-pihole-static-dhcp.conf") +function readStaticLeasesFile($origin_file = "/etc/dnsmasq.d/04-pihole-static-dhcp.conf") { - global $dhcp_static_leases; - $dhcp_static_leases = array(); - try - { - $dhcpstatic = @fopen($origin_file, 'r'); - } - catch(Exception $e) - { - echo "Warning: Failed to read ".$origin_file.", this is not an error"; - return false; - } - - if(!is_resource($dhcpstatic)) - return false; - - while(!feof($dhcpstatic)) - { - // Remove any possibly existing variable with this name - $mac = ""; $one = ""; $two = ""; - sscanf(trim(fgets($dhcpstatic)),"dhcp-host=%[^,],%[^,],%[^,]",$mac,$one,$two); - if(strlen($mac) > 0 && validMAC($mac)) - { - if(validIP($one) && strlen($two) == 0) - // dhcp-host=mac,IP - no HOST - array_push($dhcp_static_leases,["hwaddr"=>$mac, "IP"=>$one, "host"=>""]); - elseif(strlen($two) == 0) - // dhcp-host=mac,hostname - no IP - array_push($dhcp_static_leases,["hwaddr"=>$mac, "IP"=>"", "host"=>$one]); - else - // dhcp-host=mac,IP,hostname - array_push($dhcp_static_leases,["hwaddr"=>$mac, "IP"=>$one, "host"=>$two]); - } - else if(validIP($one) && validDomain($mac)) - { - // dhcp-host=hostname,IP - no MAC - array_push($dhcp_static_leases,["hwaddr"=>"", "IP"=>$one, "host"=>$mac]); - } - } - return true; + global $dhcp_static_leases; + $dhcp_static_leases = array(); + try { + $dhcpstatic = @fopen($origin_file, 'r'); + } catch (Exception $e) { + echo "Warning: Failed to read " . $origin_file . ", this is not an error"; + return false; + } + + if (!is_resource($dhcpstatic)) { + return false; + } + + while (!feof($dhcpstatic)) { + // Remove any possibly existing variable with this name + $mac = ""; + $one = ""; + $two = ""; + sscanf(trim(fgets($dhcpstatic)), "dhcp-host=%[^,],%[^,],%[^,]", $mac, $one, $two); + if (strlen($mac) > 0 && validMAC($mac)) { + if (validIP($one) && strlen($two) == 0) { + // dhcp-host=mac,IP - no HOST + array_push($dhcp_static_leases, ["hwaddr" => $mac, "IP" => $one, "host" => ""]); + } elseif (strlen($two) == 0) { + // dhcp-host=mac,hostname - no IP + array_push($dhcp_static_leases, ["hwaddr" => $mac, "IP" => "", "host" => $one]); + } else { // dhcp-host=mac,IP,hostname + array_push($dhcp_static_leases, ["hwaddr" => $mac, "IP" => $one, "host" => $two]); + } + } elseif (validIP($one) && validDomain($mac)) { + // dhcp-host=hostname,IP - no MAC + array_push($dhcp_static_leases, ["hwaddr" => "", "IP" => $one, "host" => $mac]); + } + } + return true; } -function isequal(&$argument, &$compareto) { - if(isset($argument)) - { - if($argument === $compareto) - { - return true; - } - } - return false; +function isequal(&$argument, &$compareto) +{ + if (isset($argument)) { + if ($argument === $compareto) { + return true; + } + } + return false; } -function isinserverlist($addr) { - global $DNSserverslist; - foreach ($DNSserverslist as $key => $value) { - if (isequal($value['v4_1'],$addr) || isequal($value['v4_2'],$addr)) - return true; - if (isequal($value['v6_1'],$addr) || isequal($value['v6_2'],$addr)) - return true; - } - return false; +function isinserverlist($addr) +{ + global $DNSserverslist; + foreach ($DNSserverslist as $key => $value) { + if (isequal($value['v4_1'], $addr) || isequal($value['v4_2'], $addr)) { + return true; + } + if (isequal($value['v6_1'], $addr) || isequal($value['v6_2'], $addr)) { + return true; + } + } + return false; } $DNSserverslist = []; function readDNSserversList() { - // Reset list - $list = []; - $handle = @fopen("/etc/pihole/dns-servers.conf", "r"); - if ($handle) - { - while (($line = fgets($handle)) !== false) - { - $line = rtrim($line); - $line = explode(';', $line); - $name = $line[0]; - $values = []; - if (!empty($line[1])) { - $values["v4_1"] = $line[1]; - } - if (!empty($line[2])) { - $values["v4_2"] = $line[2]; - } - if (!empty($line[3])) { - $values["v6_1"] = $line[3]; - } - if (!empty($line[4])) { - $values["v6_2"] = $line[4]; - } + // Reset list + $list = []; + $handle = @fopen("/etc/pihole/dns-servers.conf", "r"); + if ($handle) { + while (($line = fgets($handle)) !== false) { + $line = rtrim($line); + $line = explode(';', $line); + $name = $line[0]; + $values = []; + if (!empty($line[1])) { + $values["v4_1"] = $line[1]; + } + if (!empty($line[2])) { + $values["v4_2"] = $line[2]; + } + if (!empty($line[3])) { + $values["v6_1"] = $line[3]; + } + if (!empty($line[4])) { + $values["v6_2"] = $line[4]; + } $list[$name] = $values; - } - fclose($handle); - } - return $list; + } + fclose($handle); + } + return $list; } require_once("database.php"); $adlist = []; function readAdlists() { - // Reset list - $list = []; - $db = SQLite3_connect(getGravityDBFilename()); - if ($db) - { - $results = $db->query("SELECT * FROM adlist"); - - while($results !== false && $res = $results->fetchArray(SQLITE3_ASSOC)) - { - array_push($list, $res); - } - $db->close(); - } - return $list; + // Reset list + $list = []; + $db = SQLite3_connect(getGravityDBFilename()); + if ($db) { + $results = $db->query("SELECT * FROM adlist"); + + while ($results !== false && $res = $results->fetchArray(SQLITE3_ASSOC)) { + array_push($list, $res); + } + $db->close(); + } + return $list; } -function addStaticDHCPLease($mac, $ip, $hostname) { - global $error, $success, $dhcp_static_leases; - - try { - if(!validMAC($mac)) - { - throw new Exception("MAC address (".htmlspecialchars($mac).") is invalid!
    ", 0); - } - $mac = strtoupper($mac); - - if(!validIP($ip) && strlen($ip) > 0) - { - throw new Exception("IP address (".htmlspecialchars($ip).") is invalid!
    ", 1); - } - - if(!validDomain($hostname) && strlen($hostname) > 0) - { - throw new Exception("Host name (".htmlspecialchars($hostname).") is invalid!
    ", 2); - } - - if(strlen($hostname) == 0 && strlen($ip) == 0) - { - throw new Exception("You can not omit both the IP address and the host name!
    ", 3); - } - - if(strlen($hostname) == 0) - $hostname = "nohost"; - - if(strlen($ip) == 0) - $ip = "noip"; - - // Test if this lease is already included - readStaticLeasesFile(); - - foreach($dhcp_static_leases as $lease) { - if($lease["hwaddr"] === $mac) - { - throw new Exception("Static release for MAC address (".htmlspecialchars($mac).") already defined!
    ", 4); - } - if($ip !== "noip" && $lease["IP"] === $ip) - { - throw new Exception("Static lease for IP address (".htmlspecialchars($ip).") already defined!
    ", 5); - } - if($lease["host"] === $hostname) - { - throw new Exception("Static lease for hostname (".htmlspecialchars($hostname).") already defined!
    ", 6); - } - } - - exec("sudo pihole -a addstaticdhcp ".$mac." ".$ip." ".$hostname); - $success .= "A new static address has been added"; - return true; - } catch(Exception $exception) { - $error .= $exception->getMessage(); - return false; - } +function addStaticDHCPLease($mac, $ip, $hostname) +{ + global $error, $success, $dhcp_static_leases; + + try { + if (!validMAC($mac)) { + throw new Exception("MAC address (" . htmlspecialchars($mac) . ") is invalid!
    ", 0); + } + $mac = strtoupper($mac); + + if (!validIP($ip) && strlen($ip) > 0) { + throw new Exception("IP address (" . htmlspecialchars($ip) . ") is invalid!
    ", 1); + } + + if (!validDomain($hostname) && strlen($hostname) > 0) { + throw new Exception("Host name (" . htmlspecialchars($hostname) . ") is invalid!
    ", 2); + } + + if (strlen($hostname) == 0 && strlen($ip) == 0) { + throw new Exception("You can not omit both the IP address and the host name!
    ", 3); + } + + if (strlen($hostname) == 0) { + $hostname = "nohost"; + } + + if (strlen($ip) == 0) { + $ip = "noip"; + } + + // Test if this lease is already included + readStaticLeasesFile(); + + foreach ($dhcp_static_leases as $lease) { + if ($lease["hwaddr"] === $mac) { + throw new Exception("Static release for MAC address (" . htmlspecialchars($mac) . ") already defined!
    ", 4); + } + if ($ip !== "noip" && $lease["IP"] === $ip) { + throw new Exception("Static lease for IP address (" . htmlspecialchars($ip) . ") already defined!
    ", 5); + } + if ($lease["host"] === $hostname) { + throw new Exception("Static lease for hostname (" . htmlspecialchars($hostname) . ") already defined!
    ", 6); + } + } + + exec("sudo pihole -a addstaticdhcp " . $mac . " " . $ip . " " . $hostname); + $success .= "A new static address has been added"; + return true; + } catch (Exception $exception) { + $error .= $exception->getMessage(); + return false; + } +} + + // Read available adlists + $adlist = readAdlists(); + // Read available DNS server list + $DNSserverslist = readDNSserversList(); + + $error = ""; + $success = ""; + +if (isset($_POST["field"])) { + // Handle CSRF + check_csrf(isset($_POST["token"]) ? $_POST["token"] : ""); + + // Process request + switch ($_POST["field"]) { + // Set DNS server + case "DNS": + $DNSservers = []; + // Add selected predefined servers to list + foreach ($DNSserverslist as $key => $value) { + foreach (["v4_1", "v4_2", "v6_1", "v6_2"] as $type) { + if (@array_key_exists("DNSserver" . str_replace(".", "_", $value[$type]), $_POST)) { + array_push($DNSservers, $value[$type]); + } + } + } + + // Test custom server fields + for ($i = 1; $i <= 4; $i++) { + if (array_key_exists("custom" . $i, $_POST)) { + $exploded = explode("#", $_POST["custom" . $i . "val"], 2); + $IP = $exploded[0]; + if (count($exploded) > 1) { + $port = $exploded[1]; + } else { + $port = "53"; + } + if (!validIP($IP)) { + $error .= "IP (" . htmlspecialchars($IP) . ") is invalid!
    "; + } elseif (!is_numeric($port)) { + $error .= "Port (" . htmlspecialchars($port) . ") is invalid!
    "; + } else { + array_push($DNSservers, $IP . "#" . $port); + } + } + } + $DNSservercount = count($DNSservers); + + // Check if at least one DNS server has been added + if ($DNSservercount < 1) { + $error .= "No DNS server has been selected.
    "; + } + + // Check if domain-needed is requested + if (isset($_POST["DNSrequiresFQDN"])) { + $extra = "domain-needed "; + } else { + $extra = "domain-not-needed "; + } + + // Check if domain-needed is requested + if (isset($_POST["DNSbogusPriv"])) { + $extra .= "bogus-priv "; + } else { + $extra .= "no-bogus-priv "; + } + + // Check if DNSSEC is requested + if (isset($_POST["DNSSEC"])) { + $extra .= "dnssec"; + } else { + $extra .= "no-dnssec"; + } + + // Check if Conditional Forwarding is requested + if (isset($_POST["conditionalForwarding"])) { + // Validate conditional forwarding IP + if (!validIP($_POST["conditionalForwardingIP"])) { + $error .= "Conditional forwarding IP (" . htmlspecialchars($_POST["conditionalForwardingIP"]) . ") is invalid!
    "; + } + + // Validate conditional forwarding domain name + if (!validDomain($_POST["conditionalForwardingDomain"])) { + $error .= "Conditional forwarding domain name (" . htmlspecialchars($_POST["conditionalForwardingDomain"]) . ") is invalid!
    "; + } + if (!$error) { + $addressArray = explode(".", $_POST["conditionalForwardingIP"]); + $reverseAddress = $addressArray[2] . "." . $addressArray[1] . "." . $addressArray[0] . ".in-addr.arpa"; + $extra .= " conditional_forwarding " . $_POST["conditionalForwardingIP"] . " " . $_POST["conditionalForwardingDomain"] . " $reverseAddress"; + } + } + + // Check if DNSinterface is set + if (isset($_POST["DNSinterface"])) { + if ($_POST["DNSinterface"] === "single") { + $DNSinterface = "single"; + } elseif ($_POST["DNSinterface"] === "all") { + $DNSinterface = "all"; + } else { + $DNSinterface = "local"; + } + } else { + // Fallback + $DNSinterface = "local"; + } + exec("sudo pihole -a -i " . $DNSinterface . " -web"); + + // If there has been no error we can save the new DNS server IPs + if (!strlen($error)) { + $IPs = implode(",", $DNSservers); + $return = exec("sudo pihole -a setdns \"" . $IPs . "\" " . $extra); + $success .= htmlspecialchars($return) . "
    "; + $success .= "The DNS settings have been updated (using " . $DNSservercount . " DNS servers)"; + } else { + $error .= "The settings have been reset to their previous values"; + } + + break; + + // Set query logging + case "Logging": + if ($_POST["action"] === "Disable") { + exec("sudo pihole -l off"); + $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 { + exec("sudo pihole -l on"); + $success .= "Logging has been enabled"; + } + + break; + + // Set domains to be excluded from being shown in Top Domains (or Ads) and Top Clients + case "API": + // Explode the contents of the textareas into PHP arrays + // \n (Unix) and \r\n (Win) will be considered as newline + // array_filter( ... ) will remove any empty lines + $domains = array_filter(preg_split('/\r\n|[\r\n]/', $_POST["domains"])); + $clients = array_filter(preg_split('/\r\n|[\r\n]/', $_POST["clients"])); + + $domainlist = ""; + $first = true; + foreach ($domains as $domain) { + if (!validDomainWildcard($domain) || validIP($domain)) { + $error .= "Top Domains/Ads entry " . htmlspecialchars($domain) . " is invalid (use only domains)!
    "; + } + if (!$first) { + $domainlist .= ","; + } else { + $first = false; + } + $domainlist .= $domain; + } + + $clientlist = ""; + $first = true; + foreach ($clients as $client) { + if (!validDomainWildcard($client) && !validIP($client)) { + $error .= "Top Clients entry " . htmlspecialchars($client) . " is invalid (use only host names and IP addresses)!
    "; + } + if (!$first) { + $clientlist .= ","; + } else { + $first = false; + } + $clientlist .= $client; + } + + // Set Top Lists options + if (!strlen($error)) { + // All entries are okay + exec("sudo pihole -a setexcludedomains " . $domainlist); + exec("sudo pihole -a setexcludeclients " . $clientlist); + $success .= "The API settings have been updated
    "; + } else { + $error .= "The settings have been reset to their previous values"; + } + + // Set query log options + if (isset($_POST["querylog-permitted"]) && isset($_POST["querylog-blocked"])) { + exec("sudo pihole -a setquerylog all"); + if (!isset($_POST["privacyMode"])) { + $success .= "All entries will be shown in Query Log"; + } else { + $success .= "Only blocked entries will be shown in Query Log"; + } + } elseif (isset($_POST["querylog-permitted"])) { + exec("sudo pihole -a setquerylog permittedonly"); + if (!isset($_POST["privacyMode"])) { + $success .= "Only permitted will be shown in Query Log"; + } else { + $success .= "No entries will be shown in Query Log"; + } + } elseif (isset($_POST["querylog-blocked"])) { + exec("sudo pihole -a setquerylog blockedonly"); + $success .= "Only blocked entries will be shown in Query Log"; + } else { + exec("sudo pihole -a setquerylog nothing"); + $success .= "No entries will be shown in Query Log"; + } + + + if (isset($_POST["privacyMode"])) { + exec("sudo pihole -a privacymode true"); + $success .= " (privacy mode enabled)"; + } else { + exec("sudo pihole -a privacymode false"); + } + + break; + + case "webUI": + if ($_POST["tempunit"] == "F") { + exec('sudo pihole -a -f'); + } elseif ($_POST["tempunit"] == "K") { + exec('sudo pihole -a -k'); + } else { + exec('sudo pihole -a -c'); + } + $adminemail = trim($_POST["adminemail"]); + if (strlen($adminemail) == 0 || !isset($adminemail)) { + $adminemail = 'noadminemail'; + } elseif (!validEmail($adminemail)) { + $error .= "Administrator email address (" . htmlspecialchars($adminemail) . ") is invalid!
    "; + } else { + exec('sudo pihole -a -e \'' . $adminemail . '\''); + } + if (isset($_POST["boxedlayout"])) { + exec('sudo pihole -a layout boxed'); + } else { + exec('sudo pihole -a layout traditional'); + } + $success .= "The webUI settings have been updated"; + break; + + case "poweroff": + exec("sudo pihole -a poweroff"); + $success = "The system will poweroff in 5 seconds..."; + break; + + case "reboot": + exec("sudo pihole -a reboot"); + $success = "The system will reboot in 5 seconds..."; + break; + + case "restartdns": + exec("sudo pihole -a restartdns"); + $success = "The DNS server has been restarted"; + break; + + case "flushlogs": + exec("sudo pihole -f"); + $success = "The Pi-hole log file has been flushed"; + break; + + case "DHCP": + if (isset($_POST["addstatic"])) { + $mac = $_POST["AddMAC"]; + $ip = $_POST["AddIP"]; + $hostname = $_POST["AddHostname"]; + + addStaticDHCPLease($mac, $ip, $hostname); + break; + } + + if (isset($_POST["removestatic"])) { + $mac = $_POST["removestatic"]; + if (!validMAC($mac)) { + $error .= "MAC address (" . htmlspecialchars($mac) . ") is invalid!
    "; + } + $mac = strtoupper($mac); + + if (!strlen($error)) { + exec("sudo pihole -a removestaticdhcp " . $mac); + $success .= "The static address with MAC address " . htmlspecialchars($mac) . " has been removed"; + } + break; + } + + if (isset($_POST["active"])) { + // Validate from IP + $from = $_POST["from"]; + if (!validIP($from)) { + $error .= "From IP (" . htmlspecialchars($from) . ") is invalid!
    "; + } + + // Validate to IP + $to = $_POST["to"]; + if (!validIP($to)) { + $error .= "To IP (" . htmlspecialchars($to) . ") is invalid!
    "; + } + + // Validate router IP + $router = $_POST["router"]; + if (!validIP($router)) { + $error .= "Router IP (" . htmlspecialchars($router) . ") is invalid!
    "; + } + + $domain = $_POST["domain"]; + + // Validate Domain name + if (!validDomain($domain)) { + $error .= "Domain name " . htmlspecialchars($domain) . " is invalid!
    "; + } + + $leasetime = $_POST["leasetime"]; + + // Validate Lease time length + if (!is_numeric($leasetime) || intval($leasetime) < 0) { + $error .= "Lease time " . htmlspecialchars($leasetime) . " is invalid!
    "; + } + + if (isset($_POST["useIPv6"])) { + $ipv6 = "true"; + $type = "(IPv4 + IPv6)"; + } else { + $ipv6 = "false"; + $type = "(IPv4)"; + } + + if (isset($_POST["DHCP_rapid_commit"])) { + $rapidcommit = "true"; + } else { + $rapidcommit = "false"; + } + + if (!strlen($error)) { + exec("sudo pihole -a enabledhcp " . $from . " " . $to . " " . $router . " " . $leasetime . " " . $domain . " " . $ipv6 . " " . $rapidcommit); + $success .= "The DHCP server has been activated " . htmlspecialchars($type); + } + } else { + exec("sudo pihole -a disabledhcp"); + $success = "The DHCP server has been deactivated"; + } + + break; + + case "adlists": + foreach ($adlist as $key => $value) { + if (isset($_POST["adlist-del-" . $key])) { + // Delete list + exec("sudo pihole -a adlist del " . escapeshellcmd($value["address"])); + } elseif (isset($_POST["adlist-enable-" . $key]) && $value["enabled"] !== 1) { + // Is not enabled, but should be + exec("sudo pihole -a adlist enable " . escapeshellcmd($value["address"])); + } elseif (!isset($_POST["adlist-enable-" . $key]) && $value["enabled"] === 1) { + // Is enabled, but shouldn't be + exec("sudo pihole -a adlist disable " . escapeshellcmd($value["address"])); + } + } + + if (strlen($_POST["newuserlists"]) > 1) { + $domains = array_filter(preg_split('/\r\n|[\r\n]/', $_POST["newuserlists"])); + $comment = "'" . $_POST["newusercomment"] . "'"; + foreach ($domains as $domain) { + exec("sudo pihole -a adlist add " . escapeshellcmd($domain) . " " . escapeshellcmd($comment)); + } + } + + // Reread available adlists + $adlist = readAdlists(); + break; + + case "privacyLevel": + $level = intval($_POST["privacylevel"]); + if ($level >= 0 && $level <= 4) { + // Check if privacylevel is already set + if (isset($piholeFTLConf["PRIVACYLEVEL"])) { + $privacylevel = intval($piholeFTLConf["PRIVACYLEVEL"]); + } else { + $privacylevel = 0; + } + + // Store privacy level + exec("sudo pihole -a privacylevel " . $level); + + if ($privacylevel > $level) { + exec("sudo pihole -a restartdns"); + $success .= "The privacy level has been decreased and the DNS resolver has been restarted"; + } elseif ($privacylevel < $level) { + $success .= "The privacy level has been increased"; + } else { + $success .= "The privacy level has been not been changed"; + } + } else { + $error .= "Invalid privacy level (" . $level . ")!"; + } + break; + // Flush network table + case "flusharp": + exec("sudo pihole arpflush quiet", $output); + $error = implode("
    ", $output); + if (strlen($error) == 0) { + $success .= "The network table has been flushed"; + } + break; + + default: + // Option not found + $debug = true; + break; + } } - // Read available adlists - $adlist = readAdlists(); - // Read available DNS server list - $DNSserverslist = readDNSserversList(); - - $error = ""; - $success = ""; - - if(isset($_POST["field"])) - { - // Handle CSRF - check_csrf(isset($_POST["token"]) ? $_POST["token"] : ""); - - // Process request - switch ($_POST["field"]) { - // Set DNS server - case "DNS": - - $DNSservers = []; - // Add selected predefined servers to list - foreach ($DNSserverslist as $key => $value) - { - foreach(["v4_1", "v4_2", "v6_1", "v6_2"] as $type) - { - if(@array_key_exists("DNSserver".str_replace(".","_",$value[$type]),$_POST)) - { - array_push($DNSservers,$value[$type]); - } - } - } - - // Test custom server fields - for($i=1;$i<=4;$i++) - { - if(array_key_exists("custom".$i,$_POST)) - { - $exploded = explode("#", $_POST["custom".$i."val"], 2); - $IP = $exploded[0]; - if(count($exploded) > 1) - { - $port = $exploded[1]; - } - else - { - $port = "53"; - } - if(!validIP($IP)) - { - $error .= "IP (".htmlspecialchars($IP).") is invalid!
    "; - } - elseif(!is_numeric($port)) - { - $error .= "Port (".htmlspecialchars($port).") is invalid!
    "; - } - else - { - array_push($DNSservers,$IP."#".$port); - } - } - } - $DNSservercount = count($DNSservers); - - // Check if at least one DNS server has been added - if($DNSservercount < 1) - { - $error .= "No DNS server has been selected.
    "; - } - - // Check if domain-needed is requested - if(isset($_POST["DNSrequiresFQDN"])) - { - $extra = "domain-needed "; - } - else - { - $extra = "domain-not-needed "; - } - - // Check if domain-needed is requested - if(isset($_POST["DNSbogusPriv"])) - { - $extra .= "bogus-priv "; - } - else - { - $extra .= "no-bogus-priv "; - } - - // Check if DNSSEC is requested - if(isset($_POST["DNSSEC"])) - { - $extra .= "dnssec"; - } - else - { - $extra .= "no-dnssec"; - } - - // Check if Conditional Forwarding is requested - if(isset($_POST["conditionalForwarding"])) - { - // Validate conditional forwarding IP - if (!validIP($_POST["conditionalForwardingIP"])) - { - $error .= "Conditional forwarding IP (".htmlspecialchars($_POST["conditionalForwardingIP"]).") is invalid!
    "; - } - - // Validate conditional forwarding domain name - if(!validDomain($_POST["conditionalForwardingDomain"])) - { - $error .= "Conditional forwarding domain name (".htmlspecialchars($_POST["conditionalForwardingDomain"]).") is invalid!
    "; - } - if(!$error) - { - $addressArray = explode(".", $_POST["conditionalForwardingIP"]); - $reverseAddress = $addressArray[2].".".$addressArray[1].".".$addressArray[0].".in-addr.arpa"; - $extra .= " conditional_forwarding ".$_POST["conditionalForwardingIP"]." ".$_POST["conditionalForwardingDomain"]." $reverseAddress"; - } - } - - // Check if DNSinterface is set - if(isset($_POST["DNSinterface"])) - { - if($_POST["DNSinterface"] === "single") - { - $DNSinterface = "single"; - } - elseif($_POST["DNSinterface"] === "all") - { - $DNSinterface = "all"; - } - else - { - $DNSinterface = "local"; - } - } - else - { - // Fallback - $DNSinterface = "local"; - } - exec("sudo pihole -a -i ".$DNSinterface." -web"); - - // If there has been no error we can save the new DNS server IPs - if(!strlen($error)) - { - $IPs = implode (",", $DNSservers); - $return = exec("sudo pihole -a setdns \"".$IPs."\" ".$extra); - $success .= htmlspecialchars($return)."
    "; - $success .= "The DNS settings have been updated (using ".$DNSservercount." DNS servers)"; - } - else - { - $error .= "The settings have been reset to their previous values"; - } - - break; - - // Set query logging - case "Logging": - - if($_POST["action"] === "Disable") - { - exec("sudo pihole -l off"); - $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 - { - exec("sudo pihole -l on"); - $success .= "Logging has been enabled"; - } - - break; - - // Set domains to be excluded from being shown in Top Domains (or Ads) and Top Clients - case "API": - - // Explode the contents of the textareas into PHP arrays - // \n (Unix) and \r\n (Win) will be considered as newline - // array_filter( ... ) will remove any empty lines - $domains = array_filter(preg_split('/\r\n|[\r\n]/', $_POST["domains"])); - $clients = array_filter(preg_split('/\r\n|[\r\n]/', $_POST["clients"])); - - $domainlist = ""; - $first = true; - foreach($domains as $domain) - { - if(!validDomainWildcard($domain) || validIP($domain)) - { - $error .= "Top Domains/Ads entry ".htmlspecialchars($domain)." is invalid (use only domains)!
    "; - } - if(!$first) - { - $domainlist .= ","; - } - else - { - $first = false; - } - $domainlist .= $domain; - } - - $clientlist = ""; - $first = true; - foreach($clients as $client) - { - if(!validDomainWildcard($client) && !validIP($client)) - { - $error .= "Top Clients entry ".htmlspecialchars($client)." is invalid (use only host names and IP addresses)!
    "; - } - if(!$first) - { - $clientlist .= ","; - } - else - { - $first = false; - } - $clientlist .= $client; - } - - // Set Top Lists options - if(!strlen($error)) - { - // All entries are okay - exec("sudo pihole -a setexcludedomains ".$domainlist); - exec("sudo pihole -a setexcludeclients ".$clientlist); - $success .= "The API settings have been updated
    "; - } - else - { - $error .= "The settings have been reset to their previous values"; - } - - // Set query log options - if(isset($_POST["querylog-permitted"]) && isset($_POST["querylog-blocked"])) - { - exec("sudo pihole -a setquerylog all"); - if(!isset($_POST["privacyMode"])) - { - $success .= "All entries will be shown in Query Log"; - } - else - { - $success .= "Only blocked entries will be shown in Query Log"; - } - } - elseif(isset($_POST["querylog-permitted"])) - { - exec("sudo pihole -a setquerylog permittedonly"); - if(!isset($_POST["privacyMode"])) - { - $success .= "Only permitted will be shown in Query Log"; - } - else - { - $success .= "No entries will be shown in Query Log"; - } - } - elseif(isset($_POST["querylog-blocked"])) - { - exec("sudo pihole -a setquerylog blockedonly"); - $success .= "Only blocked entries will be shown in Query Log"; - } - else - { - exec("sudo pihole -a setquerylog nothing"); - $success .= "No entries will be shown in Query Log"; - } - - - if(isset($_POST["privacyMode"])) - { - exec("sudo pihole -a privacymode true"); - $success .= " (privacy mode enabled)"; - } - else - { - exec("sudo pihole -a privacymode false"); - } - - break; - - case "webUI": - if($_POST["tempunit"] == "F") - { - exec('sudo pihole -a -f'); - } - elseif($_POST["tempunit"] == "K") - { - exec('sudo pihole -a -k'); - } - else - { - exec('sudo pihole -a -c'); - } - $adminemail = trim($_POST["adminemail"]); - if(strlen($adminemail) == 0 || !isset($adminemail)) - { - $adminemail = 'noadminemail'; - } - elseif(!validEmail($adminemail)) - { - $error .= "Administrator email address (".htmlspecialchars($adminemail).") is invalid!
    "; - } - else - { - exec('sudo pihole -a -e \''.$adminemail.'\''); - } - if(isset($_POST["boxedlayout"])) - { - exec('sudo pihole -a layout boxed'); - } - else - { - exec('sudo pihole -a layout traditional'); - } - $success .= "The webUI settings have been updated"; - break; - - case "poweroff": - exec("sudo pihole -a poweroff"); - $success = "The system will poweroff in 5 seconds..."; - break; - - case "reboot": - exec("sudo pihole -a reboot"); - $success = "The system will reboot in 5 seconds..."; - break; - - case "restartdns": - exec("sudo pihole -a restartdns"); - $success = "The DNS server has been restarted"; - break; - - case "flushlogs": - exec("sudo pihole -f"); - $success = "The Pi-hole log file has been flushed"; - break; - - case "DHCP": - - if(isset($_POST["addstatic"])) - { - $mac = $_POST["AddMAC"]; - $ip = $_POST["AddIP"]; - $hostname = $_POST["AddHostname"]; - - addStaticDHCPLease($mac, $ip, $hostname); - break; - } - - if(isset($_POST["removestatic"])) - { - $mac = $_POST["removestatic"]; - if(!validMAC($mac)) - { - $error .= "MAC address (".htmlspecialchars($mac).") is invalid!
    "; - } - $mac = strtoupper($mac); - - if(!strlen($error)) - { - exec("sudo pihole -a removestaticdhcp ".$mac); - $success .= "The static address with MAC address ".htmlspecialchars($mac)." has been removed"; - } - break; - } - - if(isset($_POST["active"])) - { - // Validate from IP - $from = $_POST["from"]; - if (!validIP($from)) - { - $error .= "From IP (".htmlspecialchars($from).") is invalid!
    "; - } - - // Validate to IP - $to = $_POST["to"]; - if (!validIP($to)) - { - $error .= "To IP (".htmlspecialchars($to).") is invalid!
    "; - } - - // Validate router IP - $router = $_POST["router"]; - if (!validIP($router)) - { - $error .= "Router IP (".htmlspecialchars($router).") is invalid!
    "; - } - - $domain = $_POST["domain"]; - - // Validate Domain name - if(!validDomain($domain)) - { - $error .= "Domain name ".htmlspecialchars($domain)." is invalid!
    "; - } - - $leasetime = $_POST["leasetime"]; - - // Validate Lease time length - if(!is_numeric($leasetime) || intval($leasetime) < 0) - { - $error .= "Lease time ".htmlspecialchars($leasetime)." is invalid!
    "; - } - - if(isset($_POST["useIPv6"])) - { - $ipv6 = "true"; - $type = "(IPv4 + IPv6)"; - } - else - { - $ipv6 = "false"; - $type = "(IPv4)"; - } - - if(isset($_POST["DHCP_rapid_commit"])) - { - $rapidcommit = "true"; - } - else - { - $rapidcommit = "false"; - } - - if(!strlen($error)) - { - exec("sudo pihole -a enabledhcp ".$from." ".$to." ".$router." ".$leasetime." ".$domain." ".$ipv6." ".$rapidcommit); - $success .= "The DHCP server has been activated ".htmlspecialchars($type); - } - } - else - { - exec("sudo pihole -a disabledhcp"); - $success = "The DHCP server has been deactivated"; - } - - break; - - case "adlists": - foreach ($adlist as $key => $value) - { - if(isset($_POST["adlist-del-".$key])) - { - // Delete list - exec("sudo pihole -a adlist del ".escapeshellcmd($value["address"])); - } - elseif(isset($_POST["adlist-enable-".$key]) && $value["enabled"] !== 1) - { - // Is not enabled, but should be - exec("sudo pihole -a adlist enable ".escapeshellcmd($value["address"])); - - } - elseif(!isset($_POST["adlist-enable-".$key]) && $value["enabled"] === 1) - { - // Is enabled, but shouldn't be - exec("sudo pihole -a adlist disable ".escapeshellcmd($value["address"])); - } - } - - if(strlen($_POST["newuserlists"]) > 1) - { - $domains = array_filter(preg_split('/\r\n|[\r\n]/', $_POST["newuserlists"])); - $comment = "'".$_POST["newusercomment"]."'"; - foreach($domains as $domain) - { - exec("sudo pihole -a adlist add ".escapeshellcmd($domain)." ".escapeshellcmd($comment)); - } - } - - // Reread available adlists - $adlist = readAdlists(); - break; - - case "privacyLevel": - $level = intval($_POST["privacylevel"]); - if($level >= 0 && $level <= 4) - { - // Check if privacylevel is already set - if (isset($piholeFTLConf["PRIVACYLEVEL"])) { - $privacylevel = intval($piholeFTLConf["PRIVACYLEVEL"]); - } else { - $privacylevel = 0; - } - - // Store privacy level - exec("sudo pihole -a privacylevel ".$level); - - if($privacylevel > $level) - { - exec("sudo pihole -a restartdns"); - $success .= "The privacy level has been decreased and the DNS resolver has been restarted"; - } - elseif($privacylevel < $level) - { - $success .= "The privacy level has been increased"; - } - else - { - $success .= "The privacy level has been not been changed"; - } - } - else - { - $error .= "Invalid privacy level (".$level.")!"; - } - break; - // Flush network table - case "flusharp": - exec("sudo pihole arpflush quiet", $output); - $error = implode("
    ", $output); - if(strlen($error) == 0) - { - $success .= "The network table has been flushed"; - } - break; - - default: - // Option not found - $debug = true; - break; - } - } - - // Credit: http://stackoverflow.com/a/5501447/2087442 - function formatSizeUnits($bytes) - { - if ($bytes >= 1073741824) - { - $bytes = number_format($bytes / 1073741824, 2) . ' GB'; - } - elseif ($bytes >= 1048576) - { - $bytes = number_format($bytes / 1048576, 2) . ' MB'; - } - elseif ($bytes >= 1024) - { - $bytes = number_format($bytes / 1024, 2) . ' kB'; - } - elseif ($bytes > 1) - { - $bytes = $bytes . ' bytes'; - } - elseif ($bytes == 1) - { - $bytes = $bytes . ' byte'; - } - else - { - $bytes = '0 bytes'; - } - - return $bytes; - } -?> + // Credit: http://stackoverflow.com/a/5501447/2087442 +function formatSizeUnits($bytes) +{ + if ($bytes >= 1073741824) { + $bytes = number_format($bytes / 1073741824, 2) . ' GB'; + } elseif ($bytes >= 1048576) { + $bytes = number_format($bytes / 1048576, 2) . ' MB'; + } elseif ($bytes >= 1024) { + $bytes = number_format($bytes / 1024, 2) . ' kB'; + } elseif ($bytes > 1) { + $bytes = $bytes . ' bytes'; + } elseif ($bytes == 1) { + $bytes = $bytes . ' byte'; + } else { + $bytes = '0 bytes'; + } + + return $bytes; +} diff --git a/scripts/pi-hole/php/sub.php b/scripts/pi-hole/php/sub.php index cdee3ceba..813235899 100644 --- a/scripts/pi-hole/php/sub.php +++ b/scripts/pi-hole/php/sub.php @@ -25,27 +25,26 @@ $GRAVITYDB = getGravityDBFilename(); $db = SQLite3_connect($GRAVITYDB, SQLITE3_OPEN_READWRITE); -switch($type) { - case "white": - echo remove_from_table($db, "domainlist", $domains, false, ListType::whitelist); - break; +switch ($type) { + case "white": + echo remove_from_table($db, "domainlist", $domains, false, ListType::whitelist); + break; - case "black": - echo remove_from_table($db, "domainlist", $domains, false, ListType::blacklist); - break; + case "black": + echo remove_from_table($db, "domainlist", $domains, false, ListType::blacklist); + break; - case "white_regex": - echo remove_from_table($db, "domainlist", $domains, false, ListType::regex_whitelist); - break; + case "white_regex": + echo remove_from_table($db, "domainlist", $domains, false, ListType::regex_whitelist); + break; - case "black_regex": - echo remove_from_table($db, "domainlist", $domains, false, ListType::regex_blacklist); - break; + case "black_regex": + echo remove_from_table($db, "domainlist", $domains, false, ListType::regex_blacklist); + break; - default: - die("Invalid list!"); + default: + die("Invalid list!"); } // Reload lists in pihole-FTL after having removed something echo shell_exec("sudo pihole restartdns reload"); -?> diff --git a/scripts/pi-hole/php/tailLog.php b/scripts/pi-hole/php/tailLog.php index f778d5616..9e0f9c9b6 100644 --- a/scripts/pi-hole/php/tailLog.php +++ b/scripts/pi-hole/php/tailLog.php @@ -7,42 +7,37 @@ * Please see LICENSE file for your rights under this license. */ require "password.php"; -if(!$auth) die("Not authorized"); +if (!$auth) { + die("Not authorized"); +} // Not using SplFileObject here, since direct // usage of f-streams will be much faster for // files as large as the pihole.log -if(isset($_GET["FTL"])) -{ - $file = fopen("/var/log/pihole-FTL.log","r"); -} -else -{ - $file = fopen("/var/log/pihole.log","r"); +if (isset($_GET["FTL"])) { + $file = fopen("/var/log/pihole-FTL.log", "r"); +} else { + $file = fopen("/var/log/pihole.log", "r"); } -if(!$file) -{ - die(json_encode(array("offset" => 0, "lines" => array("Failed to open log file. Check permissions!\n")))); +if (!$file) { + die(json_encode(array("offset" => 0, "lines" => array("Failed to open log file. Check permissions!\n")))); } -if(isset($_GET["offset"])) -{ - $offset = intval($_GET['offset']); - if($offset > 0) - { - // Seeks on the file pointer where we want to continue reading is known - fseek($file, $offset); - $lines = []; - while (!feof($file)) - array_push($lines, htmlspecialchars(fgets($file))); - die(json_encode(array("offset" => ftell($file), "lines" => $lines))); - } +if (isset($_GET["offset"])) { + $offset = intval($_GET['offset']); + if ($offset > 0) { + // Seeks on the file pointer where we want to continue reading is known + fseek($file, $offset); + $lines = []; + while (!feof($file)) { + array_push($lines, htmlspecialchars(fgets($file))); + } + die(json_encode(array("offset" => ftell($file), "lines" => $lines))); + } } // Locate the current position of the file read/write pointer fseek($file, -1, SEEK_END); // Add one to skip the very last "\n" in the log file -die(json_encode(array("offset" => ftell($file)+1))); - -?> +die(json_encode(array("offset" => ftell($file) + 1))); diff --git a/scripts/pi-hole/php/teleporter.php b/scripts/pi-hole/php/teleporter.php index 7c34c47fa..1767fa706 100644 --- a/scripts/pi-hole/php/teleporter.php +++ b/scripts/pi-hole/php/teleporter.php @@ -12,19 +12,22 @@ require "savesettings.php"; if (php_sapi_name() !== "cli") { - if(!$auth) die("Not authorized"); - check_csrf(isset($_POST["token"]) ? $_POST["token"] : ""); + if (!$auth) { + die("Not authorized"); + } + check_csrf(isset($_POST["token"]) ? $_POST["token"] : ""); } $db = SQLite3_connect(getGravityDBFilename(), SQLITE3_OPEN_READWRITE); $flushed_tables = array(); -function archive_add_file($path,$name,$subdir="") +function archive_add_file($path, $name, $subdir = "") { - global $archive; - if(file_exists($path.$name)) - $archive[$subdir.$name] = file_get_contents($path.$name); + global $archive; + if (file_exists($path . $name)) { + $archive[$subdir . $name] = file_get_contents($path . $name); + } } /** @@ -34,32 +37,29 @@ function archive_add_file($path,$name,$subdir="") * @param $table string The table to export * @param $type integer Type of domains to store */ -function archive_add_table($name, $table, $type=-1) +function archive_add_table($name, $table, $type = -1) { - global $archive, $db; - - if($type > -1) - { - $querystr = "SELECT * FROM $table WHERE type = $type;"; - } - else - { - $querystr = "SELECT * FROM $table;"; - } - $results = $db->query($querystr); - - // Return early without creating a file if the - // requested table cannot be accessed - if(is_null($results)) - return; - - $content = array(); - while ($row = $results->fetchArray(SQLITE3_ASSOC)) - { - array_push($content, $row); - } - - $archive[$name] = json_encode($content); + global $archive, $db; + + if ($type > -1) { + $querystr = "SELECT * FROM $table WHERE type = $type;"; + } else { + $querystr = "SELECT * FROM $table;"; + } + $results = $db->query($querystr); + + // Return early without creating a file if the + // requested table cannot be accessed + if (is_null($results)) { + return; + } + + $content = array(); + while ($row = $results->fetchArray(SQLITE3_ASSOC)) { + array_push($content, $row); + } + + $archive[$name] = json_encode($content); } /** @@ -70,116 +70,108 @@ function archive_add_table($name, $table, $type=-1) * @param $flush boolean Whether to flush the table before importing the archived data * @return integer Number of restored rows */ -function archive_restore_table($file, $table, $flush=false) +function archive_restore_table($file, $table, $flush = false) { - global $db, $flushed_tables; - - $json_string = file_get_contents($file); - // Return early if we cannot extract the JSON string - if(is_null($json_string)) - return 0; - - $contents = json_decode($json_string, true); - // Return early if we cannot decode the JSON string - if(is_null($contents)) - return 0; - - // Flush table if requested, only flush each table once - if($flush && !in_array($table, $flushed_tables)) - { - $db->exec("DELETE FROM ".$table); - array_push($flushed_tables, $table); - } - - // Prepare field name for domain/address depending on the table we restore to - if($table === "adlist") - { - $sql = "INSERT OR IGNORE INTO adlist"; - $sql .= " (id,address,enabled,date_added,comment)"; - $sql .= " VALUES (:id,:address,:enabled,:date_added,:comment);"; - $field = "address"; - } - elseif($table === "domain_audit") - { - $sql = "INSERT OR IGNORE INTO domain_audit"; - $sql .= " (id,domain,date_added)"; - $sql .= " VALUES (:id,:domain,:date_added);"; - $field = "domain"; - } - elseif($table === "domainlist") - { - $sql = "INSERT OR IGNORE INTO domainlist"; - $sql .= " (id,domain,enabled,date_added,comment,type)"; - $sql .= " VALUES (:id,:domain,:enabled,:date_added,:comment,:type);"; - $field = "domain"; - } - else - { - if($table === "whitelist") - $type = 0; - elseif($table === "blacklist") - $type = 1; - elseif($table === "regex_whitelist") - $type = 2; - elseif($table === "regex_blacklist") - $type = 3; - - $sql = "INSERT OR IGNORE INTO domainlist"; - $sql .= " (id,domain,enabled,date_added,comment,type)"; - $sql .= " VALUES (:id,:domain,:enabled,:date_added,:comment,$type);"; - $field = "domain"; - } - - // Prepare SQLite statememt - $stmt = $db->prepare($sql); - - // Return early if we fail to prepare the SQLite statement - if(!$stmt) - { - echo "Failed to prepare statement for ".$table." table."; - echo $sql; - return 0; - } - - // Loop over rows and inject the entries into the database - $num = 0; - foreach($contents as $row) - { - // Limit max length for a domain entry to 253 chars - if(strlen($row[$field]) > 253) - continue; - - $stmt->bindValue(":id", $row["id"], SQLITE3_INTEGER); - $stmt->bindValue(":date_added", $row["date_added"], SQLITE3_INTEGER); - $stmt->bindValue(":".$field, $row[$field], SQLITE3_TEXT); - - if($table !== "domain_audit") - { - $stmt->bindValue(":enabled", $row["enabled"], SQLITE3_INTEGER); - if(is_null($row["comment"])) - $type = SQLITE3_NULL; - else - $type = SQLITE3_TEXT; - $stmt->bindValue(":comment", $row["comment"], $type); - } - - if($table === "domainlist") - { - $stmt->bindValue(":type", $row["type"], SQLITE3_INTEGER); - } - - if($stmt->execute() && $stmt->reset() && $stmt->clear()) - $num++; - else - { - $stmt->close(); - return $num; - } - } - - // Close database connection and return number or processed rows - $stmt->close(); - return $num; + global $db, $flushed_tables; + + $json_string = file_get_contents($file); + // Return early if we cannot extract the JSON string + if (is_null($json_string)) { + return 0; + } + + $contents = json_decode($json_string, true); + // Return early if we cannot decode the JSON string + if (is_null($contents)) { + return 0; + } + + // Flush table if requested, only flush each table once + if ($flush && !in_array($table, $flushed_tables)) { + $db->exec("DELETE FROM " . $table); + array_push($flushed_tables, $table); + } + + // Prepare field name for domain/address depending on the table we restore to + if ($table === "adlist") { + $sql = "INSERT OR IGNORE INTO adlist"; + $sql .= " (id,address,enabled,date_added,comment)"; + $sql .= " VALUES (:id,:address,:enabled,:date_added,:comment);"; + $field = "address"; + } elseif ($table === "domain_audit") { + $sql = "INSERT OR IGNORE INTO domain_audit"; + $sql .= " (id,domain,date_added)"; + $sql .= " VALUES (:id,:domain,:date_added);"; + $field = "domain"; + } elseif ($table === "domainlist") { + $sql = "INSERT OR IGNORE INTO domainlist"; + $sql .= " (id,domain,enabled,date_added,comment,type)"; + $sql .= " VALUES (:id,:domain,:enabled,:date_added,:comment,:type);"; + $field = "domain"; + } else { + if ($table === "whitelist") { + $type = 0; + } elseif ($table === "blacklist") { + $type = 1; + } elseif ($table === "regex_whitelist") { + $type = 2; + } elseif ($table === "regex_blacklist") { + $type = 3; + } + + $sql = "INSERT OR IGNORE INTO domainlist"; + $sql .= " (id,domain,enabled,date_added,comment,type)"; + $sql .= " VALUES (:id,:domain,:enabled,:date_added,:comment,$type);"; + $field = "domain"; + } + + // Prepare SQLite statememt + $stmt = $db->prepare($sql); + + // Return early if we fail to prepare the SQLite statement + if (!$stmt) { + echo "Failed to prepare statement for " . $table . " table."; + echo $sql; + return 0; + } + + // Loop over rows and inject the entries into the database + $num = 0; + foreach ($contents as $row) { + // Limit max length for a domain entry to 253 chars + if (strlen($row[$field]) > 253) { + continue; + } + + $stmt->bindValue(":id", $row["id"], SQLITE3_INTEGER); + $stmt->bindValue(":date_added", $row["date_added"], SQLITE3_INTEGER); + $stmt->bindValue(":" . $field, $row[$field], SQLITE3_TEXT); + + if ($table !== "domain_audit") { + $stmt->bindValue(":enabled", $row["enabled"], SQLITE3_INTEGER); + if (is_null($row["comment"])) { + $type = SQLITE3_NULL; + } else { + $type = SQLITE3_TEXT; + } + $stmt->bindValue(":comment", $row["comment"], $type); + } + + if ($table === "domainlist") { + $stmt->bindValue(":type", $row["type"], SQLITE3_INTEGER); + } + + if ($stmt->execute() && $stmt->reset() && $stmt->clear()) { + $num++; + } else { + $stmt->close(); + return $num; + } + } + + // Close database connection and return number or processed rows + $stmt->close(); + return $num; } /** @@ -191,248 +183,225 @@ function archive_restore_table($file, $table, $flush=false) * @param $wildcardstyle boolean Whether to format the input domains in legacy wildcard notation * @return integer Number of processed rows from the imported file */ -function archive_insert_into_table($file, $table, $flush=false, $wildcardstyle=false) +function archive_insert_into_table($file, $table, $flush = false, $wildcardstyle = false) { - global $db, $flushed_tables; - - $domains = array_filter(explode("\n",file_get_contents($file))); - // Return early if we cannot extract the lines in the file - if(is_null($domains)) - return 0; - - // Flush table if requested, only flush each table once - if($flush && !in_array($table, $flushed_tables)) - { - $db->exec("DELETE FROM ".$table); - array_push($flushed_tables, $table); - } - - // Add domains to requested table - return add_to_table($db, $table, $domains, $wildcardstyle, true); + global $db, $flushed_tables; + + $domains = array_filter(explode("\n", file_get_contents($file))); + // Return early if we cannot extract the lines in the file + if (is_null($domains)) { + return 0; + } + + // Flush table if requested, only flush each table once + if ($flush && !in_array($table, $flushed_tables)) { + $db->exec("DELETE FROM " . $table); + array_push($flushed_tables, $table); + } + + // Add domains to requested table + return add_to_table($db, $table, $domains, $wildcardstyle, true); } -function archive_add_directory($path,$subdir="") +function archive_add_directory($path, $subdir = "") { - if($dir = opendir($path)) - { - while(false !== ($entry = readdir($dir))) - { - if($entry !== "." && $entry !== "..") - { - archive_add_file($path,$entry,$subdir); - } - } - closedir($dir); - } + if ($dir = opendir($path)) { + while (false !== ($entry = readdir($dir))) { + if ($entry !== "." && $entry !== "..") { + archive_add_file($path, $entry, $subdir); + } + } + closedir($dir); + } } function limit_length(&$item, $key) { - // limit max length for a domain entry to 253 chars - // return only a part of the string if it is longer - $item = substr($item, 0, 253); + // limit max length for a domain entry to 253 chars + // return only a part of the string if it is longer + $item = substr($item, 0, 253); } function process_file($contents) { - $domains = array_filter(explode("\n",$contents)); - // Walk array and apply a max string length - // function to every member of the array of domains - array_walk($domains, "limit_length"); - return $domains; + $domains = array_filter(explode("\n", $contents)); + // Walk array and apply a max string length + // function to every member of the array of domains + array_walk($domains, "limit_length"); + return $domains; } -if(isset($_POST["action"])) -{ - if($_FILES["zip_file"]["name"] && $_POST["action"] == "in") - { - $filename = $_FILES["zip_file"]["name"]; - $source = $_FILES["zip_file"]["tmp_name"]; - $type = mime_content_type($source); - - $name = explode(".", $filename); - $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; - } - } - - $continue = strtolower($name[1]) == 'tar' && strtolower($name[2]) == 'gz' ? true : false; - if(!$continue || !$okay) { - die("The file you are trying to upload is not a .tar.gz file (filename: ".htmlentities($filename).", type: ".htmlentities($type)."). Please try again."); - } - - $fullfilename = sys_get_temp_dir()."/".$filename; - if(!move_uploaded_file($source, $fullfilename)) - { - die("Failed moving ".htmlentities($source)." to ".htmlentities($fullfilename)); - } - - $archive = new PharData($fullfilename); - - $importedsomething = false; - - $flushtables = isset($_POST["flushtables"]); - - foreach(new RecursiveIteratorIterator($archive) as $file) - { - if(isset($_POST["blacklist"]) && $file->getFilename() === "blacklist.txt") - { - $num = archive_insert_into_table($file, "blacklist", $flushtables); - echo "Processed blacklist (exact) (".$num." entries)
    \n"; - $importedsomething = true; - } - - if(isset($_POST["whitelist"]) && $file->getFilename() === "whitelist.txt") - { - $num = archive_insert_into_table($file, "whitelist", $flushtables); - echo "Processed whitelist (exact) (".$num." entries)
    \n"; - $importedsomething = true; - } - - if(isset($_POST["regexlist"]) && $file->getFilename() === "regex.list") - { - $num = archive_insert_into_table($file, "regex_blacklist", $flushtables); - echo "Processed blacklist (regex) (".$num." entries)
    \n"; - $importedsomething = true; - } - - // Also try to import legacy wildcard list if found - if(isset($_POST["regexlist"]) && $file->getFilename() === "wildcardblocking.txt") - { - $num = archive_insert_into_table($file, "regex_blacklist", $flushtables, true); - echo "Processed blacklist (regex, wildcard style) (".$num." entries)
    \n"; - $importedsomething = true; - } - - if(isset($_POST["auditlog"]) && $file->getFilename() === "auditlog.list") - { - $num = archive_insert_into_table($file, "domain_audit", $flushtables); - echo "Processed blacklist (regex) (".$num." entries)
    \n"; - $importedsomething = true; - } - - if(isset($_POST["blacklist"]) && $file->getFilename() === "blacklist.exact.json") - { - $num = archive_restore_table($file, "blacklist", $flushtables); - echo "Processed blacklist (exact) (".$num." entries)
    \n"; - $importedsomething = true; - } - - if(isset($_POST["regexlist"]) && $file->getFilename() === "blacklist.regex.json") - { - $num = archive_restore_table($file, "regex_blacklist", $flushtables); - echo "Processed blacklist (regex) (".$num." entries)
    \n"; - $importedsomething = true; - } - - if(isset($_POST["whitelist"]) && $file->getFilename() === "whitelist.exact.json") - { - $num = archive_restore_table($file, "whitelist", $flushtables); - echo "Processed whitelist (exact) (".$num." entries)
    \n"; - $importedsomething = true; - } - - if(isset($_POST["regex_whitelist"]) && $file->getFilename() === "whitelist.regex.json") - { - $num = archive_restore_table($file, "regex_whitelist", $flushtables); - echo "Processed whitelist (regex) (".$num." entries)
    \n"; - $importedsomething = true; - } - - if(isset($_POST["adlist"]) && $file->getFilename() === "adlist.json") - { - $num = archive_restore_table($file, "adlist", $flushtables); - echo "Processed adlist (".$num." entries)
    \n"; - $importedsomething = true; - } - - if(isset($_POST["auditlog"]) && $file->getFilename() === "domain_audit.json") - { - $num = archive_restore_table($file, "domain_audit", $flushtables); - echo "Processed domain_audit (".$num." entries)
    \n"; - $importedsomething = true; - } - - if(isset($_POST["staticdhcpleases"]) && $file->getFilename() === "04-pihole-static-dhcp.conf") - { - if($flushtables) { - $local_file = @fopen("/etc/dnsmasq.d/04-pihole-static-dhcp.conf", "r+"); - if ($local_file !== false) { - ftruncate($local_file, 0); - fclose($local_file); - } - } - $num = 0; - $staticdhcpleases = process_file(file_get_contents($file)); - foreach($staticdhcpleases as $lease) { - list($mac,$ip,$hostname) = explode(",",$lease); - $mac = formatMAC($mac); - if(addStaticDHCPLease($mac,$ip,$hostname)) - $num++; - } - - readStaticLeasesFile(); - echo "Processed static DHCP leases (".$num." entries)
    \n"; - if($num > 0) { - $importedsomething = true; - } - } - } - - if($importedsomething) - { - exec("sudo pihole restartdns reload"); - } - - unlink($fullfilename); - echo "OK"; - } - else - { - die("No file transmitted or parameter error."); - } -} -else -{ - $tarname = "pi-hole-teleporter_".date("Y-m-d_h-i-s").".tar"; - $filename = $tarname.".gz"; - $archive_file_name = sys_get_temp_dir() ."/". $tarname; - $archive = new PharData($archive_file_name); - - if ($archive->isWritable() !== TRUE) { - exit("cannot open/create ".htmlentities($archive_file_name)."
    \nPHP user: ".exec('whoami')."\n"); - } - - archive_add_table("whitelist.exact.json", "domainlist", ListType::whitelist); - archive_add_table("whitelist.regex.json", "domainlist", ListType::regex_whitelist); - archive_add_table("blacklist.exact.json", "domainlist", ListType::blacklist); - archive_add_table("blacklist.regex.json", "domainlist", ListType::regex_blacklist); - archive_add_table("adlist.json", "adlist"); - archive_add_table("domain_audit.json", "domain_audit"); - archive_add_file("/etc/pihole/","setupVars.conf"); - archive_add_file("/etc/pihole/","dhcp.leases"); - archive_add_file("/etc/","hosts","etc/"); - archive_add_directory("/etc/dnsmasq.d/","dnsmasq.d/"); - - $archive->compress(Phar::GZ); // Creates a gziped copy - unlink($archive_file_name); // Unlink original tar file as it is not needed anymore - $archive_file_name .= ".gz"; // Append ".gz" extension to ".tar" - - header("Content-type: application/gzip"); - header('Content-Transfer-Encoding: binary'); - header("Content-Disposition: attachment; filename=".$filename); - header("Content-length: " . filesize($archive_file_name)); - header("Pragma: no-cache"); - header("Expires: 0"); - if(ob_get_length() > 0) ob_end_clean(); - readfile($archive_file_name); - ignore_user_abort(true); - unlink($archive_file_name); - exit; +if (isset($_POST["action"])) { + if ($_FILES["zip_file"]["name"] && $_POST["action"] == "in") { + $filename = $_FILES["zip_file"]["name"]; + $source = $_FILES["zip_file"]["tmp_name"]; + $type = mime_content_type($source); + + $name = explode(".", $filename); + $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; + } + } + + $continue = strtolower($name[1]) == 'tar' && strtolower($name[2]) == 'gz' ? true : false; + if (!$continue || !$okay) { + die("The file you are trying to upload is not a .tar.gz file (filename: " . htmlentities($filename) . ", type: " . htmlentities($type) . "). Please try again."); + } + + $fullfilename = sys_get_temp_dir() . "/" . $filename; + if (!move_uploaded_file($source, $fullfilename)) { + die("Failed moving " . htmlentities($source) . " to " . htmlentities($fullfilename)); + } + + $archive = new PharData($fullfilename); + + $importedsomething = false; + + $flushtables = isset($_POST["flushtables"]); + + foreach (new RecursiveIteratorIterator($archive) as $file) { + if (isset($_POST["blacklist"]) && $file->getFilename() === "blacklist.txt") { + $num = archive_insert_into_table($file, "blacklist", $flushtables); + echo "Processed blacklist (exact) (" . $num . " entries)
    \n"; + $importedsomething = true; + } + + if (isset($_POST["whitelist"]) && $file->getFilename() === "whitelist.txt") { + $num = archive_insert_into_table($file, "whitelist", $flushtables); + echo "Processed whitelist (exact) (" . $num . " entries)
    \n"; + $importedsomething = true; + } + + if (isset($_POST["regexlist"]) && $file->getFilename() === "regex.list") { + $num = archive_insert_into_table($file, "regex_blacklist", $flushtables); + echo "Processed blacklist (regex) (" . $num . " entries)
    \n"; + $importedsomething = true; + } + + // Also try to import legacy wildcard list if found + if (isset($_POST["regexlist"]) && $file->getFilename() === "wildcardblocking.txt") { + $num = archive_insert_into_table($file, "regex_blacklist", $flushtables, true); + echo "Processed blacklist (regex, wildcard style) (" . $num . " entries)
    \n"; + $importedsomething = true; + } + + if (isset($_POST["auditlog"]) && $file->getFilename() === "auditlog.list") { + $num = archive_insert_into_table($file, "domain_audit", $flushtables); + echo "Processed blacklist (regex) (" . $num . " entries)
    \n"; + $importedsomething = true; + } + + if (isset($_POST["blacklist"]) && $file->getFilename() === "blacklist.exact.json") { + $num = archive_restore_table($file, "blacklist", $flushtables); + echo "Processed blacklist (exact) (" . $num . " entries)
    \n"; + $importedsomething = true; + } + + if (isset($_POST["regexlist"]) && $file->getFilename() === "blacklist.regex.json") { + $num = archive_restore_table($file, "regex_blacklist", $flushtables); + echo "Processed blacklist (regex) (" . $num . " entries)
    \n"; + $importedsomething = true; + } + + if (isset($_POST["whitelist"]) && $file->getFilename() === "whitelist.exact.json") { + $num = archive_restore_table($file, "whitelist", $flushtables); + echo "Processed whitelist (exact) (" . $num . " entries)
    \n"; + $importedsomething = true; + } + + if (isset($_POST["regex_whitelist"]) && $file->getFilename() === "whitelist.regex.json") { + $num = archive_restore_table($file, "regex_whitelist", $flushtables); + echo "Processed whitelist (regex) (" . $num . " entries)
    \n"; + $importedsomething = true; + } + + if (isset($_POST["adlist"]) && $file->getFilename() === "adlist.json") { + $num = archive_restore_table($file, "adlist", $flushtables); + echo "Processed adlist (" . $num . " entries)
    \n"; + $importedsomething = true; + } + + if (isset($_POST["auditlog"]) && $file->getFilename() === "domain_audit.json") { + $num = archive_restore_table($file, "domain_audit", $flushtables); + echo "Processed domain_audit (" . $num . " entries)
    \n"; + $importedsomething = true; + } + + if (isset($_POST["staticdhcpleases"]) && $file->getFilename() === "04-pihole-static-dhcp.conf") { + if ($flushtables) { + $local_file = @fopen("/etc/dnsmasq.d/04-pihole-static-dhcp.conf", "r+"); + if ($local_file !== false) { + ftruncate($local_file, 0); + fclose($local_file); + } + } + $num = 0; + $staticdhcpleases = process_file(file_get_contents($file)); + foreach ($staticdhcpleases as $lease) { + list($mac,$ip,$hostname) = explode(",", $lease); + $mac = formatMAC($mac); + if (addStaticDHCPLease($mac, $ip, $hostname)) { + $num++; + } + } + + readStaticLeasesFile(); + echo "Processed static DHCP leases (" . $num . " entries)
    \n"; + if ($num > 0) { + $importedsomething = true; + } + } + } + + if ($importedsomething) { + exec("sudo pihole restartdns reload"); + } + + unlink($fullfilename); + echo "OK"; + } else { + die("No file transmitted or parameter error."); + } +} else { + $tarname = "pi-hole-teleporter_" . date("Y-m-d_h-i-s") . ".tar"; + $filename = $tarname . ".gz"; + $archive_file_name = sys_get_temp_dir() . "/" . $tarname; + $archive = new PharData($archive_file_name); + + if ($archive->isWritable() !== true) { + exit("cannot open/create " . htmlentities($archive_file_name) . "
    \nPHP user: " . exec('whoami') . "\n"); + } + + archive_add_table("whitelist.exact.json", "domainlist", ListType::whitelist); + archive_add_table("whitelist.regex.json", "domainlist", ListType::regex_whitelist); + archive_add_table("blacklist.exact.json", "domainlist", ListType::blacklist); + archive_add_table("blacklist.regex.json", "domainlist", ListType::regex_blacklist); + archive_add_table("adlist.json", "adlist"); + archive_add_table("domain_audit.json", "domain_audit"); + archive_add_file("/etc/pihole/", "setupVars.conf"); + archive_add_file("/etc/pihole/", "dhcp.leases"); + archive_add_file("/etc/", "hosts", "etc/"); + archive_add_directory("/etc/dnsmasq.d/", "dnsmasq.d/"); + + $archive->compress(Phar::GZ); // Creates a gziped copy + unlink($archive_file_name); // Unlink original tar file as it is not needed anymore + $archive_file_name .= ".gz"; // Append ".gz" extension to ".tar" + + header("Content-type: application/gzip"); + header('Content-Transfer-Encoding: binary'); + header("Content-Disposition: attachment; filename=" . $filename); + header("Content-length: " . filesize($archive_file_name)); + header("Pragma: no-cache"); + header("Expires: 0"); + if (ob_get_length() > 0) { + ob_end_clean(); + } + readfile($archive_file_name); + ignore_user_abort(true); + unlink($archive_file_name); + exit; } - -?> diff --git a/scripts/pi-hole/php/update_checker.php b/scripts/pi-hole/php/update_checker.php index d479318a4..beb47ecff 100644 --- a/scripts/pi-hole/php/update_checker.php +++ b/scripts/pi-hole/php/update_checker.php @@ -4,95 +4,77 @@ $localbranches = "/etc/pihole/localbranches"; $GitHubVersions = "/etc/pihole/GitHubVersions"; -if(!is_readable($localversions) || !is_readable($localbranches) || !is_readable($GitHubVersions)) -{ - $core_branch = "master"; - $core_current = "N/A"; - $core_update = false; - $web_branch = "master"; - $web_current = "N/A"; - $web_update = false; - $FTL_current = "N/A"; - $FTL_update = false; -} -else -{ - $versions = explode(" ", file_get_contents($localversions)); - $branches = explode(" ", file_get_contents($localbranches)); - $GitHubversions = explode(" ", file_get_contents($GitHubVersions)); - - /********** Get Pi-hole core branch / version / commit **********/ - // Check if on a dev branch - $core_branch = $branches[0]; - if($core_branch !== "master") { - $core_current = "vDev"; - $core_commit = $versions[0]; - } - else { - $core_current = explode("-",$versions[0])[0]; - } +if (!is_readable($localversions) || !is_readable($localbranches) || !is_readable($GitHubVersions)) { + $core_branch = "master"; + $core_current = "N/A"; + $core_update = false; + $web_branch = "master"; + $web_current = "N/A"; + $web_update = false; + $FTL_current = "N/A"; + $FTL_update = false; +} else { + $versions = explode(" ", file_get_contents($localversions)); + $branches = explode(" ", file_get_contents($localbranches)); + $GitHubversions = explode(" ", file_get_contents($GitHubVersions)); - /********** Get Pi-hole web branch / version / commit **********/ - $web_branch = $branches[1]; - if($web_branch !== "master") { - $web_current = "vDev"; - $web_commit = $versions[1]; - } - else { - $web_current = explode("-",$versions[1])[0]; - } + /********** Get Pi-hole core branch / version / commit **********/ + // Check if on a dev branch + $core_branch = $branches[0]; + if ($core_branch !== "master") { + $core_current = "vDev"; + $core_commit = $versions[0]; + } else { + $core_current = explode("-", $versions[0])[0]; + } - /********** Get Pi-hole FTL (not a git repository) **********/ - $FTL_branch = $branches[2]; - if(substr($versions[2], 0, 4) === "vDev") { - $FTL_current = "vDev"; - $FTL_commit = $versions[2]; - } - else { - $FTL_current = $versions[2]; - } + /********** Get Pi-hole web branch / version / commit **********/ + $web_branch = $branches[1]; + if ($web_branch !== "master") { + $web_current = "vDev"; + $web_commit = $versions[1]; + } else { + $web_current = explode("-", $versions[1])[0]; + } - // Get data from GitHub - $core_latest = $GitHubversions[0]; - $web_latest = $GitHubversions[1]; - $FTL_latest = $GitHubversions[2]; + /********** Get Pi-hole FTL (not a git repository) **********/ + $FTL_branch = $branches[2]; + if (substr($versions[2], 0, 4) === "vDev") { + $FTL_current = "vDev"; + $FTL_commit = $versions[2]; + } else { + $FTL_current = $versions[2]; + } - // Core version comparison - if($core_current !== "vDev") - { - // This logic allows the local core version to be newer than the upstream version - // The update indicator is only shown if the upstream version is NEWER - $core_update = (version_compare($core_current, $core_latest) < 0); - } - else - { - $core_update = false; - } + // Get data from GitHub + $core_latest = $GitHubversions[0]; + $web_latest = $GitHubversions[1]; + $FTL_latest = $GitHubversions[2]; - // Web version comparison - if($web_current !== "vDev") - { - // This logic allows the local core version to be newer than the upstream version - // The update indicator is only shown if the upstream version is NEWER - $web_update = (version_compare($web_current, $web_latest) < 0); - } - else - { - $web_update = false; - } + // Core version comparison + if ($core_current !== "vDev") { + // This logic allows the local core version to be newer than the upstream version + // The update indicator is only shown if the upstream version is NEWER + $core_update = (version_compare($core_current, $core_latest) < 0); + } else { + $core_update = false; + } - // FTL version comparison - // This logic allows the local core version to be newer than the upstream version - // The update indicator is only shown if the upstream version is NEWER - if($FTL_current !== "vDev") - { - $FTL_update = (version_compare($FTL_current, $FTL_latest) < 0); - } - else - { - $FTL_update = false; - } + // Web version comparison + if ($web_current !== "vDev") { + // This logic allows the local core version to be newer than the upstream version + // The update indicator is only shown if the upstream version is NEWER + $web_update = (version_compare($web_current, $web_latest) < 0); + } else { + $web_update = false; + } + // FTL version comparison + // This logic allows the local core version to be newer than the upstream version + // The update indicator is only shown if the upstream version is NEWER + if ($FTL_current !== "vDev") { + $FTL_update = (version_compare($FTL_current, $FTL_latest) < 0); + } else { + $FTL_update = false; + } } - -?> diff --git a/settings.php b/settings.php index 1861eb36f..de7eac319 100644 --- a/settings.php +++ b/settings.php @@ -9,28 +9,24 @@ require "scripts/pi-hole/php/savesettings.php"; // Reread ini file as things might have been changed $setupVars = parse_ini_file("/etc/pihole/setupVars.conf"); -if(is_readable($piholeFTLConfFile)) -{ - $piholeFTLConf = parse_ini_file($piholeFTLConfFile); -} -else -{ - $piholeFTLConf = array(); +if (is_readable($piholeFTLConfFile)) { + $piholeFTLConf = parse_ini_file($piholeFTLConfFile); +} else { + $piholeFTLConf = array(); } // Handling of PHP internal errors $last_error = error_get_last(); -if($last_error["type"] === E_WARNING || $last_error["type"] === E_ERROR) -{ - $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"]); +if ($last_error["type"] === E_WARNING || $last_error["type"] === E_ERROR) { + $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"]); } ?>
    @@ -443,7 +466,9 @@
    Router
    disabled> + disabled>
    @@ -466,7 +491,9 @@
    Domain
    disabled> + disabled>
    @@ -480,7 +507,9 @@ disabled> + data-mask disabled>

    Hint: 0 = infinite, 24 = one day, 168 = one week, 744 = one month, 8760 = one year

    @@ -491,17 +520,25 @@
    + checked disabled>Enable IPv6 support (SLAAC + RA)
    + checked disabled>Enable DHCP rapid commit (fast address assignment)
    @@ -519,8 +556,9 @@ // Read leases file $leasesfile = true; $dhcpleases = @fopen('/etc/pihole/dhcp.leases', 'r'); - if (!is_resource($dhcpleases)) + if (!is_resource($dhcpleases)) { $leasesfile = false; + } function convertseconds($argument) { @@ -542,8 +580,7 @@ function convertseconds($argument) $counter = intval($line[0]); if ($counter == 0) { $time = "Infinite"; - } elseif ($counter <= 315360000) // 10 years in seconds - { + } elseif ($counter <= 315360000) { // 10 years in seconds $time = convertseconds($counter); } else // Assume time stamp { @@ -670,7 +707,9 @@ function convertseconds($argument)
    -
    in active"> +
    in active">
    @@ -689,40 +728,52 @@ function convertseconds($argument) $value) { ?> - + "> " value="true" - checked> + checked> - + - - + + "> " value="true" - checked> + checked> - + - - + + "> " value="true" - checked disabled > + checked disabled > - + - - + + "> " value="true" - checked disabled > + checked disabled > - + - + @@ -746,19 +797,27 @@ function convertseconds($argument)
    checked> + checked>
    value=""> + value="">
    checked> + checked>
    value=""> + value="">
    @@ -768,19 +827,27 @@ function convertseconds($argument)
    checked> + checked>
    value=""> + value="">
    checked> + checked>
    value=""> + value="">
    @@ -799,19 +866,25 @@ function convertseconds($argument)
    @@ -840,15 +913,19 @@ function convertseconds($argument)
    + checked>Never forward non-FQDNs
    + checked>Never forward reverse lookups for private IP ranges

    Note that enabling these two options may increase your privacy @@ -857,8 +934,10 @@ function convertseconds($argument)

    + checked>Use DNSSEC

    Validate DNS replies and cache DNSSEC data. When forwarding DNS @@ -875,15 +954,17 @@ function convertseconds($argument) determine the names of devices on your local network. As a result, tables such as Top Clients will only show IP addresses.

    One solution for this is to configure Pi-hole to forward these - requests to your DHCP server (most likely your router), but only for devices on your - home network. To configure this we will need to know the IP - address of your DHCP server and the name of your local network.

    + requests to your DHCP server (most likely your router), but only for devices on your + home network. To configure this we will need to know the IP + address of your DHCP server and the name of your local network.

    Note: The local domain name must match the domain name specified in your DHCP server, likely found within the DHCP settings.

    @@ -896,10 +977,14 @@ function convertseconds($argument)
    value=""> + value=""> value=""> + value="">
    @@ -933,7 +1018,9 @@ function convertseconds($argument) $adminemail = ""; } ?> -
    in active"> +
    in active">
    @@ -954,8 +1041,9 @@ function convertseconds($argument) + echo $domain . "\n"; + } + ?>
    @@ -963,8 +1051,9 @@ function convertseconds($argument) + echo $client . "\n"; + } + ?>
    @@ -976,12 +1065,16 @@ function convertseconds($argument)
    -
    +
    -
    +
    @@ -1008,26 +1101,34 @@ function convertseconds($argument)
    + checked>Use boxed layout (helpful when working on large screens)

    CPU Temperature Unit

    + checked>Celsius
    + checked>Kelvin
    + checked>Fahrenheit

    Administrator Email Address

    @@ -1059,7 +1160,9 @@ function convertseconds($argument) $privacylevel = 0; } ?> -
    in active"> +
    in active">
    @@ -1075,32 +1178,42 @@ function convertseconds($argument)
    + checked>Show everything and record everything
    Gives maximum amount of statistics
    + checked>Hide domains: Display and store all domains as "hidden"
    This disables the Top Domains and Top Ads tables on the dashboard
    + checked>Hide domains and clients: Display and store all domains as "hidden" and all clients as "0.0.0.0"
    This disables all tables on the dashboard
    + checked>Anonymous mode: This disables basically everything except the live anonymous statistics
    No history is saved at all to the database, and nothing is shown in the query log. Also, there are no top item lists.
    + checked>No Statistics mode: This disables all statistics processing. Even the query counters will not be available.
    Note that regex blocking is not available when query analyzing is disabled.
    Additionally, you can disable logging to the file /var/log/pihole.log using sudo pihole logging off.

    The privacy level may be increased at any time without having to restart the DNS resolver. However, note that the DNS resolver needs to be restarted when lowering the privacy level. This restarting is automatically done when saving.

    - 0 && $piHoleLogging){ ?> + 0 && $piHoleLogging) { ?>

    Warning: Pi-hole's query logging is activated. Although the dashboard will hide the requested details, all queries are still fully logged to the pihole.log file.

    @@ -1117,7 +1230,9 @@ function convertseconds($argument)
    -
    in active"> +
    in active">
    -
    in active"> +
    in active">
    @@ -1273,7 +1390,7 @@ function get_FTL_data($arg) } $FTLversion = exec("/usr/bin/pihole-FTL version"); - ?> + ?> diff --git a/taillog-FTL.php b/taillog-FTL.php index fd40f2230..1a7693a89 100644 --- a/taillog-FTL.php +++ b/taillog-FTL.php @@ -1,4 +1,4 @@ -