Merge branch 'devel' into wildcard_blacklisting

This commit is contained in:
DL6ER
2017-01-09 14:51:54 +01:00
14 changed files with 180 additions and 75 deletions
+1
View File
@@ -1,5 +1,6 @@
Pi-hole Admin Dashboard
============
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/938b4d9e61b7487da77cf63ba05c683d)](https://www.codacy.com/app/Pi-hole/AdminLTE?utm_source=github.com&utm_medium=referral&utm_content=pi-hole/AdminLTE&utm_campaign=badger)
[![Join the chat at https://gitter.im/pi-hole/AdminLTE](https://badges.gitter.im/pi-hole/AdminLTE.svg)](https://gitter.im/pi-hole/AdminLTE?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif "AdminLTE Presentation")](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3J2L3Z4DHW9UY "Donate")
+1 -1
View File
@@ -51,7 +51,7 @@ 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">&times;</span></button>
Failure! Something went wrong.
Failure! Something went wrong.<br/><span id="err"></span>
</div>
<!-- Domain List -->
+10 -2
View File
@@ -40,7 +40,7 @@ function piholeChange(action, duration)
case "enable":
btnStatus = $("#flip-status-enable");
btnStatus.html("<i class='fa fa-spinner'> </i>");
$.getJSON("api.php?enable&token=" + token, (data) => {
$.getJSON("api.php?enable&token=" + token, function(data) {
if(data.status === "enabled") {
btnStatus.html("");
piholeChanged("enabled");
@@ -51,7 +51,7 @@ function piholeChange(action, duration)
case "disable":
btnStatus = $("#flip-status-disable");
btnStatus.html("<i class='fa fa-spinner'> </i>");
$.getJSON("api.php?disable=" + duration + "&token=" + token, (data) => {
$.getJSON("api.php?disable=" + duration + "&token=" + token, function(data) {
if(data.status === "disabled") {
btnStatus.html("");
piholeChanged("disabled");
@@ -196,3 +196,11 @@ if(versionCompare(piholeVersion, "v2.9.5") < 1)
{
$("#btnSearchExact").hide();
}
// Handle Strg + Enter button on Login page
$(document).keypress(function(e) {
if((e.keyCode === 10 || e.keyCode === 13) && e.ctrlKey && $("#loginpw").is(":focus")) {
$("#loginform").attr("action", "settings.php");
$("#loginform").submit();
}
});
+10 -6
View File
@@ -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);
});
@@ -291,7 +295,7 @@ $(document).ready(function() {
enabled: true,
mode: "x-axis",
callbacks: {
title(tooltipItem, data) {
title: function(tooltipItem, data) {
var label = tooltipItem[0].xLabel;
var time = label.match(/(\d?\d):?(\d?\d?)/);
var h = parseInt(time[1], 10);
@@ -300,7 +304,7 @@ $(document).ready(function() {
var to = padNumber(h)+":"+padNumber(m+9)+":59";
return "Queries from "+from+" to "+to;
},
label(tooltipItems, data) {
label: function(tooltipItems, data) {
if(tooltipItems.datasetIndex === 1)
{
var percentage = 0.0;
+4 -2
View File
@@ -126,6 +126,7 @@ function add(arg) {
var alInfo = $("#alInfo");
var alSuccess = $("#alSuccess");
var alFailure = $("#alFailure");
var err = $("#err");
alInfo.show();
alSuccess.hide();
alFailure.hide();
@@ -137,10 +138,11 @@ function add(arg) {
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 {
+15 -3
View File
@@ -69,6 +69,17 @@ 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;
@@ -94,11 +105,11 @@ $(document).ready(function() {
status = data[4];
if (status.substr(0,2) === "Pi") {
$(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{
$(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>" );
}
},
@@ -106,8 +117,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" },
+1
View File
@@ -55,6 +55,7 @@ $(".confirm-flushlogs").confirm({
$("#DHCPchk").click(function() {
$("input.DHCPgroup").prop("disabled", !this.checked);
$("#dhcpnotice").prop("hidden", !this.checked).addClass("lookatme");
});
var leasetable;
+16 -7
View File
@@ -35,7 +35,11 @@ function check_cors() {
// to validate that the client is authorized, only unauthorized.
$server_host = $_SERVER['HTTP_HOST'];
// If HTTP_HOST contains a non-standard port (!= 80) we have to strip the port
// Use parse_url if HTTP_HOST contains a colon (:) to get the host name
// e.g.
// 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, ":"))
{
$server_host = parse_url($_SERVER['HTTP_HOST'], PHP_URL_HOST);
@@ -48,7 +52,7 @@ function check_cors() {
if(isset($_SERVER['HTTP_ORIGIN'])) {
$server_origin = $_SERVER['HTTP_ORIGIN'];
// If HTTP_ORIGIN contains a non-standard port (!= 80) we have to strip the port
// Detect colon in $_SERVER['HTTP_ORIGIN'] (see comment above)
if(strpos($server_origin, ":"))
{
$server_origin = parse_url($_SERVER['HTTP_ORIGIN'], PHP_URL_HOST);
@@ -99,14 +103,19 @@ 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'));
}
}
}
}
function list_verify($type) {
global $pwhash, $wrongpassword;
if(!isset($_POST['domain']) || !isset($_POST['list']) || !(isset($_POST['pw']) || isset($_POST['token']))) {
log_and_die("Missing POST variables");
}
@@ -121,11 +130,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
+12 -16
View File
@@ -679,14 +679,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];
@@ -721,14 +719,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];
+25 -24
View File
@@ -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']))
{
@@ -171,7 +172,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 -->
@@ -249,25 +250,25 @@
<!-- Sidebar user panel -->
<div class="user-panel">
<div class="pull-left image">
<img src="img/logo.svg" class="img-responsive" alt="Pi-hole logo" />
<img src="img/logo.svg" class="img-responsive" alt="Pi-hole logo" style="display: table; table-layout: fixed; height: 67px;" />
</div>
<div class="pull-left info">
<p>Status</p>
<?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,33 +294,33 @@
?>
<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';
echo "#FF0000";
}
else
{
echo '#7FFF00';
echo "#7FFF00";
}
echo '""></i> Load:&nbsp;&nbsp;' . $loaddata[0] . '&nbsp;&nbsp;' . $loaddata[1] . '&nbsp;&nbsp;'. $loaddata[2] . '</a>';
echo "\"></i> Load:&nbsp;&nbsp;" . $loaddata[0] . "&nbsp;&nbsp;" . $loaddata[1] . "&nbsp;&nbsp;". $loaddata[2] . "</a>";
?>
<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';
echo "#FF0000";
}
else
{
echo '#7FFF00';
echo "#7FFF00";
}
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) . "%</a>";
}
else
{
echo '""></i> Memory usage:&nbsp;&nbsp; N/A</a>';
echo "\"></i> Memory usage:&nbsp;&nbsp; N/A</a>";
}
?>
</div>
@@ -442,7 +443,7 @@
// Show Logout button if $auth is set and authorization is required
if(strlen($pwhash) > 0) { ?>
<li>
<a href="index.php?logout">
<a href="?logout">
<i class="fa fa-user-times"></i> <span>Logout</span>
</a>
</li>
+9 -3
View File
@@ -13,13 +13,19 @@
</div>
<div class="panel-body">
<form action="" method="post">
<form action="" id="loginform" method="post">
<div class="form-group has-feedback <?php if ($wrongpassword) { ?>has-error<?php } ?> ">
<input type="password" name="pw" class="form-control" placeholder="Password" autofocus>
<input type="password" id="loginpw" name="pw" class="form-control" placeholder="Password" autofocus>
<span class="glyphicon glyphicon-lock form-control-feedback"></span>
</div>
<div class="row">
<div class="col-xs-4 col-xs-offset-8">
<div class="col-xs-8">
<ul>
<li><tt>Return</tt> &rarr; Log in and go to requested page (<?php echo $scriptname; ?>)</li>
<li><tt>Ctrl+Return</tt> &rarr; Log in and go to Settings page</li>
</ul>
</div>
<div class="col-xs-4">
<button type="submit" href="#" class="btn btn-primary pull-right"><i class="glyphicon glyphicon-log-in"></i>&nbsp;&nbsp;&nbsp;Log in</button>
</div>
</div>
+1
View File
@@ -21,6 +21,7 @@
}
$wrongpassword = false;
$auth = false;
// Test if password is set
if(strlen($pwhash) > 0)
+13 -2
View File
@@ -355,10 +355,21 @@ function validDomain($domain_name)
$error .= "Lease time ".$leasetime." is invalid!<br>";
}
if(isset($_POST["useIPv6"]))
{
$ipv6 = "true";
$type = "(IPv4 + IPv6)";
}
else
{
$ipv6 = "false";
$type = "(IPv4)";
}
if(!strlen($error))
{
exec("sudo pihole -a enabledhcp ".$from." ".$to." ".$router." ".$leasetime." ".$domain);
$success .= "The DHCP server has been activated";
exec("sudo pihole -a enabledhcp ".$from." ".$to." ".$router." ".$leasetime." ".$domain." ".$ipv6);
$success .= "The DHCP server has been activated ".$type;
}
}
else
+62 -9
View File
@@ -9,6 +9,16 @@
max-width: none;
white-space: nowrap;
}
@-webkit-keyframes Pulse{
from {color:#630030;-webkit-text-shadow:0 0 9px #333;}
50% {color:#e33100;-webkit-text-shadow:0 0 18px #e33100;}
to {color:#630030;-webkit-text-shadow:0 0 9px #333;}
}
p.lookatme {
-webkit-animation-name: Pulse;
-webkit-animation-duration: 2s;
-webkit-animation-iteration-count: infinite;
}
</style>
<?php if(isset($debug)){ ?>
@@ -81,6 +91,7 @@
<div class="input-group-addon"><i class="fa fa-plug"></i></div>
<input type="text" class="form-control" disabled value="<?php echo $piHoleIPv6; ?>">
</div>
<?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>
@@ -93,6 +104,17 @@
</div>
<?php
// Pi-Hole DHCP server
// Detect IPv6
$usingipv6 = false;
if(strlen($piHoleIPv6) > 0 && $piHoleIPv6 != "unknown")
{
if(substr($piHoleIPv6, 0, 4) != "fe80")
{
$usingipv6 = true;
}
}
if(isset($setupVars["DHCP_ACTIVE"]))
{
if($setupVars["DHCP_ACTIVE"] == 1)
@@ -107,12 +129,29 @@
$DHCPstart = $setupVars["DHCP_START"];
$DHCPend = $setupVars["DHCP_END"];
$DHCProuter = $setupVars["DHCP_ROUTER"];
$DHCPleasetime = $setupVars["DHCP_LEASETIME"];
if(strlen($DHCPleasetime) < 1)
// This setting has been added later, we have to check if it exists
if(isset($setupVars["DHCP_LEASETIME"]))
{
$DHCPleasetime = $setupVars["DHCP_LEASETIME"];
if(strlen($DHCPleasetime) < 1)
{
// Fallback if empty string
$DHCPleasetime = 24;
}
}
else
{
// Fallback if it was not set before
$DHCPleasetime = 24;
}
if(isset($setupVars["DHCP_IPv6"]))
{
$DHCPIPv6 = $setupVars["DHCP_IPv6"];
}
else
{
$DHCPIPv6 = $usingipv6;
}
}
else
{
@@ -130,6 +169,7 @@
$DHCProuter = "";
}
$DHCPleasetime = 24;
$DHCPIPv6 = $usingipv6;
}
if(isset($setupVars["PIHOLE_DOMAIN"])){
$piHoleDomain = $setupVars["PIHOLE_DOMAIN"];
@@ -143,8 +183,13 @@
</div>
<div class="box-body">
<form role="form" method="post">
<div class="form-group">
<div class="checkbox"><label><input type="checkbox" name="active" <?php if($DHCP){ ?>checked<?php } ?> id="DHCPchk"> DHCP server enabled</label></div>
<div class="col-md-6">
<div class="form-group">
<div class="checkbox"><label><input type="checkbox" name="active" <?php if($DHCP){ ?>checked<?php } ?> id="DHCPchk"> DHCP server enabled</label></div>
</div>
</div>
<div class="col-md-6">
<p id="dhcpnotice" <?php if(!$DHCP){ ?>hidden<?php } ?>>Make sure your router's DHCP server is disabled when using the Pi-hole DHCP server!</p>
</div>
<div class="col-md-12">
<label>Range of IP addresses to hand out</label>
@@ -181,6 +226,11 @@
<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">
<div class="col-md-12">
<div class="form-group">
<div class="checkbox"><label><input type="checkbox" name="useIPv6" <?php if($DHCPIPv6){ ?>checked<?php } ?> class="DHCPgroup" <?php if(!$DHCP){ ?>disabled<?php } ?>> Enable IPv6 support (SLAAC + RA)</label></div>
</div>
</div>
<div class="col-md-12">
<label>Pi-Hole domain name</label>
<div class="form-group">
@@ -403,10 +453,10 @@
<div class="box-body">
<div class="col-lg-12">
<div class="form-group">
<div class="checkbox"><label><input type="checkbox" name="DNSrequiresFQDN" <?php if($DNSrequiresFQDN){ ?>checked<?php } ?>> never forward non-FQDNs</label></div>
<div class="checkbox"><label><input type="checkbox" name="DNSrequiresFQDN" <?php if($DNSrequiresFQDN){ ?>checked<?php } ?> title="domain-needed"> never forward non-FQDNs</label></div>
</div>
<div class="form-group">
<div class="checkbox"><label><input type="checkbox" name="DNSbogusPriv" <?php if($DNSbogusPriv){ ?>checked<?php } ?>> never forward reverse lookups for private IP ranges</label></div>
<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>
@@ -455,6 +505,7 @@
</div>
<div class="box-footer">
<form role="form" method="post">
<button type="button" class="btn btn-default confirm-flushlogs">Flush logs</button>
<input type="hidden" name="field" value="Logging">
<?php if($piHoleLogging) { ?>
<input type="hidden" name="action" value="Disable">
@@ -562,8 +613,10 @@
</div>
</div>
<h4>Privacy mode</h4>
<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="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>
</div>
</div>
<div class="box-footer">