Updated Block Page to work with queryFunc output

This commit is contained in:
WaLLy3K 2017-07-19 00:15:59 +10:00 committed by GitHub
parent 69fa9874dd
commit f2a3b557c8
1 changed files with 79 additions and 96 deletions

View File

@ -6,30 +6,21 @@
* This file is copyright under the latest version of the EUPL.
* Please see LICENSE file for your rights under this license. */
// Function to validate server name (Including underscores & IPv6)
ini_set("pcre.recursion_limit", 1500);
function validate_server_name($domain) { // Cr: http://stackoverflow.com/a/4694816
if (filter_var($domain, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) return TRUE;
return (preg_match("/^([a-z\d]((-|_)*[a-z\d])*)(\.([a-z\d]((-|_)*[a-z\d])*))*$/i", $domain) // Valid chars check
&& preg_match("/^.{1,253}$/", $domain) // Overall length check
&& preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain)); // Length of each label
}
// Validate HTTP_HOST output
if (validate_server_name($_SERVER["HTTP_HOST"]) === TRUE) {
$serverName = $_SERVER["HTTP_HOST"];
} else {
die("[ERROR]: <code>HTTP_HOST</code> header output does not appear to be valid: <code>".$_SERVER["HTTP_HOST"]."</code>");
}
// Sanitise HTTP_HOST output
$serverName = htmlspecialchars($_SERVER["HTTP_HOST"]);
// Get values from setupVars.conf
$setupVars = parse_ini_file("/etc/pihole/setupVars.conf");
$svFQDN = (!empty($setupVars["FQDN"]) && validate_server_name($setupVars["FQDN"]) === TRUE) ? $setupVars["FQDN"] : "";
$svPasswd = !empty($setupVars["WEBPASSWORD"]);
$svEmail = (!empty($setupVars["ADMIN_EMAIL"]) && filter_var($setupVars["ADMIN_EMAIL"], FILTER_VALIDATE_EMAIL)) ? $setupVars["ADMIN_EMAIL"] : "";
unset($setupVars);
if (is_file("/etc/pihole/setupVars.conf")) {
$setupVars = parse_ini_file("/etc/pihole/setupVars.conf");
$svFQDN = $setupVars["FQDN"];
$svPasswd = !empty($setupVars["WEBPASSWORD"]);
$svEmail = (!empty($setupVars["ADMIN_EMAIL"]) && filter_var($setupVars["ADMIN_EMAIL"], FILTER_VALIDATE_EMAIL)) ? $setupVars["ADMIN_EMAIL"] : "";
unset($setupVars);
} else {
die("[ERROR] File not found: <code>/etc/pihole/setupVars.conf</code>");
}
// Set landing page name, found within /var/www/html/pihole/
// Set landing page location, found within /var/www/html/
$landPage = "../landing.php";
// Set empty array for hostnames to be accepted as self address for splash page
@ -40,14 +31,10 @@ if (!empty($svFQDN)) array_push($authorizedHosts, $svFQDN);
// Append virtual hostname to $authorizedHosts
if (!empty($_SERVER["VIRTUAL_HOST"])) {
if (validate_server_name($_SERVER["VIRTUAL_HOST"]) === TRUE) {
array_push($authorizedHosts, $_SERVER["VIRTUAL_HOST"]);
} else {
die("[ERROR]: <code>VIRTUAL_HOST</code> header output does not appear to be valid: <code>".$_SERVER["VIRTUAL_HOST"]."</code>");
}
array_push($authorizedHosts, $_SERVER["VIRTUAL_HOST"]);
}
// Set which extension types get rendered as "Website Blocked" (Including "" for index file extensions)
// Set which extension types render as Block Page (Including "" for index.wxyz)
$validExtTypes = array("asp", "htm", "html", "php", "rss", "xml", "");
// Get extension of current URL
@ -62,31 +49,33 @@ function setHeader($type = "x") {
if (isset($type) && $type === "js") header("Content-Type: application/javascript");
}
// Determine block page redirect
// Determine block page redirect type
if ($serverName === "pi.hole") {
exit(header("Location: /admin"));
} elseif (filter_var($serverName, FILTER_VALIDATE_IP) || in_array($serverName, $authorizedHosts)) {
// Show splash page or landing page when directly browsing via IP or auth'd hostname
// Set Splash Page output
$splashPage = "
<html><head>
$viewPort
<link rel='stylesheet' href='/pihole/blockingpage.css' type='text/css'/>
</head><body id='splashpage'><img src='/admin/img/logo.svg'/><br/>Pi-<b>hole</b>: Your black hole for Internet advertisements</body></html>
";
$pageType = is_file(getcwd()."/$landPage") ? include $landPage : "$splashPage";
// Render splash page or landing page when directly browsing via IP or auth'd hostname
$renderPage = is_file(getcwd()."/$landPage") ? include $landPage : "$splashPage";
unset($serverName, $svFQDN, $svPasswd, $svEmail, $authorizedHosts, $validExtTypes, $currentUrlExt, $viewPort);
exit($pageType);
exit($renderPage);
} elseif ($currentUrlExt === "js") {
// Set Javascript redirect for blocked sources
// Serve dummy Javascript for blocked domains
exit(setHeader("js").'var x = "Pi-hole: A black hole for Internet advertisements."');
} elseif (strpos($_SERVER["REQUEST_URI"], "?") !== FALSE && isset($_SERVER["HTTP_REFERER"])) {
// Set blank image upon receiving REQUEST_URI w/ query string & HTTP_REFERRER (Presumably from iframe)
// Serve blank image upon receiving REQUEST_URI w/ query string & HTTP_REFERRER (e.g: an iframe of a blocked domain)
exit(setHeader().'<html>
<head><script>window.close();</script></head>
<body><img src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs="></body>
</html>');
} elseif (!in_array($currentUrlExt, $validExtTypes) || substr_count($_SERVER["REQUEST_URI"], "?")) {
// Set svg image upon receiving non $validExtTypes URL extension or query string (Presumably not from an iframe)
// Serve SVG upon receiving non $validExtTypes URL extension or query string (e.g: not an iframe of a blocked domain)
$blockImg = '<a href="/"><svg xmlns="http://www.w3.org/2000/svg" width="110" height="16"><defs><style>a {text-decoration: none;} circle {stroke: rgba(152,2,2,0.5); fill: none; stroke-width: 2;} rect {fill: rgba(152,2,2,0.5);} text {opacity: 0.3; font: 11px Arial;}</style></defs><circle cx="8" cy="8" r="7"/><rect x="10.3" y="-6" width="2" height="12" transform="rotate(45)"/><text x="19.3" y="12">Blocked by Pi-hole</text></svg></a>';
exit(setHeader()."<html>
<head>$viewPort</head>
@ -94,89 +83,86 @@ if ($serverName === "pi.hole") {
</html>");
}
/* Start processing block page from here */
// Get Pi-hole core branch name
$phBranch = exec("cd /etc/.pihole/ && git rev-parse --abbrev-ref HEAD");
if ($phBranch !== "master") {
error_reporting(E_ALL);
ini_set("display_errors", 1);
ini_set("display_startup_errors", 1);
}
// Validate SERVER_IP output
if (filter_var($_SERVER['SERVER_ADDR'], FILTER_VALIDATE_IP)) {
$serverAddr = $_SERVER["SERVER_ADDR"];
} else {
die("[ERROR]: <code>SERVER_IP</code> header output does not appear to be valid: <code>".$_SERVER["SERVER_ADDR"]."</code>");
}
/* Start processing Block Page from here */
// Determine placeholder text based off $svPasswd presence
$wlPlaceHolder = empty($svPasswd) ? "No admin password set" : "Javascript disabled";
// Get admin email address
// Define admin email address text
$bpAskAdmin = !empty($svEmail) ? '<a href="mailto:'.$svEmail.'?subject=Site Blocked: '.$serverName.'"></a>' : "<span/>";
// Determine if at least one block list has been generated
if (empty(glob("/etc/pihole/list.0.*.domains"))) die("[ERROR]: There are no domain lists generated lists within <code>/etc/pihole/</code>! Please update gravity by running <code>pihole -g</code>, or repair Pi-hole using <code>pihole -r</code>.");
if (empty(glob("/etc/pihole/list.0.*.domains")))
die("[ERROR] There are no domain lists generated lists within <code>/etc/pihole/</code>! Please update gravity by running <code>pihole -g</code>, or repair Pi-hole using <code>pihole -r</code>.");
// Get contents of adlist.list
$adLists = is_file("/etc/pihole/adlists.list") ? "/etc/pihole/adlists.list" : "/etc/pihole/adlists.default";
if (!is_file($adLists)) die("[ERROR]: Unable to find file: <code>$adLists</code>");
// Set location of adlists file
if (is_file("/etc/pihole/adlists.list")) {
$adLists = "/etc/pihole/adlists.list";
} elseif (is_file("/etc/pihole/adlists.default")) {
$adLists = "/etc/pihole/adlists.default";
} else {
die("[ERROR] File not found: <code>/etc/pihole/adlists.list</code>");
}
// Get all URLs starting with "http" or "www" from $adLists and re-index array numerically
// Get all URLs starting with "http" or "www" from adlists and re-index array numerically
$adlistsUrls = array_values(preg_grep("/(^http)|(^www)/i", file($adLists, FILE_IGNORE_NEW_LINES)));
if (empty($adlistsUrls)) die("[ERROR]: There are no adlist URL's found within <code>$adLists</code>");
$adlistsCount = count($adlistsUrls) + 3; // +1 because array starts at 0, +2 for Blacklist & Wildcard lists
if (empty($adlistsUrls))
die("[ERROR]: There are no adlist URL's found within <code>$adLists</code>");
// Get total number of blocklists (Including Whitelist, Blacklist & Wildcard lists)
$adlistsCount = count($adlistsUrls) + 3;
// Get results of queryads.php exact search
ini_set("default_socket_timeout", 3);
function queryAds($serverName) {
// Determine the time it takes while querying adlists
$preQueryTime = microtime(true)-$_SERVER["REQUEST_TIME_FLOAT"];
$queryAds = file("http://127.0.0.1/admin/scripts/pi-hole/php/queryads.php?domain=$serverName&exact", FILE_IGNORE_NEW_LINES);
$queryAds = file("http://127.0.0.1/admin/scripts/pi-hole/php/queryads.php?domain=$serverName&bp", FILE_IGNORE_NEW_LINES);
$queryAds = array_values(array_filter(preg_replace("/data:\s+/", "", $queryAds)));
$queryTime = sprintf("%.0f", (microtime(true)-$_SERVER["REQUEST_TIME_FLOAT"]) - $preQueryTime);
// Exception Handling
try {
if ($queryTime >= ini_get("default_socket_timeout")) {
throw new Exception ("Connection timeout (".ini_get("default_socket_timeout")."s)");
} elseif ($queryAds[0][0] === ":") {
if (strpos($queryAds[0], "Invalid") !== FALSE) throw new Exception ("Invalid Domain ($serverName)");
if (strpos($queryAds[0], "No exact") !== FALSE) return array("0" => "none");
} elseif (!strpos($queryAds[0], ".") !== false) {
if (strpos($queryAds[0], "No exact results") !== FALSE) return array("0" => "none");
throw new Exception ("Unhandled error message (<code>$queryAds[0]</code>)");
} elseif ($queryAds[0][0] !== "/") {
throw new Exception ("Unexpected output (<code>$queryAds[0]</code>)");
}
return $queryAds;
} catch (Exception $e) {
return array("0" => "error", "1" => $e->getMessage());
}
}
$queryAds = queryAds($serverName);
if ($queryAds[0] === "error") {
die("[ERROR]: Unable to parse results from <i>queryads.php</i>: <code>".$queryAds[1]."</code>");
}
// Filter, sort, and count $queryAds array
if ($queryAds[0] !== "none") {
$queryAds = preg_replace("/(\/etc\/pihole\/)|(\/etc\/dnsmasq\.d\/)/", "", $queryAds);
$queryAds = preg_replace("/(^list\.)|(\..*domains)/", "", $queryAds);
} else {
$featuredTotal = count($queryAds);
// Place results into key => value array
$queryResults = null;
foreach ($queryAds as $str) {
$value = explode(" ", $str);
@$queryResults[$value[0]] .= "$value[1]";
}
}
// Determine if domain has been blacklisted or wildcarded
if ($queryAds[0] === "blacklist.txt") {
$intBlacklist = array("&#960;" => $queryAds[0]);
$queryAds[0] = "&#960;"; // Manually blacklisted sites do not have a number
// Determine if domain has been blacklisted, whitelisted, wildcarded or CNAME blocked
if (strpos($queryAds[0], "blacklist") !== FALSE) {
$notableFlagClass = "blacklist";
} elseif ($queryAds[0] === "whitelist.txt") {
$intBlacklist = array("&#960;" => $queryAds[0]);
$queryAds[0] = "&#960;";
$adlistsUrls = array("π" => substr($queryAds[0], 2));
} elseif (strpos($queryAds[0], "whitelist") !== FALSE) {
$notableFlagClass = "noblock";
$adlistsUrls = array("π" => substr($queryAds[0], 2));
$wlInfo = "recentwl";
} elseif ($queryAds[0] === "03-pihole-wildcard.conf") {
$intBlacklist = array("&#960;" => $queryAds[0]);
$queryAds[0] = "&#960;";
} elseif (strpos($queryAds[0], "wildcard") !== FALSE) {
$notableFlagClass = "wildcard";
$adlistsUrls = array("π" => substr($queryAds[0], 2));
} elseif ($queryAds[0] === "none") {
$featuredTotal = "0";
$notableFlagClass = "noblock";
@ -190,38 +176,34 @@ if ($queryAds[0] === "blacklist.txt") {
}
}
// Merge $intBlacklist with $adlistsUrls if domain has been blacklisted or wildcarded
if (isset($intBlacklist)) $adlistsUrls = array_merge($intBlacklist, $adlistsUrls);
// Set #bpOutput notification
$wlOutputClass = (isset($wlInfo) && $wlInfo === "recentwl") ? $wlInfo : "hidden";
$wlOutput = (isset($wlInfo) && $wlInfo !== "recentwl") ? "<a href='http://$wlInfo'>$wlInfo</a>" : "";
// Get Pi-hole core version
if ($phBranch !== "master") {
$phVersion = exec("cd /etc/.pihole/ && git describe --long --dirty --tags");
$execTime = microtime(true)-$_SERVER["REQUEST_TIME_FLOAT"];
} else {
$phVersion = exec("cd /etc/.pihole/ && git describe --tags --abbrev=0");
}
// Get Pi-hole Core version
$phVersion = exec("cd /etc/.pihole/ && git describe --long --tags");
// Print $execTime on development branches
if (substr_count("-", $phVersion) != "1")
$execTime = microtime(true)-$_SERVER["REQUEST_TIME_FLOAT"];
?>
<!DOCTYPE html>
<html>
<!-- Pi-hole: A black hole for Internet advertisements
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
* Network-wide ad blocking via your own hardware.
*
* This file is copyright under the latest version of the EUPL. -->
<html>
<head>
<meta charset="UTF-8">
<?=$viewPort ?>
<?=setHeader() ?>
<meta name="robots" content="noindex,nofollow"/>
<meta http-equiv="x-dns-prefetch-control" content="off">
<link rel="shortcut icon" href="http://<?=$serverAddr ?>/admin/img/favicon.png" type="image/x-icon"/>
<link rel="stylesheet" href="http://<?=$serverAddr ?>/pihole/blockingpage.css" type="text/css"/>
<link rel="shortcut icon" href="http://pi.hole/admin/img/favicon.png" type="image/x-icon"/>
<link rel="stylesheet" href="http://pi.hole/pihole/blockingpage.css" type="text/css"/>
<title> <?=$serverName ?></title>
<script src="http://<?=$serverAddr ?>/admin/scripts/vendor/jquery.min.js"></script>
<script src="http://pi.hole/admin/scripts/vendor/jquery.min.js"></script>
<script>
window.onload = function () {
<?php
@ -280,7 +262,8 @@ if ($phBranch !== "master") {
<input id="bpMoreToggle" type="checkbox">
<div id="bpMoreInfo">
<span id="bpFoundIn"><span><?=$featuredTotal ?></span><?=$adlistsCount ?></span>
<pre id='bpQueryOutput'><?php if ($featuredTotal > 0) foreach ($queryAds as $num) { echo "<span>[$num]:</span>$adlistsUrls[$num]\n"; } ?></pre>
<pre id='bpQueryOutput'><?php if ($featuredTotal > 0) foreach ($queryResults as $num => $value) { echo "<span>[$num]:</span>$adlistsUrls[$num]\n"; } ?></pre>
<form id="bpWLButtons" class="buttons">
<input id="bpWLDomain" type="text" value="<?=$serverName ?>" disabled/>
<input id="bpWLPassword" type="password" placeholder="<?=$wlPlaceHolder ?>" disabled/><button id="bpWhitelist" type="button" disabled></button>
@ -288,7 +271,7 @@ if ($phBranch !== "master") {
</div>
</main>
<footer><span><?=date("l g:i A, F dS"); ?>.</span> Pi-hole <?=$phVersion ?> (<?=gethostname()."/".$serverAddr; if (isset($execTime)) printf("/%.2fs", $execTime); ?>)</footer>
<footer><span><?=date("l g:i A, F dS"); ?>.</span> Pi-hole <?=$phVersion ?> (<?=gethostname()."/".$_SERVER["SERVER_ADDR"]; if (isset($execTime)) printf("/%.2fs", $execTime); ?>)</footer>
</div>
<script>