From 72057cfa26353f2260e4318fe5edb51b9c13ee7b Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Wed, 24 Jul 2019 22:14:07 +0200
Subject: [PATCH 09/80] Close database connection at the end of a table
recovery.
Signed-off-by: DL6ER
---
scripts/pi-hole/php/teleporter.php | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/scripts/pi-hole/php/teleporter.php b/scripts/pi-hole/php/teleporter.php
index 65e7f490..2d377c83 100644
--- a/scripts/pi-hole/php/teleporter.php
+++ b/scripts/pi-hole/php/teleporter.php
@@ -59,7 +59,7 @@ function archive_add_table($name, $table)
*/
function archive_restore_table($file, $table, $flush=false)
{
- global $archive, $db;
+ global $db;
$json_string = file_get_contents($file);
// Return early if we cannot extract the JSON string
@@ -128,12 +128,17 @@ function archive_restore_table($file, $table, $flush=false)
$stmt->bindValue(":comment", $row["comment"], $type);
}
- $stmt->execute();
- $stmt->reset();
- $stmt->clear();
- $num++;
+ if($stmt->execute() && $stmt->reset() && $stmt->clear())
+ $num++;
+ else
+ {
+ $stmt->close();
+ return $num;
+ }
}
+ // Close database connection and return number or processed rows
+ $stmt->close();
return $num;
}
From 3cfb2267571f83f9f0b8525673e29cb36d628a40 Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Wed, 24 Jul 2019 22:14:48 +0200
Subject: [PATCH 10/80] Reload only ONCE not after EACH imported file.
Signed-off-by: DL6ER
---
scripts/pi-hole/php/teleporter.php | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/scripts/pi-hole/php/teleporter.php b/scripts/pi-hole/php/teleporter.php
index 2d377c83..ddc4e7c4 100644
--- a/scripts/pi-hole/php/teleporter.php
+++ b/scripts/pi-hole/php/teleporter.php
@@ -316,11 +316,11 @@ if(isset($_POST["action"]))
echo "Processed domain_audit (".$num." entries) \n";
$importedsomething = true;
}
+ }
- if($importedsomething)
- {
- exec("sudo pihole restartdns");
- }
+ if($importedsomething)
+ {
+ exec("sudo pihole restartdns");
}
unlink($fullfilename);
From eac87f139f480641c2e96755f64bea7e007f52de Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Wed, 24 Jul 2019 22:19:15 +0200
Subject: [PATCH 11/80] pihole-FTL only needs to be reloaded not restarted when
the lists have been updated. This is much faster than a hard restart.
Signed-off-by: DL6ER
---
scripts/pi-hole/php/teleporter.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/pi-hole/php/teleporter.php b/scripts/pi-hole/php/teleporter.php
index ddc4e7c4..db5688df 100644
--- a/scripts/pi-hole/php/teleporter.php
+++ b/scripts/pi-hole/php/teleporter.php
@@ -320,7 +320,7 @@ if(isset($_POST["action"]))
if($importedsomething)
{
- exec("sudo pihole restartdns");
+ exec("sudo pihole restartdns reload");
}
unlink($fullfilename);
From 13f07f9d87c681eccd9ee884a11ffba795cd2a89 Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Wed, 24 Jul 2019 23:15:19 +0200
Subject: [PATCH 12/80] Switch the teleporter to only interact with gravity.db
directly. This avoids any need for escaping regexes and just seems to be the
right thing to do. Ensure that we flush a table only once (in case multiple
files add to the same table).
Signed-off-by: DL6ER
---
scripts/pi-hole/js/list.js | 6 +-
scripts/pi-hole/php/teleporter.php | 152 ++++++++++++++++++-----------
2 files changed, 96 insertions(+), 62 deletions(-)
diff --git a/scripts/pi-hole/js/list.js b/scripts/pi-hole/js/list.js
index a5bcafd9..adb7c642 100644
--- a/scripts/pi-hole/js/list.js
+++ b/scripts/pi-hole/js/list.js
@@ -82,11 +82,11 @@ function refresh(fade) {
if(data.length > 0)
{
- $("#h3-exact").show();
+ $("#h3-exact").fadeIn(100);
}
if(data2.length > 0)
{
- $("#h3-regex").show();
+ $("#h3-regex").fadeIn(100);
}
data.forEach(function (entry, index)
@@ -132,7 +132,7 @@ function sub(index, entry, arg) {
domain.remove();
if($(list+" li").length < 1)
{
- $(heading).hide();
+ $(heading).fadeOut(100);
}
},
error: function(jqXHR, exception) {
diff --git a/scripts/pi-hole/php/teleporter.php b/scripts/pi-hole/php/teleporter.php
index db5688df..6d4083f8 100644
--- a/scripts/pi-hole/php/teleporter.php
+++ b/scripts/pi-hole/php/teleporter.php
@@ -17,6 +17,8 @@ if (php_sapi_name() !== "cli") {
$db = SQLite3_connect(getGravityDBFilename(), SQLITE3_OPEN_READWRITE);
+$flushed_tables = array();
+
function archive_add_file($path,$name,$subdir="")
{
global $archive;
@@ -59,7 +61,7 @@ function archive_add_table($name, $table)
*/
function archive_restore_table($file, $table, $flush=false)
{
- global $db;
+ global $db, $flushed_tables;
$json_string = file_get_contents($file);
// Return early if we cannot extract the JSON string
@@ -71,9 +73,12 @@ function archive_restore_table($file, $table, $flush=false)
if(is_null($contents))
return 0;
- // Flush table if requested
- if($flush)
+ // Flush table if requested, only flush each table once
+ if($flush && !in_array($table, $flushed_tables))
+ {
$db->exec("DELETE FROM ".$table);
+ array_push($flushed_tables, $table);
+ }
// Prepare field name for domain/address depending on the table we restore to
if($table === "adlist")
@@ -142,6 +147,80 @@ function archive_restore_table($file, $table, $flush=false)
return $num;
}
+/**
+ * Create table rows from an uploaded archive file
+ *
+ * @param $file object The file of the file in the archive to import
+ * @param $table string The target table
+ * @param $flush boolean Whether to flush the table before importing the archived data
+ */
+function archive_insert_into_table($file, $table, $flush=false, $wildcardstyle=false)
+{
+ global $db, $flushed_tables;
+
+ $rows = array_filter(explode("\n",file_get_contents($file)));
+ // Return early if we cannot extract the lines in the file
+ if(is_null($rows))
+ return 0;
+
+ // Flush table if requested, only flush each table once
+ if($flush && !in_array($table, $flushed_tables))
+ {
+ $db->exec("DELETE FROM ".$table);
+ array_push($flushed_tables, $table);
+ }
+
+ // Prepare field name for domain/address depending on the table we restore to
+ if($table === "adlist")
+ {
+ $sql = "INSERT OR IGNORE INTO adlist";
+ $sql .= " (address) VALUES (:address);";
+ }
+ else
+ {
+ $sql = "INSERT OR IGNORE INTO ".$table;
+ $sql .= " (domain) VALUES (:domain);";
+ }
+
+ // Prepare SQLite statememt
+ $stmt = $db->prepare($sql);
+
+ // Return early if we prepare the SQLite statement
+ if(!$stmt)
+ {
+ echo "Failed to prepare statement for ".$table." table.";
+ echo $sql;
+ return 0;
+ }
+
+ // Loop over rows and inject the lines into the database
+ $num = 0;
+ foreach($rows as $row)
+ {
+ if($wildcardstyle)
+ $line = "(\\.|^)".str_replace(".","\\.",$row)."$";
+ else
+ $line = $row;
+
+ if($table === "adlist")
+ $stmt->bindValue(":address", $line, SQLITE3_TEXT);
+ else
+ $stmt->bindValue(":domain", $line, SQLITE3_TEXT);
+
+ if($stmt->execute() && $stmt->reset() && $stmt->clear())
+ $num++;
+ else
+ {
+ $stmt->close();
+ return $num;
+ }
+ }
+
+ // Close database connection and return number or processed rows
+ $stmt->close();
+ return $num;
+}
+
function archive_add_directory($path,$subdir="")
{
if($dir = opendir($path))
@@ -157,40 +236,6 @@ function archive_add_directory($path,$subdir="")
}
}
-function limit_length(&$item, $key)
-{
- // limit max length for a domain entry to 253 chars
- // return only a part of the string if it is longer
- $item = substr($item, 0, 253);
-}
-
-function process_file($contents,$check=True)
-{
- $domains = array_filter(explode("\n",$contents));
-
- // Walk array and apply a max string length
- // function to every member of the array of domains
- array_walk($domains, "limit_length");
-
- // Check validity of domains (don't do it for regex filters)
- if($check)
- {
- check_domains($domains);
- }
-
- return $domains;
-}
-
-function check_domains($domains)
-{
- foreach($domains as $domain)
- {
- if(!is_valid_domain_name($domain)){
- die(htmlspecialchars($domain).' is not a valid domain');
- }
- }
-}
-
if(isset($_POST["action"]))
{
if($_FILES["zip_file"]["name"] && $_POST["action"] == "in")
@@ -230,49 +275,38 @@ if(isset($_POST["action"]))
{
if(isset($_POST["blacklist"]) && $file->getFilename() === "blacklist.txt")
{
- $blacklist = process_file(file_get_contents($file));
- echo "Processing blacklist.txt (".count($blacklist)." entries) \n";
- exec("sudo pihole -b -nr --nuke");
- exec("sudo pihole -b -q -nr ".implode(" ", $blacklist));
+ $num = archive_insert_into_table($file, "blacklist", $flushtables);
+ echo "Processed blacklist (exact) (".$num." entries) \n";
$importedsomething = true;
}
if(isset($_POST["whitelist"]) && $file->getFilename() === "whitelist.txt")
{
- $whitelist = process_file(file_get_contents($file));
- echo "Processing whitelist.txt (".count($whitelist)." entries) \n";
- exec("sudo pihole -w -nr --nuke");
- exec("sudo pihole -w -q -nr ".implode(" ", $whitelist));
+ $num = archive_insert_into_table($file, "whitelist", $flushtables);
+ echo "Processed whitelist (exact) (".$num." entries) \n";
$importedsomething = true;
}
if(isset($_POST["regexlist"]) && $file->getFilename() === "regex.list")
{
- $regexlist = process_file(file_get_contents($file),false);
- echo "Processing regex.list (".count($regexlist)." entries) \n";
-
- $escapedRegexlist = array_map("escapeshellcmd", $regexlist);
- exec("sudo pihole --regex -nr --nuke");
- exec("sudo pihole --regex -q -nr ".implode(" ", $escapedRegexlist));
+ $num = archive_insert_into_table($file, "regex_blacklist", $flushtables);
+ echo "Processed blacklist (regex) (".$num." entries) \n";
$importedsomething = true;
}
// Also try to import legacy wildcard list if found
if(isset($_POST["regexlist"]) && $file->getFilename() === "wildcardblocking.txt")
{
- $wildlist = process_file(file_get_contents($file));
- echo "Processing wildcardblocking.txt (".count($wildlist)." entries) \n";
- exec("sudo pihole --wild -nr --nuke");
- exec("sudo pihole --wild -q -nr ".implode(" ", $wildlist));
+ $num = archive_insert_into_table($file, "regex_blacklist", $flushtables, true);
+ echo "Processed blacklist (regex, wildcard style) (".$num." entries) \n";
$importedsomething = true;
}
if(isset($_POST["auditlog"]) && $file->getFilename() === "auditlog.list")
{
- $auditlog = process_file(file_get_contents($file));
- echo "Processing auditlog.list (".count($auditlog)." entries) \n";
- exec("sudo pihole -a clearaudit");
- exec("sudo pihole -a audit ".implode(" ",$auditlog));
+ $num = archive_insert_into_table($file, "domain_audit", $flushtables);
+ echo "Processed blacklist (regex) (".$num." entries) \n";
+ $importedsomething = true;
}
if(isset($_POST["blacklist"]) && $file->getFilename() === "blacklist.exact.json")
From 8991605f0468157a22dac722c82a1e500250cea3 Mon Sep 17 00:00:00 2001
From: denny0754
Date: Mon, 15 Jul 2019 16:33:05 +0100
Subject: [PATCH 13/80] Fixed Issue#983
---
scripts/pi-hole/js/queries.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/scripts/pi-hole/js/queries.js b/scripts/pi-hole/js/queries.js
index 95276cad..2b6ca3db 100644
--- a/scripts/pi-hole/js/queries.js
+++ b/scripts/pi-hole/js/queries.js
@@ -183,7 +183,7 @@ $(document).ready(function() {
blocked = true;
color = "red";
fieldtext = "Blocked (gravity)";
- buttontext = "";
+ buttontext = "";
break;
case "2":
blocked = false;
@@ -201,13 +201,13 @@ $(document).ready(function() {
blocked = true;
color = "red";
fieldtext = "Blocked (regex/wildcard)";
- buttontext = "" ;
+ buttontext = "" ;
break;
case "5":
blocked = true;
color = "red";
fieldtext = "Blocked (blacklist)";
- buttontext = "" ;
+ buttontext = "" ;
break;
case "6":
blocked = true;
From bc7aef744cdd4f557c8b6bc65dbb06ac31d1c417 Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Mon, 5 Aug 2019 21:13:53 +0200
Subject: [PATCH 14/80] "pihole --whiteregex" has been renamed to "pihole
--white-regex". Similar for "--whitewild" -> "--white-wild".
Signed-off-by: DL6ER
---
scripts/pi-hole/php/add.php | 4 ++--
scripts/pi-hole/php/sub.php | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/scripts/pi-hole/php/add.php b/scripts/pi-hole/php/add.php
index 9f3c1b0a..663320f2 100644
--- a/scripts/pi-hole/php/add.php
+++ b/scripts/pi-hole/php/add.php
@@ -48,13 +48,13 @@ switch($type) {
echo shell_exec("sudo pihole --regex --web ".$domains);
break;
case "white_regex":
- echo shell_exec("sudo pihole --whiteregex --web ".$domains);
+ echo shell_exec("sudo pihole --white-regex --web ".$domains);
break;
case "black_wild":
echo shell_exec("sudo pihole --wild --web ".$domains);
break;
case "white_wild":
- echo shell_exec("sudo pihole --whitewild --web ".$domains);
+ echo shell_exec("sudo pihole --white-wild --web ".$domains);
break;
case "audit":
echo shell_exec("sudo pihole -a audit ".$domains);
diff --git a/scripts/pi-hole/php/sub.php b/scripts/pi-hole/php/sub.php
index 4eae79c7..570520a8 100644
--- a/scripts/pi-hole/php/sub.php
+++ b/scripts/pi-hole/php/sub.php
@@ -36,7 +36,7 @@ switch($type) {
echo shell_exec("sudo pihole --regex -q -d ".$domain);
break;
case "white_regex":
- echo shell_exec("sudo pihole --whiteregex -q -d ".$domain);
+ echo shell_exec("sudo pihole --white-regex -q -d ".$domain);
break;
}
From c9f5c9500a30e7cc6cd6faef4c4550338600a8ee Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Mon, 5 Aug 2019 21:48:31 +0200
Subject: [PATCH 15/80] Directly modify gravity tables from the lists pages.
Signed-off-by: DL6ER
---
list.php | 2 +-
scripts/pi-hole/js/list.js | 37 ++++++++----
scripts/pi-hole/php/add.php | 115 +++++++++++++++++++++++++-----------
scripts/pi-hole/php/sub.php | 76 +++++++++++++++++-------
4 files changed, 160 insertions(+), 70 deletions(-)
diff --git a/list.php b/list.php
index d6ea04b9..21db22cc 100644
--- a/list.php
+++ b/list.php
@@ -49,7 +49,7 @@ function getFullName() {
- Success! The list will refresh.
+ Success!
diff --git a/scripts/pi-hole/js/list.js b/scripts/pi-hole/js/list.js
index adb7c642..599dfb22 100644
--- a/scripts/pi-hole/js/list.js
+++ b/scripts/pi-hole/js/list.js
@@ -119,6 +119,11 @@ function sub(index, entry, arg) {
heading = "#h3-regex";
locallistType = arg;
}
+ var alInfo = $("#alInfo");
+ var alSuccess = $("#alSuccess");
+ var alFailure = $("#alFailure");
+ var alWarning = $("#alWarning");
+
var domain = $(list+" #"+index);
domain.hide("highlight");
$.ajax({
@@ -126,14 +131,29 @@ function sub(index, entry, arg) {
method: "post",
data: {"domain":entry, "list":locallistType, "token":token},
success: function(response) {
- if(response.length !== 0){
- return;
- }
+ 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();
+ alSuccess.delay(1000).fadeOut(2000, function() {
+ alSuccess.hide();
+ });
+ alInfo.delay(1000).fadeOut(2000, function() {
+ alInfo.hide();
+ });
domain.remove();
if($(list+" li").length < 1)
{
$(heading).fadeOut(100);
}
+ }
},
error: function(jqXHR, exception) {
alert("Failed to remove the domain!");
@@ -163,16 +183,7 @@ function add(type) {
method: "post",
data: {"domain":domain.val().trim(), "list":type, "token":token},
success: function(response) {
- if (response.indexOf(" already exists in ") !== -1) {
- alWarning.show();
- warn.html(response);
- alWarning.delay(8000).fadeOut(2000, function() {
- alWarning.hide();
- });
- alInfo.delay(8000).fadeOut(2000, function() {
- alInfo.hide();
- });
- } else if (response.indexOf("DONE") === -1) {
+ if (response.indexOf("Success") === -1) {
alFailure.show();
err.html(response);
alFailure.delay(8000).fadeOut(2000, function() {
diff --git a/scripts/pi-hole/php/add.php b/scripts/pi-hole/php/add.php
index 663320f2..ecec95dc 100644
--- a/scripts/pi-hole/php/add.php
+++ b/scripts/pi-hole/php/add.php
@@ -18,47 +18,90 @@ if (empty($api)) {
// Don't check if the added item is a valid domain for regex expressions. Regex
// filters are validated by FTL on import and skipped if invalid
-if($type !== "regex") {
+$check_lists = ["white","black","audit"];
+if(in_array($list, $check_lists)) {
check_domain();
}
// Escape shell metacharacters
-$domains = escapeshellcmd($_POST['domain']);
+$domains = explode(",",$_POST['domain']);
-switch($type) {
- case "white":
- if(!isset($_POST["auditlog"]))
- echo shell_exec("sudo pihole -w --web ".$domains);
- else
- {
- echo shell_exec("sudo pihole -w --web ".$domains);
- echo shell_exec("sudo pihole -a audit ".$domains);
- }
- break;
- case "black":
- if(!isset($_POST["auditlog"]))
- echo shell_exec("sudo pihole -b --web ".$domains);
- else
- {
- echo shell_exec("sudo pihole -b --web ".$domains);
- echo shell_exec("sudo pihole -a audit ".$domains);
- }
- break;
- case "black_regex":
- echo shell_exec("sudo pihole --regex --web ".$domains);
- break;
- case "white_regex":
- echo shell_exec("sudo pihole --white-regex --web ".$domains);
- break;
- case "black_wild":
- echo shell_exec("sudo pihole --wild --web ".$domains);
- break;
- case "white_wild":
- echo shell_exec("sudo pihole --white-wild --web ".$domains);
- break;
- case "audit":
- echo shell_exec("sudo pihole -a audit ".$domains);
- break;
+require_once("func.php");
+
+require("database.php");
+$GRAVITYDB = getGravityDBFilename();
+$db = SQLite3_connect($GRAVITYDB, SQLITE3_OPEN_READWRITE);
+
+function add_to_table($table, $domains, $wildcardstyle=false)
+{
+ global $db;
+ // Prepare SQLite statememt
+ $stmt = $db->prepare("INSERT OR IGNORE INTO ".$table." (domain) VALUES (:domain);");
+
+ // Return early if we prepare the SQLite statement
+ if(!$stmt)
+ {
+ echo "Failed to prepare statement for ".$table." table.";
+ echo $sql;
+ return 0;
+ }
+
+ // Loop over domains and inject the lines into the database
+ $num = 0;
+ foreach($domains as $row)
+ {
+ if($wildcardstyle)
+ $line = "(\\.|^)".str_replace(".","\\.",$row)."$";
+ else
+ $line = $row;
+
+ $stmt->bindValue(":domain", $line, SQLITE3_TEXT);
+
+ if($stmt->execute() && $stmt->reset() && $stmt->clear())
+ $num++;
+ else
+ {
+ $stmt->close();
+ return "Error, added: ".$num."\n";
+ }
+ }
+
+ // Close database connection and return number or processed rows
+ $stmt->close();
+ return "Success, added: ".$num."\n";
}
+switch($type) {
+ case "white":
+ if(isset($_POST["auditlog"]))
+ echo add_to_table("domain_audit", $domains);
+ echo add_to_table("whitelist", $domains);
+ break;
+
+ case "black":
+ if(isset($_POST["auditlog"]))
+ echo add_to_table("domain_audit", $domains);
+ echo add_to_table("blacklist", $domains);
+ break;
+
+ case "black_regex":
+ echo add_to_table("regex_blacklist", $domains);
+ break;
+
+ case "white_regex":
+ echo add_to_table("regex_whitelist", $domains);
+ break;
+
+ case "black_wild":
+ echo add_to_table("regex_blacklist", $domains, true);
+ break;
+
+ case "white_wild":
+ echo add_to_table("regex_whitelist", $domains, true);
+ break;
+
+ case "audit":
+ echo add_to_table("domain_audit", $domains);
+ break;
+}
?>
diff --git a/scripts/pi-hole/php/sub.php b/scripts/pi-hole/php/sub.php
index 570520a8..25d75a31 100644
--- a/scripts/pi-hole/php/sub.php
+++ b/scripts/pi-hole/php/sub.php
@@ -16,28 +16,64 @@ if (empty($api)) {
list_verify($type);
}
-// Don't check if the added item is a valid domain for regex expressions.
-// Regex filters are validated by FTL on import and skipped if invalid
-if($type !== "black_regex" && $type !== "white_regex") {
- check_domain();
-}
-
// Escape shell metacharacters
-$domain = escapeshellcmd($_POST['domain']);
+$domains = explode(",",$_POST['domain']);
+
+require_once("func.php");
+
+require("database.php");
+$GRAVITYDB = getGravityDBFilename();
+$db = SQLite3_connect($GRAVITYDB, SQLITE3_OPEN_READWRITE);
+
+function remove_from_table($table, $domains)
+{
+ global $db;
+ // Prepare SQLite statememt
+ $stmt = $db->prepare("DELETE FROM ".$table." WHERE domain = :domain;");
+
+ // Return early if we prepare the SQLite statement
+ if(!$stmt)
+ {
+ echo "Failed to prepare statement for ".$table." table.";
+ echo $sql;
+ return 0;
+ }
+
+ // Loop over domains and remove the lines from the database
+ $num = 0;
+ foreach($domains as $row)
+ {
+ $stmt->bindValue(":domain", $row, SQLITE3_TEXT);
+
+ if($stmt->execute() && $stmt->reset() && $stmt->clear())
+ $num++;
+ else
+ {
+ $stmt->close();
+ return "Error, removed: ".$num."\n";
+ }
+ }
+
+ // Close database connection and return number or processed rows
+ $stmt->close();
+ return "Success, removed: ".$num."\n";
+}
switch($type) {
- case "white":
- echo shell_exec("sudo pihole -w -q -d ".$domain);
- break;
- case "black":
- echo shell_exec("sudo pihole -b -q -d ".$domain);
- break;
- case "black_regex":
- echo shell_exec("sudo pihole --regex -q -d ".$domain);
- break;
- case "white_regex":
- echo shell_exec("sudo pihole --white-regex -q -d ".$domain);
- break;
-}
+ case "white":
+ echo remove_from_table("whitelist", $domains);
+ break;
+ case "black":
+ echo remove_from_table("blacklist", $domains);
+ break;
+
+ case "black_regex":
+ echo remove_from_table("regex_blacklist", $domains);
+ break;
+
+ case "white_regex":
+ echo remove_from_table("regex_whitelist", $domains);
+ break;
+}
?>
From c53832c9d0755c31747b57bb9bf734a179e864d3 Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Mon, 5 Aug 2019 22:06:53 +0200
Subject: [PATCH 16/80] Review comments
Signed-off-by: DL6ER
---
scripts/pi-hole/php/teleporter.php | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/scripts/pi-hole/php/teleporter.php b/scripts/pi-hole/php/teleporter.php
index 6d4083f8..1c903e25 100644
--- a/scripts/pi-hole/php/teleporter.php
+++ b/scripts/pi-hole/php/teleporter.php
@@ -38,7 +38,7 @@ function archive_add_table($name, $table)
$results = $db->query("SELECT * FROM $table");
- // Return early without creating a file if th
+ // Return early without creating a file if the
// requested table cannot be accessed
if(is_null($results))
return;
@@ -55,9 +55,10 @@ function archive_add_table($name, $table)
/**
* Restore the contents of a table from an uploaded archive
*
- * @param $file object The file of the file in the archive to restore the table from
+ * @param $file object The file in the archive to restore the table from
* @param $table string The table to import
* @param $flush boolean Whether to flush the table before importing the archived data
+ * @return integer Number of restored rows
*/
function archive_restore_table($file, $table, $flush=false)
{
@@ -103,7 +104,7 @@ function archive_restore_table($file, $table, $flush=false)
// Prepare SQLite statememt
$stmt = $db->prepare($sql);
- // Return early if we prepare the SQLite statement
+ // Return early if we fail to prepare the SQLite statement
if(!$stmt)
{
echo "Failed to prepare statement for ".$table." table.";
@@ -153,6 +154,8 @@ function archive_restore_table($file, $table, $flush=false)
* @param $file object The file of the file in the archive to import
* @param $table string The target table
* @param $flush boolean Whether to flush the table before importing the archived data
+ * @param $wildcardstyle boolean Whether to format the input domains in legacy wildcard notation
+ * @return integer Number of processed rows from the imported file
*/
function archive_insert_into_table($file, $table, $flush=false, $wildcardstyle=false)
{
From 464e55461d5915e91492b2e08934397cfb912124 Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Tue, 6 Aug 2019 20:29:32 +0200
Subject: [PATCH 17/80] Fix indentation.
Signed-off-by: DL6ER
---
scripts/pi-hole/js/list.js | 84 +++++++++++++++++++-------------------
1 file changed, 42 insertions(+), 42 deletions(-)
diff --git a/scripts/pi-hole/js/list.js b/scripts/pi-hole/js/list.js
index 599dfb22..7b9e54a8 100644
--- a/scripts/pi-hole/js/list.js
+++ b/scripts/pi-hole/js/list.js
@@ -131,29 +131,29 @@ function sub(index, entry, arg) {
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();
- alSuccess.delay(1000).fadeOut(2000, function() {
- alSuccess.hide();
- });
- alInfo.delay(1000).fadeOut(2000, function() {
- alInfo.hide();
- });
- domain.remove();
- if($(list+" li").length < 1)
- {
- $(heading).fadeOut(100);
+ 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();
+ alSuccess.delay(1000).fadeOut(2000, function() {
+ alSuccess.hide();
+ });
+ alInfo.delay(1000).fadeOut(2000, function() {
+ alInfo.hide();
+ });
+ domain.remove();
+ if($(list+" li").length < 1)
+ {
+ $(heading).fadeOut(100);
+ }
}
- }
},
error: function(jqXHR, exception) {
alert("Failed to remove the domain!");
@@ -183,26 +183,26 @@ function add(type) {
method: "post",
data: {"domain":domain.val().trim(), "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();
- alSuccess.delay(1000).fadeOut(2000, function() {
- alSuccess.hide();
- });
- alInfo.delay(1000).fadeOut(2000, function() {
- alInfo.hide();
- });
- domain.val("");
- refresh(true);
- }
+ 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();
+ alSuccess.delay(1000).fadeOut(2000, function() {
+ alSuccess.hide();
+ });
+ alInfo.delay(1000).fadeOut(2000, function() {
+ alInfo.hide();
+ });
+ domain.val("");
+ refresh(true);
+ }
},
error: function(jqXHR, exception) {
alFailure.show();
From 6ca35b0b763dfca0bc9af656362148bf6ca6f18f Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Tue, 6 Aug 2019 20:32:49 +0200
Subject: [PATCH 18/80] Update comment and change require() to require_once().
Signed-off-by: DL6ER
---
scripts/pi-hole/php/add.php | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/scripts/pi-hole/php/add.php b/scripts/pi-hole/php/add.php
index ecec95dc..9b3e3ce8 100644
--- a/scripts/pi-hole/php/add.php
+++ b/scripts/pi-hole/php/add.php
@@ -16,8 +16,8 @@ if (empty($api)) {
list_verify($type);
}
-// Don't check if the added item is a valid domain for regex expressions. Regex
-// filters are validated by FTL on import and skipped if invalid
+// Only check domains we add to the exact lists.
+// Regex are validated by FTL during import
$check_lists = ["white","black","audit"];
if(in_array($list, $check_lists)) {
check_domain();
@@ -27,8 +27,7 @@ if(in_array($list, $check_lists)) {
$domains = explode(",",$_POST['domain']);
require_once("func.php");
-
-require("database.php");
+require_once("database.php");
$GRAVITYDB = getGravityDBFilename();
$db = SQLite3_connect($GRAVITYDB, SQLITE3_OPEN_READWRITE);
From 5b9ccecd11f04f8d58a3a8d4e89673591d6e463a Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Tue, 6 Aug 2019 20:40:20 +0200
Subject: [PATCH 19/80] Limit max length for a domain entry to 253 chars when
importing from teleoprter archives, skip longer entries without importing
them.
Signed-off-by: DL6ER
---
scripts/pi-hole/php/teleporter.php | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/scripts/pi-hole/php/teleporter.php b/scripts/pi-hole/php/teleporter.php
index 1c903e25..13838d6f 100644
--- a/scripts/pi-hole/php/teleporter.php
+++ b/scripts/pi-hole/php/teleporter.php
@@ -116,13 +116,18 @@ function archive_restore_table($file, $table, $flush=false)
$num = 0;
foreach($contents as $row)
{
+ if($table === "adlist")
+ $line = "address";
+ else
+ $line = "domain";
+
+ // Limit max length for a domain entry to 253 chars
+ if(strlen($row[$line]) > 253)
+ continue;
+
$stmt->bindValue(":id", $row["id"], SQLITE3_INTEGER);
$stmt->bindValue(":date_added", $row["date_added"], SQLITE3_INTEGER);
-
- if($table === "adlist")
- $stmt->bindValue(":address", $row["address"], SQLITE3_TEXT);
- else
- $stmt->bindValue(":domain", $row["domain"], SQLITE3_TEXT);
+ $stmt->bindValue(":".$line, $row[$line], SQLITE3_TEXT);
if($table !== "domain_audit")
{
@@ -205,6 +210,10 @@ function archive_insert_into_table($file, $table, $flush=false, $wildcardstyle=f
else
$line = $row;
+ // Limit max length for a domain entry to 253 chars
+ if(strlen($line) > 253)
+ continue;
+
if($table === "adlist")
$stmt->bindValue(":address", $line, SQLITE3_TEXT);
else
From 98e5f21373736c7b38a78fb9a226af39f24668fc Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Tue, 6 Aug 2019 20:45:56 +0200
Subject: [PATCH 20/80] Move add_to_table() to database.php.
Signed-off-by: DL6ER
---
scripts/pi-hole/php/add.php | 67 +++++++-------------------------
scripts/pi-hole/php/database.php | 45 +++++++++++++++++++++
2 files changed, 59 insertions(+), 53 deletions(-)
diff --git a/scripts/pi-hole/php/add.php b/scripts/pi-hole/php/add.php
index 9b3e3ce8..0888b65c 100644
--- a/scripts/pi-hole/php/add.php
+++ b/scripts/pi-hole/php/add.php
@@ -8,12 +8,12 @@
require_once('auth.php');
-$type = $_POST['list'];
+$list = $_POST['list'];
// Perform all of the authentication for list editing
// when NOT invoked and authenticated from API
if (empty($api)) {
- list_verify($type);
+ list_verify($list);
}
// Only check domains we add to the exact lists.
@@ -23,84 +23,45 @@ if(in_array($list, $check_lists)) {
check_domain();
}
-// Escape shell metacharacters
-$domains = explode(",",$_POST['domain']);
+// Split individual domains into array
+$domains = explode(" ",$_POST['domain']);
require_once("func.php");
require_once("database.php");
$GRAVITYDB = getGravityDBFilename();
$db = SQLite3_connect($GRAVITYDB, SQLITE3_OPEN_READWRITE);
-function add_to_table($table, $domains, $wildcardstyle=false)
-{
- global $db;
- // Prepare SQLite statememt
- $stmt = $db->prepare("INSERT OR IGNORE INTO ".$table." (domain) VALUES (:domain);");
-
- // Return early if we prepare the SQLite statement
- if(!$stmt)
- {
- echo "Failed to prepare statement for ".$table." table.";
- echo $sql;
- return 0;
- }
-
- // Loop over domains and inject the lines into the database
- $num = 0;
- foreach($domains as $row)
- {
- if($wildcardstyle)
- $line = "(\\.|^)".str_replace(".","\\.",$row)."$";
- else
- $line = $row;
-
- $stmt->bindValue(":domain", $line, SQLITE3_TEXT);
-
- if($stmt->execute() && $stmt->reset() && $stmt->clear())
- $num++;
- else
- {
- $stmt->close();
- return "Error, added: ".$num."\n";
- }
- }
-
- // Close database connection and return number or processed rows
- $stmt->close();
- return "Success, added: ".$num."\n";
-}
-
-switch($type) {
+switch($list) {
case "white":
if(isset($_POST["auditlog"]))
- echo add_to_table("domain_audit", $domains);
- echo add_to_table("whitelist", $domains);
+ echo add_to_table($db, "domain_audit", $domains);
+ echo add_to_table($db, "whitelist", $domains);
break;
case "black":
if(isset($_POST["auditlog"]))
- echo add_to_table("domain_audit", $domains);
- echo add_to_table("blacklist", $domains);
+ echo add_to_table($db, "domain_audit", $domains);
+ echo add_to_table($db, "blacklist", $domains);
break;
case "black_regex":
- echo add_to_table("regex_blacklist", $domains);
+ echo add_to_table($db, "regex_blacklist", $domains);
break;
case "white_regex":
- echo add_to_table("regex_whitelist", $domains);
+ echo add_to_table($db, "regex_whitelist", $domains);
break;
case "black_wild":
- echo add_to_table("regex_blacklist", $domains, true);
+ echo add_to_table($db, "regex_blacklist", $domains, true);
break;
case "white_wild":
- echo add_to_table("regex_whitelist", $domains, true);
+ echo add_to_table($db, "regex_whitelist", $domains, true);
break;
case "audit":
- echo add_to_table("domain_audit", $domains);
+ echo add_to_table($db, "domain_audit", $domains);
break;
}
?>
diff --git a/scripts/pi-hole/php/database.php b/scripts/pi-hole/php/database.php
index 3a453677..08f767ba 100644
--- a/scripts/pi-hole/php/database.php
+++ b/scripts/pi-hole/php/database.php
@@ -54,4 +54,49 @@ function SQLite3_connect($filename, $mode=SQLITE3_OPEN_READONLY)
}
return $db;
}
+
+
+/**
+ * Add domains to a given table
+ *
+ * @param $db object The SQLite3 database connection object
+ * @param $table string The target table
+ * @param $domains array Array of domains (strings) to be added to the table
+ * @param $wildcardstyle boolean Whether to format the input domains in legacy wildcard notation
+ * @return string Success/error and number of processed domains
+ */
+function add_to_table($db, $table, $domains, $wildcardstyle=false)
+{
+ // Prepare SQLite statememt
+ $stmt = $db->prepare("INSERT OR IGNORE INTO ".$table." (domain) VALUES (:domain);");
+
+ // Return early if we prepare the SQLite statement
+ if(!$stmt)
+ {
+ echo "Failed to prepare statement for ".$table." table.";
+ return "Error, added: 0\n";
+ }
+
+ // Loop over domains and inject the lines into the database
+ $num = 0;
+ foreach($domains as $domain)
+ {
+ if($wildcardstyle)
+ $domain = "(\\.|^)".str_replace(".","\\.",$domain)."$";
+
+ $stmt->bindValue(":domain", $domain, SQLITE3_TEXT);
+
+ if($stmt->execute() && $stmt->reset())
+ $num++;
+ else
+ {
+ $stmt->close();
+ return "Error, added: ".$num."\n";
+ }
+ }
+
+ // Close database connection and return number of processed rows
+ $stmt->close();
+ return "Success, added: ".$num."\n";
+}
?>
From 424fe7636ba4ebd69b0b647f723e4966b15a7e33 Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Tue, 6 Aug 2019 22:02:36 +0200
Subject: [PATCH 21/80] Call "sudo pihole restartdns reload" after having added
or removed domains to notify FTL of the updated lists.
Signed-off-by: DL6ER
---
scripts/pi-hole/php/add.php | 8 +++++
scripts/pi-hole/php/database.php | 41 ++++++++++++++++++++++++++
scripts/pi-hole/php/sub.php | 50 ++++++++------------------------
3 files changed, 61 insertions(+), 38 deletions(-)
diff --git a/scripts/pi-hole/php/add.php b/scripts/pi-hole/php/add.php
index 0888b65c..ba42bba2 100644
--- a/scripts/pi-hole/php/add.php
+++ b/scripts/pi-hole/php/add.php
@@ -63,5 +63,13 @@ switch($list) {
case "audit":
echo add_to_table($db, "domain_audit", $domains);
break;
+
+ default:
+ echo "Invalid list!";
+ exit();
+ break;
}
+
+// Reload lists in pihole-FTL after having removed something
+echo shell_exec("sudo pihole restartdns reload");
?>
diff --git a/scripts/pi-hole/php/database.php b/scripts/pi-hole/php/database.php
index 08f767ba..878f6df8 100644
--- a/scripts/pi-hole/php/database.php
+++ b/scripts/pi-hole/php/database.php
@@ -99,4 +99,45 @@ function add_to_table($db, $table, $domains, $wildcardstyle=false)
$stmt->close();
return "Success, added: ".$num."\n";
}
+
+/**
+ * Remove domains from a given table
+ *
+ * @param $db object The SQLite3 database connection object
+ * @param $table string The target table
+ * @param $domains array Array of domains (strings) to be removed from the table
+ * @return string Success/error and number of processed domains
+ */
+function remove_from_table($db, $table, $domains)
+{
+ // Prepare SQLite statememt
+ $stmt = $db->prepare("DELETE FROM ".$table." WHERE domain = :domain;");
+
+ // Return early if we prepare the SQLite statement
+ if(!$stmt)
+ {
+ echo "Failed to prepare statement for ".$table." table.";
+ return "Error, added: 0\n";
+ }
+
+ // Loop over domains and remove the lines from the database
+ $num = 0;
+ foreach($domains as $domain)
+ {
+ $stmt->bindValue(":domain", $domain, SQLITE3_TEXT);
+
+ if($stmt->execute() && $stmt->reset())
+ $num++;
+ else
+ {
+ $stmt->close();
+ return "Error, removed: ".$num."\n";
+ }
+ }
+
+ // Close database connection and return number or processed rows
+ $stmt->close();
+ return "Success, removed: ".$num."\n";
+}
+
?>
diff --git a/scripts/pi-hole/php/sub.php b/scripts/pi-hole/php/sub.php
index 25d75a31..a2e69822 100644
--- a/scripts/pi-hole/php/sub.php
+++ b/scripts/pi-hole/php/sub.php
@@ -25,55 +25,29 @@ require("database.php");
$GRAVITYDB = getGravityDBFilename();
$db = SQLite3_connect($GRAVITYDB, SQLITE3_OPEN_READWRITE);
-function remove_from_table($table, $domains)
-{
- global $db;
- // Prepare SQLite statememt
- $stmt = $db->prepare("DELETE FROM ".$table." WHERE domain = :domain;");
-
- // Return early if we prepare the SQLite statement
- if(!$stmt)
- {
- echo "Failed to prepare statement for ".$table." table.";
- echo $sql;
- return 0;
- }
-
- // Loop over domains and remove the lines from the database
- $num = 0;
- foreach($domains as $row)
- {
- $stmt->bindValue(":domain", $row, SQLITE3_TEXT);
-
- if($stmt->execute() && $stmt->reset() && $stmt->clear())
- $num++;
- else
- {
- $stmt->close();
- return "Error, removed: ".$num."\n";
- }
- }
-
- // Close database connection and return number or processed rows
- $stmt->close();
- return "Success, removed: ".$num."\n";
-}
-
switch($type) {
case "white":
- echo remove_from_table("whitelist", $domains);
+ echo remove_from_table($db, "whitelist", $domains);
break;
case "black":
- echo remove_from_table("blacklist", $domains);
+ echo remove_from_table($db, "blacklist", $domains);
break;
case "black_regex":
- echo remove_from_table("regex_blacklist", $domains);
+ echo remove_from_table($db, "regex_blacklist", $domains);
break;
case "white_regex":
- echo remove_from_table("regex_whitelist", $domains);
+ echo remove_from_table($db, "regex_whitelist", $domains);
+ break;
+
+ default:
+ echo "Invalid list!";
+ exit();
break;
}
+
+// Reload lists in pihole-FTL after having removed something
+echo shell_exec("sudo pihole restartdns reload");
?>
From 7fdafb2dcceb9101900f7cec634eed259e897a65 Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Tue, 6 Aug 2019 22:06:44 +0200
Subject: [PATCH 22/80] Update comment and code in sub.php
Signed-off-by: DL6ER
---
scripts/pi-hole/php/sub.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/scripts/pi-hole/php/sub.php b/scripts/pi-hole/php/sub.php
index a2e69822..8d967707 100644
--- a/scripts/pi-hole/php/sub.php
+++ b/scripts/pi-hole/php/sub.php
@@ -16,8 +16,8 @@ if (empty($api)) {
list_verify($type);
}
-// Escape shell metacharacters
-$domains = explode(",",$_POST['domain']);
+// Split individual domains into array
+$domains = explode(" ",$_POST['domain']);
require_once("func.php");
From 7807f12d65dc8be967eb1e850c9af4e9602fdcbd Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Tue, 6 Aug 2019 22:08:18 +0200
Subject: [PATCH 23/80] Fix codefactor complaints.
Signed-off-by: DL6ER
---
scripts/pi-hole/php/add.php | 4 +---
scripts/pi-hole/php/sub.php | 4 +---
2 files changed, 2 insertions(+), 6 deletions(-)
diff --git a/scripts/pi-hole/php/add.php b/scripts/pi-hole/php/add.php
index ba42bba2..58f68e76 100644
--- a/scripts/pi-hole/php/add.php
+++ b/scripts/pi-hole/php/add.php
@@ -65,9 +65,7 @@ switch($list) {
break;
default:
- echo "Invalid list!";
- exit();
- break;
+ die("Invalid list!");
}
// Reload lists in pihole-FTL after having removed something
diff --git a/scripts/pi-hole/php/sub.php b/scripts/pi-hole/php/sub.php
index 8d967707..fba80af4 100644
--- a/scripts/pi-hole/php/sub.php
+++ b/scripts/pi-hole/php/sub.php
@@ -43,9 +43,7 @@ switch($type) {
break;
default:
- echo "Invalid list!";
- exit();
- break;
+ die("Invalid list!");
}
// Reload lists in pihole-FTL after having removed something
From 71fc7a47919c727a1885d037fc87afd463cfd68a Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Wed, 7 Aug 2019 21:23:29 +0200
Subject: [PATCH 24/80] Use preg_split() instead of explode() for better space
handling. Skip empty domains in add_to_table() and remove_from_table().
Signed-off-by: DL6ER
---
scripts/pi-hole/php/add.php | 2 +-
scripts/pi-hole/php/database.php | 8 ++++++++
scripts/pi-hole/php/sub.php | 2 +-
3 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/scripts/pi-hole/php/add.php b/scripts/pi-hole/php/add.php
index 58f68e76..94a17345 100644
--- a/scripts/pi-hole/php/add.php
+++ b/scripts/pi-hole/php/add.php
@@ -24,7 +24,7 @@ if(in_array($list, $check_lists)) {
}
// Split individual domains into array
-$domains = explode(" ",$_POST['domain']);
+$domains = preg_split('/\s+/', $_POST['domain']);
require_once("func.php");
require_once("database.php");
diff --git a/scripts/pi-hole/php/database.php b/scripts/pi-hole/php/database.php
index 878f6df8..3304bec5 100644
--- a/scripts/pi-hole/php/database.php
+++ b/scripts/pi-hole/php/database.php
@@ -81,6 +81,10 @@ function add_to_table($db, $table, $domains, $wildcardstyle=false)
$num = 0;
foreach($domains as $domain)
{
+ // Skip empty domains
+ if(strlen($domain) == 0)
+ continue;
+
if($wildcardstyle)
$domain = "(\\.|^)".str_replace(".","\\.",$domain)."$";
@@ -124,6 +128,10 @@ function remove_from_table($db, $table, $domains)
$num = 0;
foreach($domains as $domain)
{
+ // Skip empty domains
+ if(strlen($domain) == 0)
+ continue;
+
$stmt->bindValue(":domain", $domain, SQLITE3_TEXT);
if($stmt->execute() && $stmt->reset())
diff --git a/scripts/pi-hole/php/sub.php b/scripts/pi-hole/php/sub.php
index fba80af4..0030b4dd 100644
--- a/scripts/pi-hole/php/sub.php
+++ b/scripts/pi-hole/php/sub.php
@@ -17,7 +17,7 @@ if (empty($api)) {
}
// Split individual domains into array
-$domains = explode(" ",$_POST['domain']);
+$domains = preg_split('/\s+/', $_POST['domain']);
require_once("func.php");
From d568b49fb14f25d319e702294272dcb17cb21630 Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Wed, 7 Aug 2019 21:24:05 +0200
Subject: [PATCH 25/80] Add busy timeout so adding/removing domains does not
immediately fail in case the database is busy.
Signed-off-by: DL6ER
---
scripts/pi-hole/php/database.php | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/scripts/pi-hole/php/database.php b/scripts/pi-hole/php/database.php
index 3304bec5..588aeed6 100644
--- a/scripts/pi-hole/php/database.php
+++ b/scripts/pi-hole/php/database.php
@@ -52,6 +52,10 @@ function SQLite3_connect($filename, $mode=SQLITE3_OPEN_READONLY)
{
die("Error connecting to database");
}
+
+ // Add busy timeout so methods don't fail immediately when, e.g., FTL is currently reading from the DB
+ $db->busyTimeout(5000);
+
return $db;
}
From 07af532b0910bf9d089b5b5ed036751a93ca7841 Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Wed, 7 Aug 2019 21:32:49 +0200
Subject: [PATCH 26/80] Review comments
Signed-off-by: DL6ER
---
scripts/pi-hole/php/add.php | 2 +-
scripts/pi-hole/php/database.php | 8 ++++----
scripts/pi-hole/php/teleporter.php | 32 ++++++++++--------------------
3 files changed, 16 insertions(+), 26 deletions(-)
diff --git a/scripts/pi-hole/php/add.php b/scripts/pi-hole/php/add.php
index 94a17345..ff306a68 100644
--- a/scripts/pi-hole/php/add.php
+++ b/scripts/pi-hole/php/add.php
@@ -68,6 +68,6 @@ switch($list) {
die("Invalid list!");
}
-// Reload lists in pihole-FTL after having removed something
+// Reload lists in pihole-FTL after having added something
echo shell_exec("sudo pihole restartdns reload");
?>
diff --git a/scripts/pi-hole/php/database.php b/scripts/pi-hole/php/database.php
index 588aeed6..44b37b31 100644
--- a/scripts/pi-hole/php/database.php
+++ b/scripts/pi-hole/php/database.php
@@ -74,7 +74,7 @@ function add_to_table($db, $table, $domains, $wildcardstyle=false)
// Prepare SQLite statememt
$stmt = $db->prepare("INSERT OR IGNORE INTO ".$table." (domain) VALUES (:domain);");
- // Return early if we prepare the SQLite statement
+ // Return early if we failed to prepare the SQLite statement
if(!$stmt)
{
echo "Failed to prepare statement for ".$table." table.";
@@ -103,7 +103,7 @@ function add_to_table($db, $table, $domains, $wildcardstyle=false)
}
}
- // Close database connection and return number of processed rows
+ // Close prepared statement and return number of processed rows
$stmt->close();
return "Success, added: ".$num."\n";
}
@@ -121,7 +121,7 @@ function remove_from_table($db, $table, $domains)
// Prepare SQLite statememt
$stmt = $db->prepare("DELETE FROM ".$table." WHERE domain = :domain;");
- // Return early if we prepare the SQLite statement
+ // Return early if we failed to prepare the SQLite statement
if(!$stmt)
{
echo "Failed to prepare statement for ".$table." table.";
@@ -147,7 +147,7 @@ function remove_from_table($db, $table, $domains)
}
}
- // Close database connection and return number or processed rows
+ // Close prepared statement and return number or processed rows
$stmt->close();
return "Success, removed: ".$num."\n";
}
diff --git a/scripts/pi-hole/php/teleporter.php b/scripts/pi-hole/php/teleporter.php
index 13838d6f..f88f02db 100644
--- a/scripts/pi-hole/php/teleporter.php
+++ b/scripts/pi-hole/php/teleporter.php
@@ -87,18 +87,21 @@ function archive_restore_table($file, $table, $flush=false)
$sql = "INSERT OR IGNORE INTO adlist";
$sql .= " (id,address,enabled,date_added,comment)";
$sql .= " VALUES (:id,:address,:enabled,:date_added,:comment);";
+ $field = "address";
}
elseif($table === "domain_audit")
{
$sql = "INSERT OR IGNORE INTO domain_audit";
$sql .= " (id,domain,date_added)";
$sql .= " VALUES (:id,:domain,:date_added);";
+ $field = "domain";
}
else
{
$sql = "INSERT OR IGNORE INTO ".$table;
$sql .= " (id,domain,enabled,date_added,comment)";
$sql .= " VALUES (:id,:domain,:enabled,:date_added,:comment);";
+ $field = "domain";
}
// Prepare SQLite statememt
@@ -112,22 +115,17 @@ function archive_restore_table($file, $table, $flush=false)
return 0;
}
- // Loop over rows and inject the lines into the database
+ // Loop over rows and inject the entries into the database
$num = 0;
foreach($contents as $row)
{
- if($table === "adlist")
- $line = "address";
- else
- $line = "domain";
-
// Limit max length for a domain entry to 253 chars
- if(strlen($row[$line]) > 253)
+ if(strlen($row[$field]) > 253)
continue;
$stmt->bindValue(":id", $row["id"], SQLITE3_INTEGER);
$stmt->bindValue(":date_added", $row["date_added"], SQLITE3_INTEGER);
- $stmt->bindValue(":".$line, $row[$line], SQLITE3_TEXT);
+ $stmt->bindValue(":".$field, $row[$field], SQLITE3_TEXT);
if($table !== "domain_audit")
{
@@ -180,17 +178,12 @@ function archive_insert_into_table($file, $table, $flush=false, $wildcardstyle=f
// Prepare field name for domain/address depending on the table we restore to
if($table === "adlist")
- {
- $sql = "INSERT OR IGNORE INTO adlist";
- $sql .= " (address) VALUES (:address);";
- }
+ $field = "address";
else
- {
- $sql = "INSERT OR IGNORE INTO ".$table;
- $sql .= " (domain) VALUES (:domain);";
- }
+ $field = "domain";
- // Prepare SQLite statememt
+ // Prepare SQLite statement
+ $sql = "INSERT OR IGNORE INTO ".$table." (".$field.") VALUES (:".$field.");";
$stmt = $db->prepare($sql);
// Return early if we prepare the SQLite statement
@@ -214,10 +207,7 @@ function archive_insert_into_table($file, $table, $flush=false, $wildcardstyle=f
if(strlen($line) > 253)
continue;
- if($table === "adlist")
- $stmt->bindValue(":address", $line, SQLITE3_TEXT);
- else
- $stmt->bindValue(":domain", $line, SQLITE3_TEXT);
+ $stmt->bindValue(":".$field, $line, SQLITE3_TEXT);
if($stmt->execute() && $stmt->reset() && $stmt->clear())
$num++;
From 838516e558545763f4592733ef092163ea7eccf5 Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Wed, 7 Aug 2019 21:44:01 +0200
Subject: [PATCH 27/80] Ensure preg does not output empty array elements.
Signed-off-by: DL6ER
---
scripts/pi-hole/php/add.php | 2 +-
scripts/pi-hole/php/database.php | 8 --------
scripts/pi-hole/php/sub.php | 2 +-
3 files changed, 2 insertions(+), 10 deletions(-)
diff --git a/scripts/pi-hole/php/add.php b/scripts/pi-hole/php/add.php
index ff306a68..f09da424 100644
--- a/scripts/pi-hole/php/add.php
+++ b/scripts/pi-hole/php/add.php
@@ -24,7 +24,7 @@ if(in_array($list, $check_lists)) {
}
// Split individual domains into array
-$domains = preg_split('/\s+/', $_POST['domain']);
+$domains = preg_split('/\s+/', $_POST['domain'], -1, PREG_SPLIT_NO_EMPTY);
require_once("func.php");
require_once("database.php");
diff --git a/scripts/pi-hole/php/database.php b/scripts/pi-hole/php/database.php
index 44b37b31..bc986b69 100644
--- a/scripts/pi-hole/php/database.php
+++ b/scripts/pi-hole/php/database.php
@@ -85,10 +85,6 @@ function add_to_table($db, $table, $domains, $wildcardstyle=false)
$num = 0;
foreach($domains as $domain)
{
- // Skip empty domains
- if(strlen($domain) == 0)
- continue;
-
if($wildcardstyle)
$domain = "(\\.|^)".str_replace(".","\\.",$domain)."$";
@@ -132,10 +128,6 @@ function remove_from_table($db, $table, $domains)
$num = 0;
foreach($domains as $domain)
{
- // Skip empty domains
- if(strlen($domain) == 0)
- continue;
-
$stmt->bindValue(":domain", $domain, SQLITE3_TEXT);
if($stmt->execute() && $stmt->reset())
diff --git a/scripts/pi-hole/php/sub.php b/scripts/pi-hole/php/sub.php
index 0030b4dd..b324177f 100644
--- a/scripts/pi-hole/php/sub.php
+++ b/scripts/pi-hole/php/sub.php
@@ -17,7 +17,7 @@ if (empty($api)) {
}
// Split individual domains into array
-$domains = preg_split('/\s+/', $_POST['domain']);
+$domains = preg_split('/\s+/', $_POST['domain'], -1, PREG_SPLIT_NO_EMPTY);
require_once("func.php");
From 3770556732fbbb927ffc3bb338f166e56ff0836d Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Wed, 7 Aug 2019 21:49:51 +0200
Subject: [PATCH 28/80] Use database.php:add_to_table() in
teleporter.php:archive_insert_into_table().
Signed-off-by: DL6ER
---
scripts/pi-hole/php/database.php | 36 ++++++++++++++++-----
scripts/pi-hole/php/teleporter.php | 51 +++---------------------------
2 files changed, 32 insertions(+), 55 deletions(-)
diff --git a/scripts/pi-hole/php/database.php b/scripts/pi-hole/php/database.php
index bc986b69..d600e977 100644
--- a/scripts/pi-hole/php/database.php
+++ b/scripts/pi-hole/php/database.php
@@ -67,9 +67,10 @@ function SQLite3_connect($filename, $mode=SQLITE3_OPEN_READONLY)
* @param $table string The target table
* @param $domains array Array of domains (strings) to be added to the table
* @param $wildcardstyle boolean Whether to format the input domains in legacy wildcard notation
+ * @param $returnnum boolean Whether to return an integer or a string
* @return string Success/error and number of processed domains
*/
-function add_to_table($db, $table, $domains, $wildcardstyle=false)
+function add_to_table($db, $table, $domains, $wildcardstyle=false, $returnnum=false)
{
// Prepare SQLite statememt
$stmt = $db->prepare("INSERT OR IGNORE INTO ".$table." (domain) VALUES (:domain);");
@@ -78,7 +79,10 @@ function add_to_table($db, $table, $domains, $wildcardstyle=false)
if(!$stmt)
{
echo "Failed to prepare statement for ".$table." table.";
- return "Error, added: 0\n";
+ if($returnnum)
+ return 0;
+ else
+ return "Error, added: 0\n";
}
// Loop over domains and inject the lines into the database
@@ -95,13 +99,19 @@ function add_to_table($db, $table, $domains, $wildcardstyle=false)
else
{
$stmt->close();
- return "Error, added: ".$num."\n";
+ if($returnnum)
+ return $num;
+ else
+ return "Error, added: ".$num."\n";
}
}
// Close prepared statement and return number of processed rows
$stmt->close();
- return "Success, added: ".$num."\n";
+ if($returnnum)
+ return $num;
+ else
+ return "Success, added: ".$num."\n";
}
/**
@@ -110,9 +120,10 @@ function add_to_table($db, $table, $domains, $wildcardstyle=false)
* @param $db object The SQLite3 database connection object
* @param $table string The target table
* @param $domains array Array of domains (strings) to be removed from the table
+ * @param $returnnum boolean Whether to return an integer or a string
* @return string Success/error and number of processed domains
*/
-function remove_from_table($db, $table, $domains)
+function remove_from_table($db, $table, $domains, $returnnum=false)
{
// Prepare SQLite statememt
$stmt = $db->prepare("DELETE FROM ".$table." WHERE domain = :domain;");
@@ -121,7 +132,10 @@ function remove_from_table($db, $table, $domains)
if(!$stmt)
{
echo "Failed to prepare statement for ".$table." table.";
- return "Error, added: 0\n";
+ if($returnnum)
+ return 0;
+ else
+ return "Error, added: 0\n";
}
// Loop over domains and remove the lines from the database
@@ -135,13 +149,19 @@ function remove_from_table($db, $table, $domains)
else
{
$stmt->close();
- return "Error, removed: ".$num."\n";
+ if($returnnum)
+ return $num;
+ else
+ return "Error, removed: ".$num."\n";
}
}
// Close prepared statement and return number or processed rows
$stmt->close();
- return "Success, removed: ".$num."\n";
+ if($returnnum)
+ return $num;
+ else
+ return "Success, removed: ".$num."\n";
}
?>
diff --git a/scripts/pi-hole/php/teleporter.php b/scripts/pi-hole/php/teleporter.php
index f88f02db..8e140bce 100644
--- a/scripts/pi-hole/php/teleporter.php
+++ b/scripts/pi-hole/php/teleporter.php
@@ -164,9 +164,9 @@ function archive_insert_into_table($file, $table, $flush=false, $wildcardstyle=f
{
global $db, $flushed_tables;
- $rows = array_filter(explode("\n",file_get_contents($file)));
+ $domains = array_filter(explode("\n",file_get_contents($file)));
// Return early if we cannot extract the lines in the file
- if(is_null($rows))
+ if(is_null($domains))
return 0;
// Flush table if requested, only flush each table once
@@ -176,51 +176,8 @@ function archive_insert_into_table($file, $table, $flush=false, $wildcardstyle=f
array_push($flushed_tables, $table);
}
- // Prepare field name for domain/address depending on the table we restore to
- if($table === "adlist")
- $field = "address";
- else
- $field = "domain";
-
- // Prepare SQLite statement
- $sql = "INSERT OR IGNORE INTO ".$table." (".$field.") VALUES (:".$field.");";
- $stmt = $db->prepare($sql);
-
- // Return early if we prepare the SQLite statement
- if(!$stmt)
- {
- echo "Failed to prepare statement for ".$table." table.";
- echo $sql;
- return 0;
- }
-
- // Loop over rows and inject the lines into the database
- $num = 0;
- foreach($rows as $row)
- {
- if($wildcardstyle)
- $line = "(\\.|^)".str_replace(".","\\.",$row)."$";
- else
- $line = $row;
-
- // Limit max length for a domain entry to 253 chars
- if(strlen($line) > 253)
- continue;
-
- $stmt->bindValue(":".$field, $line, SQLITE3_TEXT);
-
- if($stmt->execute() && $stmt->reset() && $stmt->clear())
- $num++;
- else
- {
- $stmt->close();
- return $num;
- }
- }
-
- // Close database connection and return number or processed rows
- $stmt->close();
- return $num;
+ // Add domains to requested table
+ return add_to_table($db, $table, $domains, $wildcardstyle, true);
}
function archive_add_directory($path,$subdir="")
From 586224fde21cba3879cf6759c93e1a99f760f4fa Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Wed, 7 Aug 2019 21:57:59 +0200
Subject: [PATCH 29/80] Replace PREG_SPLIT_NO_EMPTY by using trim().
Signed-off-by: DL6ER
---
scripts/pi-hole/php/add.php | 2 +-
scripts/pi-hole/php/sub.php | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/scripts/pi-hole/php/add.php b/scripts/pi-hole/php/add.php
index f09da424..e733ef2b 100644
--- a/scripts/pi-hole/php/add.php
+++ b/scripts/pi-hole/php/add.php
@@ -24,7 +24,7 @@ if(in_array($list, $check_lists)) {
}
// Split individual domains into array
-$domains = preg_split('/\s+/', $_POST['domain'], -1, PREG_SPLIT_NO_EMPTY);
+$domains = preg_split('/\s+/', trim($_POST['domain']));
require_once("func.php");
require_once("database.php");
diff --git a/scripts/pi-hole/php/sub.php b/scripts/pi-hole/php/sub.php
index b324177f..4eb5c3c6 100644
--- a/scripts/pi-hole/php/sub.php
+++ b/scripts/pi-hole/php/sub.php
@@ -17,7 +17,7 @@ if (empty($api)) {
}
// Split individual domains into array
-$domains = preg_split('/\s+/', $_POST['domain'], -1, PREG_SPLIT_NO_EMPTY);
+$domains = preg_split('/\s+/', trim($_POST['domain']));
require_once("func.php");
From 965f2083a68e08e5845e2a258d6465e037f57f84 Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Wed, 7 Aug 2019 22:20:00 +0200
Subject: [PATCH 30/80] Remove special handling for audited domains and just
add them separately to both lists.
Signed-off-by: DL6ER
---
scripts/pi-hole/js/auditlog.js | 4 +++-
scripts/pi-hole/php/add.php | 4 ----
scripts/pi-hole/php/database.php | 12 ++++++------
3 files changed, 9 insertions(+), 11 deletions(-)
diff --git a/scripts/pi-hole/js/auditlog.js b/scripts/pi-hole/js/auditlog.js
index 52790602..7fe5e021 100644
--- a/scripts/pi-hole/js/auditlog.js
+++ b/scripts/pi-hole/js/auditlog.js
@@ -78,7 +78,7 @@ function add(domain,list) {
$.ajax({
url: "scripts/pi-hole/php/add.php",
method: "post",
- data: {"domain":domain, "list":list, "token":token, "auditlog":1}
+ data: {"domain":domain, "list":list, "token":token}
});
}
@@ -91,6 +91,7 @@ $(document).ready(function() {
var url = ($(this).parents("tr"))[0].innerText.split(" ")[0];
if($(this).context.innerText === " Blacklist")
{
+ add(url,"audit");
add(url,"black");
$("#gravityBtn").prop("disabled", false);
}
@@ -104,6 +105,7 @@ $(document).ready(function() {
var url = ($(this).parents("tr"))[0].innerText.split(" ")[0].split(" ")[0];
if($(this).context.innerText === " Whitelist")
{
+ add(url,"audit");
add(url,"white");
$("#gravityBtn").prop("disabled", false);
}
diff --git a/scripts/pi-hole/php/add.php b/scripts/pi-hole/php/add.php
index e733ef2b..895df011 100644
--- a/scripts/pi-hole/php/add.php
+++ b/scripts/pi-hole/php/add.php
@@ -33,14 +33,10 @@ $db = SQLite3_connect($GRAVITYDB, SQLITE3_OPEN_READWRITE);
switch($list) {
case "white":
- if(isset($_POST["auditlog"]))
- echo add_to_table($db, "domain_audit", $domains);
echo add_to_table($db, "whitelist", $domains);
break;
case "black":
- if(isset($_POST["auditlog"]))
- echo add_to_table($db, "domain_audit", $domains);
echo add_to_table($db, "blacklist", $domains);
break;
diff --git a/scripts/pi-hole/php/database.php b/scripts/pi-hole/php/database.php
index d600e977..319a3260 100644
--- a/scripts/pi-hole/php/database.php
+++ b/scripts/pi-hole/php/database.php
@@ -82,7 +82,7 @@ function add_to_table($db, $table, $domains, $wildcardstyle=false, $returnnum=fa
if($returnnum)
return 0;
else
- return "Error, added: 0\n";
+ return "Error, added: 0";
}
// Loop over domains and inject the lines into the database
@@ -102,7 +102,7 @@ function add_to_table($db, $table, $domains, $wildcardstyle=false, $returnnum=fa
if($returnnum)
return $num;
else
- return "Error, added: ".$num."\n";
+ return "Error, added: ".$num;
}
}
@@ -111,7 +111,7 @@ function add_to_table($db, $table, $domains, $wildcardstyle=false, $returnnum=fa
if($returnnum)
return $num;
else
- return "Success, added: ".$num."\n";
+ return "Success, added: ".$num;
}
/**
@@ -135,7 +135,7 @@ function remove_from_table($db, $table, $domains, $returnnum=false)
if($returnnum)
return 0;
else
- return "Error, added: 0\n";
+ return "Error, added: 0";
}
// Loop over domains and remove the lines from the database
@@ -152,7 +152,7 @@ function remove_from_table($db, $table, $domains, $returnnum=false)
if($returnnum)
return $num;
else
- return "Error, removed: ".$num."\n";
+ return "Error, removed: ".$num;
}
}
@@ -161,7 +161,7 @@ function remove_from_table($db, $table, $domains, $returnnum=false)
if($returnnum)
return $num;
else
- return "Success, removed: ".$num."\n";
+ return "Success, removed: ".$num;
}
?>
From e66d0c4a740bca0e6ab2182e0a2f92e44964accb Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Wed, 7 Aug 2019 22:25:17 +0200
Subject: [PATCH 31/80] Limit maximum length of each domain to 253 characters.
We should document this somewhere if power users want to add insanely long
regex filters, they will have to do this by directly interacting with the
database.
Signed-off-by: DL6ER
---
scripts/pi-hole/php/database.php | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/scripts/pi-hole/php/database.php b/scripts/pi-hole/php/database.php
index 319a3260..d3ac258b 100644
--- a/scripts/pi-hole/php/database.php
+++ b/scripts/pi-hole/php/database.php
@@ -89,6 +89,10 @@ function add_to_table($db, $table, $domains, $wildcardstyle=false, $returnnum=fa
$num = 0;
foreach($domains as $domain)
{
+ // Limit max length for a domain entry to 253 chars
+ if(strlen($domain) > 253)
+ continue;
+
if($wildcardstyle)
$domain = "(\\.|^)".str_replace(".","\\.",$domain)."$";
From 9f25f34398ec32f9328b76a43ef20fb11d396c5f Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Tue, 20 Aug 2019 14:07:34 +0200
Subject: [PATCH 32/80] Add TEMPERATURELIMIT setting in setupVars.conf for
setting the level beyond which we show the temperature icon in red on the
dashboard.
Signed-off-by: DL6ER
---
scripts/pi-hole/php/header.php | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/scripts/pi-hole/php/header.php b/scripts/pi-hole/php/header.php
index e070bc81..ca94d496 100644
--- a/scripts/pi-hole/php/header.php
+++ b/scripts/pi-hole/php/header.php
@@ -60,6 +60,15 @@
{
$temperatureunit = $_POST["tempunit"];
}
+ // Get user-defined temperature limit if set
+ if(isset($setupVars['TEMPERATURELIMIT']))
+ {
+ $temperaturelimit = intval($setupVars['TEMPERATURELIMIT']);
+ }
+ else
+ {
+ $temperaturelimit = 60;
+ }
}
else
{
@@ -339,7 +348,7 @@ if($auth) {
{
if ($celsius >= -273.15) {
echo " 60) {
+ if ($celsius > $temperaturelimit) {
echo "#FF0000";
}
else
From 693a2f4e6010a408e970b19e4bcb6b699d3f204b Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Wed, 21 Aug 2019 10:09:47 +0200
Subject: [PATCH 33/80] Change key: TEMPERATURELIMIT -> TEMPERATURE_LIMIT
Signed-off-by: DL6ER
---
scripts/pi-hole/php/header.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/scripts/pi-hole/php/header.php b/scripts/pi-hole/php/header.php
index ca94d496..9ab0d721 100644
--- a/scripts/pi-hole/php/header.php
+++ b/scripts/pi-hole/php/header.php
@@ -61,9 +61,9 @@
$temperatureunit = $_POST["tempunit"];
}
// Get user-defined temperature limit if set
- if(isset($setupVars['TEMPERATURELIMIT']))
+ if(isset($setupVars['TEMPERATURE_LIMIT']))
{
- $temperaturelimit = intval($setupVars['TEMPERATURELIMIT']);
+ $temperaturelimit = intval($setupVars['TEMPERATURE_LIMIT']);
}
else
{
From 2cf034070427232ead5fee385960727616eed0dd Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Tue, 27 Aug 2019 16:56:22 +0200
Subject: [PATCH 34/80] Remove dead code
Signed-off-by: DL6ER
---
index.php | 60 -------------------------------------------------------
1 file changed, 60 deletions(-)
diff --git a/index.php b/index.php
index ab7ca967..f34a7171 100644
--- a/index.php
+++ b/index.php
@@ -162,66 +162,6 @@
-
-
-
-
-
-
-
-
Query Types (over time)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Upstreams (over time)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Date: Tue, 27 Aug 2019 16:56:42 +0200
Subject: [PATCH 35/80] Use correct IDs for spinners in index.js
Signed-off-by: DL6ER
---
scripts/pi-hole/js/index.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/scripts/pi-hole/js/index.js b/scripts/pi-hole/js/index.js
index 21e00bda..8058b16e 100644
--- a/scripts/pi-hole/js/index.js
+++ b/scripts/pi-hole/js/index.js
@@ -637,8 +637,8 @@ function updateSummaryData(runOnce) {
$("#temperature").html(" FTL offline");
// Show spinner
$("#queries-over-time .overlay").show();
- $("#forward-destinations .overlay").show();
- $("#query-types .overlay").show();
+ $("#forward-destinations-pie .overlay").show();
+ $("#query-types-pie .overlay").show();
$("#client-frequency .overlay").show();
$("#domain-frequency .overlay").show();
$("#ad-frequency .overlay").show();
From 4743228a863c1ec50a82a48efebd65edb9603581 Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Tue, 27 Aug 2019 17:19:05 +0200
Subject: [PATCH 36/80] Allow domains to be added by hitting return (add them
as exact domains).
Signed-off-by: DL6ER
---
scripts/pi-hole/js/list.js | 2 +-
scripts/pi-hole/php/database.php | 3 +--
settings.php | 4 ++--
3 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/scripts/pi-hole/js/list.js b/scripts/pi-hole/js/list.js
index 7b9e54a8..4de285de 100644
--- a/scripts/pi-hole/js/list.js
+++ b/scripts/pi-hole/js/list.js
@@ -223,7 +223,7 @@ function add(type) {
$(document).keypress(function(e) {
if(e.which === 13 && $("#domain").is(":focus")) {
// Enter was pressed, and the input has focus
- add("exact");
+ add(listType);
}
});
diff --git a/scripts/pi-hole/php/database.php b/scripts/pi-hole/php/database.php
index d3ac258b..b2a7bf82 100644
--- a/scripts/pi-hole/php/database.php
+++ b/scripts/pi-hole/php/database.php
@@ -78,11 +78,10 @@ function add_to_table($db, $table, $domains, $wildcardstyle=false, $returnnum=fa
// Return early if we failed to prepare the SQLite statement
if(!$stmt)
{
- echo "Failed to prepare statement for ".$table." table.";
if($returnnum)
return 0;
else
- return "Error, added: 0";
+ return "Error: Failed to prepare statement for ".$table." table.";
}
// Loop over domains and inject the lines into the database
diff --git a/settings.php b/settings.php
index 4b76daf7..59c79b5c 100644
--- a/settings.php
+++ b/settings.php
@@ -1165,7 +1165,7 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "blocklists"
- Lists of Ads
+ Blocklists
- Flush tables during import
+ Clear existing data
From d101465c62eb18d49b952e61607fce0183f203ac Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Tue, 27 Aug 2019 18:53:10 +0200
Subject: [PATCH 37/80] Pass through errors to user interface
Signed-off-by: DL6ER
---
scripts/pi-hole/php/database.php | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/scripts/pi-hole/php/database.php b/scripts/pi-hole/php/database.php
index b2a7bf82..bbdbec72 100644
--- a/scripts/pi-hole/php/database.php
+++ b/scripts/pi-hole/php/database.php
@@ -105,7 +105,7 @@ function add_to_table($db, $table, $domains, $wildcardstyle=false, $returnnum=fa
if($returnnum)
return $num;
else
- return "Error, added: ".$num;
+ return "Error: ".$db->lastErrorMsg().", added: ".$num;
}
}
@@ -134,11 +134,10 @@ function remove_from_table($db, $table, $domains, $returnnum=false)
// Return early if we failed to prepare the SQLite statement
if(!$stmt)
{
- echo "Failed to prepare statement for ".$table." table.";
if($returnnum)
return 0;
else
- return "Error, added: 0";
+ return "Error: Failed to prepare statement for ".$table." table.";
}
// Loop over domains and remove the lines from the database
@@ -155,7 +154,7 @@ function remove_from_table($db, $table, $domains, $returnnum=false)
if($returnnum)
return $num;
else
- return "Error, removed: ".$num;
+ return "Error: ".$db->lastErrorMsg().", removed: ".$num;
}
}
From fcc49e392870b270cd258e9ebd1cc4f238c51a81 Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Tue, 27 Aug 2019 19:26:51 +0200
Subject: [PATCH 38/80] Wrap addition and removal of domains in a transaction +
deliver a more detailed success message to the user specifying how many
domains are actually added (in case some already existed).
Signed-off-by: DL6ER
---
list.php | 2 +-
scripts/pi-hole/js/list.js | 7 ++++
scripts/pi-hole/php/database.php | 58 +++++++++++++++++++++++++++++---
3 files changed, 62 insertions(+), 5 deletions(-)
diff --git a/list.php b/list.php
index 21db22cc..7e9d5f62 100644
--- a/list.php
+++ b/list.php
@@ -49,7 +49,7 @@ function getFullName() {
- Success!
+
diff --git a/scripts/pi-hole/js/list.js b/scripts/pi-hole/js/list.js
index 4de285de..f0d8a045 100644
--- a/scripts/pi-hole/js/list.js
+++ b/scripts/pi-hole/js/list.js
@@ -123,6 +123,10 @@ function sub(index, entry, arg) {
var alSuccess = $("#alSuccess");
var alFailure = $("#alFailure");
var alWarning = $("#alWarning");
+ var err = $("#err");
+ var warn = $("#warn");
+ var msg = $("#success-message");
+
var domain = $(list+" #"+index);
domain.hide("highlight");
@@ -142,6 +146,7 @@ function sub(index, entry, arg) {
});
} else {
alSuccess.show();
+ msg.html(response);
alSuccess.delay(1000).fadeOut(2000, function() {
alSuccess.hide();
});
@@ -174,6 +179,7 @@ function add(type) {
var alWarning = $("#alWarning");
var err = $("#err");
var warn = $("#warn");
+ var msg = $("#success-message");
alInfo.show();
alSuccess.hide();
alFailure.hide();
@@ -194,6 +200,7 @@ function add(type) {
});
} else {
alSuccess.show();
+ msg.html(response);
alSuccess.delay(1000).fadeOut(2000, function() {
alSuccess.hide();
});
diff --git a/scripts/pi-hole/php/database.php b/scripts/pi-hole/php/database.php
index bbdbec72..89b93e02 100644
--- a/scripts/pi-hole/php/database.php
+++ b/scripts/pi-hole/php/database.php
@@ -72,6 +72,16 @@ function SQLite3_connect($filename, $mode=SQLITE3_OPEN_READONLY)
*/
function add_to_table($db, $table, $domains, $wildcardstyle=false, $returnnum=false)
{
+ // Begin transaction
+ if(!$db->exec("BEGIN TRANSACTION;"))
+ {
+ if($returnnum)
+ return 0;
+ else
+ return "Error: Unable to begin transaction for ".$table." table.";
+ }
+ $initialcount = intval($db->querySingle("SELECT COUNT(*) FROM ".$table.";"));
+
// Prepare SQLite statememt
$stmt = $db->prepare("INSERT OR IGNORE INTO ".$table." (domain) VALUES (:domain);");
@@ -105,16 +115,32 @@ function add_to_table($db, $table, $domains, $wildcardstyle=false, $returnnum=fa
if($returnnum)
return $num;
else
- return "Error: ".$db->lastErrorMsg().", added: ".$num;
+ {
+ if($num === 1)
+ $plural = "";
+ else
+ $plural = "s";
+ return "Error: ".$db->lastErrorMsg().", added ".$num." domain".$plural;
+ }
}
}
// Close prepared statement and return number of processed rows
$stmt->close();
+ $db->exec("COMMIT;");
+
if($returnnum)
return $num;
else
- return "Success, added: ".$num;
+ {
+ $finalcount = intval($db->querySingle("SELECT COUNT(*) FROM ".$table.";"));
+ $modified = $finalcount - $initialcount;
+ if($num === 1)
+ $plural = "";
+ else
+ $plural = "s";
+ return "Success, added ".$modified." of ".$num." domain".$plural;
+ }
}
/**
@@ -128,6 +154,16 @@ function add_to_table($db, $table, $domains, $wildcardstyle=false, $returnnum=fa
*/
function remove_from_table($db, $table, $domains, $returnnum=false)
{
+ // Begin transaction
+ if(!$db->exec("BEGIN TRANSACTION;"))
+ {
+ if($returnnum)
+ return 0;
+ else
+ return "Error: Unable to begin transaction for ".$table." table.";
+ }
+ $initialcount = intval($db->querySingle("SELECT COUNT(*) FROM ".$table.";"));
+
// Prepare SQLite statememt
$stmt = $db->prepare("DELETE FROM ".$table." WHERE domain = :domain;");
@@ -154,16 +190,30 @@ function remove_from_table($db, $table, $domains, $returnnum=false)
if($returnnum)
return $num;
else
- return "Error: ".$db->lastErrorMsg().", removed: ".$num;
+ {
+ if($num === 1)
+ $plural = "";
+ else
+ $plural = "s";
+ return "Error: ".$db->lastErrorMsg().", removed ".$num." domain".$plural;
+ }
}
}
// Close prepared statement and return number or processed rows
$stmt->close();
+ $db->exec("COMMIT;");
+
if($returnnum)
return $num;
else
- return "Success, removed: ".$num;
+ {
+ if($num === 1)
+ $plural = "";
+ else
+ $plural = "s";
+ return "Success, removed ".$num." domain".$plural;
+ }
}
?>
From 50e5349ee485e408fff44f1b174a53596f76a27e Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Thu, 29 Aug 2019 16:53:00 +0200
Subject: [PATCH 39/80] If some domains are not added, then this happened
because they are duplicates. Highlight this in the success message.
Signed-off-by: DL6ER
---
scripts/pi-hole/php/database.php | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/scripts/pi-hole/php/database.php b/scripts/pi-hole/php/database.php
index 89b93e02..0c19fee0 100644
--- a/scripts/pi-hole/php/database.php
+++ b/scripts/pi-hole/php/database.php
@@ -135,11 +135,23 @@ function add_to_table($db, $table, $domains, $wildcardstyle=false, $returnnum=fa
{
$finalcount = intval($db->querySingle("SELECT COUNT(*) FROM ".$table.";"));
$modified = $finalcount - $initialcount;
+
+ // If we add less domains than the user specified, then they wanted to add duplicates
+ if($modified !== $num)
+ {
+ $delta = $num - $modified;
+ $extra = " (".$delta." already existing)";
+ }
+ else
+ {
+ $extra = "";
+ }
+
if($num === 1)
$plural = "";
else
$plural = "s";
- return "Success, added ".$modified." of ".$num." domain".$plural;
+ return "Success, added ".$modified." of ".$num." domain".$plural.$extra;
}
}
From d97c85f7245133d47658565335c4896a848759e7 Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Thu, 29 Aug 2019 17:26:32 +0200
Subject: [PATCH 40/80] Slightly change the message shown when domains are
duplicates.
Signed-off-by: DL6ER
---
scripts/pi-hole/php/database.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/pi-hole/php/database.php b/scripts/pi-hole/php/database.php
index 0c19fee0..d4893d71 100644
--- a/scripts/pi-hole/php/database.php
+++ b/scripts/pi-hole/php/database.php
@@ -140,7 +140,7 @@ function add_to_table($db, $table, $domains, $wildcardstyle=false, $returnnum=fa
if($modified !== $num)
{
$delta = $num - $modified;
- $extra = " (".$delta." already existing)";
+ $extra = " (skipped ".$delta." duplicates)";
}
else
{
From 32566b66b30c86b725d36c08d907dcf6f7df1a31 Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Mon, 2 Sep 2019 17:25:22 +0200
Subject: [PATCH 41/80] Use gravity updated timestamp from database. This fixes
#989.
Signed-off-by: DL6ER
---
scripts/pi-hole/php/gravity.php | 112 +++++++++++++++++---------------
1 file changed, 61 insertions(+), 51 deletions(-)
diff --git a/scripts/pi-hole/php/gravity.php b/scripts/pi-hole/php/gravity.php
index cb3c3404..d29d7cf5 100644
--- a/scripts/pi-hole/php/gravity.php
+++ b/scripts/pi-hole/php/gravity.php
@@ -1,51 +1,61 @@
- | April 23rd, 2018:
- Checks when the gravity list was last updated, if it exists at all.
- Returns the info in human-readable format for use on the dashboard,
- or raw for use by the API.
- */
- $gravitylist = "/etc/pihole/gravity.list";
- if (file_exists($gravitylist)){
- $date_file_created_unix = filemtime($gravitylist);
- $date_file_created = date_create("@".$date_file_created_unix);
- $date_now = date_create("now");
- $gravitydiff = date_diff($date_file_created,$date_now);
- if($raw){
- $output = array(
- "file_exists"=> true,
- "absolute" => $date_file_created_unix,
- "relative" => array(
- "days" => $gravitydiff->format("%a"),
- "hours" => $gravitydiff->format("%H"),
- "minutes" => $gravitydiff->format("%I"),
- )
- );
- }else{
- if($gravitydiff->d > 1){
- $output = $gravitydiff->format("Blocking list updated %a days, %H:%I ago");
- }elseif($gravitydiff->d == 1){
- $output = $gravitydiff->format("Blocking list updated one day, %H:%I ago");
- }else{
- $output = $gravitydiff->format("Blocking list updated %H:%I ago");
- }
- }
- }else{
- if($raw){
- $output = array("file_exists"=>false);
- }else{
- $output = "Blocking list not found";
- }
- }
- return $output;
-}
-
-?>
\ No newline at end of file
+querySingle("SELECT value FROM info WHERE property = 'updated';");
+ if($date_file_created_unix !== false)
+ {
+ $date_file_created = date_create("@".intval($date_file_created_unix));
+ $date_now = date_create("now");
+ $gravitydiff = date_diff($date_file_created,$date_now);
+ if($raw)
+ {
+ $output = array(
+ "file_exists"=> true,
+ "absolute" => $date_file_created_unix,
+ "relative" => array(
+ "days" => $gravitydiff->format("%a"),
+ "hours" => $gravitydiff->format("%H"),
+ "minutes" => $gravitydiff->format("%I"),
+ )
+ );
+ }
+ else
+ {
+ if($gravitydiff->d > 1)
+ {
+ $output = $gravitydiff->format("Blocking list updated %a days, %H:%I ago");
+ }
+ elseif($gravitydiff->d == 1)
+ {
+ $output = $gravitydiff->format("Blocking list updated one day, %H:%I ago");
+ }
+ else
+ {
+ $output = $gravitydiff->format("Blocking list updated %H:%I ago");
+ }
+ }
+ }
+ else
+ {
+ if($raw)
+ {
+ $output = array("file_exists" => false);
+ }
+ else
+ {
+ $output = "Gravity database not available";
+ }
+ }
+ return $output;
+}
+?>
From d42180d2be05f4b981d8be126e2fe2e572da0946 Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Mon, 2 Sep 2019 21:34:39 +0200
Subject: [PATCH 42/80] Pass possible exception from SQLite3_connect_try() to
the calling process. This makes this function return either valid SQLite3
objects (success) or strings (errors). We can pass the errors to the user
interface to help user helping themselves.
Signed-off-by: DL6ER
---
scripts/pi-hole/php/database.php | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/scripts/pi-hole/php/database.php b/scripts/pi-hole/php/database.php
index d4893d71..f98f2b8a 100644
--- a/scripts/pi-hole/php/database.php
+++ b/scripts/pi-hole/php/database.php
@@ -33,7 +33,13 @@ function SQLite3_connect_try($filename, $mode, $trytoreconnect)
if($trytoreconnect)
{
sleep(3);
- $db = SQLite3_connect_try($filename, $mode, false);
+ return SQLite3_connect_try($filename, $mode, false);
+ }
+ else
+ {
+ // If we should not try again (or are already trying again!), we return the exception string
+ // so the user gets it on the dashboard
+ return $filename.": ".$exception->getMessage();
}
}
}
@@ -48,9 +54,9 @@ function SQLite3_connect($filename, $mode=SQLITE3_OPEN_READONLY)
{
die("No database available");
}
- if(!$db)
+ if(is_string($db))
{
- die("Error connecting to database");
+ die("Error connecting to database\n".$db);
}
// Add busy timeout so methods don't fail immediately when, e.g., FTL is currently reading from the DB
From fb17a8536ce403cd7f3061f4abc3877280d59789 Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Thu, 5 Sep 2019 19:08:05 +0200
Subject: [PATCH 43/80] Extend description of regex lists (they also contain
the wildcard-style rules)
Signed-off-by: DL6ER
---
settings.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/settings.php b/settings.php
index 9fa01c2b..07c1f1b6 100644
--- a/settings.php
+++ b/settings.php
@@ -1150,7 +1150,7 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "blocklists"
- Whitelist (regex)
+ Whitelist (regex/wildcard)
- Blacklist (regex)
+ Blacklist (regex/wildcard)
Date: Sat, 18 May 2019 23:38:00 +0200
Subject: [PATCH 44/80] Update link to git-scm.com, make the checkboxes actual
checkboxes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Sandro Jäckel
---
.github/PULL_REQUEST_TEMPLATE.md | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 7c288989..1be609f0 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -2,15 +2,15 @@
`{Please ensure that your pull request is for the 'devel' branch!}`
-- [] I have read and understood the [contributors guide](https://github.com/pi-hole/AdminLTE/blob/master/CONTRIBUTING.md), as well as this entire template.
-- [] I have made only one major change in my proposed changes.
-- [] I have commented my proposed changes within the code.
-- [] I have tested my proposed changes.
-- [] I am willing to help maintain this change if there are issues with it later.
-- [] I give this submission freely and claim no ownership.
-- [] It is compatible with the [EUPL 1.2 license](https://opensource.org/licenses/EUPL-1.1)
-- [] I have squashed any insignificant commits. ([`git rebase`](http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html))
-- [] I have Signed Off all commits. ([`git commit --signoff`](https://git-scm.com/docs/git-commit#git-commit---signoff))
+- [ ] I have read and understood the [contributors guide](https://github.com/pi-hole/AdminLTE/blob/master/CONTRIBUTING.md), as well as this entire template.
+- [ ] I have made only one major change in my proposed changes.
+- [ ] I have commented my proposed changes within the code.
+- [ ] I have tested my proposed changes.
+- [ ] I am willing to help maintain this change if there are issues with it later.
+- [ ] I give this submission freely and claim no ownership.
+- [ ] It is compatible with the [EUPL 1.2 license](https://opensource.org/licenses/EUPL-1.1)
+- [ ] I have squashed any insignificant commits. ([`git rebase`](http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html))
+- [ ] I have Signed Off all commits. ([`git commit --signoff`](https://git-scm.com/docs/git-commit#Documentation/git-commit.txt---signoff))
---
From b8088e7f0feaa2e469525dfe8e8683d883f558ec Mon Sep 17 00:00:00 2001
From: Mcat12
Date: Sun, 19 May 2019 14:16:55 -0700
Subject: [PATCH 45/80] Replace fa-refresh with fa-sync
Font Awesome 5 replaced the refresh icon from 4 with fa-sync:
https://fontawesome.com/how-to-use/on-the-web/setup/upgrading-from-version-4#name-changes
Fixes #941
Signed-off-by: Mcat12
---
auditlog.php | 4 ++--
db_graph.php | 2 +-
db_lists.php | 6 +++---
index.php | 20 ++++++++++----------
list.php | 2 +-
5 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/auditlog.php b/auditlog.php
index 86ebb685..20c36fdb 100644
--- a/auditlog.php
+++ b/auditlog.php
@@ -35,7 +35,7 @@
From a8b4cb74d8ca4ee3130aa0b98a6ec2e9abcbeae1 Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Sat, 15 Jun 2019 17:20:49 +0200
Subject: [PATCH 60/80] Check data before converting. This allows us to detect
if there is no data for the graph so we can hide it. Fixes #932
Signed-off-by: DL6ER
---
scripts/pi-hole/js/index.js | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/scripts/pi-hole/js/index.js b/scripts/pi-hole/js/index.js
index 17f1e092..21e00bda 100644
--- a/scripts/pi-hole/js/index.js
+++ b/scripts/pi-hole/js/index.js
@@ -261,15 +261,16 @@ function updateClientsOverTime() {
return;
}
- // convert received objects to arrays
- data.over_time = objectToArray(data.over_time);
-
// Remove graph if there are no results (e.g. privacy mode enabled)
if(jQuery.isEmptyObject(data.over_time))
{
$("#clients").parent().remove();
return;
}
+
+ // convert received objects to arrays
+ data.over_time = objectToArray(data.over_time);
+
// remove last data point since it not representative
data.over_time[0].splice(-1,1);
var timestamps = data.over_time[0];
From d2ff1f90939f001df1a8af315ebad050cebb4d85 Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Sat, 15 Jun 2019 17:47:07 +0200
Subject: [PATCH 61/80] Clarify that the router does not always have to be the
DHCP server. Fixes #893
Signed-off-by: DL6ER
---
settings.php | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/settings.php b/settings.php
index e2063097..73993429 100644
--- a/settings.php
+++ b/settings.php
@@ -856,11 +856,11 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "blocklists"
determine the names of devices on your local network. As a
result, tables such as Top Clients will only show IP addresses.
One solution for this is to configure Pi-hole to forward these
- requests to your home router, but only for devices on your
+ requests to your DHCP server (most likely your router), but only for devices on your
home network. To configure this we will need to know the IP
- address of your router and the name of your local network.
+ address of your DHCP server and the name of your local network.
Note: The local domain name must match the domain name specified
- in your router, likely found within the DHCP settings.
+ in your DHCP server, likely found within the DHCP settings.
Date: Sun, 20 Jan 2019 11:54:15 +0100
Subject: [PATCH 62/80] Always show the full requested range. Fill data with
zero at the end when the daterange is extending into the future. Similarly,
fill data wil zero at the beginning if the requested range extends into a
region without recorded queries.
Signed-off-by: DL6ER
---
api_db.php | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/api_db.php b/api_db.php
index 7687fb6e..1fe77449 100644
--- a/api_db.php
+++ b/api_db.php
@@ -378,15 +378,18 @@ if (isset($_GET['getGraphData']) && $auth)
$interval = $q;
}
+ $from = intval($_GET['from']);
+ $until = intval($_GET['until']);
+
// Count permitted queries in intervals
$stmt = $db->prepare('SELECT (timestamp/:interval)*:interval interval, COUNT(*) FROM queries WHERE (status != 0 )'.$limit.' GROUP by interval ORDER by interval');
- $stmt->bindValue(":from", intval($_GET['from']), SQLITE3_INTEGER);
- $stmt->bindValue(":until", intval($_GET['until']), SQLITE3_INTEGER);
+ $stmt->bindValue(":from", $from, SQLITE3_INTEGER);
+ $stmt->bindValue(":until", $until, SQLITE3_INTEGER);
$stmt->bindValue(":interval", $interval, SQLITE3_INTEGER);
$results = $stmt->execute();
// Parse the DB result into graph data, filling in missing sections with zero
- function parseDBData($results, $interval) {
+ function parseDBData($results, $interval, $from, $until) {
$data = array();
$min = null;
$max = null;
@@ -406,7 +409,7 @@ if (isset($_GET['getGraphData']) && $auth)
}
// Fill the missing intervals with zero
- for($i = $min; $i < $max; $i += $interval) {
+ for($i = min($min,$from); $i < max($max,$until); $i += $interval) {
if(!array_key_exists($i, $data))
$data[$i] = 0;
}
@@ -415,19 +418,19 @@ if (isset($_GET['getGraphData']) && $auth)
return $data;
}
- $domains = parseDBData($results, $interval);
+ $domains = parseDBData($results, $interval, $from, $until);
$result = array('domains_over_time' => $domains);
$data = array_merge($data, $result);
// Count blocked queries in intervals
$stmt = $db->prepare('SELECT (timestamp/:interval)*:interval interval, COUNT(*) FROM queries WHERE (status == 1 OR status == 4 OR status == 5)'.$limit.' GROUP by interval ORDER by interval');
- $stmt->bindValue(":from", intval($_GET['from']), SQLITE3_INTEGER);
- $stmt->bindValue(":until", intval($_GET['until']), SQLITE3_INTEGER);
+ $stmt->bindValue(":from", $from, SQLITE3_INTEGER);
+ $stmt->bindValue(":until", $until, SQLITE3_INTEGER);
$stmt->bindValue(":interval", $interval, SQLITE3_INTEGER);
$results = $stmt->execute();
- $addomains = parseDBData($results, $interval);
+ $addomains = parseDBData($results, $interval, $from, $until);
$result = array('ads_over_time' => $addomains);
$data = array_merge($data, $result);
From 429aa066e7e9af5483dbce5833f7815143ec0f1f Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Sat, 15 Jun 2019 16:24:00 +0200
Subject: [PATCH 63/80] Fix (almost) endless loop when there are no (or no
blocked) queries in the selected interval.
Signed-off-by: DL6ER
---
api_db.php | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/api_db.php b/api_db.php
index 1fe77449..06f7b9a3 100644
--- a/api_db.php
+++ b/api_db.php
@@ -404,10 +404,17 @@ if (isset($_GET['getGraphData']) && $auth)
if($max === null || $max < $row[0])
$max = $row[0];
- // Get the non-zero graph data
+ // $data[timestamp] = value_in_this_interval
$data[$row[0]] = intval($row[1]);
}
+ // Fall back to $from and $until if we read
+ // no data in the fetchArray while loop above
+ if($min === null)
+ $min = $from;
+ if($max === null)
+ $max = $until;
+
// Fill the missing intervals with zero
for($i = min($min,$from); $i < max($max,$until); $i += $interval) {
if(!array_key_exists($i, $data))
From 1fa2e0764269c5ce7e1448f5ed7fd55b14e6fb61 Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Sun, 16 Jun 2019 14:06:52 +0200
Subject: [PATCH 64/80] Simplify getGraphData and round and to match the
requested .
Signed-off-by: DL6ER
---
api_db.php | 40 +++++++++++++---------------------------
1 file changed, 13 insertions(+), 27 deletions(-)
diff --git a/api_db.php b/api_db.php
index 06f7b9a3..a5d91b62 100644
--- a/api_db.php
+++ b/api_db.php
@@ -378,45 +378,24 @@ if (isset($_GET['getGraphData']) && $auth)
$interval = $q;
}
- $from = intval($_GET['from']);
- $until = intval($_GET['until']);
+ // Round $from and $until to match the requested $interval
+ $from = intval((intval($_GET['from'])/$interval)*$interval);
+ $until = intval((intval($_GET['until'])/$interval)*$interval);
- // Count permitted queries in intervals
- $stmt = $db->prepare('SELECT (timestamp/:interval)*:interval interval, COUNT(*) FROM queries WHERE (status != 0 )'.$limit.' GROUP by interval ORDER by interval');
- $stmt->bindValue(":from", $from, SQLITE3_INTEGER);
- $stmt->bindValue(":until", $until, SQLITE3_INTEGER);
- $stmt->bindValue(":interval", $interval, SQLITE3_INTEGER);
- $results = $stmt->execute();
-
- // Parse the DB result into graph data, filling in missing sections with zero
+ // Parse the DB result into graph data, filling in missing interval sections with zero
function parseDBData($results, $interval, $from, $until) {
$data = array();
- $min = null;
- $max = null;
if(!is_bool($results)) {
// Read in the data
while($row = $results->fetchArray()) {
- // Get min and max timestamps
- if($min === null || $min > $row[0])
- $min = $row[0];
-
- if($max === null || $max < $row[0])
- $max = $row[0];
-
// $data[timestamp] = value_in_this_interval
$data[$row[0]] = intval($row[1]);
}
- // Fall back to $from and $until if we read
- // no data in the fetchArray while loop above
- if($min === null)
- $min = $from;
- if($max === null)
- $max = $until;
-
// Fill the missing intervals with zero
- for($i = min($min,$from); $i < max($max,$until); $i += $interval) {
+ // Advance in steps of interval
+ for($i = $from; $i < $until; $i += $interval) {
if(!array_key_exists($i, $data))
$data[$i] = 0;
}
@@ -425,6 +404,13 @@ if (isset($_GET['getGraphData']) && $auth)
return $data;
}
+ // Count permitted queries in intervals
+ $stmt = $db->prepare('SELECT (timestamp/:interval)*:interval interval, COUNT(*) FROM queries WHERE (status != 0 )'.$limit.' GROUP by interval ORDER by interval');
+ $stmt->bindValue(":from", $from, SQLITE3_INTEGER);
+ $stmt->bindValue(":until", $until, SQLITE3_INTEGER);
+ $stmt->bindValue(":interval", $interval, SQLITE3_INTEGER);
+ $results = $stmt->execute();
+
$domains = parseDBData($results, $interval, $from, $until);
$result = array('domains_over_time' => $domains);
From 48f7de4cf05f952627c336046456b29f305635b6 Mon Sep 17 00:00:00 2001
From: DL6ER
Date: Sun, 16 Jun 2019 14:08:26 +0200
Subject: [PATCH 65/80] Reposition parseDBData() to simplify diff output
Signed-off-by: DL6ER
---
api_db.php | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/api_db.php b/api_db.php
index a5d91b62..5195114e 100644
--- a/api_db.php
+++ b/api_db.php
@@ -382,6 +382,13 @@ if (isset($_GET['getGraphData']) && $auth)
$from = intval((intval($_GET['from'])/$interval)*$interval);
$until = intval((intval($_GET['until'])/$interval)*$interval);
+ // Count permitted queries in intervals
+ $stmt = $db->prepare('SELECT (timestamp/:interval)*:interval interval, COUNT(*) FROM queries WHERE (status != 0 )'.$limit.' GROUP by interval ORDER by interval');
+ $stmt->bindValue(":from", $from, SQLITE3_INTEGER);
+ $stmt->bindValue(":until", $until, SQLITE3_INTEGER);
+ $stmt->bindValue(":interval", $interval, SQLITE3_INTEGER);
+ $results = $stmt->execute();
+
// Parse the DB result into graph data, filling in missing interval sections with zero
function parseDBData($results, $interval, $from, $until) {
$data = array();
@@ -404,13 +411,6 @@ if (isset($_GET['getGraphData']) && $auth)
return $data;
}
- // Count permitted queries in intervals
- $stmt = $db->prepare('SELECT (timestamp/:interval)*:interval interval, COUNT(*) FROM queries WHERE (status != 0 )'.$limit.' GROUP by interval ORDER by interval');
- $stmt->bindValue(":from", $from, SQLITE3_INTEGER);
- $stmt->bindValue(":until", $until, SQLITE3_INTEGER);
- $stmt->bindValue(":interval", $interval, SQLITE3_INTEGER);
- $results = $stmt->execute();
-
$domains = parseDBData($results, $interval, $from, $until);
$result = array('domains_over_time' => $domains);
From 964c54360b0f9b020805e8ca56db8ffd09c1fdcc Mon Sep 17 00:00:00 2001
From: Mcat12
Date: Fri, 28 Jun 2019 20:14:05 -0700
Subject: [PATCH 66/80] Don't show the "Click to ..." tooltip when filtering is
disabled
Fixes #971
Signed-off-by: Mcat12
---
scripts/pi-hole/js/queries.js | 30 +++++++++++++++++++++++++++---
1 file changed, 27 insertions(+), 3 deletions(-)
diff --git a/scripts/pi-hole/js/queries.js b/scripts/pi-hole/js/queries.js
index 74e79ee1..95276cad 100644
--- a/scripts/pi-hole/js/queries.js
+++ b/scripts/pi-hole/js/queries.js
@@ -350,21 +350,45 @@ $(document).ready(function() {
// Query type IPv4 / IPv6
api.$("td:eq(1)").click( function () { if(autofilter()){ api.search( this.innerHTML ).draw(); $("#resetButton").show(); }});
api.$("td:eq(1)").hover(
- function () { this.title="Click to show only "+this.innerHTML+" queries"; this.style.color="#72afd2"; },
+ function () {
+ if(autofilter()) {
+ this.title = "Click to show only " + this.innerHTML + " 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.innerHTML ).draw(); $("#resetButton").show(); }});
api.$("td:eq(2)").hover(
- function () { this.title="Click to show only queries with domain "+this.innerHTML; this.style.color="#72afd2"; },
+ function () {
+ if(autofilter()) {
+ this.title = "Click to show only queries with domain " + this.innerHTML;
+ 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.innerHTML ).draw(); $("#resetButton").show(); }});
api.$("td:eq(3)").hover(
- function () { this.title="Click to show only queries made by "+this.innerHTML; this.style.color="#72afd2"; },
+ function () {
+ if(autofilter()) {
+ this.title = "Click to show only queries made by " + this.innerHTML;
+ this.style.color = "#72afd2";
+ } else {
+ this.title = "";
+ this.style.color = "";
+ }
+ },
function () { this.style.color=""; }
);
api.$("td:eq(3)").css("cursor","pointer");
From f6aeac5a1c59ce898f51f62cbfc20ca801031dc3 Mon Sep 17 00:00:00 2001
From: Daniel
Date: Thu, 4 Jul 2019 22:50:00 -0400
Subject: [PATCH 67/80] Improve audit logic to batch requests.
Signed-off-by: Daniel
---
scripts/pi-hole/js/auditlog.js | 22 +++++++++++++++++++---
1 file changed, 19 insertions(+), 3 deletions(-)
diff --git a/scripts/pi-hole/js/auditlog.js b/scripts/pi-hole/js/auditlog.js
index 3aa9912c..52790602 100644
--- a/scripts/pi-hole/js/auditlog.js
+++ b/scripts/pi-hole/js/auditlog.js
@@ -5,7 +5,7 @@
* 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 timeLineChart, queryTypeChart, forwardDestinationChart;
+var timeLineChart, queryTypeChart, forwardDestinationChart, auditList = [], auditTimeout;
// Credit: http://stackoverflow.com/questions/1787322/htmlspecialchars-equivalent-in-javascript/4835406#4835406
function escapeHtml(text) {
@@ -96,7 +96,7 @@ $(document).ready(function() {
}
else
{
- add(url,"audit");
+ auditUrl(url);
}
});
@@ -109,11 +109,27 @@ $(document).ready(function() {
}
else
{
- add(url,"audit");
+ 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);
+}
+
$("#gravityBtn").on("click", function() {
window.location.replace("gravity.php?go");
From fafd5b419b26187e7e1a6a47f8e6f6c3af6febe0 Mon Sep 17 00:00:00 2001
From: Mcat12
Date: Tue, 9 Jul 2019 20:35:15 -0700
Subject: [PATCH 68/80] Prevent static DHCP leases from having duplicate
hostnames
Fixes #979
Signed-off-by: Mcat12
---
scripts/pi-hole/php/savesettings.php | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/scripts/pi-hole/php/savesettings.php b/scripts/pi-hole/php/savesettings.php
index fc358d66..d8692cef 100644
--- a/scripts/pi-hole/php/savesettings.php
+++ b/scripts/pi-hole/php/savesettings.php
@@ -570,7 +570,7 @@ function readAdlists()
if(strlen($ip) == 0)
$ip = "noip";
- // Test if this MAC address is already included
+ // Test if this lease is already included
readStaticLeasesFile();
foreach($dhcp_static_leases as $lease) {
if($lease["hwaddr"] === $mac)
@@ -583,6 +583,10 @@ function readAdlists()
$error .= "Static lease for IP address (".htmlspecialchars($ip).") already defined! ";
break;
}
+ if($lease["host"] === $hostname)
+ {
+ $error .= "Static lease for hostname (".htmlspecialchars($hostname).") already defined! ";
+ }
}
if(!strlen($error))
From 580f1eb06d53851ed8b67e6ec8b5a9deb3dcb302 Mon Sep 17 00:00:00 2001
From: Mcat12
Date: Tue, 9 Jul 2019 20:37:05 -0700
Subject: [PATCH 69/80] Add missing break
Signed-off-by: Mcat12
---
scripts/pi-hole/php/savesettings.php | 1 +
1 file changed, 1 insertion(+)
diff --git a/scripts/pi-hole/php/savesettings.php b/scripts/pi-hole/php/savesettings.php
index d8692cef..d0c39710 100644
--- a/scripts/pi-hole/php/savesettings.php
+++ b/scripts/pi-hole/php/savesettings.php
@@ -586,6 +586,7 @@ function readAdlists()
if($lease["host"] === $hostname)
{
$error .= "Static lease for hostname (".htmlspecialchars($hostname).") already defined! ";
+ break;
}
}
From e816c28fd05fdddfb66b27ab94537634e6612233 Mon Sep 17 00:00:00 2001
From: TheME
Date: Sun, 4 Aug 2019 21:11:32 +0200
Subject: [PATCH 70/80] fix broken Icons
Signed-off-by: Th3M3
---
scripts/pi-hole/js/auditlog.js | 2 +-
scripts/pi-hole/js/db_queries.js | 6 +-
scripts/pi-hole/php/loginpage.php | 2 +-
scripts/vendor/daterangepicker.js | 601 +++++++++++++++--------------
settings.php | 2 +-
style/vendor/daterangepicker.css | 606 +++++++++++++++++++-----------
6 files changed, 710 insertions(+), 509 deletions(-)
diff --git a/scripts/pi-hole/js/auditlog.js b/scripts/pi-hole/js/auditlog.js
index 52790602..95c7fc3d 100644
--- a/scripts/pi-hole/js/auditlog.js
+++ b/scripts/pi-hole/js/auditlog.js
@@ -60,7 +60,7 @@ function updateTopLists() {
{
url = ""+printdomain+"";
adtable.append("
';
if ((!minDate || minDate.isBefore(calendar.firstDay)) && (!this.linkedCalendars || side == 'left')) {
- html += '
';
+ html += '
';
} else {
html += '
';
}
@@ -690,14 +709,14 @@
if (this.showDropdowns) {
var currentMonth = calendar[1][1].month();
var currentYear = calendar[1][1].year();
- var maxYear = (maxDate && maxDate.year()) || (currentYear + 5);
- var minYear = (minDate && minDate.year()) || (currentYear - 50);
+ var maxYear = (maxDate && maxDate.year()) || (this.maxYear);
+ var minYear = (minDate && minDate.year()) || (this.minYear);
var inMinYear = currentYear == minYear;
var inMaxYear = currentYear == maxYear;
var monthHtml = '';
html += '';
- //adjust maxDate to reflect the dateLimit setting in order to
- //grey out end dates beyond the dateLimit
- if (this.endDate == null && this.dateLimit) {
- var maxLimit = this.startDate.clone().add(this.dateLimit).endOf('day');
+ //adjust maxDate to reflect the maxSpan setting in order to
+ //grey out end dates beyond the maxSpan
+ if (this.endDate == null && this.maxSpan) {
+ var maxLimit = this.startDate.clone().add(this.maxSpan).endOf('day');
if (!maxDate || maxLimit.isBefore(maxDate)) {
maxDate = maxLimit;
}
@@ -774,7 +793,7 @@
//grey out the dates in other months displayed at beginning and end of this calendar
if (calendar[row][col].month() != calendar[1][1].month())
- classes.push('off');
+ classes.push('off', 'ends');
//don't allow selection of dates before the minimum date
if (this.minDate && calendar[row][col].isBefore(this.minDate, 'day'))
@@ -800,6 +819,15 @@
if (this.endDate != null && calendar[row][col] > this.startDate && calendar[row][col] < this.endDate)
classes.push('in-range');
+ //apply custom classes for this date
+ var isCustom = this.isCustomDate(calendar[row][col]);
+ if (isCustom !== false) {
+ if (typeof isCustom === 'string')
+ classes.push(isCustom);
+ else
+ Array.prototype.push.apply(classes, isCustom);
+ }
+
var cname = '', disabled = false;
for (var i = 0; i < classes.length; i++) {
cname += classes[i] + ' ';
@@ -818,31 +846,35 @@
html += '';
html += '
';
- this.container.find('.calendar.' + side + ' .calendar-table').html(html);
+ this.container.find('.drp-calendar.' + side + ' .calendar-table').html(html);
},
renderTimePicker: function(side) {
+ // Don't bother updating the time picker if it's currently disabled
+ // because an end date hasn't been clicked yet
+ if (side == 'right' && !this.endDate) return;
+
var html, selected, minDate, maxDate = this.maxDate;
- if (this.dateLimit && (!this.maxDate || this.startDate.clone().add(this.dateLimit).isAfter(this.maxDate)))
- maxDate = this.startDate.clone().add(this.dateLimit);
+ if (this.maxSpan && (!this.maxDate || this.startDate.clone().add(this.maxSpan).isBefore(this.maxDate)))
+ maxDate = this.startDate.clone().add(this.maxSpan);
if (side == 'left') {
selected = this.startDate.clone();
minDate = this.minDate;
} else if (side == 'right') {
- selected = this.endDate ? this.endDate.clone() : this.previousRightTime.clone();
+ selected = this.endDate.clone();
minDate = this.startDate;
//Preserve the time already selected
- var timeSelector = this.container.find('.calendar.right .calendar-time div');
+ var timeSelector = this.container.find('.drp-calendar.right .calendar-time');
if (timeSelector.html() != '') {
- selected.hour(timeSelector.find('.hourselect option:selected').val() || selected.hour());
- selected.minute(timeSelector.find('.minuteselect option:selected').val() || selected.minute());
- selected.second(timeSelector.find('.secondselect option:selected').val() || selected.second());
+ selected.hour(!isNaN(selected.hour()) ? selected.hour() : timeSelector.find('.hourselect option:selected').val());
+ selected.minute(!isNaN(selected.minute()) ? selected.minute() : timeSelector.find('.minuteselect option:selected').val());
+ selected.second(!isNaN(selected.second()) ? selected.second() : timeSelector.find('.secondselect option:selected').val());
if (!this.timePicker24Hour) {
var ampm = timeSelector.find('.ampmselect option:selected').val();
@@ -852,13 +884,14 @@
selected.hour(0);
}
- if (selected.isBefore(this.startDate))
- selected = this.startDate.clone();
-
- if (selected.isAfter(maxDate))
- selected = maxDate.clone();
-
}
+
+ if (selected.isBefore(this.startDate))
+ selected = this.startDate.clone();
+
+ if (maxDate && selected.isAfter(maxDate))
+ selected = maxDate.clone();
+
}
//
@@ -974,20 +1007,12 @@
html += '';
}
- this.container.find('.calendar.' + side + ' .calendar-time div').html(html);
+ this.container.find('.drp-calendar.' + side + ' .calendar-time').html(html);
},
updateFormInputs: function() {
- //ignore mouse movements while an above-calendar text input has focus
- if (this.container.find('input[name=daterangepicker_start]').is(":focus") || this.container.find('input[name=daterangepicker_end]').is(":focus"))
- return;
-
- this.container.find('input[name=daterangepicker_start]').val(this.startDate.format(this.locale.format));
- if (this.endDate)
- this.container.find('input[name=daterangepicker_end]').val(this.endDate.format(this.locale.format));
-
if (this.singleDatePicker || (this.endDate && (this.startDate.isBefore(this.endDate) || this.startDate.isSame(this.endDate)))) {
this.container.find('button.applyBtn').removeAttr('disabled');
} else {
@@ -1012,44 +1037,68 @@
containerTop = this.element.offset().top - this.container.outerHeight() - parentOffset.top;
else
containerTop = this.element.offset().top + this.element.outerHeight() - parentOffset.top;
- this.container[this.drops == 'up' ? 'addClass' : 'removeClass']('dropup');
+
+ // Force the container to it's actual width
+ this.container.css({
+ top: 0,
+ left: 0,
+ right: 'auto'
+ });
+ var containerWidth = this.container.outerWidth();
+
+ this.container[this.drops == 'up' ? 'addClass' : 'removeClass']('drop-up');
if (this.opens == 'left') {
- this.container.css({
- top: containerTop,
- right: parentRightEdge - this.element.offset().left - this.element.outerWidth(),
- left: 'auto'
- });
- if (this.container.offset().left < 0) {
+ var containerRight = parentRightEdge - this.element.offset().left - this.element.outerWidth();
+ if (containerWidth + containerRight > $(window).width()) {
this.container.css({
+ top: containerTop,
right: 'auto',
left: 9
});
+ } else {
+ this.container.css({
+ top: containerTop,
+ right: containerRight,
+ left: 'auto'
+ });
}
} else if (this.opens == 'center') {
- this.container.css({
- top: containerTop,
- left: this.element.offset().left - parentOffset.left + this.element.outerWidth() / 2
- - this.container.outerWidth() / 2,
- right: 'auto'
- });
- if (this.container.offset().left < 0) {
+ var containerLeft = this.element.offset().left - parentOffset.left + this.element.outerWidth() / 2
+ - containerWidth / 2;
+ if (containerLeft < 0) {
this.container.css({
+ top: containerTop,
right: 'auto',
left: 9
});
- }
- } else {
- this.container.css({
- top: containerTop,
- left: this.element.offset().left - parentOffset.left,
- right: 'auto'
- });
- if (this.container.offset().left + this.container.outerWidth() > $(window).width()) {
+ } else if (containerLeft + containerWidth > $(window).width()) {
this.container.css({
+ top: containerTop,
left: 'auto',
right: 0
});
+ } else {
+ this.container.css({
+ top: containerTop,
+ left: containerLeft,
+ right: 'auto'
+ });
+ }
+ } else {
+ var containerLeft = this.element.offset().left - parentOffset.left;
+ if (containerLeft + containerWidth > $(window).width()) {
+ this.container.css({
+ top: containerTop,
+ left: 'auto',
+ right: 0
+ });
+ } else {
+ this.container.css({
+ top: containerTop,
+ left: containerLeft,
+ right: 'auto'
+ });
}
}
},
@@ -1095,7 +1144,7 @@
//if a new date range was selected, invoke the user callback function
if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate))
- this.callback(this.startDate, this.endDate, this.chosenLabel);
+ this.callback(this.startDate.clone(), this.endDate.clone(), this.chosenLabel);
//if picker is attached to a text input, update it
this.updateElement();
@@ -1127,6 +1176,7 @@
target.closest('.calendar-table').length
) return;
this.hide();
+ this.element.trigger('outsideClick.daterangepicker', this);
},
showCalendars: function() {
@@ -1140,25 +1190,8 @@
this.element.trigger('hideCalendar.daterangepicker', this);
},
- hoverRange: function(e) {
-
- //ignore mouse movements while an above-calendar text input has focus
- if (this.container.find('input[name=daterangepicker_start]').is(":focus") || this.container.find('input[name=daterangepicker_end]').is(":focus"))
- return;
-
- var label = e.target.innerHTML;
- if (label == this.locale.customRangeLabel) {
- this.updateView();
- } else {
- var dates = this.ranges[label];
- this.container.find('input[name=daterangepicker_start]').val(dates[0].format(this.locale.format));
- this.container.find('input[name=daterangepicker_end]').val(dates[1].format(this.locale.format));
- }
-
- },
-
clickRange: function(e) {
- var label = e.target.innerHTML;
+ var label = e.target.getAttribute('data-range-key');
this.chosenLabel = label;
if (label == this.locale.customRangeLabel) {
this.showCalendars();
@@ -1179,7 +1212,7 @@
},
clickPrev: function(e) {
- var cal = $(e.target).parents('.calendar');
+ var cal = $(e.target).parents('.drp-calendar');
if (cal.hasClass('left')) {
this.leftCalendar.month.subtract(1, 'month');
if (this.linkedCalendars)
@@ -1191,7 +1224,7 @@
},
clickNext: function(e) {
- var cal = $(e.target).parents('.calendar');
+ var cal = $(e.target).parents('.drp-calendar');
if (cal.hasClass('left')) {
this.leftCalendar.month.add(1, 'month');
} else {
@@ -1204,32 +1237,21 @@
hoverDate: function(e) {
- //ignore mouse movements while an above-calendar text input has focus
- if (this.container.find('input[name=daterangepicker_start]').is(":focus") || this.container.find('input[name=daterangepicker_end]').is(":focus"))
- return;
-
//ignore dates that can't be selected
if (!$(e.target).hasClass('available')) return;
- //have the text inputs above calendars reflect the date being hovered over
var title = $(e.target).attr('data-title');
var row = title.substr(1, 1);
var col = title.substr(3, 1);
- var cal = $(e.target).parents('.calendar');
+ var cal = $(e.target).parents('.drp-calendar');
var date = cal.hasClass('left') ? this.leftCalendar.calendar[row][col] : this.rightCalendar.calendar[row][col];
- if (this.endDate) {
- this.container.find('input[name=daterangepicker_start]').val(date.format(this.locale.format));
- } else {
- this.container.find('input[name=daterangepicker_end]').val(date.format(this.locale.format));
- }
-
//highlight the dates between the start date and the date being hovered as a potential end date
var leftCalendar = this.leftCalendar;
var rightCalendar = this.rightCalendar;
var startDate = this.startDate;
if (!this.endDate) {
- this.container.find('.calendar td').each(function(index, el) {
+ this.container.find('.drp-calendar tbody td').each(function(index, el) {
//skip week numbers, only look at dates
if ($(el).hasClass('week')) return;
@@ -1237,10 +1259,10 @@
var title = $(el).attr('data-title');
var row = title.substr(1, 1);
var col = title.substr(3, 1);
- var cal = $(el).parents('.calendar');
+ var cal = $(el).parents('.drp-calendar');
var dt = cal.hasClass('left') ? leftCalendar.calendar[row][col] : rightCalendar.calendar[row][col];
- if (dt.isAfter(startDate) && dt.isBefore(date)) {
+ if ((dt.isAfter(startDate) && dt.isBefore(date)) || dt.isSame(date, 'day')) {
$(el).addClass('in-range');
} else {
$(el).removeClass('in-range');
@@ -1258,7 +1280,7 @@
var title = $(e.target).attr('data-title');
var row = title.substr(1, 1);
var col = title.substr(3, 1);
- var cal = $(e.target).parents('.calendar');
+ var cal = $(e.target).parents('.drp-calendar');
var date = cal.hasClass('left') ? this.leftCalendar.calendar[row][col] : this.rightCalendar.calendar[row][col];
//
@@ -1267,9 +1289,10 @@
// * if the time picker is enabled, apply the hour/minute/second from the select boxes to the clicked date
// * if autoapply is enabled, and an end date was chosen, apply the selection
// * if single date picker mode, and time picker isn't enabled, apply the selection immediately
+ // * if one of the inputs above the calendars was focused, cancel that manual input
//
- if (this.endDate || date.isBefore(this.startDate, 'day')) {
+ if (this.endDate || date.isBefore(this.startDate, 'day')) { //picking start
if (this.timePicker) {
var hour = parseInt(this.container.find('.left .hourselect').val(), 10);
if (!this.timePicker24Hour) {
@@ -1280,16 +1303,19 @@
hour = 0;
}
var minute = parseInt(this.container.find('.left .minuteselect').val(), 10);
+ if (isNaN(minute)) {
+ minute = parseInt(this.container.find('.left .minuteselect option:last').val(), 10);
+ }
var second = this.timePickerSeconds ? parseInt(this.container.find('.left .secondselect').val(), 10) : 0;
date = date.clone().hour(hour).minute(minute).second(second);
}
this.endDate = null;
this.setStartDate(date.clone());
} else if (!this.endDate && date.isBefore(this.startDate)) {
- //special case: clicking the same date for start/end,
+ //special case: clicking the same date for start/end,
//but the time of the end date is before the start date
this.setEndDate(this.startDate.clone());
- } else {
+ } else { // picking end
if (this.timePicker) {
var hour = parseInt(this.container.find('.right .hourselect').val(), 10);
if (!this.timePicker24Hour) {
@@ -1300,6 +1326,9 @@
hour = 0;
}
var minute = parseInt(this.container.find('.right .minuteselect').val(), 10);
+ if (isNaN(minute)) {
+ minute = parseInt(this.container.find('.right .minuteselect option:last').val(), 10);
+ }
var second = this.timePickerSeconds ? parseInt(this.container.find('.right .secondselect').val(), 10) : 0;
date = date.clone().hour(hour).minute(minute).second(second);
}
@@ -1318,32 +1347,41 @@
this.updateView();
+ //This is to cancel the blur event handler if the mouse was in one of the inputs
+ e.stopPropagation();
+
},
- calculateChosenLabel: function() {
- var customRange = true;
- var i = 0;
- for (var range in this.ranges) {
+ calculateChosenLabel: function () {
+ var customRange = true;
+ var i = 0;
+ for (var range in this.ranges) {
if (this.timePicker) {
- if (this.startDate.isSame(this.ranges[range][0]) && this.endDate.isSame(this.ranges[range][1])) {
- customRange = false;
- this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')').addClass('active').html();
- break;
- }
- } else {
- //ignore times when comparing dates if time picker is not enabled
- if (this.startDate.format('YYYY-MM-DD') == this.ranges[range][0].format('YYYY-MM-DD') && this.endDate.format('YYYY-MM-DD') == this.ranges[range][1].format('YYYY-MM-DD')) {
- customRange = false;
- this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')').addClass('active').html();
- break;
- }
- }
- i++;
- }
- if (customRange) {
- this.chosenLabel = this.container.find('.ranges li:last').addClass('active').html();
- this.showCalendars();
- }
+ var format = this.timePickerSeconds ? "YYYY-MM-DD HH:mm:ss" : "YYYY-MM-DD HH:mm";
+ //ignore times when comparing dates if time picker seconds is not enabled
+ if (this.startDate.format(format) == this.ranges[range][0].format(format) && this.endDate.format(format) == this.ranges[range][1].format(format)) {
+ customRange = false;
+ this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')').addClass('active').attr('data-range-key');
+ break;
+ }
+ } else {
+ //ignore times when comparing dates if time picker is not enabled
+ if (this.startDate.format('YYYY-MM-DD') == this.ranges[range][0].format('YYYY-MM-DD') && this.endDate.format('YYYY-MM-DD') == this.ranges[range][1].format('YYYY-MM-DD')) {
+ customRange = false;
+ this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')').addClass('active').attr('data-range-key');
+ break;
+ }
+ }
+ i++;
+ }
+ if (customRange) {
+ if (this.showCustomRangeLabel) {
+ this.chosenLabel = this.container.find('.ranges li:last').addClass('active').attr('data-range-key');
+ } else {
+ this.chosenLabel = null;
+ }
+ this.showCalendars();
+ }
},
clickApply: function(e) {
@@ -1359,9 +1397,9 @@
},
monthOrYearChanged: function(e) {
- var isLeft = $(e.target).closest('.calendar').hasClass('left'),
+ var isLeft = $(e.target).closest('.drp-calendar').hasClass('left'),
leftOrRight = isLeft ? 'left' : 'right',
- cal = this.container.find('.calendar.'+leftOrRight);
+ cal = this.container.find('.drp-calendar.'+leftOrRight);
// Month must be Number for new moment versions
var month = parseInt(cal.find('.monthselect').val(), 10);
@@ -1402,11 +1440,14 @@
timeChanged: function(e) {
- var cal = $(e.target).closest('.calendar'),
+ var cal = $(e.target).closest('.drp-calendar'),
isLeft = cal.hasClass('left');
var hour = parseInt(cal.find('.hourselect').val(), 10);
var minute = parseInt(cal.find('.minuteselect').val(), 10);
+ if (isNaN(minute)) {
+ minute = parseInt(cal.find('.minuteselect option:last').val(), 10);
+ }
var second = this.timePickerSeconds ? parseInt(cal.find('.secondselect').val(), 10) : 0;
if (!this.timePicker24Hour) {
@@ -1448,38 +1489,9 @@
},
- formInputsChanged: function(e) {
- var isRight = $(e.target).closest('.calendar').hasClass('right');
- var start = moment(this.container.find('input[name="daterangepicker_start"]').val(), this.locale.format);
- var end = moment(this.container.find('input[name="daterangepicker_end"]').val(), this.locale.format);
-
- if (start.isValid() && end.isValid()) {
-
- if (isRight && end.isBefore(start))
- start = end.clone();
-
- this.setStartDate(start);
- this.setEndDate(end);
-
- if (isRight) {
- this.container.find('input[name="daterangepicker_start"]').val(this.startDate.format(this.locale.format));
- } else {
- this.container.find('input[name="daterangepicker_end"]').val(this.endDate.format(this.locale.format));
- }
-
- }
-
- this.updateCalendars();
- if (this.timePicker) {
- this.renderTimePicker('left');
- this.renderTimePicker('right');
- }
- },
-
elementChanged: function() {
if (!this.element.is('input')) return;
if (!this.element.val().length) return;
- if (this.element.val().length < this.locale.format.length) return;
var dateString = this.element.val().split(this.locale.separator),
start = null,
@@ -1507,15 +1519,25 @@
if ((e.keyCode === 9) || (e.keyCode === 13)) {
this.hide();
}
+
+ //hide on esc and prevent propagation
+ if (e.keyCode === 27) {
+ e.preventDefault();
+ e.stopPropagation();
+
+ this.hide();
+ }
},
updateElement: function() {
- if (this.element.is('input') && !this.singleDatePicker && this.autoUpdateInput) {
- this.element.val(this.startDate.format(this.locale.format) + this.locale.separator + this.endDate.format(this.locale.format));
- this.element.trigger('change');
- } else if (this.element.is('input') && this.autoUpdateInput) {
- this.element.val(this.startDate.format(this.locale.format));
- this.element.trigger('change');
+ if (this.element.is('input') && this.autoUpdateInput) {
+ var newValue = this.startDate.format(this.locale.format);
+ if (!this.singleDatePicker) {
+ newValue += this.locale.separator + this.endDate.format(this.locale.format);
+ }
+ if (newValue !== this.element.val()) {
+ this.element.val(newValue).trigger('change');
+ }
}
},
@@ -1528,15 +1550,16 @@
};
$.fn.daterangepicker = function(options, callback) {
+ var implementOptions = $.extend(true, {}, $.fn.daterangepicker.defaultOptions, options);
this.each(function() {
var el = $(this);
if (el.data('daterangepicker'))
el.data('daterangepicker').remove();
- el.data('daterangepicker', new DateRangePicker(el, options, callback));
+ el.data('daterangepicker', new DateRangePicker(el, implementOptions, callback));
});
return this;
};
-
+
return DateRangePicker;
}));
diff --git a/settings.php b/settings.php
index 73993429..61b2f5d5 100644
--- a/settings.php
+++ b/settings.php
@@ -46,7 +46,7 @@ if (isset($_POST["submit"])) {