mirror of
https://github.com/pi-hole/web.git
synced 2024-12-06 19:36:21 +01:00
@@ -1,2 +0,0 @@
|
||||
memory_limit = 256M
|
||||
max_execution_time = 300
|
||||
@@ -18,28 +18,9 @@ $FTL_IP = "127.0.0.1";
|
||||
$data = array();
|
||||
|
||||
// Common API functions
|
||||
if (isset($_GET['status']))
|
||||
{
|
||||
$pistatus = pihole_execute('status web');
|
||||
if(isset($pistatus[0]))
|
||||
{
|
||||
$pistatus = $pistatus[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
$pistatus = null;
|
||||
}
|
||||
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['status'])) {
|
||||
$data = array_merge($data, array("status" => piholeStatusAPI()));
|
||||
} elseif (isset($_GET['enable']) && $auth) {
|
||||
if(isset($_GET["auth"]))
|
||||
{
|
||||
if($_GET["auth"] !== $pwhash)
|
||||
@@ -160,17 +141,64 @@ elseif (isset($_GET['list']))
|
||||
|
||||
return;
|
||||
}
|
||||
elseif(isset($_GET['customdns']) && $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']);
|
||||
}
|
||||
|
||||
switch ($_GET["action"]) {
|
||||
case 'get':
|
||||
$_POST['action'] = 'get';
|
||||
break;
|
||||
case 'add':
|
||||
$_POST['action'] = 'add';
|
||||
break;
|
||||
case 'delete':
|
||||
$_POST['action'] = 'delete';
|
||||
break;
|
||||
}
|
||||
|
||||
require("scripts/pi-hole/php/customdns.php");
|
||||
}
|
||||
elseif(isset($_GET['customcname']) && $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']);
|
||||
}
|
||||
|
||||
switch ($_GET["action"]) {
|
||||
case 'get':
|
||||
$_POST['action'] = 'get';
|
||||
break;
|
||||
case 'add':
|
||||
$_POST['action'] = 'add';
|
||||
break;
|
||||
case 'delete':
|
||||
$_POST['action'] = 'delete';
|
||||
break;
|
||||
}
|
||||
|
||||
require("scripts/pi-hole/php/customcname.php");
|
||||
}
|
||||
|
||||
// Other API functions
|
||||
require("api_FTL.php");
|
||||
|
||||
header('Content-type: application/json');
|
||||
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);
|
||||
}
|
||||
?>
|
||||
|
||||
+30
-8
@@ -29,26 +29,48 @@ else
|
||||
$data["version"] = 3;
|
||||
}
|
||||
|
||||
if (isset($_GET['summary']) || isset($_GET['summaryRaw']) || !count($_GET))
|
||||
{
|
||||
if (isset($_GET['summary']) || isset($_GET['summaryRaw']) || !count($_GET)) {
|
||||
require_once("scripts/pi-hole/php/gravity.php");
|
||||
sendRequestFTL("stats");
|
||||
$return = getResponseFTL();
|
||||
|
||||
$stats = [];
|
||||
foreach($return as $line)
|
||||
{
|
||||
foreach($return as $line) {
|
||||
$tmp = explode(" ",$line);
|
||||
|
||||
if(($tmp[0] === "domains_being_blocked" && !is_numeric($tmp[1])) || $tmp[0] === "status")
|
||||
$stats[$tmp[0]] = $tmp[1]; // Expect string response
|
||||
else
|
||||
$stats[$tmp[0]] = floatval($tmp[1]); // Expect float response
|
||||
if($tmp[0] === "domains_being_blocked" && !is_numeric($tmp[1])) {
|
||||
// Expect string response
|
||||
$stats[$tmp[0]] = $tmp[1];
|
||||
} elseif ($tmp[0] === "status") {
|
||||
// Expect string response
|
||||
$stats[$tmp[0]] = piholeStatusAPI();
|
||||
} elseif (isset($_GET['summary'])) {
|
||||
// "summary" expects a formmated string response
|
||||
if($tmp[0] !== "ads_percentage_today") {
|
||||
$stats[$tmp[0]] = number_format($tmp[1]);
|
||||
} else {
|
||||
$stats[$tmp[0]] = number_format($tmp[1], 1, '.', '');
|
||||
}
|
||||
} else {
|
||||
// Expect float response
|
||||
$stats[$tmp[0]] = floatval($tmp[1]);
|
||||
}
|
||||
|
||||
}
|
||||
$stats['gravity_last_updated'] = gravity_last_update(true);
|
||||
$data = array_merge($data,$stats);
|
||||
}
|
||||
|
||||
if (isset($_GET["getMaxlogage"]) && $auth) {
|
||||
sendRequestFTL("maxlogage");
|
||||
// Convert seconds to hours and rounds to one decimal place.
|
||||
$ret = round(intval(getResponseFTL()[0]) / 3600, 1);
|
||||
// Return 24h if value is 0, empty, null or non numeric.
|
||||
$ret = $ret ?: 24;
|
||||
|
||||
$data = array_merge($data, array("maxlogage" => $ret));
|
||||
}
|
||||
|
||||
if (isset($_GET['overTimeData10mins']))
|
||||
{
|
||||
sendRequestFTL("overTime");
|
||||
|
||||
+27
-8
@@ -87,17 +87,36 @@ if (isset($_GET['getAllQueries']) && $auth)
|
||||
$stmt->bindValue(":from", intval($from), SQLITE3_INTEGER);
|
||||
$stmt->bindValue(":until", intval($until), SQLITE3_INTEGER);
|
||||
$results = $stmt->execute();
|
||||
if(!is_bool($results))
|
||||
while ($row = $results->fetchArray())
|
||||
{
|
||||
// Convert query type ID to name
|
||||
$query_type = getQueryTypeStr($row[1]);
|
||||
if (!is_bool($results)) {
|
||||
// Start the JSON string
|
||||
echo '{"data":[';
|
||||
|
||||
// Insert into array
|
||||
// array: time type domain client status upstream destination
|
||||
$allQueries[] = [$row[0], $query_type, utf8_encode(str_replace("~"," ",$row[2])), $row[3], $row[4], utf8_encode($row[5])];
|
||||
$first = true;
|
||||
while ($row = $results->fetchArray()) {
|
||||
// Insert a comma before the next record (except on the first one)
|
||||
if (!$first) {
|
||||
echo ",";
|
||||
} else {
|
||||
$first = false;
|
||||
}
|
||||
|
||||
// Convert query type ID to name, encode domain, encode destination
|
||||
$query_type = getQueryTypeStr($row[1]);
|
||||
$domain = utf8_encode(str_replace("~"," ",$row[2]));
|
||||
$destination = utf8_encode($row[5]);
|
||||
|
||||
// Insert into array and output it in JSON format
|
||||
// array: time type domain client status upstream destination
|
||||
echo json_encode([$row[0], $query_type, $domain, $row[3], $row[4], $destination]);
|
||||
}
|
||||
|
||||
// Finish the JSON string
|
||||
echo ']}';
|
||||
}
|
||||
// exit at the end
|
||||
exit();
|
||||
}
|
||||
// only used if getAllQueries==empty
|
||||
$result = array('data' => $allQueries);
|
||||
$data = array_merge($data, $result);
|
||||
}
|
||||
|
||||
+1
-1
@@ -67,7 +67,7 @@
|
||||
<th>Status</th>
|
||||
<th>Comment</th>
|
||||
<th>Group assignment</th>
|
||||
<th>Action</th>
|
||||
<th> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
|
||||
+1
-1
@@ -73,7 +73,7 @@
|
||||
<th title="Acceptable values are: IP address, subnet (CIDR notation), MAC address (AA:BB:CC:DD:EE:FF format) or host names.">Client</th>
|
||||
<th>Comment</th>
|
||||
<th>Group assignment</th>
|
||||
<th>Action</th>
|
||||
<th> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
|
||||
+1
-1
@@ -126,7 +126,7 @@
|
||||
<th>Status</th>
|
||||
<th>Comment</th>
|
||||
<th>Group assignment</th>
|
||||
<th>Action</th>
|
||||
<th> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@
|
||||
<th>Name</th>
|
||||
<th>Status</th>
|
||||
<th>Description</th>
|
||||
<th>Action</th>
|
||||
<th> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
|
||||
@@ -1,26 +1,14 @@
|
||||
<?php /*
|
||||
* 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. */
|
||||
$indexpage = true;
|
||||
require "scripts/pi-hole/php/header.php";
|
||||
require_once "scripts/pi-hole/php/gravity.php";
|
||||
|
||||
function getinterval()
|
||||
{
|
||||
global $piholeFTLConf;
|
||||
if(isset($piholeFTLConf["MAXLOGAGE"]))
|
||||
{
|
||||
return round(floatval($piholeFTLConf["MAXLOGAGE"]), 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return "24";
|
||||
}
|
||||
}
|
||||
$indexpage = true;
|
||||
require "scripts/pi-hole/php/header.php";
|
||||
require_once "scripts/pi-hole/php/gravity.php";
|
||||
?>
|
||||
<!-- Sourceing CSS colors from stylesheet to be used in JS code -->
|
||||
<span class="queries-permitted"></span>
|
||||
@@ -72,7 +60,7 @@
|
||||
<!-- small box -->
|
||||
<div class="small-box bg-red no-user-select" title="<?php echo gravity_last_update(); ?>">
|
||||
<div class="inner">
|
||||
<p>Domains on Blocklist</p>
|
||||
<p>Domains on Adlists</p>
|
||||
<h3 class="statistic"><span id="domains_being_blocked">---</span></h3>
|
||||
</div>
|
||||
<div class="icon">
|
||||
@@ -87,7 +75,7 @@
|
||||
<div class="col-md-12">
|
||||
<div class="box" id="queries-over-time">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">Total queries over last <?php echo getinterval(); ?> hours</h3>
|
||||
<h3 class="box-title">Total queries over last <span class="maxlogage-interval">24</span> hours</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="chart">
|
||||
@@ -112,7 +100,7 @@
|
||||
<div class="col-md-12">
|
||||
<div class="box" id="clients">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">Client activity over last <?php echo getinterval(); ?> hours</h3>
|
||||
<h3 class="box-title">Client activity over last <span class="maxlogage-interval">24</span> hours</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="chart">
|
||||
|
||||
Generated
+271
-632
File diff suppressed because it is too large
Load Diff
+4
-4
@@ -24,12 +24,12 @@
|
||||
"testpr": "npm run prettier:fix && git diff --ws-error-highlight=all --color=always --exit-code && npm run xo"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^10.4.1",
|
||||
"eslint-plugin-compat": "^4.0.0",
|
||||
"postcss": "^8.4.5",
|
||||
"autoprefixer": "^10.4.2",
|
||||
"eslint-plugin-compat": "^4.0.2",
|
||||
"postcss": "^8.4.6",
|
||||
"postcss-cli": "^9.1.0",
|
||||
"prettier": "2.5.1",
|
||||
"xo": "^0.47.0"
|
||||
"xo": "^0.48.0"
|
||||
},
|
||||
"browserslist": [
|
||||
"defaults",
|
||||
|
||||
+3
-3
@@ -50,9 +50,9 @@ else if(isset($_GET["client"]))
|
||||
}
|
||||
else if(isset($_GET["forwarddest"]))
|
||||
{
|
||||
if($_GET["forwarddest"] === "blocklist")
|
||||
$showing .= " queries answered from blocklists";
|
||||
elseif($_GET["forwarddest"] === "cache")
|
||||
if($_GET["forwarddest"] === "blocked")
|
||||
$showing .= " queries blocked by Pi-hole";
|
||||
elseif($_GET["forwarddest"] === "cached")
|
||||
$showing .= " queries answered from cache";
|
||||
else
|
||||
$showing .= " queries for upstream destination ".htmlentities($_GET["forwarddest"]);
|
||||
|
||||
@@ -84,7 +84,8 @@ function handleAjaxError(xhr, textStatus) {
|
||||
alert(
|
||||
"An unknown error occurred while loading the data.\n" +
|
||||
xhr.responseText +
|
||||
"\nCheck the server's log files (/var/log/lighttpd/error.log when you're using the default Pi-hole web server) for details. You may need to increase the memory available for Pi-hole in case you requested a lot of data."
|
||||
"\nCheck the server's log files (/var/log/lighttpd/error.log) for details.\n\nYou may need to increase PHP memory limit." +
|
||||
"\n\nYou can find more info in pi-hole's FAQ:\nhttps://docs.pi-hole.net/main/faq/#error-while-loading-data-from-the-long-term-database"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -296,7 +297,7 @@ $(function () {
|
||||
}
|
||||
|
||||
$(row).addClass(blocked === true ? "blocked-row" : "allowed-row");
|
||||
if (localStorage.getItem("colorfulQueryLog_chkbox") === "true") {
|
||||
if (localStorage && localStorage.getItem("colorfulQueryLog_chkbox") === "true") {
|
||||
$(row).addClass(blocked === true ? "text-red" : "text-green");
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,9 @@ function countDown() {
|
||||
} else {
|
||||
ena.text("Enable");
|
||||
piholeChanged("enabled");
|
||||
localStorage.removeItem("countDownTarget");
|
||||
if (localStorage) {
|
||||
localStorage.removeItem("countDownTarget");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,7 +150,7 @@ function initCheckboxRadioStyle() {
|
||||
}
|
||||
|
||||
// Read from local storage, initialize if needed
|
||||
var chkboxStyle = localStorage.getItem("theme_icheck");
|
||||
var chkboxStyle = localStorage ? localStorage.getItem("theme_icheck") : null;
|
||||
if (chkboxStyle === null) {
|
||||
chkboxStyle = "primary";
|
||||
}
|
||||
@@ -172,7 +174,10 @@ function initCheckboxRadioStyle() {
|
||||
|
||||
function initCPUtemp() {
|
||||
function setCPUtemp(unit) {
|
||||
localStorage.setItem("tempunit", tempunit);
|
||||
if (localStorage) {
|
||||
localStorage.setItem("tempunit", tempunit);
|
||||
}
|
||||
|
||||
var temperature = parseFloat($("#rawtemp").text());
|
||||
var displaytemp = $("#tempdisplay");
|
||||
if (!isNaN(temperature)) {
|
||||
@@ -195,7 +200,7 @@ function initCPUtemp() {
|
||||
}
|
||||
|
||||
// Read from local storage, initialize if needed
|
||||
var tempunit = localStorage.getItem("tempunit");
|
||||
var tempunit = localStorage ? localStorage.getItem("tempunit") : null;
|
||||
if (tempunit === null) {
|
||||
tempunit = "C";
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ function initTable() {
|
||||
{ data: "enabled", searchable: false },
|
||||
{ data: "comment" },
|
||||
{ data: "groups", searchable: false },
|
||||
{ data: null, width: "80px", orderable: false },
|
||||
{ data: null, width: "22px", orderable: false },
|
||||
],
|
||||
columnDefs: [
|
||||
{
|
||||
@@ -291,7 +291,8 @@ function initTable() {
|
||||
$("td:eq(5)", row).html(button);
|
||||
},
|
||||
dom:
|
||||
"<'row'<'col-sm-4'l><'col-sm-8'f>>" +
|
||||
"<'row'<'col-sm-12'f>>" +
|
||||
"<'row'<'col-sm-4'l><'col-sm-8'p>>" +
|
||||
"<'row'<'col-sm-12'<'table-responsive'tr>>>" +
|
||||
"<'row'<'col-sm-5'i><'col-sm-7'p>>",
|
||||
lengthMenu: [
|
||||
|
||||
@@ -95,7 +95,7 @@ function initTable() {
|
||||
{ data: "ip", type: "ip-address" },
|
||||
{ data: "comment" },
|
||||
{ data: "groups", searchable: false },
|
||||
{ data: "name", width: "80px", orderable: false },
|
||||
{ data: "name", width: "22px", orderable: false },
|
||||
],
|
||||
columnDefs: [
|
||||
{
|
||||
@@ -215,7 +215,8 @@ function initTable() {
|
||||
$("td:eq(3)", row).html(button);
|
||||
},
|
||||
dom:
|
||||
"<'row'<'col-sm-4'l><'col-sm-8'f>>" +
|
||||
"<'row'<'col-sm-12'f>>" +
|
||||
"<'row'<'col-sm-4'l><'col-sm-8'p>>" +
|
||||
"<'row'<'col-sm-12'<'table-responsive'tr>>>" +
|
||||
"<'row'<'col-sm-5'i><'col-sm-7'p>>",
|
||||
lengthMenu: [
|
||||
|
||||
@@ -74,7 +74,7 @@ function initTable() {
|
||||
{ data: "enabled", searchable: false },
|
||||
{ data: "comment" },
|
||||
{ data: "groups", searchable: false, visible: showtype === "all" },
|
||||
{ data: null, width: "80px", orderable: false },
|
||||
{ data: null, width: "22px", orderable: false },
|
||||
],
|
||||
columnDefs: [
|
||||
{
|
||||
@@ -244,7 +244,8 @@ function initTable() {
|
||||
}
|
||||
},
|
||||
dom:
|
||||
"<'row'<'col-sm-4'l><'col-sm-8'f>>" +
|
||||
"<'row'<'col-sm-12'f>>" +
|
||||
"<'row'<'col-sm-4'l><'col-sm-8'p>>" +
|
||||
"<'row'<'col-sm-12'<'table-responsive'tr>>>" +
|
||||
"<'row'<'col-sm-5'i><'col-sm-7'p>>",
|
||||
lengthMenu: [
|
||||
|
||||
@@ -25,7 +25,7 @@ $(function () {
|
||||
{ data: "name" },
|
||||
{ data: "enabled", searchable: false },
|
||||
{ data: "description" },
|
||||
{ data: null, width: "60px", orderable: false },
|
||||
{ data: null, width: "22px", orderable: false },
|
||||
],
|
||||
columnDefs: [
|
||||
{
|
||||
@@ -84,7 +84,8 @@ $(function () {
|
||||
}
|
||||
},
|
||||
dom:
|
||||
"<'row'<'col-sm-4'l><'col-sm-8'f>>" +
|
||||
"<'row'<'col-sm-12'f>>" +
|
||||
"<'row'<'col-sm-4'l><'col-sm-8'p>>" +
|
||||
"<'row'<'col-sm-12'<'table-responsive'tr>>>" +
|
||||
"<'row'<'col-sm-5'i><'col-sm-7'p>>",
|
||||
lengthMenu: [
|
||||
|
||||
+80
-27
@@ -319,24 +319,71 @@ function updateQueryTypesPie() {
|
||||
queryTypePieChart.update();
|
||||
// Don't use rotation animation for further updates
|
||||
queryTypePieChart.options.animation.duration = 0;
|
||||
queryTypePieChart.options.legendCallback = customLegend;
|
||||
|
||||
// Generate legend in separate div
|
||||
$("#query-types-legend").html(queryTypePieChart.generateLegend());
|
||||
$("#query-types-legend > ul > li").prepend(createEyeConElement());
|
||||
$("#query-types-legend > ul > li").click(function (e) {
|
||||
if (isEyeCon(e.target)) {
|
||||
if (iscolorBox(e.target)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
window.location.href = "queries.php?querytype=" + querytypeids[$(this).index()];
|
||||
});
|
||||
$("#query-types-legend .colorBoxWrapper").click(function (e) {
|
||||
hidePieSlice(e);
|
||||
});
|
||||
}).done(function () {
|
||||
// Reload graph after minute
|
||||
setTimeout(updateQueryTypesPie, 60000);
|
||||
});
|
||||
}
|
||||
|
||||
function customLegend(chart) {
|
||||
var text = [];
|
||||
var data = chart.data;
|
||||
var datasets = data.datasets;
|
||||
var labels = data.labels;
|
||||
|
||||
text.push('<ul class="' + chart.id + '-legend">');
|
||||
|
||||
if (datasets.length > 0) {
|
||||
for (var i = 0; i < datasets[0].data.length; ++i) {
|
||||
var color = datasets[0].backgroundColor[i];
|
||||
|
||||
var txt = "";
|
||||
|
||||
// legend box icon
|
||||
txt =
|
||||
'<span class="colorBoxWrapper" style="color: ' +
|
||||
color +
|
||||
'" title="Toggle visibility">' +
|
||||
'<i class="fa fa-check-square"></i>' +
|
||||
"</span>";
|
||||
|
||||
// color block
|
||||
txt += '<span class="legend-color-box" style="background-color:' + color + '"></span>';
|
||||
|
||||
// label
|
||||
if (labels[i]) {
|
||||
txt +=
|
||||
'<span class="legend-label-text" title="List ' +
|
||||
labels[i] +
|
||||
' queries">' +
|
||||
labels[i] +
|
||||
"</span>";
|
||||
}
|
||||
|
||||
text.push("<li>" + txt + "</li>");
|
||||
}
|
||||
}
|
||||
|
||||
text.push("</ul>");
|
||||
return text.join("");
|
||||
}
|
||||
|
||||
function hidePieSlice(event) {
|
||||
toggleEyeCon(event.target);
|
||||
togglecolorBox(event.target);
|
||||
|
||||
var legendID = $(event.target).closest(".chart-legend").attr("id");
|
||||
var ci =
|
||||
@@ -360,19 +407,19 @@ function hidePieSlice(event) {
|
||||
ci.update();
|
||||
}
|
||||
|
||||
function toggleEyeCon(target) {
|
||||
function togglecolorBox(target) {
|
||||
var parentListItem = $(target).closest("li");
|
||||
var eyeCon = $(parentListItem).find(".fa-eye, .fa-eye-slash");
|
||||
var colorBox = $(parentListItem).find(".fa-check-square, .fa-square");
|
||||
|
||||
if (eyeCon) {
|
||||
$(eyeCon).toggleClass("fa-eye");
|
||||
$(eyeCon).toggleClass("fa-eye-slash");
|
||||
if (colorBox) {
|
||||
$(colorBox).toggleClass("fa-check-square");
|
||||
$(colorBox).toggleClass("fa-square");
|
||||
}
|
||||
}
|
||||
|
||||
function isEyeCon(target) {
|
||||
// See if click happened on eyeConWrapper or child SVG
|
||||
if ($(target).closest(".eyeConWrapper")[0]) {
|
||||
function iscolorBox(target) {
|
||||
// See if click happened on colorBoxWrapper or child SVG
|
||||
if ($(target).closest(".colorBoxWrapper")[0]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -468,16 +515,6 @@ function updateClientsOverTime() {
|
||||
});
|
||||
}
|
||||
|
||||
function createEyeConElement() {
|
||||
var eyeConWrapper = $("<span></span>")
|
||||
.addClass("eyeConWrapper")
|
||||
.click(function (e) {
|
||||
hidePieSlice(e);
|
||||
});
|
||||
eyeConWrapper.append($("<i class='fa fa-eye'></i>"));
|
||||
return eyeConWrapper;
|
||||
}
|
||||
|
||||
function updateForwardDestinationsPie() {
|
||||
$.getJSON("api.php?getForwardDestinations", function (data) {
|
||||
if ("FTLnotrunning" in data) {
|
||||
@@ -519,11 +556,12 @@ function updateForwardDestinationsPie() {
|
||||
forwardDestinationPieChart.update();
|
||||
// Don't use rotation animation for further updates
|
||||
forwardDestinationPieChart.options.animation.duration = 0;
|
||||
forwardDestinationPieChart.options.legendCallback = customLegend;
|
||||
|
||||
// Generate legend in separate div
|
||||
$("#forward-destinations-legend").html(forwardDestinationPieChart.generateLegend());
|
||||
$("#forward-destinations-legend > ul > li").prepend(createEyeConElement());
|
||||
$("#forward-destinations-legend > ul > li").click(function (e) {
|
||||
if (isEyeCon(e.target)) {
|
||||
if (iscolorBox(e.target)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -532,6 +570,9 @@ function updateForwardDestinationsPie() {
|
||||
window.location.href = "queries.php?forwarddest=" + obj;
|
||||
}
|
||||
});
|
||||
$("#forward-destinations-legend .colorBoxWrapper").click(function (e) {
|
||||
hidePieSlice(e);
|
||||
});
|
||||
}).done(function () {
|
||||
// Reload graph after one minute
|
||||
setTimeout(updateForwardDestinationsPie, 60000);
|
||||
@@ -723,7 +764,7 @@ function updateSummaryData(runOnce) {
|
||||
}
|
||||
};
|
||||
|
||||
$.getJSON("api.php?summary", function (data) {
|
||||
$.getJSON("api.php?summaryRaw", function (data) {
|
||||
updateSessionTimer();
|
||||
|
||||
if ("FTLnotrunning" in data) {
|
||||
@@ -795,7 +836,7 @@ function updateSummaryData(runOnce) {
|
||||
|
||||
function doughnutTooltip(tooltipItems, data) {
|
||||
var dataset = data.datasets[tooltipItems.datasetIndex];
|
||||
var label = data.labels[tooltipItems.index];
|
||||
var label = " " + data.labels[tooltipItems.index];
|
||||
// Compute share of total and of displayed
|
||||
var scale = 0,
|
||||
total = 0;
|
||||
@@ -813,16 +854,28 @@ function doughnutTooltip(tooltipItems, data) {
|
||||
return label + ": " + dataset.data[tooltipItems.index].toFixed(1) + "%";
|
||||
return (
|
||||
label +
|
||||
":<br>- " +
|
||||
":<br>• " +
|
||||
dataset.data[tooltipItems.index].toFixed(1) +
|
||||
"% of all queries<br>- " +
|
||||
"% of all queries<br>• " +
|
||||
((dataset.data[tooltipItems.index] * 100) / (total - scale)).toFixed(1) +
|
||||
"% of shown items"
|
||||
);
|
||||
}
|
||||
|
||||
var maxlogage = "24";
|
||||
function getMaxlogage() {
|
||||
$.getJSON("api.php?getMaxlogage", function (data) {
|
||||
if (!("FTLnotrunning" in data)) {
|
||||
maxlogage = data.maxlogage;
|
||||
}
|
||||
}).done(function () {
|
||||
$(".maxlogage-interval").html(maxlogage);
|
||||
});
|
||||
}
|
||||
|
||||
$(function () {
|
||||
// Pull in data via AJAX
|
||||
getMaxlogage();
|
||||
updateSummaryData();
|
||||
|
||||
var gridColor = $(".graphs-grid").css("background-color");
|
||||
|
||||
@@ -174,7 +174,8 @@ $(function () {
|
||||
$("td:eq(3)", row).html(button);
|
||||
},
|
||||
dom:
|
||||
"<'row'<'col-sm-4'l><'col-sm-8'f>>" +
|
||||
"<'row'<'col-sm-12'f>>" +
|
||||
"<'row'<'col-sm-4'l><'col-sm-8'p>>" +
|
||||
"<'row'<'col-sm-12'<'table-responsive'tr>>>" +
|
||||
"<'row'<'col-sm-5'i><'col-sm-7'p>>",
|
||||
lengthMenu: [
|
||||
|
||||
@@ -231,7 +231,7 @@ $(function () {
|
||||
fieldtext += '<input type="hidden" name="id" value="' + parseInt(data[4], 10) + '">';
|
||||
|
||||
$(row).addClass(blocked === true ? "blocked-row" : "allowed-row");
|
||||
if (localStorage.getItem("colorfulQueryLog_chkbox") === "true") {
|
||||
if (localStorage && localStorage.getItem("colorfulQueryLog_chkbox") === "true") {
|
||||
$(row).addClass(blocked === true ? "text-red" : "text-green");
|
||||
}
|
||||
|
||||
|
||||
@@ -213,9 +213,15 @@ function loadCacheInfo() {
|
||||
var cachelivefreed = parseInt(data.cacheinfo["cache-live-freed"], 10);
|
||||
$("#cache-live-freed").text(cachelivefreed);
|
||||
if (cachelivefreed > 0) {
|
||||
$("#cache-live-freed").parent("tr").addClass("lookatme");
|
||||
$("#cache-live-freed").parent("tr").children("th").children("span").addClass("lookatme");
|
||||
$("#cache-live-freed").parent("tr").children("td").addClass("lookatme");
|
||||
$("#cache-live-freed")
|
||||
.parent("tr")
|
||||
.children("td")
|
||||
.attr("lookatme-text", cachelivefreed.toString());
|
||||
} else {
|
||||
$("#cache-live-freed").parent("tr").removeClass("lookatme");
|
||||
$("#cache-live-freed").parent("tr").children("th").children("span").removeClass("lookatme");
|
||||
$("#cache-live-freed").parent("tr").children("td").removeClass("lookatme");
|
||||
}
|
||||
|
||||
// Update cache info every 10 seconds
|
||||
@@ -228,7 +234,8 @@ $(function () {
|
||||
if (document.getElementById("DHCPLeasesTable")) {
|
||||
leasetable = $("#DHCPLeasesTable").DataTable({
|
||||
dom:
|
||||
"<'row'<'col-sm-4'l><'col-sm-8'f>>" +
|
||||
"<'row'<'col-sm-12'f>>" +
|
||||
"<'row'<'col-sm-4'l><'col-sm-8'p>>" +
|
||||
"<'row'<'col-sm-12'<'table-responsive'tr>>>" +
|
||||
"<'row'<'col-sm-5'i><'col-sm-7'p>>",
|
||||
lengthMenu: [
|
||||
@@ -238,9 +245,23 @@ $(function () {
|
||||
columnDefs: [
|
||||
{ bSortable: false, orderable: false, targets: -1 },
|
||||
{
|
||||
targets: [0, 1, 2],
|
||||
targets: [0, 1],
|
||||
render: $.fn.dataTable.render.text(),
|
||||
},
|
||||
{
|
||||
targets: 2,
|
||||
render: function (data) {
|
||||
// Show "unknown", when host is "*"
|
||||
var str;
|
||||
if (data === "*") {
|
||||
str = "<i>unknown</i>";
|
||||
} else {
|
||||
str = typeof data === "string" ? utils.escapeHtml(data) : data;
|
||||
}
|
||||
|
||||
return str;
|
||||
},
|
||||
},
|
||||
],
|
||||
paging: true,
|
||||
order: [[2, "asc"]],
|
||||
@@ -258,7 +279,8 @@ $(function () {
|
||||
if (document.getElementById("DHCPStaticLeasesTable")) {
|
||||
staticleasetable = $("#DHCPStaticLeasesTable").DataTable({
|
||||
dom:
|
||||
"<'row'<'col-sm-4'l><'col-sm-8'f>>" +
|
||||
"<'row'<'col-sm-12'f>>" +
|
||||
"<'row'<'col-sm-4'l><'col-sm-8'p>>" +
|
||||
"<'row'<'col-sm-12'<'table-responsive'tr>>>" +
|
||||
"<'row'<'col-sm-5'i><'col-sm-7'p>>",
|
||||
lengthMenu: [
|
||||
@@ -342,7 +364,7 @@ $(".nav-tabs a").on("shown.bs.tab", function (e) {
|
||||
// Bar/Smooth chart toggle
|
||||
$(function () {
|
||||
var bargraphs = $("#bargraphs");
|
||||
var chkboxData = localStorage.getItem("barchart_chkbox");
|
||||
var chkboxData = localStorage ? localStorage.getItem("barchart_chkbox") : null;
|
||||
|
||||
if (chkboxData !== null) {
|
||||
// Restore checkbox state
|
||||
@@ -350,7 +372,9 @@ $(function () {
|
||||
} else {
|
||||
// Initialize checkbox
|
||||
bargraphs.prop("checked", true);
|
||||
localStorage.setItem("barchart_chkbox", true);
|
||||
if (localStorage) {
|
||||
localStorage.setItem("barchart_chkbox", true);
|
||||
}
|
||||
}
|
||||
|
||||
bargraphs.click(function () {
|
||||
@@ -360,7 +384,7 @@ $(function () {
|
||||
|
||||
$(function () {
|
||||
var colorfulQueryLog = $("#colorfulQueryLog");
|
||||
var chkboxData = localStorage.getItem("colorfulQueryLog_chkbox");
|
||||
var chkboxData = localStorage ? localStorage.getItem("colorfulQueryLog_chkbox") : null;
|
||||
|
||||
if (chkboxData !== null) {
|
||||
// Restore checkbox state
|
||||
@@ -368,7 +392,9 @@ $(function () {
|
||||
} else {
|
||||
// Initialize checkbox
|
||||
colorfulQueryLog.prop("checked", false);
|
||||
localStorage.setItem("colorfulQueryLog_chkbox", false);
|
||||
if (localStorage) {
|
||||
localStorage.setItem("colorfulQueryLog_chkbox", false);
|
||||
}
|
||||
}
|
||||
|
||||
colorfulQueryLog.click(function () {
|
||||
|
||||
@@ -229,13 +229,25 @@ function setBsSelectDefaults() {
|
||||
};
|
||||
}
|
||||
|
||||
var backupStorage = {};
|
||||
function stateSaveCallback(itemName, data) {
|
||||
localStorage.setItem(itemName, JSON.stringify(data));
|
||||
if (localStorage === null) {
|
||||
backupStorage[itemName] = JSON.stringify(data);
|
||||
} else {
|
||||
localStorage.setItem(itemName, JSON.stringify(data));
|
||||
}
|
||||
}
|
||||
|
||||
function stateLoadCallback(itemName) {
|
||||
var data;
|
||||
// Receive previous state from client's local storage area
|
||||
var data = localStorage.getItem(itemName);
|
||||
if (localStorage === null) {
|
||||
var item = backupStorage[itemName];
|
||||
data = typeof item === "undefined" ? null : item;
|
||||
} else {
|
||||
data = localStorage.getItem(itemName);
|
||||
}
|
||||
|
||||
// Return if not available
|
||||
if (data === null) {
|
||||
return null;
|
||||
@@ -259,7 +271,7 @@ function stateLoadCallback(itemName) {
|
||||
|
||||
function getGraphType() {
|
||||
// Only return line if `barchart_chkbox` is explicitly set to false. Else return bar
|
||||
return localStorage.getItem("barchart_chkbox") === "false" ? "line" : "bar";
|
||||
return localStorage && localStorage.getItem("barchart_chkbox") === "false" ? "line" : "bar";
|
||||
}
|
||||
|
||||
function addFromQueryLog(domain, list) {
|
||||
|
||||
@@ -73,7 +73,7 @@ function check_cors() {
|
||||
$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));
|
||||
log_and_die("Failed Host Check: " . $server_host .' vs '. htmlspecialchars(join(', ', $AUTHORIZED_HOSTNAMES)));
|
||||
}
|
||||
|
||||
if(isset($_SERVER['HTTP_ORIGIN'])) {
|
||||
@@ -88,7 +88,7 @@ function check_cors() {
|
||||
$server_origin = str_replace(array("[","]","http://","https://"), array("","","",""), $server_origin);
|
||||
|
||||
if(!in_array($server_origin, $AUTHORIZED_HOSTNAMES)) {
|
||||
log_and_die("Failed CORS: " . htmlspecialchars($server_origin) .' vs '. join(', ', $AUTHORIZED_HOSTNAMES));
|
||||
log_and_die("Failed CORS: " . htmlspecialchars($server_origin) .' vs '. htmlspecialchars(join(', ', $AUTHORIZED_HOSTNAMES)));
|
||||
}
|
||||
header("Access-Control-Allow-Origin: ${_SERVER['HTTP_ORIGIN']}");
|
||||
}
|
||||
|
||||
@@ -5,11 +5,13 @@
|
||||
require_once('auth.php');
|
||||
|
||||
// Authentication checks
|
||||
if (isset($_POST['token'])) {
|
||||
check_cors();
|
||||
check_csrf($_POST['token']);
|
||||
} else {
|
||||
log_and_die('Not allowed (login session invalid or expired, please relogin on the Pi-hole dashboard)!');
|
||||
if (!isset($api)) {
|
||||
if (isset($_POST['token'])) {
|
||||
check_cors();
|
||||
check_csrf($_POST['token']);
|
||||
} else {
|
||||
log_and_die('Not allowed (login session invalid or expired, please relogin on the Pi-hole dashboard)!');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -5,11 +5,13 @@
|
||||
require_once('auth.php');
|
||||
|
||||
// Authentication checks
|
||||
if (isset($_POST['token'])) {
|
||||
check_cors();
|
||||
check_csrf($_POST['token']);
|
||||
} else {
|
||||
log_and_die('Not allowed (login session invalid or expired, please relogin on the Pi-hole dashboard)!');
|
||||
if (!isset($api)) {
|
||||
if (isset($_POST['token'])) {
|
||||
check_cors();
|
||||
check_csrf($_POST['token']);
|
||||
} else {
|
||||
log_and_die('Not allowed (login session invalid or expired, please relogin on the Pi-hole dashboard)!');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -49,14 +49,16 @@
|
||||
$coreVersionStr = $core_current . (isset($core_commit) ? " (" . $core_branch . ", " . $core_commit . ")" : "");
|
||||
$ftlVersionStr = $FTL_current . (isset($FTL_commit) ? " (" . $FTL_branch . ", " . $FTL_commit . ")" : "");
|
||||
$webVersionStr = $web_current . (isset($web_commit) ? " (" . $web_branch . ", " . $web_commit . ")" : "");
|
||||
$dockerTag = getenv('PIHOLE_DOCKER_TAG');
|
||||
$dockerTag = htmlspecialchars(getenv('PIHOLE_DOCKER_TAG'));
|
||||
|
||||
$githubBaseUrl = "https://github.com/pi-hole";
|
||||
$coreUrl = $githubBaseUrl . "/pi-hole";
|
||||
$dockerUrl = $githubBaseUrl . "/docker-pi-hole";
|
||||
$ftlUrl = $githubBaseUrl . "/FTL";
|
||||
$webUrl = $githubBaseUrl . "/AdminLTE";
|
||||
|
||||
$coreReleasesUrl = $coreUrl . "/releases";
|
||||
$dockerReleasesUrl = $dockerUrl . "/releases";
|
||||
$ftlReleasesUrl = $ftlUrl . "/releases";
|
||||
$webReleasesUrl = $webUrl . "/releases";
|
||||
?>
|
||||
@@ -78,21 +80,26 @@
|
||||
</ul>
|
||||
<?php } else { ?>
|
||||
<ul class="list-inline">
|
||||
<?php if($dockerTag) { ?> <li><strong>Docker Tag</strong> <?php echo $dockerTag; ?></li> <?php } ?>
|
||||
<?php if($dockerTag) { ?>
|
||||
<li>
|
||||
<strong>Docker Tag</strong>
|
||||
<a href="<?php echo $dockerReleasesUrl . "/" . $dockerTag; ?>" rel="noopener" target="_blank"><?php echo $dockerTag; ?></a>
|
||||
</li>
|
||||
<?php } ?>
|
||||
<li>
|
||||
<strong>Pi-hole</strong>
|
||||
<a href="<?php echo $coreReleasesUrl . "/" . $core_current; ?>" rel="noopener" target="_blank"><?php echo $core_current; ?></a>
|
||||
<?php if ($core_update) { ?> · <a class="lookatme" href="<?php echo $coreReleasesUrl . "/latest"; ?>" rel="noopener" target="_blank">Update available!</a><?php } ?>
|
||||
<?php if ($core_update) { ?> · <a class="lookatme" lookatme-text="Update available!" href="<?php echo $coreReleasesUrl . "/latest"; ?>" rel="noopener" target="_blank">Update available!</a><?php } ?>
|
||||
</li>
|
||||
<li>
|
||||
<strong>FTL</strong>
|
||||
<a href="<?php echo $ftlReleasesUrl . "/" . $FTL_current; ?>" rel="noopener" target="_blank"><?php echo $FTL_current; ?></a>
|
||||
<?php if ($FTL_update) { ?> · <a class="lookatme" href="<?php echo $ftlReleasesUrl . "/latest"; ?>" rel="noopener" target="_blank">Update available!</a><?php } ?>
|
||||
<?php if ($FTL_update) { ?> · <a class="lookatme" lookatme-text="Update available!" href="<?php echo $ftlReleasesUrl . "/latest"; ?>" rel="noopener" target="_blank">Update available!</a><?php } ?>
|
||||
</li>
|
||||
<li>
|
||||
<strong>Web Interface</strong>
|
||||
<a href="<?php echo $webReleasesUrl . "/" . $web_current; ?>" rel="noopener" target="_blank"><?php echo $web_current; ?></a>
|
||||
<?php if ($web_update) { ?> · <a class="lookatme" href="<?php echo $webReleasesUrl . "/latest"; ?>" rel="noopener" target="_blank">Update available!</a><?php } ?>
|
||||
<?php if ($web_update) { ?> · <a class="lookatme" lookatme-text="Update available!" href="<?php echo $webReleasesUrl . "/latest"; ?>" rel="noopener" target="_blank">Update available!</a><?php } ?>
|
||||
</li>
|
||||
</ul>
|
||||
<?php if($core_update || $web_update || $FTL_update) { ?>
|
||||
|
||||
@@ -483,4 +483,31 @@ function getQueryTypeStr($querytype)
|
||||
return "TYPE".($qtype - 100);
|
||||
}
|
||||
|
||||
// Returns an integer representing pihole blocking status
|
||||
function piholeStatus()
|
||||
{
|
||||
// Receive the return of "pihole status web"
|
||||
$pistatus = pihole_execute('status web');
|
||||
return isset($pistatus[0]) ? intval($pistatus[0]) : -2;
|
||||
}
|
||||
|
||||
// Returns pihole status, using only valid API responses (enabled/disabled)
|
||||
function piholeStatusAPI()
|
||||
{
|
||||
// Receive the return of "pihole status web"
|
||||
$pistatus = piholeStatus();
|
||||
|
||||
switch ($pistatus) {
|
||||
case -2: // Unkown
|
||||
case -1: // DNS service not running"
|
||||
case 0: // Offline
|
||||
$response = "disabled";
|
||||
break;
|
||||
|
||||
default:
|
||||
// DNS service running on port $returncode
|
||||
$response = "enabled";
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -47,15 +47,15 @@ function gravity_last_update($raw = false)
|
||||
if($gravitydiff->d > 1)
|
||||
{
|
||||
// String output (more than one day ago)
|
||||
return $gravitydiff->format("Blocking list updated %a days, %H:%I (hh:mm) ago");
|
||||
return $gravitydiff->format("Adlists updated %a days, %H:%I (hh:mm) ago");
|
||||
}
|
||||
elseif($gravitydiff->d == 1)
|
||||
{
|
||||
// String output (one day ago)
|
||||
return $gravitydiff->format("Blocking list updated one day, %H:%I (hh:mm) ago");
|
||||
return $gravitydiff->format("Adlists updated one day, %H:%I (hh:mm) ago");
|
||||
}
|
||||
|
||||
// String output (less than one day ago)
|
||||
return $gravitydiff->format("Blocking list updated %H:%I (hh:mm) ago");
|
||||
return $gravitydiff->format("Adlists updated %H:%I (hh:mm) ago");
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
require "scripts/pi-hole/php/auth.php";
|
||||
require "scripts/pi-hole/php/password.php";
|
||||
require_once "scripts/pi-hole/php/FTL.php";
|
||||
require_once "scripts/pi-hole/php/func.php";
|
||||
require "scripts/pi-hole/php/theme.php";
|
||||
$scriptname = basename($_SERVER['SCRIPT_FILENAME']);
|
||||
$hostname = gethostname() ? gethostname() : "";
|
||||
@@ -66,6 +67,8 @@
|
||||
// Nothing can be colder than -273.15 degree Celsius (= 0 Kelvin)
|
||||
// This is the minimum temperature possible (AKA absolute zero)
|
||||
$celsius = -273.16;
|
||||
// Set templimit to null if no tempsensor was found
|
||||
$temperaturelimit = null;
|
||||
}
|
||||
|
||||
// Get load
|
||||
@@ -331,19 +334,14 @@ if($auth) {
|
||||
<div class="pull-left info">
|
||||
<p>Status</p>
|
||||
<?php
|
||||
$pistatus = pihole_execute('status web');
|
||||
if (isset($pistatus[0])) {
|
||||
$pistatus = intval($pistatus[0]);
|
||||
} else {
|
||||
$pistatus = null;
|
||||
}
|
||||
$pistatus = piholeStatus();
|
||||
if ($pistatus == 53) {
|
||||
echo '<span id="status"><i class="fa fa-w fa-circle text-green-light"></i> Active</span>';
|
||||
} elseif ($pistatus == 0) {
|
||||
echo '<span id="status"><i class="fa fa-w fa-circle text-red"></i> Offline</span>';
|
||||
} elseif ($pistatus == -1) {
|
||||
echo '<span id="status"><i class="fa fa-w fa-circle text-red"></i> DNS service not running</span>';
|
||||
} elseif ($pistatus == -2 || is_null($pistatus)) {
|
||||
} elseif ($pistatus == -2) {
|
||||
echo '<span id="status"><i class="fa fa-w fa-circle text-red"></i> Unknown</span>';
|
||||
} else {
|
||||
echo '<span id="status"><i class="fa fa-w fa-circle text-orange"></i> DNS service on port '.$pistatus.'</span>';
|
||||
@@ -375,18 +373,16 @@ if($auth) {
|
||||
?>
|
||||
<br/>
|
||||
<?php
|
||||
$tempcolor = "text-vivid-blue";
|
||||
if ($celsius > $temperaturelimit) {
|
||||
$tempcolor = "text-red";
|
||||
}
|
||||
echo '<span id="temperature"><i class="fa fa-w fa-fire '.$tempcolor.'" style="width: 1em !important"></i> ';
|
||||
|
||||
if ($celsius >= -273.15) {
|
||||
if ($celsius >= -273.15) {
|
||||
// Only show temp info if any data is available -->
|
||||
$tempcolor = "text-vivid-blue";
|
||||
if (isset($temperaturelimit) && $celsius > $temperaturelimit) {
|
||||
$tempcolor = "text-red";
|
||||
}
|
||||
echo '<span id="temperature"><i class="fa fa-w fa-fire '.$tempcolor.'" style="width: 1em !important"></i> ';
|
||||
echo 'Temp: <span id="rawtemp" hidden>' .$celsius. '</span>';
|
||||
} else {
|
||||
echo "No temp sensor found";
|
||||
}
|
||||
echo '<span id="tempdisplay"></span></span>';
|
||||
echo '<span id="tempdisplay"></span></span>';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -17,7 +17,7 @@ header('Cache-Control: no-cache');
|
||||
|
||||
function echoEvent($datatext) {
|
||||
if(!isset($_GET["IE"]))
|
||||
echo "data: ".implode("\ndata: ", explode("\n", $datatext))."\n\n";
|
||||
echo "data:".implode("\ndata:", explode("\n", $datatext))."\n\n";
|
||||
else
|
||||
echo $datatext;
|
||||
}
|
||||
|
||||
@@ -84,11 +84,15 @@ function archive_restore_table($file, $table, $flush=false)
|
||||
if(is_null($contents))
|
||||
return 0;
|
||||
|
||||
// Flush table if requested, only flush each table once
|
||||
// Flush table if requested. Only flush each table once, and only if it exists
|
||||
if($flush && !in_array($table, $flushed_tables))
|
||||
{
|
||||
$db->exec("DELETE FROM \"".$table."\"");
|
||||
array_push($flushed_tables, $table);
|
||||
$tableExists = $db->querySingle("SELECT name FROM sqlite_master WHERE type='table' AND name='".$table."';");
|
||||
if ($tableExists)
|
||||
{
|
||||
$db->exec("DELETE FROM \"".$table."\"");
|
||||
array_push($flushed_tables, $table);
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare fields depending on the table we restore to
|
||||
@@ -337,18 +341,15 @@ if(isset($_POST["action"]))
|
||||
$source = $_FILES["zip_file"]["tmp_name"];
|
||||
$type = mime_content_type($source);
|
||||
|
||||
$name = explode(".", $filename);
|
||||
// verify the file mime type
|
||||
$accepted_types = array('application/gzip', 'application/tar', 'application/x-compressed', 'application/x-gzip');
|
||||
$okay = false;
|
||||
foreach($accepted_types as $mime_type) {
|
||||
if($mime_type == $type) {
|
||||
$okay = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$mime_valid = in_array($type, $accepted_types);
|
||||
|
||||
$continue = strtolower($name[1]) == 'tar' && strtolower($name[2]) == 'gz' ? true : false;
|
||||
if(!$continue || !$okay) {
|
||||
// verify the file extension (Looking for ".tar.gz" at the end of the file name)
|
||||
$ext = array_slice(explode(".", $filename), -2, 2);
|
||||
$ext_valid = strtolower($ext[0]) == "tar" && strtolower($ext[1]) == "gz" ? true : false;
|
||||
|
||||
if(!$ext_valid || !$mime_valid) {
|
||||
die("The file you are trying to upload is not a .tar.gz file (filename: ".htmlentities($filename).", type: ".htmlentities($type)."). Please try again.");
|
||||
}
|
||||
|
||||
|
||||
+10
-7
@@ -19,6 +19,12 @@ if(isset($last_error) && ($last_error["type"] === E_WARNING || $last_error["type
|
||||
$error .= "There was a problem applying your settings.<br>Debugging information:<br>PHP error (".htmlspecialchars($last_error["type"])."): ".htmlspecialchars($last_error["message"])." in ".htmlspecialchars($last_error["file"]).":".htmlspecialchars($last_error["line"]);
|
||||
}
|
||||
|
||||
# Timezone is set in docker via ENV otherwise get it from commandline
|
||||
$timezone=htmlspecialchars(getenv("TZ"));
|
||||
if (empty($timezone)) {
|
||||
$timezone=shell_exec("date +'%Z'");
|
||||
}
|
||||
|
||||
?>
|
||||
<style>
|
||||
.tooltip-inner {
|
||||
@@ -253,7 +259,7 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "dns", "piho
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Time FTL started:</th>
|
||||
<td><?php print_r(get_FTL_data("lstart")); ?></td>
|
||||
<td><?php print_r(get_FTL_data("lstart")); echo " ".$timezone; ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">User / Group:</th>
|
||||
@@ -287,7 +293,7 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "dns", "piho
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<span title="Number of cache entries that had to be removed although they are not expired (increase cache size to reduce this number)">DNS cache evictions:</span>
|
||||
<span title="Number of cache entries that had to be removed although they are not expired (increase cache size to reduce this number)" lookatme-text="DNS cache evictions:">DNS cache evictions:</span>
|
||||
</th>
|
||||
<td id="cache-live-freed"> </td>
|
||||
</tr>
|
||||
@@ -457,7 +463,7 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "dns", "piho
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div><input type="checkbox" name="active" id="DHCPchk" <?php if ($DHCP){ ?>checked<?php } ?>><label for="DHCPchk"><strong>DHCP server enabled</strong></label></div><br>
|
||||
<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>
|
||||
<p id="dhcpnotice" lookatme-text="Make sure your router's DHCP server is disabled when using the Pi-hole DHCP server!" <?php if (!$DHCP){ ?>hidden<?php } ?>>Make sure your router's DHCP server is disabled when using the Pi-hole DHCP server!</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@@ -595,9 +601,6 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "dns", "piho
|
||||
}
|
||||
|
||||
$host = htmlentities($line[3]);
|
||||
if ($host == "*") {
|
||||
$host = "<i>unknown</i>";
|
||||
}
|
||||
|
||||
$clid = $line[4];
|
||||
if ($clid == "*") {
|
||||
@@ -1263,7 +1266,7 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "dns", "piho
|
||||
</div>
|
||||
<p>The privacy level may be increased at any time without having to restart the DNS resolver. However, note that the DNS resolver needs to be restarted when lowering the privacy level. This restarting is automatically done when saving.</p>
|
||||
<?php if($privacylevel > 0 && $piHoleLogging){ ?>
|
||||
<p class="lookatme">Warning: Pi-hole's query logging is activated. Although the dashboard will hide the requested details, all queries are still fully logged to the pihole.log file.</p>
|
||||
<p class="lookatme" lookatme-text="Warning: Pi-hole's query logging is activated. Although the dashboard will hide the requested details, all queries are still fully logged to the pihole.log file.">Warning: Pi-hole's query logging is activated. Although the dashboard will hide the requested details, all queries are still fully logged to the pihole.log file.</p>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+169
-31
@@ -19,41 +19,66 @@
|
||||
|
||||
@-webkit-keyframes Pulse {
|
||||
from {
|
||||
color: #630030;
|
||||
text-shadow: 0 0 2px transparent;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
50% {
|
||||
color: #e33100;
|
||||
text-shadow: 0 0 5px #e33100;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
to {
|
||||
color: #630030;
|
||||
text-shadow: 0 0 2px transparent;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes Pulse {
|
||||
from {
|
||||
color: #630030;
|
||||
text-shadow: 0 0 2px transparent;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
50% {
|
||||
color: #e33100;
|
||||
text-shadow: 0 0 5px #e33100;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
to {
|
||||
color: #630030;
|
||||
text-shadow: 0 0 2px transparent;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
p#dhcpnotice[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.lookatme #dhcpnotice {
|
||||
display: block;
|
||||
}
|
||||
|
||||
td.lookatme {
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.lookatme {
|
||||
-webkit-animation: 2s infinite Pulse;
|
||||
animation: 2s infinite Pulse;
|
||||
color: #630030;
|
||||
opacity: 1;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* this pseudo element will be faded in and out in front /*
|
||||
/* of the lookatme element to create an efficient animation. */
|
||||
.lookatme:after {
|
||||
color: #e33100;
|
||||
text-shadow: 0 0 5px #e33100;
|
||||
/* in the html, the lookatme-text attribute must */
|
||||
/* contain the same text as the .lookatme element */
|
||||
content: attr(lookatme-text);
|
||||
padding: inherit;
|
||||
position: absolute;
|
||||
inset: 0 0 0 0;
|
||||
z-index: 1;
|
||||
/* 20 steps / 2 seconds = 10fps */
|
||||
-webkit-animation: 2s infinite Pulse steps(20);
|
||||
animation: 2s infinite Pulse steps(20);
|
||||
}
|
||||
|
||||
.table-responsive {
|
||||
@@ -215,21 +240,54 @@
|
||||
|
||||
.chart-legend ul {
|
||||
list-style-type: none;
|
||||
padding-left: 45px;
|
||||
}
|
||||
|
||||
.chart-legend li {
|
||||
cursor: pointer;
|
||||
word-break: break-all;
|
||||
position: relative;
|
||||
line-height: 1;
|
||||
margin: 0 0 6px;
|
||||
}
|
||||
|
||||
.chart-legend li span {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
.colorBoxWrapper {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.colorBoxWrapper:hover {
|
||||
transform: scale(1.15);
|
||||
}
|
||||
|
||||
.chart-legend li .colorBoxWrapper {
|
||||
position: absolute;
|
||||
width: 20px;
|
||||
left: -20px;
|
||||
top: 0;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.chart-legend li .legend-color-box {
|
||||
display: none;
|
||||
width: 12px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.strike {
|
||||
.chart-legend li .legend-label-text {
|
||||
line-height: 1;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.chart-legend li .legend-label-text:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.strike,
|
||||
.strike span {
|
||||
text-decoration: line-through !important;
|
||||
}
|
||||
|
||||
@@ -442,29 +500,113 @@ td.details-control {
|
||||
right: 12px;
|
||||
}
|
||||
|
||||
/* Fix some datatables layout on small screens */
|
||||
@media screen and (max-width: 660px), screen and (min-width: 767px) and (max-width: 960px) {
|
||||
#domainsTable_wrapper .table-responsive {
|
||||
border: none;
|
||||
overflow: unset;
|
||||
}
|
||||
#domainsTable {
|
||||
border: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
#domainsTable thead {
|
||||
display: none;
|
||||
}
|
||||
#domainsTable tr {
|
||||
display: flex;
|
||||
padding: 15px 0;
|
||||
flex-wrap: wrap;
|
||||
box-sizing: border-box;
|
||||
align-items: end;
|
||||
border: 1px solid rgba(127, 127, 127, 0.4);
|
||||
margin: 10px 0;
|
||||
border-radius: 6px;
|
||||
}
|
||||
#domainsTable td {
|
||||
flex: 1 1 auto;
|
||||
width: 100px;
|
||||
display: block;
|
||||
border: none;
|
||||
box-sizing: border-box;
|
||||
order: 2;
|
||||
text-align: right;
|
||||
padding: 4px 8px;
|
||||
}
|
||||
#domainsTable td:nth-child(2n) {
|
||||
width: calc(100% - 120px);
|
||||
}
|
||||
#domainsTable td:first-child {
|
||||
width: calc(100% - 40px);
|
||||
order: 1;
|
||||
text-align: left;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid rgba(127, 127, 127, 0.25);
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
#domainsTable td:last-child {
|
||||
width: 40px;
|
||||
order: 1;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid rgba(127, 127, 127, 0.25);
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
#domainsTable td:nth-child(2),
|
||||
#domainsTable td:nth-child(4) {
|
||||
text-align: left;
|
||||
}
|
||||
#domainsTable td::before {
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
font-size: smaller;
|
||||
}
|
||||
#domainsTable td:nth-child(2)::before {
|
||||
content: "Type:";
|
||||
}
|
||||
#domainsTable td:nth-child(4)::before {
|
||||
content: "Comment:";
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: 767px) {
|
||||
#domainsTable select.form-control {
|
||||
padding: 0 0 0 5px;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 767px) {
|
||||
#domainsTable th {
|
||||
white-space: normal;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-bounce {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
animation: icon-bounce 1.5s infinite linear;
|
||||
animation: icon-bounce 2.4s 3 ease-in-out;
|
||||
font-size: 1.6em;
|
||||
}
|
||||
|
||||
@keyframes icon-bounce {
|
||||
0%,
|
||||
20%,
|
||||
15%,
|
||||
50%,
|
||||
70%,
|
||||
90%,
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
25% {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
30% {
|
||||
transform: translateY(4px);
|
||||
}
|
||||
35% {
|
||||
transform: translateY(-3px);
|
||||
}
|
||||
40% {
|
||||
transform: translateY(-15px);
|
||||
transform: translateY(2px);
|
||||
}
|
||||
60% {
|
||||
transform: translateY(-8px);
|
||||
}
|
||||
80% {
|
||||
transform: translateY(-4px);
|
||||
45% {
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -472,10 +614,6 @@ td.details-control {
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.eyeConWrapper {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#apiTokenIframe {
|
||||
width: 100%;
|
||||
border: 0;
|
||||
|
||||
@@ -211,6 +211,7 @@ h4 {
|
||||
.main-header .navbar .nav > li > a,
|
||||
.main-header .navbar .nav > li > .navbar-text {
|
||||
color: #bec5cb;
|
||||
max-height: 50px;
|
||||
}
|
||||
.main-header .navbar .nav > li > a:hover,
|
||||
.main-header .navbar .nav > li > a:active,
|
||||
@@ -263,24 +264,36 @@ h4 {
|
||||
.nav-tabs-custom .tab-content {
|
||||
background-color: #30383f;
|
||||
}
|
||||
.nav-tabs-custom > .nav-tabs > li.active > a {
|
||||
border-left-color: #353c42;
|
||||
border-right-color: #353c42;
|
||||
background-color: #272c30;
|
||||
color: #bec5cb;
|
||||
}
|
||||
.nav-tabs-custom > .nav-tabs.pull-right > li:first-of-type.active > a {
|
||||
border-left-color: #353c42;
|
||||
.nav-tabs-custom > .nav-tabs {
|
||||
background: rgba(64, 72, 80, 0.666);
|
||||
}
|
||||
.nav-tabs-custom > .nav-tabs > li {
|
||||
margin-right: 1px;
|
||||
color: #bec5cb;
|
||||
}
|
||||
.nav-tabs-custom > .nav-tabs > li.active > a,
|
||||
.nav-tabs-custom > .nav-tabs > li.active:hover > a {
|
||||
border-left-color: #30383f;
|
||||
border-right-color: #30383f;
|
||||
background-color: #30383f;
|
||||
color: #bec5cb;
|
||||
}
|
||||
.nav-tabs-custom > .nav-tabs > li:not(.active):hover {
|
||||
border-top-color: #d2d6de;
|
||||
background-color: transparent;
|
||||
}
|
||||
.nav-tabs-custom > .nav-tabs > li > a {
|
||||
color: #bec5cb;
|
||||
color: #8e959b;
|
||||
}
|
||||
.nav-tabs-custom > .nav-tabs > li > a:focus {
|
||||
background: #404850;
|
||||
color: #3c8dbc;
|
||||
}
|
||||
.nav-tabs-custom > .nav-tabs > li:hover > a,
|
||||
.nav-tabs-custom > .nav-tabs > li.active:hover > a {
|
||||
background-color: #353c42;
|
||||
color: #bec5cb;
|
||||
}
|
||||
|
||||
.list-group {
|
||||
color: #bec5cb;
|
||||
background-color: #272c30;
|
||||
@@ -452,11 +465,6 @@ div.dataTables_wrapper div.dataTables_length select {
|
||||
color: #bec5cb;
|
||||
border: 1px solid #3d444b;
|
||||
}
|
||||
.nav-tabs-custom > .nav-tabs > li:hover > a,
|
||||
.nav-tabs-custom > .nav-tabs > li.active:hover > a {
|
||||
background-color: #353c42;
|
||||
color: #bec5cb;
|
||||
}
|
||||
.form-control[disabled],
|
||||
.form-control[readonly],
|
||||
fieldset[disabled] .form-control {
|
||||
|
||||
@@ -3330,16 +3330,18 @@ a:focus {
|
||||
box-shadow: rgba(0, 0, 0, 0.1) 0 1px 1px;
|
||||
}
|
||||
.nav-tabs-custom > .nav-tabs {
|
||||
background: rgb(30, 40, 44);
|
||||
border-bottom-color: rgb(51, 55, 57);
|
||||
}
|
||||
.nav-tabs-custom > .nav-tabs > li {
|
||||
border-top-color: transparent;
|
||||
margin-right: 1px;
|
||||
}
|
||||
.nav-tabs-custom > .nav-tabs > li.disabled > a {
|
||||
color: rgb(157, 148, 136);
|
||||
}
|
||||
.nav-tabs-custom > .nav-tabs > li > a {
|
||||
color: rgb(189, 183, 175);
|
||||
color: rgb(140, 144, 154);
|
||||
}
|
||||
.nav-tabs-custom > .nav-tabs > li > a.text-muted {
|
||||
color: rgb(168, 160, 149);
|
||||
@@ -3352,10 +3354,8 @@ a:focus {
|
||||
.nav-tabs-custom > .nav-tabs > li > a:hover {
|
||||
color: rgb(168, 160, 149);
|
||||
}
|
||||
.nav-tabs-custom > .nav-tabs > li:not(.active) > a:hover,
|
||||
.nav-tabs-custom > .nav-tabs > li:not(.active) > a:focus,
|
||||
.nav-tabs-custom > .nav-tabs > li:not(.active) > a:active {
|
||||
border-color: transparent;
|
||||
.nav-tabs-custom > .nav-tabs > li:not(.active):hover {
|
||||
background: rgb(24, 32, 35);
|
||||
}
|
||||
.nav-tabs-custom > .nav-tabs > li.active {
|
||||
border-top-color: rgb(44, 103, 137);
|
||||
@@ -3392,7 +3392,7 @@ a:focus {
|
||||
}
|
||||
.nav-tabs-custom > .nav-tabs > li > a:focus,
|
||||
.nav-tabs-custom > .nav-tabs > li.active > a:focus {
|
||||
color: rgb(95, 142, 170);
|
||||
color: rgb(60, 140, 188);
|
||||
}
|
||||
|
||||
.nav-tabs-custom.tab-primary > .nav-tabs > li.active {
|
||||
@@ -5456,6 +5456,7 @@ link-muted {
|
||||
.main-header .navbar .nav > li > a,
|
||||
.main-header .navbar .nav > li > .navbar-text {
|
||||
color: rgb(232, 230, 227);
|
||||
max-height: 50px;
|
||||
}
|
||||
.main-header .navbar .nav > li > a:hover,
|
||||
.main-header .navbar .nav > li > a:active,
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
.main-header .navbar .nav > li > a,
|
||||
.main-header .navbar .nav > li > .navbar-text {
|
||||
color: #fff;
|
||||
max-height: 50px;
|
||||
}
|
||||
.main-header .navbar .nav > li > a:hover,
|
||||
.main-header .navbar .nav > li > a:active,
|
||||
@@ -130,8 +131,23 @@
|
||||
border-bottom-right-radius: 2px;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
.nav-tabs-custom > .nav-tabs {
|
||||
background: #e4e8f0;
|
||||
}
|
||||
.nav-tabs-custom > .nav-tabs > li {
|
||||
margin-right: 1px;
|
||||
}
|
||||
.nav-tabs-custom > .nav-tabs > li:not(.active):hover {
|
||||
background: #fff;
|
||||
border-top-color: #d2d6de;
|
||||
}
|
||||
.nav-tabs-custom > .nav-tabs > li > a,
|
||||
.nav-tabs-custom > .nav-tabs > li > a:hover {
|
||||
color: #567;
|
||||
}
|
||||
.nav-tabs-custom > .nav-tabs > li > a:focus {
|
||||
color: #60a4cc;
|
||||
color: #3c8dbc;
|
||||
}
|
||||
|
||||
.layout-top-nav .main-header > .logo {
|
||||
|
||||
+69
-24
@@ -312,6 +312,13 @@ label {
|
||||
font-weight: bold !important;
|
||||
}
|
||||
|
||||
div .panel-title,
|
||||
p.login-box-msg,
|
||||
.form-group.has-error label {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.form-control::placeholder {
|
||||
color: #456;
|
||||
}
|
||||
@@ -329,24 +336,34 @@ label {
|
||||
|
||||
.form-group.has-error.login-box-msg::before {
|
||||
content: "ACCESS DENIED";
|
||||
display: block;
|
||||
margin: -20px -20px 20px;
|
||||
padding: calc(45px + 0.7em) 0 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 130px;
|
||||
color: #d43;
|
||||
inset: 0 0 0 0;
|
||||
color: #630030;
|
||||
font-size: 3.825em;
|
||||
font-size: calc((100vw - var(--sidebar-width) - 60px) / 12);
|
||||
line-height: 1;
|
||||
animation: 3s infinite Pulse;
|
||||
background: rgba(0, 0, 0, 0.88);
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.layout-boxed .form-group.has-error.login-box-msg::before {
|
||||
.form-group.has-error.login-box-msg::after {
|
||||
content: "ACCESS DENIED";
|
||||
margin: -20px -20px 20px;
|
||||
padding: calc(45px + 0.7em) 0 0;
|
||||
position: absolute;
|
||||
inset: 0 0 0 0;
|
||||
color: #e33100;
|
||||
font-size: 3.825em;
|
||||
font-size: calc((100vw - var(--sidebar-width) - 60px) / 12);
|
||||
line-height: 1;
|
||||
text-shadow: 0 0 5px #e33100;
|
||||
animation: 3s infinite Pulse steps(30);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.layout-boxed .form-group.has-error.login-box-msg::before,
|
||||
.layout-boxed .form-group.has-error.login-box-msg::after {
|
||||
padding: calc(50% - 0.5em) 0 0;
|
||||
}
|
||||
|
||||
@@ -1460,37 +1477,54 @@ table.dataTable {
|
||||
|
||||
@-webkit-keyframes warningPulse {
|
||||
0% {
|
||||
border-color: rgba(255, 153, 0, 0.4);
|
||||
opacity: 0;
|
||||
}
|
||||
50% {
|
||||
border-color: rgba(255, 150, 0, 1);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
border-color: rgba(255, 153, 0, 0.4);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes warningPulse {
|
||||
0% {
|
||||
border-color: rgba(255, 153, 0, 0.4);
|
||||
opacity: 0;
|
||||
}
|
||||
50% {
|
||||
border-color: rgba(255, 150, 0, 1);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
border-color: rgba(255, 153, 0, 0.4);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.box-warning {
|
||||
animation: 3s infinite warningPulse;
|
||||
.box.box-warning {
|
||||
border-top-color: #71480a;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.box.box-warning:after {
|
||||
content: "";
|
||||
border-top: 3px solid #f89201;
|
||||
border-radius: 12px;
|
||||
position: absolute;
|
||||
margin-top: -3px;
|
||||
inset: 0 0 0 0;
|
||||
z-index: -1;
|
||||
animation: 3s infinite warningPulse steps(30);
|
||||
}
|
||||
|
||||
.box.box-warning div {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
/*** MEDIA QUERIES ***/
|
||||
|
||||
/*--- Media - max-width ---*/
|
||||
@media (max-width: 991px) {
|
||||
.form-group.has-error.login-box-msg::before {
|
||||
.form-group.has-error.login-box-msg::before,
|
||||
.form-group.has-error.login-box-msg::after {
|
||||
font-size: calc((100vw - var(--sidebar-width) - 60px) / 9);
|
||||
}
|
||||
}
|
||||
@@ -1581,7 +1615,8 @@ table.dataTable {
|
||||
.main-footer {
|
||||
margin-left: 0;
|
||||
}
|
||||
.form-group.has-error.login-box-msg::before {
|
||||
.form-group.has-error.login-box-msg::before,
|
||||
.form-group.has-error.login-box-msg::after {
|
||||
font-size: calc((100vw - 60px) / 6);
|
||||
}
|
||||
}
|
||||
@@ -1652,24 +1687,34 @@ table.dataTable {
|
||||
}
|
||||
|
||||
@media (min-width: 1320px) {
|
||||
.layout-boxed .form-group.has-error.login-box-msg::before {
|
||||
.layout-boxed .form-group.has-error.login-box-msg::before,
|
||||
.layout-boxed .form-group.has-error.login-box-msg::after {
|
||||
font-size: calc((1320px - var(--sidebar-width) - 60px) / 12);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1920px) {
|
||||
.layout-boxed .form-group.has-error.login-box-msg::before {
|
||||
@media (min-width: 1960px) {
|
||||
.layout-boxed .form-group.has-error.login-box-msg::before,
|
||||
.layout-boxed .form-group.has-error.login-box-msg::after {
|
||||
font-size: calc((1920px - var(--sidebar-width) - 60px) / 12);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1960px) {
|
||||
.layout-boxed .wrapper {
|
||||
box-shadow: none;
|
||||
max-width: 1920px;
|
||||
}
|
||||
}
|
||||
|
||||
/*** Fix some datatables layout on small screens ***/
|
||||
@media screen and (max-width: 660px), screen and (min-width: 767px) and (max-width: 960px) {
|
||||
#domainsTable td::before {
|
||||
margin: 0 5px 2px;
|
||||
}
|
||||
#domainsTable td:nth-child(2n) {
|
||||
width: calc(100% - 160px);
|
||||
}
|
||||
}
|
||||
|
||||
/*** Used by the long-term pages ***/
|
||||
.daterangepicker {
|
||||
background-color: #345;
|
||||
|
||||
Reference in New Issue
Block a user