Merge pull request #482 from pi-hole/devel

3.0
This commit is contained in:
Adam Warner
2017-05-01 22:03:58 +01:00
committed by GitHub
33 changed files with 1676 additions and 638 deletions
+1 -1
View File
@@ -33,6 +33,6 @@ groups:
conditions:
branches:
- master
required: -1
required: 4
teams:
- admin
+1
View File
@@ -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)
+4 -2
View File
@@ -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>
+89 -139
View File
@@ -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
View File
@@ -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
View File
@@ -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);
?>
+7 -1
View File
@@ -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
View File
@@ -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 -->
+18 -21
View File
@@ -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) { ?>
+10 -10
View File
@@ -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">
+7 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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 -->
+4 -3
View File
@@ -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();
+10 -2
View File
@@ -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
+14
View File
@@ -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
View File
@@ -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;
+51 -34
View File
@@ -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);
}
} );
+11
View File
@@ -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);
});
+46
View File
@@ -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;
});
+2 -2
View File
@@ -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"];
});
+132
View File
@@ -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";
}
}
?>
+12
View File
@@ -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";
+15
View File
@@ -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&amp;hosted_button_id=3J2L3Z4DHW9UY">Donate</a></strong> if you found this useful.</div>
</footer>
+64 -27
View File
@@ -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:&nbsp;";
if($temperatureunit === "F")
{
echo round($fahrenheit,1) . "&nbsp;&deg;F";
}
elseif($temperatureunit === "K")
{
echo round($kelvin,1) . "&nbsp;K";
}
else
{
echo round($celsius,1) . "&nbsp;&deg;C";
}
echo "</a>";
}
else
{
echo "#3366FF";
}
echo "\"></i> Temp:&nbsp;";
if($temperatureunit === "F")
{
echo round($fahrenheit,1) . "&deg;F";
}
elseif($temperatureunit === "K")
{
echo round($kelvin,1) . "K";
}
else
{
echo round($celsius,1) . "&deg;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:&nbsp;&nbsp;" . sprintf("%.1f",100.0*$memory_usage) . "%</a>";
echo "\"></i> Memory usage:&nbsp;&nbsp;" . sprintf("%.1f",100.0*$memory_usage) . "&thinsp;%</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">
+6 -7
View File
@@ -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>
+117 -41
View File
@@ -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;
+43
View File
@@ -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)));
?>
+19 -2
View File
@@ -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;
}
-74
View File
@@ -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
View File
@@ -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">&times;</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>&nbsp;</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>
+24
View File
@@ -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
View File
@@ -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 -->