mirror of
https://github.com/pi-hole/web.git
synced 2024-12-06 19:36:21 +01:00
Merge pull request #372 from pi-hole/devel
[RELEASE] Pi-hole Admin Page v2.4
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
Pi-hole Admin Dashboard
|
||||
============
|
||||
[](https://www.codacy.com/app/Pi-hole/AdminLTE?utm_source=github.com&utm_medium=referral&utm_content=pi-hole/AdminLTE&utm_campaign=badger)
|
||||
[](https://gitter.im/pi-hole/AdminLTE?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3J2L3Z4DHW9UY "Donate")
|
||||
@@ -8,8 +9,7 @@ Using **[AdminLTE](https://almsaeedstudio.com)**, this project will create a Web
|
||||
|
||||
From this interface, you will be able to see stats on how well your Pi-hole is performing. You will also be able to update the lists used to block ads.
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
## API
|
||||
A read-only API can be accessed at `/admin/api.php`. With either no parameters or `api.php?summary` it returns the following JSON:
|
||||
@@ -22,6 +22,9 @@ A read-only API can be accessed at `/admin/api.php`. With either no parameters o
|
||||
}
|
||||
```
|
||||
|
||||
There are many more parameters, such as `summaryRaw`, `overTimeData`, `topItems`, `recentItems`, `getQueryTypes`, `getForwardDestinations`, `getQuerySources`, and finally `getAllQueries`.
|
||||
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.
|
||||
|
||||
`getAllQueries` can optionally be set with one of these values to return JSON hash ordered as value implies: `orderByClientDomainTime`, `orderByClientTimeDomain`, `orderByTimeClientDomain`, `orderByTimeDomainClient`, `orderByDomainClientTime` or `orderByDomainTimeClient`.
|
||||
<hr>
|
||||
<img src="https://assets.pi-hole.net/static/BStackLogo.png" height="80"><br>
|
||||
We use BrowserStack for multi-platform multi-browser testing.
|
||||
|
||||
@@ -89,20 +89,20 @@
|
||||
$data = array_merge($data, getGravity());
|
||||
}
|
||||
|
||||
if (isset($_GET['tailLog'])) {
|
||||
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);
|
||||
$outArray = array();
|
||||
foreach ($inArray as $key=>$value) {
|
||||
if (is_array($value)) {
|
||||
$outArray[htmlspecialchars($key)] = filterArray($value);
|
||||
} else {
|
||||
$outArray[htmlspecialchars($key)] = htmlspecialchars($value);
|
||||
$outArray[htmlspecialchars($key)] = !is_numeric($value) ? htmlspecialchars($value) : $value;
|
||||
}
|
||||
}
|
||||
return $outArray;
|
||||
}
|
||||
return $outArray;
|
||||
}
|
||||
|
||||
$data = filterArray($data);
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
<li>and others</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Query Types: Shows to which upstream DNS the permitted requests have been forwarded to.</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>
|
||||
@@ -70,19 +70,9 @@
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h2>White- / Blacklist</h2>
|
||||
<p>Add or remove domains (or subdomains) from the white-/blacklist. If a domain is added to e.g. the whitelist, any possible entry of the same domain will be automatically removed from the blacklist and vice versa. Adding wildcards using the web UI is currently <em>not</em> supported.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h2>Update Lists</h2>
|
||||
<p>Will download any updates from the third-party ad-serving domain lists that we source. By default, this command runs once a week via cron.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h2>Query adlists</h2>
|
||||
This function is useful to find out what list a domain appears on. Since we don't control what the third-parties put on the block lists, you may find that a domain you normally visit stops working. If this is the case, you could run this command to scan for strings in the list of blocked domains and it will return the list the domain is found on. This proved useful a while back when the Mahakala list was adding apple.com and microsoft.com to their block list.</p>
|
||||
<p>Add or remove domains (or subdomains) from the white-/blacklist. If a domain is added to e.g. the whitelist, any possible entry of the same domain will be automatically removed from the blacklist and vice versa.</p>
|
||||
<p>Wildcard blacklisting is supported (entering <tt>something.de</tt> will block this domain including all subdomains like <tt>a.bb.c.999.something.de</tt>). Note that wildcard whitelisting is <em>not</em> supported.</p>
|
||||
<p>You can white-/blacklist multiple entries at a time if you separate the domains by spaces.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@@ -91,18 +81,36 @@
|
||||
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">
|
||||
<div class="col-md-12">
|
||||
<h2>Tools → Update Lists</h2>
|
||||
<p>Will download any updates from the third-party ad-serving domain lists that we source. By default, this command runs once a week via cron (Sunday at 01:59).</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h2>Tools → Query adlists</h2>
|
||||
This function is useful to find out what list a domain appears on. Since we don't control what the third-parties put on the block lists, you may find that a domain you normally visit stops working. If this is the case, you could run this command to scan for strings in the list of blocked domains and it will return the list the domain is found on. This proved useful a while back when the Mahakala list was adding <tt>apple.com</tt> and <tt>microsoft.com</tt> to their block list.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h2>Tools → Tail pihole.log</h2>
|
||||
Live tailing of the raw Pi-hole log.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h2>Settings</h2>
|
||||
Change settings for the Pi-Hole
|
||||
<h4>Networking</h4>
|
||||
Displays information about the interfaces of the Pi-Hole. No changes possible
|
||||
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.
|
||||
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
|
||||
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
|
||||
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
|
||||
|
||||
@@ -29,10 +29,18 @@ function getFullName() {
|
||||
<div class="form-group input-group">
|
||||
<input id="domain" type="text" class="form-control" placeholder="Add a domain (example.com or sub.example.com)">
|
||||
<span class="input-group-btn">
|
||||
<?php if($list === "black") { ?>
|
||||
<button id="btnAdd" class="btn btn-default" type="button">Add (exact)</button>
|
||||
<button id="btnAddWildcard" class="btn btn-default" type="button">Add (wildcard)</button>
|
||||
<?php }else{ ?>
|
||||
<button id="btnAdd" class="btn btn-default" type="button">Add</button>
|
||||
<?php } ?>
|
||||
<button id="btnRefresh" class="btn btn-default" type="button">Refresh</button>
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
<?php if($list === "white") { ?>
|
||||
<p>Note that whitelisting domains which are blocked using the wildcard method won't work.</p><?php } ?>
|
||||
|
||||
<!-- Alerts -->
|
||||
<div id="alInfo" class="alert alert-info alert-dismissible fade in" role="alert" hidden="true">
|
||||
@@ -45,11 +53,18 @@ function getFullName() {
|
||||
</div>
|
||||
<div id="alFailure" class="alert alert-danger alert-dismissible fade in" role="alert" hidden="true">
|
||||
<button type="button" class="close" data-hide="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
Failure! Something went wrong.
|
||||
Failure! Something went wrong.<br/><span id="err"></span>
|
||||
</div>
|
||||
|
||||
<!-- Domain List -->
|
||||
<?php if($list === "black") { ?>
|
||||
<h3>Exact blocking</h3>
|
||||
<?php } ?>
|
||||
<ul class="list-group" id="list"></ul>
|
||||
<?php if($list === "black") { ?>
|
||||
<h3>Wildcard blocking</h3>
|
||||
<ul class="list-group" id="list-wildcard"></ul>
|
||||
<?php } ?>
|
||||
|
||||
<?php
|
||||
require "scripts/pi-hole/php/footer.php";
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ if(isset($setupVars["API_PRIVACY_MODE"]))
|
||||
</div>
|
||||
<div id="alFailure" class="alert alert-danger alert-dismissible fade in" role="alert" hidden="true">
|
||||
<button type="button" class="close" data-hide="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
Failure! Something went wrong.
|
||||
Failure! Something went wrong.<span id="err"></span>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
|
||||
@@ -10,9 +10,9 @@ $("body").on("click", function(event) {
|
||||
|
||||
function piholeChanged(action)
|
||||
{
|
||||
const status = $("#status");
|
||||
const ena = $("#pihole-enable");
|
||||
const dis = $("#pihole-disable");
|
||||
var status = $("#status");
|
||||
var ena = $("#pihole-enable");
|
||||
var dis = $("#pihole-disable");
|
||||
|
||||
switch(action) {
|
||||
case "enabled":
|
||||
@@ -33,7 +33,7 @@ function piholeChanged(action)
|
||||
|
||||
function piholeChange(action, duration)
|
||||
{
|
||||
const token = encodeURIComponent($("#token").html());
|
||||
var token = encodeURIComponent($("#token").html());
|
||||
var btnStatus;
|
||||
|
||||
switch(action) {
|
||||
@@ -62,25 +62,25 @@ function piholeChange(action, duration)
|
||||
}
|
||||
|
||||
// Handle Enable/Disable
|
||||
$("#pihole-enable").on("click", (e) => {
|
||||
$("#pihole-enable").on("click", function(e){
|
||||
e.preventDefault();
|
||||
piholeChange("enable","");
|
||||
});
|
||||
$("#pihole-disable-permanently").on("click", (e) => {
|
||||
$("#pihole-disable-permanently").on("click", function(e){
|
||||
e.preventDefault();
|
||||
piholeChange("disable","0");
|
||||
});
|
||||
$("#pihole-disable-10s").on("click", (e) => {
|
||||
$("#pihole-disable-10s").on("click", function(e){
|
||||
e.preventDefault();
|
||||
piholeChange("disable","10");
|
||||
setTimeout(function(){piholeChanged("enabled");},10000);
|
||||
});
|
||||
$("#pihole-disable-30s").on("click", (e) => {
|
||||
$("#pihole-disable-30s").on("click", function(e){
|
||||
e.preventDefault();
|
||||
piholeChange("disable","30");
|
||||
setTimeout(function(){piholeChanged("enabled");},30000);
|
||||
});
|
||||
$("#pihole-disable-5m").on("click", (e) => {
|
||||
$("#pihole-disable-5m").on("click", function(e){
|
||||
e.preventDefault();
|
||||
piholeChange("disable","300");
|
||||
setTimeout(function(){piholeChanged("enabled");},300000);
|
||||
@@ -204,3 +204,27 @@ $(document).keypress(function(e) {
|
||||
$("#loginform").submit();
|
||||
}
|
||||
});
|
||||
|
||||
function testCookies()
|
||||
{
|
||||
if (navigator.cookieEnabled)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// set and read cookie
|
||||
document.cookie = "cookietest=1";
|
||||
var ret = document.cookie.indexOf("cookietest=") !== -1;
|
||||
|
||||
// delete cookie
|
||||
document.cookie = "cookietest=1; expires=Thu, 01-Jan-1970 00:00:01 GMT";
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
$(function() {
|
||||
if(!testCookies() && $("#cookieInfo").length)
|
||||
{
|
||||
$("#cookieInfo").show();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2,6 +2,13 @@ function eventsource() {
|
||||
var alInfo = $("#alInfo");
|
||||
var alSuccess = $("#alSuccess");
|
||||
var ta = $("#output");
|
||||
|
||||
// IE does not support EventSource - exit early
|
||||
if (typeof EventSource !== "function") {
|
||||
ta.show();
|
||||
ta.html("Updating lists of ad-serving domains is not supported with this browser!");
|
||||
return;
|
||||
}
|
||||
var source = new EventSource("scripts/pi-hole/php/gravity.sh.php");
|
||||
|
||||
ta.html("");
|
||||
@@ -27,7 +34,7 @@ function eventsource() {
|
||||
}, false);
|
||||
}
|
||||
|
||||
$("#gravityBtn").on("click", () => {
|
||||
$("#gravityBtn").on("click", function(){
|
||||
$("#gravityBtn").attr("disabled", true);
|
||||
eventsource();
|
||||
});
|
||||
|
||||
@@ -132,7 +132,7 @@ function escapeHtml(text) {
|
||||
function updateTopClientsChart() {
|
||||
$.getJSON("api.php?summaryRaw&getQuerySources", function(data) {
|
||||
var clienttable = $("#client-frequency").find("tbody:last");
|
||||
var domain, percentage, domainname;
|
||||
var domain, percentage, domainname, domainip;
|
||||
for (domain in data.top_sources) {
|
||||
|
||||
if ({}.hasOwnProperty.call(data.top_sources, domain)){
|
||||
@@ -140,14 +140,17 @@ function updateTopClientsChart() {
|
||||
domain = escapeHtml(domain);
|
||||
if(domain.indexOf("|") > -1)
|
||||
{
|
||||
domainname = domain.substr(0, domain.indexOf("|"));
|
||||
var idx = domain.indexOf("|");
|
||||
domainname = domain.substr(0, idx);
|
||||
domainip = domain.substr(idx+1, domain.length-idx);
|
||||
}
|
||||
else
|
||||
{
|
||||
domainname = domain;
|
||||
domainip = domain;
|
||||
}
|
||||
|
||||
var url = "<a href=\"queries.php?client="+domain+"\">"+domainname+"</a>";
|
||||
var url = "<a href=\"queries.php?client="+domain+"\" title=\""+domainip+"\">"+domainname+"</a>";
|
||||
percentage = data.top_sources[domain] / 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: " +
|
||||
@@ -172,7 +175,8 @@ function updateForwardDestinations() {
|
||||
c.push(colors.shift());
|
||||
if(key.indexOf("|") > -1)
|
||||
{
|
||||
key = key.substr(0, key.indexOf("|"));
|
||||
var idx = key.indexOf("|");
|
||||
key = key.substr(0, idx)+" ("+key.substr(idx+1, key.length-idx)+")";
|
||||
}
|
||||
forwardDestinationChart.data.labels.push(key);
|
||||
});
|
||||
|
||||
+79
-17
@@ -6,13 +6,18 @@ var token = $("#token").html();
|
||||
var listType = $("#list-type").html();
|
||||
var fullName = listType === "white" ? "Whitelist" : "Blacklist";
|
||||
|
||||
function sub(index, entry) {
|
||||
function sub(index, entry, arg) {
|
||||
var domain = $("#"+index);
|
||||
var locallistType = listType;
|
||||
domain.hide("highlight");
|
||||
if(arg === "wild")
|
||||
{
|
||||
locallistType = "wild";
|
||||
}
|
||||
$.ajax({
|
||||
url: "scripts/pi-hole/php/sub.php",
|
||||
method: "post",
|
||||
data: {"domain":entry, "list":listType, "token":token},
|
||||
data: {"domain":entry, "list":locallistType, "token":token},
|
||||
success: function(response) {
|
||||
if(response.length !== 0){
|
||||
return;
|
||||
@@ -21,14 +26,24 @@ function sub(index, entry) {
|
||||
},
|
||||
error: function(jqXHR, exception) {
|
||||
alert("Failed to remove the domain!");
|
||||
domain.show({queue:true});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function refresh(fade) {
|
||||
var listw;
|
||||
var list = $("#list");
|
||||
if(listType === "black")
|
||||
{
|
||||
listw = $("#list-wildcard");
|
||||
}
|
||||
if(fade) {
|
||||
list.fadeOut(100);
|
||||
if(listw)
|
||||
{
|
||||
listw.fadeOut(100);
|
||||
}
|
||||
}
|
||||
$.ajax({
|
||||
url: "scripts/pi-hole/php/get.php",
|
||||
@@ -36,26 +51,60 @@ function refresh(fade) {
|
||||
data: {"list":listType},
|
||||
success: function(response) {
|
||||
list.html("");
|
||||
if(listw)
|
||||
{
|
||||
listw.html("");
|
||||
}
|
||||
var data = JSON.parse(response);
|
||||
|
||||
if(data.length === 0) {
|
||||
list.html("<div class=\"alert alert-info\" role=\"alert\">Your " + fullName + " is empty!</div>");
|
||||
$("h3").hide();
|
||||
if(listw)
|
||||
{
|
||||
listw.html("<div class=\"alert alert-info\" role=\"alert\">Your " + fullName + " is empty!</div>");
|
||||
}
|
||||
else
|
||||
{
|
||||
list.html("<div class=\"alert alert-info\" role=\"alert\">Your " + fullName + " is empty!</div>");
|
||||
}
|
||||
}
|
||||
else {
|
||||
$("h3").show();
|
||||
data.forEach(function (entry, index) {
|
||||
list.append(
|
||||
if(entry.substr(0,1) === "*")
|
||||
{
|
||||
// Wildcard entry
|
||||
// remove leading *
|
||||
entry = entry.substr(1, entry.length - 1);
|
||||
listw.append(
|
||||
"<li id=\"" + index + "\" class=\"list-group-item clearfix\">" + entry +
|
||||
"<button class=\"btn btn-danger btn-xs pull-right\" type=\"button\">" +
|
||||
"<span class=\"glyphicon glyphicon-trash\"></span></button></li>"
|
||||
);
|
||||
"<span class=\"glyphicon glyphicon-trash\"></span></button></li>");
|
||||
// Handle button
|
||||
$("#list-wildcard #"+index+"").on("click", "button", function() {
|
||||
sub(index, entry, "wild");
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal entry
|
||||
list.append(
|
||||
"<li id=\"" + index + "\" class=\"list-group-item clearfix\">" + entry +
|
||||
"<button class=\"btn btn-danger btn-xs pull-right\" type=\"button\">" +
|
||||
"<span class=\"glyphicon glyphicon-trash\"></span></button></li>");
|
||||
// Handle button
|
||||
$("#list #"+index+"").on("click", "button", function() {
|
||||
sub(index, entry, "exact");
|
||||
});
|
||||
}
|
||||
|
||||
// Handle button
|
||||
$("#list #"+index+"").on("click", "button", function() {
|
||||
sub(index, entry);
|
||||
});
|
||||
});
|
||||
}
|
||||
list.fadeIn("fast");
|
||||
list.fadeIn(100);
|
||||
if(listw)
|
||||
{
|
||||
listw.fadeIn(100);
|
||||
}
|
||||
},
|
||||
error: function(jqXHR, exception) {
|
||||
$("#alFailure").show();
|
||||
@@ -65,30 +114,37 @@ function refresh(fade) {
|
||||
|
||||
window.onload = refresh(false);
|
||||
|
||||
function add() {
|
||||
function add(arg) {
|
||||
var locallistType = listType;
|
||||
var domain = $("#domain");
|
||||
if(domain.val().length === 0){
|
||||
return;
|
||||
}
|
||||
if(arg === "wild")
|
||||
{
|
||||
locallistType = "wild";
|
||||
}
|
||||
|
||||
var alInfo = $("#alInfo");
|
||||
var alSuccess = $("#alSuccess");
|
||||
var alFailure = $("#alFailure");
|
||||
var err = $("#err");
|
||||
alInfo.show();
|
||||
alSuccess.hide();
|
||||
alFailure.hide();
|
||||
$.ajax({
|
||||
url: "scripts/pi-hole/php/add.php",
|
||||
method: "post",
|
||||
data: {"domain":domain.val(), "list":listType, "token":token},
|
||||
data: {"domain":domain.val(), "list":locallistType, "token":token},
|
||||
success: function(response) {
|
||||
if (response.indexOf("not a valid argument") >= 0 ||
|
||||
response.indexOf("is not a valid domain") >= 0) {
|
||||
alFailure.show();
|
||||
alFailure.delay(1000).fadeOut(2000, function() {
|
||||
err.html(response);
|
||||
alFailure.delay(4000).fadeOut(2000, function() {
|
||||
alFailure.hide();
|
||||
});
|
||||
alInfo.delay(1000).fadeOut(2000, function() {
|
||||
alInfo.delay(4000).fadeOut(2000, function() {
|
||||
alInfo.hide();
|
||||
});
|
||||
} else {
|
||||
@@ -105,6 +161,7 @@ function add() {
|
||||
},
|
||||
error: function(jqXHR, exception) {
|
||||
alFailure.show();
|
||||
err.html("");
|
||||
alFailure.delay(1000).fadeOut(2000, function() {
|
||||
alFailure.hide();
|
||||
});
|
||||
@@ -121,14 +178,19 @@ function add() {
|
||||
$(document).keypress(function(e) {
|
||||
if(e.which === 13 && $("#domain").is(":focus")) {
|
||||
// Enter was pressed, and the input has focus
|
||||
add();
|
||||
add("exact");
|
||||
}
|
||||
});
|
||||
|
||||
// Handle buttons
|
||||
$("#btnAdd").on("click", function() {
|
||||
add();
|
||||
add("exact");
|
||||
});
|
||||
|
||||
$("#btnAddWildcard").on("click", function() {
|
||||
add("wild");
|
||||
});
|
||||
|
||||
$("#btnRefresh").on("click", function() {
|
||||
refresh(true);
|
||||
});
|
||||
|
||||
@@ -22,6 +22,7 @@ function add(domain,list) {
|
||||
alDomain.html(domain);
|
||||
var alSuccess = $("#alSuccess");
|
||||
var alFailure = $("#alFailure");
|
||||
var err = $("#err");
|
||||
|
||||
if(list === "white")
|
||||
{
|
||||
@@ -43,7 +44,8 @@ function add(domain,list) {
|
||||
if (response.indexOf("not a valid argument") >= 0 || response.indexOf("is not a valid domain") >= 0)
|
||||
{
|
||||
alFailure.show();
|
||||
alFailure.delay(1000).fadeOut(2000, function() { alFailure.hide(); });
|
||||
err.html(response);
|
||||
alFailure.delay(4000).fadeOut(2000, function() { alFailure.hide(); });
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -58,6 +60,7 @@ function add(domain,list) {
|
||||
},
|
||||
error: function(jqXHR, exception) {
|
||||
alFailure.show();
|
||||
err.html("");
|
||||
alFailure.delay(1000).fadeOut(2000, function() {
|
||||
alFailure.hide();
|
||||
});
|
||||
@@ -69,8 +72,20 @@ function add(domain,list) {
|
||||
}
|
||||
});
|
||||
}
|
||||
function handleAjaxError( xhr, textStatus, error ) {
|
||||
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." );
|
||||
}
|
||||
$("#all-queries_processing").hide();
|
||||
tableApi.clear();
|
||||
tableApi.draw();
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
var status;
|
||||
|
||||
// Do we want to filter queries?
|
||||
var GETDict = {};
|
||||
@@ -90,13 +105,18 @@ $(document).ready(function() {
|
||||
|
||||
tableApi = $("#all-queries").DataTable( {
|
||||
"rowCallback": function( row, data, index ){
|
||||
if (data[4] === "Pi-holed") {
|
||||
status = data[4];
|
||||
if (status === "Pi-holed (exact)") {
|
||||
$(row).css("color","red");
|
||||
$("td:eq(5)", row).html( "<button style=\"color:green;\"><i class=\"fa fa-pencil-square-o\"></i> Whitelist</button>" );
|
||||
$("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{
|
||||
$(row).css("color","green");
|
||||
$("td:eq(5)", row).html( "<button style=\"color:red;\"><i class=\"fa fa-ban\"></i> Blacklist</button>" );
|
||||
$("td:eq(5)", row).html( "<button style=\"color:red; white-space: nowrap;\"><i class=\"fa fa-ban\"></i> Blacklist</button>" );
|
||||
}
|
||||
|
||||
},
|
||||
@@ -104,8 +124,9 @@ $(document).ready(function() {
|
||||
"<'row'<'col-sm-4'l><'col-sm-8'p>>" +
|
||||
"<'row'<'col-sm-12'tr>>" +
|
||||
"<'row'<'col-sm-5'i><'col-sm-7'p>>",
|
||||
"ajax": APIstring,
|
||||
"ajax": {"url": APIstring, "error": handleAjaxError },
|
||||
"autoWidth" : false,
|
||||
"processing": true,
|
||||
"order" : [[0, "desc"]],
|
||||
"columns": [
|
||||
{ "width" : "20%", "type": "date" },
|
||||
@@ -124,7 +145,8 @@ $(document).ready(function() {
|
||||
});
|
||||
$("#all-queries tbody").on( "click", "button", function () {
|
||||
var data = tableApi.row( $(this).parents("tr") ).data();
|
||||
if (data[4] === "Pi-holed")
|
||||
status = data[4];
|
||||
if (status.substr(0,2) === "Pi")
|
||||
{
|
||||
add(data[2],"white");
|
||||
}
|
||||
|
||||
@@ -1,4 +1,54 @@
|
||||
var exact = "";
|
||||
|
||||
function quietfilter(ta,data)
|
||||
{
|
||||
var lines = data.split("\n");
|
||||
for(var i = 0;i<lines.length;i++)
|
||||
{
|
||||
if(lines[i].indexOf("results") !== -1 && lines[i].indexOf("0 results") === -1)
|
||||
{
|
||||
var shortstring = lines[i].replace("::: /etc/pihole/","");
|
||||
// Remove "(x results)"
|
||||
shortstring = shortstring.replace(/\(.*/,"");
|
||||
ta.append(shortstring+"\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Credit: http://stackoverflow.com/a/10642418/2087442
|
||||
function httpGet(ta,quiet,theUrl)
|
||||
{
|
||||
var xmlhttp;
|
||||
if (window.XMLHttpRequest)
|
||||
{
|
||||
// code for IE7+
|
||||
xmlhttp = new XMLHttpRequest();
|
||||
}
|
||||
else
|
||||
{
|
||||
// code for IE6, IE5
|
||||
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
|
||||
}
|
||||
xmlhttp.onreadystatechange=function()
|
||||
{
|
||||
if (xmlhttp.readyState === 4 && xmlhttp.status === 200)
|
||||
{
|
||||
ta.show();
|
||||
ta.empty();
|
||||
if(!quiet)
|
||||
{
|
||||
ta.append(xmlhttp.responseText);
|
||||
}
|
||||
else
|
||||
{
|
||||
quietfilter(ta,xmlhttp.responseText);
|
||||
}
|
||||
}
|
||||
};
|
||||
xmlhttp.open("GET", theUrl, false);
|
||||
xmlhttp.send();
|
||||
}
|
||||
|
||||
function eventsource() {
|
||||
var ta = $("#output");
|
||||
var domain = $("#domain");
|
||||
@@ -12,11 +62,17 @@ function eventsource() {
|
||||
if(q.val() === "yes")
|
||||
{
|
||||
quiet = true;
|
||||
exact = "exact";
|
||||
exact = "&exact";
|
||||
}
|
||||
|
||||
// IE does not support EventSource - load whole content at once
|
||||
if (typeof EventSource !== "function") {
|
||||
httpGet(ta,quiet,"/admin/scripts/pi-hole/php/queryads.php?domain="+domain.val().toLowerCase()+exact+"&IE");
|
||||
return;
|
||||
}
|
||||
|
||||
var host = window.location.host;
|
||||
var source = new EventSource("http://"+host+"/admin/scripts/pi-hole/php/queryads.php?domain="+domain.val().toLowerCase()+"&"+exact);
|
||||
var source = new EventSource("/admin/scripts/pi-hole/php/queryads.php?domain="+domain.val().toLowerCase()+exact);
|
||||
|
||||
// Reset and show field
|
||||
ta.empty();
|
||||
@@ -29,17 +85,7 @@ function eventsource() {
|
||||
}
|
||||
else
|
||||
{
|
||||
var lines = e.data.split("\n");
|
||||
for(var i = 0;i<lines.length;i++)
|
||||
{
|
||||
if(lines[i].indexOf("results") !== -1 && lines[i].indexOf("0 results") === -1)
|
||||
{
|
||||
var shortstring = lines[i].replace("::: /etc/pihole/","");
|
||||
// Remove "(x results)"
|
||||
shortstring = shortstring.replace(/\(.*/,"");
|
||||
ta.append(shortstring+"\n");
|
||||
}
|
||||
}
|
||||
quietfilter(ta,e.data);
|
||||
}
|
||||
}, false);
|
||||
|
||||
|
||||
@@ -2,6 +2,17 @@ $(function () {
|
||||
$("[data-mask]").inputmask();
|
||||
});
|
||||
|
||||
$(function(){
|
||||
$("#custom1val").ipAddress({s:4});
|
||||
$("#custom2val").ipAddress({s:4});
|
||||
$("#custom3val").ipAddress({v:6});
|
||||
$("#custom4val").ipAddress({v:6});
|
||||
|
||||
$("#DHCPfrom").ipAddress({s:4});
|
||||
$("#DHCPto").ipAddress({s:4});
|
||||
$("#DHCProuter").ipAddress({s:4});
|
||||
});
|
||||
|
||||
$(".confirm-reboot").confirm({
|
||||
text: "Are you sure you want to send a reboot command to your Pi-Hole?",
|
||||
title: "Confirmation required",
|
||||
|
||||
@@ -13,6 +13,9 @@ switch($type) {
|
||||
case "black":
|
||||
echo exec("sudo pihole -b -q ${_POST['domain']}");
|
||||
break;
|
||||
case "wild":
|
||||
echo exec("sudo pihole -wild -q ${_POST['domain']}");
|
||||
break;
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
@@ -17,10 +17,12 @@ function log_and_die($message) {
|
||||
function check_cors() {
|
||||
$setupVars = parse_ini_file("/etc/pihole/setupVars.conf");
|
||||
$ipv4 = isset($setupVars["IPV4_ADDRESS"]) ? explode("/", $setupVars["IPV4_ADDRESS"])[0] : $_SERVER['SERVER_ADDR'];
|
||||
$ipv6 = isset($setupVars["IPV6_ADDRESS"]) ? explode("/", $setupVars["IPV6_ADDRESS"])[0] : $_SERVER['SERVER_ADDR'];
|
||||
|
||||
// Check CORS
|
||||
$AUTHORIZED_HOSTNAMES = array(
|
||||
$ipv4,
|
||||
$ipv6,
|
||||
$_SERVER["SERVER_NAME"],
|
||||
"pi.hole",
|
||||
"localhost"
|
||||
@@ -40,10 +42,15 @@ function check_cors() {
|
||||
// https://pi.hole
|
||||
// pi.hole:8080
|
||||
// However, we don't use parse_url(...) if there is no colon, since it will fail for e.g. "pi.hole"
|
||||
if(strpos($server_host, ":"))
|
||||
|
||||
// Don't use parse_url for IPv6 addresses, since it does not support them
|
||||
// see PHP bug report: https://bugs.php.net/bug.php?id=72811
|
||||
if(strpos($server_host, ":") && !strpos($server_host, "[") && !strpos($server_host, "]"))
|
||||
{
|
||||
$server_host = parse_url($_SERVER['HTTP_HOST'], PHP_URL_HOST);
|
||||
}
|
||||
// Remove "[" ... "]"
|
||||
$server_host = str_replace(array("[","]"), array("",""), $server_host);
|
||||
|
||||
if(isset($_SERVER['HTTP_HOST']) && !in_array($server_host, $AUTHORIZED_HOSTNAMES)) {
|
||||
log_and_die("Failed Host Check: " . $server_host .' vs '. join(', ', $AUTHORIZED_HOSTNAMES));
|
||||
@@ -53,10 +60,12 @@ function check_cors() {
|
||||
$server_origin = $_SERVER['HTTP_ORIGIN'];
|
||||
|
||||
// Detect colon in $_SERVER['HTTP_ORIGIN'] (see comment above)
|
||||
if(strpos($server_origin, ":"))
|
||||
if(strpos($server_origin, ":") && !strpos($server_origin, "[") && !strpos($server_origin, "]"))
|
||||
{
|
||||
$server_origin = parse_url($_SERVER['HTTP_ORIGIN'], PHP_URL_HOST);
|
||||
}
|
||||
// Remove "[" ... "]"
|
||||
$server_origin = str_replace(array("[","]"), array("",""), $server_origin);
|
||||
|
||||
if(!in_array($server_origin, $AUTHORIZED_HOSTNAMES)) {
|
||||
log_and_die("Failed CORS: " . $server_origin .' vs '. join(', ', $AUTHORIZED_HOSTNAMES));
|
||||
@@ -103,9 +112,13 @@ function check_csrf($token) {
|
||||
|
||||
function check_domain() {
|
||||
if(isset($_POST['domain'])){
|
||||
$validDomain = is_valid_domain_name($_POST['domain']);
|
||||
if(!$validDomain){
|
||||
log_and_die($_POST['domain']. ' is not a valid domain');
|
||||
$domains = explode(" ",$_POST['domain']);
|
||||
foreach($domains as $domain)
|
||||
{
|
||||
$validDomain = is_valid_domain_name($domain);
|
||||
if(!$validDomain){
|
||||
log_and_die(htmlspecialchars($domain. ' is not a valid domain'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -126,11 +139,11 @@ function list_verify($type) {
|
||||
require("password.php");
|
||||
if(strlen($pwhash) == 0)
|
||||
{
|
||||
log_and_die("No password set - ".$type."listing with password not supported");
|
||||
log_and_die("No password set - ".htmlspecialchars($type)."listing with password not supported");
|
||||
}
|
||||
elseif($wrongpassword)
|
||||
{
|
||||
log_and_die("Wrong password - ".$type."listing of ${_POST['domain']} not permitted");
|
||||
log_and_die("Wrong password - ".htmlspecialchars($type)."listing of ${_POST['domain']} not permitted");
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -333,6 +333,7 @@
|
||||
|
||||
// Create empty array for gravity
|
||||
$gravity_domains = getGravity();
|
||||
$wildcard_domains = getWildcardListContent();
|
||||
|
||||
if(isset($_GET["from"]))
|
||||
{
|
||||
@@ -380,10 +381,37 @@
|
||||
|
||||
$exploded = explode(" ", trim($query));
|
||||
$domain = $exploded[count($exploded)-3];
|
||||
$tmp = $exploded[count($exploded)-4];
|
||||
|
||||
$status = isset($gravity_domains[$domain]) ? "Pi-holed" : "OK";
|
||||
if(($status === "Pi-holed" && $showBlocked) || ($status === "OK" && $showPermitted))
|
||||
$status = "";
|
||||
|
||||
if(isset($gravity_domains[$domain]))
|
||||
{
|
||||
if($gravity_domains[$domain] > 0)
|
||||
{
|
||||
// Exact matching gravity domain
|
||||
$status = "Pi-holed (exact)";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Explicitly whitelisted
|
||||
$status = "OK (whitelisted)";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Test for wildcard blocking
|
||||
foreach ($wildcard_domains as $entry) {
|
||||
if(strpos($domain, $entry) !== false)
|
||||
{
|
||||
$status = "Pi-holed (wildcard)";
|
||||
}
|
||||
}
|
||||
if(!strlen($status))
|
||||
{
|
||||
$status = "OK";
|
||||
}
|
||||
}
|
||||
if((substr($status,0,2) === "Pi" && $showBlocked) || (substr($status,0,2) === "OK" && $showPermitted))
|
||||
{
|
||||
$type = substr($exploded[count($exploded)-4], 6, -1);
|
||||
$client = $exploded[count($exploded)-1];
|
||||
@@ -481,7 +509,7 @@
|
||||
|
||||
function countDnsQueries() {
|
||||
global $logListName;
|
||||
return exec("grep -c \": query\\[A\" $logListName");
|
||||
return intval(exec("grep -c \": query\\[A\" $logListName"));
|
||||
}
|
||||
|
||||
function getDnsQueriesAll(\SplFileObject $log) {
|
||||
@@ -506,16 +534,33 @@
|
||||
if($action && strlen($key) > 0)
|
||||
{
|
||||
// $action is true (we want to add) *and* key is not empty
|
||||
$array[$key] = true;
|
||||
$array[$key] = 1;
|
||||
}
|
||||
elseif(!$action && isset($array[$key]))
|
||||
{
|
||||
// $action is false (we want to remove) *and* key is set
|
||||
unset($array[$key]);
|
||||
$array[$key] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getWildcardListContent() {
|
||||
$rawList = file_get_contents(checkfile("/etc/dnsmasq.d/03-pihole-wildcard.conf"));
|
||||
$wclist = explode("\n", $rawList);
|
||||
$list = [];
|
||||
|
||||
foreach ($wclist as $entry) {
|
||||
$expl = explode("/", $entry);
|
||||
if(count($expl) == 3)
|
||||
{
|
||||
array_push($list,$expl[1]);
|
||||
}
|
||||
}
|
||||
|
||||
return array_unique($list);
|
||||
|
||||
}
|
||||
|
||||
function getGravity() {
|
||||
global $gravity,$whitelist,$blacklist;
|
||||
$domains = [];
|
||||
@@ -577,7 +622,17 @@
|
||||
|
||||
function countBlockedQueries() {
|
||||
global $logListName;
|
||||
return exec("grep \"gravity.list\" $logListName | grep -c \" is \"");
|
||||
// Blocked due to gravity entries (ad lists + blacklist)
|
||||
$gravityblocked = intval(exec("grep -c -e \"gravity\.list.*is\" $logListName"));
|
||||
|
||||
// Blocked due to wildcard entries
|
||||
$wildcard_domains = getWildcardListContent();
|
||||
$wildcardblocked = 0;
|
||||
foreach ($wildcard_domains as $domain) {
|
||||
$wildcardblocked += intval(exec("grep -c -e \"config.*$domain is\" $logListName"));
|
||||
}
|
||||
|
||||
return $gravityblocked +$wildcardblocked;
|
||||
}
|
||||
|
||||
function getForwards(\SplFileObject $log) {
|
||||
@@ -623,14 +678,12 @@
|
||||
$byTimeAds[$time] = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isset($byTimeDomains[$time])) {
|
||||
$byTimeDomains[$time]++;
|
||||
}
|
||||
else {
|
||||
$byTimeDomains[$time] = 1;
|
||||
}
|
||||
|
||||
if (isset($byTimeDomains[$time])) {
|
||||
$byTimeDomains[$time]++;
|
||||
}
|
||||
else {
|
||||
$byTimeDomains[$time] = 1;
|
||||
}
|
||||
}
|
||||
return [$byTimeDomains,$byTimeAds];
|
||||
@@ -665,14 +718,12 @@
|
||||
$byTimeAds[$time] = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isset($byTimeDomains[$time])) {
|
||||
$byTimeDomains[$time]++;
|
||||
}
|
||||
else {
|
||||
$byTimeDomains[$time] = 1;
|
||||
}
|
||||
|
||||
if (isset($byTimeDomains[$time])) {
|
||||
$byTimeDomains[$time]++;
|
||||
}
|
||||
else {
|
||||
$byTimeDomains[$time] = 1;
|
||||
}
|
||||
}
|
||||
return [$byTimeDomains,$byTimeAds];
|
||||
|
||||
+45
-11
@@ -1,21 +1,55 @@
|
||||
<?php
|
||||
if(!isset($_GET['list']))
|
||||
die();
|
||||
die("Missing parameter");
|
||||
|
||||
$type = $_GET['list'];
|
||||
|
||||
if($type !== "white" && $type !== "black")
|
||||
die("Invalid list parameter");
|
||||
$listtype = $_GET['list'];
|
||||
|
||||
require "func.php";
|
||||
|
||||
$rawList = file_get_contents(checkfile("/etc/pihole/${type}list.txt"));
|
||||
$list = explode("\n", $rawList);
|
||||
switch ($listtype) {
|
||||
case "white":
|
||||
$list = getListContent("white");
|
||||
break;
|
||||
|
||||
case "black":
|
||||
$list = array_merge(getListContent("black"),getWildcardListContent());
|
||||
break;
|
||||
|
||||
default:
|
||||
die("Invalid list parameter");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
function getListContent($type) {
|
||||
$rawList = file_get_contents(checkfile("/etc/pihole/".$type."list.txt"));
|
||||
$list = explode("\n", $rawList);
|
||||
|
||||
// Get rid of empty lines
|
||||
for($i = sizeof($list)-1; $i >= 0; $i--) {
|
||||
if($list[$i] == "")
|
||||
unset($list[$i]);
|
||||
}
|
||||
|
||||
return $list;
|
||||
|
||||
}
|
||||
|
||||
function getWildcardListContent() {
|
||||
$rawList = file_get_contents(checkfile("/etc/dnsmasq.d/03-pihole-wildcard.conf"));
|
||||
$wclist = explode("\n", $rawList);
|
||||
$list = [];
|
||||
|
||||
foreach ($wclist as $entry) {
|
||||
$expl = explode("/", $entry);
|
||||
if(count($expl) == 3)
|
||||
{
|
||||
array_push($list,"*${expl[1]}");
|
||||
}
|
||||
}
|
||||
|
||||
return array_unique($list);
|
||||
|
||||
// Get rid of empty lines
|
||||
for($i = sizeof($list)-1; $i >= 0; $i--) {
|
||||
if($list[$i] == "")
|
||||
unset($list[$i]);
|
||||
}
|
||||
|
||||
function filterArray(&$inArray) {
|
||||
|
||||
@@ -83,15 +83,16 @@
|
||||
$memory_usage = -1;
|
||||
}
|
||||
|
||||
if($auth) {
|
||||
// For session timer
|
||||
$maxlifetime = ini_get("session.gc_maxlifetime");
|
||||
|
||||
// For session timer
|
||||
$maxlifetime = ini_get("session.gc_maxlifetime");
|
||||
|
||||
// Generate CSRF token
|
||||
if(empty($_SESSION['token'])) {
|
||||
$_SESSION['token'] = base64_encode(openssl_random_pseudo_bytes(32));
|
||||
// Generate CSRF token
|
||||
if(empty($_SESSION['token'])) {
|
||||
$_SESSION['token'] = base64_encode(openssl_random_pseudo_bytes(32));
|
||||
}
|
||||
$token = $_SESSION['token'];
|
||||
}
|
||||
$token = $_SESSION['token'];
|
||||
|
||||
if(isset($setupVars['WEBUIBOXEDLAYOUT']))
|
||||
{
|
||||
@@ -149,6 +150,7 @@
|
||||
|
||||
<link href="style/vendor/AdminLTE.min.css" rel="stylesheet" type="text/css" />
|
||||
<link href="style/vendor/skin-blue.min.css" rel="stylesheet" type="text/css" />
|
||||
<link href="style/pi-hole.css" rel="stylesheet" type="text/css" />
|
||||
<link rel="icon" type="image/png" sizes="160x160" href="img/logo.svg" />
|
||||
<style type="text/css">
|
||||
.glow { text-shadow: 0px 0px 5px #fff; }
|
||||
@@ -171,7 +173,7 @@
|
||||
<!-- /JS Warning -->
|
||||
<script src="scripts/pi-hole/js/header.js"></script>
|
||||
<!-- Send token to JS -->
|
||||
<div id="token" hidden><?php echo $token ?></div>
|
||||
<div id="token" hidden><?php if($auth) echo $token; ?></div>
|
||||
<div class="wrapper">
|
||||
<header class="main-header">
|
||||
<!-- Logo -->
|
||||
@@ -256,18 +258,18 @@
|
||||
<?php
|
||||
$pistatus = exec('sudo pihole status web');
|
||||
if ($pistatus == "1") {
|
||||
echo '<a href="#" id="status"><i class="fa fa-circle" style="color:#7FFF00"></i> Active</a>';
|
||||
echo '<a id="status"><i class="fa fa-circle" style="color:#7FFF00"></i> Active</a>';
|
||||
} elseif ($pistatus == "0") {
|
||||
echo '<a href="#" id="status"><i class="fa fa-circle" style="color:#FF0000"></i> Offline</a>';
|
||||
echo '<a id="status"><i class="fa fa-circle" style="color:#FF0000"></i> Offline</a>';
|
||||
} elseif ($pistatus == "-1") {
|
||||
echo '<a href="#" id="status"><i class="fa fa-circle" style="color:#FF0000"></i> DNS service not running</a>';
|
||||
echo '<a id="status"><i class="fa fa-circle" style="color:#FF0000"></i> DNS service not running</a>';
|
||||
} else {
|
||||
echo '<a href="#" id="status"><i class="fa fa-circle" style="color:#ff9900"></i> Unknown</a>';
|
||||
echo '<a id="status"><i class="fa fa-circle" style="color:#ff9900"></i> Unknown</a>';
|
||||
}
|
||||
|
||||
// CPU Temp
|
||||
if ($celsius >= -273.15) {
|
||||
echo "<a href=\"#\" id=\"temperature\"><i class=\"fa fa-fire\" style=\"color:";
|
||||
echo "<a id=\"temperature\"><i class=\"fa fa-fire\" style=\"color:";
|
||||
if ($celsius > 60) {
|
||||
echo "#FF0000";
|
||||
}
|
||||
@@ -293,7 +295,7 @@
|
||||
?>
|
||||
<br/>
|
||||
<?php
|
||||
echo "<a href=\"#\"><i class=\"fa fa-circle\" style=\"color:";
|
||||
echo "<a><i class=\"fa fa-circle\" style=\"color:";
|
||||
if ($loaddata[0] > $nproc) {
|
||||
echo "#FF0000";
|
||||
}
|
||||
@@ -305,7 +307,7 @@
|
||||
?>
|
||||
<br/>
|
||||
<?php
|
||||
echo "<a href=\"#\"><i class=\"fa fa-circle\" style=\"color:";
|
||||
echo "<a><i class=\"fa fa-circle\" style=\"color:";
|
||||
if ($memory_usage > 0.75 || $memory_usage < 0.0) {
|
||||
echo "#FF0000";
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
<div class="panel-title text-center"><span class="logo-lg" style="font-size: 25px;"><b>Pi</b>-hole</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) { ?>
|
||||
<div class="form-group has-error login-box-msg">
|
||||
<label class="control-label"><i class="fa fa-times-circle-o"></i> Wrong password!</label>
|
||||
@@ -54,7 +55,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
}
|
||||
|
||||
$wrongpassword = false;
|
||||
$auth = false;
|
||||
|
||||
// Test if password is set
|
||||
if(strlen($pwhash) > 0)
|
||||
|
||||
@@ -6,7 +6,10 @@ header('Content-Type: text/event-stream');
|
||||
header('Cache-Control: no-cache');
|
||||
|
||||
function echoEvent($datatext) {
|
||||
echo "data: ".implode("\ndata: ", explode("\n", $datatext))."\n\n";
|
||||
if(!isset($_GET["IE"]))
|
||||
echo "data: ".implode("\ndata: ", explode("\n", $datatext))."\n\n";
|
||||
else
|
||||
echo $datatext;
|
||||
}
|
||||
|
||||
// Credit: http://stackoverflow.com/a/4694816/2087442
|
||||
|
||||
@@ -6,7 +6,7 @@ if(basename($_SERVER['SCRIPT_FILENAME']) !== "settings.php")
|
||||
}
|
||||
|
||||
function validIP($address){
|
||||
return !filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false;
|
||||
return !filter_var($address, FILTER_VALIDATE_IP) === false;
|
||||
}
|
||||
|
||||
// Check for existance of variable
|
||||
@@ -32,20 +32,17 @@ function validDomain($domain_name)
|
||||
return ( $validChars && $lengthCheck && $labelLengthCheck ); //length of each label
|
||||
}
|
||||
|
||||
$primaryDNSservers = [
|
||||
"8.8.8.8" => "Google",
|
||||
"208.67.222.222" => "OpenDNS",
|
||||
"4.2.2.1" => "Level3",
|
||||
"199.85.126.10" => "Norton",
|
||||
"8.26.56.26" => "Comodo"
|
||||
];
|
||||
|
||||
$secondaryDNSservers = [
|
||||
"8.8.4.4" => "Google",
|
||||
"208.67.220.220" => "OpenDNS",
|
||||
"4.2.2.2" => "Level3",
|
||||
"199.85.127.10" => "Norton",
|
||||
"8.20.247.20" => "Comodo"
|
||||
$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)",
|
||||
"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)"
|
||||
];
|
||||
|
||||
$error = "";
|
||||
@@ -57,46 +54,38 @@ function validDomain($domain_name)
|
||||
switch ($_POST["field"]) {
|
||||
// Set DNS server
|
||||
case "DNS":
|
||||
$primaryDNS = $_POST["primaryDNS"];
|
||||
$secondaryDNS = $_POST["secondaryDNS"];
|
||||
|
||||
// Get primary DNS server IP address
|
||||
if($primaryDNS === "Custom")
|
||||
$DNSservers = [];
|
||||
// Add selected predefined servers to list
|
||||
foreach ($DNSserverslist as $key => $value)
|
||||
{
|
||||
$primaryIP = $_POST["DNS1IP"];
|
||||
}
|
||||
else
|
||||
{
|
||||
$primaryIP = array_flip($primaryDNSservers)[$primaryDNS];
|
||||
}
|
||||
|
||||
// Validate primary IP
|
||||
if (!validIP($primaryIP))
|
||||
{
|
||||
$error .= "Primary IP (".$primaryIP.") is invalid!<br>";
|
||||
}
|
||||
|
||||
// Get secondary DNS server IP address
|
||||
if($secondaryDNS === "Custom")
|
||||
{
|
||||
if(strlen($_POST["DNS2IP"]) > 0)
|
||||
if(array_key_exists("DNSserver".str_replace(".","_",$key),$_POST))
|
||||
{
|
||||
$secondaryIP = $_POST["DNS2IP"];
|
||||
}
|
||||
else
|
||||
{
|
||||
$secondaryIP = "none";
|
||||
array_push($DNSservers,$key);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
// Test custom server fields
|
||||
for($i=1;$i<=4;$i++)
|
||||
{
|
||||
$secondaryIP = array_flip($secondaryDNSservers)[$secondaryDNS];
|
||||
if(array_key_exists("custom".$i,$_POST))
|
||||
{
|
||||
$IP = $_POST["custom".$i."val"];
|
||||
if(validIP($IP))
|
||||
{
|
||||
array_push($DNSservers,$IP);
|
||||
}
|
||||
else
|
||||
{
|
||||
$error .= "IP (".$IP.") is invalid!<br>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validate secondary IP
|
||||
if (!validIP($secondaryIP) && $secondaryIP != "none" && strlen($secondaryIP) > 0)
|
||||
// Check if at least one DNS server has been added
|
||||
if(count($DNSservers) < 1)
|
||||
{
|
||||
$error .= "Secondary IP (".$secondaryIP.") is invalid!<br>";
|
||||
$error .= "No DNS server has been selected.<br>";
|
||||
}
|
||||
|
||||
// Check if domain-needed is requested
|
||||
@@ -112,18 +101,29 @@ function validDomain($domain_name)
|
||||
// Check if domain-needed is requested
|
||||
if(isset($_POST["DNSbogusPriv"]))
|
||||
{
|
||||
$extra .= "bogus-priv";
|
||||
$extra .= "bogus-priv ";
|
||||
}
|
||||
else
|
||||
{
|
||||
$extra .= "no-bogus-priv";
|
||||
$extra .= "no-bogus-priv ";
|
||||
}
|
||||
|
||||
// Check if DNSSEC is requested
|
||||
if(isset($_POST["DNSSEC"]))
|
||||
{
|
||||
$extra .= "dnssec";
|
||||
}
|
||||
else
|
||||
{
|
||||
$extra .= "no-dnssec";
|
||||
}
|
||||
|
||||
// If there has been no error we can save the new DNS server IPs
|
||||
if(!strlen($error))
|
||||
{
|
||||
exec("sudo pihole -a setdns ".$primaryIP." ".$secondaryIP." ".$extra);
|
||||
$success .= "The DNS settings have been updated";
|
||||
$IPs = implode (",", $DNSservers);
|
||||
exec("sudo pihole -a setdns ".$IPs." ".$extra);
|
||||
$success .= "The DNS settings have been updated (using ".count($DNSservers)." DNS servers)";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -13,6 +13,9 @@ switch($type) {
|
||||
case "black":
|
||||
exec("sudo pihole -b -q -d ${_POST['domain']}");
|
||||
break;
|
||||
case "wild":
|
||||
exec("sudo pihole -wild -q -d ${_POST['domain']}");
|
||||
break;
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
<?php
|
||||
require('func.php');
|
||||
function process_zip($name)
|
||||
{
|
||||
global $zip;
|
||||
$zippointer = $zip->getStream($name);
|
||||
if(!$zippointer)
|
||||
{
|
||||
echo "$name not found in provided ZIP file, skipping...<br>";
|
||||
return;
|
||||
}
|
||||
$contents = "";
|
||||
while (!feof($zippointer)) {
|
||||
$contents .= fread($zippointer, 4096);
|
||||
}
|
||||
fclose($zippointer);
|
||||
$domains = array_filter(explode("\n",$contents));
|
||||
check_domains($domains);
|
||||
return $domains;
|
||||
}
|
||||
|
||||
function add_to_zip($path,$name)
|
||||
{
|
||||
global $zip;
|
||||
if(file_exists($path.$name))
|
||||
$zip->addFile($path.$name,$name);
|
||||
}
|
||||
|
||||
function check_domains($domains)
|
||||
{
|
||||
foreach($domains as $domain)
|
||||
{
|
||||
if(!is_valid_domain_name($domain)){
|
||||
die(htmlspecialchars($domain).' is not a valid domain');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getWildcardListContent() {
|
||||
if(file_exists("/etc/dnsmasq.d/03-pihole-wildcard.conf"))
|
||||
{
|
||||
$rawList = file_get_contents("/etc/dnsmasq.d/03-pihole-wildcard.conf");
|
||||
$wclist = explode("\n", $rawList);
|
||||
$list = [];
|
||||
|
||||
foreach ($wclist as $entry) {
|
||||
$expl = explode("/", $entry);
|
||||
if(count($expl) == 3)
|
||||
{
|
||||
array_push($list,$expl[1]);
|
||||
}
|
||||
}
|
||||
|
||||
return implode("\n",array_unique($list));
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
if($_POST["action"] == "in")
|
||||
{
|
||||
if($_FILES["zip_file"]["name"])
|
||||
{
|
||||
$filename = $_FILES["zip_file"]["name"];
|
||||
$source = $_FILES["zip_file"]["tmp_name"];
|
||||
$type = $_FILES["zip_file"]["type"];
|
||||
|
||||
$name = explode(".", $filename);
|
||||
$accepted_types = array('application/zip', 'application/x-zip-compressed', 'multipart/x-zip', 'application/x-compressed');
|
||||
$okay = false;
|
||||
foreach($accepted_types as $mime_type) {
|
||||
if($mime_type == $type) {
|
||||
$okay = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$continue = strtolower($name[1]) == 'zip' ? true : false;
|
||||
if(!$continue || !$okay) {
|
||||
die("The file you are trying to upload is not a .zip file. Please try again.");
|
||||
}
|
||||
|
||||
$zip = new ZipArchive();
|
||||
$x = $zip->open($source);
|
||||
if ($x === true) {
|
||||
if(isset($_POST["blacklist"]))
|
||||
{
|
||||
$blacklist = process_zip("blacklist.txt");
|
||||
exec("sudo pihole -b -q ".implode(" ", $blacklist));
|
||||
}
|
||||
|
||||
if(isset($_POST["whitelist"]))
|
||||
{
|
||||
$whitelist = process_zip("whitelist.txt");
|
||||
exec("sudo pihole -w -q ".implode(" ", $whitelist));
|
||||
}
|
||||
|
||||
if(isset($_POST["wildlist"]))
|
||||
{
|
||||
$wildlist = process_zip("wildcardblocking.txt");
|
||||
exec("sudo pihole -wild -q ".implode(" ", $wildlist));
|
||||
}
|
||||
|
||||
echo "OK";
|
||||
|
||||
$zip->close();
|
||||
}
|
||||
else
|
||||
{
|
||||
die("Error opening uploaded archive!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
die("No file transmitted.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$archive_file_name = "/var/www/html/pi-hole-teleporter_".microtime(true).".zip";
|
||||
$zip = new ZipArchive();
|
||||
touch($archive_file_name);
|
||||
$res = $zip->open($archive_file_name, ZipArchive::CREATE | ZipArchive::OVERWRITE);
|
||||
|
||||
if ($res !== TRUE) {
|
||||
exit("cannot open/create $archive_file_name<br>Error: ".$zip->getStatusString()."<br>PHP user: ".exec('whoami')."\n");
|
||||
}
|
||||
|
||||
add_to_zip("/etc/pihole/","whitelist.txt");
|
||||
add_to_zip("/etc/pihole/","blacklist.txt");
|
||||
add_to_zip("/etc/pihole/","adlists.list");
|
||||
add_to_zip("/etc/pihole/","setupVars.conf");
|
||||
|
||||
$zip->addFromString("wildcardblocking.txt", getWildcardListContent());
|
||||
$zip->close();
|
||||
|
||||
header("Content-type: application/zip");
|
||||
header('Content-Transfer-Encoding: binary');
|
||||
header("Content-Disposition: attachment; filename=pi-hole-teleporter.zip");
|
||||
header("Content-length: " . filesize($archive_file_name));
|
||||
header("Pragma: no-cache");
|
||||
header("Expires: 0");
|
||||
ob_end_clean();
|
||||
readfile($archive_file_name);
|
||||
exit;
|
||||
}
|
||||
|
||||
?>
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
/*!
|
||||
* jQuery Input Ip Address Control : v0.1beta (2010/11/09 16:15:43)
|
||||
* Copyright (c) 2010 jquery-input-ip-address-control@googlecode.com
|
||||
* Licensed under the MIT license and GPL licenses.
|
||||
*
|
||||
*/
|
||||
eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('(l($){Q.1o.1t=l(){E=/\\b(?:(?:25[0-5]|2[0-4][0-9]|[1m]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[1m]?[0-9][0-9]?)\\b/;h E.1a(p.1i())};Q.1o.1S=l(){E=/\\b([A-16-9]{1,4}:){7}([A-16-9]{1,4})\\b/i;h E.1a(p.1i())};$.1X.1h({y:l(u,c){f(p.z==0)h;f(1k u==\'1f\'){c=(1k c==\'1f\')?c:u;h p.1d(l(){f(p.18){p.1s();p.18(u,c)}w f(p.1e){t C=p.1e();C.1L(S);C.1z(\'10\',c);C.1b(\'10\',u);C.1w()}})}w{f(p[0].18){u=p[0].1u;c=p[0].1C}w f(14.12&&14.12.19){t C=14.12.19();u=0-C.1D().1b(\'10\',-1E);c=u+C.1H.z}h{u:u,c:c}}},1B:l(s){s=$.1h({v:4},s);f(s.v==4){s.W=M I(\'[0-9]\',\'g\');s.r=\'R.R.R.R\'}f(s.v==6){s.W=M I(\'[A-16-9]\',\'1x\');s.r=\'x:x:x:x:x:x:x:x\'}s.D=s.r.K(\'\').Y();s.q=s.r.X(M I(s.D,\'g\'),\'\').K(\'\').Y();s.O=s.r.K(s.q).Y();h $(p).1d(l(){t a={k:T,n:T,o:T,d:T};a.d=$(p);f(a.d.m()==\'\'||!J(a.d.m()))a.d.m(s.r);a.d.1j(\'1Z\',(s.v==4?15:1c)).1j(\'1W\',(s.v==4?15:1c));l J(o){h 24("o.21"+s.v+"()")};l P(){a.k=a.d.y();a.o=J(L(a.d.m()))?L(a.d.m()):a.o;a.n=a.d.m().K(\'\')};l 1n(o){t G=o.K(s.q);1p(t j=0;j<G.z;j++){1M((s.O.z-G[j].z)>0)G[j]+=s.D}h G.H(s.q)};l L(o){t E=M I(s.O,\'g\');t 1g=M I(s.D,\'g\');h o.X(E,\'0\').X(1g,\'\')};l 11(e){1R(e.1Q){U 8:f(a.n[a.k.c-1]!=s.q){a.n[a.k.c-1]=s.D;a.d.m(a.n.H("")).m()}a.d.y(a.k.c-1);h B;V;U 13:U 1T:a.d.17();V;U 1P:f(a.n[a.k.c]!=s.q&&a.k.c<s.r.z){a.n[a.k.c]=s.D;a.d.m(a.n.H(""))}f(a.k.c<s.r.z)a.d.y(a.k.c+1);h B;V}h S};a.d.N(\'1O\',l(e){P();f($.1l.1K||$.1l.1V){h 11(e)}}).N(\'1U\',l(e){P();f(e.23||e.22||e.1Y)h S;w f((e.F>=20&&e.F<=1N)||e.F>1J){f(Q.1q(e.F).1y(s.W)){a.n[a.k.c]=Q.1q(e.F);f(!J(L(a.n.H(\'\')))){f((a.k.c==0||a.n[a.k.c-1]==s.q)){1p(t i=a.k.c+1;i<a.k.c+s.O.z;i++){a.n[i]=s.D}}w h B}a.d.m(a.n.H(\'\'));f(a.n[a.k.c+1]==s.q){a.d.y(a.k.c+2)}w{a.d.y(a.k.c+1)}h B}w f(s.q.1v(0)==e.F){t Z=a.d.m().1A(s.q,a.k.c);f(Z==-1)h B;f(a.n[a.k.c-1]==s.q)h B;a.k.c=Z;a.d.y(a.k.c+1);h B}w h B}h 11(e)}).N(\'17\',l(){f(a.d.m()==s.r)h S;t o=L($.1G(a.d.m()));f(J(o))a.d.m(o);w a.d.m(a.o)}).N(\'1s\',l(){1r(l(){P();f(a.d.m()!=s.r)a.d.m(1n(a.o));a.d.y(0)},0)}).N(\'1I\',l(e){a.d.m(\'\');1r(l(){a.d.17()},0)})})}})})(1F);',62,130,'||||||||||ctx||end|input||if||return|||cursor|function|val|buffer|ip|this|separator|label||var|begin||else|____|caret|length||false|range|place|rgx|which|part|join|RegExp|isIp|split|unmask|new|bind|partplace|loadCtx|String|___|true|null|case|break|rgxcase|replace|pop|pos|character|entryNoCharacter|selection||document||F0|blur|setSelectionRange|createRange|test|moveStart|39|each|createTextRange|number|rgx2|extend|toString|attr|typeof|browser|01|mask|prototype|for|fromCharCode|setTimeout|focus|isIpv4|selectionStart|charCodeAt|select|gi|match|moveEnd|indexOf|ipAddress|selectionEnd|duplicate|100000|jQuery|trim|text|paste|186|webkit|collapse|while|125|keydown|46|keyCode|switch|isIpv6|27|keypress|msie|size|fn|metaKey|maxlength|32|isIpv|altKey|ctrlKey|eval|'.split('|'),0,{}))
|
||||
+125
-43
@@ -198,7 +198,7 @@
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">From</div>
|
||||
<input type="text" class="form-control DHCPgroup" name="from" value="<?php echo $DHCPstart; ?>" data-inputmask="'alias': 'ip'" data-mask <?php if(!$DHCP){ ?>disabled<?php } ?>>
|
||||
<input type="text" class="form-control DHCPgroup" name="from" id="DHCPfrom" value="<?php echo $DHCPstart; ?>" <?php if(!$DHCP){ ?>disabled<?php } ?>>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -206,7 +206,7 @@
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">To</div>
|
||||
<input type="text" class="form-control DHCPgroup" name="to" value="<?php echo $DHCPend; ?>" data-inputmask="'alias': 'ip'" data-mask <?php if(!$DHCP){ ?>disabled<?php } ?>>
|
||||
<input type="text" class="form-control DHCPgroup" name="to" id="DHCPto" value="<?php echo $DHCPend; ?>" <?php if(!$DHCP){ ?>disabled<?php } ?>>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -215,7 +215,7 @@
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">Router</div>
|
||||
<input type="text" class="form-control DHCPgroup" name="router" value="<?php echo $DHCProuter; ?>" data-inputmask="'alias': 'ip'" data-mask <?php if(!$DHCP){ ?>disabled<?php } ?>>
|
||||
<input type="text" class="form-control DHCPgroup" name="router" id="DHCProuter" value="<?php echo $DHCProuter; ?>" <?php if(!$DHCP){ ?>disabled<?php } ?>>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -360,30 +360,41 @@
|
||||
|
||||
<?php
|
||||
// DNS settings
|
||||
if(isset($setupVars["PIHOLE_DNS_1"])){
|
||||
if(isset($primaryDNSservers[$setupVars["PIHOLE_DNS_1"]]))
|
||||
{
|
||||
$piHoleDNS1 = $primaryDNSservers[$setupVars["PIHOLE_DNS_1"]];
|
||||
$DNSservers = [];
|
||||
$DNSactive = [];
|
||||
for($i=1;$i<=12;$i++)
|
||||
{
|
||||
if(isset($setupVars["PIHOLE_DNS_".$i])){
|
||||
if(isset($DNSserverslist[$setupVars["PIHOLE_DNS_".$i]]))
|
||||
{
|
||||
$DNSservers[] = [$setupVars["PIHOLE_DNS_".$i],$DNSserverslist[$setupVars["PIHOLE_DNS_".$i]]];
|
||||
array_push($DNSactive,$setupVars["PIHOLE_DNS_".$i]);
|
||||
}
|
||||
elseif(strpos($setupVars["PIHOLE_DNS_".$i],"."))
|
||||
{
|
||||
$DNSservers[] = [$setupVars["PIHOLE_DNS_".$i],"CustomIPv4"];
|
||||
if(!isset($custom1))
|
||||
{
|
||||
$custom1 = $setupVars["PIHOLE_DNS_".$i];
|
||||
}
|
||||
else
|
||||
{
|
||||
$custom2 = $setupVars["PIHOLE_DNS_".$i];
|
||||
}
|
||||
}
|
||||
elseif(strpos($setupVars["PIHOLE_DNS_".$i],":"))
|
||||
{
|
||||
$DNSservers[] = [$setupVars["PIHOLE_DNS_".$i],"CustomIPv6"];
|
||||
if(!isset($custom3))
|
||||
{
|
||||
$custom3 = $setupVars["PIHOLE_DNS_".$i];
|
||||
}
|
||||
else
|
||||
{
|
||||
$custom4 = $setupVars["PIHOLE_DNS_".$i];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$piHoleDNS1 = "Custom";
|
||||
}
|
||||
} else {
|
||||
$piHoleDNS1 = "unknown";
|
||||
}
|
||||
|
||||
if(isset($setupVars["PIHOLE_DNS_2"])){
|
||||
if(isset($secondaryDNSservers[$setupVars["PIHOLE_DNS_2"]]))
|
||||
{
|
||||
$piHoleDNS2 = $secondaryDNSservers[$setupVars["PIHOLE_DNS_2"]];
|
||||
}
|
||||
else
|
||||
{
|
||||
$piHoleDNS2 = "Custom";
|
||||
}
|
||||
} else {
|
||||
$piHoleDNS2 = "unknown";
|
||||
}
|
||||
|
||||
if(isset($setupVars["DNS_FQDN_REQUIRED"])){
|
||||
@@ -411,6 +422,19 @@
|
||||
} else {
|
||||
$DNSbogusPriv = true;
|
||||
}
|
||||
|
||||
if(isset($setupVars["DNSSEC"])){
|
||||
if($setupVars["DNSSEC"])
|
||||
{
|
||||
$DNSSEC = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$DNSSEC = false;
|
||||
}
|
||||
} else {
|
||||
$DNSSEC = false;
|
||||
}
|
||||
?>
|
||||
<div class="box box-warning">
|
||||
<div class="box-header with-border">
|
||||
@@ -419,28 +443,41 @@
|
||||
<div class="box-body">
|
||||
<form role="form" method="post">
|
||||
<div class="col-lg-6">
|
||||
<label>Primary DNS Server</label>
|
||||
<label>Upstream DNS Servers</label>
|
||||
<div class="form-group">
|
||||
<?php foreach ($primaryDNSservers as $key => $value) { ?> <div class="radio"><label><input type="radio" name="primaryDNS" value="<?php echo $value;?>" <?php if($piHoleDNS1 === $value){ ?>checked<?php } ?> ><?php echo $value;?> (<?php echo $key;?>)</label></div> <?php } ?>
|
||||
<label>Custom</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon"><input type="radio" name="primaryDNS" value="Custom"
|
||||
<?php if($piHoleDNS1 === "Custom"){ ?>checked<?php } ?>></div>
|
||||
<input type="text" name="DNS1IP" class="form-control" data-inputmask="'alias': 'ip'" data-mask
|
||||
<?php if($piHoleDNS1 === "Custom"){ ?>value="<?php echo $setupVars["PIHOLE_DNS_1"]; ?>"<?php } ?>>
|
||||
</div>
|
||||
<?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>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<label>Secondary DNS Server</label>
|
||||
<label> </label>
|
||||
<div class="form-group">
|
||||
<?php foreach ($secondaryDNSservers as $key => $value) { ?> <div class="radio"><label><input type="radio" name="secondaryDNS" value="<?php echo $value;?>" <?php if($piHoleDNS2 === $value){ ?>checked<?php } ?> ><?php echo $value;?> (<?php echo $key;?>)</label></div> <?php } ?>
|
||||
<label>Custom</label>
|
||||
<label>Custom 1 (IPv4)</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon"><input type="radio" name="secondaryDNS" value="Custom"
|
||||
<?php if($piHoleDNS2 === "Custom"){ ?>checked<?php } ?>></div>
|
||||
<input type="text" name="DNS2IP" class="form-control" data-inputmask="'alias': 'ip'" data-mask
|
||||
<?php if($piHoleDNS2 === "Custom"){ ?>value="<?php echo $setupVars["PIHOLE_DNS_2"]; ?>"<?php } ?>>
|
||||
<div class="input-group-addon"><input type="checkbox" name="custom1" value="Customv4"
|
||||
<?php if(isset($custom1)){ ?>checked<?php } ?>></div>
|
||||
<input type="text" name="custom1val" class="form-control" id="custom1val" <?php if(isset($custom1)){ ?>value="<?php echo $custom1; ?>"<?php } ?>>
|
||||
</div>
|
||||
<label>Custom 2 (IPv4)</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon"><input type="checkbox" name="custom2" value="Customv4"
|
||||
<?php if(isset($custom2)){ ?>checked<?php } ?>></div>
|
||||
<input type="text" name="custom2val" class="form-control" id="custom2val" <?php if(isset($custom2)){ ?>value="<?php echo $custom2; ?>"<?php } ?>>
|
||||
</div>
|
||||
<label>Custom 3 (IPv6)</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon"><input type="checkbox" name="custom3" value="Customv6"
|
||||
<?php if(isset($custom3)){ ?>checked<?php } ?>></div>
|
||||
<input type="text" name="custom3val" class="form-control" id="custom3val" <?php if(isset($custom3)){ ?>value="<?php echo $custom3; ?>"<?php } ?>>
|
||||
</div>
|
||||
<label>Custom 4 (IPv6)</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon"><input type="checkbox" name="custom4" value="Customv6"
|
||||
<?php if(isset($custom4)){ ?>checked<?php } ?>></div>
|
||||
<input type="text" name="custom4val" class="form-control" id="custom4val" <?php if(isset($custom4)){ ?>value="<?php echo $custom4; ?>"<?php } ?>>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -459,6 +496,10 @@
|
||||
<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>
|
||||
<div class="form-group">
|
||||
<div class="checkbox"><label><input type="checkbox" name="DNSSEC" <?php if($DNSSEC){ ?>checked<?php } ?>> Use DNSSEC</label></div>
|
||||
</div>
|
||||
<p>Validate DNS replies and cache DNSSEC data. When forwarding DNS queries, Pi-hole requests the DNSSEC records needed to validate the replies. Use Google or Norton DNS servers when activating DNSSEC. Note that the size of your log might increase significantly when enabling DNSSEC. A DNSSEC resolver test can be found <a href="http://dnssec.vs.uni-due.de/" target="_blank">here</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -711,6 +752,47 @@
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box box-danger collapsed-box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">Pi-hole Teleporter</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 (extension_loaded('zip')) { ?>
|
||||
<form role="form" method="post" id="takeoutform" action="scripts/pi-hole/php/teleporter.php" target="_blank" enctype="multipart/form-data">
|
||||
<div class="col-lg-12">
|
||||
<p>Export your Pi-hole lists as downloadable ZIP file</p>
|
||||
<button type="submit" class="btn btn-default" name="action" value="out">Export</button>
|
||||
<hr>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<label>Import ...</label>
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" name="whitelist" value="true" checked> Whitelist</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" name="blacklist" value="true" checked> Blacklist (exact)</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" name="wildlist" value="true" checked> Blacklist (wildcard)</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="form-group">
|
||||
<label for="zip_file">File input</label>
|
||||
<input type="file" name="zip_file" id="zip_file">
|
||||
<p class="help-block">Upload only Pi-hole backup files.</p>
|
||||
<button type="submit" class="btn btn-default" name="action" value="in">Import</button>
|
||||
</div>
|
||||
</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>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -719,6 +801,6 @@
|
||||
?>
|
||||
|
||||
<script src="scripts/vendor/jquery.inputmask.js"></script>
|
||||
<script src="scripts/vendor/jquery.inputmask.extensions.js"></script>
|
||||
<script src="scripts/vendor/jquery.input-ip-address-control-1.0.min.js"></script>
|
||||
<script src="scripts/vendor/jquery.confirm.min.js"></script>
|
||||
<script src="scripts/pi-hole/js/settings.js"></script>
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
.small-box {
|
||||
-webkit-user-select: none; /* Chrome/Safari */
|
||||
-moz-user-select: none; /* Firefox */
|
||||
-ms-user-select: none; /* IE10+ */
|
||||
|
||||
/* Rules below not implemented in browsers yet */
|
||||
-o-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
Reference in New Issue
Block a user