mirror of
https://github.com/pi-hole/web.git
synced 2024-12-06 19:36:21 +01:00
+1
-1
@@ -33,6 +33,6 @@ groups:
|
||||
conditions:
|
||||
branches:
|
||||
- master
|
||||
required: -1
|
||||
required: 4
|
||||
teams:
|
||||
- admin
|
||||
|
||||
@@ -7,3 +7,4 @@ This is a basic checklist for now, We will update it in the future.
|
||||
* Submit Pull Requests to the development branch only.
|
||||
* Before Submitting your Pull Request, merge `devel` with your new branch and fix any conflicts. (Make sure you don't break anything in development!)
|
||||
* Be patient. We will review all submitted pull requests, but our focus is on stability.. please don't be offended if we reject your PR, or it appears we're doing nothing with it! We'll get around to it..
|
||||
* Please use the Pi-hole brand: **Pi-hole** (Take a special look at the capitalized 'P' and a low 'h' with a hyphen)
|
||||
|
||||
@@ -22,8 +22,10 @@ A read-only API can be accessed at `/admin/api.php`. With either no parameters o
|
||||
}
|
||||
```
|
||||
|
||||
There are many more parameters, such as `summaryRaw`, `overTimeData10mins`, ` topClients` or `getQuerySources`, `getQueryTypes`, `getForwardDestinations`, and `getAllQueries`.
|
||||
Together with a token it is also possible to enable and disable (also with a set timeout) blocking via the API.
|
||||
There are many more parameters, such as `summaryRaw`, `overTimeData10mins`, `topItems`, ` topClients` or `getQuerySources`, `getQueryTypes`, `getForwardDestinations`, and finally `getAllQueries`.
|
||||
Together with a token it is also possible to enable and disable (also with a set timeout) blocking via the API
|
||||
|
||||
The API returns more information (in a slighly different format if `FTL` is running) - it supports a fall-back to the "old" PHP API if `FTL` is not running. Test the type and/or version of the API by using the parameter `type` and `version`.
|
||||
|
||||
<hr>
|
||||
<img src="https://assets.pi-hole.net/static/BStackLogo.png" height="80"><br>
|
||||
|
||||
@@ -1,151 +1,101 @@
|
||||
<?php
|
||||
/* Pi-hole: A black hole for Internet advertisements
|
||||
/* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||
* Network-wide ad blocking via your own hardware.
|
||||
*
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
* Please see LICENSE file for your rights under this license */
|
||||
|
||||
$api = true;
|
||||
require "scripts/pi-hole/php/password.php";
|
||||
require "scripts/pi-hole/php/auth.php";
|
||||
$api = true;
|
||||
header('Content-type: application/json');
|
||||
require("scripts/pi-hole/php/FTL.php");
|
||||
require("scripts/pi-hole/php/password.php");
|
||||
require("scripts/pi-hole/php/auth.php");
|
||||
check_cors();
|
||||
|
||||
check_cors();
|
||||
|
||||
include('scripts/pi-hole/php/data.php');
|
||||
header('Content-type: application/json');
|
||||
$data = array();
|
||||
|
||||
$data = array();
|
||||
// Common API functions
|
||||
if (isset($_GET['status']) && $auth)
|
||||
{
|
||||
$pistatus = exec('sudo pihole status web');
|
||||
if ($pistatus == "1")
|
||||
{
|
||||
$data = array_merge($data, array("status" => "enabled"));
|
||||
}
|
||||
else
|
||||
{
|
||||
$data = array_merge($data, array("status" => "disabled"));
|
||||
}
|
||||
}
|
||||
elseif (isset($_GET['enable']) && $auth)
|
||||
{
|
||||
if(isset($_GET["auth"]))
|
||||
{
|
||||
if($_GET["auth"] !== $pwhash)
|
||||
die("Not authorized!");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Skip token validation if explicit auth string is given
|
||||
check_csrf($_GET['token']);
|
||||
}
|
||||
exec('sudo pihole enable');
|
||||
$data = array_merge($data, array("status" => "enabled"));
|
||||
unlink("../custom_disable_timer");
|
||||
}
|
||||
elseif (isset($_GET['disable']) && $auth)
|
||||
{
|
||||
if(isset($_GET["auth"]))
|
||||
{
|
||||
if($_GET["auth"] !== $pwhash)
|
||||
die("Not authorized!");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Skip token validation if explicit auth string is given
|
||||
check_csrf($_GET['token']);
|
||||
}
|
||||
$disable = intval($_GET['disable']);
|
||||
// intval returns the integer value on success, or 0 on failure
|
||||
if($disable > 0)
|
||||
{
|
||||
$timestamp = time();
|
||||
exec("sudo pihole disable ".$disable."s");
|
||||
file_put_contents("../custom_disable_timer",($timestamp+$disable)*1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
exec('sudo pihole disable');
|
||||
unlink("../custom_disable_timer");
|
||||
}
|
||||
$data = array_merge($data, array("status" => "disabled"));
|
||||
}
|
||||
|
||||
// Non-Auth
|
||||
// Other API functions
|
||||
if(!testFTL() && !isset($_GET["PHP"]))
|
||||
{
|
||||
$data = array_merge($data, array("FTLnotrunning" => true));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!isset($_GET["PHP"]))
|
||||
{
|
||||
require("api_FTL.php");
|
||||
}
|
||||
else
|
||||
{
|
||||
require("api_PHP.php");
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_GET['type'])) {
|
||||
$data["type"] = "PHP";
|
||||
}
|
||||
|
||||
if (isset($_GET['version'])) {
|
||||
$data["version"] = 2;
|
||||
}
|
||||
|
||||
if (isset($_GET['summaryRaw'])) {
|
||||
$data = array_merge($data, getSummaryData());
|
||||
}
|
||||
|
||||
if (isset($_GET['summary']) || !count($_GET)) {
|
||||
$sum = getSummaryData();
|
||||
$sum['ads_blocked_today'] = number_format( $sum['ads_blocked_today']);
|
||||
$sum['dns_queries_today'] = number_format( $sum['dns_queries_today']);
|
||||
$sum['ads_percentage_today'] = number_format( $sum['ads_percentage_today'], 1, '.', '');
|
||||
$sum['domains_being_blocked'] = number_format( $sum['domains_being_blocked']);
|
||||
$data = array_merge($data, $sum);
|
||||
}
|
||||
|
||||
if (isset($_GET['overTimeData'])) {
|
||||
$data = array_merge($data, getOverTimeData());
|
||||
}
|
||||
|
||||
if (isset($_GET['overTimeData10mins'])) {
|
||||
$data = array_merge($data, getOverTimeData10mins());
|
||||
}
|
||||
|
||||
// Auth Required
|
||||
|
||||
if (isset($_GET['topItems']) && $auth) {
|
||||
$data = array_merge($data, getTopItems($_GET['topItems']));
|
||||
}
|
||||
|
||||
if (isset($_GET['recentItems']) && $auth) {
|
||||
if (is_numeric($_GET['recentItems'])) {
|
||||
$data = array_merge($data, getRecentItems($_GET['recentItems']));
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_GET['getQueryTypes']) && $auth) {
|
||||
$data = array_merge($data, getIpvType());
|
||||
}
|
||||
|
||||
if (isset($_GET['getForwardDestinations']) && $auth) {
|
||||
$data = array_merge($data, getForwardDestinations());
|
||||
}
|
||||
|
||||
if (isset($_GET['getQuerySources']) && $auth) {
|
||||
$data = array_merge($data, getQuerySources());
|
||||
}
|
||||
|
||||
if (isset($_GET['getAllQueries']) && $auth) {
|
||||
$data = array_merge($data, getAllQueries($_GET['getAllQueries']));
|
||||
}
|
||||
|
||||
if (isset($_GET['enable']) && $auth) {
|
||||
if(isset($_GET["auth"]))
|
||||
{
|
||||
if($_GET["auth"] !== $pwhash)
|
||||
die("Not authorized!");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Skip token validation if explicit auth string is given
|
||||
check_csrf($_GET['token']);
|
||||
}
|
||||
exec('sudo pihole enable');
|
||||
$data = array_merge($data, array("status" => "enabled"));
|
||||
unlink("../custom_disable_timer");
|
||||
}
|
||||
elseif (isset($_GET['disable']) && $auth) {
|
||||
if(isset($_GET["auth"]))
|
||||
{
|
||||
if($_GET["auth"] !== $pwhash)
|
||||
die("Not authorized!");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Skip token validation if explicit auth string is given
|
||||
check_csrf($_GET['token']);
|
||||
}
|
||||
$disable = intval($_GET['disable']);
|
||||
// intval returns the integer value on success, or 0 on failure
|
||||
if($disable > 0)
|
||||
{
|
||||
$timestamp = time();
|
||||
exec("sudo pihole disable ".$disable."s");
|
||||
file_put_contents("../custom_disable_timer",($timestamp+$disable)*1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
exec('sudo pihole disable');
|
||||
unlink("../custom_disable_timer");
|
||||
}
|
||||
$data = array_merge($data, array("status" => "disabled"));
|
||||
}
|
||||
|
||||
if (isset($_GET['getGravityDomains'])) {
|
||||
$data = array_merge($data, getGravity());
|
||||
}
|
||||
|
||||
if (isset($_GET['tailLog']) && $auth) {
|
||||
$data = array_merge($data, tailPiholeLog($_GET['tailLog']));
|
||||
}
|
||||
|
||||
function filterArray(&$inArray) {
|
||||
$outArray = array();
|
||||
foreach ($inArray as $key=>$value) {
|
||||
if (is_array($value)) {
|
||||
$outArray[htmlspecialchars($key)] = filterArray($value);
|
||||
} else {
|
||||
$outArray[htmlspecialchars($key)] = !is_numeric($value) ? htmlspecialchars($value) : $value;
|
||||
}
|
||||
}
|
||||
return $outArray;
|
||||
}
|
||||
|
||||
$data = filterArray($data);
|
||||
|
||||
if(isset($_GET["jsonForceObject"]))
|
||||
{
|
||||
echo json_encode($data, JSON_FORCE_OBJECT);
|
||||
}
|
||||
else
|
||||
{
|
||||
echo json_encode($data);
|
||||
}
|
||||
if(isset($_GET["jsonForceObject"]))
|
||||
{
|
||||
echo json_encode($data, JSON_FORCE_OBJECT);
|
||||
}
|
||||
else
|
||||
{
|
||||
echo json_encode($data);
|
||||
}
|
||||
?>
|
||||
|
||||
+287
@@ -0,0 +1,287 @@
|
||||
<?php
|
||||
/* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||
* Network-wide ad blocking via your own hardware.
|
||||
*
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license */
|
||||
|
||||
|
||||
if(!isset($api))
|
||||
{
|
||||
die("Direct call to api_FTL.php is not allowed!");
|
||||
}
|
||||
|
||||
$socket = connectFTL("127.0.0.1");
|
||||
|
||||
if (isset($_GET['type'])) {
|
||||
$data["type"] = "FTL";
|
||||
}
|
||||
|
||||
if (isset($_GET['version'])) {
|
||||
$data["version"] = 3;
|
||||
}
|
||||
|
||||
if (isset($_GET['summary']) || isset($_GET['summaryRaw']) || !count($_GET))
|
||||
{
|
||||
sendRequestFTL("stats");
|
||||
$return = getResponseFTL();
|
||||
|
||||
$stats = [];
|
||||
foreach($return as $line)
|
||||
{
|
||||
$tmp = explode(" ",$line);
|
||||
|
||||
if(isset($_GET['summary']))
|
||||
{
|
||||
if($tmp[0] !== "ads_percentage_today")
|
||||
{
|
||||
$stats[$tmp[0]] = number_format($tmp[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$stats[$tmp[0]] = number_format($tmp[1], 1, '.', '');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$stats[$tmp[0]] = intval($tmp[1]);
|
||||
}
|
||||
}
|
||||
$data = array_merge($data,$stats);
|
||||
}
|
||||
|
||||
if (isset($_GET['overTimeData10mins']))
|
||||
{
|
||||
sendRequestFTL("overTime");
|
||||
$return = getResponseFTL();
|
||||
|
||||
$domains_over_time = array();
|
||||
$ads_over_time = array();
|
||||
foreach($return as $line)
|
||||
{
|
||||
$tmp = explode(" ",$line);
|
||||
$domains_over_time[intval($tmp[0])] = intval($tmp[1]);
|
||||
$ads_over_time[intval($tmp[0])] = intval($tmp[2]);
|
||||
}
|
||||
$result = array('domains_over_time' => $domains_over_time,
|
||||
'ads_over_time' => $ads_over_time);
|
||||
$data = array_merge($data, $result);
|
||||
}
|
||||
|
||||
if (isset($_GET['topItems']) && $auth)
|
||||
{
|
||||
if(is_numeric($_GET['topItems']))
|
||||
{
|
||||
sendRequestFTL("top-domains (".$_GET['topItems'].")");
|
||||
}
|
||||
else
|
||||
{
|
||||
sendRequestFTL("top-domains");
|
||||
}
|
||||
|
||||
$return = getResponseFTL();
|
||||
$top_queries = array();
|
||||
foreach($return as $line)
|
||||
{
|
||||
$tmp = explode(" ",$line);
|
||||
$top_queries[$tmp[2]] = intval($tmp[1]);
|
||||
}
|
||||
|
||||
if(is_numeric($_GET['topItems']))
|
||||
{
|
||||
sendRequestFTL("top-ads (".$_GET['topItems'].")");
|
||||
}
|
||||
else
|
||||
{
|
||||
sendRequestFTL("top-ads");
|
||||
}
|
||||
|
||||
$return = getResponseFTL();
|
||||
$top_ads = array();
|
||||
foreach($return as $line)
|
||||
{
|
||||
$tmp = explode(" ",$line);
|
||||
$top_ads[$tmp[2]] = intval($tmp[1]);
|
||||
}
|
||||
|
||||
$result = array('top_queries' => $top_queries,
|
||||
'top_ads' => $top_ads);
|
||||
|
||||
$data = array_merge($data, $result);
|
||||
}
|
||||
|
||||
if ((isset($_GET['topClients']) || isset($_GET['getQuerySources'])) && $auth)
|
||||
{
|
||||
|
||||
if(isset($_GET['topClients']))
|
||||
{
|
||||
$number = $_GET['topClients'];
|
||||
}
|
||||
elseif(isset($_GET['getQuerySources']))
|
||||
{
|
||||
$number = $_GET['getQuerySources'];
|
||||
}
|
||||
|
||||
if(is_numeric($number))
|
||||
{
|
||||
sendRequestFTL("top-clients (".$number.")");
|
||||
}
|
||||
else
|
||||
{
|
||||
sendRequestFTL("top-clients");
|
||||
}
|
||||
|
||||
$return = getResponseFTL();
|
||||
$top_clients = array();
|
||||
foreach($return as $line)
|
||||
{
|
||||
$tmp = explode(" ",$line);
|
||||
if(count($tmp) == 4)
|
||||
{
|
||||
$top_clients[$tmp[3]."|".$tmp[2]] = intval($tmp[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$top_clients[$tmp[2]] = intval($tmp[1]);
|
||||
}
|
||||
}
|
||||
|
||||
$result = array('top_sources' => $top_clients);
|
||||
$data = array_merge($data, $result);
|
||||
}
|
||||
|
||||
if (isset($_GET['getForwardDestinations']) && $auth)
|
||||
{
|
||||
sendRequestFTL("forward-dest");
|
||||
$return = getResponseFTL();
|
||||
$forward_dest = array();
|
||||
foreach($return as $line)
|
||||
{
|
||||
$tmp = explode(" ",$line);
|
||||
if(count($tmp) == 4)
|
||||
{
|
||||
$forward_dest[$tmp[3]."|".$tmp[2]] = intval($tmp[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$forward_dest[$tmp[2]] = intval($tmp[1]);
|
||||
}
|
||||
}
|
||||
|
||||
$result = array('forward_destinations' => $forward_dest);
|
||||
$data = array_merge($data, $result);
|
||||
}
|
||||
|
||||
if (isset($_GET['getQueryTypes']) && $auth)
|
||||
{
|
||||
sendRequestFTL("querytypes");
|
||||
$return = getResponseFTL();
|
||||
$querytypes = array();
|
||||
foreach($return as $ret)
|
||||
{
|
||||
$tmp = explode(": ",$ret);
|
||||
$querytypes[$tmp[0]] = intval($tmp[1]);
|
||||
}
|
||||
|
||||
$result = array('querytypes' => $querytypes);
|
||||
$data = array_merge($data, $result);
|
||||
}
|
||||
|
||||
if (isset($_GET['getAllQueries']) && $auth)
|
||||
{
|
||||
if(isset($_GET['from']) && isset($_GET['until']))
|
||||
{
|
||||
// Get limited time interval
|
||||
sendRequestFTL("getallqueries-time ".$_GET['from']." ".$_GET['until']);
|
||||
}
|
||||
else if(isset($_GET['domain']))
|
||||
{
|
||||
// Get specific domain only
|
||||
sendRequestFTL("getallqueries-domain ".$_GET['domain']);
|
||||
}
|
||||
else if(isset($_GET['client']))
|
||||
{
|
||||
// Get specific client only
|
||||
sendRequestFTL("getallqueries-client ".$_GET['client']);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get all queries
|
||||
sendRequestFTL("getallqueries");
|
||||
}
|
||||
$return = getResponseFTL();
|
||||
$allQueries = array();
|
||||
foreach($return as $line)
|
||||
{
|
||||
$tmp = explode(" ",$line);
|
||||
array_push($allQueries,$tmp);
|
||||
}
|
||||
|
||||
$result = array('data' => $allQueries);
|
||||
$data = array_merge($data, $result);
|
||||
}
|
||||
|
||||
if(isset($_GET["recentBlocked"]))
|
||||
{
|
||||
sendRequestFTL("recentBlocked");
|
||||
die(getResponseFTL()[0]);
|
||||
unset($data);
|
||||
}
|
||||
|
||||
if (isset($_GET['overTimeDataForwards']) && $auth)
|
||||
{
|
||||
sendRequestFTL("ForwardedoverTime");
|
||||
$return = getResponseFTL();
|
||||
|
||||
foreach($return as $line)
|
||||
{
|
||||
$tmp = explode(" ",$line);
|
||||
for ($i=0; $i < count($tmp)-1; $i++) {
|
||||
$over_time[intval($tmp[0])][$i] = intval($tmp[$i+1]);
|
||||
}
|
||||
}
|
||||
$result = array('over_time' => $over_time);
|
||||
$data = array_merge($data, $result);
|
||||
}
|
||||
|
||||
if (isset($_GET['getForwardDestinationNames']) && $auth)
|
||||
{
|
||||
sendRequestFTL("forward-names");
|
||||
$return = getResponseFTL();
|
||||
$forward_dest = array();
|
||||
foreach($return as $line)
|
||||
{
|
||||
$tmp = explode(" ",$line);
|
||||
if(count($tmp) == 4)
|
||||
{
|
||||
$forward_dest[$tmp[3]."|".$tmp[2]] = intval($tmp[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$forward_dest[$tmp[2]] = intval($tmp[1]);
|
||||
}
|
||||
}
|
||||
|
||||
$result = array('forward_destinations' => $forward_dest);
|
||||
$data = array_merge($data, $result);
|
||||
}
|
||||
|
||||
if (isset($_GET['overTimeDataQueryTypes']) && $auth)
|
||||
{
|
||||
sendRequestFTL("QueryTypesoverTime");
|
||||
$return = getResponseFTL();
|
||||
|
||||
foreach($return as $line)
|
||||
{
|
||||
$tmp = explode(" ",$line);
|
||||
for ($i=0; $i < count($tmp)-1; $i++) {
|
||||
$over_time[intval($tmp[0])][$i] = intval($tmp[$i+1]);
|
||||
}
|
||||
}
|
||||
$result = array('over_time' => $over_time);
|
||||
$data = array_merge($data, $result);
|
||||
}
|
||||
|
||||
disconnectFTL();
|
||||
?>
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
/* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||
* Network-wide ad blocking via your own hardware.
|
||||
*
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
|
||||
|
||||
if(!isset($api))
|
||||
{
|
||||
die("Direct call to api_PHP.php is not allowed!");
|
||||
}
|
||||
|
||||
include('scripts/pi-hole/php/data.php');
|
||||
|
||||
// Non-Auth
|
||||
|
||||
if (isset($_GET['type'])) {
|
||||
$data["type"] = "PHP";
|
||||
}
|
||||
|
||||
if (isset($_GET['version'])) {
|
||||
$data["version"] = 2;
|
||||
}
|
||||
|
||||
if (isset($_GET['summaryRaw'])) {
|
||||
$data = array_merge($data, getSummaryData());
|
||||
}
|
||||
|
||||
if (isset($_GET['summary']) || !count($_GET)) {
|
||||
$sum = getSummaryData();
|
||||
$sum['ads_blocked_today'] = number_format( $sum['ads_blocked_today']);
|
||||
$sum['dns_queries_today'] = number_format( $sum['dns_queries_today']);
|
||||
$sum['ads_percentage_today'] = number_format( $sum['ads_percentage_today'], 1, '.', '');
|
||||
$sum['domains_being_blocked'] = number_format( $sum['domains_being_blocked']);
|
||||
$data = array_merge($data, $sum);
|
||||
}
|
||||
|
||||
if (isset($_GET['overTimeData'])) {
|
||||
$data = array_merge($data, getOverTimeData());
|
||||
}
|
||||
|
||||
if (isset($_GET['overTimeData10mins'])) {
|
||||
$data = array_merge($data, getOverTimeData10mins());
|
||||
}
|
||||
|
||||
// Auth Required
|
||||
|
||||
if (isset($_GET['topItems']) && $auth) {
|
||||
$data = array_merge($data, getTopItems($_GET['topItems']));
|
||||
}
|
||||
|
||||
if (isset($_GET['recentItems']) && $auth) {
|
||||
if (is_numeric($_GET['recentItems'])) {
|
||||
$data = array_merge($data, getRecentItems($_GET['recentItems']));
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_GET['getQueryTypes']) && $auth) {
|
||||
$data = array_merge($data, getIpvType());
|
||||
}
|
||||
|
||||
if (isset($_GET['getForwardDestinations']) && $auth) {
|
||||
$data = array_merge($data, getForwardDestinations());
|
||||
}
|
||||
|
||||
if (isset($_GET['getQuerySources']) && $auth) {
|
||||
$data = array_merge($data, getQuerySources());
|
||||
}
|
||||
|
||||
if (isset($_GET['getAllQueries']) && $auth) {
|
||||
$data = array_merge($data, getAllQueries($_GET['getAllQueries']));
|
||||
}
|
||||
|
||||
if (isset($_GET['getGravityDomains'])) {
|
||||
$data = array_merge($data, getGravity());
|
||||
}
|
||||
|
||||
function filterArray(&$inArray) {
|
||||
$outArray = array();
|
||||
foreach ($inArray as $key=>$value) {
|
||||
if (is_array($value)) {
|
||||
$outArray[htmlspecialchars($key)] = filterArray($value);
|
||||
} else {
|
||||
$outArray[htmlspecialchars($key)] = !is_numeric($value) ? htmlspecialchars($value) : $value;
|
||||
}
|
||||
}
|
||||
return $outArray;
|
||||
}
|
||||
|
||||
$data = filterArray($data);
|
||||
?>
|
||||
@@ -1,4 +1,10 @@
|
||||
<?php
|
||||
<?php /*
|
||||
* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||
* Network-wide ad blocking via your own hardware.
|
||||
*
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
require "scripts/pi-hole/php/header.php";
|
||||
?>
|
||||
<!-- Title -->
|
||||
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
<!-- Pi-hole: A black hole for Internet advertisements
|
||||
<?php /*
|
||||
* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||
* Network-wide ad blocking via your own hardware.
|
||||
*
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. -->
|
||||
<?php
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
require "scripts/pi-hole/php/header.php";
|
||||
?>
|
||||
<!-- Title -->
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<!-- Pi-hole: A black hole for Internet advertisements
|
||||
<?php /*
|
||||
* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||
* Network-wide ad blocking via your own hardware.
|
||||
*
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. -->
|
||||
<?php
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
require "scripts/pi-hole/php/header.php";
|
||||
|
||||
if(strlen($pwhash) > 0)
|
||||
@@ -48,20 +48,13 @@
|
||||
<ul>
|
||||
<li>Summary: A summary of statistics showing how many total DNS queries have been blocked today, what percentage of DNS queries have been blocked, and how many domains are in the compiled ad list. This summary is updated every 10 seconds.</li>
|
||||
<li>Queries over time: Graph showing DNS queries (total and blocked) over 10 minute time intervals. More information can be acquired by hovering over the lines. This graph is updated every 10 minutes.</li>
|
||||
<li>Query Types: Identifies the types of processed queries:
|
||||
<ul>
|
||||
<li>A: address lookup (most commonly used to map hostnames to an IPv4 address of the host)</li>
|
||||
<li>AAAA: address lookup (most commonly used to map hostnames to an IPv6 address of the host)</li>
|
||||
<li>PTR: most common use is for implementing reverse DNS lookups</li>
|
||||
<li>SRV: Service locator (often used by XMPP, SIP, and LDAP)</li>
|
||||
<li>and others</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Query Types: Identifies the types of processed queries</li>
|
||||
<li>Forward Destinations: Shows to which upstream DNS the permitted requests have been forwarded to.</li>
|
||||
<li>Top Domains: Ranking of requested sites by number of DNS lookups.</li>
|
||||
<li>Top Advertisers: Ranking of requested advertisements by number of DNS lookups.</li>
|
||||
<li>Top Clients: Ranking of how many DNS requests each client has made on the local network.</li>
|
||||
</ul>
|
||||
<p>The Top Domains and Top Advertisers lists may be hidden depending on the privacy Settings on the settings page</p>
|
||||
<?php if($authenticationsystem){ ?>
|
||||
<p>Note that the login session does <em>not</em> expire on the dashboard, as the summary is updated every 10 seconds which refreshes the session.</p>
|
||||
<?php } ?>
|
||||
@@ -70,7 +63,7 @@
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h2>Query Log</h2>
|
||||
<p>Shows the recent queries by parsing Pi-hole's log. It is possible to search through the whole list by using the "Search" input field. If the status is reported as "OK", then the DNS request has been permitted. Otherwise ("Pi-holed") it has been blocked. By clicking on the buttons under "Action" the corresponding domains can quickly be added to the white-/blacklist. The status of the action will be reported on this page.</p>
|
||||
<p>Shows the recent queries by parsing Pi-hole's log. It is possible to search through the whole list by using the "Search" input field. If the status is reported as "OK", then the DNS request has been permitted. Otherwise ("Pi-holed") it has been blocked. By clicking on the buttons under "Action" the corresponding domains can quickly be added to the white-/blacklist. The status of the action will be reported on this page. By default, only the recent 10 minutes are shown to enhance the loading speed of the query log page. All domains can be requested by clicking on the corresponding link in the header of the page. Note that the result heavily depends on your privacy settings (see Settings page).</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@@ -84,7 +77,7 @@
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h2>Disable / Enable</h2>
|
||||
Disables/enables Pi-Hole blocking completely. You may have to wait a few minutes for the changes to reach all of your devices. The change will be reflected by a changed status (top left)
|
||||
Disables/enables Pi-hole blocking completely. You may have to wait a few minutes for the changes to reach all of your devices. The change will be reflected by a changed status (top left)
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@@ -108,18 +101,22 @@
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h2>Settings</h2>
|
||||
Change settings for the Pi-Hole
|
||||
Change settings for the Pi-hole
|
||||
<h4>Networking</h4>
|
||||
Displays information about the interfaces of the Pi-Hole. No changes possible.
|
||||
<h4>Pi-Hole DHCP Server</h4>
|
||||
Using this setting you can enable/disable the DHCP server of the Pi-Hole. Note that you should disable any other DHCP server on your network to avoid IP addresses being used more than once. You have to give the range of IPs that DHCP will serve and the IP of the local router (gateway). If the DHCP server is active, the current leases are shown on the settings page. IPv4 DHCP will always be activated, IPv6 (stateless + statefull) can be enabled.
|
||||
Displays information about the interfaces of the Pi-hole. No changes possible.
|
||||
<h4>Pi-hole DHCP Server</h4>
|
||||
Using this setting you can enable/disable the DHCP server of the Pi-hole. Note that you should disable any other DHCP server on your network to avoid IP addresses being used more than once. You have to give the range of IPs that DHCP will serve and the IP of the local router (gateway). If the DHCP server is active, the current leases are shown on the settings page. IPv4 DHCP will always be activated, IPv6 (stateless + statefull) can be enabled.
|
||||
<h4>Upstream DNS Servers</h4>
|
||||
Customize used upstream DNS servers + advanced settings for DNS servers. Note that any number of DNS servers may be enabled at a time.
|
||||
<h4>Query Logging</h4>
|
||||
Enabled/disable query logging on your Pi-hole + provide option to flush the log
|
||||
<h4>API</h4>
|
||||
Change settings which apply to the API as well as the web UI<br>
|
||||
Note that Top Clients have to be given as IP addresses
|
||||
Change settings which apply to the API as well as the web UI
|
||||
<ul>
|
||||
<li>Show permitted domain entries: Toogle permitted queries in Query Log + Top Domains on Main Page</li>
|
||||
<li>Show blockes domain entries: Toogle blocked queries in Query Log + Top Ads on Main Page</li>
|
||||
<li>Privacy mode: Replace IPs in query log with "hidden"</li>
|
||||
</ul>
|
||||
<h4>Web User Interface</h4>
|
||||
Other settings which affect the webUI but not the API of Pi-hole
|
||||
<h4>System Administration</h4>
|
||||
@@ -129,7 +126,7 @@
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h2>Authentication system (currently <?php if($authenticationsystem) { ?>enabled<?php } else { ?>disabled<?php } ?>)</h2>
|
||||
<p>Using the command<pre>sudo pihole -a -p pa22w0rd</pre> where <em>pa22w0rd</em> is the password to be set in this example, one can enable the authentication system of this web interface. Thereafter, a login is required for most pages (the dashboard will show a limited amount of statistics). Note that the authentication system may be disabled again, by setting an empty password using the command shown above. The Help center will show more details concerning the authentication system only if it is enabled</p>
|
||||
<p>Using the command<pre>sudo pihole -a -p</pre> and entering a password to be set, one can enable the authentication system of this web interface. Thereafter, a login is required for most pages (the dashboard will show a limited amount of statistics). Note that the authentication system may be disabled again, by setting an empty password using the command shown above. The Help center will show more details concerning the authentication system only if it is enabled</p>
|
||||
</div>
|
||||
</div>
|
||||
<?php if($authenticationsystem) { ?>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<!-- Pi-hole: A black hole for Internet advertisements
|
||||
<?php /*
|
||||
* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||
* Network-wide ad blocking via your own hardware.
|
||||
*
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. -->
|
||||
<?php
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
$indexpage = true;
|
||||
require "scripts/pi-hole/php/header.php";
|
||||
?>
|
||||
@@ -68,7 +68,7 @@
|
||||
<div class="col-md-12">
|
||||
<div class="box" id="queries-over-time">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">Queries over time</h3>
|
||||
<h3 class="box-title">Queries over Time</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="chart">
|
||||
@@ -89,14 +89,14 @@
|
||||
// a password
|
||||
if($auth){ ?>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="hidden-xs hidden-sm col-md-12 col-lg-6">
|
||||
<div class="box" id="query-types">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">Query Types</h3>
|
||||
<h3 class="box-title">Query Types over Time</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="chart">
|
||||
<canvas id="queryTypeChart" width="400" height="200"></canvas>
|
||||
<canvas id="queryTypeChart" width="400" height="150"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overlay">
|
||||
@@ -105,14 +105,14 @@
|
||||
<!-- /.box-body -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="hidden-xs hidden-sm col-md-12 col-lg-6">
|
||||
<div class="box" id="forward-destinations">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">Forward Destinations</h3>
|
||||
<h3 class="box-title">Forward Destinations over Time</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="chart">
|
||||
<canvas id="forwardDestinationChart" width="400" height="200"></canvas>
|
||||
<canvas id="forwardDestinationChart" width="400" height="150"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overlay">
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<!-- Pi-hole: A black hole for Internet advertisements
|
||||
<?php /*
|
||||
* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||
* Network-wide ad blocking via your own hardware.
|
||||
*
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. -->
|
||||
<?php
|
||||
require "scripts/pi-hole/php/header.php";
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
require "scripts/pi-hole/php/header.php";
|
||||
|
||||
$list = $_GET['l'];
|
||||
|
||||
@@ -30,6 +30,7 @@ function getFullName() {
|
||||
<div class="page-header">
|
||||
<h1><?php getFullName(); ?></h1>
|
||||
</div>
|
||||
<?php if($list == "white"){ ?><p>Note that the ad list domains are automatically added to the whitelist so that a list can never get blocked by another list.</p><?php } ?>
|
||||
|
||||
<!-- Domain Input -->
|
||||
<div class="form-group input-group">
|
||||
@@ -46,6 +47,7 @@ function getFullName() {
|
||||
</div>
|
||||
<?php if($list === "white") { ?>
|
||||
<p>Note: Whitelisting a subdomain of a wildcard blocked domain is not possible.</p>
|
||||
<p>Some of the domains shown below are domains of the adlists sources, which are automatically added in order to prevent adlists being able to blacklist each other. See <a href="https://github.com/pi-hole/pi-hole/blob/master/adlists.default" target="_blank">here</a> for the default set of adlists.</p>
|
||||
<?php } ?>
|
||||
|
||||
<!-- Alerts -->
|
||||
@@ -62,6 +64,7 @@ function getFullName() {
|
||||
Failure! Something went wrong.<br/><span id="err"></span>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Domain List -->
|
||||
<?php if($list === "black") { ?>
|
||||
<h3>Exact blocking</h3>
|
||||
|
||||
+41
-10
@@ -1,10 +1,10 @@
|
||||
<!-- Pi-hole: A black hole for Internet advertisements
|
||||
<?php /*
|
||||
* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||
* Network-wide ad blocking via your own hardware.
|
||||
*
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. -->
|
||||
<?php
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
require "scripts/pi-hole/php/header.php";
|
||||
|
||||
// Generate CSRF token
|
||||
@@ -19,30 +19,62 @@ if(isset($setupVars["API_QUERY_LOG_SHOW"]))
|
||||
{
|
||||
if($setupVars["API_QUERY_LOG_SHOW"] === "all")
|
||||
{
|
||||
$showing = "(showing all queries)";
|
||||
$showing = "showing all queries";
|
||||
}
|
||||
elseif($setupVars["API_QUERY_LOG_SHOW"] === "permittedonly")
|
||||
{
|
||||
$showing = "(showing permitted queries only)";
|
||||
$showing = "showing permitted queries only";
|
||||
}
|
||||
elseif($setupVars["API_QUERY_LOG_SHOW"] === "blockedonly")
|
||||
{
|
||||
$showing = "(showing blocked queries only)";
|
||||
$showing = "showing blocked queries only";
|
||||
}
|
||||
elseif($setupVars["API_QUERY_LOG_SHOW"] === "nothing")
|
||||
{
|
||||
$showing = "(showing no queries at all)";
|
||||
$showing = "showing no queries at all";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If filter variable is not set, we
|
||||
// automatically show all queries
|
||||
$showing = "showing all queries";
|
||||
}
|
||||
|
||||
if(isset($_GET["all"]))
|
||||
{
|
||||
$showing .= " within the Pi-hole log";
|
||||
}
|
||||
else if(isset($_GET["client"]))
|
||||
{
|
||||
$showing .= " for client ".htmlentities($_GET["client"]);
|
||||
}
|
||||
else if(isset($_GET["domain"]))
|
||||
{
|
||||
$showing .= " for domain ".htmlentities($_GET["domain"]);
|
||||
}
|
||||
else if(isset($_GET["from"]) && isset($_GET["until"]))
|
||||
{
|
||||
$showing .= " within limited time interval";
|
||||
}
|
||||
else
|
||||
{
|
||||
$showing .= " within recent 10 minutes, <a href=\"?all\">show all</a>";
|
||||
}
|
||||
|
||||
if(isset($setupVars["API_PRIVACY_MODE"]))
|
||||
{
|
||||
if($setupVars["API_PRIVACY_MODE"])
|
||||
{
|
||||
// Overwrite string from above
|
||||
$showing = "(privacy mode enabled)";
|
||||
$showing .= ", privacy mode enabled";
|
||||
}
|
||||
}
|
||||
|
||||
if(strlen($showing) > 0)
|
||||
{
|
||||
$showing = "(".$showing.")";
|
||||
}
|
||||
?>
|
||||
<!-- Send PHP info to JS -->
|
||||
<div id="token" hidden><?php echo $token ?></div>
|
||||
@@ -114,6 +146,5 @@ if(isset($setupVars["API_PRIVACY_MODE"]))
|
||||
require "scripts/pi-hole/php/footer.php";
|
||||
?>
|
||||
|
||||
<script src="scripts/pi-hole/js/queries.js"></script>
|
||||
<script src="scripts/vendor/moment.min.js"></script>
|
||||
<script src="scripts/vendor/datetime-moment.js"></script>
|
||||
<script src="scripts/pi-hole/js/queries.js"></script>
|
||||
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
<!-- Pi-hole: A black hole for Internet advertisements
|
||||
<?php /*
|
||||
* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||
* Network-wide ad blocking via your own hardware.
|
||||
*
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. -->
|
||||
<?php
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
require "scripts/pi-hole/php/header.php";
|
||||
?>
|
||||
<!-- Title -->
|
||||
|
||||
@@ -29,20 +29,21 @@ function eventsource() {
|
||||
var ta = $("#output");
|
||||
var upload = $( "#upload" );
|
||||
var checked = "";
|
||||
var token = encodeURIComponent($("#token").html());
|
||||
|
||||
if(upload.prop("checked"))
|
||||
{
|
||||
checked = "upload";
|
||||
checked = "upload";
|
||||
}
|
||||
|
||||
// IE does not support EventSource - load whole content at once
|
||||
if (typeof EventSource !== "function") {
|
||||
httpGet(ta,"/admin/scripts/pi-hole/php/debug.php?IE&"+checked);
|
||||
httpGet(ta,"/admin/scripts/pi-hole/php/debug.php?IE&token="+token+"&"+checked);
|
||||
return;
|
||||
}
|
||||
|
||||
var host = window.location.host;
|
||||
var source = new EventSource("/admin/scripts/pi-hole/php/debug.php?"+checked);
|
||||
var source = new EventSource("/admin/scripts/pi-hole/php/debug.php?&token="+token+"&"+checked);
|
||||
|
||||
// Reset and show field
|
||||
ta.empty();
|
||||
|
||||
@@ -144,6 +144,7 @@ $("#pihole-disable-custom").on("click", function(e){
|
||||
|
||||
var piholeVersion = $("#piholeVersion").html();
|
||||
var webVersion = $("#webVersion").html();
|
||||
var FTLVersion = $("#FTLVersion").html();
|
||||
|
||||
// Credit for following function: https://gist.github.com/alexey-bass/1115557
|
||||
// Modified to discard any possible "v" in the string
|
||||
@@ -183,17 +184,24 @@ function versionCompare(left, right) {
|
||||
$.getJSON("https://api.github.com/repos/pi-hole/pi-hole/releases/latest", function(json) {
|
||||
if(versionCompare(piholeVersion, json.tag_name.slice(1)) < 0) {
|
||||
// Alert user
|
||||
$("#piholeVersion").html($("#piholeVersion").text() + "<a class=\"alert-link\" href=\"https://github.com/pi-hole/pi-hole/releases\">(Update available!)</a>");
|
||||
$("#piholeVersion").html($("#piholeVersion").text() + " <a class=\"alert-link lookatme\" href=\"https://github.com/pi-hole/pi-hole/releases\">(Update available!)</a>");
|
||||
$("#alPiholeUpdate").show();
|
||||
}
|
||||
});
|
||||
$.getJSON("https://api.github.com/repos/pi-hole/AdminLTE/releases/latest", function(json) {
|
||||
if(versionCompare(webVersion, json.tag_name.slice(1)) < 0) {
|
||||
// Alert user
|
||||
$("#webVersion").html($("#webVersion").text() + "<a class=\"alert-link\" href=\"https://github.com/pi-hole/adminLTE/releases\">(Update available!)</a>");
|
||||
$("#webVersion").html($("#webVersion").text() + " <a class=\"alert-link lookatme\" href=\"https://github.com/pi-hole/adminLTE/releases\">(Update available!)</a>");
|
||||
$("#alWebUpdate").show();
|
||||
}
|
||||
});
|
||||
$.getJSON("https://api.github.com/repos/pi-hole/FTL/releases/latest", function(json) {
|
||||
if(versionCompare(FTLVersion, json.tag_name.slice(1)) < 0) {
|
||||
// Alert user
|
||||
$("#FTLVersion").html($("#FTLVersion").text() + " <a class=\"alert-link lookatme\" href=\"https://github.com/pi-hole/FTL/releases\">(Update available!)</a>");
|
||||
$("#alFTLUpdate").show();
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* Make sure that Pi-hole is updated to at least v2.7, since that is needed to use the sudo
|
||||
|
||||
@@ -45,9 +45,23 @@ $("#gravityBtn").on("click", function(){
|
||||
eventsource();
|
||||
});
|
||||
|
||||
$("#gravityBtn").on("click", () => {
|
||||
$("#gravityBtn").attr("disabled", true);
|
||||
eventsource();
|
||||
});
|
||||
|
||||
// Handle hiding of alerts
|
||||
$(function(){
|
||||
$("[data-hide]").on("click", function(){
|
||||
$(this).closest("." + $(this).attr("data-hide")).hide();
|
||||
});
|
||||
|
||||
// Do we want to start updating immediately?
|
||||
// gravity.php?go
|
||||
var searchString = window.location.search.substring(1);
|
||||
if(searchString.indexOf("go") !== -1)
|
||||
{
|
||||
$("#gravityBtn").attr("disabled", true);
|
||||
eventsource();
|
||||
}
|
||||
});
|
||||
|
||||
+370
-147
@@ -29,39 +29,15 @@ function objectToArray(p){
|
||||
|
||||
// Functions to update data in page
|
||||
|
||||
|
||||
function updateSummaryData(runOnce) {
|
||||
var setTimer = function(timeInSeconds) {
|
||||
if (!runOnce) {
|
||||
setTimeout(updateSummaryData, timeInSeconds * 1000);
|
||||
}
|
||||
};
|
||||
$.getJSON("api.php?summary", function LoadSummaryData(data) {
|
||||
|
||||
["ads_blocked_today", "dns_queries_today", "ads_percentage_today"].forEach(function(today) {
|
||||
var todayElement = $("h3#" + today);
|
||||
todayElement.text() !== data[today] && todayElement.addClass("glow");
|
||||
});
|
||||
|
||||
window.setTimeout(function() {
|
||||
["ads_blocked_today", "dns_queries_today", "domains_being_blocked", "ads_percentage_today"].forEach(function(header, idx) {
|
||||
var textData = idx === 3 ? data[header] + "%" : data[header];
|
||||
$("h3#" + header).text(textData);
|
||||
});
|
||||
$("h3.statistic.glow").removeClass("glow");
|
||||
}, 500);
|
||||
|
||||
updateSessionTimer();
|
||||
}).done(function() {
|
||||
setTimer(10);
|
||||
}).fail(function() {
|
||||
setTimer(300);
|
||||
});
|
||||
}
|
||||
|
||||
var failures = 0;
|
||||
function updateQueriesOverTime() {
|
||||
$.getJSON("api.php?overTimeData10mins", function(data) {
|
||||
|
||||
if("FTLnotrunning" in data)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// convert received objects to arrays
|
||||
data.domains_over_time = objectToArray(data.domains_over_time);
|
||||
data.ads_over_time = objectToArray(data.ads_over_time);
|
||||
@@ -71,18 +47,29 @@ function updateQueriesOverTime() {
|
||||
timeLineChart.data.labels = [];
|
||||
timeLineChart.data.datasets[0].data = [];
|
||||
timeLineChart.data.datasets[1].data = [];
|
||||
// Add data for each hour that is available
|
||||
|
||||
// Add data for each hour that is available
|
||||
for (var hour in data.ads_over_time[0]) {
|
||||
if ({}.hasOwnProperty.call(data.ads_over_time[0], hour)) {
|
||||
var h = parseInt(data.domains_over_time[0][hour]);
|
||||
var d = new Date().setHours(Math.floor(h / 6), 10 * (h % 6), 0, 0);
|
||||
var d,h;
|
||||
h = parseInt(data.domains_over_time[0][hour]);
|
||||
if(parseInt(data.ads_over_time[0][0]) < 1200)
|
||||
{
|
||||
// Fallback - old style
|
||||
d = new Date().setHours(Math.floor(h / 6), 10 * (h % 6), 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// New style: Get Unix timestamps
|
||||
d = new Date(1000*h);
|
||||
}
|
||||
|
||||
timeLineChart.data.labels.push(d);
|
||||
timeLineChart.data.datasets[0].data.push(data.domains_over_time[1][hour]);
|
||||
timeLineChart.data.datasets[1].data.push(data.ads_over_time[1][hour]);
|
||||
}
|
||||
}
|
||||
$("#queries-over-time .overlay").remove();
|
||||
$("#queries-over-time .overlay").hide();
|
||||
timeLineChart.update();
|
||||
}).done(function() {
|
||||
// Reload graph after 10 minutes
|
||||
@@ -99,26 +86,148 @@ function updateQueriesOverTime() {
|
||||
});
|
||||
}
|
||||
|
||||
function updateQueryTypes() {
|
||||
$.getJSON("api.php?getQueryTypes", function(data) {
|
||||
function updateQueryTypesOverTime() {
|
||||
$.getJSON("api.php?overTimeDataQueryTypes", function(data) {
|
||||
|
||||
if("FTLnotrunning" in data)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// convert received objects to arrays
|
||||
data.over_time = objectToArray(data.over_time);
|
||||
var timestamps = data.over_time[0];
|
||||
var plotdata = data.over_time[1];
|
||||
// Remove possibly already existing data
|
||||
queryTypeChart.data.labels = [];
|
||||
queryTypeChart.data.datasets[0].data = [];
|
||||
queryTypeChart.data.datasets[1].data = [];
|
||||
|
||||
var colors = [];
|
||||
// Get colors from AdminLTE
|
||||
$.each($.AdminLTE.options.colors, function(key, value) { colors.push(value); });
|
||||
var v = [], c = [];
|
||||
// Collect values and colors, immediately push individual labels
|
||||
$.each(data, function(key , value) {
|
||||
v.push(value);
|
||||
c.push(colors.shift());
|
||||
queryTypeChart.data.labels.push(key.substr(6,key.length - 7));
|
||||
});
|
||||
// Build a single dataset with the data to be pushed
|
||||
var dd = {data: v, backgroundColor: c};
|
||||
// and push it at once
|
||||
queryTypeChart.data.datasets.push(dd);
|
||||
$("#query-types .overlay").remove();
|
||||
queryTypeChart.update();
|
||||
queryTypeChart.chart.config.options.cutoutPercentage=30;
|
||||
queryTypeChart.data.datasets[0].backgroundColor = colors[0];
|
||||
queryTypeChart.data.datasets[1].backgroundColor = colors[1];
|
||||
|
||||
// Add data for each hour that is available
|
||||
for (var j in timestamps) {
|
||||
if ({}.hasOwnProperty.call(timestamps, j)) {
|
||||
var d,h;
|
||||
h = parseInt(timestamps[j]);
|
||||
// New style: Get Unix timestamps
|
||||
d = new Date(1000*h);
|
||||
|
||||
var sum = plotdata[j][0] + plotdata[j][1];
|
||||
var A = 0, AAAA = 0;
|
||||
if(sum > 0)
|
||||
{
|
||||
A = plotdata[j][0]/sum;
|
||||
AAAA = plotdata[j][1]/sum;
|
||||
}
|
||||
|
||||
queryTypeChart.data.labels.push(d);
|
||||
queryTypeChart.data.datasets[0].data.push(A);
|
||||
queryTypeChart.data.datasets[1].data.push(AAAA);
|
||||
}
|
||||
}
|
||||
$("#query-types .overlay").hide();
|
||||
queryTypeChart.update();
|
||||
}).done(function() {
|
||||
// Reload graph after 10 minutes
|
||||
failures = 0;
|
||||
setTimeout(updateQueryTypesOverTime, 600000);
|
||||
}).fail(function() {
|
||||
failures++;
|
||||
if(failures < 5)
|
||||
{
|
||||
// Try again after 1 minute only if this has not failed more
|
||||
// than five times in a row
|
||||
setTimeout(updateQueryTypesOverTime, 60000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function updateForwardedOverTime() {
|
||||
$.getJSON("api.php?overTimeDataForwards&getForwardDestinationNames", function(data) {
|
||||
|
||||
if("FTLnotrunning" in data)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// convert received objects to arrays
|
||||
data.over_time = objectToArray(data.over_time);
|
||||
var timestamps = data.over_time[0];
|
||||
var plotdata = data.over_time[1];
|
||||
var labels = [];
|
||||
var key, i, j;
|
||||
for (key in data.forward_destinations)
|
||||
{
|
||||
if (!{}.hasOwnProperty.call(data.forward_destinations, key)) continue;
|
||||
if(key.indexOf("|") > -1)
|
||||
{
|
||||
var idx = key.indexOf("|");
|
||||
key = key.substr(0, idx);
|
||||
}
|
||||
labels.push(key);
|
||||
}
|
||||
// Get colors from AdminLTE
|
||||
var colors = [];
|
||||
$.each($.AdminLTE.options.colors, function(key, value) { colors.push(value); });
|
||||
var v = [], c = [], k = [];
|
||||
|
||||
// Remove possibly already existing data
|
||||
forwardDestinationChart.data.labels = [];
|
||||
forwardDestinationChart.data.datasets[0].data = [];
|
||||
for (i = 1; i < forwardDestinationChart.data.datasets.length; i++)
|
||||
{
|
||||
forwardDestinationChart.data.datasets[i].data = [];
|
||||
}
|
||||
|
||||
// Collect values and colors, and labels
|
||||
forwardDestinationChart.data.datasets[0].backgroundColor = colors[0];
|
||||
forwardDestinationChart.data.datasets[0].pointRadius = 0;
|
||||
forwardDestinationChart.data.datasets[0].label = labels[0];
|
||||
|
||||
for (i = forwardDestinationChart.data.datasets.length; i < plotdata[0].length; i++)
|
||||
{
|
||||
forwardDestinationChart.data.datasets.push({data: [], backgroundColor: colors[i], pointRadius: 0, label: labels[i]});
|
||||
}
|
||||
|
||||
// Add data for each dataset that is available
|
||||
for (j in timestamps)
|
||||
{
|
||||
if (!{}.hasOwnProperty.call(timestamps, j)) continue;
|
||||
var sum = 0.0;
|
||||
for (key in plotdata[j])
|
||||
{
|
||||
if (!{}.hasOwnProperty.call(plotdata[j], key)) continue;
|
||||
sum += plotdata[j][key];
|
||||
}
|
||||
var dd = [];
|
||||
for (key in plotdata[j])
|
||||
{
|
||||
if (!{}.hasOwnProperty.call(plotdata[j], key)) continue;
|
||||
var singlepoint = plotdata[j][key];
|
||||
forwardDestinationChart.data.datasets[key].data.push(singlepoint/sum);
|
||||
}
|
||||
|
||||
var d = new Date(1000*parseInt(timestamps[j]));
|
||||
forwardDestinationChart.data.labels.push(d);
|
||||
}
|
||||
$("#forward-destinations .overlay").hide();
|
||||
forwardDestinationChart.update();
|
||||
}).done(function() {
|
||||
// Reload graph after 10 minutes
|
||||
failures = 0;
|
||||
setTimeout(updateForwardedOverTime, 600000);
|
||||
}).fail(function() {
|
||||
failures++;
|
||||
if(failures < 5)
|
||||
{
|
||||
// Try again after 1 minute only if this has not failed more
|
||||
// than five times in a row
|
||||
setTimeout(updateForwardedOverTime, 60000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -137,68 +246,59 @@ function escapeHtml(text) {
|
||||
|
||||
function updateTopClientsChart() {
|
||||
$.getJSON("api.php?summaryRaw&getQuerySources", function(data) {
|
||||
var clienttable = $("#client-frequency").find("tbody:last");
|
||||
var domain, percentage, domainname, domainip;
|
||||
for (domain in data.top_sources) {
|
||||
|
||||
if ({}.hasOwnProperty.call(data.top_sources, domain)){
|
||||
// Sanitize domain
|
||||
domain = escapeHtml(domain);
|
||||
if(domain.indexOf("|") > -1)
|
||||
if("FTLnotrunning" in data)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear tables before filling them with data
|
||||
$("#client-frequency td").parent().remove();
|
||||
var clienttable = $("#client-frequency").find("tbody:last");
|
||||
var client, percentage, clientname, clientip;
|
||||
for (client in data.top_sources) {
|
||||
|
||||
if ({}.hasOwnProperty.call(data.top_sources, client)){
|
||||
// Sanitize client
|
||||
client = escapeHtml(client);
|
||||
if(client.indexOf("|") > -1)
|
||||
{
|
||||
var idx = domain.indexOf("|");
|
||||
domainname = domain.substr(0, idx);
|
||||
domainip = domain.substr(idx+1, domain.length-idx);
|
||||
var idx = client.indexOf("|");
|
||||
clientname = client.substr(0, idx);
|
||||
clientip = client.substr(idx+1, client.length-idx);
|
||||
}
|
||||
else
|
||||
{
|
||||
domainname = domain;
|
||||
domainip = domain;
|
||||
clientname = client;
|
||||
clientip = client;
|
||||
}
|
||||
|
||||
var url = "<a href=\"queries.php?client="+domain+"\" title=\""+domainip+"\">"+domainname+"</a>";
|
||||
percentage = data.top_sources[domain] / data.dns_queries_today * 100;
|
||||
var url = "<a href=\"queries.php?client="+clientip+"\" title=\""+clientip+"\">"+clientname+"</a>";
|
||||
percentage = data.top_sources[client] / data.dns_queries_today * 100;
|
||||
clienttable.append("<tr> <td>" + url +
|
||||
"</td> <td>" + data.top_sources[domain] + "</td> <td> <div class=\"progress progress-sm\" title=\""+percentage.toFixed(1)+"%\"> <div class=\"progress-bar progress-bar-blue\" style=\"width: " +
|
||||
"</td> <td>" + data.top_sources[client] + "</td> <td> <div class=\"progress progress-sm\" title=\""+percentage.toFixed(1)+"% of " + data.dns_queries_today + "\"> <div class=\"progress-bar progress-bar-blue\" style=\"width: " +
|
||||
percentage + "%\"></div> </div> </td> </tr> ");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$("#client-frequency .overlay").remove();
|
||||
});
|
||||
}
|
||||
|
||||
function updateForwardDestinations() {
|
||||
$.getJSON("api.php?getForwardDestinations", function(data) {
|
||||
var colors = [];
|
||||
// Get colors from AdminLTE
|
||||
$.each($.AdminLTE.options.colors, function(key, value) { colors.push(value); });
|
||||
var v = [], c = [];
|
||||
// Collect values and colors, immediately push individual labels
|
||||
$.each(data, function(key , value) {
|
||||
v.push(value);
|
||||
c.push(colors.shift());
|
||||
if(key.indexOf("|") > -1)
|
||||
{
|
||||
var idx = key.indexOf("|");
|
||||
key = key.substr(0, idx)+" ("+key.substr(idx+1, key.length-idx)+")";
|
||||
}
|
||||
forwardDestinationChart.data.labels.push(key);
|
||||
});
|
||||
// Build a single dataset with the data to be pushed
|
||||
var dd = {data: v, backgroundColor: c};
|
||||
// and push it at once
|
||||
forwardDestinationChart.data.datasets.push(dd);
|
||||
$("#forward-destinations .overlay").remove();
|
||||
forwardDestinationChart.update();
|
||||
forwardDestinationChart.chart.config.options.cutoutPercentage=30;
|
||||
forwardDestinationChart.update();
|
||||
$("#client-frequency .overlay").hide();
|
||||
// Update top clients list data every ten seconds
|
||||
setTimeout(updateTopClientsChart, 10000);
|
||||
});
|
||||
}
|
||||
|
||||
function updateTopLists() {
|
||||
$.getJSON("api.php?summaryRaw&topItems", function(data) {
|
||||
|
||||
if("FTLnotrunning" in data)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear tables before filling them with data
|
||||
$("#domain-frequency td").parent().remove();
|
||||
$("#ad-frequency td").parent().remove();
|
||||
var domaintable = $("#domain-frequency").find("tbody:last");
|
||||
var adtable = $("#ad-frequency").find("tbody:last");
|
||||
var url, domain, percentage;
|
||||
@@ -206,17 +306,10 @@ function updateTopLists() {
|
||||
if ({}.hasOwnProperty.call(data.top_queries,domain)){
|
||||
// Sanitize domain
|
||||
domain = escapeHtml(domain);
|
||||
if(domain !== "pi.hole")
|
||||
{
|
||||
url = "<a href=\"queries.php?domain="+domain+"\">"+domain+"</a>";
|
||||
}
|
||||
else
|
||||
{
|
||||
url = domain;
|
||||
}
|
||||
url = "<a href=\"queries.php?domain="+domain+"\">"+domain+"</a>";
|
||||
percentage = data.top_queries[domain] / data.dns_queries_today * 100;
|
||||
domaintable.append("<tr> <td>" + url +
|
||||
"</td> <td>" + data.top_queries[domain] + "</td> <td> <div class=\"progress progress-sm\" title=\""+percentage.toFixed(1)+"%\"> <div class=\"progress-bar progress-bar-green\" style=\"width: " +
|
||||
"</td> <td>" + data.top_queries[domain] + "</td> <td> <div class=\"progress progress-sm\" title=\""+percentage.toFixed(1)+"% of " + data.dns_queries_today + "\"> <div class=\"progress-bar progress-bar-green\" style=\"width: " +
|
||||
percentage + "%\"></div> </div> </td> </tr> ");
|
||||
}
|
||||
}
|
||||
@@ -234,13 +327,94 @@ function updateTopLists() {
|
||||
url = "<a href=\"queries.php?domain="+domain+"\">"+domain+"</a>";
|
||||
percentage = data.top_ads[domain] / data.ads_blocked_today * 100;
|
||||
adtable.append("<tr> <td>" + url +
|
||||
"</td> <td>" + data.top_ads[domain] + "</td> <td> <div class=\"progress progress-sm\" title=\""+percentage.toFixed(1)+"%\"> <div class=\"progress-bar progress-bar-yellow\" style=\"width: " +
|
||||
"</td> <td>" + data.top_ads[domain] + "</td> <td> <div class=\"progress progress-sm\" title=\""+percentage.toFixed(1)+"% of " + data.ads_blocked_today + "\"> <div class=\"progress-bar progress-bar-yellow\" style=\"width: " +
|
||||
percentage + "%\"></div> </div> </td> </tr> ");
|
||||
}
|
||||
}
|
||||
|
||||
$("#domain-frequency .overlay").remove();
|
||||
$("#ad-frequency .overlay").remove();
|
||||
// Remove table if there are no results (e.g. privacy mode enabled)
|
||||
if(jQuery.isEmptyObject(data.top_ads))
|
||||
{
|
||||
$("#ad-frequency").parent().remove();
|
||||
}
|
||||
|
||||
$("#domain-frequency .overlay").hide();
|
||||
$("#ad-frequency .overlay").hide();
|
||||
// Update top lists data every 10 seconds
|
||||
setTimeout(updateTopLists, 10000);
|
||||
});
|
||||
}
|
||||
|
||||
var FTLoffline = false;
|
||||
function updateSummaryData(runOnce) {
|
||||
var setTimer = function(timeInSeconds) {
|
||||
if (!runOnce) {
|
||||
setTimeout(updateSummaryData, timeInSeconds * 1000);
|
||||
}
|
||||
};
|
||||
$.getJSON("api.php?summary", function LoadSummaryData(data) {
|
||||
|
||||
updateSessionTimer();
|
||||
|
||||
if("FTLnotrunning" in data)
|
||||
{
|
||||
data["ads_blocked_today"] = "Lost";
|
||||
data["dns_queries_today"] = "connection";
|
||||
data["ads_percentage_today"] = "to";
|
||||
data["domains_being_blocked"] = "API";
|
||||
// Adjust text
|
||||
$("#temperature").html("<i class=\"fa fa-circle\" style=\"color:#FF0000\"></i> FTL offline");
|
||||
// Show spinner
|
||||
$("#queries-over-time .overlay").show();
|
||||
$("#forward-destinations .overlay").show();
|
||||
$("#query-types .overlay").show();
|
||||
$("#client-frequency .overlay").show();
|
||||
$("#domain-frequency .overlay").show();
|
||||
$("#ad-frequency .overlay").show();
|
||||
|
||||
FTLoffline = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(FTLoffline)
|
||||
{
|
||||
// FTL was previously offline
|
||||
FTLoffline = false;
|
||||
$("#temperature").text(" ");
|
||||
updateQueriesOverTime();
|
||||
updateForwardedOverTime();
|
||||
updateQueryTypesOverTime();
|
||||
updateTopClientsChart();
|
||||
updateTopLists();
|
||||
}
|
||||
}
|
||||
|
||||
["ads_blocked_today", "dns_queries_today", "ads_percentage_today"].forEach(function(today) {
|
||||
var todayElement = $("h3#" + today);
|
||||
todayElement.text() !== data[today] &&
|
||||
todayElement.text() !== data[today] + "%" &&
|
||||
todayElement.addClass("glow");
|
||||
});
|
||||
|
||||
window.setTimeout(function() {
|
||||
["ads_blocked_today", "dns_queries_today", "domains_being_blocked", "ads_percentage_today"].forEach(function(header, idx) {
|
||||
var textData = (idx === 3 && data[header] !== "to") ? data[header] + "%" : data[header];
|
||||
$("h3#" + header).text(textData);
|
||||
});
|
||||
$("h3.statistic.glow").removeClass("glow");
|
||||
}, 500);
|
||||
|
||||
}).done(function() {
|
||||
if(!FTLoffline)
|
||||
{
|
||||
setTimer(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
setTimer(10);
|
||||
}
|
||||
}).fail(function() {
|
||||
setTimer(300);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -264,6 +438,10 @@ $(document).ready(function() {
|
||||
}
|
||||
};
|
||||
|
||||
// Pull in data via AJAX
|
||||
|
||||
updateSummaryData();
|
||||
|
||||
var ctx = document.getElementById("queryOverTimeChart").getContext("2d");
|
||||
timeLineChart = new Chart(ctx, {
|
||||
type: "line",
|
||||
@@ -306,8 +484,8 @@ $(document).ready(function() {
|
||||
var time = label.match(/(\d?\d):?(\d?\d?)/);
|
||||
var h = parseInt(time[1], 10);
|
||||
var m = parseInt(time[2], 10) || 0;
|
||||
var from = padNumber(h)+":"+padNumber(m)+":00";
|
||||
var to = padNumber(h)+":"+padNumber(m+9)+":59";
|
||||
var from = padNumber(h)+":"+padNumber(m-5)+":00";
|
||||
var to = padNumber(h)+":"+padNumber(m+4)+":59";
|
||||
return "Queries from "+from+" to "+to;
|
||||
},
|
||||
label: function(tooltipItems, data) {
|
||||
@@ -355,54 +533,101 @@ $(document).ready(function() {
|
||||
|
||||
// Pull in data via AJAX
|
||||
|
||||
updateSummaryData();
|
||||
|
||||
updateQueriesOverTime();
|
||||
|
||||
// Create / load "Query Types" only if authorized
|
||||
if(document.getElementById("queryTypeChart"))
|
||||
{
|
||||
ctx = document.getElementById("queryTypeChart").getContext("2d");
|
||||
queryTypeChart = new Chart(ctx, {
|
||||
type: "doughnut",
|
||||
data: {
|
||||
labels: [],
|
||||
datasets: [{ data: [] }]
|
||||
},
|
||||
options: {
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
animation: {
|
||||
duration: 2000
|
||||
},
|
||||
cutoutPercentage: 0
|
||||
}
|
||||
});
|
||||
updateQueryTypes();
|
||||
}
|
||||
|
||||
// Create / load "Forward Destinations" only if authorized
|
||||
// Create / load "Forward Destinations over Time" only if authorized
|
||||
if(document.getElementById("forwardDestinationChart"))
|
||||
{
|
||||
ctx = document.getElementById("forwardDestinationChart").getContext("2d");
|
||||
forwardDestinationChart = new Chart(ctx, {
|
||||
type: "doughnut",
|
||||
type: "line",
|
||||
data: {
|
||||
labels: [],
|
||||
datasets: [{ data: [] }]
|
||||
},
|
||||
options: {
|
||||
legend: {
|
||||
display: false
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: "time",
|
||||
time: {
|
||||
unit: "hour",
|
||||
displayFormats: {
|
||||
hour: "HH:mm"
|
||||
},
|
||||
tooltipFormat: "HH:mm"
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
mix: 0.0,
|
||||
max: 1.0,
|
||||
beginAtZero: true,
|
||||
callback: function(value, index, values) {
|
||||
return Math.round(value*100) + " %";
|
||||
}
|
||||
},
|
||||
stacked: true
|
||||
}]
|
||||
},
|
||||
animation: {
|
||||
duration: 2000
|
||||
},
|
||||
cutoutPercentage: 0
|
||||
maintainAspectRatio: true
|
||||
}
|
||||
});
|
||||
updateForwardDestinations();
|
||||
|
||||
// Pull in data via AJAX
|
||||
updateForwardedOverTime();
|
||||
}
|
||||
|
||||
// Create / load "Query Types over Time" only if authorized
|
||||
if(document.getElementById("queryTypeChart"))
|
||||
{
|
||||
ctx = document.getElementById("queryTypeChart").getContext("2d");
|
||||
queryTypeChart = new Chart(ctx, {
|
||||
type: "line",
|
||||
data: {
|
||||
labels: [],
|
||||
datasets: [
|
||||
{
|
||||
label: "A: IPv4 queries",
|
||||
pointRadius: 0,
|
||||
data: []
|
||||
},
|
||||
{
|
||||
label: "AAAA: IPv6 queries",
|
||||
pointRadius: 0,
|
||||
data: []
|
||||
}
|
||||
]
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: "time",
|
||||
time: {
|
||||
unit: "hour",
|
||||
displayFormats: {
|
||||
hour: "HH:mm"
|
||||
},
|
||||
tooltipFormat: "HH:mm"
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
mix: 0.0,
|
||||
max: 1.0,
|
||||
beginAtZero: true,
|
||||
callback: function(value, index, values) {
|
||||
return Math.round(value*100) + " %";
|
||||
}
|
||||
},
|
||||
stacked: true
|
||||
}]
|
||||
},
|
||||
maintainAspectRatio: true
|
||||
}
|
||||
});
|
||||
|
||||
// Pull in data via AJAX
|
||||
updateQueryTypesOverTime();
|
||||
}
|
||||
|
||||
// Create / load "Top Domains" and "Top Advertisers" only if authorized
|
||||
@@ -429,10 +654,8 @@ $(document).ready(function() {
|
||||
var label = timeLineChart.data.labels[clickedElementindex];
|
||||
|
||||
//get value by index
|
||||
//var value = timeLineChart.data.datasets[0].data[clickedElementindex];
|
||||
var time = new Date(label);
|
||||
var from = time.getHours()+":"+time.getMinutes();
|
||||
var until = time.getHours()+":"+padNumber(parseInt(time.getMinutes()+9),2);
|
||||
var from = label/1000 - 300;
|
||||
var until = label/1000 + 300;
|
||||
window.location.href = "queries.php?from="+from+"&until="+until;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -79,11 +79,17 @@ function add(domain,list) {
|
||||
});
|
||||
}
|
||||
function handleAjaxError( xhr, textStatus, error ) {
|
||||
if ( textStatus === "timeout" ) {
|
||||
if ( textStatus === "timeout" )
|
||||
{
|
||||
alert( "The server took too long to send the data." );
|
||||
}
|
||||
else {
|
||||
alert( "An error occured while loading the data. Presumably your log is too large to be processed." );
|
||||
else if(xhr.responseText.indexOf("Connection refused") >= 0)
|
||||
{
|
||||
alert( "An error occured while loading the data: Connection refused. Is FTL running?" );
|
||||
}
|
||||
else
|
||||
{
|
||||
alert( "An unknown error occured while loading the data.\n"+xhr.responseText );
|
||||
}
|
||||
$("#all-queries_processing").hide();
|
||||
tableApi.clear();
|
||||
@@ -99,34 +105,58 @@ $(document).ready(function() {
|
||||
|
||||
var APIstring = "api.php?getAllQueries";
|
||||
|
||||
if("from" in GETDict)
|
||||
if("from" in GETDict && "until" in GETDict)
|
||||
{
|
||||
APIstring += "&from="+GETDict["from"];
|
||||
}
|
||||
|
||||
if("until" in GETDict)
|
||||
{
|
||||
APIstring += "&until="+GETDict["until"];
|
||||
}
|
||||
|
||||
$.fn.dataTable.moment("YYY-MM-DD z HH:MM:SS");
|
||||
else if("client" in GETDict)
|
||||
{
|
||||
APIstring += "&client="+GETDict["client"];
|
||||
}
|
||||
else if("domain" in GETDict)
|
||||
{
|
||||
APIstring += "&domain="+GETDict["domain"];
|
||||
}
|
||||
else if(!("all" in GETDict))
|
||||
{
|
||||
var timestamp = Math.floor(Date.now() / 1000);
|
||||
APIstring += "&from="+(timestamp - 600);
|
||||
APIstring += "&until="+(timestamp + 100);
|
||||
}
|
||||
|
||||
tableApi = $("#all-queries").DataTable( {
|
||||
"rowCallback": function( row, data, index ){
|
||||
status = data[4];
|
||||
if (status === "Pi-holed (exact)") {
|
||||
if (data[4] === "1")
|
||||
{
|
||||
$(row).css("color","red");
|
||||
$("td:eq(4)", row).html( "Pi-holed" );
|
||||
$("td:eq(5)", row).html( "<button style=\"color:green; white-space: nowrap;\"><i class=\"fa fa-pencil-square-o\"></i> Whitelist</button>" );
|
||||
}
|
||||
else if (status === "Pi-holed (wildcard)") {
|
||||
$(row).css("color","red");
|
||||
$("td:eq(5)", row).html( "" );
|
||||
}
|
||||
else{
|
||||
else if (data[4] === "2")
|
||||
{
|
||||
$(row).css("color","green");
|
||||
$("td:eq(4)", row).html( "OK (forwarded)" );
|
||||
$("td:eq(5)", row).html( "<button style=\"color:red; white-space: nowrap;\"><i class=\"fa fa-ban\"></i> Blacklist</button>" );
|
||||
}
|
||||
else if (data[4] === "3")
|
||||
{
|
||||
$(row).css("color","green");
|
||||
$("td:eq(4)", row).html( "OK (cached)" );
|
||||
$("td:eq(5)", row).html( "<button style=\"color:red; white-space: nowrap;\"><i class=\"fa fa-ban\"></i> Blacklist</button>" );
|
||||
|
||||
}
|
||||
else if (data[4] === "4")
|
||||
{
|
||||
$(row).css("color","red");
|
||||
$("td:eq(4)", row).html( "Pi-holed (wildcard)" );
|
||||
$("td:eq(5)", row).html( "" );
|
||||
}
|
||||
else
|
||||
{
|
||||
$("td:eq(4)", row).html( "Unknown" );
|
||||
$("td:eq(5)", row).html( "" );
|
||||
}
|
||||
},
|
||||
dom: "<'row'<'col-sm-12'f>>" +
|
||||
"<'row'<'col-sm-4'l><'col-sm-8'p>>" +
|
||||
@@ -137,7 +167,7 @@ $(document).ready(function() {
|
||||
"processing": true,
|
||||
"order" : [[0, "desc"]],
|
||||
"columns": [
|
||||
{ "width" : "20%" },
|
||||
{ "width" : "20%", "render": function (data, type, full, meta) { if(type === "display"){return moment.unix(data).format("Y-MM-DD HH:mm:ss z");}else{return data;} }},
|
||||
{ "width" : "10%" },
|
||||
{ "width" : "40%" },
|
||||
{ "width" : "10%" },
|
||||
@@ -153,8 +183,7 @@ $(document).ready(function() {
|
||||
});
|
||||
$("#all-queries tbody").on( "click", "button", function () {
|
||||
var data = tableApi.row( $(this).parents("tr") ).data();
|
||||
status = data[4];
|
||||
if (status.substr(0,2) === "Pi")
|
||||
if (data[4] === "1")
|
||||
{
|
||||
add(data[2],"white");
|
||||
}
|
||||
@@ -163,18 +192,6 @@ $(document).ready(function() {
|
||||
add(data[2],"black");
|
||||
}
|
||||
} );
|
||||
|
||||
if("client" in GETDict)
|
||||
{
|
||||
// Search in third column (zero indexed)
|
||||
// Use regular expression to only show exact matches, i.e.
|
||||
// don't show 192.168.0.100 when searching for 192.168.0.1
|
||||
// true = use regex, false = don't use smart search
|
||||
tableApi.column(3).search("^"+escapeRegex(GETDict["client"])+"$",true,false);
|
||||
}
|
||||
if("domain" in GETDict)
|
||||
{
|
||||
// Search in second column (zero indexed)
|
||||
tableApi.column(2).search("^"+escapeRegex(GETDict["domain"])+"$",true,false);
|
||||
}
|
||||
} );
|
||||
|
||||
|
||||
|
||||
@@ -134,3 +134,14 @@ $(document).ready(function(){
|
||||
$("[data-toggle=\"tooltip\"]").tooltip({"html": true, container : "body"});
|
||||
});
|
||||
|
||||
// Handle list deletion
|
||||
$("button[id^='adlist-btn-']").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
var status = $(this).siblings("input[name^='adlist-del-']").is(":checked");
|
||||
var textType = status ? "none" : "line-through";
|
||||
|
||||
$(this).siblings("input[name^='adlist-del-']").prop("checked", !status);
|
||||
$(this).siblings("input[name^='adlist-enable-']").prop("disabled", !status);
|
||||
$(this).siblings("a").css("text-decoration", textType);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||
* Network-wide ad blocking via your own hardware.
|
||||
*
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
var offset, timer, pre, scrolling = true;
|
||||
|
||||
// Check every 200msec for fresh data
|
||||
var interval = 200;
|
||||
|
||||
// Function that asks the API for new data
|
||||
function reloadData(){
|
||||
clearTimeout(timer);
|
||||
$.getJSON("scripts/pi-hole/php/tailLog.php?FTL&offset="+offset, function (data)
|
||||
{
|
||||
offset = data["offset"];
|
||||
pre.append(data["lines"]);
|
||||
});
|
||||
|
||||
if(scrolling)
|
||||
{
|
||||
window.scrollTo(0,document.body.scrollHeight);
|
||||
}
|
||||
timer = setTimeout(reloadData, interval);
|
||||
}
|
||||
|
||||
$(function(){
|
||||
// Get offset at first loading of page
|
||||
$.getJSON("scripts/pi-hole/php/tailLog.php?FTL", function (data)
|
||||
{
|
||||
offset = data["offset"];
|
||||
});
|
||||
pre = $("#output");
|
||||
// Trigger function that looks for new data
|
||||
reloadData();
|
||||
});
|
||||
|
||||
$("#chk1").click(function() {
|
||||
$("#chk2").prop("checked",this.checked);
|
||||
scrolling = this.checked;
|
||||
});
|
||||
$("#chk2").click(function() {
|
||||
$("#chk1").prop("checked",this.checked);
|
||||
scrolling = this.checked;
|
||||
});
|
||||
@@ -12,7 +12,7 @@ var interval = 200;
|
||||
// Function that asks the API for new data
|
||||
function reloadData(){
|
||||
clearTimeout(timer);
|
||||
$.getJSON("api.php?tailLog="+offset, function (data)
|
||||
$.getJSON("scripts/pi-hole/php/tailLog.php?offset="+offset, function (data)
|
||||
{
|
||||
offset = data["offset"];
|
||||
pre.append(data["lines"]);
|
||||
@@ -27,7 +27,7 @@ function reloadData(){
|
||||
|
||||
$(function(){
|
||||
// Get offset at first loading of page
|
||||
$.getJSON("api.php?tailLog", function (data)
|
||||
$.getJSON("scripts/pi-hole/php/tailLog.php", function (data)
|
||||
{
|
||||
offset = data["offset"];
|
||||
});
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
/* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||
* Network-wide ad blocking via your own hardware.
|
||||
*
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
|
||||
function testFTL()
|
||||
{
|
||||
$ret = shell_exec("pidof pihole-FTL");
|
||||
return intval($ret);
|
||||
}
|
||||
|
||||
function connectFTL($address, $port=4711, $quiet=true)
|
||||
{
|
||||
$timeout = 3;
|
||||
|
||||
if(!$quiet)
|
||||
{
|
||||
echo "Attempting to connect to '$address' on port '$port'...\n";
|
||||
}
|
||||
|
||||
if($address == "127.0.0.1")
|
||||
{
|
||||
// Read port
|
||||
$portfile = file_get_contents("/var/run/pihole-FTL.port");
|
||||
if(is_numeric($portfile))
|
||||
$port = intval($portfile);
|
||||
}
|
||||
|
||||
// Create a TCP/IP socket
|
||||
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)
|
||||
or die("socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n");
|
||||
|
||||
socket_set_nonblock($socket) or die("Unable to set nonblock on socket\n");
|
||||
|
||||
$time = time();
|
||||
while (!@socket_connect($socket, $address, $port))
|
||||
{
|
||||
$err = socket_last_error($socket);
|
||||
if ($err == 115 || $err == 114)
|
||||
{
|
||||
if ((time() - $time) >= $timeout)
|
||||
{
|
||||
socket_close($socket);
|
||||
die("Connection timed out.\n");
|
||||
}
|
||||
// Wait for 1 millisecond
|
||||
usleep(1000);
|
||||
continue;
|
||||
}
|
||||
die(socket_strerror($err) . "\n");
|
||||
}
|
||||
|
||||
socket_set_block($socket) or die("Unable to set block on socket\n");
|
||||
|
||||
// Set timeout to 3 seconds
|
||||
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, ['sec'=>$timeout, 'usec'=>0]);
|
||||
socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, ['sec'=>$timeout, 'usec'=>0]);
|
||||
|
||||
if(!$quiet)
|
||||
{
|
||||
echo "Success!\n\n";
|
||||
}
|
||||
|
||||
return $socket;
|
||||
}
|
||||
function sendRequestFTL($requestin, $quiet=true)
|
||||
{
|
||||
global $socket;
|
||||
|
||||
$request = ">".$requestin;
|
||||
if(!$quiet)
|
||||
{
|
||||
echo "Sending request (".$request.")...\n";
|
||||
}
|
||||
|
||||
socket_write($socket, $request, strlen($request)) or die("Could not send data to server\n");
|
||||
if(!$quiet)
|
||||
{
|
||||
echo "OK.\n";
|
||||
}
|
||||
}
|
||||
|
||||
function getResponseFTL($quiet=true)
|
||||
{
|
||||
global $socket;
|
||||
if(!$quiet)
|
||||
{
|
||||
echo "Reading response:\n";
|
||||
}
|
||||
|
||||
$response = [];
|
||||
|
||||
while(true)
|
||||
{
|
||||
$out = socket_read($socket, 2048, PHP_NORMAL_READ);
|
||||
if(!$quiet)
|
||||
{
|
||||
echo $out;
|
||||
}
|
||||
if(strrpos($out,"---EOM---") !== false)
|
||||
{
|
||||
break;
|
||||
}
|
||||
$out = rtrim($out);
|
||||
if(strlen($out) > 0)
|
||||
{
|
||||
$response[] = $out;
|
||||
}
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
function disconnectFTL($quiet=true)
|
||||
{
|
||||
global $socket;
|
||||
if(!$quiet)
|
||||
{
|
||||
echo "Closing socket...";
|
||||
}
|
||||
|
||||
socket_close($socket);
|
||||
|
||||
if(!$quiet)
|
||||
{
|
||||
echo "OK.\n\n";
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -5,6 +5,18 @@ ob_implicit_flush(true);
|
||||
header('Content-Type: text/event-stream');
|
||||
header('Cache-Control: no-cache');
|
||||
|
||||
require "password.php";
|
||||
require "auth.php";
|
||||
|
||||
if(!$auth) {
|
||||
die("Unauthorized");
|
||||
}
|
||||
|
||||
check_cors();
|
||||
|
||||
$token = isset($_GET["token"]) ? $_GET["token"] : "";
|
||||
check_csrf($token);
|
||||
|
||||
function echoEvent($datatext) {
|
||||
if(!isset($_GET["IE"]))
|
||||
echo "data: ".implode("\ndata: ", explode("\n", $datatext))."\n\n";
|
||||
|
||||
@@ -62,10 +62,25 @@
|
||||
else {
|
||||
$webVersion = exec("git describe --tags --abbrev=0");
|
||||
}
|
||||
|
||||
$FTLVersion = exec("pihole-FTL version");
|
||||
?>
|
||||
<style type="text/css">
|
||||
@-webkit-keyframes Pulse{
|
||||
from {color:#630030;-webkit-text-shadow:0 0 9px #333;}
|
||||
50% {color:#e33100;-webkit-text-shadow:0 0 32px #e33100;}
|
||||
to {color:#630030;-webkit-text-shadow:0 0 9px #333;}
|
||||
}
|
||||
a.lookatme {
|
||||
-webkit-animation-name: Pulse;
|
||||
-webkit-animation-duration: 2s;
|
||||
-webkit-animation-iteration-count: infinite;
|
||||
}
|
||||
</style>
|
||||
<div class="pull-right hidden-xs <?php if(isset($piholeCommit) || isset($webCommit)) { ?>hidden-md<?php } ?>">
|
||||
<b>Pi-hole Version </b> <span id="piholeVersion"><?php echo $piholeVersion; ?></span><?php if(isset($piholeCommit)) { echo " (".$piholeBranch.", ".$piholeCommit.")"; } ?>
|
||||
<b>Web Interface Version </b> <span id="webVersion"><?php echo $webVersion; ?></span><?php if(isset($webCommit)) { echo " (".$webBranch.", ".$webCommit.")"; } ?>
|
||||
<b>FTL Version </b> <span id="FTLVersion"><?php echo $FTLVersion; ?></span>
|
||||
</div>
|
||||
<div><a href="https://github.com/pi-hole"><i class="fa fa-github"></i></a> <strong><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3J2L3Z4DHW9UY">Donate</a></strong> if you found this useful.</div>
|
||||
</footer>
|
||||
|
||||
@@ -12,6 +12,12 @@
|
||||
|
||||
check_cors();
|
||||
|
||||
// Generate CSRF token
|
||||
if(empty($_SESSION['token'])) {
|
||||
$_SESSION['token'] = base64_encode(openssl_random_pseudo_bytes(32));
|
||||
}
|
||||
$token = $_SESSION['token'];
|
||||
|
||||
// Try to get temperature value from different places (OS dependent)
|
||||
if(file_exists("/sys/class/thermal/thermal_zone0/temp"))
|
||||
{
|
||||
@@ -139,9 +145,22 @@
|
||||
$boxedlayout = false;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
function pidofFTL()
|
||||
{
|
||||
return shell_exec("pidof pihole-FTL");
|
||||
}
|
||||
$FTLpid = intval(pidofFTL());
|
||||
$FTL = ($FTLpid !== 0 ? true : false);
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<!-- Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||
* Network-wide ad blocking via your own hardware.
|
||||
*
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. -->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
@@ -188,6 +207,11 @@
|
||||
<p>To enable Javascript click <a href="http://www.enable-javascript.com/" target="_blank">here</a></p><label for="js-hide">Close</label></div>
|
||||
</div>
|
||||
<!-- /JS Warning -->
|
||||
<?php
|
||||
if($auth) {
|
||||
echo "<div id='token' hidden>$token</div>";
|
||||
}
|
||||
?>
|
||||
<script src="scripts/pi-hole/js/header.js"></script>
|
||||
<!-- Send token to JS -->
|
||||
<div id="token" hidden><?php if($auth) echo $token; ?></div>
|
||||
@@ -197,9 +221,9 @@
|
||||
<!-- Logo -->
|
||||
<a href="http://pi-hole.net" class="logo">
|
||||
<!-- mini logo for sidebar mini 50x50 pixels -->
|
||||
<span class="logo-mini"><b>P</b>H</span>
|
||||
<span class="logo-mini">P<b>h</b></span>
|
||||
<!-- logo for regular state and mobile devices -->
|
||||
<span class="logo-lg"><b>Pi</b>-hole</span>
|
||||
<span class="logo-lg">Pi-<b>hole</b></span>
|
||||
</a>
|
||||
<!-- Header Navbar: style can be found in header.less -->
|
||||
<nav class="navbar navbar-static-top" role="navigation">
|
||||
@@ -273,7 +297,7 @@
|
||||
</div>
|
||||
<div class="pull-left info">
|
||||
<p>Status</p>
|
||||
<?php
|
||||
<?php
|
||||
$pistatus = exec('sudo pihole status web');
|
||||
if ($pistatus == "1") {
|
||||
echo '<a id="status"><i class="fa fa-circle" style="color:#7FFF00"></i> Active</a>';
|
||||
@@ -286,29 +310,36 @@
|
||||
}
|
||||
|
||||
// CPU Temp
|
||||
if ($celsius >= -273.15) {
|
||||
echo "<a id=\"temperature\"><i class=\"fa fa-fire\" style=\"color:";
|
||||
if ($celsius > 60) {
|
||||
echo "#FF0000";
|
||||
if($FTL)
|
||||
{
|
||||
if ($celsius >= -273.15) {
|
||||
echo "<a id=\"temperature\"><i class=\"fa fa-fire\" style=\"color:";
|
||||
if ($celsius > 60) {
|
||||
echo "#FF0000";
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "#3366FF";
|
||||
}
|
||||
echo "\"></i> Temp: ";
|
||||
if($temperatureunit === "F")
|
||||
{
|
||||
echo round($fahrenheit,1) . " °F";
|
||||
}
|
||||
elseif($temperatureunit === "K")
|
||||
{
|
||||
echo round($kelvin,1) . " K";
|
||||
}
|
||||
else
|
||||
{
|
||||
echo round($celsius,1) . " °C";
|
||||
}
|
||||
echo "</a>";
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "#3366FF";
|
||||
}
|
||||
echo "\"></i> Temp: ";
|
||||
if($temperatureunit === "F")
|
||||
{
|
||||
echo round($fahrenheit,1) . "°F";
|
||||
}
|
||||
elseif($temperatureunit === "K")
|
||||
{
|
||||
echo round($kelvin,1) . "K";
|
||||
}
|
||||
else
|
||||
{
|
||||
echo round($celsius,1) . "°C";
|
||||
}
|
||||
echo "</a>";
|
||||
}
|
||||
else
|
||||
{
|
||||
echo '<a id=\"temperature\"><i class="fa fa-circle" style="color:#FF0000"></i> FTL offline</a>';
|
||||
}
|
||||
?>
|
||||
<br/>
|
||||
@@ -335,7 +366,7 @@
|
||||
}
|
||||
if($memory_usage > 0.0)
|
||||
{
|
||||
echo "\"></i> Memory usage: " . sprintf("%.1f",100.0*$memory_usage) . "%</a>";
|
||||
echo "\"></i> Memory usage: " . sprintf("%.1f",100.0*$memory_usage) . " %</a>";
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -454,6 +485,12 @@
|
||||
<i class="fa fa-list-ul"></i> <span>Tail pihole.log</span>
|
||||
</a>
|
||||
</li>
|
||||
<!-- Tail pihole-FTL.log -->
|
||||
<li<?php if($scriptname === "taillog-FTL.php"){ ?> class="active"<?php } ?>>
|
||||
<a href="taillog-FTL.php">
|
||||
<i class="fa fa-list-ul"></i> <span>Tail pihole-FTL.log</span>
|
||||
</a>
|
||||
</li>
|
||||
<!-- Generate debug log -->
|
||||
<li<?php if($scriptname === "debug.php"){ ?> class="active"<?php } ?>>
|
||||
<a href="debug.php">
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<div class="panel-heading">
|
||||
<div style="text-align: center;"><img src="img/logo.svg" width="<?php if ($boxedlayout) { ?>50%<?php } else { ?>30%<?php } ?>"></div><br>
|
||||
|
||||
<div class="panel-title text-center"><span class="logo-lg" style="font-size: 25px;"><b>Pi</b>-hole</span></div>
|
||||
<div class="panel-title text-center"><span class="logo-lg" style="font-size: 25px;">Pi-<b>hole</b></span></div>
|
||||
<p class="login-box-msg">Sign in to start your session</p>
|
||||
<div id="cookieInfo" class="panel-title text-center" style="color:#F00; font-size: 150%" hidden>Verify that cookies are allowed for <tt><?php echo $_SERVER['HTTP_HOST']; ?></tt></div>
|
||||
<?php if ($wrongpassword) { ?>
|
||||
@@ -25,7 +25,7 @@
|
||||
<form action="" id="loginform" method="post">
|
||||
<div class="form-group has-feedback <?php if ($wrongpassword) { ?>has-error<?php } ?> ">
|
||||
<input type="password" id="loginpw" name="pw" class="form-control" placeholder="Password" autofocus>
|
||||
<span class="glyphicon glyphicon-lock form-control-feedback"></span>
|
||||
<span class="fa fa-key form-control-feedback"></span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-8">
|
||||
@@ -53,11 +53,10 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
After installing Pi-Hole for the first time, a password is generated and displayed to the user. The
|
||||
password cannot be retrived later on, but it is possible to set a new password (or explicitly disable
|
||||
the
|
||||
password by setting an empty password) using the command
|
||||
<pre>sudo pihole -a -p newpassword</pre>
|
||||
After installing Pi-hole for the first time, a password is generated and displayed to the user. The
|
||||
password cannot be retrieved later on, but it is possible to set a new password (or explicitly disable
|
||||
the password by setting an empty password) using the command
|
||||
<pre>sudo pihole -a -p</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -24,15 +24,14 @@ function validIP($address){
|
||||
// Check for existance of variable
|
||||
// and test it only if it exists
|
||||
function istrue(&$argument) {
|
||||
$ret = false;
|
||||
if(isset($argument))
|
||||
{
|
||||
if($argument)
|
||||
{
|
||||
$ret = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Credit: http://stackoverflow.com/a/4694816/2087442
|
||||
@@ -44,6 +43,15 @@ function validDomain($domain_name)
|
||||
return ( $validChars && $lengthCheck && $labelLengthCheck ); //length of each label
|
||||
}
|
||||
|
||||
function validDomainWildcard($domain_name)
|
||||
{
|
||||
// There has to be either no or at most one "*" at the beginning of a line
|
||||
$validChars = preg_match("/^((\*)?[_a-z\d](-*[_a-z\d])*)(\.([_a-z\d](-*[a-z\d])*))*(\.([a-z\d])*)*$/i", $domain_name);
|
||||
$lengthCheck = preg_match("/^.{1,253}$/", $domain_name);
|
||||
$labelLengthCheck = preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name);
|
||||
return ( $validChars && $lengthCheck && $labelLengthCheck ); //length of each label
|
||||
}
|
||||
|
||||
function validMAC($mac_addr)
|
||||
{
|
||||
// Accepted input format: 00:01:02:1A:5F:FF (characters may be lower case)
|
||||
@@ -86,26 +94,74 @@ function readStaticLeasesFile()
|
||||
return true;
|
||||
}
|
||||
|
||||
function isequal(&$argument, &$compareto) {
|
||||
if(isset($argument))
|
||||
{
|
||||
if($argument === $compareto)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isinserverlist($addr) {
|
||||
global $DNSserverslist;
|
||||
foreach ($DNSserverslist as $key => $value) {
|
||||
if (isequal($value['v4_1'],$addr) || isequal($value['v4_2'],$addr))
|
||||
return true;
|
||||
if (isequal($value['v6_1'],$addr) || isequal($value['v6_2'],$addr))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
$DNSserverslist = [
|
||||
"8.8.8.8" => "Google (Primary)",
|
||||
"208.67.222.222" => "OpenDNS (Primary)",
|
||||
"4.2.2.1" => "Level3 (Primary)",
|
||||
"199.85.126.10" => "Norton (Primary)",
|
||||
"8.26.56.26" => "Comodo (Primary)",
|
||||
"84.200.69.80" => "DNS.WATCH (Primary)",
|
||||
"8.8.4.4" => "Google (Secondary)",
|
||||
"208.67.220.220" => "OpenDNS (Secondary)",
|
||||
"4.2.2.2" => "Level3 (Secondary)",
|
||||
"199.85.127.10" => "Norton (Secondary)",
|
||||
"8.20.247.20" => "Comodo (Secondary)",
|
||||
"84.200.70.40" => "DNS.WATCH (Secondary)",
|
||||
"Google" => ["v4_1" => "8.8.8.8","v4_2" => "8.8.4.4", "v6_1" => "2001:4860:4860:0:0:0:0:8888", "v6_2" => "2001:4860:4860:0:0:0:0:8844"],
|
||||
"OpenDNS" => ["v4_1" => "208.67.222.222", "v4_2" => "208.67.220.220", "v6_1" => "2620:0:ccc::2", "v6_2" => "2620:0:ccd::2"],
|
||||
"Level3" => ["v4_1" => "4.2.2.1", "v4_2" => "4.2.2.2"],
|
||||
"Norton" => ["v4_1" => "199.85.126.10", "v4_2" => "199.85.127.10"],
|
||||
"Comodo" => ["v4_1" => "8.26.56.26", "v4_2" => "8.20.247.20"],
|
||||
"DNS.WATCH" => ["v4_1" => "84.200.69.80", "v4_2" => "84.200.70.40", "v6_1" => "2001:1608:10:25:0:0:1c04:b12f", "v6_2" => "2001:1608:10:25:0:0:9249:d69b"]
|
||||
];
|
||||
|
||||
$adlist = [];
|
||||
function readAdlists()
|
||||
{
|
||||
// Reset list
|
||||
$list = [];
|
||||
$handle = @fopen("/etc/pihole/adlists.list", "r");
|
||||
if ($handle)
|
||||
{
|
||||
while (($line = fgets($handle)) !== false)
|
||||
{
|
||||
if(substr($line, 0, 5) === "#http")
|
||||
{
|
||||
// Commented list
|
||||
array_push($list, [false,rtrim(substr($line, 1))]);
|
||||
}
|
||||
elseif(substr($line, 0, 4) === "http")
|
||||
{
|
||||
// Active list
|
||||
array_push($list, [true,rtrim($line)]);
|
||||
}
|
||||
}
|
||||
fclose($handle);
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
// Read available adlists
|
||||
$adlist = readAdlists();
|
||||
|
||||
$error = "";
|
||||
$success = "";
|
||||
|
||||
if(isset($_POST["field"]))
|
||||
{
|
||||
// Handle CSRF
|
||||
check_csrf(isset($_POST["token"]) ? $_POST["token"] : "");
|
||||
|
||||
// Process request
|
||||
switch ($_POST["field"]) {
|
||||
// Set DNS server
|
||||
@@ -115,9 +171,12 @@ function readStaticLeasesFile()
|
||||
// Add selected predefined servers to list
|
||||
foreach ($DNSserverslist as $key => $value)
|
||||
{
|
||||
if(array_key_exists("DNSserver".str_replace(".","_",$key),$_POST))
|
||||
foreach(["v4_1", "v4_2", "v6_1", "v6_2"] as $type)
|
||||
{
|
||||
array_push($DNSservers,$key);
|
||||
if(@array_key_exists("DNSserver".str_replace(".","_",$value[$type]),$_POST))
|
||||
{
|
||||
array_push($DNSservers,$value[$type]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,13 +254,13 @@ function readStaticLeasesFile()
|
||||
// Fallback
|
||||
$DNSinterface = "local";
|
||||
}
|
||||
$return .= exec("sudo pihole -a -i ".$DNSinterface." -web");
|
||||
exec("sudo pihole -a -i ".$DNSinterface." -web");
|
||||
|
||||
// If there has been no error we can save the new DNS server IPs
|
||||
if(!strlen($error))
|
||||
{
|
||||
$IPs = implode (",", $DNSservers);
|
||||
exec("sudo pihole -a setdns ".$IPs." ".$extra);
|
||||
$return = exec("sudo pihole -a setdns ".$IPs." ".$extra);
|
||||
$success .= htmlspecialchars($return)."<br>";
|
||||
$success .= "The DNS settings have been updated (using ".count($DNSservers)." DNS servers)";
|
||||
}
|
||||
@@ -241,9 +300,9 @@ function readStaticLeasesFile()
|
||||
$first = true;
|
||||
foreach($domains as $domain)
|
||||
{
|
||||
if(!validDomain($domain))
|
||||
if(!validDomainWildcard($domain) || validIP($domain))
|
||||
{
|
||||
$error .= "Top Domains/Ads entry ".htmlspecialchars($domain)." is invalid!<br>";
|
||||
$error .= "Top Domains/Ads entry ".htmlspecialchars($domain)." is invalid (use only domains)!<br>";
|
||||
}
|
||||
if(!$first)
|
||||
{
|
||||
@@ -260,7 +319,7 @@ function readStaticLeasesFile()
|
||||
$first = true;
|
||||
foreach($clients as $client)
|
||||
{
|
||||
if(!validIP($client))
|
||||
if(!validDomainWildcard($client))
|
||||
{
|
||||
$error .= "Top Clients entry ".htmlspecialchars($client)." is invalid (use only IP addresses)!<br>";
|
||||
}
|
||||
@@ -335,24 +394,6 @@ function readStaticLeasesFile()
|
||||
exec("sudo pihole -a privacymode false");
|
||||
}
|
||||
|
||||
if(isset($_POST["resolve-forward"]))
|
||||
{
|
||||
exec("sudo pihole -a resolve forward true");
|
||||
}
|
||||
else
|
||||
{
|
||||
exec("sudo pihole -a resolve forward false");
|
||||
}
|
||||
|
||||
if(isset($_POST["resolve-clients"]))
|
||||
{
|
||||
exec("sudo pihole -a resolve clients true");
|
||||
}
|
||||
else
|
||||
{
|
||||
exec("sudo pihole -a resolve clients false");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "webUI":
|
||||
@@ -391,7 +432,7 @@ function readStaticLeasesFile()
|
||||
|
||||
case "flushlogs":
|
||||
exec("sudo pihole -f");
|
||||
$success = "The Pi-Hole log file has been flushed";
|
||||
$success = "The Pi-hole log file has been flushed";
|
||||
break;
|
||||
|
||||
case "DHCP":
|
||||
@@ -528,6 +569,41 @@ function readStaticLeasesFile()
|
||||
|
||||
break;
|
||||
|
||||
case "adlists":
|
||||
foreach ($adlist as $key => $value)
|
||||
{
|
||||
if(isset($_POST["adlist-del-".$key]))
|
||||
{
|
||||
// Delete list
|
||||
exec("sudo pihole -a adlist del ".escapeshellcmd($value[1]));
|
||||
}
|
||||
elseif(isset($_POST["adlist-enable-".$key]) && !$value[0])
|
||||
{
|
||||
// Is not enabled, but should be
|
||||
exec("sudo pihole -a adlist enable ".escapeshellcmd($value[1]));
|
||||
|
||||
}
|
||||
elseif(!isset($_POST["adlist-enable-".$key]) && $value[0])
|
||||
{
|
||||
// Is enabled, but shouldn't be
|
||||
exec("sudo pihole -a adlist disable ".escapeshellcmd($value[1]));
|
||||
}
|
||||
}
|
||||
|
||||
if(strlen($_POST["newuserlists"]) > 1)
|
||||
{
|
||||
$domains = array_filter(preg_split('/\r\n|[\r\n]/', $_POST["newuserlists"]));
|
||||
foreach($domains as $domain)
|
||||
{
|
||||
exec("sudo pihole -a adlist add ".escapeshellcmd($domain));
|
||||
}
|
||||
}
|
||||
|
||||
// Reread available adlists
|
||||
$adlist = readAdlists();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
// Option not found
|
||||
$debug = true;
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
/* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||
* Network-wide ad blocking via your own hardware.
|
||||
*
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
|
||||
require "password.php";
|
||||
if(!$auth) die("Not authorized");
|
||||
|
||||
// Not using SplFileObject here, since direct
|
||||
// usage of f-streams will be much faster for
|
||||
// files as large as the pihole.log
|
||||
if(isset($_GET["FTL"]))
|
||||
{
|
||||
$file = fopen("/var/log/pihole-FTL.log","r");
|
||||
}
|
||||
else
|
||||
{
|
||||
$file = fopen("/var/log/pihole.log","r");
|
||||
}
|
||||
|
||||
if(isset($_GET["offset"]))
|
||||
{
|
||||
$offset = intval($_GET['offset']);
|
||||
if($offset > 0)
|
||||
{
|
||||
// Seeks on the file pointer where we want to continue reading is known
|
||||
fseek($file, $offset);
|
||||
$lines = [];
|
||||
while (!feof($file))
|
||||
array_push($lines,fgets($file));
|
||||
die(json_encode(array("offset" => ftell($file), "lines" => $lines)));
|
||||
}
|
||||
}
|
||||
|
||||
// Locate the current position of the file read/write pointer
|
||||
fseek($file, -1, SEEK_END);
|
||||
// Add one to skip the very last "\n" in the log file
|
||||
die(json_encode(array("offset" => ftell($file)+1)));
|
||||
|
||||
?>
|
||||
@@ -7,11 +7,20 @@
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
|
||||
require "password.php";
|
||||
require "auth.php"; // Also imports func.php
|
||||
|
||||
if (php_sapi_name() !== "cli") {
|
||||
if(!$auth) die("Not authorized");
|
||||
check_csrf(isset($_POST["token"]) ? $_POST["token"] : "");
|
||||
}
|
||||
|
||||
function limit_length(&$item, $key)
|
||||
{
|
||||
// limit max length for a domain entry to 253 chars
|
||||
// return only a part of the string if it is longer
|
||||
$item = substr($item, 0, 253);
|
||||
}
|
||||
|
||||
require('func.php');
|
||||
function process_zip($name)
|
||||
{
|
||||
global $zip;
|
||||
@@ -27,6 +36,12 @@ function process_zip($name)
|
||||
}
|
||||
fclose($zippointer);
|
||||
$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");
|
||||
|
||||
// Check validity of domains (after possible clipping)
|
||||
check_domains($domains);
|
||||
return $domains;
|
||||
}
|
||||
@@ -146,7 +161,7 @@ if(isset($_POST["action"]))
|
||||
else
|
||||
{
|
||||
$filename = "pi-hole-teleporter_".date("Y-m-d_h-i-s").".zip";
|
||||
$archive_file_name = "/var/www/html/".$filename;
|
||||
$archive_file_name = tempnam("/tmp", "Teleporter");
|
||||
$zip = new ZipArchive();
|
||||
touch($archive_file_name);
|
||||
$res = $zip->open($archive_file_name, ZipArchive::CREATE | ZipArchive::OVERWRITE);
|
||||
@@ -172,6 +187,8 @@ else
|
||||
header("Expires: 0");
|
||||
if(ob_get_length() > 0) ob_end_clean();
|
||||
readfile($archive_file_name);
|
||||
ignore_user_abort(true);
|
||||
unlink($archive_file_name);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
Vendored
-74
@@ -1,74 +0,0 @@
|
||||
/**
|
||||
* This plug-in for DataTables represents the ultimate option in extensibility
|
||||
* for sorting date / time strings correctly. It uses
|
||||
* [Moment.js](http://momentjs.com) to create automatic type detection and
|
||||
* sorting plug-ins for DataTables based on a given format. This way, DataTables
|
||||
* will automatically detect your temporal information and sort it correctly.
|
||||
*
|
||||
* For usage instructions, please see the DataTables blog
|
||||
* post that [introduces it](//datatables.net/blog/2014-12-18).
|
||||
*
|
||||
* @name Ultimate Date / Time sorting
|
||||
* @summary Sort date and time in any format using Moment.js
|
||||
* @author [Allan Jardine](//datatables.net)
|
||||
* @depends DataTables 1.10+, Moment.js 1.7+
|
||||
*
|
||||
* @example
|
||||
* $.fn.dataTable.moment( 'HH:mm MMM D, YY' );
|
||||
* $.fn.dataTable.moment( 'dddd, MMMM Do, YYYY' );
|
||||
*
|
||||
* $('#example').DataTable();
|
||||
*/
|
||||
|
||||
(function (factory) {
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define(["jquery", "moment", "datatables.net"], factory);
|
||||
} else {
|
||||
factory(jQuery, moment);
|
||||
}
|
||||
}(function ($, moment) {
|
||||
|
||||
$.fn.dataTable.moment = function ( format, locale ) {
|
||||
var types = $.fn.dataTable.ext.type;
|
||||
|
||||
// Add type detection
|
||||
types.detect.unshift( function ( d ) {
|
||||
if ( d ) {
|
||||
// Strip HTML tags and newline characters if possible
|
||||
if ( d.replace ) {
|
||||
d = d.replace(/(<.*?>)|(\r?\n|\r)/g, '');
|
||||
}
|
||||
|
||||
// Strip out surrounding white space
|
||||
d = $.trim( d );
|
||||
}
|
||||
|
||||
// Null and empty values are acceptable
|
||||
if ( d === '' || d === null ) {
|
||||
return 'moment-'+format;
|
||||
}
|
||||
|
||||
return moment( d, format, locale, true ).isValid() ?
|
||||
'moment-'+format :
|
||||
null;
|
||||
} );
|
||||
|
||||
// Add sorting method - use an integer for the sorting
|
||||
types.order[ 'moment-'+format+'-pre' ] = function ( d ) {
|
||||
if ( d ) {
|
||||
// Strip HTML tags and newline characters if possible
|
||||
if ( d.replace ) {
|
||||
d = d.replace(/(<.*?>)|(\r?\n|\r)/g, '');
|
||||
}
|
||||
|
||||
// Strip out surrounding white space
|
||||
d = $.trim( d );
|
||||
}
|
||||
|
||||
return d === '' || d === null ?
|
||||
-Infinity :
|
||||
parseInt( moment( d, format, locale, true ).format( 'x' ), 10 );
|
||||
};
|
||||
};
|
||||
|
||||
}));
|
||||
+169
-102
@@ -1,10 +1,10 @@
|
||||
<!-- Pi-hole: A black hole for Internet advertisements
|
||||
<?php /*
|
||||
* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||
* Network-wide ad blocking via your own hardware.
|
||||
*
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. -->
|
||||
<?php
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
require "scripts/pi-hole/php/header.php";
|
||||
require "scripts/pi-hole/php/savesettings.php";
|
||||
// Reread ini file as things might have been changed
|
||||
@@ -27,11 +27,19 @@
|
||||
}
|
||||
</style>
|
||||
|
||||
<?php // Check if ad lists should be updated after saving ...
|
||||
if(isset($_POST["submit"])) {
|
||||
if($_POST["submit"] == "saveupdate") {
|
||||
// If that is the case -> refresh to the gravity page and start updating immediately
|
||||
?>
|
||||
<meta http-equiv="refresh" content="1;url=gravity.php?go">
|
||||
<?php }} ?>
|
||||
|
||||
<?php if(isset($debug)){ ?>
|
||||
<div id="alDebug" class="alert alert-warning alert-dismissible fade in" role="alert">
|
||||
<button type="button" class="close" data-hide="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4><i class="icon fa fa-warning"></i> Debug</h4>
|
||||
<?php print_r($_POST); ?>
|
||||
<pre><?php print_r($_POST); ?></pre>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
@@ -65,8 +73,24 @@
|
||||
} else {
|
||||
$piHoleIPv4 = "unknown";
|
||||
}
|
||||
$IPv6connectivity = false;
|
||||
if(isset($setupVars["IPV6_ADDRESS"])){
|
||||
$piHoleIPv6 = $setupVars["IPV6_ADDRESS"];
|
||||
sscanf($piHoleIPv6, "%2[0-9a-f]", $hexstr);
|
||||
if(strlen($hexstr) == 2)
|
||||
{
|
||||
// Convert HEX string to number
|
||||
$hex = hexdec($hexstr);
|
||||
// Global Unicast Address (2000::/3, RFC 4291)
|
||||
$GUA = (($hex & 0x70) === 0x20);
|
||||
// Unique Local Address (fc00::/7, RFC 4193)
|
||||
$ULA = (($hex & 0xfe) === 0xfc);
|
||||
if($GUA || $ULA)
|
||||
{
|
||||
// Scope global address detected
|
||||
$IPv6connectivity = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$piHoleIPv6 = "unknown";
|
||||
}
|
||||
@@ -78,21 +102,21 @@
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="form-group">
|
||||
<label>Pi-Hole Ethernet Interface</label>
|
||||
<label>Pi-hole Ethernet Interface</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon"><i class="fa fa-plug"></i></div>
|
||||
<input type="text" class="form-control" disabled value="<?php echo $piHoleInterface; ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Pi-Hole IPv4 address</label>
|
||||
<label>Pi-hole IPv4 address</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon"><i class="fa fa-plug"></i></div>
|
||||
<input type="text" class="form-control" disabled value="<?php echo $piHoleIPv4; ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Pi-Hole IPv6 address</label>
|
||||
<label>Pi-hole IPv6 address</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon"><i class="fa fa-plug"></i></div>
|
||||
<input type="text" class="form-control" disabled value="<?php echo $piHoleIPv6; ?>">
|
||||
@@ -100,7 +124,7 @@
|
||||
<?php if (!defined('AF_INET6')){ ?><p style="color: #F00;">Warning: PHP has been compiled without IPv6 support.</p><?php } ?>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Pi-Hole hostname</label>
|
||||
<label>Pi-hole hostname</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon"><i class="fa fa-laptop"></i></div>
|
||||
<input type="text" class="form-control" disabled value="<?php echo $hostname; ?>">
|
||||
@@ -109,18 +133,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
// Pi-Hole DHCP server
|
||||
|
||||
// Detect IPv6
|
||||
$usingipv6 = false;
|
||||
if(strlen($piHoleIPv6) > 0 && $piHoleIPv6 != "unknown")
|
||||
{
|
||||
if(substr($piHoleIPv6, 0, 4) != "fe80")
|
||||
{
|
||||
$usingipv6 = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Pi-hole DHCP server
|
||||
if(isset($setupVars["DHCP_ACTIVE"]))
|
||||
{
|
||||
if($setupVars["DHCP_ACTIVE"] == 1)
|
||||
@@ -155,7 +168,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
$DHCPIPv6 = $usingipv6;
|
||||
$DHCPIPv6 = false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -175,7 +188,7 @@
|
||||
$DHCProuter = "";
|
||||
}
|
||||
$DHCPleasetime = 24;
|
||||
$DHCPIPv6 = $usingipv6;
|
||||
$DHCPIPv6 = false;
|
||||
}
|
||||
if(isset($setupVars["PIHOLE_DOMAIN"])){
|
||||
$piHoleDomain = $setupVars["PIHOLE_DOMAIN"];
|
||||
@@ -185,7 +198,7 @@
|
||||
?>
|
||||
<div class="box box-warning">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">Pi-Hole DHCP Server</h3>
|
||||
<h3 class="box-title">Pi-hole DHCP Server</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<form role="form" method="post">
|
||||
@@ -238,7 +251,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<label>Pi-Hole domain name</label>
|
||||
<label>Pi-hole domain name</label>
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">Domain</div>
|
||||
@@ -259,14 +272,14 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php if($DHCP) {
|
||||
|
||||
<?php
|
||||
$dhcp_leases = array();
|
||||
if($DHCP) {
|
||||
// Read leases file
|
||||
$leasesfile = true;
|
||||
$dhcpleases = @fopen('/etc/pihole/dhcp.leases', 'r');
|
||||
if(!is_resource($dhcpleases ))
|
||||
if(!is_resource($dhcpleases))
|
||||
$leasesfile = false;
|
||||
$dhcp_leases = array();
|
||||
|
||||
function convertseconds($argument) {
|
||||
$seconds = round($argument);
|
||||
@@ -286,7 +299,7 @@
|
||||
{
|
||||
return sprintf('%dd %dh %dm %ds', ($seconds/86400), ($seconds/3600%24),($seconds/60%60), ($seconds%60));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while(!feof($dhcpleases) && $leasesfile)
|
||||
{
|
||||
@@ -333,10 +346,10 @@
|
||||
array_push($dhcp_leases,["TIME"=>$time, "hwaddr"=>strtoupper($line[1]), "IP"=>$line[2], "host"=>$host, "clid"=>$clid, "type"=>$type]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
readStaticLeasesFile();
|
||||
|
||||
?>
|
||||
readStaticLeasesFile();
|
||||
?>
|
||||
<div class="col-md-12">
|
||||
<div class="box box-warning <?php if(!isset($_POST["addstatic"])){ ?>collapsed-box<?php } ?>">
|
||||
<div class="box-header with-border">
|
||||
@@ -378,56 +391,55 @@
|
||||
<tr><td><input type="text" name="AddMAC"></td><td><input type="text" name="AddIP"></td><td><input type="text" name="AddHostname" value=""></td><td><button class="btn btn-success btn-xs" type="submit" name="addstatic"><span class="glyphicon glyphicon-plus"></span></button></td></tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
<p>Specifying the MAC address is mandatory and only one entry per MAC address is allowed. If the IP address is omitted and a host name is given, the IP address will still be generated dynamically and the specified host name will be used. If the host name is omitted, only a static release will be added.</p>
|
||||
<p>Specifying the MAC address is mandatory and only one entry per MAC address is allowed. If the IP address is omitted and a host name is given, the IP address will still be generated dynamically and the specified host name will be used. If the host name is omitted, only a static lease will be added.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
<input type="hidden" name="field" value="DHCP">
|
||||
<input type="hidden" name="token" value="<?php echo $token ?>">
|
||||
<button type="submit" class="btn btn-primary pull-right">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
|
||||
// DNS settings
|
||||
$DNSservers = [];
|
||||
$DNSactive = [];
|
||||
|
||||
$i = 1;
|
||||
while(isset($setupVars["PIHOLE_DNS_".$i])){
|
||||
if(isset($DNSserverslist[$setupVars["PIHOLE_DNS_".$i]]))
|
||||
if(isinserverlist($setupVars["PIHOLE_DNS_".$i]))
|
||||
{
|
||||
array_push($DNSactive,$setupVars["PIHOLE_DNS_".$i]);
|
||||
}
|
||||
elseif(strpos($setupVars["PIHOLE_DNS_".$i],"."))
|
||||
{
|
||||
if(!isset($custom1))
|
||||
{
|
||||
$DNSservers[] = [$setupVars["PIHOLE_DNS_".$i],$DNSserverslist[$setupVars["PIHOLE_DNS_".$i]]];
|
||||
array_push($DNSactive,$setupVars["PIHOLE_DNS_".$i]);
|
||||
$custom1 = $setupVars["PIHOLE_DNS_".$i];
|
||||
}
|
||||
elseif(strpos($setupVars["PIHOLE_DNS_".$i],"."))
|
||||
else
|
||||
{
|
||||
$DNSservers[] = [$setupVars["PIHOLE_DNS_".$i],"CustomIPv4"];
|
||||
if(!isset($custom1))
|
||||
{
|
||||
$custom1 = $setupVars["PIHOLE_DNS_".$i];
|
||||
}
|
||||
else
|
||||
{
|
||||
$custom2 = $setupVars["PIHOLE_DNS_".$i];
|
||||
}
|
||||
$custom2 = $setupVars["PIHOLE_DNS_".$i];
|
||||
}
|
||||
elseif(strpos($setupVars["PIHOLE_DNS_".$i],":"))
|
||||
}
|
||||
elseif(strpos($setupVars["PIHOLE_DNS_".$i],":"))
|
||||
{
|
||||
if(!isset($custom3))
|
||||
{
|
||||
$DNSservers[] = [$setupVars["PIHOLE_DNS_".$i],"CustomIPv6"];
|
||||
if(!isset($custom3))
|
||||
{
|
||||
$custom3 = $setupVars["PIHOLE_DNS_".$i];
|
||||
}
|
||||
else
|
||||
{
|
||||
$custom4 = $setupVars["PIHOLE_DNS_".$i];
|
||||
}
|
||||
$custom3 = $setupVars["PIHOLE_DNS_".$i];
|
||||
}
|
||||
$i += 1;
|
||||
else
|
||||
{
|
||||
$custom4 = $setupVars["PIHOLE_DNS_".$i];
|
||||
}
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
|
||||
if(isset($setupVars["DNS_FQDN_REQUIRED"])){
|
||||
@@ -494,13 +506,26 @@
|
||||
<form role="form" method="post">
|
||||
<div class="col-lg-6">
|
||||
<label>Upstream DNS Servers</label>
|
||||
<div class="form-group">
|
||||
<table class="table table-bordered">
|
||||
<tr>
|
||||
<th colspan="2">IPv4</th>
|
||||
<th colspan="2">IPv6</th>
|
||||
<th>Name</th>
|
||||
</tr>
|
||||
<?php foreach ($DNSserverslist as $key => $value) { ?>
|
||||
<div class="checkbox">
|
||||
<label title="<?php echo $key;?>">
|
||||
<input type="checkbox" name="DNSserver<?php echo $key;?>" value="true" <?php if(in_array($key,$DNSactive)){ ?>checked<?php } ?> ><?php echo $value;?></label>
|
||||
</div> <?php } ?>
|
||||
</div>
|
||||
<tr>
|
||||
<?php if(isset($value["v4_1"])) { ?>
|
||||
<td title="<?php echo $value["v4_1"];?>"><input type="checkbox" name="DNSserver<?php echo $value["v4_1"];?>" value="true" <?php if(in_array($value["v4_1"],$DNSactive)){ ?>checked<?php } ?> ></td><?php }else{ ?><td></td><?php } ?>
|
||||
<?php if(isset($value["v4_2"])) { ?>
|
||||
<td title="<?php echo $value["v4_2"];?>"><input type="checkbox" name="DNSserver<?php echo $value["v4_2"];?>" value="true" <?php if(in_array($value["v4_2"],$DNSactive)){ ?>checked<?php } ?> ></td><?php }else{ ?><td></td><?php } ?>
|
||||
<?php if(isset($value["v6_1"])) { ?>
|
||||
<td title="<?php echo $value["v6_1"];?>"><input type="checkbox" name="DNSserver<?php echo $value["v6_1"];?>" value="true" <?php if(in_array($value["v6_1"],$DNSactive) && $IPv6connectivity){ ?>checked<?php } if(!$IPv6connectivity){ ?> disabled <?php } ?> ></td><?php }else{ ?><td></td><?php } ?>
|
||||
<?php if(isset($value["v6_2"])) { ?>
|
||||
<td title="<?php echo $value["v6_2"];?>"><input type="checkbox" name="DNSserver<?php echo $value["v6_2"];?>" value="true" <?php if(in_array($value["v6_2"],$DNSactive) && $IPv6connectivity){ ?>checked<?php } if(!$IPv6connectivity){ ?> disabled <?php } ?> ></td><?php }else{ ?><td></td><?php } ?>
|
||||
<td><?php echo $key;?></td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<label> </label>
|
||||
@@ -545,7 +570,7 @@
|
||||
<div class="form-group">
|
||||
<div class="checkbox"><label><input type="checkbox" name="DNSbogusPriv" <?php if($DNSbogusPriv){ ?>checked<?php } ?> title="bogus-priv"> never forward reverse lookups for private IP ranges</label></div>
|
||||
</div>
|
||||
<p>Note that enabling these two options may increase your privacy slightly, but may also prevent you from being able to access local hostnames if the Pi-Hole is not used as DHCP server</p>
|
||||
<p>Note that enabling these two options may increase your privacy slightly, but may also prevent you from being able to access local hostnames if the Pi-hole is not used as DHCP server</p>
|
||||
<div class="form-group">
|
||||
<div class="checkbox"><label><input type="checkbox" name="DNSSEC" <?php if($DNSSEC){ ?>checked<?php } ?>> Use DNSSEC</label></div>
|
||||
</div>
|
||||
@@ -571,6 +596,7 @@
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
<input type="hidden" name="field" value="DNS">
|
||||
<input type="hidden" name="token" value="<?php echo $token ?>">
|
||||
<button type="submit" class="btn btn-primary pull-right">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
@@ -612,6 +638,7 @@
|
||||
<form role="form" method="post">
|
||||
<button type="button" class="btn btn-default confirm-flushlogs">Flush logs</button>
|
||||
<input type="hidden" name="field" value="Logging">
|
||||
<input type="hidden" name="token" value="<?php echo $token ?>">
|
||||
<?php if($piHoleLogging) { ?>
|
||||
<input type="hidden" name="action" value="Disable">
|
||||
<button type="submit" class="btn btn-primary pull-right">Disable query logging</button>
|
||||
@@ -655,26 +682,45 @@
|
||||
$privacyMode = false;
|
||||
}
|
||||
|
||||
if(istrue($setupVars["API_GET_UPSTREAM_DNS_HOSTNAME"]))
|
||||
{
|
||||
$resolveForward = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$resolveForward = false;
|
||||
}
|
||||
|
||||
if(istrue($setupVars["API_GET_CLIENT_HOSTNAME"]))
|
||||
{
|
||||
$resolveClients = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$resolveClients = false;
|
||||
}
|
||||
|
||||
?>
|
||||
<div class="box box-success">
|
||||
<div class="box box-danger collapsed-box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">Pi-Hole's Block Lists</h3>
|
||||
<div class="box-tools pull-right"><button type="button" class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-plus"></i></button></div>
|
||||
</div>
|
||||
<form role="form" method="post">
|
||||
<div class="box-body">
|
||||
<div class="col-lg-12">
|
||||
<label>Lists used to generate Pi-hole's Gravity</label>
|
||||
<?php foreach ($adlist as $key => $value) { ?>
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
<label style="word-break: break-word;">
|
||||
<input type="checkbox" name="adlist-enable-<?php echo $key; ?>" <?php if($value[0]){ ?>checked<?php } ?>>
|
||||
<a href="<?php echo htmlentities ($value[1]); ?>" target="_new"><?php echo htmlentities($value[1]); ?></a>
|
||||
<input type="checkbox" name="adlist-del-<?php echo $key; ?>" hidden>
|
||||
<br>
|
||||
<button class="btn btn-danger btn-xs" id="adlist-btn-<?php echo $key; ?>">
|
||||
<span class="glyphicon glyphicon-trash"></span>
|
||||
</button>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<div class="form-group">
|
||||
<textarea name="newuserlists" class="form-control" rows="1" placeholder="Enter one URL per line to add new ad lists"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
<input type="hidden" name="field" value="adlists">
|
||||
<input type="hidden" name="token" value="<?php echo $token ?>">
|
||||
<button type="submit" class="btn btn-primary" name="submit" value="save">Save</button>
|
||||
<button type="submit" class="btn btn-primary pull-right" name="submit" value="saveupdate">Save and Update</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="box box-success">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">API</h3>
|
||||
</div>
|
||||
@@ -691,41 +737,30 @@
|
||||
<div class="col-lg-6">
|
||||
<div class="form-group">
|
||||
<label>Top Clients</label>
|
||||
<textarea name="clients" class="form-control" rows="4" placeholder="Enter one IP address per line"><?php foreach ($excludedClients as $client) { echo $client."\n"; } ?></textarea>
|
||||
<textarea name="clients" class="form-control" rows="4" placeholder="Enter one IP address or host name per line"><?php foreach ($excludedClients as $client) { echo $client."\n"; } ?></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<h4>Reverse DNS lookup</h4>
|
||||
<p>Try to determine the domain name via querying the Pi-hole for</p>
|
||||
<h4>Privacy settings (Statistics / Query Log)</h4>
|
||||
<div class="col-lg-6">
|
||||
<div class="form-group">
|
||||
<div class="checkbox"><label><input type="checkbox" name="resolve-forward" <?php if($resolveForward){ ?>checked<?php } ?>> Forward Destinations</label></div>
|
||||
<div class="checkbox"><label><input type="checkbox" name="querylog-permitted" <?php if($queryLog === "permittedonly" || $queryLog === "all"){ ?>checked<?php } ?>> Show permitted domain entries</label></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="form-group">
|
||||
<div class="checkbox"><label><input type="checkbox" name="resolve-clients" <?php if($resolveClients){ ?>checked<?php } ?>> Top Clients</label></div>
|
||||
</div>
|
||||
</div>
|
||||
<h4>Query Log</h4>
|
||||
<div class="col-lg-6">
|
||||
<div class="form-group">
|
||||
<div class="checkbox"><label><input type="checkbox" name="querylog-permitted" <?php if($queryLog === "permittedonly" || $queryLog === "all"){ ?>checked<?php } ?>> Show permitted queries</label></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="form-group">
|
||||
<div class="checkbox"><label><input type="checkbox" name="querylog-blocked" <?php if($queryLog === "blockedonly" || $queryLog === "all"){ ?>checked<?php } ?>> Show blocked queries</label></div>
|
||||
<div class="checkbox"><label><input type="checkbox" name="querylog-blocked" <?php if($queryLog === "blockedonly" || $queryLog === "all"){ ?>checked<?php } ?>> Show blocked domain entries</label></div>
|
||||
</div>
|
||||
</div>
|
||||
<h4>Privacy mode</h4>
|
||||
<div class="col-lg-12">
|
||||
<div class="form-group">
|
||||
<div class="checkbox"><label><input type="checkbox" name="privacyMode" <?php if($privacyMode){ ?>checked<?php } ?>> Don't show query results for permitted requests</label></div>
|
||||
<div class="checkbox"><label><input type="checkbox" name="privacyMode" <?php if($privacyMode){ ?>checked<?php } ?>> Don't show origin of DNS requests in query log</label></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
<input type="hidden" name="field" value="API">
|
||||
<input type="hidden" name="token" value="<?php echo $token ?>">
|
||||
<button type="button" class="btn btn-primary api-token">Show API token</button>
|
||||
<button type="submit" class="btn btn-primary pull-right">Save</button>
|
||||
</div>
|
||||
@@ -777,6 +812,7 @@
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
<input type="hidden" name="field" value="webUI">
|
||||
<input type="hidden" name="token" value="<?php echo $token ?>">
|
||||
<button type="submit" class="btn btn-primary pull-right">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
@@ -808,15 +844,45 @@
|
||||
|
||||
<form role="form" method="post" id="rebootform">
|
||||
<input type="hidden" name="field" value="reboot">
|
||||
<input type="hidden" name="token" value="<?php echo $token ?>">
|
||||
</form>
|
||||
<form role="form" method="post" id="restartdnsform">
|
||||
<input type="hidden" name="field" value="restartdns">
|
||||
<input type="hidden" name="token" value="<?php echo $token ?>">
|
||||
</form>
|
||||
<form role="form" method="post" id="flushlogsform">
|
||||
<input type="hidden" name="field" value="flushlogs">
|
||||
<input type="hidden" name="token" value="<?php echo $token ?>">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
if($FTL)
|
||||
{
|
||||
function get_FTL_data($arg)
|
||||
{
|
||||
global $FTLpid;
|
||||
return trim(exec("ps -p ".$FTLpid." -o ".$arg));
|
||||
}
|
||||
$FTLversion = exec("/usr/bin/pihole-FTL version");
|
||||
}
|
||||
?>
|
||||
<div class="box box-danger collapsed-box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">Pi-hole FTL (<?php if($FTL){ ?>Running<?php }else{ ?>Not running<?php } ?>)</h3>
|
||||
<div class="box-tools pull-right"><button type="button" class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-plus"></i></button></div>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<?php if($FTL){ ?>FTL version: <?php echo $FTLversion; ?><br>
|
||||
Process identifier (PID): <?php echo $FTLpid; ?><br>
|
||||
Time FTL started: <?php print_r(get_FTL_data("start")); ?><br>
|
||||
User / Group: <?php print_r(get_FTL_data("euser")); ?> / <?php print_r(get_FTL_data("egroup")); ?><br>
|
||||
Total CPU utilization: <?php print_r(get_FTL_data("%cpu")); ?>%<br>
|
||||
Memory utilization: <?php print_r(get_FTL_data("%mem")); ?>%<br>
|
||||
<span title="Resident memory is the portion of memory occupied by a process that is held in main memory (RAM). The rest of the occupied memory exists in the swap space or file system.">Used memory: <?php echo formatSizeUnits(1e3*floatval(get_FTL_data("rss"))); ?></span><br>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box box-danger collapsed-box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">Pi-hole Teleporter</h3>
|
||||
@@ -825,6 +891,7 @@
|
||||
<div class="box-body">
|
||||
<?php if (extension_loaded('zip')) { ?>
|
||||
<form role="form" method="post" id="takeoutform" action="scripts/pi-hole/php/teleporter.php" target="_blank" enctype="multipart/form-data">
|
||||
<input type="hidden" name="token" value="<?php echo $token ?>">
|
||||
<div class="col-lg-12">
|
||||
<p>Export your Pi-hole lists as downloadable ZIP file</p>
|
||||
<button type="submit" class="btn btn-default">Export</button>
|
||||
@@ -854,7 +921,7 @@
|
||||
</div>
|
||||
</form>
|
||||
<?php } else { ?>
|
||||
<p>The PHP extension <tt>zip</tt> is not loaded. Please ensure it is installed and loaded if you want to use the Pi-hole teleporter.</p>
|
||||
<p>The PHP extension <code>zip</code> is not loaded. Please ensure it is installed and loaded if you want to use the Pi-hole teleporter.</p>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php /*
|
||||
* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||
* Network-wide ad blocking via your own hardware.
|
||||
*
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
require "scripts/pi-hole/php/header.php";
|
||||
?>
|
||||
<!-- Title -->
|
||||
<div class="page-header">
|
||||
<h1>Output the last lines of the pihole-FTL.log file (live)</h1>
|
||||
</div>
|
||||
|
||||
<div class="checkbox"><label><input type="checkbox" name="active" checked id="chk1"> Automatic scrolling on update</label></div>
|
||||
<pre id="output" style="width: 100%; height: 100%;"></pre>
|
||||
<div class="checkbox"><label><input type="checkbox" name="active" checked id="chk2"> Automatic scrolling on update</label></div>
|
||||
|
||||
<?php
|
||||
require "scripts/pi-hole/php/footer.php";
|
||||
?>
|
||||
|
||||
|
||||
<script src="scripts/pi-hole/js/taillog-FTL.js"></script>
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
<!-- Pi-hole: A black hole for Internet advertisements
|
||||
<?php /*
|
||||
* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||
* Network-wide ad blocking via your own hardware.
|
||||
*
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. -->
|
||||
<?php
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
require "scripts/pi-hole/php/header.php";
|
||||
?>
|
||||
<!-- Title -->
|
||||
|
||||
Reference in New Issue
Block a user