Run PHP-CS-Fixer on all files

Signed-off-by: DL6ER <dl6er@dl6er.de>
This commit is contained in:
DL6ER
2022-08-07 10:52:23 +02:00
parent 69e118ad45
commit 6ec4b8a529
47 changed files with 2643 additions and 2831 deletions

179
api.php
View File

@@ -8,200 +8,197 @@
*/
$api = true;
require_once("scripts/pi-hole/php/FTL.php");
require_once("scripts/pi-hole/php/password.php");
require_once("scripts/pi-hole/php/database.php");
require_once("scripts/pi-hole/php/auth.php");
require_once 'scripts/pi-hole/php/FTL.php';
require_once 'scripts/pi-hole/php/password.php';
require_once 'scripts/pi-hole/php/database.php';
require_once 'scripts/pi-hole/php/auth.php';
check_cors();
$data = array();
// Common API functions
if (isset($_GET['enable']) && $auth) {
if(isset($_GET["auth"]))
{
if($_GET["auth"] !== $pwhash)
die("Not authorized!");
}
else
{
if (isset($_GET['auth'])) {
if ($_GET['auth'] !== $pwhash) {
exit('Not authorized!');
}
} else {
// Skip token validation if explicit auth string is given
check_csrf($_GET['token']);
}
pihole_execute('enable');
$data = array_merge($data, array("status" => "enabled"));
if (file_exists("../custom_disable_timer"))
{
unlink("../custom_disable_timer");
$data = array_merge($data, array('status' => 'enabled'));
if (file_exists('../custom_disable_timer')) {
unlink('../custom_disable_timer');
}
}
elseif (isset($_GET['disable']) && $auth)
{
if(isset($_GET["auth"]))
{
if($_GET["auth"] !== $pwhash)
die("Not authorized!");
}
else
{
} elseif (isset($_GET['disable']) && $auth) {
if (isset($_GET['auth'])) {
if ($_GET['auth'] !== $pwhash) {
exit('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)
{
if ($disable > 0) {
$timestamp = time();
pihole_execute("disable ".$disable."s");
file_put_contents("../custom_disable_timer",($timestamp+$disable)*1000);
}
else
{
pihole_execute('disable '.$disable.'s');
file_put_contents('../custom_disable_timer', ($timestamp + $disable) * 1000);
} else {
pihole_execute('disable');
if (file_exists("../custom_disable_timer"))
{
unlink("../custom_disable_timer");
if (file_exists('../custom_disable_timer')) {
unlink('../custom_disable_timer');
}
}
$data = array_merge($data, array("status" => "disabled"));
}
elseif (isset($_GET['versions']))
{
$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);
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 (!$auth)
die("Not authorized!");
} elseif (isset($_GET['list'])) {
if (!$auth) {
exit('Not authorized!');
}
if(!isset($_GET["list"]))
die("List has not been specified.");
if (!isset($_GET['list'])) {
exit('List has not been specified.');
}
switch ($_GET["list"]) {
switch ($_GET['list']) {
case 'black':
$_POST['type'] = ListType::blacklist;
break;
case 'regex_black':
$_POST['type'] = ListType::regex_blacklist;
break;
case 'white':
$_POST['type'] = ListType::whitelist;
break;
case 'regex_white':
$_POST['type'] = ListType::regex_whitelist;
break;
default:
die("Invalid list [supported: black, regex_black, white, regex_white]");
exit('Invalid list [supported: black, regex_black, white, regex_white]');
}
if (isset($_GET['add']))
{
if (isset($_GET['add'])) {
// Set POST parameters and invoke script to add domain to list
$_POST['domain'] = $_GET['add'];
$_POST['action'] = 'add_domain';
require("scripts/pi-hole/php/groups.php");
}
elseif (isset($_GET['sub']))
{
require 'scripts/pi-hole/php/groups.php';
} elseif (isset($_GET['sub'])) {
// Set POST parameters and invoke script to remove domain from list
$_POST['domain'] = $_GET['sub'];
$_POST['action'] = 'delete_domain_string';
require("scripts/pi-hole/php/groups.php");
}
else
{
require 'scripts/pi-hole/php/groups.php';
} else {
// Set POST parameters and invoke script to get all domains
$_POST['action'] = 'get_domains';
require("scripts/pi-hole/php/groups.php");
require 'scripts/pi-hole/php/groups.php';
}
return;
}
elseif(isset($_GET['customdns']) && $auth)
{
if (isset($_GET["auth"])) {
if ($_GET["auth"] !== $pwhash) {
die("Not authorized!");
} elseif (isset($_GET['customdns']) && $auth) {
if (isset($_GET['auth'])) {
if ($_GET['auth'] !== $pwhash) {
exit('Not authorized!');
}
} else {
// Skip token validation if explicit auth string is given
check_csrf($_GET['token']);
}
switch ($_GET["action"]) {
switch ($_GET['action']) {
case 'get':
$data = echoCustomDNSEntries();
break;
case 'add':
$data = addCustomDNSEntry();
break;
case 'delete':
$data = deleteCustomDNSEntry();
break;
default:
die("Wrong action");
exit('Wrong action');
}
}
elseif(isset($_GET['customcname']) && $auth)
{
if (isset($_GET["auth"])) {
if ($_GET["auth"] !== $pwhash) {
die("Not authorized!");
} elseif (isset($_GET['customcname']) && $auth) {
if (isset($_GET['auth'])) {
if ($_GET['auth'] !== $pwhash) {
exit('Not authorized!');
}
} else {
// Skip token validation if explicit auth string is given
check_csrf($_GET['token']);
}
switch ($_GET["action"]) {
switch ($_GET['action']) {
case 'get':
$data = echoCustomCNAMEEntries();
break;
case 'add':
$data = addCustomCNAMEEntry();
break;
case 'delete':
$data = deleteCustomCNAMEEntry();
break;
default:
die("Wrong action");
exit('Wrong action');
}
}
// Other API functions
require("api_FTL.php");
require 'api_FTL.php';
header('Content-type: application/json');
if(isset($_GET["jsonForceObject"])) {
if (isset($_GET['jsonForceObject'])) {
echo json_encode($data, JSON_FORCE_OBJECT);
} else {
echo json_encode($data);
}
?>

View File

@@ -8,47 +8,47 @@
*/
if (!isset($api)) {
die("Direct call to api_FTL.php is not allowed!");
exit('Direct call to api_FTL.php is not allowed!');
}
if (isset($_GET['type'])) {
$data["type"] = "FTL";
$data['type'] = 'FTL';
}
if (isset($_GET['version'])) {
$data["version"] = 3;
$data['version'] = 3;
}
if (isset($_GET['status'])) {
$return = callFTLAPI("stats");
if (array_key_exists("FTLnotrunning", $return)) {
$data = array("FTLnotrunning" => true);
$return = callFTLAPI('stats');
if (array_key_exists('FTLnotrunning', $return)) {
$data = array('FTLnotrunning' => true);
} else {
if (in_array("status enabled", $return)) {
$data = array_merge($data, array("status" => "enabled"));
if (in_array('status enabled', $return)) {
$data = array_merge($data, array('status' => 'enabled'));
} else {
$data = array_merge($data, array("status" => "disabled"));
$data = array_merge($data, array('status' => 'disabled'));
}
}
}
if (isset($_GET['summary']) || isset($_GET['summaryRaw']) || !count($_GET)) {
require_once("scripts/pi-hole/php/gravity.php");
require_once 'scripts/pi-hole/php/gravity.php';
$return = callFTLAPI("stats");
if (array_key_exists("FTLnotrunning", $return)) {
$data = array("FTLnotrunning" => true);
$return = callFTLAPI('stats');
if (array_key_exists('FTLnotrunning', $return)) {
$data = array('FTLnotrunning' => true);
} else {
$stats = [];
$stats = array();
foreach ($return as $line) {
$tmp = explode(" ",$line);
$tmp = explode(' ', $line);
if ($tmp[0] === "domains_being_blocked" && !is_numeric($tmp[1]) || $tmp[0] === "status") {
if ('domains_being_blocked' === $tmp[0] && !is_numeric($tmp[1]) || 'status' === $tmp[0]) {
// Expect string response
$stats[$tmp[0]] = $tmp[1];
} elseif (isset($_GET['summary'])) {
// "summary" expects a formmated string response
if ($tmp[0] !== "ads_percentage_today") {
if ('ads_percentage_today' !== $tmp[0]) {
$stats[$tmp[0]] = number_format($tmp[1]);
} else {
$stats[$tmp[0]] = number_format($tmp[1], 1, '.', '');
@@ -57,43 +57,42 @@ if (isset($_GET['summary']) || isset($_GET['summaryRaw']) || !count($_GET)) {
// Expect float response
$stats[$tmp[0]] = floatval($tmp[1]);
}
}
$stats['gravity_last_updated'] = gravity_last_update(true);
$data = array_merge($data,$stats);
$data = array_merge($data, $stats);
}
}
if (isset($_GET["getMaxlogage"]) && $auth) {
$return = callFTLAPI("maxlogage");
if (array_key_exists("FTLnotrunning", $return)) {
$data = array("FTLnotrunning" => true);
if (isset($_GET['getMaxlogage']) && $auth) {
$return = callFTLAPI('maxlogage');
if (array_key_exists('FTLnotrunning', $return)) {
$data = array('FTLnotrunning' => true);
} else {
// Convert seconds to hours and rounds to one decimal place.
$ret = round(intval($return[0]) / 3600, 1);
// Return 24h if value is 0, empty, null or non numeric.
$ret = $ret ?: 24;
$data = array_merge($data, array("maxlogage" => $ret));
$data = array_merge($data, array('maxlogage' => $ret));
}
}
if (isset($_GET['overTimeData10mins'])) {
$return = callFTLAPI("overTime");
if (array_key_exists("FTLnotrunning", $return)) {
$data = array("FTLnotrunning" => true);
$return = callFTLAPI('overTime');
if (array_key_exists('FTLnotrunning', $return)) {
$data = array('FTLnotrunning' => true);
} else {
$domains_over_time = array();
$ads_over_time = array();
foreach ($return as $line) {
$tmp = explode(" ",$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
'ads_over_time' => $ads_over_time,
);
$data = array_merge($data, $result);
@@ -101,45 +100,45 @@ if (isset($_GET['overTimeData10mins'])) {
}
if (isset($_GET['topItems']) && $auth) {
if ($_GET['topItems'] === "audit") {
$return = callFTLAPI("top-domains for audit");
if ('audit' === $_GET['topItems']) {
$return = callFTLAPI('top-domains for audit');
} elseif (is_numeric($_GET['topItems'])) {
$return = callFTLAPI("top-domains (".$_GET['topItems'].")");
$return = callFTLAPI('top-domains ('.$_GET['topItems'].')');
} else {
$return = callFTLAPI("top-domains");
$return = callFTLAPI('top-domains');
}
if (array_key_exists("FTLnotrunning", $return)) {
$data = array("FTLnotrunning" => true);
if (array_key_exists('FTLnotrunning', $return)) {
$data = array('FTLnotrunning' => true);
} else {
$top_queries = array();
foreach ($return as $line) {
$tmp = explode(" ",$line);
if (count($tmp) == 2) {
$tmp[2]="";
$tmp = explode(' ', $line);
if (2 == count($tmp)) {
$tmp[2] = '';
}
$domain = utf8_encode($tmp[2]);
$top_queries[$domain] = intval($tmp[1]);
}
}
if ($_GET['topItems'] === "audit") {
$return = callFTLAPI("top-ads for audit");
if ('audit' === $_GET['topItems']) {
$return = callFTLAPI('top-ads for audit');
} elseif (is_numeric($_GET['topItems'])) {
$return = callFTLAPI("top-ads (".$_GET['topItems'].")");
$return = callFTLAPI('top-ads ('.$_GET['topItems'].')');
} else {
$return = callFTLAPI("top-ads");
$return = callFTLAPI('top-ads');
}
if (array_key_exists("FTLnotrunning", $return)) {
$data = array("FTLnotrunning" => true);
if (array_key_exists('FTLnotrunning', $return)) {
$data = array('FTLnotrunning' => true);
} else {
$top_ads = array();
foreach ($return as $line) {
$tmp = explode(" ",$line);
$tmp = explode(' ', $line);
$domain = utf8_encode($tmp[2]);
if (count($tmp) > 3) {
$top_ads[$domain." (".$tmp[3].")"] = intval($tmp[1]);
$top_ads[$domain.' ('.$tmp[3].')'] = intval($tmp[1]);
} else {
$top_ads[$domain] = intval($tmp[1]);
}
@@ -147,7 +146,7 @@ if (isset($_GET['topItems']) && $auth) {
$result = array(
'top_queries' => $top_queries,
'top_ads' => $top_ads
'top_ads' => $top_ads,
);
$data = array_merge($data, $result);
@@ -155,7 +154,6 @@ if (isset($_GET['topItems']) && $auth) {
}
if ((isset($_GET['topClients']) || isset($_GET['getQuerySources'])) && $auth) {
if (isset($_GET['topClients'])) {
$number = $_GET['topClients'];
} elseif (isset($_GET['getQuerySources'])) {
@@ -163,20 +161,20 @@ if ((isset($_GET['topClients']) || isset($_GET['getQuerySources'])) && $auth) {
}
if (is_numeric($number)) {
$return = callFTLAPI("top-clients (".$number.")");
$return = callFTLAPI('top-clients ('.$number.')');
} else {
$return = callFTLAPI("top-clients");
$return = callFTLAPI('top-clients');
}
if (array_key_exists("FTLnotrunning", $return)) {
$data = array("FTLnotrunning" => true);
if (array_key_exists('FTLnotrunning', $return)) {
$data = array('FTLnotrunning' => true);
} else {
$top_clients = array();
foreach ($return as $line) {
$tmp = explode(" ",$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]);
$top_clients[$clientname.'|'.$clientip] = intval($tmp[1]);
} else {
$top_clients[$clientip] = intval($tmp[1]);
}
@@ -188,26 +186,25 @@ if ((isset($_GET['topClients']) || isset($_GET['getQuerySources'])) && $auth) {
}
if (isset($_GET['topClientsBlocked']) && $auth) {
if (isset($_GET['topClientsBlocked'])) {
$number = $_GET['topClientsBlocked'];
}
if (is_numeric($number)) {
$return = callFTLAPI("top-clients blocked (".$number.")");
$return = callFTLAPI('top-clients blocked ('.$number.')');
} else {
$return = callFTLAPI("top-clients blocked");
$return = callFTLAPI('top-clients blocked');
}
if (array_key_exists("FTLnotrunning", $return)) {
$data = array("FTLnotrunning" => true);
if (array_key_exists('FTLnotrunning', $return)) {
$data = array('FTLnotrunning' => true);
} else {
$top_clients = array();
foreach ($return as $line) {
$tmp = explode(" ",$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]);
$top_clients[$clientname.'|'.$clientip] = intval($tmp[1]);
} else {
$top_clients[$clientip] = intval($tmp[1]);
}
@@ -219,21 +216,21 @@ if (isset($_GET['topClientsBlocked']) && $auth) {
}
if (isset($_GET['getForwardDestinations']) && $auth) {
if ($_GET['getForwardDestinations'] === "unsorted") {
$return = callFTLAPI("forward-dest unsorted");
if ('unsorted' === $_GET['getForwardDestinations']) {
$return = callFTLAPI('forward-dest unsorted');
} else {
$return = callFTLAPI("forward-dest");
$return = callFTLAPI('forward-dest');
}
if (array_key_exists("FTLnotrunning", $return)) {
$data = array("FTLnotrunning" => true);
if (array_key_exists('FTLnotrunning', $return)) {
$data = array('FTLnotrunning' => true);
} else {
$forward_dest = array();
foreach ($return as $line) {
$tmp = explode(" ",$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]);
$forward_dest[$forwardname.'|'.$forwardip] = floatval($tmp[1]);
} else {
$forward_dest[$forwardip] = floatval($tmp[1]);
}
@@ -245,13 +242,13 @@ if (isset($_GET['getForwardDestinations']) && $auth) {
}
if (isset($_GET['getQueryTypes']) && $auth) {
$return = callFTLAPI("querytypes");
if (array_key_exists("FTLnotrunning", $return)) {
$data = array("FTLnotrunning" => true);
$return = callFTLAPI('querytypes');
if (array_key_exists('FTLnotrunning', $return)) {
$data = array('FTLnotrunning' => true);
} else {
$querytypes = array();
foreach ($return as $ret) {
$tmp = explode(": ",$ret);
$tmp = explode(': ', $ret);
// Reply cannot contain non-ASCII characters
$querytypes[$tmp[0]] = floatval($tmp[1]);
}
@@ -262,13 +259,13 @@ if (isset($_GET['getQueryTypes']) && $auth) {
}
if (isset($_GET['getCacheInfo']) && $auth) {
$return = callFTLAPI("cacheinfo");
if (array_key_exists("FTLnotrunning", $return)) {
$data = array("FTLnotrunning" => true);
$return = callFTLAPI('cacheinfo');
if (array_key_exists('FTLnotrunning', $return)) {
$data = array('FTLnotrunning' => true);
} else {
$cacheinfo = array();
foreach ($return as $ret) {
$tmp = explode(": ",$ret);
$tmp = explode(': ', $ret);
// Reply cannot contain non-ASCII characters
$cacheinfo[$tmp[0]] = floatval($tmp[1]);
}
@@ -279,33 +276,33 @@ if (isset($_GET['getCacheInfo']) && $auth) {
}
if (isset($_GET['getAllQueries']) && $auth) {
if (isset($_GET['from']) && isset($_GET['until'])) {
if (isset($_GET['from'], $_GET['until'])) {
// Get limited time interval
$return = callFTLAPI("getallqueries-time ".$_GET['from']." ".$_GET['until']);
$return = callFTLAPI('getallqueries-time '.$_GET['from'].' '.$_GET['until']);
} elseif (isset($_GET['domain'])) {
// Get specific domain only
$return = callFTLAPI("getallqueries-domain ".$_GET['domain']);
} elseif (isset($_GET['client']) && (isset($_GET['type']) && $_GET['type'] === "blocked")) {
$return = callFTLAPI('getallqueries-domain '.$_GET['domain']);
} elseif (isset($_GET['client']) && (isset($_GET['type']) && 'blocked' === $_GET['type'])) {
// Get specific client only
$return = callFTLAPI("getallqueries-client-blocked ".$_GET['client']);
$return = callFTLAPI('getallqueries-client-blocked '.$_GET['client']);
} elseif (isset($_GET['client'])) {
// Get specific client only
$return = callFTLAPI("getallqueries-client ".$_GET['client']);
$return = callFTLAPI('getallqueries-client '.$_GET['client']);
} elseif (isset($_GET['querytype'])) {
// Get specific query type only
$return = callFTLAPI("getallqueries-qtype ".$_GET['querytype']);
$return = callFTLAPI('getallqueries-qtype '.$_GET['querytype']);
} elseif (isset($_GET['forwarddest'])) {
// Get specific forward destination only
$return = callFTLAPI("getallqueries-forward ".$_GET['forwarddest']);
$return = callFTLAPI('getallqueries-forward '.$_GET['forwarddest']);
} elseif (is_numeric($_GET['getAllQueries'])) {
$return = callFTLAPI("getallqueries (".$_GET['getAllQueries'].")");
$return = callFTLAPI('getallqueries ('.$_GET['getAllQueries'].')');
} else {
// Get all queries
$return = callFTLAPI("getallqueries");
$return = callFTLAPI('getallqueries');
}
if (array_key_exists("FTLnotrunning", $return)) {
$data = array("FTLnotrunning" => true);
if (array_key_exists('FTLnotrunning', $return)) {
$data = array('FTLnotrunning' => true);
} else {
// Set the header
header('Content-type: application/json');
@@ -314,49 +311,49 @@ if (isset($_GET['getAllQueries']) && $auth) {
echo '{"data":[';
$first = true;
foreach($return as $line) {
foreach ($return as $line) {
// Insert a comma before the next record (except on the first one)
if (!$first) {
echo ",";
echo ',';
} else {
$first = false;
}
$row = str_getcsv($line," ");
$row = str_getcsv($line, ' ');
// UTF-8 encode domain
$domain = utf8_encode(str_replace("~"," ",$row[2]));
$domain = utf8_encode(str_replace('~', ' ', $row[2]));
// UTF-8 encode client host name
$client = utf8_encode($row[3]);
// Insert into array and output it in JSON format
// array: time type domain client status dnssecStatus reply response_time CNAMEDomain regexID upstream destination EDE
echo json_encode([$row[0], $row[1], $domain, $client, $row[4], $row[5], $row[6], $row[7], $row[8], $row[9], $row[10], $row[11]]);
echo json_encode(array($row[0], $row[1], $domain, $client, $row[4], $row[5], $row[6], $row[7], $row[8], $row[9], $row[10], $row[11]));
}
// Finish the JSON string
echo ']}';
// exit at the end
exit();
exit;
}
}
if (isset($_GET["recentBlocked"]) && $auth) {
die(utf8_encode(callFTLAPI("recentBlocked")[0]));
if (isset($_GET['recentBlocked']) && $auth) {
exit(utf8_encode(callFTLAPI('recentBlocked')[0]));
unset($data);
}
if (isset($_GET['getForwardDestinationNames']) && $auth) {
$return = callFTLAPI("forward-names");
$return = callFTLAPI('forward-names');
if (array_key_exists("FTLnotrunning", $return)) {
$data = array("FTLnotrunning" => true);
if (array_key_exists('FTLnotrunning', $return)) {
$data = array('FTLnotrunning' => true);
} else {
$forward_dest = array();
foreach ($return as $line) {
$tmp = explode(" ",$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]);
$forward_dest[$forwardname.'|'.$forwardip] = floatval($tmp[1]);
} else {
$forward_dest[$forwardip] = floatval($tmp[1]);
}
@@ -368,15 +365,15 @@ if (isset($_GET['getForwardDestinationNames']) && $auth) {
}
if (isset($_GET['overTimeDataQueryTypes']) && $auth) {
$return = callFTLAPI("QueryTypesoverTime");
if (array_key_exists("FTLnotrunning", $return)) {
$data = array("FTLnotrunning" => true);
$return = callFTLAPI('QueryTypesoverTime');
if (array_key_exists('FTLnotrunning', $return)) {
$data = array('FTLnotrunning' => true);
} else {
$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]);
$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);
@@ -385,16 +382,16 @@ if (isset($_GET['overTimeDataQueryTypes']) && $auth) {
}
if (isset($_GET['getClientNames']) && $auth) {
$return = callFTLAPI("client-names");
if (array_key_exists("FTLnotrunning", $return)) {
$data = array("FTLnotrunning" => true);
$return = callFTLAPI('client-names');
if (array_key_exists('FTLnotrunning', $return)) {
$data = array('FTLnotrunning' => true);
} else {
$client_names = array();
foreach ($return as $line) {
$tmp = explode(" ", $line);
$tmp = explode(' ', $line);
$client_names[] = array(
"name" => utf8_encode($tmp[0]),
"ip" => utf8_encode($tmp[1])
'name' => utf8_encode($tmp[0]),
'ip' => utf8_encode($tmp[1]),
);
}
@@ -404,16 +401,16 @@ if (isset($_GET['getClientNames']) && $auth) {
}
if (isset($_GET['overTimeDataClients']) && $auth) {
$return = callFTLAPI("ClientsoverTime");
$return = callFTLAPI('ClientsoverTime');
if (array_key_exists("FTLnotrunning", $return)) {
$data = array("FTLnotrunning" => true);
if (array_key_exists('FTLnotrunning', $return)) {
$data = array('FTLnotrunning' => true);
} else {
$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]);
$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);
@@ -422,20 +419,19 @@ if (isset($_GET['overTimeDataClients']) && $auth) {
}
if (isset($_GET['delete_lease']) && $auth) {
$return = callFTLAPI("delete-lease ".$_GET['delete_lease']);
if (array_key_exists("FTLnotrunning", $return)) {
$data = array("FTLnotrunning" => true);
$return = callFTLAPI('delete-lease '.$_GET['delete_lease']);
if (array_key_exists('FTLnotrunning', $return)) {
$data = array('FTLnotrunning' => true);
} else {
$data["delete_lease"] = $return[0];
$data['delete_lease'] = $return[0];
}
}
if (isset($_GET['dns-port']) && $auth) {
$return = callFTLAPI("dns-port");
if (array_key_exists("FTLnotrunning", $return)) {
$data = array("FTLnotrunning" => true);
$return = callFTLAPI('dns-port');
if (array_key_exists('FTLnotrunning', $return)) {
$data = array('FTLnotrunning' => true);
} else {
$data["dns-port"] = $return[0];
$data['dns-port'] = $return[0];
}
}
?>

View File

@@ -9,14 +9,18 @@
$api = true;
header('Content-type: application/json');
require("scripts/pi-hole/php/database.php");
require("scripts/pi-hole/php/password.php");
require("scripts/pi-hole/php/auth.php");
require_once("scripts/pi-hole/php/func.php");
require 'scripts/pi-hole/php/database.php';
require 'scripts/pi-hole/php/password.php';
require 'scripts/pi-hole/php/auth.php';
require_once 'scripts/pi-hole/php/func.php';
check_cors();
// Set maximum execution time to 10 minutes
ini_set("max_execution_time","600");
ini_set('max_execution_time', '600');
$data = array();
@@ -26,31 +30,29 @@ $data = array();
$QUERYDB = getQueriesDBFilename();
$db = SQLite3_connect($QUERYDB);
if(isset($_GET["network"]) && $auth)
{
if (isset($_GET['network']) && $auth) {
$network = array();
$results = $db->query('SELECT * FROM network');
while($results !== false && $res = $results->fetchArray(SQLITE3_ASSOC))
{
$id = intval($res["id"]);
while (false !== $results && $res = $results->fetchArray(SQLITE3_ASSOC)) {
$id = intval($res['id']);
// Get IP addresses and host names for this device
$res["ip"] = array();
$res["name"] = array();
$network_addresses = $db->query("SELECT ip,name FROM network_addresses WHERE network_id = $id ORDER BY lastSeen DESC");
while($network_addresses !== false && $network_address = $network_addresses->fetchArray(SQLITE3_ASSOC))
{
array_push($res["ip"],$network_address["ip"]);
if($network_address["name"] !== null)
array_push($res["name"],utf8_encode($network_address["name"]));
else
array_push($res["name"],"");
$res['ip'] = array();
$res['name'] = array();
$network_addresses = $db->query("SELECT ip,name FROM network_addresses WHERE network_id = {$id} ORDER BY lastSeen DESC");
while (false !== $network_addresses && $network_address = $network_addresses->fetchArray(SQLITE3_ASSOC)) {
array_push($res['ip'], $network_address['ip']);
if (null !== $network_address['name']) {
array_push($res['name'], utf8_encode($network_address['name']));
} else {
array_push($res['name'], '');
}
}
$network_addresses->finalize();
// UTF-8 encode vendor
$res["macVendor"] = utf8_encode($res["macVendor"]);
$res['macVendor'] = utf8_encode($res['macVendor']);
array_push($network, $res);
}
$results->finalize();
@@ -58,48 +60,42 @@ if(isset($_GET["network"]) && $auth)
$data = array_merge($data, array('network' => $network));
}
if (isset($_GET['getAllQueries']) && $auth)
{
if (isset($_GET['getAllQueries']) && $auth) {
$allQueries = array();
if($_GET['getAllQueries'] !== "empty")
{
$from = intval($_GET["from"]);
$until = intval($_GET["until"]);
if ('empty' !== $_GET['getAllQueries']) {
$from = intval($_GET['from']);
$until = intval($_GET['until']);
// Use table "query_storage"
// - replace domain ID with domain
// - replace client ID with client name
// - replace forward ID with forward destination
$dbquery = "SELECT timestamp, type,";
$dbquery = 'SELECT timestamp, type,';
$dbquery .= " CASE typeof(domain) WHEN 'integer' THEN (SELECT domain FROM domain_by_id d WHERE d.id = q.domain) ELSE domain END domain,";
$dbquery .= " CASE typeof(client) WHEN 'integer' THEN (";
$dbquery .= " SELECT CASE TRIM(name) WHEN '' THEN c.ip ELSE c.name END name FROM client_by_id c WHERE c.id = q.client";
$dbquery .= " ) ELSE client END client,";
$dbquery .= ' ) ELSE client END client,';
$dbquery .= " CASE typeof(forward) WHEN 'integer' THEN (SELECT forward FROM forward_by_id f WHERE f.id = q.forward) ELSE forward END forward,";
$dbquery .= " status, reply_type, reply_time, dnssec";
$dbquery .= " FROM query_storage q";
$dbquery .= " WHERE timestamp >= :from AND timestamp <= :until ";
if(isset($_GET["types"]))
{
$types = $_GET["types"];
if(preg_match("/^[0-9]+(?:,[0-9]+)*$/", $types) === 1)
{
$dbquery .= ' status, reply_type, reply_time, dnssec';
$dbquery .= ' FROM query_storage q';
$dbquery .= ' WHERE timestamp >= :from AND timestamp <= :until ';
if (isset($_GET['types'])) {
$types = $_GET['types'];
if (1 === preg_match('/^[0-9]+(?:,[0-9]+)*$/', $types)) {
// 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 .= 'AND status IN ('.$types.') ';
} else {
exit('Error. Selector types specified using an invalid format.');
}
}
$dbquery .= "ORDER BY timestamp ASC";
$dbquery .= 'ORDER BY timestamp ASC';
$stmt = $db->prepare($dbquery);
$stmt->bindValue(":from", intval($from), SQLITE3_INTEGER);
$stmt->bindValue(":until", intval($until), SQLITE3_INTEGER);
$stmt->bindValue(':from', intval($from), SQLITE3_INTEGER);
$stmt->bindValue(':until', intval($until), SQLITE3_INTEGER);
$results = $stmt->execute();
// Start the JSON string
@@ -110,24 +106,24 @@ if (isset($_GET['getAllQueries']) && $auth)
while ($row = $results->fetchArray(SQLITE3_ASSOC)) {
// Insert a comma before the next record (except on the first one)
if (!$first) {
echo ",";
echo ',';
} else {
$first = false;
}
// Format, encode, transform each field (if necessary).
$time = $row["timestamp"];
$query_type = getQueryTypeStr($row["type"]); // Convert query type ID to name
$domain = utf8_encode(str_replace("~"," ",$row["domain"]));
$client = $row["client"];
$status = $row["status"];
$destination = utf8_encode($row["forward"]);
$reply_type = $row["reply_type"];
$reply_time = $row["reply_time"];
$dnssec = $row["dnssec"];
$time = $row['timestamp'];
$query_type = getQueryTypeStr($row['type']); // Convert query type ID to name
$domain = utf8_encode(str_replace('~', ' ', $row['domain']));
$client = $row['client'];
$status = $row['status'];
$destination = utf8_encode($row['forward']);
$reply_type = $row['reply_type'];
$reply_time = $row['reply_time'];
$dnssec = $row['dnssec'];
// Insert into array and output it in JSON format
echo json_encode([$time, $query_type, $domain, $client, $status, $destination, $reply_type, $reply_time, $dnssec]);
echo json_encode(array($time, $query_type, $domain, $client, $status, $destination, $reply_type, $reply_time, $dnssec));
}
}
@@ -135,56 +131,47 @@ if (isset($_GET['getAllQueries']) && $auth)
echo ']}';
// exit at the end
exit();
exit;
}
// only used if getAllQueries==empty
$result = array('data' => $allQueries);
$data = array_merge($data, $result);
}
if (isset($_GET['topClients']) && $auth)
{
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";
$limit = '';
if (isset($_GET['from'], $_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';
}
$dbquery = "SELECT CASE typeof(client) WHEN 'integer' THEN (";
$dbquery .= " SELECT CASE TRIM(name) WHEN '' THEN c.ip ELSE c.name END name FROM client_by_id c WHERE c.id = q.client)";
$dbquery .= " ELSE client END client, count(client) FROM query_storage q ".$limit." GROUP BY client ORDER BY count(client) DESC LIMIT 20";
$dbquery .= ' ELSE client END client, count(client) FROM query_storage q '.$limit.' GROUP BY client ORDER BY count(client) DESC LIMIT 20';
$stmt = $db->prepare($dbquery);
$stmt->bindValue(":from", intval($_GET['from']), SQLITE3_INTEGER);
$stmt->bindValue(":until", intval($_GET['until']), SQLITE3_INTEGER);
$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())
{
if (!is_bool($results)) {
while ($row = $results->fetchArray()) {
// $row[0] is the client IP
if(array_key_exists($row[0], $clientnums))
{
if (array_key_exists($row[0], $clientnums)) {
// Entry already exists, add to it (might appear multiple times due to mixed capitalization in the database)
$clientnums[$row[0]] += intval($row[1]);
}
else
{
} else {
// Entry does not yet exist
$clientnums[$row[0]] = intval($row[1]);
}
}
}
// Sort by number of hits
arsort($clientnums);
@@ -196,46 +183,37 @@ if (isset($_GET['topClients']) && $auth)
$data = array_merge($data, $result);
}
if (isset($_GET['topDomains']) && $auth)
{
$limit = "";
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";
if (isset($_GET['from'], $_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';
}
// Select top permitted domains only
$stmt = $db->prepare('SELECT domain,count(domain) FROM queries WHERE status IN (2,3,12,13,14)'.$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);
$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())
{
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))
{
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
{
} else {
// Entry does not yet exist
$domains[$c] = intval($row[1]);
}
}
}
// Sort by number of hits
arsort($domains);
@@ -247,130 +225,119 @@ if (isset($_GET['topDomains']) && $auth)
$data = array_merge($data, $result);
}
if (isset($_GET['topAds']) && $auth)
{
$limit = "";
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";
if (isset($_GET['from'], $_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 IN (1,4,5,6,7,8,9,10,11)'.$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);
$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())
{
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)
{
if (isset($_GET['getMinTimestamp']) && $auth) {
$results = $db->query('SELECT MIN(timestamp) FROM queries');
if(!is_bool($results))
if (!is_bool($results)) {
$result = array('mintimestamp' => $results->fetchArray()[0]);
else
} else {
$result = array();
}
$data = array_merge($data, $result);
}
if (isset($_GET['getMaxTimestamp']) && $auth)
{
if (isset($_GET['getMaxTimestamp']) && $auth) {
$results = $db->query('SELECT MAX(timestamp) FROM queries');
if(!is_bool($results))
if (!is_bool($results)) {
$result = array('maxtimestamp' => $results->fetchArray()[0]);
else
} else {
$result = array();
}
$data = array_merge($data, $result);
}
if (isset($_GET['getQueriesCount']) && $auth)
{
if (isset($_GET['getQueriesCount']) && $auth) {
$results = $db->query('SELECT COUNT(timestamp) FROM queries');
if(!is_bool($results))
if (!is_bool($results)) {
$result = array('count' => $results->fetchArray()[0]);
else
} else {
$result = array();
}
$data = array_merge($data, $result);
}
if (isset($_GET['getDBfilesize']) && $auth)
{
$filesize = filesize("/etc/pihole/pihole-FTL.db");
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['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";
if (isset($_GET['from'], $_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)
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);
$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);
$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) {
function parseDBData($results, $interval, $from, $until)
{
$data = array();
$first_db_timestamp = -1;
if(!is_bool($results)) {
if (!is_bool($results)) {
// Read in the data
while($row = $results->fetchArray()) {
while ($row = $results->fetchArray()) {
// $data[timestamp] = value_in_this_interval
$data[$row[0]] = intval($row[1]);
if($first_db_timestamp === -1)
if (-1 === $first_db_timestamp) {
$first_db_timestamp = intval($row[0]);
}
}
}
@@ -381,9 +348,10 @@ if (isset($_GET['getGraphData']) && $auth)
$aligned_from = $from + (($first_db_timestamp - $from) % $interval);
// Fill gaps in returned data
for($i = $aligned_from; $i < $until; $i += $interval) {
if(!array_key_exists($i, $data))
for ($i = $aligned_from; $i < $until; $i += $interval) {
if (!array_key_exists($i, $data)) {
$data[$i] = 0;
}
}
return $data;
@@ -396,9 +364,9 @@ if (isset($_GET['getGraphData']) && $auth)
// Count blocked queries in intervals
$stmt = $db->prepare('SELECT (timestamp/:interval)*:interval interval, COUNT(*) FROM queries WHERE status IN (1,4,5,6,7,8,9,10,11)'.$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);
$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);
@@ -407,37 +375,38 @@ if (isset($_GET['getGraphData']) && $auth)
$data = array_merge($data, $result);
}
if (isset($_GET['status']) && $auth)
{
$extra = ";";
if(isset($_GET["ignore"]) && $_GET["ignore"] === 'DNSMASQ_WARN')
if (isset($_GET['status']) && $auth) {
$extra = ';';
if (isset($_GET['ignore']) && 'DNSMASQ_WARN' === $_GET['ignore']) {
$extra = "WHERE type != 'DNSMASQ_WARN';";
}
$results = $db->query('SELECT COUNT(*) FROM message '.$extra);
if(!is_bool($results))
if (!is_bool($results)) {
$result = array('message_count' => $results->fetchArray()[0]);
else
} else {
$result = array();
}
$data = array_merge($data, $result);
}
if(isset($_GET["messages"]) && $auth)
{
$extra = ";";
if(isset($_GET["ignore"]) && $_GET["ignore"] === 'DNSMASQ_WARN')
if (isset($_GET['messages']) && $auth) {
$extra = ';';
if (isset($_GET['ignore']) && 'DNSMASQ_WARN' === $_GET['ignore']) {
$extra = "WHERE type != 'DNSMASQ_WARN';";
}
$messages = array();
$results = $db->query('SELECT * FROM message '.$extra);
while($results !== false && $res = $results->fetchArray(SQLITE3_ASSOC))
{
while (false !== $results && $res = $results->fetchArray(SQLITE3_ASSOC)) {
// Convert string to to UTF-8 encoding to ensure php-json can handle it.
// Furthermore, convert special characters to HTML entities to prevent XSS attacks.
foreach ($res as $key => $value) {
if (is_string($value))
if (is_string($value)) {
$res[$key] = htmlspecialchars(utf8_encode($value));
}
}
array_push($messages, $res);
}
@@ -445,11 +414,8 @@ if(isset($_GET["messages"]) && $auth)
$data = array_merge($data, array('messages' => $messages));
}
if(isset($_GET["jsonForceObject"]))
{
if (isset($_GET['jsonForceObject'])) {
echo json_encode($data, JSON_FORCE_OBJECT);
}
else
{
} else {
echo json_encode($data);
}

View File

@@ -8,7 +8,7 @@
* Please see LICENSE file for your rights under this license.
*/
require "scripts/pi-hole/php/header.php";
require 'scripts/pi-hole/php/header.php';
?>
<!-- Title -->
@@ -79,8 +79,8 @@ require "scripts/pi-hole/php/header.php";
</div>
<!-- /.row -->
<script src="scripts/pi-hole/js/auditlog.js?v=<?=$cacheVer?>"></script>
<script src="scripts/pi-hole/js/auditlog.js?v=<?php echo $cacheVer; ?>"></script>
<?php
require "scripts/pi-hole/php/footer.php";
require 'scripts/pi-hole/php/footer.php';
?>

View File

@@ -8,7 +8,7 @@
* Please see LICENSE file for your rights under this license.
*/
require "scripts/pi-hole/php/header.php";
require 'scripts/pi-hole/php/header.php';
?>
<!-- Title -->
@@ -79,8 +79,8 @@ require "scripts/pi-hole/php/header.php";
</div>
</div>
<script src="scripts/pi-hole/js/customcname.js?v=<?=$cacheVer?>"></script>
<script src="scripts/pi-hole/js/customcname.js?v=<?php echo $cacheVer; ?>"></script>
<?php
require "scripts/pi-hole/php/footer.php";
require 'scripts/pi-hole/php/footer.php';
?>

View File

@@ -8,7 +8,7 @@
* Please see LICENSE file for your rights under this license.
*/
require "scripts/pi-hole/php/header.php";
require 'scripts/pi-hole/php/header.php';
?>
<!-- Sourceing CSS colors from stylesheet to be used in JS code -->
<span class="queries-permitted"></span>
@@ -75,8 +75,8 @@ require "scripts/pi-hole/php/header.php";
</div>
</div>
<script src="scripts/vendor/daterangepicker.min.js?v=<?=$cacheVer?>"></script>
<script src="scripts/pi-hole/js/db_graph.js?v=<?=$cacheVer?>"></script>
<script src="scripts/vendor/daterangepicker.min.js?v=<?php echo $cacheVer; ?>"></script>
<script src="scripts/pi-hole/js/db_graph.js?v=<?php echo $cacheVer; ?>"></script>
<?php
require "scripts/pi-hole/php/footer.php";
require 'scripts/pi-hole/php/footer.php';
?>

View File

@@ -8,7 +8,7 @@
* Please see LICENSE file for your rights under this license.
*/
require "scripts/pi-hole/php/header.php";
require 'scripts/pi-hole/php/header.php';
?>
<!-- Sourceing CSS colors from stylesheet to be used in JS code -->
@@ -49,13 +49,10 @@ require "scripts/pi-hole/php/header.php";
</div>
<?php
if($boxedlayout)
{
$tablelayout = "col-md-6";
}
else
{
$tablelayout = "col-md-6 col-lg-4";
if ($boxedlayout) {
$tablelayout = 'col-md-6';
} else {
$tablelayout = 'col-md-6 col-lg-4';
}
?>
<div class="row">
@@ -148,9 +145,9 @@ else
<!-- /.col -->
</div>
<script src="scripts/vendor/daterangepicker.min.js?v=<?=$cacheVer?>"></script>
<script src="scripts/pi-hole/js/db_lists.js?v=<?=$cacheVer?>"></script>
<script src="scripts/vendor/daterangepicker.min.js?v=<?php echo $cacheVer; ?>"></script>
<script src="scripts/pi-hole/js/db_lists.js?v=<?php echo $cacheVer; ?>"></script>
<?php
require "scripts/pi-hole/php/footer.php";
require 'scripts/pi-hole/php/footer.php';
?>

View File

@@ -8,7 +8,7 @@
* Please see LICENSE file for your rights under this license.
*/
require "scripts/pi-hole/php/header.php";
require 'scripts/pi-hole/php/header.php';
?>
<!-- Title -->
@@ -206,10 +206,10 @@ require "scripts/pi-hole/php/header.php";
</div>
</div>
<!-- /.row -->
<script src="scripts/pi-hole/js/ip-address-sorting.js?v=<?=$cacheVer?>"></script>
<script src="scripts/vendor/daterangepicker.min.js?v=<?=$cacheVer?>"></script>
<script src="scripts/pi-hole/js/db_queries.js?v=<?=$cacheVer?>"></script>
<script src="scripts/pi-hole/js/ip-address-sorting.js?v=<?php echo $cacheVer; ?>"></script>
<script src="scripts/vendor/daterangepicker.min.js?v=<?php echo $cacheVer; ?>"></script>
<script src="scripts/pi-hole/js/db_queries.js?v=<?php echo $cacheVer; ?>"></script>
<?php
require "scripts/pi-hole/php/footer.php";
require 'scripts/pi-hole/php/footer.php';
?>

View File

@@ -8,7 +8,7 @@
* Please see LICENSE file for your rights under this license.
*/
require "scripts/pi-hole/php/header.php";
require 'scripts/pi-hole/php/header.php';
?>
<!-- Title -->
<div class="page-header">
@@ -36,8 +36,8 @@ require "scripts/pi-hole/php/header.php";
<button type="button" id="debugBtn" class="btn btn-lg btn-primary btn-block">Generate debug log</button>
<pre id="output" style="width: 100%; height: 100%;" hidden></pre>
<script src="scripts/pi-hole/js/debug.js?v=<?=$cacheVer?>"></script>
<script src="scripts/pi-hole/js/debug.js?v=<?php echo $cacheVer; ?>"></script>
<?php
require "scripts/pi-hole/php/footer.php";
require 'scripts/pi-hole/php/footer.php';
?>

View File

@@ -8,7 +8,7 @@
* Please see LICENSE file for your rights under this license.
*/
require "scripts/pi-hole/php/header.php";
require 'scripts/pi-hole/php/header.php';
?>
<!-- Title -->
@@ -83,9 +83,9 @@ require "scripts/pi-hole/php/header.php";
</div>
</div>
<script src="scripts/pi-hole/js/ip-address-sorting.js?v=<?=$cacheVer?>"></script>
<script src="scripts/pi-hole/js/customdns.js?v=<?=$cacheVer?>"></script>
<script src="scripts/pi-hole/js/ip-address-sorting.js?v=<?php echo $cacheVer; ?>"></script>
<script src="scripts/pi-hole/js/customdns.js?v=<?php echo $cacheVer; ?>"></script>
<?php
require "scripts/pi-hole/php/footer.php";
require 'scripts/pi-hole/php/footer.php';
?>

View File

@@ -8,7 +8,7 @@
* Please see LICENSE file for your rights under this license.
*/
require "scripts/pi-hole/php/header.php";
require 'scripts/pi-hole/php/header.php';
?>
<!-- Title -->
<div class="page-header">
@@ -28,8 +28,8 @@ require "scripts/pi-hole/php/header.php";
<button type="button" id="gravityBtn" class="btn btn-lg btn-primary btn-block">Update</button>
<pre id="output" style="width: 100%; height: 100%;" hidden></pre>
<script src="scripts/pi-hole/js/gravity.js?v=<?=$cacheVer?>"></script>
<script src="scripts/pi-hole/js/gravity.js?v=<?php echo $cacheVer; ?>"></script>
<?php
require "scripts/pi-hole/php/footer.php";
require 'scripts/pi-hole/php/footer.php';
?>

View File

@@ -7,7 +7,7 @@
* Please see LICENSE file for your rights under this license.
*/
require "scripts/pi-hole/php/header.php";
require 'scripts/pi-hole/php/header.php';
?>
<!-- Title -->
@@ -82,10 +82,10 @@ require "scripts/pi-hole/php/header.php";
</div>
</div>
<script src="scripts/vendor/bootstrap-select.min.js?v=<?=$cacheVer?>"></script>
<script src="scripts/vendor/bootstrap-toggle.min.js?v=<?=$cacheVer?>"></script>
<script src="scripts/pi-hole/js/groups-adlists.js?v=<?=$cacheVer?>"></script>
<script src="scripts/vendor/bootstrap-select.min.js?v=<?php echo $cacheVer; ?>"></script>
<script src="scripts/vendor/bootstrap-toggle.min.js?v=<?php echo $cacheVer; ?>"></script>
<script src="scripts/pi-hole/js/groups-adlists.js?v=<?php echo $cacheVer; ?>"></script>
<?php
require "scripts/pi-hole/php/footer.php";
require 'scripts/pi-hole/php/footer.php';
?>

View File

@@ -8,7 +8,7 @@
* Please see LICENSE file for your rights under this license.
*/
require "scripts/pi-hole/php/header.php";
require 'scripts/pi-hole/php/header.php';
?>
<!-- Title -->
@@ -91,11 +91,11 @@ require "scripts/pi-hole/php/header.php";
</div>
</div>
<script src="scripts/vendor/bootstrap-select.min.js?v=<?=$cacheVer?>"></script>
<script src="scripts/vendor/bootstrap-toggle.min.js?v=<?=$cacheVer?>"></script>
<script src="scripts/pi-hole/js/ip-address-sorting.js?v=<?=$cacheVer?>"></script>
<script src="scripts/pi-hole/js/groups-clients.js?v=<?=$cacheVer?>"></script>
<script src="scripts/vendor/bootstrap-select.min.js?v=<?php echo $cacheVer; ?>"></script>
<script src="scripts/vendor/bootstrap-toggle.min.js?v=<?php echo $cacheVer; ?>"></script>
<script src="scripts/pi-hole/js/ip-address-sorting.js?v=<?php echo $cacheVer; ?>"></script>
<script src="scripts/pi-hole/js/groups-clients.js?v=<?php echo $cacheVer; ?>"></script>
<?php
require "scripts/pi-hole/php/footer.php";
require 'scripts/pi-hole/php/footer.php';
?>

View File

@@ -8,7 +8,7 @@
* Please see LICENSE file for your rights under this license.
*/
require "scripts/pi-hole/php/header.php";
require 'scripts/pi-hole/php/header.php';
?>
<!-- Title -->
@@ -138,10 +138,10 @@ require "scripts/pi-hole/php/header.php";
</div>
</div>
<script src="scripts/vendor/bootstrap-select.min.js?v=<?=$cacheVer?>"></script>
<script src="scripts/vendor/bootstrap-toggle.min.js?v=<?=$cacheVer?>"></script>
<script src="scripts/pi-hole/js/groups-domains.js?v=<?=$cacheVer?>"></script>
<script src="scripts/vendor/bootstrap-select.min.js?v=<?php echo $cacheVer; ?>"></script>
<script src="scripts/vendor/bootstrap-toggle.min.js?v=<?php echo $cacheVer; ?>"></script>
<script src="scripts/pi-hole/js/groups-domains.js?v=<?php echo $cacheVer; ?>"></script>
<?php
require "scripts/pi-hole/php/footer.php";
require 'scripts/pi-hole/php/footer.php';
?>

View File

@@ -8,7 +8,7 @@
* Please see LICENSE file for your rights under this license.
*/
require "scripts/pi-hole/php/header.php";
require 'scripts/pi-hole/php/header.php';
?>
<!-- Title -->
@@ -80,10 +80,10 @@ require "scripts/pi-hole/php/header.php";
</div>
</div>
<script src="scripts/vendor/bootstrap-select.min.js?v=<?=$cacheVer?>"></script>
<script src="scripts/vendor/bootstrap-toggle.min.js?v=<?=$cacheVer?>"></script>
<script src="scripts/pi-hole/js/groups.js?v=<?=$cacheVer?>"></script>
<script src="scripts/vendor/bootstrap-select.min.js?v=<?php echo $cacheVer; ?>"></script>
<script src="scripts/vendor/bootstrap-toggle.min.js?v=<?php echo $cacheVer; ?>"></script>
<script src="scripts/pi-hole/js/groups.js?v=<?php echo $cacheVer; ?>"></script>
<?php
require "scripts/pi-hole/php/footer.php";
require 'scripts/pi-hole/php/footer.php';
?>

View File

@@ -8,8 +8,10 @@
*/
$indexpage = true;
require "scripts/pi-hole/php/header.php";
require_once "scripts/pi-hole/php/gravity.php";
require 'scripts/pi-hole/php/header.php';
require_once 'scripts/pi-hole/php/gravity.php';
?>
<!-- Sourceing CSS colors from stylesheet to be used in JS code -->
<span class="queries-permitted"></span>
@@ -95,8 +97,8 @@ require_once "scripts/pi-hole/php/gravity.php";
// 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) {
?>
<div class="row">
<div class="col-md-12">
@@ -159,15 +161,11 @@ if($auth){
</div>
<?php
if($boxedlayout)
{
$tablelayout = "col-md-6";
}
else
{
$tablelayout = "col-md-6 col-lg-6";
}
?>
if ($boxedlayout) {
$tablelayout = 'col-md-6';
} else {
$tablelayout = 'col-md-6 col-lg-6';
} ?>
<div class="row">
<div class="<?php echo $tablelayout; ?>">
<div class="box" id="domain-frequency">
@@ -289,10 +287,11 @@ if($auth){
<!-- /.col -->
</div>
<!-- /.row -->
<?php } ?>
<?php
} ?>
<script src="scripts/pi-hole/js/index.js?v=<?=$cacheVer?>"></script>
<script src="scripts/pi-hole/js/index.js?v=<?php echo $cacheVer; ?>"></script>
<?php
require "scripts/pi-hole/php/footer.php";
require 'scripts/pi-hole/php/footer.php';
?>

View File

@@ -8,7 +8,7 @@
* Please see LICENSE file for your rights under this license.
*/
require "scripts/pi-hole/php/header.php";
require 'scripts/pi-hole/php/header.php';
?>
<!-- Title -->
@@ -47,8 +47,8 @@ require "scripts/pi-hole/php/header.php";
</div>
</div>
<script src="scripts/pi-hole/js/messages.js?v=<?=$cacheVer?>"></script>
<script src="scripts/pi-hole/js/messages.js?v=<?php echo $cacheVer; ?>"></script>
<?php
require "scripts/pi-hole/php/footer.php";
require 'scripts/pi-hole/php/footer.php';
?>

View File

@@ -7,7 +7,7 @@
* Please see LICENSE file for your rights under this license.
*/
require "scripts/pi-hole/php/header.php";
require 'scripts/pi-hole/php/header.php';
?>
<div class="row">
@@ -66,9 +66,9 @@ require "scripts/pi-hole/php/header.php";
</div>
<!-- /.row -->
<script src="scripts/pi-hole/js/ip-address-sorting.js?v=<?=$cacheVer?>"></script>
<script src="scripts/pi-hole/js/network.js?v=<?=$cacheVer?>"></script>
<script src="scripts/pi-hole/js/ip-address-sorting.js?v=<?php echo $cacheVer; ?>"></script>
<script src="scripts/pi-hole/js/network.js?v=<?php echo $cacheVer; ?>"></script>
<?php
require "scripts/pi-hole/php/footer.php";
require 'scripts/pi-hole/php/footer.php';
?>

View File

@@ -8,93 +8,66 @@
* Please see LICENSE file for your rights under this license.
*/
require "scripts/pi-hole/php/header.php";
require 'scripts/pi-hole/php/header.php';
$showing = "";
$showing = '';
if(isset($setupVars["API_QUERY_LOG_SHOW"]))
{
if($setupVars["API_QUERY_LOG_SHOW"] === "all")
{
$showing = "showing";
if (isset($setupVars['API_QUERY_LOG_SHOW'])) {
if ('all' === $setupVars['API_QUERY_LOG_SHOW']) {
$showing = 'showing';
} elseif ('permittedonly' === $setupVars['API_QUERY_LOG_SHOW']) {
$showing = 'showing permitted';
} elseif ('blockedonly' === $setupVars['API_QUERY_LOG_SHOW']) {
$showing = 'showing blocked';
} elseif ('nothing' === $setupVars['API_QUERY_LOG_SHOW']) {
$showing = 'showing no queries (due to setting)';
}
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(isset($_GET["type"]) && $_GET["type"] === "blocked")
{
$showing = "showing blocked";
}
else
{
} elseif (isset($_GET['type']) && 'blocked' === $_GET['type']) {
$showing = 'showing blocked';
} else {
// If filter variable is not set, we
// automatically show all queries
$showing = "showing";
$showing = 'showing';
}
$showall = false;
if(isset($_GET["all"]))
{
$showing .= " all queries within the Pi-hole log";
}
else if(isset($_GET["client"]))
{
if (isset($_GET['all'])) {
$showing .= ' all queries within the Pi-hole log';
} elseif (isset($_GET['client'])) {
// Add switch between showing all queries and blocked only
if (isset($_GET["type"]) && $_GET["type"] === "blocked")
{
if (isset($_GET['type']) && 'blocked' === $_GET['type']) {
// Show blocked queries for this client + link to all
$showing .= " blocked queries for client ".htmlentities($_GET["client"]);
$showing .= ", <a href=\"?client=".htmlentities($_GET["client"])."\">show all</a>";
}
else
{
$showing .= ' blocked queries for client '.htmlentities($_GET['client']);
$showing .= ', <a href="?client='.htmlentities($_GET['client']).'">show all</a>';
} else {
// Show All queries for this client + link to show only blocked
$showing .= " all queries for client ".htmlentities($_GET["client"]);
$showing .= ", <a href=\"?client=".htmlentities($_GET["client"])."&type=blocked\">show blocked only</a>";
$showing .= ' all queries for client '.htmlentities($_GET['client']);
$showing .= ', <a href="?client='.htmlentities($_GET['client']).'&type=blocked">show blocked only</a>';
}
}
else if(isset($_GET["forwarddest"]))
{
if($_GET["forwarddest"] === "blocked")
$showing .= " queries blocked by Pi-hole";
elseif($_GET["forwarddest"] === "cached")
$showing .= " queries answered from cache";
else
$showing .= " queries for upstream destination ".htmlentities($_GET["forwarddest"]);
}
else if(isset($_GET["querytype"]))
{
$showing .= " type ".getQueryTypeStr($_GET["querytype"])." queries";
}
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";
} elseif (isset($_GET['forwarddest'])) {
if ('blocked' === $_GET['forwarddest']) {
$showing .= ' queries blocked by Pi-hole';
} elseif ('cached' === $_GET['forwarddest']) {
$showing .= ' queries answered from cache';
} else {
$showing .= ' queries for upstream destination '.htmlentities($_GET['forwarddest']);
}
} elseif (isset($_GET['querytype'])) {
$showing .= ' type '.getQueryTypeStr($_GET['querytype']).' queries';
} 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(strlen($showing) > 0)
{
$showing = "(".$showing.")";
if($showall)
$showing .= ", <a href=\"?all\">show all</a>";
if (strlen($showing) > 0) {
$showing = '('.$showing.')';
if ($showall) {
$showing .= ', <a href="?all">show all</a>';
}
}
?>
@@ -178,9 +151,9 @@ if(strlen($showing) > 0)
</div>
</div>
<!-- /.row -->
<script src="scripts/pi-hole/js/ip-address-sorting.js?v=<?=$cacheVer?>"></script>
<script src="scripts/pi-hole/js/queries.js?v=<?=$cacheVer?>"></script>
<script src="scripts/pi-hole/js/ip-address-sorting.js?v=<?php echo $cacheVer; ?>"></script>
<script src="scripts/pi-hole/js/queries.js?v=<?php echo $cacheVer; ?>"></script>
<?php
require "scripts/pi-hole/php/footer.php";
require 'scripts/pi-hole/php/footer.php';
?>

View File

@@ -8,7 +8,7 @@
* Please see LICENSE file for your rights under this license.
*/
require "scripts/pi-hole/php/header.php";
require 'scripts/pi-hole/php/header.php';
?>
<!-- Title -->
<div class="page-header">
@@ -35,7 +35,7 @@ require "scripts/pi-hole/php/header.php";
<pre id="output" style="width: 100%; height: 100%;" hidden></pre>
<script src="scripts/pi-hole/js/queryads.js?v=<?=$cacheVer?>"></script>
<script src="scripts/pi-hole/js/queryads.js?v=<?php echo $cacheVer; ?>"></script>
<?php
require "scripts/pi-hole/php/footer.php";
require 'scripts/pi-hole/php/footer.php';
?>

View File

@@ -7,12 +7,13 @@
* Please see LICENSE file for your rights under this license.
*/
const DEFAULT_FTLCONFFILE = "/etc/pihole/pihole-FTL.conf";
const DEFAULT_FTL_IP = "127.0.0.1";
const DEFAULT_FTLCONFFILE = '/etc/pihole/pihole-FTL.conf';
const DEFAULT_FTL_IP = '127.0.0.1';
const DEFAULT_FTL_PORT = 4711;
const DEFAULT_FTL_PORTFILE = "/run/pihole-FTL.port";
const DEFAULT_FTL_PORTFILE = '/run/pihole-FTL.port';
function piholeFTLConfig($piholeFTLConfFile = DEFAULT_FTLCONFFILE, $force = false) {
function piholeFTLConfig($piholeFTLConfFile = DEFAULT_FTLCONFFILE, $force = false)
{
static $piholeFTLConfig;
if (isset($piholeFTLConfig) && !$force) {
@@ -28,12 +29,13 @@ function piholeFTLConfig($piholeFTLConfFile = DEFAULT_FTLCONFFILE, $force = fals
return $piholeFTLConfig;
}
function connectFTL($address, $port) {
if ($address == DEFAULT_FTL_IP) {
function connectFTL($address, $port)
{
if (DEFAULT_FTL_IP == $address) {
$config = piholeFTLConfig();
// Read port
$portfileName = isset($config['PORTFILE']) ? $config['PORTFILE'] : DEFAULT_FTL_PORTFILE;
if ($portfileName != '') {
if ('' != $portfileName) {
$portfileContents = file_get_contents($portfileName);
if (is_numeric($portfileContents)) {
$port = intval($portfileContents);
@@ -42,32 +44,32 @@ function connectFTL($address, $port) {
}
// Open Internet socket connection
$socket = @fsockopen($address, $port, $errno, $errstr, 1.0);
return $socket;
return @fsockopen($address, $port, $errno, $errstr, 1.0);
}
function sendRequestFTL($requestin, $socket) {
$request = ">".$requestin;
fwrite($socket, $request) or die('{"error":"Could not send data to server"}');
function sendRequestFTL($requestin, $socket)
{
$request = '>'.$requestin;
fwrite($socket, $request) or exit('{"error":"Could not send data to server"}');
}
function getResponseFTL($socket) {
$response = [];
function getResponseFTL($socket)
{
$response = array();
$errCount = 0;
while (true) {
$out = fgets($socket);
if ($out == "") {
$errCount++;
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!"}');
exit('{"error":"Tried 100 times to connect to FTL server, but never got proper reply. Please check Port and logs!"}');
}
if (strrpos($out,"---EOM---") !== false) {
if (false !== strrpos($out, '---EOM---')) {
break;
}
@@ -80,22 +82,24 @@ function getResponseFTL($socket) {
return $response;
}
function disconnectFTL($socket) {
function disconnectFTL($socket)
{
if (is_resource($socket)) {
fclose($socket);
}
}
function callFTLAPI($request, $FTL_IP = DEFAULT_FTL_IP, $port = DEFAULT_FTL_PORT) {
function callFTLAPI($request, $FTL_IP = DEFAULT_FTL_IP, $port = DEFAULT_FTL_PORT)
{
$socket = connectFTL($FTL_IP, $port);
if (!is_resource($socket)) {
$data = array("FTLnotrunning" => true);
$data = array('FTLnotrunning' => true);
} else {
sendRequestFTL($request, $socket);
$data = getResponseFTL($socket);
}
disconnectFTL($socket);
return $data;
}
?>

View File

@@ -1,6 +1,7 @@
<?php
require "auth.php";
require "password.php";
require 'auth.php';
require 'password.php';
check_cors();
?>
@@ -30,20 +31,21 @@ body {
</head>
<body>
<?php
if($auth) {
if(strlen($pwhash) > 0) {
if ($auth) {
if (strlen($pwhash) > 0) {
echo '<div class="qrcode">';
require_once("../../vendor/qrcode.php");
require_once '../../vendor/qrcode.php';
$qr = QRCode::getMinimumQRCode($pwhash, QR_ERROR_CORRECT_LEVEL_Q);
// The size of each block (in pixels) should be an integer
$qr->printSVG(10);
echo "</div>";
echo 'Raw API Token: <code class="token">' . $pwhash . "</code></div>";
echo '</div>';
echo 'Raw API Token: <code class="token">'.$pwhash.'</code></div>';
} else {
echo "<p>No password set</p>";
echo '<p>No password set</p>';
}
} else {
echo "<p>Not authorized!</p>";
echo '<p>Not authorized!</p>';
}
?>
</body>

View File

@@ -7,7 +7,7 @@
* Please see LICENSE file for your rights under this license.
*/
require_once('func.php');
require_once 'func.php';
$ERRORLOG = getenv('PHP_ERROR_LOG');
if (empty($ERRORLOG)) {
@@ -22,35 +22,41 @@ if (empty($ERRORLOG)) {
}
}
function pi_log($message) {
error_log(date('Y-m-d H:i:s') . ': ' . $message . "\n", 3, $GLOBALS['ERRORLOG']);
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);
exit($message);
}
function check_cors() {
function check_cors()
{
$ip = $_SERVER['SERVER_ADDR'];
// Check CORS
$AUTHORIZED_HOSTNAMES = array(
$ip,
str_replace(array("[","]"), array("",""), $_SERVER["SERVER_NAME"]),
"pi.hole",
"localhost"
str_replace(array('[', ']'), array('', ''), $_SERVER['SERVER_NAME']),
'pi.hole',
'localhost',
);
# Allow user set virtual hostnames
// Allow user set virtual hostnames
$virtual_host = getenv('VIRTUAL_HOST');
if (! empty($virtual_host))
if (!empty($virtual_host)) {
array_push($AUTHORIZED_HOSTNAMES, $virtual_host);
}
# Allow user set CORS
// Allow user set CORS
$cors_hosts = getenv('CORS_HOSTS');
if (! empty($cors_hosts))
array_push($AUTHORIZED_HOSTNAMES, ...explode(",", $cors_hosts));
if (!empty($cors_hosts)) {
array_push($AUTHORIZED_HOSTNAMES, ...explode(',', $cors_hosts));
}
// 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.
@@ -64,43 +70,42 @@ 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);
$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 '. htmlspecialchars(join(', ', $AUTHORIZED_HOSTNAMES)));
if (isset($_SERVER['HTTP_HOST']) && !in_array($server_host, $AUTHORIZED_HOSTNAMES)) {
log_and_die('Failed Host Check: '.$server_host.' vs '.htmlspecialchars(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);
$server_origin = str_replace(array('[', ']', 'http://', 'https://'), array('', '', '', ''), $server_origin);
if(!in_array($server_origin, $AUTHORIZED_HOSTNAMES)) {
log_and_die("Failed CORS: " . htmlspecialchars($server_origin) .' vs '. htmlspecialchars(join(', ', $AUTHORIZED_HOSTNAMES)));
if (!in_array($server_origin, $AUTHORIZED_HOSTNAMES)) {
log_and_die('Failed CORS: '.htmlspecialchars($server_origin).' vs '.htmlspecialchars(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() == "";
$session_started = function_exists('session_status') ?
PHP_SESSION_ACTIVE == session_status() :
'' == session_id();
if(!$session_started) {
if (!$session_started) {
// Start a new PHP session (or continue an existing one)
// Prevents javascript XSS attacks aimed to steal the session ID
ini_set('session.cookie_httponly', 1);
@@ -109,26 +114,25 @@ function check_csrf($token) {
session_start();
}
if(!isset($_SESSION['token'])) {
log_and_die("Session expired! Please re-login on the Pi-hole dashboard.");
if (!isset($_SESSION['token'])) {
log_and_die('Session expired! Please re-login on the Pi-hole dashboard.');
}
if(empty($token)) {
log_and_die("Empty token! Check if cookies are enabled on your system.");
if (empty($token)) {
log_and_die('Empty token! Check if cookies are enabled on your system.');
}
if(!hash_equals($_SESSION['token'], $token)) {
log_and_die("Wrong token! Please re-login on the Pi-hole dashboard.");
if (!hash_equals($_SESSION['token'], $token)) {
log_and_die('Wrong token! Please re-login on the Pi-hole dashboard.');
}
}
function check_domain(&$domains) {
foreach($domains as &$domain)
{
function check_domain(&$domains)
{
foreach ($domains as &$domain) {
$validDomain = validDomain($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'));
}
}
}
?>

View File

@@ -1,6 +1,8 @@
<?php
require_once "func.php";
require_once('auth.php');
require_once 'func.php';
require_once 'auth.php';
// Authentication checks
if (!isset($api)) {
@@ -13,10 +15,18 @@ if (!isset($api)) {
}
switch ($_POST['action']) {
case 'get': echo json_encode(echoCustomCNAMEEntries()); break;
case 'add': echo json_encode(addCustomCNAMEEntry()); break;
case 'delete': echo json_encode(deleteCustomCNAMEEntry()); break;
case 'get': echo json_encode(echoCustomCNAMEEntries());
break;
case 'add': echo json_encode(addCustomCNAMEEntry());
break;
case 'delete': echo json_encode(deleteCustomCNAMEEntry());
break;
default:
die("Wrong action");
exit('Wrong action');
}
?>

View File

@@ -1,6 +1,8 @@
<?php
require_once "func.php";
require_once('auth.php');
require_once 'func.php';
require_once 'auth.php';
// Authentication checks
if (!isset($api)) {
@@ -13,10 +15,18 @@ if (!isset($api)) {
}
switch ($_POST['action']) {
case 'get': echo json_encode(echoCustomDNSEntries()); break;
case 'add': echo json_encode(addCustomDNSEntry()); break;
case 'delete': echo json_encode(deleteCustomDNSEntry()); break;
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");
exit('Wrong action');
}
?>

View File

@@ -10,68 +10,53 @@
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";
$FTLsettings = parse_ini_file('/etc/pihole/pihole-FTL.conf');
if (isset($FTLsettings['GRAVITYDB'])) {
return $FTLsettings['GRAVITYDB'];
}
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";
$FTLsettings = parse_ini_file('/etc/pihole/pihole-FTL.conf');
if (isset($FTLsettings['DBFILE'])) {
return $FTLsettings['DBFILE'];
}
return '/etc/pihole/pihole-FTL.db';
}
function SQLite3_connect_try($filename, $mode, $trytoreconnect)
{
try
{
try {
// connect to database
return new SQLite3($filename, $mode);
}
catch (Exception $exception)
{
} catch (Exception $exception) {
// sqlite3 throws an exception when it is unable to connect, try to reconnect after 3 seconds
if($trytoreconnect)
{
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();
}
// 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)
{
if (strlen($filename) > 0) {
$db = SQLite3_connect_try($filename, $mode, true);
} else {
exit('No database available');
}
else
{
die("No database available");
}
if(is_string($db))
{
die("Error connecting to database\n".$db);
if (is_string($db)) {
exit("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
@@ -80,9 +65,8 @@ function SQLite3_connect($filename, $mode=SQLITE3_OPEN_READONLY)
return $db;
}
/**
* Add domains to a given table
* Add domains to a given table.
*
* @param $db object The SQLite3 database connection object
* @param $table string The target table
@@ -90,233 +74,222 @@ function SQLite3_connect($filename, $mode=SQLITE3_OPEN_READONLY)
* @param $wildcardstyle boolean Whether to format the input domains in legacy wildcard notation
* @param $returnnum boolean Whether to return an integer or a string
* @param $type integer The target type (0 = exact whitelist, 1 = exact blacklist, 2 = regex whitelist, 3 = regex blacklist)
* @param null|mixed $comment
*
* @return string Success/error and number of processed domains
*/
function add_to_table($db, $table, $domains, $comment=null, $wildcardstyle=false, $returnnum=false, $type=-1)
function add_to_table($db, $table, $domains, $comment = null, $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)
if (!$db->exec('BEGIN TRANSACTION;')) {
if ($returnnum) {
return 0;
else
return "Error: Unable to begin transaction for $table table.";
}
return "Error: Unable to begin transaction for {$table} table.";
}
// To which column should the record be added to?
if ($table === "adlist")
{
$field = "address";
}
else
{
$field = "domain";
if ('adlist' === $table) {
$field = 'address';
} else {
$field = 'domain';
}
// 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;";
if (-1 === $type) {
$countquery = "SELECT COUNT(*) FROM {$table};";
} else {
$countquery = "SELECT COUNT(*) FROM {$table} WHERE type = {$type};";
}
$initialcount = intval($db->querySingle($countquery));
// Prepare INSERT SQLite statement
$bindcomment = false;
if($table === "domain_audit") {
$querystr = "INSERT OR IGNORE INTO $table ($field) VALUES (:$field);";
} elseif($type === -1) {
$querystr = "INSERT OR IGNORE INTO $table ($field,comment) VALUES (:$field, :comment);";
if ('domain_audit' === $table) {
$querystr = "INSERT OR IGNORE INTO {$table} ({$field}) VALUES (:{$field});";
} elseif (-1 === $type) {
$querystr = "INSERT OR IGNORE INTO {$table} ({$field},comment) VALUES (:{$field}, :comment);";
$bindcomment = true;
} else {
$querystr = "REPLACE INTO $table ($field,comment,type) VALUES (:$field, :comment, $type);";
$querystr = "REPLACE INTO {$table} ({$field},comment,type) VALUES (:{$field}, :comment, {$type});";
$bindcomment = true;
}
$stmt = $db->prepare($querystr);
// Return early if we failed to prepare the SQLite statement
if(!$stmt)
{
if($returnnum)
if (!$stmt) {
if ($returnnum) {
return 0;
else
return "Error: Failed to prepare statement for $table table (type = $type, field = $field).";
}
return "Error: Failed to prepare statement for {$table} table (type = {$type}, field = {$field}).";
}
// Loop over domains and inject the lines into the database
$num = 0;
foreach($domains as $domain)
{
foreach ($domains as $domain) {
// Limit max length for a domain entry to 253 chars
if(strlen($domain) > 253)
if (strlen($domain) > 253) {
continue;
if($wildcardstyle)
$domain = "(\\.|^)".str_replace(".","\\.",$domain)."$";
$stmt->bindValue(":$field", htmlentities($domain), SQLITE3_TEXT);
if($bindcomment) {
$stmt->bindValue(":comment", htmlentities($comment), SQLITE3_TEXT);
}
if($stmt->execute() && $stmt->reset())
$num++;
else
{
if ($wildcardstyle) {
$domain = '(\\.|^)'.str_replace('.', '\\.', $domain).'$';
}
$stmt->bindValue(":{$field}", htmlentities($domain), SQLITE3_TEXT);
if ($bindcomment) {
$stmt->bindValue(':comment', htmlentities($comment), SQLITE3_TEXT);
}
if ($stmt->execute() && $stmt->reset()) {
++$num;
} else {
$stmt->close();
if($returnnum)
if ($returnnum) {
return $num;
else
{
if($num === 1)
$plural = "";
else
$plural = "s";
return "Error: ".$db->lastErrorMsg().", added ".$num." domain".$plural;
}
if (1 === $num) {
$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;");
$db->exec('COMMIT;');
if($returnnum)
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($num === 1)
$plural = "";
else
$plural = "s";
return "Success, added ".$modified." of ".$num." domain".$plural.$extra;
}
$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 (1 === $num) {
$plural = '';
} else {
$plural = 's';
}
return 'Success, added '.$modified.' of '.$num.' domain'.$plural.$extra;
}
/**
* Remove domains from a given table
* Remove domains from a given table.
*
* @param $db object The SQLite3 database connection object
* @param $table string The target table
* @param $domains array Array of domains (strings) to be removed from the table
* @param $returnnum boolean Whether to return an integer or a string
* @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)
if (!$db->exec('BEGIN TRANSACTION;')) {
if ($returnnum) {
return 0;
else
return "Error: Unable to begin transaction for domainlist table.";
}
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;";
if (-1 === $type) {
$countquery = "SELECT COUNT(*) FROM {$table};";
} else {
$countquery = "SELECT COUNT(*) FROM {$table} WHERE type = {$type};";
}
$initialcount = intval($db->querySingle($countquery));
// Prepare SQLite statement
if($type === -1)
{
$querystr = "DELETE FROM $table WHERE domain = :domain AND type = $type;";
}
else
{
$querystr = "DELETE FROM $table WHERE domain = :domain;";
if (-1 === $type) {
$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)
if (!$stmt) {
if ($returnnum) {
return 0;
else
return "Error: Failed to prepare statement for ".$table." table (type = ".$type.").";
}
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);
foreach ($domains as $domain) {
$stmt->bindValue(':domain', $domain, SQLITE3_TEXT);
if($stmt->execute() && $stmt->reset())
$num++;
else
{
if ($stmt->execute() && $stmt->reset()) {
++$num;
} else {
$stmt->close();
if($returnnum)
if ($returnnum) {
return $num;
else
{
if($num === 1)
$plural = "";
else
$plural = "s";
return "Error: ".$db->lastErrorMsg().", removed ".$num." domain".$plural;
}
if (1 === $num) {
$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;");
$db->exec('COMMIT;');
if($returnnum)
if ($returnnum) {
return $num;
else
{
if($num === 1)
$plural = "";
else
$plural = "s";
return "Success, removed ".$num." domain".$plural;
}
if (1 === $num) {
$plural = '';
} else {
$plural = 's';
}
return 'Success, removed '.$num.' domain'.$plural;
}
if (!class_exists("ListType")) {
class ListType{
const whitelist = 0;
const blacklist = 1;
const regex_whitelist = 2;
const regex_blacklist = 3;
if (!class_exists('ListType')) {
class ListType
{
public const whitelist = 0;
public const blacklist = 1;
public const regex_whitelist = 2;
public const regex_blacklist = 3;
}
}

View File

@@ -1,70 +1,72 @@
<?php
ob_end_flush();
ini_set("output_buffering", "0");
ini_set('output_buffering', '0');
ob_implicit_flush(true);
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
require "password.php";
require "auth.php";
require 'password.php';
require 'auth.php';
if (!$auth) {
die("Unauthorized");
exit('Unauthorized');
}
check_cors();
$token = isset($_GET["token"]) ? $_GET["token"] : "";
$token = isset($_GET['token']) ? $_GET['token'] : '';
check_csrf($token);
function echoEvent($datatext) {
function echoEvent($datatext)
{
$ANSIcolors = array(
chr(27)."[1;91m" => '<span class="log-red">',
chr(27)."[1;32m" => '<span class="log-green">',
chr(27)."[1;33m" => '<span class="log-yellow">',
chr(27)."[1;34m" => '<span class="log-blue">',
chr(27)."[1;35m" => '<span class="log-purple">',
chr(27)."[1;36m" => '<span class="log-cyan">',
chr(27).'[1;91m' => '<span class="log-red">',
chr(27).'[1;32m' => '<span class="log-green">',
chr(27).'[1;33m' => '<span class="log-yellow">',
chr(27).'[1;34m' => '<span class="log-blue">',
chr(27).'[1;35m' => '<span class="log-purple">',
chr(27).'[1;36m' => '<span class="log-cyan">',
chr(27)."[90m" => '<span class="log-gray">',
chr(27)."[91m" => '<span class="log-red">',
chr(27)."[32m" => '<span class="log-green">',
chr(27)."[33m" => '<span class="log-yellow">',
chr(27)."[94m" => '<span class="log-blue">',
chr(27)."[95m" => '<span class="log-purple">',
chr(27)."[96m" => '<span class="log-cyan">',
chr(27).'[90m' => '<span class="log-gray">',
chr(27).'[91m' => '<span class="log-red">',
chr(27).'[32m' => '<span class="log-green">',
chr(27).'[33m' => '<span class="log-yellow">',
chr(27).'[94m' => '<span class="log-blue">',
chr(27).'[95m' => '<span class="log-purple">',
chr(27).'[96m' => '<span class="log-cyan">',
chr(27)."[1m" => '<span class="text-bold">',
chr(27)."[4m" => '<span class="text-underline">',
chr(27).'[1m' => '<span class="text-bold">',
chr(27).'[4m' => '<span class="text-underline">',
chr(27)."[0m" => '</span>',
chr(27).'[0m' => '</span>',
);
$data = str_replace(array_keys($ANSIcolors), $ANSIcolors, htmlspecialchars($datatext));
if (!isset($_GET["IE"])) {
echo "data: ".implode("\ndata: ", explode("\n", $data))."\n\n";
if (!isset($_GET['IE'])) {
echo 'data: '.implode("\ndata: ", explode("\n", $data))."\n\n";
} else {
echo $data;
}
}
// Execute "pihole" using Web option
$command = "export TERM=dumb && sudo pihole -d -w";
$command = 'export TERM=dumb && sudo pihole -d -w';
// Add auto-upload option
if (isset($_GET["upload"])) {
$command .= " -a";
if (isset($_GET['upload'])) {
$command .= ' -a';
}
// Execute database integrity_check
if (isset($_GET["dbcheck"])) {
$command .= " -c";
if (isset($_GET['dbcheck'])) {
$command .= ' -c';
}
$proc = popen($command, "r");
$proc = popen($command, 'r');
while (!feof($proc)) {
echoEvent(fread($proc, 4096));
}
?>

View File

@@ -43,26 +43,26 @@
<?php
// Flushes the system write buffers of PHP. This attempts to push everything we have so far all the way to the client's browser.
flush();
// Run update checker
// - determines local branch each time,
// - determines local and remote version every 30 minutes
require "scripts/pi-hole/php/update_checker.php";
// Run update checker
// - determines local branch each time,
// - determines local and remote version every 30 minutes
require 'scripts/pi-hole/php/update_checker.php';
$coreVersionStr = $core_current . (isset($core_commit) ? " (" . $core_branch . ", " . $core_commit . ")" : "");
$ftlVersionStr = $FTL_current . (isset($FTL_commit) ? " (" . $FTL_branch . ", " . $FTL_commit . ")" : "");
$webVersionStr = $web_current . (isset($web_commit) ? " (" . $web_branch . ", " . $web_commit . ")" : "");
$dockerTag = htmlspecialchars(getenv('PIHOLE_DOCKER_TAG'));
$coreVersionStr = $core_current.(isset($core_commit) ? ' ('.$core_branch.', '.$core_commit.')' : '');
$ftlVersionStr = $FTL_current.(isset($FTL_commit) ? ' ('.$FTL_branch.', '.$FTL_commit.')' : '');
$webVersionStr = $web_current.(isset($web_commit) ? ' ('.$web_branch.', '.$web_commit.')' : '');
$dockerTag = htmlspecialchars(getenv('PIHOLE_DOCKER_TAG'));
$githubBaseUrl = "https://github.com/pi-hole";
$coreUrl = $githubBaseUrl . "/pi-hole";
$dockerUrl = $githubBaseUrl . "/docker-pi-hole";
$ftlUrl = $githubBaseUrl . "/FTL";
$webUrl = $githubBaseUrl . "/AdminLTE";
$githubBaseUrl = 'https://github.com/pi-hole';
$coreUrl = $githubBaseUrl.'/pi-hole';
$dockerUrl = $githubBaseUrl.'/docker-pi-hole';
$ftlUrl = $githubBaseUrl.'/FTL';
$webUrl = $githubBaseUrl.'/AdminLTE';
$coreReleasesUrl = $coreUrl . "/releases";
$dockerReleasesUrl = $dockerUrl . "/releases";
$ftlReleasesUrl = $ftlUrl . "/releases";
$webReleasesUrl = $webUrl . "/releases";
$coreReleasesUrl = $coreUrl.'/releases';
$dockerReleasesUrl = $dockerUrl.'/releases';
$ftlReleasesUrl = $ftlUrl.'/releases';
$webReleasesUrl = $webUrl.'/releases';
?>
<footer class="main-footer">
<div class="row row-centered text-center">
@@ -75,37 +75,37 @@
<div class="col-xs-12 col-sm-8 col-md-6">
<?php if (isset($core_commit) || isset($web_commit) || isset($FTL_commit)) { ?>
<ul class="list-unstyled">
<?php if($dockerTag) { ?> <li><strong>Docker Tag</strong> <?php echo $dockerTag; ?></li> <?php } ?>
<?php if ($dockerTag) { ?> <li><strong>Docker Tag</strong> <?php echo $dockerTag; ?></li> <?php } ?>
<li><strong>Pi-hole</strong> <?php echo $coreVersionStr; ?></li>
<li><strong>FTL</strong> <?php echo $ftlVersionStr; ?></li>
<li><strong>Web Interface</strong> <?php echo $webVersionStr; ?></li>
</ul>
<?php } else { ?>
<ul class="list-inline">
<?php if($dockerTag) { ?>
<?php if ($dockerTag) { ?>
<li>
<strong>Docker Tag</strong>
<a href="<?php echo $dockerReleasesUrl . "/" . $dockerTag; ?>" rel="noopener" target="_blank"><?php echo $dockerTag; ?></a>
<a href="<?php echo $dockerReleasesUrl.'/'.$dockerTag; ?>" rel="noopener" target="_blank"><?php echo $dockerTag; ?></a>
</li>
<?php } ?>
<li>
<strong>Pi-hole</strong>
<a href="<?php echo $coreReleasesUrl . "/" . $core_current; ?>" rel="noopener" target="_blank"><?php echo $core_current; ?></a>
<?php if ($core_update) { ?> &middot; <a class="lookatme" lookatme-text="Update available!" href="<?php echo $coreReleasesUrl . "/latest"; ?>" rel="noopener" target="_blank">Update available!</a><?php } ?>
<a href="<?php echo $coreReleasesUrl.'/'.$core_current; ?>" rel="noopener" target="_blank"><?php echo $core_current; ?></a>
<?php if ($core_update) { ?> &middot; <a class="lookatme" lookatme-text="Update available!" href="<?php echo $coreReleasesUrl.'/latest'; ?>" rel="noopener" target="_blank">Update available!</a><?php } ?>
</li>
<li>
<strong>FTL</strong>
<a href="<?php echo $ftlReleasesUrl . "/" . $FTL_current; ?>" rel="noopener" target="_blank"><?php echo $FTL_current; ?></a>
<?php if ($FTL_update) { ?> &middot; <a class="lookatme" lookatme-text="Update available!" href="<?php echo $ftlReleasesUrl . "/latest"; ?>" rel="noopener" target="_blank">Update available!</a><?php } ?>
<a href="<?php echo $ftlReleasesUrl.'/'.$FTL_current; ?>" rel="noopener" target="_blank"><?php echo $FTL_current; ?></a>
<?php if ($FTL_update) { ?> &middot; <a class="lookatme" lookatme-text="Update available!" href="<?php echo $ftlReleasesUrl.'/latest'; ?>" rel="noopener" target="_blank">Update available!</a><?php } ?>
</li>
<li>
<strong>Web Interface</strong>
<a href="<?php echo $webReleasesUrl . "/" . $web_current; ?>" rel="noopener" target="_blank"><?php echo $web_current; ?></a>
<?php if ($web_update) { ?> &middot; <a class="lookatme" lookatme-text="Update available!" href="<?php echo $webReleasesUrl . "/latest"; ?>" rel="noopener" target="_blank">Update available!</a><?php } ?>
<a href="<?php echo $webReleasesUrl.'/'.$web_current; ?>" rel="noopener" target="_blank"><?php echo $web_current; ?></a>
<?php if ($web_update) { ?> &middot; <a class="lookatme" lookatme-text="Update available!" href="<?php echo $webReleasesUrl.'/latest'; ?>" rel="noopener" target="_blank">Update available!</a><?php } ?>
</li>
</ul>
<?php if($core_update || $web_update || $FTL_update) { ?>
<?php if($dockerTag) { ?>
<?php if ($core_update || $web_update || $FTL_update) { ?>
<?php if ($dockerTag) { ?>
<p>To install updates, <a href="https://github.com/pi-hole/docker-pi-hole#upgrading--reconfiguring" rel="noopener" target="_blank">replace this old container with a fresh upgraded image</a>.</p>
<?php } else { ?>
<p>To install updates, run <code><a href="https://docs.pi-hole.net/main/update/" rel="noopener" target="_blank">pihole -up</a></code>.</p>
@@ -118,6 +118,6 @@
</div>
<!-- ./wrapper -->
<script src="scripts/pi-hole/js/footer.js?v=<?=$cacheVer?>"></script>
<script src="scripts/pi-hole/js/footer.js?v=<?php echo $cacheVer; ?>"></script>
</body>
</html>

View File

@@ -9,22 +9,28 @@
// Credit: http://stackoverflow.com/a/4694816/2087442
// Modified because of https://github.com/pi-hole/AdminLTE/pull/533
ini_set("pcre.recursion_limit", 1500);
function validDomain($domain_name, &$message = NULL)
ini_set('pcre.recursion_limit', 1500);
function validDomain($domain_name, &$message = null)
{
if(!preg_match("/^((-|_)*[a-z\d]((-|_)*[a-z\d])*(-|_)*)(\.(-|_)*([a-z\d]((-|_)*[a-z\d])*))*$/i", $domain_name)) {
if($message !== NULL)
$message = "it contains invalid characters";
if (!preg_match('/^((-|_)*[a-z\\d]((-|_)*[a-z\\d])*(-|_)*)(\\.(-|_)*([a-z\\d]((-|_)*[a-z\\d])*))*$/i', $domain_name)) {
if (null !== $message) {
$message = 'it contains invalid characters';
}
return false;
}
if(!preg_match("/^.{1,253}$/", $domain_name)) {
if($message !== NULL)
$message = "its length is invalid";
if (!preg_match('/^.{1,253}$/', $domain_name)) {
if (null !== $message) {
$message = 'its length is invalid';
}
return false;
}
if(!preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name)) {
if($message !== NULL)
$message = "at least one label is of invalid length";
if (!preg_match('/^[^\\.]{1,63}(\\.[^\\.]{1,63})*$/', $domain_name)) {
if (null !== $message) {
$message = 'at least one label is of invalid length';
}
return false;
}
@@ -35,44 +41,49 @@ function validDomain($domain_name, &$message = NULL)
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
$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 validIP($address){
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;
return false === !filter_var($address, FILTER_VALIDATE_IP);
}
function validCIDRIP($address){
function validCIDRIP($address)
{
// This validation strategy has been taken from ../js/groups-common.js
$isIPv6 = strpos($address, ":") !== false;
if($isIPv6) {
$isIPv6 = false !== strpos($address, ':');
if ($isIPv6) {
// One IPv6 element is 16bit: 0000 - FFFF
$v6elem = "[0-9A-Fa-f]{1,4}";
$v6elem = '[0-9A-Fa-f]{1,4}';
// dnsmasq allows arbitrary prefix-length since https://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=35f93081dc9a52e64ac3b7196ad1f5c1106f8932
$v6cidr = "([1-9]|[1-9][0-9]|1[01][0-9]|12[0-8])";
$validator = "/^(((?:$v6elem))((?::$v6elem))*::((?:$v6elem))((?::$v6elem))*|((?:$v6elem))((?::$v6elem)){7})\/$v6cidr$/";
return preg_match($validator, $address);
} else {
// One IPv4 element is 8bit: 0 - 256
$v4elem = "(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)";
// dnsmasq allows arbitrary prefix-length
$allowedv4cidr = "(([1-9]|[12][0-9]|3[0-2]))";
$validator = "/^$v4elem\.$v4elem\.$v4elem\.$v4elem\/$allowedv4cidr$/";
$v6cidr = '([1-9]|[1-9][0-9]|1[01][0-9]|12[0-8])';
$validator = "/^(((?:{$v6elem}))((?::{$v6elem}))*::((?:{$v6elem}))((?::{$v6elem}))*|((?:{$v6elem}))((?::{$v6elem})){7})\\/{$v6cidr}$/";
return preg_match($validator, $address);
}
// One IPv4 element is 8bit: 0 - 256
$v4elem = '(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)';
// dnsmasq allows arbitrary prefix-length
$allowedv4cidr = '(([1-9]|[12][0-9]|3[0-2]))';
$validator = "/^{$v4elem}\\.{$v4elem}\\.{$v4elem}\\.{$v4elem}\\/{$allowedv4cidr}$/";
return preg_match($validator, $address);
}
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 false === !filter_var($mac_addr, FILTER_VALIDATE_MAC);
}
function validEmail($email)
@@ -87,26 +98,25 @@ function validEmail($email)
function get_ip_type($ip)
{
return filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) ? 4 :
return filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) ? 4 :
(filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) ? 6 :
0);
}
function checkfile($filename) {
if(is_readable($filename))
{
function checkfile($filename)
{
if (is_readable($filename)) {
return $filename;
}
else
{
// substitute dummy file
return "/dev/null";
}
// 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)) {
@@ -137,51 +147,53 @@ if(!function_exists('hash_equals')) {
*
* and returns output of that command as a string.
*
* @param $argument_string String of arguments to run pihole with.
* @param $argument_string String of arguments to run pihole with
*/
function pihole_execute($argument_string) {
function pihole_execute($argument_string)
{
$escaped = escapeshellcmd($argument_string);
$output = null;
$return_status = -1;
$command = "sudo pihole " . $escaped;
$command = 'sudo pihole '.$escaped;
exec($command, $output, $return_status);
if($return_status !== 0)
{
if (0 !== $return_status) {
trigger_error("Executing {$command} failed.", E_USER_WARNING);
}
return $output;
}
// Custom DNS
$customDNSFile = "/etc/pihole/custom.list";
$customDNSFile = '/etc/pihole/custom.list';
function echoCustomDNSEntries()
{
$entries = getCustomDNSEntries();
$data = [];
foreach ($entries as $entry)
$data[] = [ $entry->domain, $entry->ip ];
$data = array();
foreach ($entries as $entry) {
$data[] = array($entry->domain, $entry->ip);
}
return [ "data" => $data ];
return array('data' => $data);
}
function getCustomDNSEntries()
{
global $customDNSFile;
$entries = [];
$entries = array();
$handle = fopen($customDNSFile, "r");
if ($handle)
{
$handle = fopen($customDNSFile, 'r');
if ($handle) {
while (($line = fgets($handle)) !== false) {
$line = str_replace("\r","", $line);
$line = str_replace("\n","", $line);
$explodedLine = explode (" ", $line);
$line = str_replace("\r", '', $line);
$line = str_replace("\n", '', $line);
$explodedLine = explode(' ', $line);
if (count($explodedLine) != 2)
if (2 != count($explodedLine)) {
continue;
}
$data = new \stdClass();
$data->ip = $explodedLine[0];
@@ -195,105 +207,110 @@ function getCustomDNSEntries()
return $entries;
}
function addCustomDNSEntry($ip="", $domain="", $reload="", $json=true)
function addCustomDNSEntry($ip = '', $domain = '', $reload = '', $json = true)
{
try
{
if(isset($_REQUEST['ip']))
try {
if (isset($_REQUEST['ip'])) {
$ip = trim($_REQUEST['ip']);
}
if(isset($_REQUEST['domain']))
if (isset($_REQUEST['domain'])) {
$domain = trim($_REQUEST['domain']);
}
if(isset($_REQUEST['reload']))
if (isset($_REQUEST['reload'])) {
$reload = $_REQUEST['reload'];
}
if (empty($ip))
return returnError("IP must be set", $json);
if (empty($ip)) {
return returnError('IP must be set', $json);
}
$ipType = get_ip_type($ip);
if (!$ipType)
return returnError("IP must be valid", $json);
if (!$ipType) {
return returnError('IP must be valid', $json);
}
if (empty($domain))
return returnError("Domain must be set", $json);
if (empty($domain)) {
return returnError('Domain must be set', $json);
}
if (!validDomain($domain))
return returnError("Domain must be valid", $json);
if (!validDomain($domain)) {
return returnError('Domain must be valid', $json);
}
// Only check for duplicates if adding new records from the web UI (not through Teleporter)
if(isset($_REQUEST['ip']) || isset($_REQUEST['domain']))
{
if (isset($_REQUEST['ip']) || isset($_REQUEST['domain'])) {
$existingEntries = getCustomDNSEntries();
foreach ($existingEntries as $entry)
if ($entry->domain == $domain && get_ip_type($entry->ip) == $ipType)
return returnError("This domain already has a custom DNS entry for an IPv" . $ipType, $json);
foreach ($existingEntries as $entry) {
if ($entry->domain == $domain && get_ip_type($entry->ip) == $ipType) {
return returnError('This domain already has a custom DNS entry for an IPv'.$ipType, $json);
}
}
}
// Add record
pihole_execute("-a addcustomdns ".$ip." ".$domain." ".$reload);
pihole_execute('-a addcustomdns '.$ip.' '.$domain.' '.$reload);
return returnSuccess("", $json);
}
catch (\Exception $ex)
{
return returnSuccess('', $json);
} catch (\Exception $ex) {
return returnError($ex->getMessage(), $json);
}
}
function deleteCustomDNSEntry()
{
try
{
$ip = !empty($_REQUEST['ip']) ? $_REQUEST['ip']: "";
$domain = !empty($_REQUEST['domain']) ? $_REQUEST['domain']: "";
try {
$ip = !empty($_REQUEST['ip']) ? $_REQUEST['ip'] : '';
$domain = !empty($_REQUEST['domain']) ? $_REQUEST['domain'] : '';
if (empty($ip))
return returnError("IP must be set");
if (empty($ip)) {
return returnError('IP must be set');
}
if (empty($domain))
return returnError("Domain must be set");
if (empty($domain)) {
return returnError('Domain must be set');
}
$existingEntries = getCustomDNSEntries();
$found = false;
foreach ($existingEntries as $entry)
if ($entry->domain == $domain)
foreach ($existingEntries as $entry) {
if ($entry->domain == $domain) {
if ($entry->ip == $ip) {
$found = true;
break;
}
}
}
if (!$found)
return returnError("This domain/ip association does not exist");
if (!$found) {
return returnError('This domain/ip association does not exist');
}
pihole_execute("-a removecustomdns ".$ip." ".$domain);
pihole_execute('-a removecustomdns '.$ip.' '.$domain);
return returnSuccess();
}
catch (\Exception $ex)
{
} catch (\Exception $ex) {
return returnError($ex->getMessage());
}
}
function deleteAllCustomDNSEntries($reload="")
function deleteAllCustomDNSEntries($reload = '')
{
try
{
if(isset($_REQUEST['reload']))
try {
if (isset($_REQUEST['reload'])) {
$reload = $_REQUEST['reload'];
}
$existingEntries = getCustomDNSEntries();
// passing false to pihole_execute stops pihole from reloading after each entry has been deleted
foreach ($existingEntries as $entry) {
pihole_execute("-a removecustomdns ".$entry->ip." ".$entry->domain." ".$reload);
pihole_execute('-a removecustomdns '.$entry->ip.' '.$entry->domain.' '.$reload);
}
}
catch (\Exception $ex)
{
} catch (\Exception $ex) {
return returnError($ex->getMessage());
}
@@ -301,43 +318,46 @@ function deleteAllCustomDNSEntries($reload="")
}
// CNAME
$customCNAMEFile = "/etc/dnsmasq.d/05-pihole-custom-cname.conf";
$customCNAMEFile = '/etc/dnsmasq.d/05-pihole-custom-cname.conf';
function echoCustomCNAMEEntries()
{
$entries = getCustomCNAMEEntries();
$data = [];
foreach ($entries as $entry)
$data[] = [ $entry->domain, $entry->target ];
$data = array();
foreach ($entries as $entry) {
$data[] = array($entry->domain, $entry->target);
}
return [ "data" => $data ];
return array('data' => $data);
}
function getCustomCNAMEEntries()
{
global $customCNAMEFile;
$entries = [];
$entries = array();
if (!file_exists($customCNAMEFile)) return $entries;
if (!file_exists($customCNAMEFile)) {
return $entries;
}
$handle = fopen($customCNAMEFile, "r");
if ($handle)
{
$handle = fopen($customCNAMEFile, 'r');
if ($handle) {
while (($line = fgets($handle)) !== false) {
$line = str_replace("cname=","", $line);
$line = str_replace("\r","", $line);
$line = str_replace("\n","", $line);
$explodedLine = explode (",", $line);
$line = str_replace('cname=', '', $line);
$line = str_replace("\r", '', $line);
$line = str_replace("\n", '', $line);
$explodedLine = explode(',', $line);
if (count($explodedLine) <= 1)
if (count($explodedLine) <= 1) {
continue;
}
$data = new \stdClass();
$data->domains = array_slice($explodedLine, 0, -1);
$data->domain = implode(",", $data->domains);
$data->target = $explodedLine[count($explodedLine)-1];
$data->domain = implode(',', $data->domains);
$data->target = $explodedLine[count($explodedLine) - 1];
$entries[] = $data;
}
@@ -347,153 +367,163 @@ function getCustomCNAMEEntries()
return $entries;
}
function addCustomCNAMEEntry($domain="", $target="", $reload="", $json=true)
function addCustomCNAMEEntry($domain = '', $target = '', $reload = '', $json = true)
{
try
{
if(isset($_REQUEST['domain']))
try {
if (isset($_REQUEST['domain'])) {
$domain = $_REQUEST['domain'];
}
if(isset($_REQUEST['target']))
if (isset($_REQUEST['target'])) {
$target = trim($_REQUEST['target']);
}
if(isset($_REQUEST['reload']))
if (isset($_REQUEST['reload'])) {
$reload = $_REQUEST['reload'];
}
if (empty($domain))
return returnError("Domain must be set", $json);
if (empty($domain)) {
return returnError('Domain must be set', $json);
}
if (empty($target))
return returnError("Target must be set", $json);
if (empty($target)) {
return returnError('Target must be set', $json);
}
if (!validDomain($target))
return returnError("Target must be valid", $json);
if (!validDomain($target)) {
return returnError('Target must be valid', $json);
}
// Check if each submitted domain is valid
$domains = array_map('trim', explode(",", $domain));
$domains = array_map('trim', explode(',', $domain));
foreach ($domains as $d) {
if (!validDomain($d))
return returnError("Domain '$d' is not valid", $json);
if (!validDomain($d)) {
return returnError("Domain '{$d}' is not valid", $json);
}
}
$existingEntries = getCustomCNAMEEntries();
// Check if a record for one of the domains already exists
foreach ($existingEntries as $entry)
foreach ($domains as $d)
if (in_array($d, $entry->domains))
return returnError("There is already a CNAME record for '$d'", $json);
foreach ($existingEntries as $entry) {
foreach ($domains as $d) {
if (in_array($d, $entry->domains)) {
return returnError("There is already a CNAME record for '{$d}'", $json);
}
}
}
pihole_execute("-a addcustomcname ".$domain." ".$target." ".$reload);
pihole_execute('-a addcustomcname '.$domain.' '.$target.' '.$reload);
return returnSuccess("", $json);
}
catch (\Exception $ex)
{
return returnSuccess('', $json);
} catch (\Exception $ex) {
return returnError($ex->getMessage(), $json);
}
}
function deleteCustomCNAMEEntry()
{
try
{
$target = !empty($_REQUEST['target']) ? $_REQUEST['target']: "";
$domain = !empty($_REQUEST['domain']) ? $_REQUEST['domain']: "";
try {
$target = !empty($_REQUEST['target']) ? $_REQUEST['target'] : '';
$domain = !empty($_REQUEST['domain']) ? $_REQUEST['domain'] : '';
if (empty($target))
return returnError("Target must be set");
if (empty($target)) {
return returnError('Target must be set');
}
if (empty($domain))
return returnError("Domain must be set");
if (empty($domain)) {
return returnError('Domain must be set');
}
$existingEntries = getCustomCNAMEEntries();
$found = false;
foreach ($existingEntries as $entry)
if ($entry->domain == $domain)
foreach ($existingEntries as $entry) {
if ($entry->domain == $domain) {
if ($entry->target == $target) {
$found = true;
break;
}
}
}
if (!$found)
return returnError("This domain/ip association does not exist");
if (!$found) {
return returnError('This domain/ip association does not exist');
}
pihole_execute("-a removecustomcname ".$domain." ".$target);
pihole_execute('-a removecustomcname '.$domain.' '.$target);
return returnSuccess();
}
catch (\Exception $ex)
{
} catch (\Exception $ex) {
return returnError($ex->getMessage());
}
}
function deleteAllCustomCNAMEEntries($reload="")
function deleteAllCustomCNAMEEntries($reload = '')
{
try
{
if(isset($_REQUEST['reload']))
try {
if (isset($_REQUEST['reload'])) {
$reload = $_REQUEST['reload'];
}
$existingEntries = getCustomCNAMEEntries();
// passing false to pihole_execute stops pihole from reloading after each entry has been deleted
foreach ($existingEntries as $entry) {
pihole_execute("-a removecustomcname ".$entry->domain." ".$entry->target." ".$reload);
pihole_execute('-a removecustomcname '.$entry->domain.' '.$entry->target.' '.$reload);
}
}
catch (\Exception $ex)
{
} catch (\Exception $ex) {
return returnError($ex->getMessage());
}
return returnSuccess();
}
function returnSuccess($message = "", $json = true)
function returnSuccess($message = '', $json = true)
{
if ($json) {
return [ "success" => true, "message" => $message ];
} else {
echo $message."<br>";
return true;
return array('success' => true, 'message' => $message);
}
echo $message.'<br>';
return true;
}
function returnError($message = "", $json = true)
function returnError($message = '', $json = true)
{
$message = htmlentities($message) ;
$message = htmlentities($message);
if ($json) {
return [ "success" => false, "message" => $message ];
} else {
echo $message."<br>";
return false;
return array('success' => false, 'message' => $message);
}
echo $message.'<br>';
return false;
}
function getQueryTypeStr($querytype)
{
$qtypes = ["A", "AAAA", "ANY", "SRV", "SOA", "PTR", "TXT", "NAPTR", "MX", "DS", "RRSIG", "DNSKEY", "NS", "OTHER", "SVCB", "HTTPS"];
$qtypes = array('A', 'AAAA', 'ANY', 'SRV', 'SOA', 'PTR', 'TXT', 'NAPTR', 'MX', 'DS', 'RRSIG', 'DNSKEY', 'NS', 'OTHER', 'SVCB', 'HTTPS');
$qtype = intval($querytype);
if($qtype > 0 && $qtype <= count($qtypes))
return $qtypes[$qtype-1];
else
return "TYPE".($qtype - 100);
if ($qtype > 0 && $qtype <= count($qtypes)) {
return $qtypes[$qtype - 1];
}
return 'TYPE'.($qtype - 100);
}
// Functions to return Alert messages (success, error, warning) in JSON format.
// Used in multiple pages.
// Return Success message in JSON format
function JSON_success($message = null) {
function JSON_success($message = null)
{
header('Content-type: application/json');
echo json_encode(array('success' => true, 'message' => $message));
}
// Return Error message in JSON format
function JSON_error($message = null) {
function JSON_error($message = null)
{
header('Content-type: application/json');
$response = array('success' => false, 'message' => $message);
if (isset($_POST['action'])) {
@@ -505,7 +535,8 @@ function JSON_error($message = null) {
// Return Warning message in JSON format.
// - sends "success", because it wasn't a failure.
// - sends "warning" to use the correct alert type.
function JSON_warning($message = null) {
function JSON_warning($message = null)
{
header('Content-type: application/json');
echo json_encode(array(
'success' => true,
@@ -515,17 +546,18 @@ function JSON_warning($message = null) {
}
// Returns an integer representing pihole blocking status
function piholeStatus() {
function piholeStatus()
{
// Retrieve DNS Port calling FTL API directly
$port = callFTLAPI("dns-port");
$port = callFTLAPI('dns-port');
// Retrieve FTL status
$FTLstats = callFTLAPI("stats");
$FTLstats = callFTLAPI('stats');
if (array_key_exists("FTLnotrunning", $port) || array_key_exists("FTLnotrunning", $FTLstats)){
if (array_key_exists('FTLnotrunning', $port) || array_key_exists('FTLnotrunning', $FTLstats)) {
// FTL is not running
$ret = -1;
} elseif (in_array("status enabled", $FTLstats)) {
} elseif (in_array('status enabled', $FTLstats)) {
// FTL is enabled
if (intval($port[0]) <= 0) {
// Port=0; FTL is not listening
@@ -534,7 +566,7 @@ function piholeStatus() {
// FTL is running on this port
$ret = intval($port[0]);
}
} elseif (in_array("status disabled", $FTLstats)) {
} elseif (in_array('status disabled', $FTLstats)) {
// FTL is disabled
$ret = 0;
} else {
@@ -545,51 +577,53 @@ function piholeStatus() {
return $ret;
}
//Returns the default gateway address and interface
function getGateway() {
$gateway= callFTLAPI("gateway");
if (array_key_exists("FTLnotrunning", $gateway)) {
$ret = array("ip" => -1);
// Returns the default gateway address and interface
function getGateway()
{
$gateway = callFTLAPI('gateway');
if (array_key_exists('FTLnotrunning', $gateway)) {
$ret = array('ip' => -1);
} else {
$ret = array_combine(["ip", "iface"], explode(" ", $gateway[0]));
$ret = array_combine(array('ip', 'iface'), explode(' ', $gateway[0]));
}
return $ret;
}
// Try to convert possible IDNA domain to Unicode
function convertIDNAToUnicode($unicode) {
if (extension_loaded("intl")) {
function convertIDNAToUnicode($unicode)
{
if (extension_loaded('intl')) {
// we try the UTS #46 standard first
// as this is the new default, see https://sourceforge.net/p/icu/mailman/message/32980778/
// We know that this fails for some Google domains violating the standard
// see https://github.com/pi-hole/AdminLTE/issues/1223
if (defined("INTL_IDNA_VARIANT_UTS46")) {
if (defined('INTL_IDNA_VARIANT_UTS46')) {
// We have to use the option IDNA_NONTRANSITIONAL_TO_ASCII here
// to ensure sparkasse-gießen.de is not converted into
// sparkass-giessen.de but into xn--sparkasse-gieen-2ib.de
// as mandated by the UTS #46 standard
$unicode = idn_to_utf8($unicode, IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46);
} elseif (defined("INTL_IDNA_VARIANT_2003")) {
} elseif (defined('INTL_IDNA_VARIANT_2003')) {
// If conversion failed, try with the (deprecated!) IDNA 2003 variant
// We have to check for its existence as support of this variant is
// scheduled for removal with PHP 8.0
// see https://wiki.php.net/rfc/deprecate-and-remove-intl_idna_variant_2003
$unicode = idn_to_utf8($unicode, IDNA_DEFAULT, INTL_IDNA_VARIANT_2003);
}
}
return $unicode;
}
//Convert a given (unicode) domain to IDNA ASCII
function convertUnicodeToIDNA($IDNA) {
if (extension_loaded("intl")) {
// Convert a given (unicode) domain to IDNA ASCII
function convertUnicodeToIDNA($IDNA)
{
if (extension_loaded('intl')) {
// Be prepared that this may fail and see our comments about convertIDNAToUnicode()
if (defined("INTL_IDNA_VARIANT_UTS46")) {
if (defined('INTL_IDNA_VARIANT_UTS46')) {
$IDNA = idn_to_ascii($IDNA, IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46);
} elseif (defined("INTL_IDNA_VARIANT_2003")) {
} elseif (defined('INTL_IDNA_VARIANT_2003')) {
$IDNA = idn_to_ascii($IDNA, IDNA_DEFAULT, INTL_IDNA_VARIANT_2003);
}
}
@@ -598,26 +632,30 @@ function convertUnicodeToIDNA($IDNA) {
}
// Return PID of FTL (used in settings.php)
function pidofFTL() {
return shell_exec("pidof pihole-FTL");
function pidofFTL()
{
return shell_exec('pidof pihole-FTL');
}
// Get FTL process information (used in settings.php)
function get_FTL_data($FTLpid, $arg) {
return trim(exec("ps -p " . $FTLpid . " -o " . $arg));
function get_FTL_data($FTLpid, $arg)
{
return trim(exec('ps -p '.$FTLpid.' -o '.$arg));
}
// Convert seconds into readable time (used in settings.php)
function convertseconds($argument) {
function convertseconds($argument)
{
$seconds = round($argument);
if ($seconds < 60) {
return sprintf('%ds', $seconds);
} elseif ($seconds < 3600) {
return sprintf('%dm %ds', ($seconds / 60), ($seconds % 60));
} elseif ($seconds < 86400) {
return sprintf('%dh %dm %ds', ($seconds / 3600 % 24), ($seconds / 60 % 60), ($seconds % 60));
} else {
return sprintf('%dd %dh %dm %ds', ($seconds / 86400), ($seconds / 3600 % 24), ($seconds / 60 % 60), ($seconds % 60));
}
if ($seconds < 3600) {
return sprintf('%dm %ds', $seconds / 60, $seconds % 60);
}
if ($seconds < 86400) {
return sprintf('%dh %dm %ds', $seconds / 3600 % 24, $seconds / 60 % 60, $seconds % 60);
}
return sprintf('%dd %dh %dm %ds', $seconds / 86400, $seconds / 3600 % 24, $seconds / 60 % 60, $seconds % 60);
}
?>

View File

@@ -7,56 +7,48 @@
* Please see LICENSE file for your rights under this license.
*/
require_once("scripts/pi-hole/php/database.php");
require_once 'scripts/pi-hole/php/database.php';
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)
{
if (false === $date_file_created_unix) {
if ($raw) {
// Array output
return array("file_exists" => false);
}
else
{
// String output
return "Gravity database not available";
return array('file_exists' => false);
}
// 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)
{
$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")),
)
);
'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)
{
if ($gravitydiff->d > 1) {
// String output (more than one day ago)
return $gravitydiff->format("Adlists updated %a days, %H:%I (hh:mm) ago");
return $gravitydiff->format('Adlists updated %a days, %H:%I (hh:mm) ago');
}
elseif($gravitydiff->d == 1)
{
if (1 == $gravitydiff->d) {
// String output (one day ago)
return $gravitydiff->format("Adlists updated one day, %H:%I (hh:mm) ago");
return $gravitydiff->format('Adlists updated one day, %H:%I (hh:mm) ago');
}
// String output (less than one day ago)
return $gravitydiff->format("Adlists updated %H:%I (hh:mm) ago");
return $gravitydiff->format('Adlists updated %H:%I (hh:mm) ago');
}
?>

View File

@@ -7,33 +7,34 @@
* Please see LICENSE file for your rights under this license.
*/
require "password.php";
require 'password.php';
if(!$auth) die("Not authorized");
if (!$auth) {
exit('Not authorized');
}
ob_end_flush();
ini_set("output_buffering", "0");
ini_set('output_buffering', '0');
ob_implicit_flush(true);
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 (false !== $pos && 0 !== $pos) {
$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');
$proc = popen('sudo pihole -g', 'r');
while (!feof($proc)) {
echoEvent(fread($proc, 4096));
}
?>

File diff suppressed because it is too large Load Diff

View File

@@ -7,28 +7,33 @@
* Please see LICENSE file for your rights under this license.
*/
require "scripts/pi-hole/php/auth.php";
require "scripts/pi-hole/php/password.php";
require_once "scripts/pi-hole/php/FTL.php";
require_once "scripts/pi-hole/php/func.php";
require "scripts/pi-hole/php/theme.php";
require 'scripts/pi-hole/php/auth.php';
require 'scripts/pi-hole/php/password.php';
require_once 'scripts/pi-hole/php/FTL.php';
require_once 'scripts/pi-hole/php/func.php';
require 'scripts/pi-hole/php/theme.php';
$scriptname = basename($_SERVER['SCRIPT_FILENAME']);
$hostname = gethostname() ? gethostname() : "";
$hostname = gethostname() ? gethostname() : '';
// Return memory usage to show on status block
function getMemUsage() {
$data = explode("\n", file_get_contents("/proc/meminfo"));
function getMemUsage()
{
$data = explode("\n", file_get_contents('/proc/meminfo'));
$meminfo = array();
if (count($data) > 0) {
foreach ($data as $line) {
$expl = explode(":", $line);
if (count($expl) == 2) {
$expl = explode(':', $line);
if (2 == count($expl)) {
// remove " kB" from the end of the string and make it an integer
$meminfo[$expl[0]] = intval(trim(substr($expl[1],0, -3)));
$meminfo[$expl[0]] = intval(trim(substr($expl[1], 0, -3)));
}
}
$memused = $meminfo["MemTotal"] - $meminfo["MemFree"] - $meminfo["Buffers"] - $meminfo["Cached"];
$memusage = $memused / $meminfo["MemTotal"];
$memused = $meminfo['MemTotal'] - $meminfo['MemFree'] - $meminfo['Buffers'] - $meminfo['Cached'];
$memusage = $memused / $meminfo['MemTotal'];
} else {
$memusage = -1;
}
@@ -38,15 +43,16 @@ function getMemUsage() {
// Try to get temperature value from different places (OS dependent)
// - return an array, containing the temperature and limit.
function getTemperature() {
function getTemperature()
{
global $setupVars;
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"));
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 = "";
$output = '';
}
// Test if we succeeded in getting the temperature
@@ -67,7 +73,6 @@ function getTemperature() {
} else {
$limit = 60;
}
} else {
// Nothing can be colder than -273.15 degree Celsius (= 0 Kelvin)
// This is the minimum temperature possible (AKA absolute zero)
@@ -76,7 +81,7 @@ function getTemperature() {
$limit = null;
}
return [$celsius, $limit];
return array($celsius, $limit);
}
check_cors();
@@ -92,7 +97,7 @@ $token = $_SESSION['token'];
if ($auth) {
// For session timer
$maxlifetime = ini_get("session.gc_maxlifetime");
$maxlifetime = ini_get('session.gc_maxlifetime');
// Generate CSRF token
if (empty($_SESSION['token'])) {
@@ -123,17 +128,17 @@ if (!is_numeric($nproc)) {
$memory_usage = getMemUsage();
// Retrieve layout setting from setupVars
if (isset($setupVars['WEBUIBOXEDLAYOUT']) && !($setupVars['WEBUIBOXEDLAYOUT'] === "boxed")) {
if (isset($setupVars['WEBUIBOXEDLAYOUT']) && !('boxed' === $setupVars['WEBUIBOXEDLAYOUT'])) {
$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"])) {
if (isset($_POST['field'])) {
if ('webUI' === $_POST['field'] && isset($_POST['boxedlayout'])) {
$boxedlayout = true;
} elseif ($_POST["field"] === "webUI" && !isset($_POST["boxedlayout"])) {
} elseif ('webUI' === $_POST['field'] && !isset($_POST['boxedlayout'])) {
$boxedlayout = false;
}
}
@@ -157,7 +162,7 @@ $piholeFTLConf = piholeFTLConfig();
<meta http-equiv="cache-control" content="max-age=60,private">
<!-- Tell the browser to be responsive to screen width -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Pi-hole<?php echo $hostname ? " - " . $hostname : "" ?></title>
<title>Pi-hole<?php echo $hostname ? ' - '.$hostname : ''; ?></title>
<link rel="apple-touch-icon" href="img/favicons/apple-touch-icon.png" sizes="180x180">
<link rel="icon" href="img/favicons/favicon-32x32.png" sizes="32x32" type="image/png">
@@ -167,16 +172,16 @@ $piholeFTLConf = piholeFTLConfig();
<link rel="shortcut icon" href="img/favicons/favicon.ico">
<meta name="msapplication-TileColor" content="#367fa9">
<meta name="msapplication-TileImage" content="img/favicons/mstile-150x150.png">
<?php if ($theme == "default-light") { ?>
<?php if ('default-light' == $theme) { ?>
<meta name="theme-color" content="#367fa9">
<?php } elseif ($theme == "default-dark") { ?>
<?php } elseif ('default-dark' == $theme) { ?>
<meta name="theme-color" content="#272c30">
<?php } elseif ($theme == "default-darker") { ?>
<?php } elseif ('default-darker' == $theme) { ?>
<meta name="theme-color" content="#2e6786">
<?php } elseif ($theme == "lcars") { ?>
<?php } elseif ('lcars' == $theme) { ?>
<meta name="theme-color" content="#4488FF">
<link rel="stylesheet" href="style/vendor/fonts/ubuntu-mono/ubuntu-mono.css?v=<?=$cacheVer?>">
<link rel="stylesheet" href="style/vendor/fonts/antonio/antonio.css?v=<?=$cacheVer?>">
<link rel="stylesheet" href="style/vendor/fonts/ubuntu-mono/ubuntu-mono.css?v=<?php echo $cacheVer; ?>">
<link rel="stylesheet" href="style/vendor/fonts/antonio/antonio.css?v=<?php echo $cacheVer; ?>">
<?php } ?>
<?php if ($darkmode) { ?>
@@ -184,37 +189,37 @@ $piholeFTLConf = piholeFTLConfig();
html { background-color: #000; }
</style>
<?php } ?>
<link rel="stylesheet" href="style/vendor/SourceSansPro/SourceSansPro.css?v=<?=$cacheVer?>">
<link rel="stylesheet" href="style/vendor/bootstrap/css/bootstrap.min.css?v=<?=$cacheVer?>">
<link rel="stylesheet" href="style/vendor/datatables.min.css?v=<?=$cacheVer?>">
<link rel="stylesheet" href="style/vendor/datatables_extensions.min.css?v=<?=$cacheVer?>">
<link rel="stylesheet" href="style/vendor/daterangepicker.min.css?v=<?=$cacheVer?>">
<link rel="stylesheet" href="style/vendor/AdminLTE.min.css?v=<?=$cacheVer?>">
<link rel="stylesheet" href="style/vendor/select2.min.css?v=<?=$cacheVer?>">
<link rel="stylesheet" href="style/vendor/SourceSansPro/SourceSansPro.css?v=<?php echo $cacheVer; ?>">
<link rel="stylesheet" href="style/vendor/bootstrap/css/bootstrap.min.css?v=<?php echo $cacheVer; ?>">
<link rel="stylesheet" href="style/vendor/datatables.min.css?v=<?php echo $cacheVer; ?>">
<link rel="stylesheet" href="style/vendor/datatables_extensions.min.css?v=<?php echo $cacheVer; ?>">
<link rel="stylesheet" href="style/vendor/daterangepicker.min.css?v=<?php echo $cacheVer; ?>">
<link rel="stylesheet" href="style/vendor/AdminLTE.min.css?v=<?php echo $cacheVer; ?>">
<link rel="stylesheet" href="style/vendor/select2.min.css?v=<?php echo $cacheVer; ?>">
<?php if (in_array($scriptname, array("groups.php", "groups-adlists.php", "groups-clients.php", "groups-domains.php"))){ ?>
<link rel="stylesheet" href="style/vendor/animate.min.css?v=<?=$cacheVer?>">
<link rel="stylesheet" href="style/vendor/bootstrap-select.min.css?v=<?=$cacheVer?>">
<link rel="stylesheet" href="style/vendor/bootstrap-toggle.min.css?v=<?=$cacheVer?>">
<?php if (in_array($scriptname, array('groups.php', 'groups-adlists.php', 'groups-clients.php', 'groups-domains.php'))) { ?>
<link rel="stylesheet" href="style/vendor/animate.min.css?v=<?php echo $cacheVer; ?>">
<link rel="stylesheet" href="style/vendor/bootstrap-select.min.css?v=<?php echo $cacheVer; ?>">
<link rel="stylesheet" href="style/vendor/bootstrap-toggle.min.css?v=<?php echo $cacheVer; ?>">
<?php } ?>
<link rel="stylesheet" href="style/pi-hole.css?v=<?=$cacheVer?>">
<link rel="stylesheet" href="style/themes/<?php echo $theme; ?>.css?v=<?=$cacheVer?>">
<noscript><link rel="stylesheet" href="style/vendor/js-warn.css?v=<?=$cacheVer?>"></noscript>
<link rel="stylesheet" href="style/pi-hole.css?v=<?php echo $cacheVer; ?>">
<link rel="stylesheet" href="style/themes/<?php echo $theme; ?>.css?v=<?php echo $cacheVer; ?>">
<noscript><link rel="stylesheet" href="style/vendor/js-warn.css?v=<?php echo $cacheVer; ?>"></noscript>
<script src="scripts/vendor/jquery.min.js?v=<?=$cacheVer?>"></script>
<script src="style/vendor/bootstrap/js/bootstrap.min.js?v=<?=$cacheVer?>"></script>
<script src="scripts/vendor/adminlte.min.js?v=<?=$cacheVer?>"></script>
<script src="scripts/vendor/bootstrap-notify.min.js?v=<?=$cacheVer?>"></script>
<script src="scripts/vendor/select2.min.js?v=<?=$cacheVer?>"></script>
<script src="scripts/vendor/datatables.min.js?v=<?=$cacheVer?>"></script>
<script src="scripts/vendor/datatables.select.min.js?v=<?=$cacheVer?>"></script>
<script src="scripts/vendor/datatables.buttons.min.js?v=<?=$cacheVer?>"></script>
<script src="scripts/vendor/moment.min.js?v=<?=$cacheVer?>"></script>
<script src="scripts/vendor/Chart.min.js?v=<?=$cacheVer?>"></script>
<script src="style/vendor/font-awesome/js/all.min.js?v=<?=$cacheVer?>"></script>
<script src="scripts/pi-hole/js/utils.js?v=<?=$cacheVer?>"></script>
<script src="scripts/vendor/jquery.min.js?v=<?php echo $cacheVer; ?>"></script>
<script src="style/vendor/bootstrap/js/bootstrap.min.js?v=<?php echo $cacheVer; ?>"></script>
<script src="scripts/vendor/adminlte.min.js?v=<?php echo $cacheVer; ?>"></script>
<script src="scripts/vendor/bootstrap-notify.min.js?v=<?php echo $cacheVer; ?>"></script>
<script src="scripts/vendor/select2.min.js?v=<?php echo $cacheVer; ?>"></script>
<script src="scripts/vendor/datatables.min.js?v=<?php echo $cacheVer; ?>"></script>
<script src="scripts/vendor/datatables.select.min.js?v=<?php echo $cacheVer; ?>"></script>
<script src="scripts/vendor/datatables.buttons.min.js?v=<?php echo $cacheVer; ?>"></script>
<script src="scripts/vendor/moment.min.js?v=<?php echo $cacheVer; ?>"></script>
<script src="scripts/vendor/Chart.min.js?v=<?php echo $cacheVer; ?>"></script>
<script src="style/vendor/font-awesome/js/all.min.js?v=<?php echo $cacheVer; ?>"></script>
<script src="scripts/pi-hole/js/utils.js?v=<?php echo $cacheVer; ?>"></script>
</head>
<body class="hold-transition sidebar-mini<?php if($boxedlayout){ ?> layout-boxed<?php } ?><?php if($auth){ ?> logged-in<?php } ?>">
<body class="hold-transition sidebar-mini<?php if ($boxedlayout) { ?> layout-boxed<?php } ?><?php if ($auth) { ?> logged-in<?php } ?>">
<noscript>
<!-- JS Warning -->
<div>
@@ -226,13 +231,15 @@ $piholeFTLConf = piholeFTLConfig();
<!-- /JS Warning -->
</noscript>
<?php
if($auth) {
echo "<div id=\"token\" hidden>$token</div>";
if ($auth) {
echo "<div id=\"token\" hidden>{$token}</div>";
}
?>
<!-- Send token to JS -->
<div id="enableTimer" hidden><?php if(file_exists("../custom_disable_timer")){ echo file_get_contents("../custom_disable_timer"); } ?></div>
<div id="enableTimer" hidden><?php if (file_exists('../custom_disable_timer')) {
echo file_get_contents('../custom_disable_timer');
} ?></div>
<div class="wrapper">
<header class="main-header">
<!-- Logo -->
@@ -252,7 +259,7 @@ if($auth) {
</a>
<div class="navbar-custom-menu">
<ul class="nav navbar-nav">
<li<?php echo !$hostname ? ' class="hidden"' : "" ?>>
<li<?php echo !$hostname ? ' class="hidden"' : ''; ?>>
<p class="navbar-text">
<span class="hidden-xs hidden-sm">hostname:</span>
<code><?php echo $hostname; ?></code>
@@ -285,7 +292,13 @@ if($auth) {
<a class="btn-link" href="https://github.com/pi-hole/pi-hole/releases" rel="noopener" target="_blank">Updates</a>
</div>
<div id="sessiontimer" class="col-xs-12 text-center">
<strong>Session is valid for <span id="sessiontimercounter"><?php if($auth && strlen($pwhash) > 0){echo $maxlifetime;}else{echo "0";} ?></span></strong>
<strong>Session is valid for <span id="sessiontimercounter">
<?php if ($auth && strlen($pwhash) > 0) {
echo $maxlifetime;
} else {
echo '0';
} ?>
</span></strong>
</div>
</div>
</li>
@@ -304,9 +317,7 @@ if($auth) {
</div>
</nav>
</header>
<?php
require "scripts/pi-hole/php/sidebar.php";
?>
<?php require 'scripts/pi-hole/php/sidebar.php'; ?>
<!-- Content Wrapper. Contains page content -->
<div class="content-wrapper">
<!-- Main content -->
@@ -322,7 +333,8 @@ require "scripts/pi-hole/php/sidebar.php";
// 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";
exit();
require 'scripts/pi-hole/php/loginpage.php';
exit;
}
?>

View File

@@ -73,5 +73,5 @@
</div>
</div>
<?php
require "scripts/pi-hole/php/footer.php";
require 'scripts/pi-hole/php/footer.php';
?>

View File

@@ -7,9 +7,11 @@
* Please see LICENSE file for your rights under this license.
*/
require_once('auth.php');
require_once('func.php');
require_once('database.php');
require_once 'auth.php';
require_once 'func.php';
require_once 'database.php';
// Authentication checks
if (!isset($api)) {
@@ -27,22 +29,26 @@ $QueriesDB = getQueriesDBFilename();
$db = SQLite3_connect($QueriesDB, SQLITE3_OPEN_READWRITE);
// Delete message identified by IDs
if ($_POST['action'] == 'delete_message' && isset($_POST['id'])) {
if ('delete_message' == $_POST['action'] && isset($_POST['id'])) {
try {
$ids = json_decode($_POST['id']);
if(!is_array($ids))
if (!is_array($ids)) {
throw new Exception('Invalid payload: id is not an array');
// Exploit prevention: Ensure all entries in the ID array are integers
foreach($ids as $value) {
if (!is_numeric($value))
throw new Exception('Invalid payload: id contains non-numeric entries');
}
$stmt = $db->prepare('DELETE FROM message WHERE id IN ('.implode(",",$ids).')');
if (!$stmt)
throw new Exception('While preparing message statement: ' . $db->lastErrorMsg());
// Exploit prevention: Ensure all entries in the ID array are integers
foreach ($ids as $value) {
if (!is_numeric($value)) {
throw new Exception('Invalid payload: id contains non-numeric entries');
}
}
$stmt = $db->prepare('DELETE FROM message WHERE id IN ('.implode(',', $ids).')');
if (!$stmt) {
throw new Exception('While preparing message statement: '.$db->lastErrorMsg());
}
if (!$stmt->execute())
throw new Exception('While executing message statement: ' . $db->lastErrorMsg());
if (!$stmt->execute()) {
throw new Exception('While executing message statement: '.$db->lastErrorMsg());
}
$reload = true;
JSON_success();

View File

@@ -7,9 +7,11 @@
* Please see LICENSE file for your rights under this license.
*/
require_once('auth.php');
require_once('func.php');
require_once('database.php');
require_once 'auth.php';
require_once 'func.php';
require_once 'database.php';
// Authentication checks
if (!isset($api)) {
@@ -26,34 +28,33 @@ $reload = false;
$QueriesDB = getQueriesDBFilename();
$db = SQLite3_connect($QueriesDB, SQLITE3_OPEN_READWRITE);
if ($_POST['action'] == 'delete_network_entry' && isset($_POST['id'])) {
// Delete netwwork and network_addresses table entry identified by ID
if ('delete_network_entry' == $_POST['action'] && isset($_POST['id'])) {
// Delete netwwork and network_addresses table entry identified by ID
try {
$stmt = $db->prepare('DELETE FROM network_addresses WHERE network_id=:id');
if (!$stmt) {
throw new Exception('While preparing message statement: ' . $db->lastErrorMsg());
throw new Exception('While preparing message statement: '.$db->lastErrorMsg());
}
if (!$stmt->bindValue(':id', intval($_POST['id']), SQLITE3_INTEGER)) {
throw new Exception('While binding id to message statement: ' . $db->lastErrorMsg());
throw new Exception('While binding id to message statement: '.$db->lastErrorMsg());
}
if (!$stmt->execute()) {
throw new Exception('While executing message statement: ' . $db->lastErrorMsg());
throw new Exception('While executing message statement: '.$db->lastErrorMsg());
}
$stmt = $db->prepare('DELETE FROM network WHERE id=:id');
if (!$stmt) {
throw new Exception('While preparing message statement: ' . $db->lastErrorMsg());
throw new Exception('While preparing message statement: '.$db->lastErrorMsg());
}
if (!$stmt->bindValue(':id', intval($_POST['id']), SQLITE3_INTEGER)) {
throw new Exception('While binding id to message statement: ' . $db->lastErrorMsg());
throw new Exception('While binding id to message statement: '.$db->lastErrorMsg());
}
if (!$stmt->execute()) {
throw new Exception('While executing message statement: ' . $db->lastErrorMsg());
throw new Exception('While executing message statement: '.$db->lastErrorMsg());
}
$reload = true;

View File

@@ -7,7 +7,7 @@
* Please see LICENSE file for your rights under this license.
*/
require_once('func.php');
require_once 'func.php';
// Start a new PHP session (or continue an existing one)
// Prevents javascript XSS attacks aimed to steal the session ID
@@ -17,56 +17,46 @@ ini_set('session.use_only_cookies', 1);
session_start();
// Read setupVars.conf file
$setupVars = parse_ini_file("/etc/pihole/setupVars.conf");
$setupVars = parse_ini_file('/etc/pihole/setupVars.conf');
// Try to read password hash from setupVars.conf
if(isset($setupVars['WEBPASSWORD']))
{
if (isset($setupVars['WEBPASSWORD'])) {
$pwhash = $setupVars['WEBPASSWORD'];
}
else
{
$pwhash = "";
} 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"]))
{
if (isset($_GET['logout'])) {
session_unset();
setcookie('persistentlogin', '', 1);
header('Location: index.php');
exit();
exit;
}
$wrongpassword = false;
$auth = false;
// Test if password is set
if(strlen($pwhash) > 0)
{
if (strlen($pwhash) > 0) {
// Check for and authorize from persistent cookie
if (isset($_COOKIE["persistentlogin"]))
{
if (hash_equals($pwhash, $_COOKIE["persistentlogin"]))
{
if (isset($_COOKIE['persistentlogin'])) {
if (hash_equals($pwhash, $_COOKIE['persistentlogin'])) {
$auth = true;
// Refresh cookie with new expiry
// setcookie( $name, $value, $expire, $path, $domain, $secure, $httponly )
setcookie('persistentlogin', $pwhash, time()+60*60*24*7, null, null, null, true );
}
else
{
setcookie('persistentlogin', $pwhash, time() + 60 * 60 * 24 * 7, null, null, null, true);
} else {
// Invalid cookie
$auth = false;
setcookie('persistentlogin', '', 1);
}
}
// 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))
{
elseif (isset($_POST['pw'])) {
$postinput = hash('sha256', hash('sha256', $_POST['pw']));
if (hash_equals($pwhash, $postinput)) {
// Regenerate session ID to prevent session fixation
session_regenerate_id();
@@ -74,49 +64,42 @@ if(strlen($pwhash) > 0)
$_SESSION = array();
// Set hash in new session
$_SESSION["hash"] = $pwhash;
$_SESSION['hash'] = $pwhash;
// Set persistent cookie if selected
if (isset($_POST['persistentlogin']))
{
if (isset($_POST['persistentlogin'])) {
// setcookie( $name, $value, $expire, $path, $domain, $secure, $httponly )
setcookie('persistentlogin', $pwhash, time()+60*60*24*7, null, null, null, true );
setcookie('persistentlogin', $pwhash, time() + 60 * 60 * 24 * 7, null, null, null, true);
}
// Login successful, redirect the user to the homepage to discard the POST request
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $_SERVER['QUERY_STRING'] === 'login') {
if ('POST' === $_SERVER['REQUEST_METHOD'] && 'login' === $_SERVER['QUERY_STRING']) {
header('Location: index.php');
exit();
exit;
}
$auth = true;
}
else
{
} else {
$wrongpassword = true;
}
}
// Compare auth hash with saved hash
else if (isset($_SESSION["hash"]))
{
if(hash_equals($pwhash, $_SESSION["hash"]))
elseif (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"]))
elseif (isset($api, $_GET['auth'])) {
if (hash_equals($pwhash, $_GET['auth'])) {
$auth = true;
}
else
{
}
} else {
// Password or hash wrong
$auth = false;
}
}
else
{
} else {
// No password set
$auth = true;
}
?>

View File

@@ -11,51 +11,46 @@ while (ob_get_level() > 0) {
ob_end_flush();
}
require_once("func.php");
ini_set("output_buffering", "0");
require_once 'func.php';
ini_set('output_buffering', '0');
ob_implicit_flush(true);
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
function echoEvent($datatext)
{
if (!isset($_GET['IE'])) {
echo 'data:'.implode("\ndata:", explode("\n", $datatext))."\n\n";
} else {
echo $datatext;
}
}
// Test if domain is set
if(isset($_GET["domain"]))
{
if (isset($_GET['domain'])) {
// Is this a valid domain?
// Convert domain name to IDNA ASCII form for international domains
$url = convertUnicodeToIDNA($_GET["domain"]);
$url = convertUnicodeToIDNA($_GET['domain']);
if (!validDomain($url)) {
echoEvent(htmlentities($url)." is an invalid domain!");
die();
echoEvent(htmlentities($url).' is an invalid domain!');
exit;
}
}
else
{
echoEvent("No domain provided");
die();
} else {
echoEvent('No domain provided');
exit;
}
if(isset($_GET["exact"]))
{
$exact = "-exact";
}
elseif(isset($_GET["bp"]))
{
$exact = "-bp";
}
else
{
$exact = "";
if (isset($_GET['exact'])) {
$exact = '-exact';
} elseif (isset($_GET['bp'])) {
$exact = '-bp';
} 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));
}
?>

File diff suppressed because it is too large Load Diff

View File

@@ -11,13 +11,13 @@
<p>Status</p>
<?php
$pistatus = piholeStatus();
if ($pistatus == 53) {
if (53 == $pistatus) {
echo '<span id="status"><i class="fa fa-w fa-circle text-green-light"></i> Active</span>';
} elseif ($pistatus == 0) {
} elseif (0 == $pistatus) {
echo '<span id="status"><i class="fa fa-w fa-circle text-red"></i> Blocking disabled</span>';
} elseif ($pistatus == -1) {
} elseif (-1 == $pistatus) {
echo '<span id="status"><i class="fa fa-w fa-circle text-red"></i> DNS service not running</span>';
} elseif ($pistatus == -2) {
} elseif (-2 == $pistatus) {
echo '<span id="status"><i class="fa fa-w fa-circle text-red"></i> Unknown</span>';
} else {
echo '<span id="status"><i class="fa fa-w fa-circle text-orange"></i> DNS service on port '.$pistatus.'</span>';
@@ -27,22 +27,22 @@
<?php
echo '<span title="Detected '.$nproc.' cores"><i class="fa fa-w fa-circle ';
if ($loaddata[0] > $nproc) {
echo "text-red";
echo 'text-red';
} else {
echo "text-green-light";
echo 'text-green-light';
}
echo '"></i> Load:&nbsp;&nbsp;' . $loaddata[0] . "&nbsp;&nbsp;" . $loaddata[1] . "&nbsp;&nbsp;". $loaddata[2] . "</span>";
echo '"></i> Load:&nbsp;&nbsp;'.$loaddata[0].'&nbsp;&nbsp;'.$loaddata[1].'&nbsp;&nbsp;'.$loaddata[2].'</span>';
?>
<br/>
<?php
echo '<span><i class="fa fa-w fa-circle ';
if ($memory_usage > 0.75 || $memory_usage < 0.0) {
echo "text-red";
echo 'text-red';
} else {
echo "text-green-light";
echo 'text-green-light';
}
if($memory_usage > 0.0) {
echo '"></i> Memory usage:&nbsp;&nbsp;' . sprintf("%.1f",100.0*$memory_usage) . "&thinsp;%</span>";
if ($memory_usage > 0.0) {
echo '"></i> Memory usage:&nbsp;&nbsp;'.sprintf('%.1f', 100.0 * $memory_usage).'&thinsp;%</span>';
} else {
echo '"></i> Memory usage:&nbsp;&nbsp; N/A</span>';
}
@@ -51,12 +51,12 @@
<?php
if ($celsius >= -273.15) {
// Only show temp info if any data is available -->
$tempcolor = "text-vivid-blue";
$tempcolor = 'text-vivid-blue';
if (isset($temperaturelimit) && $celsius > $temperaturelimit) {
$tempcolor = "text-red";
$tempcolor = 'text-red';
}
echo '<span id="temperature"><i class="fa fa-w fa-fire '.$tempcolor.'" style="width: 1em !important"></i> ';
echo 'Temp:&nbsp;<span id="rawtemp" hidden>' .$celsius. '</span>';
echo 'Temp:&nbsp;<span id="rawtemp" hidden>'.$celsius.'</span>';
echo '<span id="tempdisplay"></span></span>';
}
?>
@@ -64,52 +64,53 @@
</div>
<!-- sidebar menu: : style can be found in sidebar.less -->
<?php
if(!$auth && (!isset($indexpage) || isset($_GET['login'])))
{
$scriptname = "login";
if (!$auth && (!isset($indexpage) || isset($_GET['login']))) {
$scriptname = 'login';
}
?>
?>
<ul class="sidebar-menu" data-widget="tree">
<li class="header text-uppercase">Main</li>
<!-- Home Page -->
<li<?php if($scriptname === "index.php"){ ?> class="active"<?php } ?>>
<li<?php if ('index.php' === $scriptname) { ?> class="active"<?php } ?>>
<a href="index.php">
<i class="fa fa-fw menu-icon fa-home"></i> <span>Dashboard</span>
</a>
</li>
<!-- Logout -->
<?php
// Show Logout button if $auth is set and authorization is required
if(strlen($pwhash) > 0 && $auth) {
?>
// Show Logout button if $auth is set and authorization is required
if (strlen($pwhash) > 0 && $auth) {
?>
<li>
<a href="?logout">
<i class="fa fa-fw menu-icon fa-sign-out-alt"></i> <span>Logout</span>
</a>
</li>
<?php } ?>
<?php
} ?>
<!-- Login -->
<?php
// Show Login button if $auth is *not* set and authorization is required
if(strlen($pwhash) > 0 && !$auth) {
?>
<li<?php if($scriptname === "login"){ ?> class="active"<?php } ?>>
// Show Login button if $auth is *not* set and authorization is required
if (strlen($pwhash) > 0 && !$auth) {
?>
<li<?php if ('login' === $scriptname) { ?> class="active"<?php } ?>>
<a href="index.php?login">
<i class="fa fa-fw menu-icon fa-user"></i> <span>Login</span>
</a>
</li>
<?php } ?>
<?php if($auth){ ?>
<?php
} ?>
<?php if ($auth) { ?>
<li class="header text-uppercase">Analysis</li>
<!-- Query Log -->
<li<?php if($scriptname === "queries.php"){ ?> class="active"<?php } ?>>
<li<?php if ('queries.php' === $scriptname) { ?> class="active"<?php } ?>>
<a href="queries.php">
<i class="fa fa-fw menu-icon fa-file-alt"></i> <span>Query Log</span>
</a>
</li>
<!-- Long-term database -->
<li class="treeview<?php if($scriptname === "db_queries.php" || $scriptname === "db_lists.php" || $scriptname === "db_graph.php"){ ?> active<?php } ?>">
<li class="treeview<?php if ('db_queries.php' === $scriptname || 'db_lists.php' === $scriptname || 'db_graph.php' === $scriptname) { ?> active<?php } ?>">
<a href="#">
<i class="fa fa-fw menu-icon fa-history"></i> <span>Long-term Data</span>
<span class="pull-right-container">
@@ -117,17 +118,17 @@
</span>
</a>
<ul class="treeview-menu">
<li<?php if($scriptname === "db_graph.php"){ ?> class="active"<?php } ?>>
<li<?php if ('db_graph.php' === $scriptname) { ?> class="active"<?php } ?>>
<a href="db_graph.php">
<i class="fa fa-fw menu-icon fa-chart-bar"></i> Graphics
</a>
</li>
<li<?php if($scriptname === "db_queries.php"){ ?> class="active"<?php } ?>>
<li<?php if ('db_queries.php' === $scriptname) { ?> class="active"<?php } ?>>
<a href="db_queries.php">
<i class="fa fa-fw menu-icon fa-file-alt"></i> Query Log
</a>
</li>
<li<?php if($scriptname === "db_lists.php"){ ?> class="active"<?php } ?>>
<li<?php if ('db_lists.php' === $scriptname) { ?> class="active"<?php } ?>>
<a href="db_lists.php">
<i class="fa fa-fw menu-icon fa-list"></i> Top Lists
</a>
@@ -137,22 +138,22 @@
<li class="header text-uppercase">Group Management</li>
<!-- Group Management -->
<li<?php if($scriptname === "groups.php"){ ?> class="active"<?php } ?>>
<li<?php if ('groups.php' === $scriptname) { ?> class="active"<?php } ?>>
<a href="groups.php">
<i class="fa fa-fw menu-icon fa-user-friends"></i> <span>Groups</span>
</a>
</li>
<li<?php if($scriptname === "groups-clients.php"){ ?> class="active"<?php } ?>>
<li<?php if ('groups-clients.php' === $scriptname) { ?> class="active"<?php } ?>>
<a href="groups-clients.php">
<i class="fa fa-fw menu-icon fa-laptop"></i> <span>Clients</span>
</a>
</li>
<li<?php if($scriptname === "groups-domains.php"){ ?> class="active"<?php } ?>>
<li<?php if ('groups-domains.php' === $scriptname) { ?> class="active"<?php } ?>>
<a href="groups-domains.php">
<i class="fa fa-fw menu-icon fa-list"></i> <span>Domains</span>
</a>
</li>
<li<?php if($scriptname === "groups-adlists.php"){ ?> class="active"<?php } ?>>
<li<?php if ('groups-adlists.php' === $scriptname) { ?> class="active"<?php } ?>>
<a href="groups-adlists.php">
<i class="fa fa-fw menu-icon fa-shield-alt"></i> <span>Adlists</span>
</a>
@@ -160,7 +161,7 @@
<li class="header text-uppercase">DNS Control</li>
<!-- Enable/Disable Blocking -->
<li id="pihole-disable" class="treeview"<?php if ($pistatus == "0") { ?> hidden<?php } ?>>
<li id="pihole-disable" class="treeview"<?php if ('0' == $pistatus) { ?> hidden<?php } ?>>
<a href="#">
<i class="fa fa-fw menu-icon fa-stop"></i> <span>Disable Blocking&nbsp;&nbsp;&nbsp;<span id="flip-status-disable"></span></span>
<span class="pull-right-container">
@@ -196,7 +197,7 @@
</ul>
<!-- <a href="#" id="flip-status"><i class="fa fa-stop"></i> <span>Disable</span></a> -->
</li>
<li id="pihole-enable" class="treeview"<?php if (!in_array($pistatus,["0","-1","-2"])) { ?> hidden<?php } ?>>
<li id="pihole-enable" class="treeview"<?php if (!in_array($pistatus, array('0', '-1', '-2'))) { ?> hidden<?php } ?>>
<a href="#">
<i class="fa fa-fw menu-icon fa-play"></i>
<span id="enableLabel">Enable Blocking&nbsp;&nbsp;&nbsp;
@@ -205,7 +206,7 @@
</a>
</li>
<!-- Local DNS Records -->
<li class="treeview <?php if(in_array($scriptname, array("dns_records.php", "cname_records.php"))){ ?>active<?php } ?>">
<li class="treeview <?php if (in_array($scriptname, array('dns_records.php', 'cname_records.php'))) { ?>active<?php } ?>">
<a href="#">
<i class="fa fa-fw menu-icon fa-address-book"></i> <span>Local DNS</span>
<span class="pull-right-container">
@@ -213,12 +214,12 @@
</span>
</a>
<ul class="treeview-menu">
<li<?php if($scriptname === "dns_records.php"){ ?> class="active"<?php } ?>>
<li<?php if ('dns_records.php' === $scriptname) { ?> class="active"<?php } ?>>
<a href="dns_records.php">
<i class="fa fa-fw menu-icon fa-address-book"></i> DNS Records
</a>
</li>
<li<?php if($scriptname === "cname_records.php"){ ?> class="active"<?php } ?>>
<li<?php if ('cname_records.php' === $scriptname) { ?> class="active"<?php } ?>>
<a href="cname_records.php">
<i class="fa fa-fw menu-icon fa-address-book"></i> CNAME Records
</a>
@@ -228,7 +229,7 @@
<li class="header text-uppercase">System</li>
<!-- Tools -->
<li class="treeview<?php if (in_array($scriptname, array("messages.php", "gravity.php", "queryads.php", "auditlog.php", "taillog.php", "taillog-FTL.php", "debug.php", "network.php"))){ ?> active<?php } ?>">
<li class="treeview<?php if (in_array($scriptname, array('messages.php', 'gravity.php', 'queryads.php', 'auditlog.php', 'taillog.php', 'taillog-FTL.php', 'debug.php', 'network.php'))) { ?> active<?php } ?>">
<a href="#">
<i class="fa fa-fw menu-icon fa-tools"></i> <span>Tools</span>
<span class="warning-count hidden"></span>
@@ -238,32 +239,32 @@
</a>
<ul class="treeview-menu">
<!-- Pi-hole diagnosis -->
<li<?php if($scriptname === "messages.php"){ ?> class="active"<?php } ?>>
<li<?php if ('messages.php' === $scriptname) { ?> class="active"<?php } ?>>
<a href="messages.php">
<i class="fa fa-fw menu-icon fa-file-medical-alt"></i> Pi-hole diagnosis
<span class="pull-right-container warning-count hidden"></span>
</a>
</li>
<!-- Run gravity.sh -->
<li<?php if($scriptname === "gravity.php"){ ?> class="active"<?php } ?>>
<li<?php if ('gravity.php' === $scriptname) { ?> class="active"<?php } ?>>
<a href="gravity.php">
<i class="fa fa-fw menu-icon fa-arrow-circle-down"></i> Update Gravity
</a>
</li>
<!-- Query Lists -->
<li<?php if($scriptname === "queryads.php"){ ?> class="active"<?php } ?>>
<li<?php if ('queryads.php' === $scriptname) { ?> class="active"<?php } ?>>
<a href="queryads.php">
<i class="fa fa-fw menu-icon fa-search"></i> Search Adlists
</a>
</li>
<!-- Audit log -->
<li<?php if($scriptname === "auditlog.php"){ ?> class="active"<?php } ?>>
<li<?php if ('auditlog.php' === $scriptname) { ?> class="active"<?php } ?>>
<a href="auditlog.php">
<i class="fa fa-fw menu-icon fa-balance-scale"></i> Audit log
</a>
</li>
<!-- Tail pihole.log -->
<li<?php if($scriptname === "taillog.php"){ ?> class="active"<?php } ?>>
<li<?php if ('taillog.php' === $scriptname) { ?> class="active"<?php } ?>>
<a href="taillog.php">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" preserveAspectRatio="xMidYMid meet" height="14" viewBox="0 0 200 200" class="svg-inline--fa custom-menu-icon fa-w-20 fa-fw menu-icon">
<g>
@@ -282,7 +283,7 @@
</a>
</li>
<!-- Tail FTL.log -->
<li<?php if($scriptname === "taillog-FTL.php"){ ?> class="active"<?php } ?>>
<li<?php if ('taillog-FTL.php' === $scriptname) { ?> class="active"<?php } ?>>
<a href="taillog-FTL.php">
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" preserveAspectRatio="xMidYMid meet" height="14" viewBox="0 0 400 340" class="svg-inline--fa custom-menu-icon fa-w-20 fa-fw menu-icon">
<g fill="currentColor">
@@ -295,13 +296,13 @@
</a>
</li>
<!-- Generate debug log -->
<li<?php if($scriptname === "debug.php"){ ?> class="active"<?php } ?>>
<li<?php if ('debug.php' === $scriptname) { ?> class="active"<?php } ?>>
<a href="debug.php">
<i class="fa fa-fw menu-icon fa-ambulance"></i> Generate debug log
</a>
</li>
<!-- Network -->
<li<?php if($scriptname === "network.php"){ ?> class="active"<?php } ?>>
<li<?php if ('network.php' === $scriptname) { ?> class="active"<?php } ?>>
<a href="network.php">
<i class="fa fa-fw menu-icon fa-network-wired"></i> Network
</a>
@@ -309,7 +310,7 @@
</ul>
</li>
<!-- Settings -->
<li<?php if($scriptname === "settings.php"){ ?> class="active"<?php } ?>>
<li<?php if ('settings.php' === $scriptname) { ?> class="active"<?php } ?>>
<a href="settings.php">
<i class="fa fa-fw menu-icon fa-cog"></i> <span>Settings</span>
</a>

View File

@@ -7,47 +7,51 @@
* Please see LICENSE file for your rights under this license.
*/
require "password.php";
if(!$auth) die("Not authorized");
require 'password.php';
if (!$auth) {
exit('Not authorized');
}
function formatLine($line){
$txt = preg_replace("/ dnsmasq\[[0-9]*\]/", "", htmlspecialchars($line));
function formatLine($line)
{
$txt = preg_replace('/ dnsmasq\\[[0-9]*\\]/', '', htmlspecialchars($line));
if (strpos($line, "blacklisted") || strpos($line, "gravity blocked")) {
if (strpos($line, 'blacklisted') || strpos($line, 'gravity blocked')) {
$txt = '<b class="log-red">'.$txt.'</b>';
} elseif (strpos($line, "query[A") || strpos($line, "query[DHCP")) {
} elseif (strpos($line, 'query[A') || strpos($line, 'query[DHCP')) {
$txt = '<b>'.$txt.'</b>';
} else {
$txt = '<span class="text-muted">'.$txt.'</span>';
}
return $txt;
}
// 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");
if (isset($_GET['FTL'])) {
$file = fopen('/var/log/pihole/FTL.log', 'r');
} else {
$file = fopen("/var/log/pihole/pihole.log","r");
$file = fopen('/var/log/pihole/pihole.log', 'r');
}
if (!$file) {
die(json_encode(array("offset" => 0, "lines" => array("Failed to open log file. Check permissions!\n"))));
exit(json_encode(array('offset' => 0, 'lines' => array("Failed to open log file. Check permissions!\n"))));
}
if (isset($_GET["offset"])) {
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 = [];
$lines = array();
while (!feof($file)) {
array_push($lines, formatLine(fgets($file)));
}
die(json_encode(array("offset" => ftell($file), "lines" => $lines)));
exit(json_encode(array('offset' => ftell($file), 'lines' => $lines)));
}
}
@@ -55,5 +59,4 @@ if (isset($_GET["offset"])) {
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)));
?>
exit(json_encode(array('offset' => ftell($file) + 1)));

View File

@@ -7,56 +7,59 @@
* Please see LICENSE file for your rights under this license.
*/
require "password.php";
require "auth.php"; // Also imports func.php
require "database.php";
require "savesettings.php";
require 'password.php';
if (php_sapi_name() !== "cli") {
if(!$auth) die("Not authorized");
check_csrf(isset($_POST["token"]) ? $_POST["token"] : "");
require 'auth.php'; // Also imports func.php
require 'database.php';
require 'savesettings.php';
if ('cli' !== php_sapi_name()) {
if (!$auth) {
exit('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))
if (file_exists($path.$name)) {
$archive[$subdir.$name] = file_get_contents($path.$name);
}
}
/**
* Add the contents of a table to the archive
* Add the contents of a table to the archive.
*
* @param $name string The name of the file in the archive to save the table to
* @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\";";
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))
if (is_null($results)) {
return;
}
$content = array();
while ($row = $results->fetchArray(SQLITE3_ASSOC))
{
while ($row = $results->fetchArray(SQLITE3_ASSOC)) {
array_push($content, $row);
}
@@ -64,206 +67,201 @@ function archive_add_table($name, $table, $type=-1)
}
/**
* Restore the contents of a table from an uploaded archive
* Restore the contents of a table from an uploaded archive.
*
* @param $file object The file in the archive to restore the table from
* @param $table string The table to import
* @param $flush boolean Whether to flush the table before importing the archived data
* @return integer Number of restored rows
*
* @return int 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))
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))
if (is_null($contents)) {
return 0;
}
// Flush table if requested. Only flush each table once, and only if it exists
if($flush && !in_array($table, $flushed_tables))
{
if ($flush && !in_array($table, $flushed_tables)) {
$tableExists = $db->querySingle("SELECT name FROM sqlite_master WHERE type='table' AND name='".$table."';");
if ($tableExists)
{
$db->exec("DELETE FROM \"".$table."\"");
if ($tableExists) {
$db->exec('DELETE FROM "'.$table.'"');
array_push($flushed_tables, $table);
}
}
// Prepare fields 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);";
}
elseif($table === "domain_audit")
{
$sql = "INSERT OR IGNORE INTO domain_audit";
$sql .= " (id,domain,date_added)";
$sql .= " VALUES (:id,:domain,:date_added);";
}
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);";
}
elseif($table === "group")
{
$sql = "INSERT OR IGNORE INTO \"group\"";
$sql .= " (id,name,date_added,description)";
$sql .= " VALUES (:id,:name,:date_added,:description);";
}
elseif($table === "client")
{
$sql = "INSERT OR IGNORE INTO client";
$sql .= " (id,ip,date_added,comment)";
$sql .= " VALUES (:id,:ip,:date_added,:comment);";
}
elseif($table === "domainlist_by_group")
{
$sql = "INSERT OR IGNORE INTO domainlist_by_group";
$sql .= " (domainlist_id,group_id)";
$sql .= " VALUES (:domainlist_id,:group_id);";
}
elseif($table === "client_by_group")
{
$sql = "INSERT OR IGNORE INTO client_by_group";
$sql .= " (client_id,group_id)";
$sql .= " VALUES (:client_id,:group_id);";
}
elseif($table === "adlist_by_group")
{
$sql = "INSERT OR IGNORE INTO adlist_by_group";
$sql .= " (adlist_id,group_id)";
$sql .= " VALUES (:adlist_id,:group_id);";
}
else
{
if($table === "whitelist")
if ('adlist' === $table) {
$sql = 'INSERT OR IGNORE INTO adlist';
$sql .= ' (id,address,enabled,date_added,comment)';
$sql .= ' VALUES (:id,:address,:enabled,:date_added,:comment);';
} elseif ('domain_audit' === $table) {
$sql = 'INSERT OR IGNORE INTO domain_audit';
$sql .= ' (id,domain,date_added)';
$sql .= ' VALUES (:id,:domain,:date_added);';
} elseif ('domainlist' === $table) {
$sql = 'INSERT OR IGNORE INTO domainlist';
$sql .= ' (id,domain,enabled,date_added,comment,type)';
$sql .= ' VALUES (:id,:domain,:enabled,:date_added,:comment,:type);';
} elseif ('group' === $table) {
$sql = 'INSERT OR IGNORE INTO "group"';
$sql .= ' (id,name,date_added,description)';
$sql .= ' VALUES (:id,:name,:date_added,:description);';
} elseif ('client' === $table) {
$sql = 'INSERT OR IGNORE INTO client';
$sql .= ' (id,ip,date_added,comment)';
$sql .= ' VALUES (:id,:ip,:date_added,:comment);';
} elseif ('domainlist_by_group' === $table) {
$sql = 'INSERT OR IGNORE INTO domainlist_by_group';
$sql .= ' (domainlist_id,group_id)';
$sql .= ' VALUES (:domainlist_id,:group_id);';
} elseif ('client_by_group' === $table) {
$sql = 'INSERT OR IGNORE INTO client_by_group';
$sql .= ' (client_id,group_id)';
$sql .= ' VALUES (:client_id,:group_id);';
} elseif ('adlist_by_group' === $table) {
$sql = 'INSERT OR IGNORE INTO adlist_by_group';
$sql .= ' (adlist_id,group_id)';
$sql .= ' VALUES (:adlist_id,:group_id);';
} else {
if ('whitelist' === $table) {
$type = 0;
elseif($table === "blacklist")
} elseif ('blacklist' === $table) {
$type = 1;
elseif($table === "regex_whitelist")
} elseif ('regex_whitelist' === $table) {
$type = 2;
elseif($table === "regex_blacklist")
} elseif ('regex_blacklist' === $table) {
$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";
$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 statement
$stmt = $db->prepare($sql);
// Return early if we fail to prepare the SQLite statement
if(!$stmt)
{
echo "Failed to prepare statement for ".$table." table.";
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)
{
foreach ($contents as $row) {
// Limit max length for a domain entry to 253 chars
if(isset($field) && strlen($row[$field]) > 253)
if (isset($field) && strlen($row[$field]) > 253) {
continue;
}
// Bind properties from JSON data
// Note that only defined above are actually used
// so even maliciously modified Teleporter files
// cannot be dangerous in any way
foreach($row as $key => $value) {
foreach ($row as $key => $value) {
$type = gettype($value);
$sqltype=NULL;
switch($type) {
case "integer":
$sqltype = null;
switch ($type) {
case 'integer':
$sqltype = SQLITE3_INTEGER;
break;
case "string":
break;
case 'string':
$sqltype = SQLITE3_TEXT;
break;
case "NULL":
break;
case 'NULL':
$sqltype = SQLITE3_NULL;
break;
break;
default:
$sqltype = "UNK";
$sqltype = 'UNK';
}
$stmt->bindValue(":".$key, htmlentities($value), $sqltype);
$stmt->bindValue(':'.$key, htmlentities($value), $sqltype);
}
if($stmt->execute() && $stmt->reset() && $stmt->clear())
$num++;
else
{
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;
}
/**
* Create table rows from an uploaded archive file
* Create table rows from an uploaded archive file.
*
* @param $file object The file in the archive to import
* @param $table string The target table
* @param $flush boolean Whether to flush the table before importing the archived data
* @param $wildcardstyle boolean Whether to format the input domains in legacy wildcard notation
* @return integer Number of processed rows from the imported file
*
* @return int 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;
$domains = array_filter(explode("\n",file_get_contents($file)));
$domains = array_filter(explode("\n", file_get_contents($file)));
// Return early if we cannot extract the lines in the file
if(is_null($domains))
if (is_null($domains)) {
return 0;
}
// Generate comment
$prefix = "phar:///tmp/";
$prefix = 'phar:///tmp/';
if (substr($file, 0, strlen($prefix)) == $prefix) {
$file = substr($file, strlen($prefix));
}
$comment = "Imported from ".$file;
$comment = 'Imported from '.$file;
// Determine table and type to import to
$type = null;
if($table === "whitelist") {
$table = "domainlist";
if ('whitelist' === $table) {
$table = 'domainlist';
$type = ListType::whitelist;
} else if($table === "blacklist") {
$table = "domainlist";
} elseif ('blacklist' === $table) {
$table = 'domainlist';
$type = ListType::blacklist;
} else if($table === "regex_blacklist") {
$table = "domainlist";
} elseif ('regex_blacklist' === $table) {
$table = 'domainlist';
$type = ListType::regex_blacklist;
} else if($table === "domain_audit") {
$table = "domain_audit";
} elseif ('domain_audit' === $table) {
$table = 'domain_audit';
$type = -1; // -1 -> not used inside add_to_table()
} else if($table === "adlist") {
$table = "adlist";
} elseif ('adlist' === $table) {
$table = 'adlist';
$type = -1; // -1 -> not used inside add_to_table()
}
// Flush table if requested
if($flush) {
if ($flush) {
flush_table($table, $type);
}
@@ -272,37 +270,33 @@ function archive_insert_into_table($file, $table, $flush=false, $wildcardstyle=f
}
/**
* Flush table if requested. This subroutine flushes each table only once
* Flush table if requested. This subroutine flushes each table only once.
*
* @param $table string The target table
* @param $type integer Type of item to flush in table (applies only to domainlist table)
*/
function flush_table($table, $type=null)
function flush_table($table, $type = null)
{
global $db, $flushed_tables;
if(!in_array($table, $flushed_tables))
{
if($type !== null) {
$sql = "DELETE FROM \"".$table."\" WHERE type = ".$type;
if (!in_array($table, $flushed_tables)) {
if (null !== $type) {
$sql = 'DELETE FROM "'.$table.'" WHERE type = '.$type;
array_push($flushed_tables, $table.$type);
} else {
$sql = "DELETE FROM \"".$table."\"";
$sql = 'DELETE FROM "'.$table.'"';
array_push($flushed_tables, $table);
}
$db->exec($sql);
}
}
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);
if ($dir = opendir($path)) {
while (false !== ($entry = readdir($dir))) {
if ('.' !== $entry && '..' !== $entry) {
archive_add_file($path, $entry, $subdir);
}
}
closedir($dir);
@@ -318,28 +312,27 @@ function limit_length(&$item, $key)
function process_file($contents)
{
$domains = array_filter(explode("\n",$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");
array_walk($domains, 'limit_length');
return $domains;
}
function noun($num)
{
if($num === 1)
{
return " entry";
if (1 === $num) {
return ' entry';
}
return " entries";
return ' entries';
}
if(isset($_POST["action"]))
{
if($_FILES["zip_file"]["name"] && $_POST["action"] == "in")
{
$filename = $_FILES["zip_file"]["name"];
$source = $_FILES["zip_file"]["tmp_name"];
if (isset($_POST['action'])) {
if ($_FILES['zip_file']['name'] && 'in' == $_POST['action']) {
$filename = $_FILES['zip_file']['name'];
$source = $_FILES['zip_file']['tmp_name'];
$type = mime_content_type($source);
// verify the file mime type
@@ -347,18 +340,17 @@ if(isset($_POST["action"]))
$mime_valid = in_array($type, $accepted_types);
// verify the file extension (Looking for ".tar.gz" at the end of the file name)
$ext = array_slice(explode(".", $filename), -2, 2);
$ext_valid = strtolower($ext[0]) == "tar" && strtolower($ext[1]) == "gz" ? true : false;
$ext = array_slice(explode('.', $filename), -2, 2);
$ext_valid = 'tar' == strtolower($ext[0]) && 'gz' == strtolower($ext[1]) ? true : false;
if(!$ext_valid || !$mime_valid) {
die("The file you are trying to upload is not a .tar.gz file (filename: ".htmlentities($filename).", type: ".htmlentities($type)."). Please try again.");
if (!$ext_valid || !$mime_valid) {
exit('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;
$fullfilename = sys_get_temp_dir().'/'.$filename;
if(!move_uploaded_file($source, $fullfilename))
{
die("Failed moving ".htmlentities($source)." to ".htmlentities($fullfilename));
if (!move_uploaded_file($source, $fullfilename)) {
exit('Failed moving '.htmlentities($source).' to '.htmlentities($fullfilename));
}
$archive = new PharData($fullfilename);
@@ -367,209 +359,191 @@ if(isset($_POST["action"]))
$fullpiholerestart = false;
$reloadsettingspage = false;
$flushtables = isset($_POST["flushtables"]);
$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.noun($num).")<br>\n";
foreach (new RecursiveIteratorIterator($archive) as $file) {
if (isset($_POST['blacklist']) && 'blacklist.txt' === $file->getFilename()) {
$num = archive_insert_into_table($file, 'blacklist', $flushtables);
echo 'Processed blacklist (exact) ('.$num.noun($num).")<br>\n";
$importedsomething = true;
}
if(isset($_POST["whitelist"]) && $file->getFilename() === "whitelist.txt")
{
$num = archive_insert_into_table($file, "whitelist", $flushtables);
echo "Processed whitelist (exact) (".$num.noun($num).")<br>\n";
if (isset($_POST['whitelist']) && 'whitelist.txt' === $file->getFilename()) {
$num = archive_insert_into_table($file, 'whitelist', $flushtables);
echo 'Processed whitelist (exact) ('.$num.noun($num).")<br>\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.noun($num).")<br>\n";
if (isset($_POST['regexlist']) && 'regex.list' === $file->getFilename()) {
$num = archive_insert_into_table($file, 'regex_blacklist', $flushtables);
echo 'Processed blacklist (regex) ('.$num.noun($num).")<br>\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.noun($num).")<br>\n";
if (isset($_POST['regexlist']) && 'wildcardblocking.txt' === $file->getFilename()) {
$num = archive_insert_into_table($file, 'regex_blacklist', $flushtables, true);
echo 'Processed blacklist (regex, wildcard style) ('.$num.noun($num).")<br>\n";
$importedsomething = true;
}
if(isset($_POST["auditlog"]) && $file->getFilename() === "auditlog.list")
{
$num = archive_insert_into_table($file, "domain_audit", $flushtables);
echo "Processed audit log (".$num.noun($num).")<br>\n";
if (isset($_POST['auditlog']) && 'auditlog.list' === $file->getFilename()) {
$num = archive_insert_into_table($file, 'domain_audit', $flushtables);
echo 'Processed audit log ('.$num.noun($num).")<br>\n";
$importedsomething = true;
}
if(isset($_POST["adlist"]) && $file->getFilename() === "adlists.list")
{
$num = archive_insert_into_table($file, "adlist", $flushtables);
echo "Processed adlists (".$num.noun($num).")<br>\n";
if (isset($_POST['adlist']) && 'adlists.list' === $file->getFilename()) {
$num = archive_insert_into_table($file, 'adlist', $flushtables);
echo 'Processed adlists ('.$num.noun($num).")<br>\n";
$importedsomething = true;
}
if(isset($_POST["blacklist"]) && $file->getFilename() === "blacklist.exact.json")
{
$num = archive_restore_table($file, "blacklist", $flushtables);
echo "Processed blacklist (exact) (".$num.noun($num).")<br>\n";
if (isset($_POST['blacklist']) && 'blacklist.exact.json' === $file->getFilename()) {
$num = archive_restore_table($file, 'blacklist', $flushtables);
echo 'Processed blacklist (exact) ('.$num.noun($num).")<br>\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.noun($num).")<br>\n";
if (isset($_POST['regexlist']) && 'blacklist.regex.json' === $file->getFilename()) {
$num = archive_restore_table($file, 'regex_blacklist', $flushtables);
echo 'Processed blacklist (regex) ('.$num.noun($num).")<br>\n";
$importedsomething = true;
}
if(isset($_POST["whitelist"]) && $file->getFilename() === "whitelist.exact.json")
{
$num = archive_restore_table($file, "whitelist", $flushtables);
echo "Processed whitelist (exact) (".$num.noun($num).")<br>\n";
if (isset($_POST['whitelist']) && 'whitelist.exact.json' === $file->getFilename()) {
$num = archive_restore_table($file, 'whitelist', $flushtables);
echo 'Processed whitelist (exact) ('.$num.noun($num).")<br>\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.noun($num).")<br>\n";
if (isset($_POST['regex_whitelist']) && 'whitelist.regex.json' === $file->getFilename()) {
$num = archive_restore_table($file, 'regex_whitelist', $flushtables);
echo 'Processed whitelist (regex) ('.$num.noun($num).")<br>\n";
$importedsomething = true;
}
if(isset($_POST["adlist"]) && $file->getFilename() === "adlist.json")
{
$num = archive_restore_table($file, "adlist", $flushtables);
echo "Processed adlist (".$num.noun($num).")<br>\n";
if (isset($_POST['adlist']) && 'adlist.json' === $file->getFilename()) {
$num = archive_restore_table($file, 'adlist', $flushtables);
echo 'Processed adlist ('.$num.noun($num).")<br>\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.noun($num).")<br>\n";
if (isset($_POST['auditlog']) && 'domain_audit.json' === $file->getFilename()) {
$num = archive_restore_table($file, 'domain_audit', $flushtables);
echo 'Processed domain_audit ('.$num.noun($num).")<br>\n";
$importedsomething = true;
}
if(isset($_POST["group"]) && $file->getFilename() === "group.json")
{
$num = archive_restore_table($file, "group", $flushtables);
echo "Processed group (".$num.noun($num).")<br>\n";
if (isset($_POST['group']) && 'group.json' === $file->getFilename()) {
$num = archive_restore_table($file, 'group', $flushtables);
echo 'Processed group ('.$num.noun($num).")<br>\n";
$importedsomething = true;
}
if(isset($_POST["client"]) && $file->getFilename() === "client.json")
{
$num = archive_restore_table($file, "client", $flushtables);
echo "Processed client (".$num.noun($num).")<br>\n";
if (isset($_POST['client']) && 'client.json' === $file->getFilename()) {
$num = archive_restore_table($file, 'client', $flushtables);
echo 'Processed client ('.$num.noun($num).")<br>\n";
$importedsomething = true;
}
if(isset($_POST["client"]) && $file->getFilename() === "client_by_group.json")
{
$num = archive_restore_table($file, "client_by_group", $flushtables);
echo "Processed client group assignments (".$num.noun($num).")<br>\n";
if (isset($_POST['client']) && 'client_by_group.json' === $file->getFilename()) {
$num = archive_restore_table($file, 'client_by_group', $flushtables);
echo 'Processed client group assignments ('.$num.noun($num).")<br>\n";
$importedsomething = true;
}
if((isset($_POST["whitelist"]) || isset($_POST["regex_whitelist"]) ||
isset($_POST["blacklist"]) || isset($_POST["regex_blacklist"])) &&
$file->getFilename() === "domainlist_by_group.json")
{
$num = archive_restore_table($file, "domainlist_by_group", $flushtables);
echo "Processed black-/whitelist group assignments (".$num.noun($num).")<br>\n";
if ((isset($_POST['whitelist']) || isset($_POST['regex_whitelist'])
|| isset($_POST['blacklist']) || isset($_POST['regex_blacklist']))
&& 'domainlist_by_group.json' === $file->getFilename()) {
$num = archive_restore_table($file, 'domainlist_by_group', $flushtables);
echo 'Processed black-/whitelist group assignments ('.$num.noun($num).")<br>\n";
$importedsomething = true;
}
if(isset($_POST["adlist"]) && $file->getFilename() === "adlist_by_group.json")
{
$num = archive_restore_table($file, "adlist_by_group", $flushtables);
echo "Processed adlist group assignments (".$num.noun($num).")<br>\n";
if (isset($_POST['adlist']) && 'adlist_by_group.json' === $file->getFilename()) {
$num = archive_restore_table($file, 'adlist_by_group', $flushtables);
echo 'Processed adlist group assignments ('.$num.noun($num).")<br>\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) {
if (isset($_POST['staticdhcpleases']) && '04-pihole-static-dhcp.conf' === $file->getFilename()) {
if ($flushtables) {
$local_file = @fopen('/etc/dnsmasq.d/04-pihole-static-dhcp.conf', 'r+');
if (false !== $local_file) {
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);
foreach ($staticdhcpleases as $lease) {
list($mac, $ip, $hostname) = explode(',', $lease);
$mac = formatMAC($mac);
if(addStaticDHCPLease($mac,$ip,$hostname))
$num++;
if (addStaticDHCPLease($mac, $ip, $hostname)) {
++$num;
}
}
readStaticLeasesFile();
echo "Processed static DHCP leases (".$num.noun($num).")<br>\n";
if($num > 0) {
echo 'Processed static DHCP leases ('.$num.noun($num).")<br>\n";
if ($num > 0) {
$importedsomething = true;
$reloadsettingspage = true;
}
}
if(isset($_POST["localdnsrecords"]) && $file->getFilename() === "custom.list")
{
if (isset($_POST['localdnsrecords']) && 'custom.list' === $file->getFilename()) {
ob_start();
$reload="false";
if($flushtables) {
$reload = 'false';
if ($flushtables) {
// Defined in func.php included via auth.php
// passing reload="false" will not restart Pi-hole
deleteAllCustomDNSEntries($reload);
}
$num = 0;
$localdnsrecords = process_file(file_get_contents($file));
foreach($localdnsrecords as $record) {
list($ip,$domain) = explode(" ",$record);
if(addCustomDNSEntry($ip, $domain, $reload, false))
$num++;
foreach ($localdnsrecords as $record) {
list($ip, $domain) = explode(' ', $record);
if (addCustomDNSEntry($ip, $domain, $reload, false)) {
++$num;
}
}
ob_end_clean();
echo "Processed local DNS records (".$num.noun($num).")<br>\n";
if($num > 0) {
echo 'Processed local DNS records ('.$num.noun($num).")<br>\n";
if ($num > 0) {
// we need a full pihole restart
$fullpiholerestart = true;
}
}
if(isset($_POST["localcnamerecords"]) && $file->getFilename() === "05-pihole-custom-cname.conf")
{
if (isset($_POST['localcnamerecords']) && '05-pihole-custom-cname.conf' === $file->getFilename()) {
ob_start();
$reload="false";
if($flushtables) {
$reload = 'false';
if ($flushtables) {
// Defined in func.php included via auth.php
//passing reload="false" will not restart Pi-hole
// passing reload="false" will not restart Pi-hole
deleteAllCustomCNAMEEntries($reload);
}
$num = 0;
$localcnamerecords = process_file(file_get_contents($file));
foreach($localcnamerecords as $record) {
$line = str_replace("cname=","", $record);
$line = str_replace("\r","", $line);
$line = str_replace("\n","", $line);
$explodedLine = explode (",", $line);
foreach ($localcnamerecords as $record) {
$line = str_replace('cname=', '', $record);
$line = str_replace("\r", '', $line);
$line = str_replace("\n", '', $line);
$explodedLine = explode(',', $line);
$domain = implode(",", array_slice($explodedLine, 0, -1));
$target = $explodedLine[count($explodedLine)-1];
$domain = implode(',', array_slice($explodedLine, 0, -1));
$target = $explodedLine[count($explodedLine) - 1];
if(addCustomCNAMEEntry($domain, $target, $reload, false))
$num++;
if (addCustomCNAMEEntry($domain, $target, $reload, false)) {
++$num;
}
}
ob_end_clean();
echo "Processed local CNAME records (".$num.noun($num).")<br>\n";
if($num > 0) {
echo 'Processed local CNAME records ('.$num.noun($num).")<br>\n";
if ($num > 0) {
// we need a full pihole restart
$fullpiholerestart = true;
}
@@ -577,79 +551,73 @@ if(isset($_POST["action"]))
}
// do we need a full restart of Pi-hole or reloading the lists?
if($fullpiholerestart)
{
pihole_execute("restartdns");
if ($fullpiholerestart) {
pihole_execute('restartdns');
} else {
if($importedsomething)
{
pihole_execute("restartdns reload");
if ($importedsomething) {
pihole_execute('restartdns reload');
}
}
unlink($fullfilename);
echo "OK";
if($reloadsettingspage)
{
echo 'OK';
if ($reloadsettingspage) {
echo "<br>\n<span data-forcereload></span>";
}
} else {
exit('No file transmitted or parameter error.');
}
else
{
die("No file transmitted or parameter error.");
}
}
else
{
$hostname = gethostname() ? str_replace(".", "_", gethostname())."-" : "";
$tarname = "pi-hole-".$hostname."teleporter_".date("Y-m-d_H-i-s").".tar";
$filename = $tarname.".gz";
$archive_file_name = tempnam(sys_get_temp_dir(), 'pihole_teleporter_'); //create a random file name in the system's tmp dir for the intermediat archive
unlink($archive_file_name); //remove intermediate file created by tempnam()
$archive_file_name .= ".tar"; // Append ".tar" extension
} else {
$hostname = gethostname() ? str_replace('.', '_', gethostname()).'-' : '';
$tarname = 'pi-hole-'.$hostname.'teleporter_'.date('Y-m-d_H-i-s').'.tar';
$filename = $tarname.'.gz';
$archive_file_name = tempnam(sys_get_temp_dir(), 'pihole_teleporter_'); // create a random file name in the system's tmp dir for the intermediat archive
unlink($archive_file_name); // remove intermediate file created by tempnam()
$archive_file_name .= '.tar'; // Append ".tar" extension
$archive = new PharData($archive_file_name);
if ($archive->isWritable() !== TRUE) {
exit("cannot open/create ".htmlentities($archive_file_name)."<br>\nPHP user: ".exec('whoami')."\n");
if (true !== $archive->isWritable()) {
exit('cannot open/create '.htmlentities($archive_file_name)."<br>\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_table("group.json", "group");
archive_add_table("client.json", "client");
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_table('group.json', 'group');
archive_add_table('client.json', 'client');
// Group linking tables
archive_add_table("domainlist_by_group.json", "domainlist_by_group");
archive_add_table("adlist_by_group.json", "adlist_by_group");
archive_add_table("client_by_group.json", "client_by_group");
archive_add_table('domainlist_by_group.json', 'domainlist_by_group');
archive_add_table('adlist_by_group.json', 'adlist_by_group');
archive_add_table('client_by_group.json', 'client_by_group');
archive_add_file("/etc/pihole/","setupVars.conf");
archive_add_file("/etc/pihole/","dhcp.leases");
archive_add_file("/etc/pihole/","custom.list");
archive_add_file("/etc/pihole/","pihole-FTL.conf");
archive_add_file("/etc/","hosts","etc/");
archive_add_directory("/etc/dnsmasq.d/","dnsmasq.d/");
archive_add_file('/etc/pihole/', 'setupVars.conf');
archive_add_file('/etc/pihole/', 'dhcp.leases');
archive_add_file('/etc/pihole/', 'custom.list');
archive_add_file('/etc/pihole/', 'pihole-FTL.conf');
archive_add_file('/etc/', 'hosts', 'etc/');
archive_add_directory('/etc/dnsmasq.d/', 'dnsmasq.d/');
$archive->compress(Phar::GZ); // Creates a gzipped copy
unlink($archive_file_name); // Unlink original tar file as it is not needed anymore
$archive_file_name .= ".gz"; // Append ".gz" extension to ".tar"
$archive_file_name .= '.gz'; // Append ".gz" extension to ".tar"
header("Content-type: application/gzip");
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();
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;
}
?>

View File

@@ -14,39 +14,40 @@ $available_themes = array();
* Array[1] = Is this a dark mode theme? (Sets background to black during page reloading to avoid white "flashing")
* Array[2] = Style sheet name
*/
$available_themes["default-light"] = array("Pi-hole default theme (light, default)", false, "default-light");
$available_themes["default-dark"] = array("Pi-hole midnight theme (dark)", true, "default-dark");
$available_themes["default-darker"] = array("Pi-hole deep-midnight theme (dark)", true, "default-darker");
$available_themes['default-light'] = array('Pi-hole default theme (light, default)', false, 'default-light');
$available_themes['default-dark'] = array('Pi-hole midnight theme (dark)', true, 'default-dark');
$available_themes['default-darker'] = array('Pi-hole deep-midnight theme (dark)', true, 'default-darker');
// Option to have the theme go with the device dark mode setting, always set the background to black to avoid flashing
$available_themes["default-auto"] = array("Pi-hole auto theme (light/dark)", true, "default-auto");
$available_themes["lcars"] = array("Star Trek LCARS theme (dark)", true, "lcars");
$available_themes['default-auto'] = array('Pi-hole auto theme (light/dark)', true, 'default-auto');
$available_themes['lcars'] = array('Star Trek LCARS theme (dark)', true, 'lcars');
$webtheme = "";
$webtheme = '';
// Try to load theme settings from setupVars.conf
if(isset($setupVars['WEBTHEME']))
if (isset($setupVars['WEBTHEME'])) {
$webtheme = $setupVars['WEBTHEME'];
// May be overwritten by settings tab
if(isset($_POST["field"]) &&
$_POST["field"] === "webUI" &&
isset($_POST["webtheme"])) {
$webtheme = $_POST["webtheme"];
}
if(!array_key_exists($webtheme,$available_themes)) {
// May be overwritten by settings tab
if (isset($_POST['field'])
&& 'webUI' === $_POST['field']
&& isset($_POST['webtheme'])) {
$webtheme = $_POST['webtheme'];
}
if (!array_key_exists($webtheme, $available_themes)) {
// Fallback to default (light) theme is property is not set
// or requested theme is not among the available
$webtheme = "default-auto";
$webtheme = 'default-auto';
}
$darkmode = $available_themes[$webtheme][1];
$theme = $available_themes[$webtheme][2];
function theme_selection() {
function theme_selection()
{
global $available_themes, $webtheme;
foreach ($available_themes as $key => $value) {
?><div><input type="radio" name="webtheme" value="<?php echo $key; ?>" id="webtheme_<?php echo $key; ?>" <?php if ($key === $webtheme){ ?>checked<?php } ?>>
?><div><input type="radio" name="webtheme" value="<?php echo $key; ?>" id="webtheme_<?php echo $key; ?>" <?php if ($key === $webtheme) { ?>checked<?php } ?>>
<label for="webtheme_<?php echo $key; ?>"><strong><?php echo $value[0]; ?></strong></label></div>
<?php
}

View File

@@ -1,54 +1,48 @@
<?php
$localversions = "/etc/pihole/localversions";
$localbranches = "/etc/pihole/localbranches";
$GitHubVersions = "/etc/pihole/GitHubVersions";
$localversions = '/etc/pihole/localversions';
$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";
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_branch = 'master';
$web_current = 'N/A';
$web_update = false;
$FTL_current = "N/A";
$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));
} 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 **********/
// Get Pi-hole core branch / version / commit
// Check if on a dev branch
$core_branch = $branches[0];
if($core_branch !== "master") {
$core_current = "vDev";
if ('master' !== $core_branch) {
$core_current = 'vDev';
$core_commit = $versions[0];
}
else {
$core_current = explode("-",$versions[0])[0];
} else {
$core_current = explode('-', $versions[0])[0];
}
/********** Get Pi-hole web branch / version / commit **********/
// Get Pi-hole web branch / version / commit
$web_branch = $branches[1];
if($web_branch !== "master") {
$web_current = "vDev";
if ('master' !== $web_branch) {
$web_current = 'vDev';
$web_commit = $versions[1];
}
else {
$web_current = explode("-",$versions[1])[0];
} else {
$web_current = explode('-', $versions[1])[0];
}
/********** Get Pi-hole FTL (not a git repository) **********/
// Get Pi-hole FTL (not a git repository)
$FTL_branch = $branches[2];
if(substr($versions[2], 0, 4) === "vDev") {
$FTL_current = "vDev";
if ('vDev' === substr($versions[2], 0, 4)) {
$FTL_current = 'vDev';
$FTL_commit = $versions[2];
}
else {
} else {
$FTL_current = $versions[2];
}
@@ -58,40 +52,29 @@ else
$FTL_latest = $GitHubversions[2];
// Core version comparison
if($core_current !== "vDev")
{
if ('vDev' !== $core_current) {
// 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
{
} else {
$core_update = false;
}
// Web version comparison
if($web_current !== "vDev")
{
if ('vDev' !== $web_current) {
// 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
{
} 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")
{
if ('vDev' !== $FTL_current) {
$FTL_update = (version_compare($FTL_current, $FTL_latest) < 0);
}
else
{
} else {
$FTL_update = false;
}
}
?>

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@
* Please see LICENSE file for your rights under this license.
*/
require "scripts/pi-hole/php/header.php";
require 'scripts/pi-hole/php/header.php';
?>
<!-- Title -->
<div class="page-header">
@@ -27,8 +27,8 @@ require "scripts/pi-hole/php/header.php";
<label for="chk2">Automatic scrolling on update</label>
</div>
<script src="scripts/pi-hole/js/taillog-FTL.js?v=<?=$cacheVer?>"></script>
<script src="scripts/pi-hole/js/taillog-FTL.js?v=<?php echo $cacheVer; ?>"></script>
<?php
require "scripts/pi-hole/php/footer.php";
require 'scripts/pi-hole/php/footer.php';
?>

View File

@@ -8,7 +8,7 @@
* Please see LICENSE file for your rights under this license.
*/
require "scripts/pi-hole/php/header.php";
require 'scripts/pi-hole/php/header.php';
?>
<!-- Title -->
<div class="page-header">
@@ -27,8 +27,8 @@ require "scripts/pi-hole/php/header.php";
<label for="chk2">Automatic scrolling on update</label>
</div>
<script src="scripts/pi-hole/js/taillog.js?v=<?=$cacheVer?>"></script>
<script src="scripts/pi-hole/js/taillog.js?v=<?php echo $cacheVer; ?>"></script>
<?php
require "scripts/pi-hole/php/footer.php";
require 'scripts/pi-hole/php/footer.php';
?>