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")