Format JS code

Signed-off-by: XhmikosR <xhmikosr@gmail.com>
This commit is contained in:
XhmikosR
2019-12-16 13:37:34 +02:00
parent 3321fa8067
commit 704c352277
21 changed files with 3536 additions and 3388 deletions
+125 -103
View File
@@ -1,12 +1,13 @@
/* 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. */
* (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. */
// Define global variables
var auditList = [], auditTimeout;
var auditList = [],
auditTimeout;
// Credit: http://stackoverflow.com/questions/1787322/htmlspecialchars-equivalent-in-javascript/4835406#4835406
function escapeHtml(text) {
@@ -14,123 +15,144 @@ function escapeHtml(text) {
"&": "&amp;",
"<": "&lt;",
">": "&gt;",
"\"": "&quot;",
'"': "&quot;",
"'": "&#039;"
};
return text.replace(/[&<>"']/g, function(m) { return map[m]; });
return text.replace(/[&<>"']/g, function(m) {
return map[m];
});
}
function updateTopLists() {
$.getJSON("api.php?topItems=audit", function(data) {
$.getJSON("api.php?topItems=audit", function(data) {
if ("FTLnotrunning" in data) {
return;
}
if("FTLnotrunning" in data)
{
return;
// Clear tables before filling them with data
$("#domain-frequency td")
.parent()
.remove();
$("#ad-frequency td")
.parent()
.remove();
var domaintable = $("#domain-frequency").find("tbody:last");
var adtable = $("#ad-frequency").find("tbody:last");
var url, domain;
for (domain in data.top_queries) {
if (Object.prototype.hasOwnProperty.call(data.top_queries, domain)) {
// Sanitize domain
domain = escapeHtml(domain);
url = '<a href="queries.php?domain=' + domain + '">' + domain + "</a>";
domaintable.append(
"<tr> <td>" +
url +
"</td> <td>" +
data.top_queries[domain] +
'</td> <td> <button type="button" class="btn btn-default btn-sm text-red"><i class="fa fa-ban"></i> Blacklist</button> <button class="btn btn-default btn-sm text-orange"><i class="fa fa-balance-scale"></i> Audit</button> </td> </tr> '
);
}
}
for (domain in data.top_ads) {
if (Object.prototype.hasOwnProperty.call(data.top_ads, domain)) {
var input = domain.split(" ");
// Sanitize domain
var printdomain = escapeHtml(input[0]);
if (input.length > 1) {
url =
'<a href="queries.php?domain=' +
printdomain +
'">' +
printdomain +
"</a> (wildcard blocked)";
adtable.append(
"<tr> <td>" +
url +
"</td> <td>" +
data.top_ads[domain] +
'</td> <td> <button type="button" class="btn btn-default btn-sm text-orange"><i class="fa fa-balance-scale"></i> Audit</button> </td> </tr> '
);
} else {
url = '<a href="queries.php?domain=' + printdomain + '">' + printdomain + "</a>";
adtable.append(
"<tr> <td>" +
url +
"</td> <td>" +
data.top_ads[domain] +
'</td> <td> <button type="button" class="btn btn-default btn-sm text-green"><i class="fas fa-check"></i> Whitelist</button> <button class="btn btn-default btn-sm text-orange"><i class="fa fa-balance-scale"></i> Audit</button> </td> </tr> '
);
}
}
}
// Clear tables before filling them with data
$("#domain-frequency td").parent().remove();
$("#ad-frequency td").parent().remove();
var domaintable = $("#domain-frequency").find("tbody:last");
var adtable = $("#ad-frequency").find("tbody:last");
var url, domain;
for (domain in data.top_queries) {
if (Object.prototype.hasOwnProperty.call(data.top_queries,domain)){
// Sanitize domain
domain = escapeHtml(domain);
url = "<a href=\"queries.php?domain="+domain+"\">"+domain+"</a>";
domaintable.append("<tr> <td>" + url +
"</td> <td>" + data.top_queries[domain] + "</td> <td> <button type=\"button\" class=\"btn btn-default btn-sm text-red\"><i class=\"fa fa-ban\"></i> Blacklist</button> <button class=\"btn btn-default btn-sm text-orange\"><i class=\"fa fa-balance-scale\"></i> Audit</button> </td> </tr> ");
}
}
for (domain in data.top_ads) {
if (Object.prototype.hasOwnProperty.call(data.top_ads,domain)){
var input = domain.split(" ");
// Sanitize domain
var printdomain = escapeHtml(input[0]);
if(input.length > 1)
{
url = "<a href=\"queries.php?domain="+printdomain+"\">"+printdomain+"</a> (wildcard blocked)";
adtable.append("<tr> <td>" + url +
"</td> <td>" + data.top_ads[domain] + "</td> <td> <button type=\"button\" class=\"btn btn-default btn-sm text-orange\"><i class=\"fa fa-balance-scale\"></i> Audit</button> </td> </tr> ");
}
else
{
url = "<a href=\"queries.php?domain="+printdomain+"\">"+printdomain+"</a>";
adtable.append("<tr> <td>" + url +
"</td> <td>" + data.top_ads[domain] + "</td> <td> <button type=\"button\" class=\"btn btn-default btn-sm text-green\"><i class=\"fas fa-check\"></i> Whitelist</button> <button class=\"btn btn-default btn-sm text-orange\"><i class=\"fa fa-balance-scale\"></i> Audit</button> </td> </tr> ");
}
}
}
$("#domain-frequency .overlay").hide();
$("#ad-frequency .overlay").hide();
// Update top lists data every second
setTimeout(updateTopLists, 1000);
});
$("#domain-frequency .overlay").hide();
$("#ad-frequency .overlay").hide();
// Update top lists data every second
setTimeout(updateTopLists, 1000);
});
}
function add(domain,list) {
var token = $("#token").text();
$.ajax({
url: "scripts/pi-hole/php/add.php",
method: "post",
data: {"domain":domain, "list":list, "token":token}
});
function add(domain, list) {
var token = $("#token").text();
$.ajax({
url: "scripts/pi-hole/php/add.php",
method: "post",
data: { domain: domain, list: list, token: token }
});
}
$(document).ready(function() {
// Pull in data via AJAX
updateTopLists();
// Pull in data via AJAX
updateTopLists();
$("#domain-frequency tbody").on("click", "button", function() {
var url = $(this)
.parents("tr")[0]
.textContent.split(" ")[0];
if ($(this).context.textContent === " Blacklist") {
add(url, "audit");
add(url, "black");
$("#gravityBtn").prop("disabled", false);
} else {
auditUrl(url);
}
});
$("#domain-frequency tbody").on( "click", "button", function () {
var url = ($(this).parents("tr"))[0].textContent.split(" ")[0];
if($(this).context.textContent === " Blacklist")
{
add(url,"audit");
add(url,"black");
$("#gravityBtn").prop("disabled", false);
}
else
{
auditUrl(url);
}
});
$("#ad-frequency tbody").on( "click", "button", function () {
var url = ($(this).parents("tr"))[0].textContent.split(" ")[0].split(" ")[0];
if($(this).context.textContent === " Whitelist")
{
add(url,"audit");
add(url,"white");
$("#gravityBtn").prop("disabled", false);
}
else
{
auditUrl(url);
}
});
$("#ad-frequency tbody").on("click", "button", function() {
var url = $(this)
.parents("tr")[0]
.textContent.split(" ")[0]
.split(" ")[0];
if ($(this).context.textContent === " Whitelist") {
add(url, "audit");
add(url, "white");
$("#gravityBtn").prop("disabled", false);
} else {
auditUrl(url);
}
});
});
function auditUrl(url) {
if (auditList.indexOf(url) > -1) {
return;
}
if (auditTimeout) {
clearTimeout(auditTimeout);
}
auditList.push(url);
// wait 3 seconds to see if more domains need auditing
// and batch them all into a single request
auditTimeout = setTimeout(function() {
add(auditList.join(' '), "audit");
auditList = [];
}, 3000);
if (auditList.indexOf(url) > -1) {
return;
}
if (auditTimeout) {
clearTimeout(auditTimeout);
}
auditList.push(url);
// wait 3 seconds to see if more domains need auditing
// and batch them all into a single request
auditTimeout = setTimeout(function() {
add(auditList.join(" "), "audit");
auditList = [];
}, 3000);
}
$("#gravityBtn").on("click", function() {
window.location.replace("gravity.php?go");
window.location.replace("gravity.php?go");
});
+91 -86
View File
@@ -1,105 +1,110 @@
/* 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. */
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
* Network-wide ad blocking via your own hardware.
*
* This file is copyright under the latest version of the EUPL.
* Please see LICENSE file for your rights under this license. */
var table;
function showAlert(type, message)
{
var alertElement = null;
var messageElement = null;
function showAlert(type, message) {
var alertElement = null;
var messageElement = null;
switch (type)
{
case 'info': alertElement = $('#alInfo'); break;
case 'success': alertElement = $('#alSuccess'); break;
case 'warning': alertElement = $('#alWarning'); messageElement = $('#warn'); break;
case 'error': alertElement = $('#alFailure'); messageElement = $('#err'); break;
default: return;
}
switch (type) {
case "info":
alertElement = $("#alInfo");
break;
case "success":
alertElement = $("#alSuccess");
break;
case "warning":
alertElement = $("#alWarning");
messageElement = $("#warn");
break;
case "error":
alertElement = $("#alFailure");
messageElement = $("#err");
break;
default:
return;
}
if (messageElement != null)
messageElement.html(message);
if (messageElement != null) messageElement.html(message);
alertElement.fadeIn(200);
alertElement.delay(8000).fadeOut(2000);
alertElement.fadeIn(200);
alertElement.delay(8000).fadeOut(2000);
}
$(document).ready(function() {
$("#btnAdd").on("click", addCustomDNS);
$('#btnAdd').on('click', addCustomDNS);
table = $("#customDNSTable").DataTable( {
"ajax": "scripts/pi-hole/php/customdns.php?action=get",
columns: [
{},
{},
{orderable: false, searchable: false}
],
"columnDefs": [ {
"targets": 2,
"render": function ( data, type, row ) {
return "<button class=\"btn btn-danger btn-xs deleteCustomDNS\" type=\"button\" data-domain='"+row[0]+"' data-ip='"+row[1]+"'>" +
"<span class=\"glyphicon glyphicon-trash\"></span>" +
"</button>";
}
} ],
"drawCallback": function() {
$('.deleteCustomDNS').on('click', deleteCustomDNS);
table = $("#customDNSTable").DataTable({
ajax: "scripts/pi-hole/php/customdns.php?action=get",
columns: [{}, {}, { orderable: false, searchable: false }],
columnDefs: [
{
targets: 2,
render: function(data, type, row) {
return (
'<button class="btn btn-danger btn-xs deleteCustomDNS" type="button" data-domain=\'' +
row[0] +
"' data-ip='" +
row[1] +
"'>" +
'<span class="glyphicon glyphicon-trash"></span>' +
"</button>"
);
}
});
}
],
drawCallback: function() {
$(".deleteCustomDNS").on("click", deleteCustomDNS);
}
});
});
function addCustomDNS()
{
var ip = $('#ip').val();
var domain = $('#domain').val();
function addCustomDNS() {
var ip = $("#ip").val();
var domain = $("#domain").val();
showAlert('info');
$.ajax({
url: "scripts/pi-hole/php/customdns.php",
method: "post",
dataType: 'json',
data: {"action":"add", "ip" : ip, "domain": domain},
success: function(response) {
if (response.success) {
showAlert('success');
table.ajax.reload();
}
else
showAlert('error', response.message);
},
error: function() {
showAlert('error', "Error while adding this custom DNS entry");
}
});
showAlert("info");
$.ajax({
url: "scripts/pi-hole/php/customdns.php",
method: "post",
dataType: "json",
data: { action: "add", ip: ip, domain: domain },
success: function(response) {
if (response.success) {
showAlert("success");
table.ajax.reload();
} else showAlert("error", response.message);
},
error: function() {
showAlert("error", "Error while adding this custom DNS entry");
}
});
}
function deleteCustomDNS()
{
var ip = $(this).attr("data-ip");
var domain = $(this).attr("data-domain");
function deleteCustomDNS() {
var ip = $(this).attr("data-ip");
var domain = $(this).attr("data-domain");
showAlert('info');
$.ajax({
url: "scripts/pi-hole/php/customdns.php",
method: "post",
dataType: 'json',
data: {"action":"delete", "domain": domain, "ip": ip},
success: function(response) {
if (response.success) {
showAlert('success');
table.ajax.reload();
}
else
showAlert('error', response.message);
},
error: function(jqXHR, exception) {
showAlert('error', "Error while deleting this custom DNS entry");
console.log(exception);
}
});
showAlert("info");
$.ajax({
url: "scripts/pi-hole/php/customdns.php",
method: "post",
dataType: "json",
data: { action: "delete", domain: domain, ip: ip },
success: function(response) {
if (response.success) {
showAlert("success");
table.ajax.reload();
} else showAlert("error", response.message);
},
error: function(jqXHR, exception) {
showAlert("error", "Error while deleting this custom DNS entry");
console.log(exception);
}
});
}
+270 -230
View File
@@ -1,66 +1,97 @@
/* 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. */
* (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. */
/* global Chart:false, moment:false */
var start__ = moment().subtract(6, "days");
var from = moment(start__).utc().valueOf()/1000;
var from =
moment(start__)
.utc()
.valueOf() / 1000;
var end__ = moment();
var until = moment(end__).utc().valueOf()/1000;
var until =
moment(end__)
.utc()
.valueOf() / 1000;
var interval = 0;
var timeoutWarning = $("#timeoutWarning");
var dateformat = "MMMM Do YYYY, HH:mm";
$(function () {
$("#querytime").daterangepicker(
$(function() {
$("#querytime").daterangepicker(
{
timePicker: true, timePickerIncrement: 15,
timePicker: true,
timePickerIncrement: 15,
locale: { format: dateformat },
startDate: start__, endDate: end__,
startDate: start__,
endDate: end__,
ranges: {
"Today": [moment().startOf("day"), moment()],
"Yesterday": [moment().subtract(1, "days").startOf("day"), moment().subtract(1, "days").endOf("day")],
Today: [moment().startOf("day"), moment()],
Yesterday: [
moment()
.subtract(1, "days")
.startOf("day"),
moment()
.subtract(1, "days")
.endOf("day")
],
"Last 7 Days": [moment().subtract(6, "days"), moment()],
"Last 30 Days": [moment().subtract(29, "days"), moment()],
"This Month": [moment().startOf("month"), moment()],
"Last Month": [moment().subtract(1, "month").startOf("month"), moment().subtract(1, "month").endOf("month")],
"Last Month": [
moment()
.subtract(1, "month")
.startOf("month"),
moment()
.subtract(1, "month")
.endOf("month")
],
"This Year": [moment().startOf("year"), moment()],
"All Time": [moment(0), moment()]
},
"opens": "center", "showDropdowns": true,
"autoUpdateInput": false
opens: "center",
showDropdowns: true,
autoUpdateInput: false
},
function (startt, endt) {
from = moment(startt).utc().valueOf()/1000;
until = moment(endt).utc().valueOf()/1000;
});
function(startt, endt) {
from =
moment(startt)
.utc()
.valueOf() / 1000;
until =
moment(endt)
.utc()
.valueOf() / 1000;
}
);
});
function padNumber(num) {
return ("00" + num).substr(-2,2);
return ("00" + num).substr(-2, 2);
}
// Helper function needed for converting the Objects to Arrays
function objectToArray(p){
var keys = Object.keys(p);
keys.sort(function(a, b) {
return a - b;
});
function objectToArray(p) {
var keys = Object.keys(p);
keys.sort(function(a, b) {
return a - b;
});
var arr = [], idx = [];
for (var i = 0; i < keys.length; i++) {
arr.push(p[keys[i]]);
idx.push(keys[i]);
}
return [idx,arr];
var arr = [],
idx = [];
for (var i = 0; i < keys.length; i++) {
arr.push(p[keys[i]]);
idx.push(keys[i]);
}
return [idx, arr];
}
var timeLineChart;
@@ -70,229 +101,238 @@ function compareNumbers(a, b) {
}
function updateQueriesOverTime() {
$("#queries-over-time .overlay").show();
timeoutWarning.show();
$("#queries-over-time .overlay").show();
timeoutWarning.show();
// Compute interval to obtain about 200 values
var num = 200;
interval = (until-from)/num;
// Default displaying axis scaling
timeLineChart.options.scales.xAxes[0].time.unit="hour"
// Compute interval to obtain about 200 values
var num = 200;
interval = (until - from) / num;
// Default displaying axis scaling
timeLineChart.options.scales.xAxes[0].time.unit = "hour";
if(num*interval >= 6*29*24*60*60)
{
// If the requested data is more than 3 months, set ticks interval to quarterly
timeLineChart.options.scales.xAxes[0].time.unit="quarter"
}
else if(num*interval >= 3*29*24*60*60)
{
// If the requested data is more than 3 months, set ticks interval to months
timeLineChart.options.scales.xAxes[0].time.unit="month"
}
if(num*interval >= 29*24*60*60)
{
// If the requested data is more than 1 month, set ticks interval to weeks
timeLineChart.options.scales.xAxes[0].time.unit="week"
}
else if(num*interval >= 6*24*60*60)
{
// If the requested data is more than 1 week, set ticks interval to days
timeLineChart.options.scales.xAxes[0].time.unit="day"
}
if (num * interval >= 6 * 29 * 24 * 60 * 60) {
// If the requested data is more than 3 months, set ticks interval to quarterly
timeLineChart.options.scales.xAxes[0].time.unit = "quarter";
} else if (num * interval >= 3 * 29 * 24 * 60 * 60) {
// If the requested data is more than 3 months, set ticks interval to months
timeLineChart.options.scales.xAxes[0].time.unit = "month";
}
$.getJSON("api_db.php?getGraphData&from="+from+"&until="+until+"&interval="+interval, function(data) {
if (num * interval >= 29 * 24 * 60 * 60) {
// If the requested data is more than 1 month, set ticks interval to weeks
timeLineChart.options.scales.xAxes[0].time.unit = "week";
} else if (num * interval >= 6 * 24 * 60 * 60) {
// If the requested data is more than 1 week, set ticks interval to days
timeLineChart.options.scales.xAxes[0].time.unit = "day";
}
// convert received objects to arrays
data.domains_over_time = objectToArray(data.domains_over_time);
data.ads_over_time = objectToArray(data.ads_over_time);
// Remove possibly already existing data
timeLineChart.data.labels = [];
timeLineChart.data.datasets[0].data = [];
timeLineChart.data.datasets[1].data = [];
$.getJSON(
"api_db.php?getGraphData&from=" + from + "&until=" + until + "&interval=" + interval,
function(data) {
// convert received objects to arrays
data.domains_over_time = objectToArray(data.domains_over_time);
data.ads_over_time = objectToArray(data.ads_over_time);
// Remove possibly already existing data
timeLineChart.data.labels = [];
timeLineChart.data.datasets[0].data = [];
timeLineChart.data.datasets[1].data = [];
var dates = [], hour;
var dates = [],
hour;
for (hour in data.domains_over_time[0]) {
if (Object.prototype.hasOwnProperty.call(data.domains_over_time[0], hour)) {
dates.push(parseInt(data.domains_over_time[0][hour]));
}
for (hour in data.domains_over_time[0]) {
if (Object.prototype.hasOwnProperty.call(data.domains_over_time[0], hour)) {
dates.push(parseInt(data.domains_over_time[0][hour]));
}
}
for (hour in data.ads_over_time[0]) {
if (Object.prototype.hasOwnProperty.call(data.ads_over_time[0], hour)) {
if(dates.indexOf(parseInt(data.ads_over_time[0][hour])) === -1)
{
dates.push(parseInt(data.ads_over_time[0][hour]));
}
}
for (hour in data.ads_over_time[0]) {
if (Object.prototype.hasOwnProperty.call(data.ads_over_time[0], hour)) {
if (dates.indexOf(parseInt(data.ads_over_time[0][hour])) === -1) {
dates.push(parseInt(data.ads_over_time[0][hour]));
}
}
}
dates.sort(compareNumbers);
dates.sort(compareNumbers);
// Add data for each hour that is available
for (hour in dates) {
if (Object.prototype.hasOwnProperty.call(dates, hour)) {
var date, dom = 0, ads = 0;
date = new Date(1000*dates[hour]);
// Add data for each hour that is available
for (hour in dates) {
if (Object.prototype.hasOwnProperty.call(dates, hour)) {
var date,
dom = 0,
ads = 0;
date = new Date(1000 * dates[hour]);
var idx = data.domains_over_time[0].indexOf(dates[hour].toString());
if (idx > -1)
{
dom = data.domains_over_time[1][idx];
}
var idx = data.domains_over_time[0].indexOf(dates[hour].toString());
if (idx > -1) {
dom = data.domains_over_time[1][idx];
}
idx = data.ads_over_time[0].indexOf(dates[hour].toString());
if (idx > -1)
{
ads = data.ads_over_time[1][idx];
}
idx = data.ads_over_time[0].indexOf(dates[hour].toString());
if (idx > -1) {
ads = data.ads_over_time[1][idx];
}
timeLineChart.data.labels.push(date);
timeLineChart.data.datasets[0].data.push(dom - ads);
timeLineChart.data.datasets[1].data.push(ads);
}
timeLineChart.data.labels.push(date);
timeLineChart.data.datasets[0].data.push(dom - ads);
timeLineChart.data.datasets[1].data.push(ads);
}
}
timeLineChart.options.scales.xAxes[0].display=true;
$("#queries-over-time .overlay").hide();
timeoutWarning.hide();
timeLineChart.update();
});
timeLineChart.options.scales.xAxes[0].display = true;
$("#queries-over-time .overlay").hide();
timeoutWarning.hide();
timeLineChart.update();
}
);
}
$(document).ready(function() {
var ctx = document.getElementById("queryOverTimeChart").getContext("2d");
timeLineChart = new Chart(ctx, {
type: "bar",
data: {
labels: [ ],
datasets: [
{
label: "Permitted DNS Queries",
fill: true,
backgroundColor: "rgba(0, 166, 90,.8)",
borderColor: "rgba(0, 166, 90,.8)",
pointBorderColor: "rgba(0, 166, 90,.8)",
pointRadius: 1,
pointHoverRadius: 5,
data: [],
pointHitRadius: 5
},
{
label: "Blocked DNS Queries",
fill: true,
backgroundColor: "rgba(0,192,239,1)",
borderColor: "rgba(0,192,239,1)",
pointBorderColor: "rgba(0,192,239,1)",
pointRadius: 1,
pointHoverRadius: 5,
data: [],
pointHitRadius: 5
}
]
var ctx = document.getElementById("queryOverTimeChart").getContext("2d");
timeLineChart = new Chart(ctx, {
type: "bar",
data: {
labels: [],
datasets: [
{
label: "Permitted DNS Queries",
fill: true,
backgroundColor: "rgba(0, 166, 90,.8)",
borderColor: "rgba(0, 166, 90,.8)",
pointBorderColor: "rgba(0, 166, 90,.8)",
pointRadius: 1,
pointHoverRadius: 5,
data: [],
pointHitRadius: 5
},
options: {
tooltips: {
enabled: true,
mode: "x-axis",
callbacks: {
title: function(tooltipItem) {
var label = tooltipItem[0].xLabel;
var time = new Date(label);
var from_date = time.getFullYear() +
"-" +
padNumber(time.getMonth()+1) +
"-" +
padNumber(time.getDate()) +
" " +
padNumber(time.getHours()) +
":" +
padNumber(time.getMinutes()) +
":" +
padNumber(time.getSeconds());
time = new Date(time.valueOf() + 1000 * interval);
var until_date = time.getFullYear() +
"-" +
padNumber(time.getMonth()+1) +
"-" +
padNumber(time.getDate()) +
" " +
padNumber(time.getHours()) +
":" +
padNumber(time.getMinutes()) +
":" +
padNumber(time.getSeconds());
return "Queries from " + from_date + " to " + until_date;
},
label: function(tooltipItems, data) {
if(tooltipItems.datasetIndex === 1)
{
var percentage = 0.0;
var total = parseInt(data.datasets[0].data[tooltipItems.index]);
var blocked = parseInt(data.datasets[1].data[tooltipItems.index]);
if(total > 0)
{
percentage = 100.0*blocked/total;
}
return data.datasets[tooltipItems.datasetIndex].label + ": " + tooltipItems.yLabel + " (" + percentage.toFixed(1) + "%)";
}
return data.datasets[tooltipItems.datasetIndex].label + ": " + tooltipItems.yLabel;
}
}
},
legend: {
display: false
},
scales: {
xAxes: [{
type: "time",
stacked: true,
time: {
unit: "hour",
displayFormats: {
"minute": "HH:mm",
"hour": "HH:mm",
"day": "MMM DD",
"week": "MMM DD",
"month": "MMM",
"quarter": "MMM",
"year": "YYYY MMM"
}
}
}],
yAxes: [{
stacked: true,
ticks: {
beginAtZero: true
}
}]
},
maintainAspectRatio: false
{
label: "Blocked DNS Queries",
fill: true,
backgroundColor: "rgba(0,192,239,1)",
borderColor: "rgba(0,192,239,1)",
pointBorderColor: "rgba(0,192,239,1)",
pointRadius: 1,
pointHoverRadius: 5,
data: [],
pointHitRadius: 5
}
});
]
},
options: {
tooltips: {
enabled: true,
mode: "x-axis",
callbacks: {
title: function(tooltipItem) {
var label = tooltipItem[0].xLabel;
var time = new Date(label);
var from_date =
time.getFullYear() +
"-" +
padNumber(time.getMonth() + 1) +
"-" +
padNumber(time.getDate()) +
" " +
padNumber(time.getHours()) +
":" +
padNumber(time.getMinutes()) +
":" +
padNumber(time.getSeconds());
time = new Date(time.valueOf() + 1000 * interval);
var until_date =
time.getFullYear() +
"-" +
padNumber(time.getMonth() + 1) +
"-" +
padNumber(time.getDate()) +
" " +
padNumber(time.getHours()) +
":" +
padNumber(time.getMinutes()) +
":" +
padNumber(time.getSeconds());
return "Queries from " + from_date + " to " + until_date;
},
label: function(tooltipItems, data) {
if (tooltipItems.datasetIndex === 1) {
var percentage = 0.0;
var total = parseInt(data.datasets[0].data[tooltipItems.index]);
var blocked = parseInt(data.datasets[1].data[tooltipItems.index]);
if (total > 0) {
percentage = (100.0 * blocked) / total;
}
return (
data.datasets[tooltipItems.datasetIndex].label +
": " +
tooltipItems.yLabel +
" (" +
percentage.toFixed(1) +
"%)"
);
}
return data.datasets[tooltipItems.datasetIndex].label + ": " + tooltipItems.yLabel;
}
}
},
legend: {
display: false
},
scales: {
xAxes: [
{
type: "time",
stacked: true,
time: {
unit: "hour",
displayFormats: {
minute: "HH:mm",
hour: "HH:mm",
day: "MMM DD",
week: "MMM DD",
month: "MMM",
quarter: "MMM",
year: "YYYY MMM"
}
}
}
],
yAxes: [
{
stacked: true,
ticks: {
beginAtZero: true
}
}
]
},
maintainAspectRatio: false
}
});
});
$("#querytime").on("apply.daterangepicker", function(ev, picker) {
$(this).val(picker.startDate.format(dateformat) + " to " + picker.endDate.format(dateformat));
$("#queries-over-time").show();
updateQueriesOverTime();
$(this).val(picker.startDate.format(dateformat) + " to " + picker.endDate.format(dateformat));
$("#queries-over-time").show();
updateQueriesOverTime();
});
$("#queryOverTimeChart").click(function(evt){
var activePoints = timeLineChart.getElementAtEvent(evt);
if(activePoints.length > 0)
{
//get the internal index in the chart
var clickedElementindex = activePoints[0]._index;
$("#queryOverTimeChart").click(function(evt) {
var activePoints = timeLineChart.getElementAtEvent(evt);
if (activePoints.length > 0) {
//get the internal index in the chart
var clickedElementindex = activePoints[0]._index;
//get specific label by index
var label = timeLineChart.data.labels[clickedElementindex];
//get specific label by index
var label = timeLineChart.data.labels[clickedElementindex];
//get value by index
var from = label/1000;
var until = label/1000 + 600;
window.location.href = "db_queries.php?from="+from+"&until="+until;
}
return false;
//get value by index
var from = label / 1000;
var until = label / 1000 + 600;
window.location.href = "db_queries.php?from=" + from + "&until=" + until;
}
return false;
});
+189 -136
View File
@@ -1,45 +1,75 @@
/* 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. */
* (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. */
/* global moment:false */
var start__ = moment().subtract(6, "days");
var from = moment(start__).utc().valueOf()/1000;
var from =
moment(start__)
.utc()
.valueOf() / 1000;
var end__ = moment();
var until = moment(end__).utc().valueOf()/1000;
var until =
moment(end__)
.utc()
.valueOf() / 1000;
var timeoutWarning = $("#timeoutWarning");
var listsStillLoading = 0;
var dateformat = "MMMM Do YYYY, HH:mm";
$(function () {
$("#querytime").daterangepicker(
$(function() {
$("#querytime").daterangepicker(
{
timePicker: true, timePickerIncrement: 15,
timePicker: true,
timePickerIncrement: 15,
locale: { format: dateformat },
startDate: start__, endDate: end__,
startDate: start__,
endDate: end__,
ranges: {
"Today": [moment().startOf("day"), moment()],
"Yesterday": [moment().subtract(1, "days").startOf("day"), moment().subtract(1, "days").endOf("day")],
Today: [moment().startOf("day"), moment()],
Yesterday: [
moment()
.subtract(1, "days")
.startOf("day"),
moment()
.subtract(1, "days")
.endOf("day")
],
"Last 7 Days": [moment().subtract(6, "days"), moment()],
"Last 30 Days": [moment().subtract(29, "days"), moment()],
"This Month": [moment().startOf("month"), moment()],
"Last Month": [moment().subtract(1, "month").startOf("month"), moment().subtract(1, "month").endOf("month")],
"Last Month": [
moment()
.subtract(1, "month")
.startOf("month"),
moment()
.subtract(1, "month")
.endOf("month")
],
"This Year": [moment().startOf("year"), moment()],
"All Time": [moment(0), moment()]
},
"opens": "center", "showDropdowns": true,
"autoUpdateInput": false
opens: "center",
showDropdowns: true,
autoUpdateInput: false
},
function (startt, endt) {
from = moment(startt).utc().valueOf()/1000;
until = moment(endt).utc().valueOf()/1000;
});
function(startt, endt) {
from =
moment(startt)
.utc()
.valueOf() / 1000;
until =
moment(endt)
.utc()
.valueOf() / 1000;
}
);
});
// Credit: http://stackoverflow.com/questions/1787322/htmlspecialchars-equivalent-in-javascript/4835406#4835406
@@ -48,151 +78,174 @@ function escapeHtml(text) {
"&": "&amp;",
"<": "&lt;",
">": "&gt;",
"\"": "&quot;",
'"': "&quot;",
"'": "&#039;"
};
return text.replace(/[&<>"']/g, function(m) { return map[m]; });
return text.replace(/[&<>"']/g, function(m) {
return map[m];
});
}
function updateTopClientsChart() {
$("#client-frequency .overlay").show();
$.getJSON("api_db.php?topClients&from="+from+"&until="+until, function(data) {
$("#client-frequency .overlay").show();
$.getJSON("api_db.php?topClients&from=" + from + "&until=" + until, function(data) {
// Clear tables before filling them with data
$("#client-frequency td")
.parent()
.remove();
var clienttable = $("#client-frequency").find("tbody:last");
var client, percentage, clientname;
var sum = 0;
for (client in data.top_sources) {
if (Object.prototype.hasOwnProperty.call(data.top_sources, client)) {
sum += data.top_sources[client];
}
}
// Clear tables before filling them with data
$("#client-frequency td").parent().remove();
var clienttable = $("#client-frequency").find("tbody:last");
var client, percentage, clientname;
var sum = 0;
for (client in data.top_sources) {
if (Object.prototype.hasOwnProperty.call(data.top_sources, client)){
sum += data.top_sources[client];
}
for (client in data.top_sources) {
if (Object.prototype.hasOwnProperty.call(data.top_sources, client)) {
// Sanitize client
client = escapeHtml(client);
if (escapeHtml(client) !== client) {
// Make a copy with the escaped index if necessary
data.top_sources[escapeHtml(client)] = data.top_sources[client];
}
for (client in data.top_sources) {
if (Object.prototype.hasOwnProperty.call(data.top_sources, client)){
// Sanitize client
client = escapeHtml(client);
if(escapeHtml(client) !== client)
{
// Make a copy with the escaped index if necessary
data.top_sources[escapeHtml(client)] = data.top_sources[client];
}
if(client.indexOf("|") > -1)
{
var idx = client.indexOf("|");
clientname = client.substr(0, idx);
}
else
{
clientname = client;
}
percentage = data.top_sources[client] / sum * 100.0;
clienttable.append("<tr> <td>" + clientname +
"</td> <td>" + data.top_sources[client] + "</td> <td> <div class=\"progress progress-sm\" title=\""+percentage.toFixed(1)+"% of " + sum + "\"> <div class=\"progress-bar progress-bar-blue\" style=\"width: " +
percentage + "%\"></div> </div> </td> </tr> ");
}
if (client.indexOf("|") > -1) {
var idx = client.indexOf("|");
clientname = client.substr(0, idx);
} else {
clientname = client;
}
$("#client-frequency .overlay").hide();
percentage = (data.top_sources[client] / sum) * 100.0;
clienttable.append(
"<tr> <td>" +
clientname +
"</td> <td>" +
data.top_sources[client] +
'</td> <td> <div class="progress progress-sm" title="' +
percentage.toFixed(1) +
"% of " +
sum +
'"> <div class="progress-bar progress-bar-blue" style="width: ' +
percentage +
'%"></div> </div> </td> </tr> '
);
}
}
listsStillLoading--;
if(listsStillLoading === 0)
timeoutWarning.hide();
});
$("#client-frequency .overlay").hide();
listsStillLoading--;
if (listsStillLoading === 0) timeoutWarning.hide();
});
}
function updateTopDomainsChart() {
$("#domain-frequency .overlay").show();
$.getJSON("api_db.php?topDomains&from="+from+"&until="+until, function(data) {
$("#domain-frequency .overlay").show();
$.getJSON("api_db.php?topDomains&from=" + from + "&until=" + until, function(data) {
// Clear tables before filling them with data
$("#domain-frequency td")
.parent()
.remove();
var domaintable = $("#domain-frequency").find("tbody:last");
var domain, percentage;
var sum = 0;
for (domain in data.top_domains) {
if (Object.prototype.hasOwnProperty.call(data.top_domains, domain)) {
sum += data.top_domains[domain];
}
}
// Clear tables before filling them with data
$("#domain-frequency td").parent().remove();
var domaintable = $("#domain-frequency").find("tbody:last");
var domain, percentage;
var sum = 0;
for (domain in data.top_domains) {
if (Object.prototype.hasOwnProperty.call(data.top_domains, domain)){
sum += data.top_domains[domain];
}
for (domain in data.top_domains) {
if (Object.prototype.hasOwnProperty.call(data.top_domains, domain)) {
// Sanitize domain
domain = escapeHtml(domain);
if (escapeHtml(domain) !== domain) {
// Make a copy with the escaped index if necessary
data.top_domains[escapeHtml(domain)] = data.top_domains[domain];
}
for (domain in data.top_domains) {
percentage = (data.top_domains[domain] / sum) * 100.0;
domaintable.append(
"<tr> <td>" +
domain +
"</td> <td>" +
data.top_domains[domain] +
'</td> <td> <div class="progress progress-sm" title="' +
percentage.toFixed(1) +
"% of " +
sum +
'"> <div class="progress-bar progress-bar-blue" style="width: ' +
percentage +
'%"></div> </div> </td> </tr> '
);
}
}
if (Object.prototype.hasOwnProperty.call(data.top_domains, domain)){
// Sanitize domain
domain = escapeHtml(domain);
if(escapeHtml(domain) !== domain)
{
// Make a copy with the escaped index if necessary
data.top_domains[escapeHtml(domain)] = data.top_domains[domain];
}
$("#domain-frequency .overlay").hide();
percentage = data.top_domains[domain] / sum * 100.0;
domaintable.append("<tr> <td>" + domain +
"</td> <td>" + data.top_domains[domain] + "</td> <td> <div class=\"progress progress-sm\" title=\""+percentage.toFixed(1)+"% of " + sum + "\"> <div class=\"progress-bar progress-bar-blue\" style=\"width: " +
percentage + "%\"></div> </div> </td> </tr> ");
}
}
$("#domain-frequency .overlay").hide();
listsStillLoading--;
if(listsStillLoading === 0)
timeoutWarning.hide();
});
listsStillLoading--;
if (listsStillLoading === 0) timeoutWarning.hide();
});
}
function updateTopAdsChart() {
$("#ad-frequency .overlay").show();
$.getJSON("api_db.php?topAds&from="+from+"&until="+until, function(data) {
$("#ad-frequency .overlay").show();
$.getJSON("api_db.php?topAds&from=" + from + "&until=" + until, function(data) {
// Clear tables before filling them with data
$("#ad-frequency td")
.parent()
.remove();
var adtable = $("#ad-frequency").find("tbody:last");
var ad, percentage;
var sum = 0;
for (ad in data.top_ads) {
if (Object.prototype.hasOwnProperty.call(data.top_ads, ad)) {
sum += data.top_ads[ad];
}
}
// Clear tables before filling them with data
$("#ad-frequency td").parent().remove();
var adtable = $("#ad-frequency").find("tbody:last");
var ad, percentage;
var sum = 0;
for (ad in data.top_ads) {
if (Object.prototype.hasOwnProperty.call(data.top_ads, ad)){
sum += data.top_ads[ad];
}
for (ad in data.top_ads) {
if (Object.prototype.hasOwnProperty.call(data.top_ads, ad)) {
// Sanitize ad
ad = escapeHtml(ad);
if (escapeHtml(ad) !== ad) {
// Make a copy with the escaped index if necessary
data.top_ads[escapeHtml(ad)] = data.top_ads[ad];
}
for (ad in data.top_ads) {
percentage = (data.top_ads[ad] / sum) * 100.0;
adtable.append(
"<tr> <td>" +
ad +
"</td> <td>" +
data.top_ads[ad] +
'</td> <td> <div class="progress progress-sm" title="' +
percentage.toFixed(1) +
"% of " +
sum +
'"> <div class="progress-bar progress-bar-blue" style="width: ' +
percentage +
'%"></div> </div> </td> </tr> '
);
}
}
if (Object.prototype.hasOwnProperty.call(data.top_ads, ad)){
// Sanitize ad
ad = escapeHtml(ad);
if(escapeHtml(ad) !== ad)
{
// Make a copy with the escaped index if necessary
data.top_ads[escapeHtml(ad)] = data.top_ads[ad];
}
$("#ad-frequency .overlay").hide();
percentage = data.top_ads[ad] / sum * 100.0;
adtable.append("<tr> <td>" + ad + "</td> <td>" + data.top_ads[ad] + "</td> <td> <div class=\"progress progress-sm\" title=\""+percentage.toFixed(1)+"% of " + sum + "\"> <div class=\"progress-bar progress-bar-blue\" style=\"width: " + percentage + "%\"></div> </div> </td> </tr> ");
}
}
$("#ad-frequency .overlay").hide();
listsStillLoading--;
if(listsStillLoading === 0)
timeoutWarning.hide();
});
listsStillLoading--;
if (listsStillLoading === 0) timeoutWarning.hide();
});
}
$("#querytime").on("apply.daterangepicker", function(ev, picker) {
$(this).val(picker.startDate.format(dateformat) + " to " + picker.endDate.format(dateformat));
timeoutWarning.show();
listsStillLoading = 3;
updateTopClientsChart();
updateTopDomainsChart();
updateTopAdsChart();
$(this).val(picker.startDate.format(dateformat) + " to " + picker.endDate.format(dateformat));
timeoutWarning.show();
listsStillLoading = 3;
updateTopClientsChart();
updateTopDomainsChart();
updateTopAdsChart();
});
+334 -288
View File
@@ -1,16 +1,22 @@
/* 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. */
* (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. */
/* global moment:false */
var start__ = moment().subtract(6, "days");
var from = moment(start__).utc().valueOf()/1000;
var from =
moment(start__)
.utc()
.valueOf() / 1000;
var end__ = moment();
var until = moment(end__).utc().valueOf()/1000;
var until =
moment(end__)
.utc()
.valueOf() / 1000;
var instantquery = false;
var daterange;
@@ -20,324 +26,364 @@ var dateformat = "MMMM Do YYYY, HH:mm";
// Do we want to filter queries?
var GETDict = {};
window.location.search.substr(1).split("&").forEach(function(item) {GETDict[item.split("=")[0]] = item.split("=")[1];});
window.location.search
.substr(1)
.split("&")
.forEach(function(item) {
GETDict[item.split("=")[0]] = item.split("=")[1];
});
if("from" in GETDict && "until" in GETDict)
{
from = parseInt(GETDict.from);
until = parseInt(GETDict.until);
start__ = moment(1000*from);
end__ = moment(1000*until);
instantquery = true;
if ("from" in GETDict && "until" in GETDict) {
from = parseInt(GETDict.from);
until = parseInt(GETDict.until);
start__ = moment(1000 * from);
end__ = moment(1000 * until);
instantquery = true;
}
$(function () {
daterange = $("#querytime").daterangepicker(
$(function() {
daterange = $("#querytime").daterangepicker(
{
timePicker: true, timePickerIncrement: 15,
timePicker: true,
timePickerIncrement: 15,
locale: { format: dateformat },
startDate: start__, endDate: end__,
startDate: start__,
endDate: end__,
ranges: {
"Today": [moment().startOf("day"), moment()],
"Yesterday": [moment().subtract(1, "days").startOf("day"), moment().subtract(1, "days").endOf("day")],
Today: [moment().startOf("day"), moment()],
Yesterday: [
moment()
.subtract(1, "days")
.startOf("day"),
moment()
.subtract(1, "days")
.endOf("day")
],
"Last 7 Days": [moment().subtract(6, "days"), moment()],
"Last 30 Days": [moment().subtract(29, "days"), moment()],
"This Month": [moment().startOf("month"), moment()],
"Last Month": [moment().subtract(1, "month").startOf("month"), moment().subtract(1, "month").endOf("month")],
"Last Month": [
moment()
.subtract(1, "month")
.startOf("month"),
moment()
.subtract(1, "month")
.endOf("month")
],
"This Year": [moment().startOf("year"), moment()],
"All Time": [moment(0), moment()]
},
"opens": "center", "showDropdowns": true,
"autoUpdateInput": false
opens: "center",
showDropdowns: true,
autoUpdateInput: false
},
function (startt, endt) {
from = moment(startt).utc().valueOf()/1000;
until = moment(endt).utc().valueOf()/1000;
});
function(startt, endt) {
from =
moment(startt)
.utc()
.valueOf() / 1000;
until =
moment(endt)
.utc()
.valueOf() / 1000;
}
);
});
var tableApi, statistics;
function add(domain,list) {
var token = $("#token").text();
var alInfo = $("#alInfo");
var alList = $("#alList");
var alDomain = $("#alDomain");
alDomain.html(domain);
var alSuccess = $("#alSuccess");
var alFailure = $("#alFailure");
var err = $("#err");
function add(domain, list) {
var token = $("#token").text();
var alInfo = $("#alInfo");
var alList = $("#alList");
var alDomain = $("#alDomain");
alDomain.html(domain);
var alSuccess = $("#alSuccess");
var alFailure = $("#alFailure");
var err = $("#err");
if(list === "white")
{
alList.html("Whitelist");
}
else
{
alList.html("Blacklist");
}
if (list === "white") {
alList.html("Whitelist");
} else {
alList.html("Blacklist");
}
alInfo.show();
alSuccess.hide();
alFailure.hide();
$.ajax({
url: "scripts/pi-hole/php/add.php",
method: "post",
data: {"domain":domain, "list":list, "token":token},
success: function(response) {
if (response.indexOf("not a valid argument") >= 0 || response.indexOf("is not a valid domain") >= 0)
{
alFailure.show();
err.html(response);
alFailure.delay(4000).fadeOut(2000, function() { alFailure.hide(); });
}
else
{
alSuccess.show();
alSuccess.delay(1000).fadeOut(2000, function() { alSuccess.hide(); });
}
alInfo.delay(1000).fadeOut(2000, function() {
alInfo.hide();
alList.html("");
alDomain.html("");
});
},
error: function() {
alFailure.show();
err.html("");
alFailure.delay(1000).fadeOut(2000, function() {
alFailure.hide();
});
alInfo.delay(1000).fadeOut(2000, function() {
alInfo.hide();
alList.html("");
alDomain.html("");
});
}
});
}
function handleAjaxError( xhr, textStatus ) {
if ( textStatus === "timeout" )
{
alert( "The server took too long to send the data." );
alInfo.show();
alSuccess.hide();
alFailure.hide();
$.ajax({
url: "scripts/pi-hole/php/add.php",
method: "post",
data: { domain: domain, list: list, token: token },
success: function(response) {
if (
response.indexOf("not a valid argument") >= 0 ||
response.indexOf("is not a valid domain") >= 0
) {
alFailure.show();
err.html(response);
alFailure.delay(4000).fadeOut(2000, function() {
alFailure.hide();
});
} else {
alSuccess.show();
alSuccess.delay(1000).fadeOut(2000, function() {
alSuccess.hide();
});
}
alInfo.delay(1000).fadeOut(2000, function() {
alInfo.hide();
alList.html("");
alDomain.html("");
});
},
error: function() {
alFailure.show();
err.html("");
alFailure.delay(1000).fadeOut(2000, function() {
alFailure.hide();
});
alInfo.delay(1000).fadeOut(2000, function() {
alInfo.hide();
alList.html("");
alDomain.html("");
});
}
else if(xhr.responseText.indexOf("Connection refused") >= 0)
{
alert( "An error occurred while loading the data: Connection refused. Is FTL running?" );
}
else
{
alert( "An unknown error occurred while loading the data.\n"+xhr.responseText );
}
$("#all-queries_processing").hide();
tableApi.clear();
tableApi.draw();
});
}
function getQueryTypes()
{
var queryType = [];
if($("#type_gravity").prop("checked"))
{
queryType.push(1);
}
if($("#type_forwarded").prop("checked"))
{
queryType.push(2);
}
if($("#type_cached").prop("checked"))
{
queryType.push(3);
}
if($("#type_regex").prop("checked"))
{
queryType.push(4);
}
if($("#type_blacklist").prop("checked"))
{
queryType.push(5);
}
if($("#type_external").prop("checked"))
{
// Multiple IDs correspond to this status
// We request queries with all of them
queryType.push([6,7,8]);
}
return queryType.join(",");
function handleAjaxError(xhr, textStatus) {
if (textStatus === "timeout") {
alert("The server took too long to send the data.");
} else if (xhr.responseText.indexOf("Connection refused") >= 0) {
alert("An error occurred while loading the data: Connection refused. Is FTL running?");
} else {
alert("An unknown error occurred while loading the data.\n" + xhr.responseText);
}
$("#all-queries_processing").hide();
tableApi.clear();
tableApi.draw();
}
var reloadCallback = function()
{
timeoutWarning.hide();
statistics = [0,0,0,0];
var data = tableApi.rows().data();
for (var i = 0; i < data.length; i++) {
statistics[0]++;
if(data[i][4] === 1)
{
statistics[2]++;
}
else if(data[i][4] === 3)
{
statistics[1]++;
}
else if(data[i][4] === 4)
{
statistics[3]++;
}
}
$("h3#dns_queries").text(statistics[0].toLocaleString());
$("h3#ads_blocked_exact").text(statistics[2].toLocaleString());
$("h3#ads_wildcard_blocked").text(statistics[3].toLocaleString());
function getQueryTypes() {
var queryType = [];
if ($("#type_gravity").prop("checked")) {
queryType.push(1);
}
var percent = 0.0;
if(statistics[2] + statistics[3] > 0)
{
percent = 100.0*(statistics[2] + statistics[3]) / statistics[0];
if ($("#type_forwarded").prop("checked")) {
queryType.push(2);
}
if ($("#type_cached").prop("checked")) {
queryType.push(3);
}
if ($("#type_regex").prop("checked")) {
queryType.push(4);
}
if ($("#type_blacklist").prop("checked")) {
queryType.push(5);
}
if ($("#type_external").prop("checked")) {
// Multiple IDs correspond to this status
// We request queries with all of them
queryType.push([6, 7, 8]);
}
return queryType.join(",");
}
var reloadCallback = function() {
timeoutWarning.hide();
statistics = [0, 0, 0, 0];
var data = tableApi.rows().data();
for (var i = 0; i < data.length; i++) {
statistics[0]++;
if (data[i][4] === 1) {
statistics[2]++;
} else if (data[i][4] === 3) {
statistics[1]++;
} else if (data[i][4] === 4) {
statistics[3]++;
}
$("h3#ads_percentage_today").text(parseFloat(percent).toFixed(1).toLocaleString()+" %");
}
$("h3#dns_queries").text(statistics[0].toLocaleString());
$("h3#ads_blocked_exact").text(statistics[2].toLocaleString());
$("h3#ads_wildcard_blocked").text(statistics[3].toLocaleString());
var percent = 0.0;
if (statistics[2] + statistics[3] > 0) {
percent = (100.0 * (statistics[2] + statistics[3])) / statistics[0];
}
$("h3#ads_percentage_today").text(
parseFloat(percent)
.toFixed(1)
.toLocaleString() + " %"
);
};
function refreshTableData() {
timeoutWarning.show();
var APIstring = "api_db.php?getAllQueries&from="+from+"&until="+until;
// Check if query type filtering is enabled
var queryType = getQueryTypes();
if(queryType !== "1,2,3,4,5,6")
{
APIstring += "&types="+queryType;
}
statistics = [0,0,0];
tableApi.ajax.url(APIstring).load(reloadCallback);
timeoutWarning.show();
var APIstring = "api_db.php?getAllQueries&from=" + from + "&until=" + until;
// Check if query type filtering is enabled
var queryType = getQueryTypes();
if (queryType !== "1,2,3,4,5,6") {
APIstring += "&types=" + queryType;
}
statistics = [0, 0, 0];
tableApi.ajax.url(APIstring).load(reloadCallback);
}
$(document).ready(function() {
var APIstring;
var APIstring;
if(instantquery)
{
APIstring = "api_db.php?getAllQueries&from="+from+"&until="+until;
}
else
{
APIstring = "api_db.php?getAllQueries=empty";
}
// Check if query type filtering is enabled
var queryType = getQueryTypes();
if(queryType !== 63) // 63 (0b00111111) = all possible query types are selected
{
APIstring += "&types="+queryType;
}
if (instantquery) {
APIstring = "api_db.php?getAllQueries&from=" + from + "&until=" + until;
} else {
APIstring = "api_db.php?getAllQueries=empty";
}
tableApi = $("#all-queries").DataTable( {
"rowCallback": function( row, data ){
var fieldtext, buttontext, color;
switch (data[4])
{
case 1:
color = "red";
fieldtext = "Blocked (gravity)";
buttontext = "<button type=\"button\" class=\"btn btn-default btn-sm text-green\"><i class=\"fas fa-check\"></i> Whitelist</button>";
break;
case 2:
color = "green";
fieldtext = "OK <br class='hidden-lg'>(forwarded)";
buttontext = "<button type=\"button\" class=\"btn btn-default btn-sm text-red\"><i class=\"fa fa-ban\"></i> Blacklist</button>";
break;
case 3:
color = "green";
fieldtext = "OK <br class='hidden-lg'>(cached)";
buttontext = "<button type=\"button\" class=\"btn btn-default btn-sm text-red\"><i class=\"fa fa-ban\"></i> Blacklist</button>";
break;
case 4:
color = "red";
fieldtext = "Blocked <br class='hidden-lg'>(regex/wildcard)";
buttontext = "<button type=\"button\" class=\"btn btn-default btn-sm text-green\"><i class=\"fas fa-check\"></i> Whitelist</button>";
break;
case 5:
color = "red";
fieldtext = "Blocked <br class='hidden-lg'>(blacklist)";
buttontext = "<button type=\"button\" class=\"btn btn-default btn-sm text-green\"><i class=\"fas fa-check\"></i> Whitelist</button>";
break;
case 6:
color = "red";
fieldtext = "Blocked <br class='hidden-lg'>(external, IP)";
buttontext = "";
break;
case 7:
color = "red";
fieldtext = "Blocked <br class='hidden-lg'>(external, NULL)";
buttontext = "";
break;
case 8:
color = "red";
fieldtext = "Blocked <br class='hidden-lg'>(external, NXRA)";
buttontext = "";
break;
default:
color = "black";
fieldtext = "Unknown";
buttontext = "";
}
// Check if query type filtering is enabled
var queryType = getQueryTypes();
if (queryType !== 63) {
// 63 (0b00111111) = all possible query types are selected
APIstring += "&types=" + queryType;
}
$(row).css("color", color);
$("td:eq(4)", row).html(fieldtext);
$("td:eq(5)", row).html(buttontext);
},
dom: "<'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>>",
"ajax": {
"url": APIstring,
"error": handleAjaxError,
"dataSrc": function(data){
var dataIndex = 0;
return data.data.map(function(x){
x[0] = x[0] * 1e6 + (dataIndex++);
return x;
});
}
},
"autoWidth" : false,
"processing": true,
"deferRender": true,
"order" : [[0, "desc"]],
"columns": [
{ "width" : "15%", "render": function (data, type) { if(type === "display"){return moment.unix(Math.floor(data/1e6)).format("Y-MM-DD [<br class='hidden-lg'>]HH:mm:ss z");}return data; }},
{ "width" : "10%" },
{ "width" : "40%" },
{ "width" : "20%" },
{ "width" : "10%" },
{ "width" : "5%" }
],
"lengthMenu": [[10, 25, 50, 100, -1], [10, 25, 50, 100, "All"]],
"columnDefs": [ {
"targets": -1,
"data": null,
"defaultContent": ""
} ],
"initComplete": reloadCallback
});
$("#all-queries tbody").on( "click", "button", function () {
var data = tableApi.row( $(this).parents("tr") ).data();
if (data[4] === 1 || data[4] === 4 || data[5] === 5)
{
add(data[2],"white");
tableApi = $("#all-queries").DataTable({
rowCallback: function(row, data) {
var fieldtext, buttontext, color;
switch (data[4]) {
case 1:
color = "red";
fieldtext = "Blocked (gravity)";
buttontext =
'<button type="button" class="btn btn-default btn-sm text-green"><i class="fas fa-check"></i> Whitelist</button>';
break;
case 2:
color = "green";
fieldtext = "OK <br class='hidden-lg'>(forwarded)";
buttontext =
'<button type="button" class="btn btn-default btn-sm text-red"><i class="fa fa-ban"></i> Blacklist</button>';
break;
case 3:
color = "green";
fieldtext = "OK <br class='hidden-lg'>(cached)";
buttontext =
'<button type="button" class="btn btn-default btn-sm text-red"><i class="fa fa-ban"></i> Blacklist</button>';
break;
case 4:
color = "red";
fieldtext = "Blocked <br class='hidden-lg'>(regex/wildcard)";
buttontext =
'<button type="button" class="btn btn-default btn-sm text-green"><i class="fas fa-check"></i> Whitelist</button>';
break;
case 5:
color = "red";
fieldtext = "Blocked <br class='hidden-lg'>(blacklist)";
buttontext =
'<button type="button" class="btn btn-default btn-sm text-green"><i class="fas fa-check"></i> Whitelist</button>';
break;
case 6:
color = "red";
fieldtext = "Blocked <br class='hidden-lg'>(external, IP)";
buttontext = "";
break;
case 7:
color = "red";
fieldtext = "Blocked <br class='hidden-lg'>(external, NULL)";
buttontext = "";
break;
case 8:
color = "red";
fieldtext = "Blocked <br class='hidden-lg'>(external, NXRA)";
buttontext = "";
break;
default:
color = "black";
fieldtext = "Unknown";
buttontext = "";
}
$(row).css("color", color);
$("td:eq(4)", row).html(fieldtext);
$("td:eq(5)", row).html(buttontext);
},
dom:
"<'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>>",
ajax: {
url: APIstring,
error: handleAjaxError,
dataSrc: function(data) {
var dataIndex = 0;
return data.data.map(function(x) {
x[0] = x[0] * 1e6 + dataIndex++;
return x;
});
}
},
autoWidth: false,
processing: true,
deferRender: true,
order: [[0, "desc"]],
columns: [
{
width: "15%",
render: function(data, type) {
if (type === "display") {
return moment
.unix(Math.floor(data / 1e6))
.format("Y-MM-DD [<br class='hidden-lg'>]HH:mm:ss z");
}
return data;
}
else
{
add(data[2],"black");
}
} );
if(instantquery)
{
daterange.val(start__.format(dateformat) + " - " + end__.format(dateformat));
},
{ width: "10%" },
{ width: "40%" },
{ width: "20%" },
{ width: "10%" },
{ width: "5%" }
],
lengthMenu: [
[10, 25, 50, 100, -1],
[10, 25, 50, 100, "All"]
],
columnDefs: [
{
targets: -1,
data: null,
defaultContent: ""
}
],
initComplete: reloadCallback
});
$("#all-queries tbody").on("click", "button", function() {
var data = tableApi.row($(this).parents("tr")).data();
if (data[4] === 1 || data[4] === 4 || data[5] === 5) {
add(data[2], "white");
} else {
add(data[2], "black");
}
} );
});
if (instantquery) {
daterange.val(start__.format(dateformat) + " - " + end__.format(dateformat));
}
});
$("#querytime").on("apply.daterangepicker", function(ev, picker) {
$(this).val(picker.startDate.format(dateformat) + " to " + picker.endDate.format(dateformat));
refreshTableData();
$(this).val(picker.startDate.format(dateformat) + " to " + picker.endDate.format(dateformat));
refreshTableData();
});
+57 -54
View File
@@ -1,74 +1,77 @@
/* 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. */
* (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. */
/* global ActiveXObject: false */
// Credit: http://stackoverflow.com/a/10642418/2087442
function httpGet(ta,theUrl)
{
var xmlhttp;
if (window.XMLHttpRequest)
{
function httpGet(ta, theUrl) {
var xmlhttp;
if (window.XMLHttpRequest) {
// code for IE7+
xmlhttp = new XMLHttpRequest();
}
else
{
xmlhttp = new XMLHttpRequest();
} else {
// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
ta.show();
ta.empty();
ta.append(xmlhttp.responseText);
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState === 4 && xmlhttp.status === 200)
{
ta.show();
ta.empty();
ta.append(xmlhttp.responseText);
}
};
xmlhttp.open("GET", theUrl, false);
xmlhttp.send();
};
xmlhttp.open("GET", theUrl, false);
xmlhttp.send();
}
function eventsource() {
var ta = $("#output");
var upload = $( "#upload" );
var checked = "";
var token = encodeURIComponent($("#token").text());
var ta = $("#output");
var upload = $("#upload");
var checked = "";
var token = encodeURIComponent($("#token").text());
if(upload.prop("checked"))
{
checked = "upload";
}
if (upload.prop("checked")) {
checked = "upload";
}
// IE does not support EventSource - load whole content at once
if (typeof EventSource !== "function") {
httpGet(ta,"scripts/pi-hole/php/debug.php?IE&token="+token+"&"+checked);
return;
}
// IE does not support EventSource - load whole content at once
if (typeof EventSource !== "function") {
httpGet(ta, "scripts/pi-hole/php/debug.php?IE&token=" + token + "&" + checked);
return;
}
var source = new EventSource("scripts/pi-hole/php/debug.php?&token="+token+"&"+checked);
var source = new EventSource("scripts/pi-hole/php/debug.php?&token=" + token + "&" + checked);
// Reset and show field
ta.empty();
ta.show();
// Reset and show field
ta.empty();
ta.show();
source.addEventListener("message", function(e) {
ta.append(e.data);
}, false);
source.addEventListener(
"message",
function(e) {
ta.append(e.data);
},
false
);
// Will be called when script has finished
source.addEventListener("error", function() {
source.close();
}, false);
// Will be called when script has finished
source.addEventListener(
"error",
function() {
source.close();
},
false
);
}
$("#debugBtn").on("click", function(){
$("#debugBtn").attr("disabled", true);
$("#upload").attr("disabled", true);
eventsource();
$("#debugBtn").on("click", function() {
$("#debugBtn").attr("disabled", true);
$("#upload").attr("disabled", true);
eventsource();
});
+140 -154
View File
@@ -1,135 +1,128 @@
/* 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. */
* (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. */
//The following functions allow us to display time until pi-hole is enabled after disabling.
//Works between all pages
function secondsTimeSpanToHMS(s) {
var h = Math.floor(s/3600); //Get whole hours
s -= h*3600;
var m = Math.floor(s/60); //Get remaining minutes
s -= m*60;
return h+":"+(m < 10 ? "0"+m : m)+":"+(s < 10 ? "0"+s : s); //zero padding on minutes and seconds
var h = Math.floor(s / 3600); //Get whole hours
s -= h * 3600;
var m = Math.floor(s / 60); //Get remaining minutes
s -= m * 60;
return h + ":" + (m < 10 ? "0" + m : m) + ":" + (s < 10 ? "0" + s : s); //zero padding on minutes and seconds
}
function piholeChanged(action)
{
var status = $("#status");
var ena = $("#pihole-enable");
var dis = $("#pihole-disable");
function piholeChanged(action) {
var status = $("#status");
var ena = $("#pihole-enable");
var dis = $("#pihole-disable");
switch(action) {
case "enabled":
status.html("<i class='fa fa-circle text-green-light'></i> Active");
ena.hide();
dis.show();
dis.removeClass("active");
break;
case "disabled":
status.html("<i class='fa fa-circle text-red'></i> Offline");
ena.show();
dis.hide();
break;
}
switch (action) {
case "enabled":
status.html("<i class='fa fa-circle text-green-light'></i> Active");
ena.hide();
dis.show();
dis.removeClass("active");
break;
case "disabled":
status.html("<i class='fa fa-circle text-red'></i> Offline");
ena.show();
dis.hide();
break;
}
}
function countDown(){
var ena = $("#enableLabel");
var enaT = $("#enableTimer");
var target = new Date(parseInt(enaT.html()));
var seconds = Math.round((target.getTime() - new Date().getTime()) / 1000);
function countDown() {
var ena = $("#enableLabel");
var enaT = $("#enableTimer");
var target = new Date(parseInt(enaT.html()));
var seconds = Math.round((target.getTime() - new Date().getTime()) / 1000);
if(seconds > 0){
setTimeout(countDown,1000);
ena.text("Enable (" + secondsTimeSpanToHMS(seconds) + ")");
}
else
{
ena.text("Enable");
piholeChanged("enabled");
localStorage.removeItem("countDownTarget");
}
if (seconds > 0) {
setTimeout(countDown, 1000);
ena.text("Enable (" + secondsTimeSpanToHMS(seconds) + ")");
} else {
ena.text("Enable");
piholeChanged("enabled");
localStorage.removeItem("countDownTarget");
}
}
function piholeChange(action, duration)
{
var token = encodeURIComponent($("#token").text());
var enaT = $("#enableTimer");
var btnStatus;
function piholeChange(action, duration) {
var token = encodeURIComponent($("#token").text());
var enaT = $("#enableTimer");
var btnStatus;
switch(action) {
case "enable":
btnStatus = $("#flip-status-enable");
btnStatus.html("<i class='fa fa-spinner'> </i>");
$.getJSON("api.php?enable&token=" + token, function(data) {
if(data.status === "enabled") {
btnStatus.html("");
piholeChanged("enabled");
}
});
break;
switch (action) {
case "enable":
btnStatus = $("#flip-status-enable");
btnStatus.html("<i class='fa fa-spinner'> </i>");
$.getJSON("api.php?enable&token=" + token, function(data) {
if (data.status === "enabled") {
btnStatus.html("");
piholeChanged("enabled");
}
});
break;
case "disable":
btnStatus = $("#flip-status-disable");
btnStatus.html("<i class='fa fa-spinner'> </i>");
$.getJSON("api.php?disable=" + duration + "&token=" + token, function(data) {
if(data.status === "disabled") {
btnStatus.html("");
piholeChanged("disabled");
if(duration > 0)
{
enaT.html(new Date().getTime() + duration * 1000);
setTimeout(countDown,100);
}
}
});
break;
}
case "disable":
btnStatus = $("#flip-status-disable");
btnStatus.html("<i class='fa fa-spinner'> </i>");
$.getJSON("api.php?disable=" + duration + "&token=" + token, function(data) {
if (data.status === "disabled") {
btnStatus.html("");
piholeChanged("disabled");
if (duration > 0) {
enaT.html(new Date().getTime() + duration * 1000);
setTimeout(countDown, 100);
}
}
});
break;
}
}
$( document ).ready(function() {
var enaT = $("#enableTimer");
var target = new Date(parseInt(enaT.html()));
var seconds = Math.round((target.getTime() - new Date().getTime()) / 1000);
if (seconds > 0)
{
setTimeout(countDown,100);
}
$(document).ready(function() {
var enaT = $("#enableTimer");
var target = new Date(parseInt(enaT.html()));
var seconds = Math.round((target.getTime() - new Date().getTime()) / 1000);
if (seconds > 0) {
setTimeout(countDown, 100);
}
});
// Handle Enable/Disable
$("#pihole-enable").on("click", function(e){
e.preventDefault();
localStorage.removeItem("countDownTarget");
piholeChange("enable","");
$("#pihole-enable").on("click", function(e) {
e.preventDefault();
localStorage.removeItem("countDownTarget");
piholeChange("enable", "");
});
$("#pihole-disable-permanently").on("click", function(e){
e.preventDefault();
piholeChange("disable","0");
$("#pihole-disable-permanently").on("click", function(e) {
e.preventDefault();
piholeChange("disable", "0");
});
$("#pihole-disable-10s").on("click", function(e){
e.preventDefault();
piholeChange("disable","10");
$("#pihole-disable-10s").on("click", function(e) {
e.preventDefault();
piholeChange("disable", "10");
});
$("#pihole-disable-30s").on("click", function(e){
e.preventDefault();
piholeChange("disable","30");
$("#pihole-disable-30s").on("click", function(e) {
e.preventDefault();
piholeChange("disable", "30");
});
$("#pihole-disable-5m").on("click", function(e){
e.preventDefault();
piholeChange("disable","300");
$("#pihole-disable-5m").on("click", function(e) {
e.preventDefault();
piholeChange("disable", "300");
});
$("#pihole-disable-custom").on("click", function(e){
e.preventDefault();
var custVal = $("#customTimeout").val();
custVal = $("#btnMins").hasClass("active") ? custVal * 60 : custVal;
piholeChange("disable",custVal);
$("#pihole-disable-custom").on("click", function(e) {
e.preventDefault();
var custVal = $("#customTimeout").val();
custVal = $("#btnMins").hasClass("active") ? custVal * 60 : custVal;
piholeChange("disable", custVal);
});
// Session timer
@@ -137,70 +130,63 @@ var sessionTimerCounter = document.getElementById("sessiontimercounter");
var sessionvalidity = parseInt(sessionTimerCounter.textContent);
var start = new Date();
function updateSessionTimer()
{
start = new Date();
start.setSeconds(start.getSeconds() + sessionvalidity);
function updateSessionTimer() {
start = new Date();
start.setSeconds(start.getSeconds() + sessionvalidity);
}
if(sessionvalidity > 0)
{
// setSeconds will correctly handle wrap-around cases
updateSessionTimer();
if (sessionvalidity > 0) {
// setSeconds will correctly handle wrap-around cases
updateSessionTimer();
setInterval(function() {
var current = new Date();
var totalseconds = (start - current) / 1000;
var minutes = Math.floor(totalseconds / 60);
if(minutes < 10){ minutes = "0" + minutes; }
setInterval(function() {
var current = new Date();
var totalseconds = (start - current) / 1000;
var minutes = Math.floor(totalseconds / 60);
if (minutes < 10) {
minutes = "0" + minutes;
}
var seconds = Math.floor(totalseconds % 60);
if(seconds < 10){ seconds = "0" + seconds; }
var seconds = Math.floor(totalseconds % 60);
if (seconds < 10) {
seconds = "0" + seconds;
}
if(totalseconds > 0)
{
sessionTimerCounter.textContent = minutes + ":" + seconds;
}
else
{
sessionTimerCounter.textContent = "-- : --";
}
}, 1000);
}
else
{
document.getElementById("sessiontimer").style.display = "none";
if (totalseconds > 0) {
sessionTimerCounter.textContent = minutes + ":" + seconds;
} else {
sessionTimerCounter.textContent = "-- : --";
}
}, 1000);
} else {
document.getElementById("sessiontimer").style.display = "none";
}
// 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();
}
if ((e.keyCode === 10 || e.keyCode === 13) && e.ctrlKey && $("#loginpw").is(":focus")) {
$("#loginform").attr("action", "settings.php");
$("#loginform").submit();
}
});
function testCookies()
{
if (navigator.cookieEnabled)
{
return true;
}
function testCookies() {
if (navigator.cookieEnabled) {
return true;
}
// set and read cookie
document.cookie = "cookietest=1";
var ret = document.cookie.indexOf("cookietest=") !== -1;
// 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";
// delete cookie
document.cookie = "cookietest=1; expires=Thu, 01-Jan-1970 00:00:01 GMT";
return ret;
return ret;
}
$(function() {
if(!testCookies() && $("#cookieInfo").length)
{
$("#cookieInfo").show();
}
if (!testCookies() && $("#cookieInfo").length) {
$("#cookieInfo").show();
}
});
+64 -57
View File
@@ -1,73 +1,80 @@
/* 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. */
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
* Network-wide ad blocking via your own hardware.
*
* This file is copyright under the latest version of the EUPL.
* Please see LICENSE file for your rights under this license. */
function eventsource() {
var alInfo = $("#alInfo");
var alSuccess = $("#alSuccess");
var ta = $("#output");
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("");
// IE does not support EventSource - exit early
if (typeof EventSource !== "function") {
ta.show();
alInfo.show();
alSuccess.hide();
ta.html("Updating lists of ad-serving domains is not supported with this browser!");
return;
}
source.addEventListener("message", function(e) {
if(e.data.indexOf("Pi-hole blocking is") !== -1)
{
alSuccess.show();
}
var source = new EventSource("scripts/pi-hole/php/gravity.sh.php");
// Detect ${OVER}
if(e.data.indexOf("<------") !== -1)
{
ta.text(ta.text().substring(0, ta.text().lastIndexOf("\n")) + "\n");
var new_string = e.data.replace("<------", "");
ta.append(new_string);
}
else
{
ta.append(e.data);
}
ta.html("");
ta.show();
alInfo.show();
alSuccess.hide();
}, false);
source.addEventListener(
"message",
function(e) {
if (e.data.indexOf("Pi-hole blocking is") !== -1) {
alSuccess.show();
}
// Will be called when script has finished
source.addEventListener("error", function() {
alInfo.delay(1000).fadeOut(2000, function() { alInfo.hide(); });
source.close();
$("#gravityBtn").removeAttr("disabled");
}, false);
// Detect ${OVER}
if (e.data.indexOf("<------") !== -1) {
ta.text(ta.text().substring(0, ta.text().lastIndexOf("\n")) + "\n");
var new_string = e.data.replace("<------", "");
ta.append(new_string);
} else {
ta.append(e.data);
}
},
false
);
// Will be called when script has finished
source.addEventListener(
"error",
function() {
alInfo.delay(1000).fadeOut(2000, function() {
alInfo.hide();
});
source.close();
$("#gravityBtn").removeAttr("disabled");
},
false
);
}
$("#gravityBtn").on("click", function(){
$("#gravityBtn").attr("disabled", true);
eventsource();
$("#gravityBtn").on("click", function() {
$("#gravityBtn").attr("disabled", true);
eventsource();
});
// Handle hiding of alerts
$(function(){
$("[data-hide]").on("click", function(){
$(this).closest("." + $(this).attr("data-hide")).hide();
});
$(function() {
$("[data-hide]").on("click", function() {
$(this)
.closest("." + $(this).attr("data-hide"))
.hide();
});
// Do we want to start updating immediately?
// gravity.php?go
var searchString = window.location.search.substring(1);
if(searchString.indexOf("go") !== -1)
{
$("#gravityBtn").attr("disabled", true);
eventsource();
}
// Do we want to start updating immediately?
// gravity.php?go
var searchString = window.location.search.substring(1);
if (searchString.indexOf("go") !== -1) {
$("#gravityBtn").attr("disabled", true);
eventsource();
}
});
+16 -49
View File
@@ -35,6 +35,7 @@ function showAlert(type, icon, title, message) {
} else {
$.notify(opts);
}
break;
case "warning":
opts = {
@@ -48,6 +49,7 @@ function showAlert(type, icon, title, message) {
} else {
$.notify(opts);
}
break;
case "error":
opts = {
@@ -61,9 +63,9 @@ function showAlert(type, icon, title, message) {
} else {
$.notify(opts);
}
break;
default:
return;
}
}
@@ -90,10 +92,7 @@ $(document).ready(function() {
$("#select").on("change", function() {
$("#ip-custom").val("");
$("#ip-custom").prop(
"disabled",
$("#select option:selected").val() !== "custom"
);
$("#ip-custom").prop("disabled", $("#select option:selected").val() !== "custom");
});
});
@@ -130,9 +129,7 @@ function initTable() {
var disabled = data.enabled === 0;
$("td:eq(1)", row).html(
'<input type="checkbox" id="status"' +
(disabled ? "" : " checked") +
">"
'<input type="checkbox" id="status"' + (disabled ? "" : " checked") + ">"
);
var status = $("#status", row);
status.bootstrapToggle({
@@ -154,9 +151,7 @@ function initTable() {
comment.on("change", editAdlist);
$("td:eq(3)", row).empty();
$("td:eq(3)", row).append(
'<select id="multiselect" multiple="multiple"></select>'
);
$("td:eq(3)", row).append('<select id="multiselect" multiple="multiple"></select>');
var sel = $("#multiselect", row);
// Add all known groups
for (var i = 0; i < groups.length; i++) {
@@ -164,12 +159,14 @@ function initTable() {
if (!groups[i].enabled) {
extra = " (disabled)";
}
sel.append(
$("<option />")
.val(groups[i].id)
.text(groups[i].name + extra)
);
}
// Select assigned groups
sel.val(data.groups);
// Initialize multiselect
@@ -200,6 +197,7 @@ function initTable() {
if (data === null) {
return null;
}
data = JSON.parse(data);
// Always start on the first page to show most recent queries
data.start = 0;
@@ -249,31 +247,16 @@ function addAdlist() {
},
success: function(response) {
if (response.success) {
showAlert(
"success",
"glyphicon glyphicon-plus",
"Successfully added adlist",
address
);
showAlert("success", "glyphicon glyphicon-plus", "Successfully added adlist", address);
$("#new_address").val("");
$("#new_comment").val("");
table.ajax.reload();
} else {
showAlert(
"error",
"",
"Error while adding new adlist: ",
response.message
);
showAlert("error", "", "Error while adding new adlist: ", response.message);
}
},
error: function(jqXHR, exception) {
showAlert(
"error",
"",
"Error while adding new adlist: ",
jqXHR.responseText
);
showAlert("error", "", "Error while adding new adlist: ", jqXHR.responseText);
console.log(exception);
}
});
@@ -331,7 +314,7 @@ function editAdlist() {
"error",
"",
"Error while " + not_done + " adlist with ID " + id,
+response.message
Number(response.message)
);
}
},
@@ -360,31 +343,15 @@ function deleteAdlist() {
data: { action: "delete_adlist", id: id, token: token },
success: function(response) {
if (response.success) {
showAlert(
"success",
"glyphicon glyphicon-trash",
"Successfully deleted adlist ",
address
);
showAlert("success", "glyphicon glyphicon-trash", "Successfully deleted adlist ", address);
table
.row(tr)
.remove()
.draw(false);
} else
showAlert(
"error",
"",
"Error while deleting adlist with ID " + id,
response.message
);
} else showAlert("error", "", "Error while deleting adlist with ID " + id, response.message);
},
error: function(jqXHR, exception) {
showAlert(
"error",
"",
"Error while deleting adlist with ID " + id,
jqXHR.responseText
);
showAlert("error", "", "Error while deleting adlist with ID " + id, jqXHR.responseText);
console.log(exception);
}
});
+20 -55
View File
@@ -35,6 +35,7 @@ function showAlert(type, icon, title, message) {
} else {
$.notify(opts);
}
break;
case "warning":
opts = {
@@ -48,6 +49,7 @@ function showAlert(type, icon, title, message) {
} else {
$.notify(opts);
}
break;
case "error":
opts = {
@@ -61,9 +63,9 @@ function showAlert(type, icon, title, message) {
} else {
$.notify(opts);
}
break;
default:
return;
}
}
@@ -78,16 +80,19 @@ function reload_client_suggestions() {
if (!data.hasOwnProperty(key)) {
continue;
}
var text = key;
if (data[key].length > 0) {
text += " (" + data[key] + ")";
}
sel.append(
$("<option />")
.val(key)
.text(text)
);
}
sel.append(
$("<option />")
.val("custom")
@@ -118,10 +123,7 @@ $(document).ready(function() {
$("#select").on("change", function() {
$("#ip-custom").val("");
$("#ip-custom").prop(
"disabled",
$("#select option:selected").val() !== "custom"
);
$("#ip-custom").prop("disabled", $("#select option:selected").val() !== "custom");
});
});
@@ -153,18 +155,11 @@ function initTable() {
data.id +
'">';
if (data.name !== null && data.name.length > 0)
ip_name +=
'<br><code id="name" title="' +
tooltip +
'">' +
data.name +
"</code>";
ip_name += '<br><code id="name" title="' + tooltip + '">' + data.name + "</code>";
$("td:eq(0)", row).html(ip_name);
$("td:eq(1)", row).empty();
$("td:eq(1)", row).append(
'<select id="multiselect" multiple="multiple"></select>'
);
$("td:eq(1)", row).append('<select id="multiselect" multiple="multiple"></select>');
var sel = $("#multiselect", row);
// Add all known groups
for (var i = 0; i < groups.length; i++) {
@@ -172,12 +167,14 @@ function initTable() {
if (!groups[i].enabled) {
extra = " (disabled)";
}
sel.append(
$("<option />")
.val(groups[i].id)
.text(groups[i].name + extra)
);
}
// Select assigned groups
sel.val(data.groups);
// Initialize multiselect
@@ -208,6 +205,7 @@ function initTable() {
if (data === null) {
return null;
}
data = JSON.parse(data);
// Always start on the first page to show most recent queries
data.start = 0;
@@ -254,30 +252,15 @@ function addClient() {
data: { action: "add_client", ip: ip, token: token },
success: function(response) {
if (response.success) {
showAlert(
"success",
"glyphicon glyphicon-plus",
"Successfully added client",
ip
);
showAlert("success", "glyphicon glyphicon-plus", "Successfully added client", ip);
reload_client_suggestions();
table.ajax.reload();
} else {
showAlert(
"error",
"",
"Error while adding new client",
response.message
);
showAlert("error", "", "Error while adding new client", response.message);
}
},
error: function(jqXHR, exception) {
showAlert(
"error",
"",
"Error while adding new client",
jqXHR.responseText
);
showAlert("error", "", "Error while adding new client", jqXHR.responseText);
console.log(exception);
}
});
@@ -318,11 +301,7 @@ function editClient() {
ip_name
);
} else {
showAlert(
"error",
"Error while " + not_done + " client with ID " + id,
response.message
);
showAlert("error", "Error while " + not_done + " client with ID " + id, response.message);
}
},
error: function(jqXHR, exception) {
@@ -347,6 +326,7 @@ function deleteClient() {
if (name.length > 0) {
ip_name += " (" + name + ")";
}
showAlert("info", "", "Deleting client...", ip_name);
$.ajax({
url: "scripts/pi-hole/php/groups.php",
@@ -355,33 +335,18 @@ function deleteClient() {
data: { action: "delete_client", id: id, token: token },
success: function(response) {
if (response.success) {
showAlert(
"success",
"glyphicon glyphicon-trash",
"Successfully deleted client ",
ip_name
);
showAlert("success", "glyphicon glyphicon-trash", "Successfully deleted client ", ip_name);
table
.row(tr)
.remove()
.draw(false);
reload_client_suggestions();
} else {
showAlert(
"error",
"",
"Error while deleting client with ID " + id,
response.message
);
showAlert("error", "", "Error while deleting client with ID " + id, response.message);
}
},
error: function(jqXHR, exception) {
showAlert(
"error",
"",
"Error while deleting client with ID " + id,
jqXHR.responseText
);
showAlert("error", "", "Error while deleting client with ID " + id, jqXHR.responseText);
console.log(exception);
}
});
+15 -49
View File
@@ -35,6 +35,7 @@ function showAlert(type, icon, title, message) {
} else {
$.notify(opts);
}
break;
case "warning":
opts = {
@@ -48,6 +49,7 @@ function showAlert(type, icon, title, message) {
} else {
$.notify(opts);
}
break;
case "error":
opts = {
@@ -61,9 +63,9 @@ function showAlert(type, icon, title, message) {
} else {
$.notify(opts);
}
break;
default:
return;
}
}
@@ -90,10 +92,7 @@ $(document).ready(function() {
$("#select").on("change", function() {
$("#ip-custom").val("");
$("#ip-custom").prop(
"disabled",
$("#select option:selected").val() !== "custom"
);
$("#ip-custom").prop("disabled", $("#select option:selected").val() !== "custom");
});
});
@@ -149,9 +148,7 @@ function initTable() {
var disabled = data.enabled === 0;
$("td:eq(2)", row).html(
'<input type="checkbox" id="status"' +
(disabled ? "" : " checked") +
">"
'<input type="checkbox" id="status"' + (disabled ? "" : " checked") + ">"
);
$("#status", row).bootstrapToggle({
on: "Enabled",
@@ -171,9 +168,7 @@ function initTable() {
$("#comment", row).on("change", editDomain);
$("td:eq(4)", row).empty();
$("td:eq(4)", row).append(
'<select id="multiselect" multiple="multiple"></select>'
);
$("td:eq(4)", row).append('<select id="multiselect" multiple="multiple"></select>');
var sel = $("#multiselect", row);
// Add all known groups
for (var i = 0; i < groups.length; i++) {
@@ -181,12 +176,14 @@ function initTable() {
if (!groups[i].enabled) {
extra = " (disabled)";
}
sel.append(
$("<option />")
.val(groups[i].id)
.text(groups[i].name + extra)
);
}
// Select assigned groups
sel.val(data.groups);
// Initialize multiselect
@@ -217,6 +214,7 @@ function initTable() {
if (data === null) {
return null;
}
data = JSON.parse(data);
// Always start on the first page to show most recent queries
data.start = 0;
@@ -268,30 +266,14 @@ function addDomain() {
},
success: function(response) {
if (response.success) {
showAlert(
"success",
"glyphicon glyphicon-plus",
"Successfully added domain",
domain
);
showAlert("success", "glyphicon glyphicon-plus", "Successfully added domain", domain);
$("#new_domain").val("");
$("#new_comment").val("");
table.ajax.reload();
} else
showAlert(
"error",
"",
"Error while adding new domain",
response.message
);
} else showAlert("error", "", "Error while adding new domain", response.message);
},
error: function(jqXHR, exception) {
showAlert(
"error",
"",
"Error while adding new domain",
jqXHR.responseText
);
showAlert("error", "", "Error while adding new domain", jqXHR.responseText);
console.log(exception);
}
});
@@ -384,31 +366,15 @@ function deleteDomain() {
data: { action: "delete_domain", id: id, token: token },
success: function(response) {
if (response.success) {
showAlert(
"success",
"glyphicon glyphicon-trash",
"Successfully deleted domain",
domain
);
showAlert("success", "glyphicon glyphicon-trash", "Successfully deleted domain", domain);
table
.row(tr)
.remove()
.draw(false);
} else
showAlert(
"error",
"",
"Error while deleting domain with ID " + id,
response.message
);
} else showAlert("error", "", "Error while deleting domain with ID " + id, response.message);
},
error: function(jqXHR, exception) {
showAlert(
"error",
"",
"Error while deleting domain with ID " + id,
jqXHR.responseText
);
showAlert("error", "", "Error while deleting domain with ID " + id, jqXHR.responseText);
console.log(exception);
}
});
+12 -46
View File
@@ -34,6 +34,7 @@ function showAlert(type, icon, title, message) {
} else {
$.notify(opts);
}
break;
case "warning":
opts = {
@@ -47,6 +48,7 @@ function showAlert(type, icon, title, message) {
} else {
$.notify(opts);
}
break;
case "error":
opts = {
@@ -60,9 +62,9 @@ function showAlert(type, icon, title, message) {
} else {
$.notify(opts);
}
break;
default:
return;
}
}
@@ -111,9 +113,7 @@ $(document).ready(function() {
var disabled = data.enabled === 0;
$("td:eq(1)", row).html(
'<input type="checkbox" id="status"' +
(disabled ? "" : " checked") +
">"
'<input type="checkbox" id="status"' + (disabled ? "" : " checked") + ">"
);
var status = $("#status", row);
status.bootstrapToggle({
@@ -158,6 +158,7 @@ $(document).ready(function() {
if (data === null) {
return null;
}
data = JSON.parse(data);
// Always start on the first page to show most recent queries
data.start = 0;
@@ -202,31 +203,16 @@ function addGroup() {
data: { action: "add_group", name: name, desc: desc, token: token },
success: function(response) {
if (response.success) {
showAlert(
"success",
"glyphicon glyphicon-plus",
"Successfully added group",
name
);
showAlert("success", "glyphicon glyphicon-plus", "Successfully added group", name);
$("#new_name").val("");
$("#new_desc").val("");
table.ajax.reload();
} else {
showAlert(
"error",
"",
"Error while adding new group",
response.message
);
showAlert("error", "", "Error while adding new group", response.message);
}
},
error: function(jqXHR, exception) {
showAlert(
"error",
"",
"Error while adding new group",
jqXHR.responseText
);
showAlert("error", "", "Error while adding new group", jqXHR.responseText);
console.log(exception);
}
});
@@ -271,12 +257,7 @@ function editGroup() {
},
success: function(response) {
if (response.success) {
showAlert(
"success",
"glyphicon glyphicon-pencil",
"Successfully " + done + " group",
name
);
showAlert("success", "glyphicon glyphicon-pencil", "Successfully " + done + " group", name);
} else {
showAlert(
"error",
@@ -311,32 +292,17 @@ function deleteGroup() {
data: { action: "delete_group", id: id, token: token },
success: function(response) {
if (response.success) {
showAlert(
"success",
"glyphicon glyphicon-trash",
"Successfully deleted group ",
name
);
showAlert("success", "glyphicon glyphicon-trash", "Successfully deleted group ", name);
table
.row(tr)
.remove()
.draw(false);
} else {
showAlert(
"error",
"",
"Error while deleting group with ID " + id,
response.message
);
showAlert("error", "", "Error while deleting group with ID " + id, response.message);
}
},
error: function(jqXHR, exception) {
showAlert(
"error",
"",
"Error while deleting group with ID " + id,
jqXHR.responseText
);
showAlert("error", "", "Error while deleting group with ID " + id, jqXHR.responseText);
console.log(exception);
}
});
File diff suppressed because it is too large Load Diff
+82 -107
View File
@@ -1,113 +1,88 @@
/* Pi-hole: A black hole for Internet advertisements
* (c) 2019 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. */
* (c) 2019 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. */
// This code has been taken from
// https://datatables.net/plug-ins/sorting/ip-address
jQuery.extend( jQuery.fn.dataTableExt.oSort,
{
"ip-address-pre": function ( a )
{
if (!a) { return 0; }
var i, item;
var m = a.split("."),
n = a.split(":"),
x = "",
xa = "";
if (m.length === 4)
{
// IPV4
for(i = 0; i < m.length; i++)
{
item = m[i];
if(item.length === 1)
{
x += "00" + item;
}
else if(item.length === 2)
{
x += "0" + item;
}
else
{
x += item;
}
}
}
else if (n.length > 0)
{
// IPV6
var count = 0;
for(i = 0; i < n.length; i++)
{
item = n[i];
if (i > 0)
{
xa += ":";
}
if(item.length === 0)
{
count += 0;
}
else if(item.length === 1)
{
xa += "000" + item;
count += 4;
}
else if(item.length === 2)
{
xa += "00" + item;
count += 4;
}
else if(item.length === 3)
{
xa += "0" + item;
count += 4;
}
else
{
xa += item;
count += 4;
}
}
// Padding the ::
n = xa.split(":");
var paddDone = 0;
for (i = 0; i < n.length; i++)
{
item = n[i];
if (item.length === 0 && paddDone === 0)
{
for(var padding = 0; padding < (32-count); padding++)
{
x += "0";
paddDone = 1;
}
}
else
{
x += item;
}
}
}
return x;
},
"ip-address-asc": function ( a, b )
{
return ((a < b) ? -1 : ((a > b) ? 1 : 0));
},
"ip-address-desc": function ( a, b )
{
return ((a < b) ? 1 : ((a > b) ? -1 : 0));
jQuery.extend(jQuery.fn.dataTableExt.oSort, {
"ip-address-pre": function(a) {
if (!a) {
return 0;
}
var i, item;
var m = a.split("."),
n = a.split(":"),
x = "",
xa = "";
if (m.length === 4) {
// IPV4
for (i = 0; i < m.length; i++) {
item = m[i];
if (item.length === 1) {
x += "00" + item;
} else if (item.length === 2) {
x += "0" + item;
} else {
x += item;
}
}
} else if (n.length > 0) {
// IPV6
var count = 0;
for (i = 0; i < n.length; i++) {
item = n[i];
if (i > 0) {
xa += ":";
}
if (item.length === 0) {
count += 0;
} else if (item.length === 1) {
xa += "000" + item;
count += 4;
} else if (item.length === 2) {
xa += "00" + item;
count += 4;
} else if (item.length === 3) {
xa += "0" + item;
count += 4;
} else {
xa += item;
count += 4;
}
}
// Padding the ::
n = xa.split(":");
var paddDone = 0;
for (i = 0; i < n.length; i++) {
item = n[i];
if (item.length === 0 && paddDone === 0) {
for (var padding = 0; padding < 32 - count; padding++) {
x += "0";
paddDone = 1;
}
} else {
x += item;
}
}
}
return x;
},
"ip-address-asc": function(a, b) {
return a < b ? -1 : a > b ? 1 : 0;
},
"ip-address-desc": function(a, b) {
return a < b ? 1 : a > b ? -1 : 0;
}
});
+235 -223
View File
@@ -1,275 +1,287 @@
/* 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. */
* (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. */
// IE likes to cache too much :P
$.ajaxSetup({cache: false});
$.ajaxSetup({ cache: false });
// Get PHP info
var token = $("#token").text();
var listType = $("#list-type").html();
var fullName = listType === "white" ? "Whitelist" : "Blacklist";
function addListEntry(entry, index, list, button, type)
{
var disabled = [];
if(entry.enabled === "0")
disabled.push("individual");
// For entry.group_enabled we either get "0" (= disabled by a group),
// "1" (= enabled by a group), or "" (= not managed by a group)
if(entry.group_enabled === "0")
disabled.push("group");
function addListEntry(entry, index, list, button, type) {
var disabled = [];
if (entry.enabled === "0") disabled.push("individual");
// For entry.group_enabled we either get "0" (= disabled by a group),
// "1" (= enabled by a group), or "" (= not managed by a group)
if (entry.group_enabled === "0") disabled.push("group");
var used = disabled.length === 0 ? "used" : "not-used";
var comment = entry.comment.length > 0 ? "&nbsp;-&nbsp;" + entry.comment : "";
var disabled_message = disabled.length > 0 ? "&nbsp;-&nbsp;disabled due to " + disabled.join(" + ") + " setting" : "";
var date_added = new Date(parseInt(entry.date_added)*1000);
var date_modified = new Date(parseInt(entry.date_modified)*1000);
var tooltip = "Added: " + date_added.toLocaleString() +
"\nModified: " + date_modified.toLocaleString();
list.append(
"<li id=\"" + index + "\" class=\"list-group-item " + used + " clearfix\">" +
"<span title=\"" + tooltip + "\" data-toggle=\"tooltip\" data-placement=\"right\">" +
entry.domain + comment + disabled_message + "</span>" +
"<button class=\"btn btn-danger btn-xs pull-right\" type=\"button\">" +
"<span class=\"glyphicon glyphicon-trash\"></span></button></li>"
);
// Handle button
$(button+" #"+index).on("click", "button", function() {
sub(index, entry.domain, type);
});
var used = disabled.length === 0 ? "used" : "not-used";
var comment = entry.comment.length > 0 ? "&nbsp;-&nbsp;" + entry.comment : "";
var disabled_message =
disabled.length > 0 ? "&nbsp;-&nbsp;disabled due to " + disabled.join(" + ") + " setting" : "";
var date_added = new Date(parseInt(entry.date_added) * 1000);
var date_modified = new Date(parseInt(entry.date_modified) * 1000);
var tooltip =
"Added: " + date_added.toLocaleString() + "\nModified: " + date_modified.toLocaleString();
list.append(
'<li id="' +
index +
'" class="list-group-item ' +
used +
' clearfix">' +
'<span title="' +
tooltip +
'" data-toggle="tooltip" data-placement="right">' +
entry.domain +
comment +
disabled_message +
"</span>" +
'<button class="btn btn-danger btn-xs pull-right" type="button">' +
'<span class="glyphicon glyphicon-trash"></span></button></li>'
);
// Handle button
$(button + " #" + index).on("click", "button", function() {
sub(index, entry.domain, type);
});
}
function refresh(fade) {
var list = $("#list");
var listw = $("#list-regex");
if(fade) {
list.fadeOut(100);
listw.fadeOut(100);
}
$.ajax({
url: "scripts/pi-hole/php/get.php",
method: "get",
data: {"list":listType},
success: function(response) {
list.html("");
listw.html("");
var list = $("#list");
var listw = $("#list-regex");
if (fade) {
list.fadeOut(100);
listw.fadeOut(100);
}
if((listType === "black" &&
response.blacklist.length === 0 &&
response.regex_blacklist.length === 0) ||
(listType === "white" &&
response.whitelist.length === 0 &&
response.regex_whitelist.length === 0))
{
$("h3").hide();
list.html("<div class=\"alert alert-info\" role=\"alert\">Your " + fullName + " is empty!</div>");
}
else
{
var data, data2;
if(listType === "white")
{
data = response.whitelist.sort();
data2 = response.regex_whitelist.sort();
}
else if(listType === "black")
{
data = response.blacklist.sort();
data2 = response.regex_blacklist.sort();
}
$.ajax({
url: "scripts/pi-hole/php/get.php",
method: "get",
data: { list: listType },
success: function(response) {
list.html("");
listw.html("");
if(data.length > 0)
{
$("#h3-exact").fadeIn(100);
}
if(data2.length > 0)
{
$("#h3-regex").fadeIn(100);
}
data.forEach(function (entry, index)
{
addListEntry(entry, index, list, "#list", "exact");
});
data2.forEach(function (entry, index)
{
addListEntry(entry, index, listw, "#list-regex", listType+"_regex");
});
}
list.fadeIn(100);
listw.fadeIn(100);
},
error: function() {
$("#alFailure").show();
if (
(listType === "black" &&
response.blacklist.length === 0 &&
response.regex_blacklist.length === 0) ||
(listType === "white" &&
response.whitelist.length === 0 &&
response.regex_whitelist.length === 0)
) {
$("h3").hide();
list.html(
'<div class="alert alert-info" role="alert">Your ' + fullName + " is empty!</div>"
);
} else {
var data, data2;
if (listType === "white") {
data = response.whitelist.sort();
data2 = response.regex_whitelist.sort();
} else if (listType === "black") {
data = response.blacklist.sort();
data2 = response.regex_blacklist.sort();
}
});
if (data.length > 0) {
$("#h3-exact").fadeIn(100);
}
if (data2.length > 0) {
$("#h3-regex").fadeIn(100);
}
data.forEach(function(entry, index) {
addListEntry(entry, index, list, "#list", "exact");
});
data2.forEach(function(entry, index) {
addListEntry(entry, index, listw, "#list-regex", listType + "_regex");
});
}
list.fadeIn(100);
listw.fadeIn(100);
},
error: function() {
$("#alFailure").show();
}
});
}
window.addEventListener('load', refresh(false));
window.addEventListener("load", refresh(false));
function sub(index, entry, arg) {
var list = "#list";
var heading = "#h3-exact";
var locallistType = listType;
if(arg === "black_regex" || arg === "white_regex")
{
list = "#list-regex";
heading = "#h3-regex";
locallistType = arg;
}
var alInfo = $("#alInfo");
var alSuccess = $("#alSuccess");
var alFailure = $("#alFailure");
var err = $("#err");
var msg = $("#success-message");
var list = "#list";
var heading = "#h3-exact";
var locallistType = listType;
if (arg === "black_regex" || arg === "white_regex") {
list = "#list-regex";
heading = "#h3-regex";
locallistType = arg;
}
var domain = $(list+" #"+index);
domain.hide("highlight");
$.ajax({
url: "scripts/pi-hole/php/sub.php",
method: "post",
data: {"domain":entry, "list":locallistType, "token":token},
success: function(response) {
if (response.indexOf("Success") === -1) {
alFailure.show();
err.html(response);
alFailure.delay(8000).fadeOut(2000, function() {
alFailure.hide();
});
alInfo.delay(8000).fadeOut(2000, function() {
alInfo.hide();
});
} else {
alSuccess.show();
msg.html(response);
alSuccess.delay(1000).fadeOut(2000, function() {
alSuccess.hide();
});
alInfo.delay(1000).fadeOut(2000, function() {
alInfo.hide();
});
domain.remove();
if($(list+" li").length === 0)
{
$(heading).fadeOut(100);
}
}
},
error: function() {
alert("Failed to remove the domain!");
domain.show({queue:true});
var alInfo = $("#alInfo");
var alSuccess = $("#alSuccess");
var alFailure = $("#alFailure");
var err = $("#err");
var msg = $("#success-message");
var domain = $(list + " #" + index);
domain.hide("highlight");
$.ajax({
url: "scripts/pi-hole/php/sub.php",
method: "post",
data: { domain: entry, list: locallistType, token: token },
success: function(response) {
if (response.indexOf("Success") === -1) {
alFailure.show();
err.html(response);
alFailure.delay(8000).fadeOut(2000, function() {
alFailure.hide();
});
alInfo.delay(8000).fadeOut(2000, function() {
alInfo.hide();
});
} else {
alSuccess.show();
msg.html(response);
alSuccess.delay(1000).fadeOut(2000, function() {
alSuccess.hide();
});
alInfo.delay(1000).fadeOut(2000, function() {
alInfo.hide();
});
domain.remove();
if ($(list + " li").length === 0) {
$(heading).fadeOut(100);
}
});
}
},
error: function() {
alert("Failed to remove the domain!");
domain.show({ queue: true });
}
});
}
function add(type) {
var domain = $("#domain");
if(domain.val().length === 0){
return;
var domain = $("#domain");
if (domain.val().length === 0) {
return;
}
var comment = $("#comment");
var alInfo = $("#alInfo");
var alSuccess = $("#alSuccess");
var alFailure = $("#alFailure");
var alWarning = $("#alWarning");
var err = $("#err");
var msg = $("#success-message");
alInfo.show();
alSuccess.hide();
alFailure.hide();
alWarning.hide();
$.ajax({
url: "scripts/pi-hole/php/add.php",
method: "post",
data: { domain: domain.val().trim(), comment: comment.val(), list: type, token: token },
success: function(response) {
if (response.indexOf("Success") === -1) {
alFailure.show();
err.html(response);
alFailure.delay(8000).fadeOut(2000, function() {
alFailure.hide();
});
alInfo.delay(8000).fadeOut(2000, function() {
alInfo.hide();
});
} else {
alSuccess.show();
msg.html(response);
alSuccess.delay(1000).fadeOut(2000, function() {
alSuccess.hide();
});
alInfo.delay(1000).fadeOut(2000, function() {
alInfo.hide();
});
domain.val("");
comment.val("");
refresh(true);
}
},
error: function() {
alFailure.show();
err.html("");
alFailure.delay(1000).fadeOut(2000, function() {
alFailure.hide();
});
alInfo.delay(1000).fadeOut(2000, function() {
alInfo.hide();
});
}
var comment = $("#comment");
var alInfo = $("#alInfo");
var alSuccess = $("#alSuccess");
var alFailure = $("#alFailure");
var alWarning = $("#alWarning");
var err = $("#err");
var msg = $("#success-message");
alInfo.show();
alSuccess.hide();
alFailure.hide();
alWarning.hide();
$.ajax({
url: "scripts/pi-hole/php/add.php",
method: "post",
data: {"domain":domain.val().trim(),"comment":comment.val(), "list":type, "token":token},
success: function(response) {
if (response.indexOf("Success") === -1) {
alFailure.show();
err.html(response);
alFailure.delay(8000).fadeOut(2000, function() {
alFailure.hide();
});
alInfo.delay(8000).fadeOut(2000, function() {
alInfo.hide();
});
} else {
alSuccess.show();
msg.html(response);
alSuccess.delay(1000).fadeOut(2000, function() {
alSuccess.hide();
});
alInfo.delay(1000).fadeOut(2000, function() {
alInfo.hide();
});
domain.val("");
comment.val("");
refresh(true);
}
},
error: function() {
alFailure.show();
err.html("");
alFailure.delay(1000).fadeOut(2000, function() {
alFailure.hide();
});
alInfo.delay(1000).fadeOut(2000, function() {
alInfo.hide();
});
}
});
});
}
// Handle enter button for adding domains
$(document).keypress(function(e) {
if(e.which === 13 && $("#domain,#comment").is(":focus")) {
// Enter was pressed, and the input has focus
add(listType);
}
if (e.which === 13 && $("#domain,#comment").is(":focus")) {
// Enter was pressed, and the input has focus
add(listType);
}
});
// Handle buttons
$("#btnAdd").on("click", function() {
add(listType);
add(listType);
});
$("#btnAddWildcard").on("click", function() {
add(listType+"_wild");
add(listType + "_wild");
});
$("#btnAddRegex").on("click", function() {
add(listType+"_regex");
add(listType + "_regex");
});
$("#btnRefresh").on("click", function() {
refresh(true);
refresh(true);
});
// Handle hiding of alerts
$(function(){
$("[data-hide]").on("click", function(){
$(this).closest("." + $(this).attr("data-hide")).hide();
});
$(function() {
$("[data-hide]").on("click", function() {
$(this)
.closest("." + $(this).attr("data-hide"))
.hide();
});
});
// Wrap form-group's buttons to next line when viewed on a small screen
$(window).on("resize",function() {
if ($(window).width() < 991) {
$(".form-group.input-group").removeClass("input-group").addClass("input-group-block");
$(".form-group.input-group-block > input").css("margin-bottom", "5px");
$(".form-group.input-group-block > .input-group-btn").removeClass("input-group-btn").addClass("btn-block text-center");
}
else {
$(".form-group.input-group-block").removeClass("input-group-block").addClass( "input-group" );
$(".form-group.input-group > input").css("margin-bottom","");
$(".form-group.input-group > .btn-block.text-center").removeClass("btn-block text-center").addClass("input-group-btn");
}
$(window).on("resize", function() {
if ($(window).width() < 991) {
$(".form-group.input-group")
.removeClass("input-group")
.addClass("input-group-block");
$(".form-group.input-group-block > input").css("margin-bottom", "5px");
$(".form-group.input-group-block > .input-group-btn")
.removeClass("input-group-btn")
.addClass("btn-block text-center");
} else {
$(".form-group.input-group-block")
.removeClass("input-group-block")
.addClass("input-group");
$(".form-group.input-group > input").css("margin-bottom", "");
$(".form-group.input-group > .btn-block.text-center")
.removeClass("btn-block text-center")
.addClass("input-group-btn");
}
});
$(document).ready(function() {
$(window).trigger("resize");
$(window).trigger("resize");
});
+160 -140
View File
@@ -1,9 +1,9 @@
/* 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. */
* (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. */
/* global moment:false */
@@ -15,159 +15,179 @@ var APIstring = "api_db.php?network";
var MAXIPDISPLAY = 3;
function handleAjaxError(xhr, textStatus) {
if ( textStatus === "timeout" )
{
alert( "The server took too long to send the data." );
}
else if(xhr.responseText.indexOf("Connection refused") >= 0)
{
alert( "An error occured while loading the data: Connection refused. Is FTL running?" );
}
else
{
alert( "An unknown error occured while loading the data.\n"+xhr.responseText );
}
$("#network-entries_processing").hide();
tableApi.clear();
tableApi.draw();
if (textStatus === "timeout") {
alert("The server took too long to send the data.");
} else if (xhr.responseText.indexOf("Connection refused") >= 0) {
alert("An error occured while loading the data: Connection refused. Is FTL running?");
} else {
alert("An unknown error occured while loading the data.\n" + xhr.responseText);
}
$("#network-entries_processing").hide();
tableApi.clear();
tableApi.draw();
}
function getTimestamp(){
if (!Date.now)
{
Date.now = function() { return new Date().getTime(); };
function getTimestamp() {
if (!Date.now) {
Date.now = function() {
return new Date().getTime();
};
}
return Math.floor(Date.now() / 1000);
}
function valueToHex(c) {
var hex = Math.round(c).toString(16);
return hex.length === 1 ? "0" + hex : hex;
var hex = Math.round(c).toString(16);
return hex.length === 1 ? "0" + hex : hex;
}
function rgbToHex(values) {
return "#" + valueToHex(values[0]) +
valueToHex(values[1]) +
valueToHex(values[2]);
return "#" + valueToHex(values[0]) + valueToHex(values[1]) + valueToHex(values[2]);
}
function mixColors(ratio, rgb1, rgb2)
{
return [(1.0-ratio)*rgb1[0]+ratio*rgb2[0],
(1.0-ratio)*rgb1[1]+ratio*rgb2[1],
(1.0-ratio)*rgb1[2]+ratio*rgb2[2]];
function mixColors(ratio, rgb1, rgb2) {
return [
(1.0 - ratio) * rgb1[0] + ratio * rgb2[0],
(1.0 - ratio) * rgb1[1] + ratio * rgb2[1],
(1.0 - ratio) * rgb1[2] + ratio * rgb2[2]
];
}
$(document).ready(function() {
tableApi = $("#network-entries").DataTable( {
"rowCallback": function( row, data )
{
var color, mark, lastQuery = parseInt(data.lastQuery);
if(lastQuery > 0)
{
var diff = getTimestamp()-lastQuery;
if(diff <= 86400)
{
// Last query came in within the last 24 hours (24*60*60 = 86400)
// Color: light-green to light-yellow
var ratio = Number(diff)/86400;
var lightgreen = [0xE7, 0xFF, 0xDE];
var lightyellow = [0xFF, 0xFF, 0xDF];
color = rgbToHex(mixColors(ratio, lightgreen, lightyellow));
mark = "&#x2714;";
}
else
{
// Last query was longer than 24 hours ago
// Color: light-orange
color = "#ffedd9";
mark = "<strong>?</strong>";
}
}
else
{
// This client has never sent a query to Pi-hole, color light-red
color = "#ffbfaa";
mark = "&#x2718;";
}
// Set determined background color
$(row).css("background-color", color);
$("td:eq(7)", row).html(mark);
tableApi = $("#network-entries").DataTable({
rowCallback: function(row, data) {
var color,
mark,
lastQuery = parseInt(data.lastQuery);
if (lastQuery > 0) {
var diff = getTimestamp() - lastQuery;
if (diff <= 86400) {
// Last query came in within the last 24 hours (24*60*60 = 86400)
// Color: light-green to light-yellow
var ratio = Number(diff) / 86400;
var lightgreen = [0xe7, 0xff, 0xde];
var lightyellow = [0xff, 0xff, 0xdf];
color = rgbToHex(mixColors(ratio, lightgreen, lightyellow));
mark = "&#x2714;";
} else {
// Last query was longer than 24 hours ago
// Color: light-orange
color = "#ffedd9";
mark = "<strong>?</strong>";
}
} else {
// This client has never sent a query to Pi-hole, color light-red
color = "#ffbfaa";
mark = "&#x2718;";
}
// Insert "Never" into Last Query field when we have
// never seen a query from this device
if(data.lastQuery === 0)
{
$("td:eq(5)", row).html("Never");
}
// Set determined background color
$(row).css("background-color", color);
$("td:eq(7)", row).html(mark);
// Set hostname to "N/A" if not available
if(!data.name || data.name.length === 0)
{
$("td:eq(3)", row).html("N/A");
}
// Insert "Never" into Last Query field when we have
// never seen a query from this device
if (data.lastQuery === 0) {
$("td:eq(5)", row).html("Never");
}
// Set number of queries to localized string (add thousand separators)
$("td:eq(6)", row).html(data.numQueries.toLocaleString());
// Set hostname to "N/A" if not available
if (!data.name || data.name.length === 0) {
$("td:eq(3)", row).html("N/A");
}
var ips = data.ip;
var shortips = ips;
if(ips.length > MAXIPDISPLAY)
{
shortips = ips.slice(0,MAXIPDISPLAY-1);
shortips.push("...");
}
$("td:eq(0)", row).html(shortips.join("<br>"));
$("td:eq(0)", row).hover(function () { this.title=ips.join("\n");});
// Set number of queries to localized string (add thousand separators)
$("td:eq(6)", row).html(data.numQueries.toLocaleString());
// MAC + Vendor field if available
if(data.macVendor && data.macVendor.length > 0)
{
$("td:eq(1)", row).html(data.hwaddr+"<br/>"+data.macVendor);
}
var ips = data.ip;
var shortips = ips;
if (ips.length > MAXIPDISPLAY) {
shortips = ips.slice(0, MAXIPDISPLAY - 1);
shortips.push("...");
}
},
dom: "<'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>>",
"ajax": {"url": APIstring, "error": handleAjaxError, "dataSrc": "network" },
"autoWidth" : false,
"processing": true,
"order" : [[5, "desc"]],
"columns": [
{data: "ip", "type": "ip-address", "width" : "10%", "render": $.fn.dataTable.render.text() },
{data: "hwaddr", "width" : "10%", "render": $.fn.dataTable.render.text() },
{data: "interface", "width" : "4%", "render": $.fn.dataTable.render.text() },
{data: "name", "width" : "15%", "render": $.fn.dataTable.render.text() },
{data: "firstSeen", "width" : "8%", "render": function (data, type) { if(type === "display"){return moment.unix(data).format("Y-MM-DD [<br class='hidden-lg'>]HH:mm:ss z");}return data; }},
{data: "lastQuery", "width" : "8%", "render": function (data, type) { if(type === "display"){return moment.unix(data).format("Y-MM-DD [<br class='hidden-lg'>]HH:mm:ss z");}return data; }},
{data: "numQueries", "width" : "9%", "render": $.fn.dataTable.render.text() },
{data: "", "width" : "6%", "orderable" : false }
],
"lengthMenu": [[10, 25, 50, 100, -1], [10, 25, 50, 100, "All"]],
"stateSave": true,
stateSaveCallback: function(settings, data) {
// Store current state in client's local storage area
localStorage.setItem("network_table", JSON.stringify(data));
},
stateLoadCallback: function() {
// Receive previous state from client's local storage area
var data = localStorage.getItem("network_table");
// Return if not available
if(data === null){ return null; }
data = JSON.parse(data);
// Always start on the first page
data.start = 0;
// Always start with empty search field
data.search.search = "";
// Apply loaded state to table
return data;
},
"columnDefs": [ {
"targets": -1,
"data": null,
"defaultContent": ""
} ]
});
} );
$("td:eq(0)", row).html(shortips.join("<br>"));
$("td:eq(0)", row).hover(function() {
this.title = ips.join("\n");
});
// MAC + Vendor field if available
if (data.macVendor && data.macVendor.length > 0) {
$("td:eq(1)", row).html(data.hwaddr + "<br/>" + data.macVendor);
}
},
dom:
"<'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>>",
ajax: { url: APIstring, error: handleAjaxError, dataSrc: "network" },
autoWidth: false,
processing: true,
order: [[5, "desc"]],
columns: [
{ data: "ip", type: "ip-address", width: "10%", render: $.fn.dataTable.render.text() },
{ data: "hwaddr", width: "10%", render: $.fn.dataTable.render.text() },
{ data: "interface", width: "4%", render: $.fn.dataTable.render.text() },
{ data: "name", width: "15%", render: $.fn.dataTable.render.text() },
{
data: "firstSeen",
width: "8%",
render: function(data, type) {
if (type === "display") {
return moment.unix(data).format("Y-MM-DD [<br class='hidden-lg'>]HH:mm:ss z");
}
return data;
}
},
{
data: "lastQuery",
width: "8%",
render: function(data, type) {
if (type === "display") {
return moment.unix(data).format("Y-MM-DD [<br class='hidden-lg'>]HH:mm:ss z");
}
return data;
}
},
{ data: "numQueries", width: "9%", render: $.fn.dataTable.render.text() },
{ data: "", width: "6%", orderable: false }
],
lengthMenu: [
[10, 25, 50, 100, -1],
[10, 25, 50, 100, "All"]
],
stateSave: true,
stateSaveCallback: function(settings, data) {
// Store current state in client's local storage area
localStorage.setItem("network_table", JSON.stringify(data));
},
stateLoadCallback: function() {
// Receive previous state from client's local storage area
var data = localStorage.getItem("network_table");
// Return if not available
if (data === null) {
return null;
}
data = JSON.parse(data);
// Always start on the first page
data.start = 0;
// Always start with empty search field
data.search.search = "";
// Apply loaded state to table
return data;
},
columnDefs: [
{
targets: -1,
data: null,
defaultContent: ""
}
]
});
});
+421 -377
View File
@@ -1,398 +1,442 @@
/* 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. */
* (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. */
/* global moment:false */
var tableApi;
function add(domain,list) {
var token = $("#token").text();
var alertModal = $("#alertModal");
var alProcessing = alertModal.find(".alProcessing");
var alSuccess = alertModal.find(".alSuccess");
var alFailure = alertModal.find(".alFailure");
var alNetworkErr = alertModal.find(".alFailure #alNetErr");
var alCustomErr = alertModal.find(".alFailure #alCustomErr");
var alList = "#alList";
var alDomain = "#alDomain";
function add(domain, list) {
var token = $("#token").text();
var alertModal = $("#alertModal");
var alProcessing = alertModal.find(".alProcessing");
var alSuccess = alertModal.find(".alSuccess");
var alFailure = alertModal.find(".alFailure");
var alNetworkErr = alertModal.find(".alFailure #alNetErr");
var alCustomErr = alertModal.find(".alFailure #alCustomErr");
var alList = "#alList";
var alDomain = "#alDomain";
// Exit the function here if the Modal is already shown (multiple running interlock)
if (alertModal.css("display") !== "none") {
return;
}
// Exit the function here if the Modal is already shown (multiple running interlock)
if (alertModal.css("display") !== "none") {
return;
}
var listtype;
if (list === "white") {
listtype = "Whitelist";
} else {
listtype = "Blacklist";
}
alProcessing.children(alDomain).html(domain);
alProcessing.children(alList).html(listtype);
alertModal.modal("show");
var listtype;
if (list === "white") {
listtype = "Whitelist";
} else {
listtype = "Blacklist";
}
// add Domain to List after Modal has faded in
alertModal.one("shown.bs.modal", function() {
$.ajax({
url: "scripts/pi-hole/php/add.php",
method: "post",
data: {"domain":domain, "list":list, "token":token},
success: function(response) {
alProcessing.hide();
if (response.indexOf("not a valid argument") >= 0 ||
response.indexOf("is not a valid domain") >= 0 ||
response.indexOf("Wrong token") >= 0)
{
// Failure
alNetworkErr.hide();
alCustomErr.html(response.replace("[✗]", ""));
alFailure.fadeIn(1000);
setTimeout(function() { alertModal.modal("hide"); }, 3000);
}
else
{
// Success
alSuccess.children(alDomain).html(domain);
alSuccess.children(alList).html(listtype);
alSuccess.fadeIn(1000);
setTimeout(function() { alertModal.modal("hide"); }, 2000);
}
},
error: function() {
// Network Error
alProcessing.hide();
alNetworkErr.show();
alFailure.fadeIn(1000);
setTimeout(function() { alertModal.modal("hide"); }, 3000);
}
});
alProcessing.children(alDomain).html(domain);
alProcessing.children(alList).html(listtype);
alertModal.modal("show");
// add Domain to List after Modal has faded in
alertModal.one("shown.bs.modal", function() {
$.ajax({
url: "scripts/pi-hole/php/add.php",
method: "post",
data: { domain: domain, list: list, token: token },
success: function(response) {
alProcessing.hide();
if (
response.indexOf("not a valid argument") >= 0 ||
response.indexOf("is not a valid domain") >= 0 ||
response.indexOf("Wrong token") >= 0
) {
// Failure
alNetworkErr.hide();
alCustomErr.html(response.replace("[✗]", ""));
alFailure.fadeIn(1000);
setTimeout(function() {
alertModal.modal("hide");
}, 3000);
} else {
// Success
alSuccess.children(alDomain).html(domain);
alSuccess.children(alList).html(listtype);
alSuccess.fadeIn(1000);
setTimeout(function() {
alertModal.modal("hide");
}, 2000);
}
},
error: function() {
// Network Error
alProcessing.hide();
alNetworkErr.show();
alFailure.fadeIn(1000);
setTimeout(function() {
alertModal.modal("hide");
}, 3000);
}
});
});
// Reset Modal after it has faded out
alertModal.one("hidden.bs.modal", function() {
alProcessing.show();
alSuccess.add(alFailure).hide();
alProcessing.add(alSuccess).children(alDomain).html("").end().children(alList).html("");
alCustomErr.html("");
});
// Reset Modal after it has faded out
alertModal.one("hidden.bs.modal", function() {
alProcessing.show();
alSuccess.add(alFailure).hide();
alProcessing
.add(alSuccess)
.children(alDomain)
.html("")
.end()
.children(alList)
.html("");
alCustomErr.html("");
});
}
function handleAjaxError( xhr, textStatus ) {
if ( textStatus === "timeout" )
{
alert( "The server took too long to send the data." );
}
else if(xhr.responseText.indexOf("Connection refused") >= 0)
{
alert( "An error occured while loading the data: Connection refused. Is FTL running?" );
}
else
{
alert( "An unknown error occured while loading the data.\n"+xhr.responseText );
}
$("#all-queries_processing").hide();
tableApi.clear();
tableApi.draw();
function handleAjaxError(xhr, textStatus) {
if (textStatus === "timeout") {
alert("The server took too long to send the data.");
} else if (xhr.responseText.indexOf("Connection refused") >= 0) {
alert("An error occured while loading the data: Connection refused. Is FTL running?");
} else {
alert("An unknown error occured while loading the data.\n" + xhr.responseText);
}
$("#all-queries_processing").hide();
tableApi.clear();
tableApi.draw();
}
function autofilter(){
return document.getElementById("autofilter").checked;
function autofilter() {
return document.getElementById("autofilter").checked;
}
$(document).ready(function() {
// Do we want to filter queries?
var GETDict = {};
window.location.search.substr(1).split("&").forEach(function(item) {GETDict[item.split("=")[0]] = item.split("=")[1];});
var APIstring = "api.php?getAllQueries";
if("from" in GETDict && "until" in GETDict)
{
APIstring += "&from="+GETDict.from;
APIstring += "&until="+GETDict.until;
}
else if("client" in GETDict)
{
APIstring += "&client="+GETDict.client;
}
else if("domain" in GETDict)
{
APIstring += "&domain="+GETDict.domain;
}
else if("querytype" in GETDict)
{
APIstring += "&querytype="+GETDict.querytype;
}
else if("forwarddest" in GETDict)
{
APIstring += "&forwarddest="+GETDict.forwarddest;
}
// If we don't ask filtering and also not for all queries, just request the most recent 100 queries
else if(!("all" in GETDict))
{
APIstring += "=100";
}
tableApi = $("#all-queries").DataTable( {
"rowCallback": function( row, data ){
// DNSSEC status
var dnssec_status;
switch (data[5])
{
case "1":
dnssec_status = "<br><span class=\"text-green\">SECURE</span>";
break;
case "2":
dnssec_status = "<br><span class=\"text-orange\">INSECURE</span>";
break;
case "3":
dnssec_status = "<br><span class=\"text-red\">BOGUS</span>";
break;
case "4":
dnssec_status = "<br><span class=\"text-red\">ABANDONED</span>";
break;
case "5":
dnssec_status = "<br><span class=\"text-orange\">UNKNOWN</span>";
break;
default: // No DNSSEC
dnssec_status = "";
}
// Query status
var blocked, fieldtext, buttontext, colorClass;
switch (data[4])
{
case "1":
blocked = true;
colorClass = "text-red";
fieldtext = "Blocked (gravity)";
buttontext = "<button type=\"button\" class=\"btn btn-default btn-sm text-green\"><i class=\"fas fa-check\"></i> Whitelist</button>";
break;
case "2":
blocked = false;
colorClass = "text-green";
fieldtext = "OK <br class='hidden-lg'>(forwarded)"+dnssec_status;
buttontext = "<button type=\"button\" class=\"btn btn-default btn-sm text-red\"><i class=\"fa fa-ban\"></i> Blacklist</button>";
break;
case "3":
blocked = false;
colorClass = "text-green";
fieldtext = "OK <br class='hidden-lg'>(cached)"+dnssec_status;
buttontext = "<button type=\"button\" class=\"btn btn-default btn-sm text-red\"><i class=\"fa fa-ban\"></i> Blacklist</button>";
break;
case "4":
blocked = true;
colorClass = "text-red";
fieldtext = "Blocked <br class='hidden-lg'>(regex/wildcard)";
buttontext = "<button type=\"button\" class=\"btn btn-default btn-sm text-green\"><i class=\"fas fa-check\"></i> Whitelist</button>";
break;
case "5":
blocked = true;
colorClass = "text-red";
fieldtext = "Blocked <br class='hidden-lg'>(blacklist)";
buttontext = "<button type=\"button\" class=\"btn btn-default btn-sm text-green\"><i class=\"fas fa-check\"></i> Whitelist</button>";
break;
case "6":
blocked = true;
colorClass = "text-red";
fieldtext = "Blocked <br class='hidden-lg'>(external, IP)";
buttontext = "";
break;
case "7":
blocked = true;
colorClass = "text-red";
fieldtext = "Blocked <br class='hidden-lg'>(external, NULL)";
buttontext = "";
break;
case "8":
blocked = true;
colorClass = "text-red";
fieldtext = "Blocked <br class='hidden-lg'>(external, NXRA)";
buttontext = "";
break;
default:
blocked = false;
colorClass = "text-black";
fieldtext = "Unknown ("+parseInt(data[4])+")";
buttontext = "";
}
$(row).addClass(colorClass);
$("td:eq(4)", row).html(fieldtext);
$("td:eq(6)", row).html(buttontext);
// Check for existence of sixth column and display only if not Pi-holed
var replytext;
if(data.length > 6 && !blocked)
{
switch(data[6])
{
case "0":
replytext = "N/A";
break;
case "1":
replytext = "NODATA";
break;
case "2":
replytext = "NXDOMAIN";
break;
case "3":
replytext = "CNAME";
break;
case "4":
replytext = "IP";
break;
case "5":
replytext = "DOMAIN";
break;
case "6":
replytext = "RRNAME";
break;
case "7":
replytext = "SERVFAIL";
break;
case "8":
replytext = "REFUSED";
break;
case "9":
replytext = "NOTIMP";
break;
case "10":
replytext = "upstream error";
break;
default:
replytext = "? ("+parseInt(data[6])+")";
}
}
else
{
replytext = "-";
}
$("td:eq(5)", row).addClass("text-black");
$("td:eq(5)", row).html(replytext);
if(data.length > 7 && data[7] > 0)
{
var content = $("td:eq(5)", row).html();
$("td:eq(5)", row).html(content + " (" + (0.1*data[7]).toFixed(1)+"ms)");
}
},
dom: "<'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>>",
"ajax": {
"url": APIstring,
"error": handleAjaxError,
"dataSrc": function(data){
var dataIndex = 0;
return data.data.map(function(x){
x[0] = x[0] * 1e6 + (dataIndex++);
return x;
});
}
},
"autoWidth" : false,
"processing": true,
"order" : [[0, "desc"]],
"columns": [
{ "width" : "15%", "render": function (data, type) { if(type === "display"){return moment.unix(Math.floor(data/1e6)).format("Y-MM-DD [<br class='hidden-lg'>]HH:mm:ss z");}return data; }},
{ "width" : "4%" },
{ "width" : "36%", "render": $.fn.dataTable.render.text() },
{ "width" : "8%", "render": $.fn.dataTable.render.text() },
{ "width" : "14%", "orderData": 4 },
{ "width" : "8%", "orderData": 6 },
{ "width" : "10%", "orderData": 4 }
],
"lengthMenu": [[10, 25, 50, 100, -1], [10, 25, 50, 100, "All"]],
"stateSave": true,
stateSaveCallback: function(settings, data) {
// Store current state in client's local storage area
localStorage.setItem("query_log_table", JSON.stringify(data));
},
stateLoadCallback: function() {
// Receive previous state from client's local storage area
var data = localStorage.getItem("query_log_table");
// Return if not available
if(data === null){ return null; }
data = JSON.parse(data);
// Always start on the first page to show most recent queries
data.start = 0;
// Always start with empty search field
data.search.search = "";
// Apply loaded state to table
return data;
},
"columnDefs": [ {
"targets": -1,
"data": null,
"defaultContent": ""
} ],
"initComplete": function () {
var api = this.api();
// Query type IPv4 / IPv6
api.$("td:eq(1)").click( function () { if(autofilter()){ api.search( this.textContent ).draw(); $("#resetButton").show(); }});
api.$("td:eq(1)").hover(
function () {
if(autofilter()) {
this.title = "Click to show only " + this.textContent + " queries";
this.style.color = "#72afd2";
} else {
this.title = "";
this.style.color = "";
}
},
function () { this.style.color=""; }
);
api.$("td:eq(1)").css("cursor","pointer");
// Domain
api.$("td:eq(2)").click( function () { if(autofilter()){ api.search( this.textContent ).draw(); $("#resetButton").show(); }});
api.$("td:eq(2)").hover(
function () {
if(autofilter()) {
this.title = "Click to show only queries with domain " + this.textContent;
this.style.color = "#72afd2";
} else {
this.title = "";
this.style.color = "";
}
},
function () { this.style.color=""; }
);
api.$("td:eq(2)").css("cursor","pointer");
// Client
api.$("td:eq(3)").click( function () { if(autofilter()){ api.search( this.textContent ).draw(); $("#resetButton").show(); }});
api.$("td:eq(3)").hover(
function () {
if(autofilter()) {
this.title = "Click to show only queries made by " + this.textContent;
this.style.color = "#72afd2";
} else {
this.title = "";
this.style.color = "";
}
},
function () { this.style.color=""; }
);
api.$("td:eq(3)").css("cursor","pointer");
}
// Do we want to filter queries?
var GETDict = {};
window.location.search
.substr(1)
.split("&")
.forEach(function(item) {
GETDict[item.split("=")[0]] = item.split("=")[1];
});
$("#all-queries tbody").on( "click", "button", function () {
var data = tableApi.row( $(this).parents("tr") ).data();
if (data[4] === "1" || data[4] === "4" || data[4] === "5")
{
add(data[2],"white");
}
else
{
add(data[2],"black");
}
} );
var APIstring = "api.php?getAllQueries";
$("#resetButton").click( function () { tableApi.search("").draw(); $("#resetButton").hide(); } );
} );
if ("from" in GETDict && "until" in GETDict) {
APIstring += "&from=" + GETDict.from;
APIstring += "&until=" + GETDict.until;
} else if ("client" in GETDict) {
APIstring += "&client=" + GETDict.client;
} else if ("domain" in GETDict) {
APIstring += "&domain=" + GETDict.domain;
} else if ("querytype" in GETDict) {
APIstring += "&querytype=" + GETDict.querytype;
} else if ("forwarddest" in GETDict) {
APIstring += "&forwarddest=" + GETDict.forwarddest;
}
// If we don't ask filtering and also not for all queries, just request the most recent 100 queries
else if (!("all" in GETDict)) {
APIstring += "=100";
}
tableApi = $("#all-queries").DataTable({
rowCallback: function(row, data) {
// DNSSEC status
var dnssec_status;
switch (data[5]) {
case "1":
dnssec_status = '<br><span class="text-green">SECURE</span>';
break;
case "2":
dnssec_status = '<br><span class="text-orange">INSECURE</span>';
break;
case "3":
dnssec_status = '<br><span class="text-red">BOGUS</span>';
break;
case "4":
dnssec_status = '<br><span class="text-red">ABANDONED</span>';
break;
case "5":
dnssec_status = '<br><span class="text-orange">UNKNOWN</span>';
break;
default:
// No DNSSEC
dnssec_status = "";
}
// Query status
var blocked, fieldtext, buttontext, colorClass;
switch (data[4]) {
case "1":
blocked = true;
colorClass = "text-red";
fieldtext = "Blocked (gravity)";
buttontext =
'<button type="button" class="btn btn-default btn-sm text-green"><i class="fas fa-check"></i> Whitelist</button>';
break;
case "2":
blocked = false;
colorClass = "text-green";
fieldtext = "OK <br class='hidden-lg'>(forwarded)" + dnssec_status;
buttontext =
'<button type="button" class="btn btn-default btn-sm text-red"><i class="fa fa-ban"></i> Blacklist</button>';
break;
case "3":
blocked = false;
colorClass = "text-green";
fieldtext = "OK <br class='hidden-lg'>(cached)" + dnssec_status;
buttontext =
'<button type="button" class="btn btn-default btn-sm text-red"><i class="fa fa-ban"></i> Blacklist</button>';
break;
case "4":
blocked = true;
colorClass = "text-red";
fieldtext = "Blocked <br class='hidden-lg'>(regex/wildcard)";
buttontext =
'<button type="button" class="btn btn-default btn-sm text-green"><i class="fas fa-check"></i> Whitelist</button>';
break;
case "5":
blocked = true;
colorClass = "text-red";
fieldtext = "Blocked <br class='hidden-lg'>(blacklist)";
buttontext =
'<button type="button" class="btn btn-default btn-sm text-green"><i class="fas fa-check"></i> Whitelist</button>';
break;
case "6":
blocked = true;
colorClass = "text-red";
fieldtext = "Blocked <br class='hidden-lg'>(external, IP)";
buttontext = "";
break;
case "7":
blocked = true;
colorClass = "text-red";
fieldtext = "Blocked <br class='hidden-lg'>(external, NULL)";
buttontext = "";
break;
case "8":
blocked = true;
colorClass = "text-red";
fieldtext = "Blocked <br class='hidden-lg'>(external, NXRA)";
buttontext = "";
break;
default:
blocked = false;
colorClass = "text-black";
fieldtext = "Unknown (" + parseInt(data[4]) + ")";
buttontext = "";
}
$(row).addClass(colorClass);
$("td:eq(4)", row).html(fieldtext);
$("td:eq(6)", row).html(buttontext);
// Check for existence of sixth column and display only if not Pi-holed
var replytext;
if (data.length > 6 && !blocked) {
switch (data[6]) {
case "0":
replytext = "N/A";
break;
case "1":
replytext = "NODATA";
break;
case "2":
replytext = "NXDOMAIN";
break;
case "3":
replytext = "CNAME";
break;
case "4":
replytext = "IP";
break;
case "5":
replytext = "DOMAIN";
break;
case "6":
replytext = "RRNAME";
break;
case "7":
replytext = "SERVFAIL";
break;
case "8":
replytext = "REFUSED";
break;
case "9":
replytext = "NOTIMP";
break;
case "10":
replytext = "upstream error";
break;
default:
replytext = "? (" + parseInt(data[6]) + ")";
}
} else {
replytext = "-";
}
$("td:eq(5)", row).addClass("text-black");
$("td:eq(5)", row).html(replytext);
if (data.length > 7 && data[7] > 0) {
var content = $("td:eq(5)", row).html();
$("td:eq(5)", row).html(content + " (" + (0.1 * data[7]).toFixed(1) + "ms)");
}
},
dom:
"<'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>>",
ajax: {
url: APIstring,
error: handleAjaxError,
dataSrc: function(data) {
var dataIndex = 0;
return data.data.map(function(x) {
x[0] = x[0] * 1e6 + dataIndex++;
return x;
});
}
},
autoWidth: false,
processing: true,
order: [[0, "desc"]],
columns: [
{
width: "15%",
render: function(data, type) {
if (type === "display") {
return moment
.unix(Math.floor(data / 1e6))
.format("Y-MM-DD [<br class='hidden-lg'>]HH:mm:ss z");
}
return data;
}
},
{ width: "4%" },
{ width: "36%", render: $.fn.dataTable.render.text() },
{ width: "8%", render: $.fn.dataTable.render.text() },
{ width: "14%", orderData: 4 },
{ width: "8%", orderData: 6 },
{ width: "10%", orderData: 4 }
],
lengthMenu: [
[10, 25, 50, 100, -1],
[10, 25, 50, 100, "All"]
],
stateSave: true,
stateSaveCallback: function(settings, data) {
// Store current state in client's local storage area
localStorage.setItem("query_log_table", JSON.stringify(data));
},
stateLoadCallback: function() {
// Receive previous state from client's local storage area
var data = localStorage.getItem("query_log_table");
// Return if not available
if (data === null) {
return null;
}
data = JSON.parse(data);
// Always start on the first page to show most recent queries
data.start = 0;
// Always start with empty search field
data.search.search = "";
// Apply loaded state to table
return data;
},
columnDefs: [
{
targets: -1,
data: null,
defaultContent: ""
}
],
initComplete: function() {
var api = this.api();
// Query type IPv4 / IPv6
api.$("td:eq(1)").click(function() {
if (autofilter()) {
api.search(this.textContent).draw();
$("#resetButton").show();
}
});
api.$("td:eq(1)").hover(
function() {
if (autofilter()) {
this.title = "Click to show only " + this.textContent + " queries";
this.style.color = "#72afd2";
} else {
this.title = "";
this.style.color = "";
}
},
function() {
this.style.color = "";
}
);
api.$("td:eq(1)").css("cursor", "pointer");
// Domain
api.$("td:eq(2)").click(function() {
if (autofilter()) {
api.search(this.textContent).draw();
$("#resetButton").show();
}
});
api.$("td:eq(2)").hover(
function() {
if (autofilter()) {
this.title = "Click to show only queries with domain " + this.textContent;
this.style.color = "#72afd2";
} else {
this.title = "";
this.style.color = "";
}
},
function() {
this.style.color = "";
}
);
api.$("td:eq(2)").css("cursor", "pointer");
// Client
api.$("td:eq(3)").click(function() {
if (autofilter()) {
api.search(this.textContent).draw();
$("#resetButton").show();
}
});
api.$("td:eq(3)").hover(
function() {
if (autofilter()) {
this.title = "Click to show only queries made by " + this.textContent;
this.style.color = "#72afd2";
} else {
this.title = "";
this.style.color = "";
}
},
function() {
this.style.color = "";
}
);
api.$("td:eq(3)").css("cursor", "pointer");
}
});
$("#all-queries tbody").on("click", "button", function() {
var data = tableApi.row($(this).parents("tr")).data();
if (data[4] === "1" || data[4] === "4" || data[4] === "5") {
add(data[2], "white");
} else {
add(data[2], "black");
}
});
$("#resetButton").click(function() {
tableApi.search("").draw();
$("#resetButton").hide();
});
});
+112 -104
View File
@@ -1,144 +1,152 @@
/* 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. */
* (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. */
/* global ActiveXObject: false */
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");
}
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)
{
function httpGet(ta, quiet, theUrl) {
var xmlhttp;
if (window.XMLHttpRequest) {
// code for IE7+
xmlhttp = new XMLHttpRequest();
}
else
{
xmlhttp = new XMLHttpRequest();
} else {
// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
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.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();
};
xmlhttp.open("GET", theUrl, false);
xmlhttp.send();
}
function eventsource() {
var ta = $("#output");
var domain = $("#domain").val().trim();
var q = $("#quiet");
var ta = $("#output");
var domain = $("#domain")
.val()
.trim();
var q = $("#quiet");
if(domain.length === 0)
{
return;
}
if (domain.length === 0) {
return;
}
var quiet = false;
if(q.val() === "yes")
{
quiet = true;
exact = "exact";
}
var quiet = false;
if (q.val() === "yes") {
quiet = true;
exact = "exact";
}
// IE does not support EventSource - load whole content at once
if (typeof EventSource !== "function") {
httpGet(ta,quiet,"scripts/pi-hole/php/queryads.php?domain="+domain.toLowerCase()+exact+"&IE");
return;
}
// IE does not support EventSource - load whole content at once
if (typeof EventSource !== "function") {
httpGet(
ta,
quiet,
"scripts/pi-hole/php/queryads.php?domain=" + domain.toLowerCase() + exact + "&IE"
);
return;
}
var source = new EventSource("scripts/pi-hole/php/queryads.php?domain="+domain.toLowerCase()+"&"+exact);
var source = new EventSource(
"scripts/pi-hole/php/queryads.php?domain=" + domain.toLowerCase() + "&" + exact
);
// Reset and show field
ta.empty();
ta.show();
// Reset and show field
ta.empty();
ta.show();
source.addEventListener("message", function(e) {
if(!quiet)
{
ta.append(e.data);
}
else
{
quietfilter(ta,e.data);
}
}, false);
source.addEventListener(
"message",
function(e) {
if (!quiet) {
ta.append(e.data);
} else {
quietfilter(ta, e.data);
}
},
false
);
// Will be called when script has finished
source.addEventListener("error", function() {
source.close();
}, false);
// Will be called when script has finished
source.addEventListener(
"error",
function() {
source.close();
},
false
);
// Reset exact variable
exact = "";
// Reset exact variable
exact = "";
}
// Handle enter button
$(document).keypress(function(e) {
if(e.which === 13 && $("#domain").is(":focus")) {
// Enter was pressed, and the input has focus
exact = "";
eventsource();
}
if (e.which === 13 && $("#domain").is(":focus")) {
// Enter was pressed, and the input has focus
exact = "";
eventsource();
}
});
// Handle button
$("#btnSearch").on("click", function() {
exact = "";
eventsource();
exact = "";
eventsource();
});
// Handle exact button
$("#btnSearchExact").on("click", function() {
exact = "exact";
eventsource();
exact = "exact";
eventsource();
});
// Wrap form-group's buttons to next line when viewed on a small screen
$(window).on("resize",function() {
if ($(window).width() < 991) {
$(".form-group.input-group").removeClass("input-group").addClass("input-group-block");
$(".form-group.input-group-block > input").css("margin-bottom", "5px");
$(".form-group.input-group-block > .input-group-btn").removeClass("input-group-btn").addClass("btn-block text-center");
}
else {
$(".form-group.input-group-block").removeClass("input-group-block").addClass( "input-group" );
$(".form-group.input-group > input").css("margin-bottom","");
$(".form-group.input-group > .btn-block.text-center").removeClass("btn-block text-center").addClass("input-group-btn");
}
$(window).on("resize", function() {
if ($(window).width() < 991) {
$(".form-group.input-group")
.removeClass("input-group")
.addClass("input-group-block");
$(".form-group.input-group-block > input").css("margin-bottom", "5px");
$(".form-group.input-group-block > .input-group-btn")
.removeClass("input-group-btn")
.addClass("btn-block text-center");
} else {
$(".form-group.input-group-block")
.removeClass("input-group-block")
.addClass("input-group");
$(".form-group.input-group > input").css("margin-bottom", "");
$(".form-group.input-group > .btn-block.text-center")
.removeClass("btn-block text-center")
.addClass("input-group-btn");
}
});
$(document).ready(function() {
$(window).trigger("resize");
$(window).trigger("resize");
});
+208 -201
View File
@@ -1,254 +1,261 @@
/* 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. */
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
* Network-wide ad blocking via your own hardware.
*
* This file is copyright under the latest version of the EUPL.
* Please see LICENSE file for your rights under this license. */
$(function () {
$("[data-static]").on("click", function(){
var row = $(this).closest("tr");
var mac = row.find("#MAC").text();
var ip = row.find("#IP").text();
var host = row.find("#HOST").text();
$("input[name=\"AddHostname\"]").val(host);
$("input[name=\"AddIP\"]").val(ip);
$("input[name=\"AddMAC\"]").val(mac);
});
$(function() {
$("[data-static]").on("click", function() {
var row = $(this).closest("tr");
var mac = row.find("#MAC").text();
var ip = row.find("#IP").text();
var host = row.find("#HOST").text();
$('input[name="AddHostname"]').val(host);
$('input[name="AddIP"]').val(ip);
$('input[name="AddMAC"]').val(mac);
});
});
$(".confirm-poweroff").confirm({
text: "Are you sure you want to send a poweroff command to your Pi-Hole?",
title: "Confirmation required",
confirm: function() {
$("#poweroffform").submit();
},
cancel: function() {
// nothing to do
},
confirmButton: "Yes, poweroff",
cancelButton: "No, go back",
post: true,
confirmButtonClass: "btn-danger",
cancelButtonClass: "btn-success",
dialogClass: "modal-dialog modal-mg" // Bootstrap classes for mid-size modal
text: "Are you sure you want to send a poweroff command to your Pi-Hole?",
title: "Confirmation required",
confirm: function() {
$("#poweroffform").submit();
},
cancel: function() {
// nothing to do
},
confirmButton: "Yes, poweroff",
cancelButton: "No, go back",
post: true,
confirmButtonClass: "btn-danger",
cancelButtonClass: "btn-success",
dialogClass: "modal-dialog modal-mg" // Bootstrap classes for mid-size modal
});
$(".confirm-reboot").confirm({
text: "Are you sure you want to send a reboot command to your Pi-Hole?",
title: "Confirmation required",
confirm: function() {
$("#rebootform").submit();
},
cancel: function() {
// nothing to do
},
confirmButton: "Yes, reboot",
cancelButton: "No, go back",
post: true,
confirmButtonClass: "btn-danger",
cancelButtonClass: "btn-success",
dialogClass: "modal-dialog modal-mg" // Bootstrap classes for mid-size modal
text: "Are you sure you want to send a reboot command to your Pi-Hole?",
title: "Confirmation required",
confirm: function() {
$("#rebootform").submit();
},
cancel: function() {
// nothing to do
},
confirmButton: "Yes, reboot",
cancelButton: "No, go back",
post: true,
confirmButtonClass: "btn-danger",
cancelButtonClass: "btn-success",
dialogClass: "modal-dialog modal-mg" // Bootstrap classes for mid-size modal
});
$(".confirm-restartdns").confirm({
text: "Are you sure you want to send a restart command to your DNS server?",
title: "Confirmation required",
confirm: function() {
$("#restartdnsform").submit();
},
cancel: function() {
// nothing to do
},
confirmButton: "Yes, restart DNS",
cancelButton: "No, go back",
post: true,
confirmButtonClass: "btn-danger",
cancelButtonClass: "btn-success",
dialogClass: "modal-dialog modal-mg"
text: "Are you sure you want to send a restart command to your DNS server?",
title: "Confirmation required",
confirm: function() {
$("#restartdnsform").submit();
},
cancel: function() {
// nothing to do
},
confirmButton: "Yes, restart DNS",
cancelButton: "No, go back",
post: true,
confirmButtonClass: "btn-danger",
cancelButtonClass: "btn-success",
dialogClass: "modal-dialog modal-mg"
});
$(".confirm-flushlogs").confirm({
text: "Are you sure you want to flush your logs?",
title: "Confirmation required",
confirm: function() {
$("#flushlogsform").submit();
},
cancel: function() {
// nothing to do
},
confirmButton: "Yes, flush logs",
cancelButton: "No, go back",
post: true,
confirmButtonClass: "btn-danger",
cancelButtonClass: "btn-success",
dialogClass: "modal-dialog modal-mg"
text: "Are you sure you want to flush your logs?",
title: "Confirmation required",
confirm: function() {
$("#flushlogsform").submit();
},
cancel: function() {
// nothing to do
},
confirmButton: "Yes, flush logs",
cancelButton: "No, go back",
post: true,
confirmButtonClass: "btn-danger",
cancelButtonClass: "btn-success",
dialogClass: "modal-dialog modal-mg"
});
$(".confirm-flusharp").confirm({
text: "Are you sure you want to flush your network table?",
title: "Confirmation required",
confirm: function() {
$("#flusharpform").submit();
},
cancel: function() {
// nothing to do
},
confirmButton: "Yes, flush my network table",
cancelButton: "No, go back",
post: true,
confirmButtonClass: "btn-warning",
cancelButtonClass: "btn-success",
dialogClass: "modal-dialog modal-mg"
text: "Are you sure you want to flush your network table?",
title: "Confirmation required",
confirm: function() {
$("#flusharpform").submit();
},
cancel: function() {
// nothing to do
},
confirmButton: "Yes, flush my network table",
cancelButton: "No, go back",
post: true,
confirmButtonClass: "btn-warning",
cancelButtonClass: "btn-success",
dialogClass: "modal-dialog modal-mg"
});
$(".confirm-disablelogging-noflush").confirm({
text: "Are you sure you want to disable logging?",
title: "Confirmation required",
confirm: function() {
$("#disablelogsform-noflush").submit();
},
cancel: function() {
// nothing to do
},
confirmButton: "Yes, disable logs",
cancelButton: "No, go back",
post: true,
confirmButtonClass: "btn-warning",
cancelButtonClass: "btn-success",
dialogClass: "modal-dialog modal-mg"
text: "Are you sure you want to disable logging?",
title: "Confirmation required",
confirm: function() {
$("#disablelogsform-noflush").submit();
},
cancel: function() {
// nothing to do
},
confirmButton: "Yes, disable logs",
cancelButton: "No, go back",
post: true,
confirmButtonClass: "btn-warning",
cancelButtonClass: "btn-success",
dialogClass: "modal-dialog modal-mg"
});
$(".api-token").confirm({
text: "Make sure that nobody else can scan this code around you. They will have full access to the API without having to know the password. Note that the generation of the QR code will take some time.",
title: "Confirmation required",
confirm: function() {
window.open("scripts/pi-hole/php/api_token.php");
},
cancel: function() {
// nothing to do
},
confirmButton: "Yes, show API token",
cancelButton: "No, go back",
post: true,
confirmButtonClass: "btn-danger",
cancelButtonClass: "btn-success",
dialogClass: "modal-dialog modal-mg"
text:
"Make sure that nobody else can scan this code around you. They will have full access to the API without having to know the password. Note that the generation of the QR code will take some time.",
title: "Confirmation required",
confirm: function() {
window.open("scripts/pi-hole/php/api_token.php");
},
cancel: function() {
// nothing to do
},
confirmButton: "Yes, show API token",
cancelButton: "No, go back",
post: true,
confirmButtonClass: "btn-danger",
cancelButtonClass: "btn-success",
dialogClass: "modal-dialog modal-mg"
});
$("#DHCPchk").click(function() {
$("input.DHCPgroup").prop("disabled", !this.checked);
$("#dhcpnotice").prop("hidden", !this.checked).addClass("lookatme");
$("input.DHCPgroup").prop("disabled", !this.checked);
$("#dhcpnotice")
.prop("hidden", !this.checked)
.addClass("lookatme");
});
function loadCacheInfo()
{
$.getJSON("api.php?getCacheInfo", function(data) {
if("FTLnotrunning" in data)
{
return;
}
function loadCacheInfo() {
$.getJSON("api.php?getCacheInfo", function(data) {
if ("FTLnotrunning" in data) {
return;
}
// Fill table with obtained values
$("#cache-size").text(parseInt(data.cacheinfo["cache-size"]));
$("#cache-inserted").text(parseInt(data.cacheinfo["cache-inserted"]));
// Fill table with obtained values
$("#cache-size").text(parseInt(data.cacheinfo["cache-size"]));
$("#cache-inserted").text(parseInt(data.cacheinfo["cache-inserted"]));
// Highlight early cache removals when present
var cachelivefreed = parseInt(data.cacheinfo["cache-live-freed"]);
$("#cache-live-freed").text(cachelivefreed);
if(cachelivefreed > 0)
{
$("#cache-live-freed").parent("tr").addClass("lookatme");
}
else
{
$("#cache-live-freed").parent("tr").removeClass("lookatme");
}
// Highlight early cache removals when present
var cachelivefreed = parseInt(data.cacheinfo["cache-live-freed"]);
$("#cache-live-freed").text(cachelivefreed);
if (cachelivefreed > 0) {
$("#cache-live-freed")
.parent("tr")
.addClass("lookatme");
} else {
$("#cache-live-freed")
.parent("tr")
.removeClass("lookatme");
}
// Update cache info every 10 seconds
setTimeout(loadCacheInfo, 10000);
});
// Update cache info every 10 seconds
setTimeout(loadCacheInfo, 10000);
});
}
var leasetable, staticleasetable;
$(document).ready(function() {
if(document.getElementById("DHCPLeasesTable"))
{
leasetable = $("#DHCPLeasesTable").DataTable({
dom: "<'row'<'col-sm-12'tr>><'row'<'col-sm-6'i><'col-sm-6'f>>",
"columnDefs": [ { "bSortable": false, "orderable": false, targets: -1} ],
"paging": false,
"scrollCollapse": true,
"scrollY": "200px",
"scrollX" : true
});
}
if(document.getElementById("DHCPStaticLeasesTable"))
{
staticleasetable = $("#DHCPStaticLeasesTable").DataTable({
dom: "<'row'<'col-sm-12'tr>><'row'<'col-sm-12'i>>",
"columnDefs": [ { "bSortable": false, "orderable": false, targets: -1} ],
"paging": false,
"scrollCollapse": true,
"scrollY": "200px",
"scrollX" : true
});
}
//call draw() on each table... they don't render properly with scrollX and scrollY set... ¯\_(ツ)_/¯
$("a[data-toggle=\"tab\"]").on("shown.bs.tab", function () {
leasetable.draw();
staticleasetable.draw();
if (document.getElementById("DHCPLeasesTable")) {
leasetable = $("#DHCPLeasesTable").DataTable({
dom: "<'row'<'col-sm-12'tr>><'row'<'col-sm-6'i><'col-sm-6'f>>",
columnDefs: [{ bSortable: false, orderable: false, targets: -1 }],
paging: false,
scrollCollapse: true,
scrollY: "200px",
scrollX: true
});
}
loadCacheInfo();
if (document.getElementById("DHCPStaticLeasesTable")) {
staticleasetable = $("#DHCPStaticLeasesTable").DataTable({
dom: "<'row'<'col-sm-12'tr>><'row'<'col-sm-12'i>>",
columnDefs: [{ bSortable: false, orderable: false, targets: -1 }],
paging: false,
scrollCollapse: true,
scrollY: "200px",
scrollX: true
});
}
} );
//call draw() on each table... they don't render properly with scrollX and scrollY set... ¯\_(ツ)_/¯
$('a[data-toggle="tab"]').on("shown.bs.tab", function() {
leasetable.draw();
staticleasetable.draw();
});
loadCacheInfo();
});
// Handle hiding of alerts
$(function(){
$("[data-hide]").on("click", function(){
$(this).closest("." + $(this).attr("data-hide")).hide();
});
$(function() {
$("[data-hide]").on("click", function() {
$(this)
.closest("." + $(this).attr("data-hide"))
.hide();
});
});
// DHCP leases tooltips
$(document).ready(function(){
$("[data-toggle=\"tooltip\"]").tooltip({"html": true, container : "body"});
$(document).ready(function() {
$('[data-toggle="tooltip"]').tooltip({ html: true, container: "body" });
});
// Handle list deletion
$("button[id^='adlist-btn-']").on("click", function (e) {
var id = parseInt($(this).context.id.replace(/[^0-9.]/g, ""), 10);
e.preventDefault();
$("button[id^='adlist-btn-']").on("click", function(e) {
var id = parseInt($(this).context.id.replace(/[^0-9.]/g, ""), 10);
e.preventDefault();
var status = $("input[name=\"adlist-del-"+id+"\"]").is(":checked");
var textType = status ? "none" : "line-through";
// Check hidden delete box (or reset)
$("input[name=\"adlist-del-"+id+"\"]").prop("checked", !status);
// Untick and disable check box (or reset)
$("input[name=\"adlist-enable-"+id+"\"]").prop("checked", status).prop("disabled", !status);
// Strike through text (or reset)
$("a[id=\"adlist-text-"+id+"\"]").css("text-decoration", textType);
// Highlight that the button has to be clicked in order to make the change live
$("button[id=\"blockinglistsaveupdate\"]").addClass("btn-danger").css("font-weight", "bold");
var status = $('input[name="adlist-del-' + id + '"]').is(":checked");
var textType = status ? "none" : "line-through";
// Check hidden delete box (or reset)
$('input[name="adlist-del-' + id + '"]').prop("checked", !status);
// Untick and disable check box (or reset)
$('input[name="adlist-enable-' + id + '"]')
.prop("checked", status)
.prop("disabled", !status);
// Strike through text (or reset)
$('a[id="adlist-text-' + id + '"]').css("text-decoration", textType);
// Highlight that the button has to be clicked in order to make the change live
$('button[id="blockinglistsaveupdate"]')
.addClass("btn-danger")
.css("font-weight", "bold");
});
// Change "?tab=" parameter in URL for save and reload
$(".nav-tabs a").on("shown.bs.tab", function (e) {
var tab = e.target.hash.substring(1);
window.history.pushState("", "", "?tab=" + tab);
if(tab === "piholedhcp")
{
window.location.reload();
}
window.scrollTo(0, 0);
$(".nav-tabs a").on("shown.bs.tab", function(e) {
var tab = e.target.hash.substring(1);
window.history.pushState("", "", "?tab=" + tab);
if (tab === "piholedhcp") {
window.location.reload();
}
window.scrollTo(0, 0);
});
// Auto dismissal for info notifications
$(document).ready(function(){
var alInfo = $("#alInfo");
if(alInfo.length)
{
alInfo.delay(3000).fadeOut(2000, function() { alInfo.hide(); });
}
$(document).ready(function() {
var alInfo = $("#alInfo");
if (alInfo.length) {
alInfo.delay(3000).fadeOut(2000, function() {
alInfo.hide();
});
}
});
+31 -30
View File
@@ -1,48 +1,49 @@
/* 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. */
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
* Network-wide ad blocking via your own hardware.
*
* This file is copyright under the latest version of the EUPL.
* Please see LICENSE file for your rights under this license. */
var offset, timer, pre, scrolling = true;
var offset,
timer,
pre,
scrolling = true;
// Check every 200msec for fresh data
var interval = 200;
// Function that asks the API for new data
function reloadData(){
clearTimeout(timer);
$.getJSON("scripts/pi-hole/php/tailLog.php?FTL&offset="+offset, function (data)
{
pre.append(data.lines);
function reloadData() {
clearTimeout(timer);
$.getJSON("scripts/pi-hole/php/tailLog.php?FTL&offset=" + offset, function(data) {
pre.append(data.lines);
if(scrolling && offset !== data.offset) {
pre.scrollTop(pre[0].scrollHeight);
}
if (scrolling && offset !== data.offset) {
pre.scrollTop(pre[0].scrollHeight);
}
offset = data.offset;
});
offset = data.offset;
});
timer = setTimeout(reloadData, interval);
timer = setTimeout(reloadData, interval);
}
$(function(){
// Get offset at first loading of page
$.getJSON("scripts/pi-hole/php/tailLog.php?FTL", function (data)
{
offset = data.offset;
});
pre = $("#output");
// Trigger function that looks for new data
reloadData();
$(function() {
// Get offset at first loading of page
$.getJSON("scripts/pi-hole/php/tailLog.php?FTL", function(data) {
offset = data.offset;
});
pre = $("#output");
// Trigger function that looks for new data
reloadData();
});
$("#chk1").click(function() {
$("#chk2").prop("checked",this.checked);
scrolling = this.checked;
$("#chk2").prop("checked", this.checked);
scrolling = this.checked;
});
$("#chk2").click(function() {
$("#chk1").prop("checked",this.checked);
scrolling = this.checked;
$("#chk1").prop("checked", this.checked);
scrolling = this.checked;
});
+31 -30
View File
@@ -1,48 +1,49 @@
/* 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. */
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
* Network-wide ad blocking via your own hardware.
*
* This file is copyright under the latest version of the EUPL.
* Please see LICENSE file for your rights under this license. */
var offset, timer, pre, scrolling = true;
var offset,
timer,
pre,
scrolling = true;
// Check every 200msec for fresh data
var interval = 200;
// Function that asks the API for new data
function reloadData(){
clearTimeout(timer);
$.getJSON("scripts/pi-hole/php/tailLog.php?offset="+offset, function (data)
{
pre.append(data.lines);
function reloadData() {
clearTimeout(timer);
$.getJSON("scripts/pi-hole/php/tailLog.php?offset=" + offset, function(data) {
pre.append(data.lines);
if(scrolling && offset !== data.offset) {
pre.scrollTop(pre[0].scrollHeight);
}
if (scrolling && offset !== data.offset) {
pre.scrollTop(pre[0].scrollHeight);
}
offset = data.offset;
});
offset = data.offset;
});
timer = setTimeout(reloadData, interval);
timer = setTimeout(reloadData, interval);
}
$(function(){
// Get offset at first loading of page
$.getJSON("scripts/pi-hole/php/tailLog.php", function (data)
{
offset = data.offset;
});
pre = $("#output");
// Trigger function that looks for new data
reloadData();
$(function() {
// Get offset at first loading of page
$.getJSON("scripts/pi-hole/php/tailLog.php", function(data) {
offset = data.offset;
});
pre = $("#output");
// Trigger function that looks for new data
reloadData();
});
$("#chk1").click(function() {
$("#chk2").prop("checked",this.checked);
scrolling = this.checked;
$("#chk2").prop("checked", this.checked);
scrolling = this.checked;
});
$("#chk2").click(function() {
$("#chk1").prop("checked",this.checked);
scrolling = this.checked;
$("#chk1").prop("checked", this.checked);
scrolling = this.checked;
});