Merge pull request #1416 from WaLLy3K/blockpage2

Block Page 2.0
pull/1691/head
WaLLy3K 7 years ago committed by GitHub
commit e7ae62ba76

@ -1,136 +1,384 @@
/* CSS Reset */ /* Pi-hole: A black hole for Internet advertisements
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit; vertical-align: baseline; } * (c) 2017 Pi-hole, LLC (https://pi-hole.net)
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { display: block; } * Network-wide ad blocking via your own hardware.
body { line-height: 1; } *
ol, ul { list-style: none; } * This file is copyright under the latest version of the EUPL.
blockquote, q { quotes: none; } * Please see LICENSE file for your rights under this license. */
blockquote:before, blockquote:after, q:before, q:after { content: ''; content: none; }
table { border-collapse: collapse; border-spacing: 0; } /* Text Customisation Options ======> */
html { height: 100%; overflow-x: hidden; } .title:before { content: "Website Blocked"; }
.altBtn:before { content: "Why am I here?"; }
/* General Style */ .linkPH:before { content: "About Pi-hole"; }
a { color: rgba(0,60,120,0.95); text-decoration: none; } /* 1E3C5A */ .linkEmail:before { content: "Contact Admin"; }
a:hover { color: rgba(210,120,0,0.95); transition-duration: .2s; } /* 255, 128, 0 */
divs a { border-bottom: 1px dashed rgba(30,60,90,0.3); } #bpOutput.add:before { content: "Info"; }
b { font-weight: bold; } #bpOutput.add:after { content: "The domain is being whitelisted..."; }
i { font-style: italic; } #bpOutput.error:before, .unhandled:before { content: "Error"; }
#bpOutput.unhandled:after { content: "An unhandled exception occured. This may happen when your browser is unable to load jQuery, or when the webserver is denying access to the Pi-hole API."; }
footer, pre, td { font-family: monospace; padding-left: 15px; } #bpOutput.success:before { content: "Success"; }
/*body, header { background: #E1E1E1; }*/ #bpOutput.success:after { content: "Website has been whitelisted! You may need to flush your DNS cache"; }
.recentwl:before { content: "This site has been whitelisted. Please flush your DNS cache and/or restart your browser."; }
.unknown:before { content: "This website is not found in any of Pi-hole's blacklists. The reason you have arrived here is unknown."; }
.cname:before { content: "This site is an alias for "; } /* <a href="http://cname.com">cname.com</a> */
.cname:after { content: ", which may be blocked by Pi-hole."; }
.blacklist:before { content: "Manually Blacklisted"; }
.wildcard:before { content: "Manually Blacklisted by Wildcard"; }
.noblock:before { content: "Not found on any Blacklist"; }
#bpBlock:before { content: "Access to the following website has been denied:"; }
#bpFlag:before { content: "This is primarily due to being flagged as:"; }
#bpHelpTxt:before { content: "If you have an ongoing use for this website, please "; }
#bpHelpTxt a:before, #bpHelpTxt span:before { content: "ask the administrator"; }
#bpHelpTxt:after{ content: " of the Pi-hole on this network to have it whitelisted"; }
#bpBack:before { content: "Back to safety"; }
#bpInfo:before { content: "Technical Info"; }
#bpFoundIn:before { content: "This site is found in "; }
#bpFoundIn span:after { content: " of "; }
#bpFoundIn:after { content: " lists:"; }
#bpWhitelist:before { content: "Whitelist"; }
footer span:before { content: "Page generated on "; }
/* Hide whitelisting form entirely */
/* #bpWLButtons { display: none; } */
/* Text Customisation Options <=============================== */
/* http://necolas.github.io/normalize.css ======> */
html { font-family: sans-serif; line-height: 1.15; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; }
body { margin: 0; }
article, aside, footer, header, nav, section { display: block; }
h1 { font-size: 2em; margin: 0.67em 0; }
figcaption, figure, main { display: block; }
figure { margin: 1em 40px; }
hr { box-sizing: content-box; height: 0; overflow: visible; }
pre { font-family: monospace, monospace; font-size: 1em; }
a { background-color: transparent; -webkit-text-decoration-skip: objects; }
a:active, a:hover { outline-width: 0; }
abbr[title] { border-bottom: none; text-decoration: underline; text-decoration: underline dotted; }
b, strong { font-weight: inherit; }
b, strong { font-weight: bolder; }
code, kbd, samp { font-family: monospace, monospace; font-size: 1em; }
dfn { font-style: italic; }
mark { background-color: #ff0; color: #000; }
small { font-size: 80%; }
sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }
sub { bottom: -0.25em; }
sup { top: -0.5em; }
audio, video { display: inline-block; }
audio:not([controls]) { display: none; height: 0; }
img { border-style: none; }
svg:not(:root) { overflow: hidden; }
button, input, optgroup, select, textarea { font-family: sans-serif; font-size: 100%; line-height: 1.15; margin: 0; }
button, input { overflow: visible; }
button, select { text-transform: none; }
button, html [type="button"], [type="reset"], [type="submit"] { -webkit-appearance: button; }
button::-moz-focus-inner, [type="button"]::-moz-focus-inner, [type="reset"]::-moz-focus-inner, [type="submit"]::-moz-focus-inner { border-style: none; padding: 0; }
button:-moz-focusring, [type="button"]:-moz-focusring, [type="reset"]:-moz-focusring, [type="submit"]:-moz-focusring { outline: 1px dotted ButtonText; }
fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em; }
legend { box-sizing: border-box; color: inherit; display: table; max-width: 100%; padding: 0; white-space: normal; }
progress { display: inline-block; vertical-align: baseline; }
textarea { overflow: auto; }
[type="checkbox"], [type="radio"] { box-sizing: border-box; padding: 0; }
[type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-outer-spin-button { height: auto; }
[type="search"] { -webkit-appearance: textfield; outline-offset: -2px; }
[type="search"]::-webkit-search-cancel-button, [type="search"]::-webkit-search-decoration { -webkit-appearance: none; }
::-webkit-file-upload-button { -webkit-appearance: button; font: inherit; }
details, menu { display: block; }
summary { display: list-item; }
canvas { display: inline-block; }
template { display: none; }
[hidden] { display: none; }
/* Normalize.css <=============================== */
html { font-size: 62.5%; }
a { color: #3c8dbc; text-decoration: none; }
a:hover { color: #72afda; text-decoration: underline; }
b { color: rgb(68,68,68); }
p { margin: 0; }
label, .buttons a {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
label, .buttons *:not([disabled]) { cursor: pointer; }
/* Touch device dark tap highlight */
header h1 a, label, .buttons * { -webkit-tap-highlight-color: transparent; }
/* Webkit Focus Glow */
textarea, input, button { outline: none; }
@font-face {
font-family: "Source Sans Pro";
font-style: normal;
font-weight: 400;
src: local("Source Sans Pro"), local("SourceSansPro-Regular"), url("/admin/style/vendor/SourceSansPro/SourceSansPro-Regular.ttf") format("truetype");
}
@font-face {
font-family: "Source Sans Pro";
font-style: normal;
font-weight: 700;
src: local("Source Sans Pro Bold"), local("SourceSansPro-Bold"), url("/admin/style/vendor/SourceSansPro/SourceSansPro-Bold.ttf") format("truetype");
}
body { body {
background-image: -webkit-linear-gradient(top, rgba(240,240,240,0.95), rgba(190,190,190,0.95)); background: #dbdbdb url("/admin/img/boxed-bg.jpg") repeat fixed;
background-image: linear-gradient(to bottom, rgba(240,240,240,0.95), rgba(190,190,190,0.95)); color: #333;
background-attachment: fixed; font: 1.4rem "Source Sans Pro", "Helvetica Neue", Helvetica, Arial, sans-serif;
color: rgba(64,64,64,0.95); line-height: 2.2rem;
font: 14px, sans-serif; }
line-height: 1em;
/* User is greeted with a splash page when browsing to Pi-hole IP address */
#splashpage { background: #222; color: rgba(255,255,255,0.7); text-align: center; }
#splashpage img { margin: 5px; width: 256px; }
#splashpage b { color: inherit; }
#bpWrapper {
margin: 0 auto;
max-width: 1250px;
box-shadow: 0 0 8px rgba(0,0,0,0.5);
} }
header { header {
min-width: 320px; background: #3c8dbc;
width: 100%;
text-shadow: 0 1px rgba(255,255,255,0.6);
display: table; display: table;
table-layout: fixed; position: relative;
border: 1px solid rgba(0,0,0,0.25); width: 100%;
border-top-color: rgba(255,255,255,0.85);
border-style: solid none;
background-image: -webkit-linear-gradient(top, rgba(240,240,240,0.95), rgba(220,220,220,0.95));
background-image: linear-gradient(to bottom, rgba(240,240,240,0.95), rgba(220,220,220,0.95));
box-shadow: 0 0 1px 1px rgba(0,0,0,0.04);
} }
header h1, header div { header h1, header h1 a, header .spc, header #bpAlt label {
display: table-cell; display: table-cell;
color: inherit; color: #fff;
font-weight: bold;
vertical-align: middle;
white-space: nowrap; white-space: nowrap;
overflow: hidden; vertical-align: middle;
height: 50px; /* Must match #bpAbout top value */
}
h1 a {
background-color: rgba(0,0,0,0.1);
font-family: "Helvetica Neue", Helvetica, Arial ,sans-serif;
font-size: 2rem;
font-weight: normal;
min-width: 230px;
text-align: center;
}
h1 a:hover, header #bpAlt:hover { background-color: rgba(0,0,0,0.12); color: inherit; text-decoration: none; }
header .spc { width: 100%; }
header #bpAlt label {
background: url("/admin/img/logo.svg") no-repeat center left 15px;
background-size: 15px 23px;
padding: 0 15px;
text-indent: 30px;
}
[type=checkbox][id$="Toggle"] { display: none; }
[type=checkbox][id$="Toggle"]:checked ~ #bpAbout,
[type=checkbox][id$="Toggle"]:checked ~ #bpMoreInfo {
display: block; }
/* Click anywhere else on screen to hide #bpAbout */
#bpAboutToggle:checked {
display: block;
height: 300px; /* VH Fallback */
height: 100vh;
left: 0;
top: 0;
opacity: 0;
position: absolute;
width: 100%;
}
#bpAbout {
background: #3c8dbc;
border-bottom-left-radius: 5px;
border: 1px solid #FFF;
border-right-width: 0;
box-shadow: -1px 1px 1px rgba(0,0,0,0.12);
box-sizing: border-box; box-sizing: border-box;
display: none;
font-size: 1.7rem;
top: 50px;
position: absolute;
right: 0;
width: 280px;
z-index: 1;
} }
header h1 { .aboutPH {
font-size: 22px; box-sizing: border-box;
font-weight: bold; color: rgba(255,255,255,0.8);
display: block;
padding: 10px;
width: 100%; width: 100%;
padding: 8px 0; text-align: center;
text-indent: 32px;
background: url("http://pi.hole/admin/img/logo.svg") left no-repeat;
background-size: 30px 22px;
} }
header h1 a, h1 a:hover { color: inherit; } .aboutImg {
header .alt { width: 85px; font-size: 0.8em; padding-right: 4px; text-align: right; line-height: 1.25em; } background: url("/admin/img/logo.svg") no-repeat center;
.active { color: green; } background-size: 90px 90px;
.inactive { color: red; } border: 3px solid rgba(255,255,255,0.2);
height: 90px;
margin: 0 auto;
padding: 2px;
width: 90px;
}
.aboutPH p { margin: 10px 0; }
.aboutPH small { display: block; font-size: 1.2rem; }
.aboutLink {
background: #fff;
border-top: 1px solid #ddd;
display: table;
font-size: 1.4rem;
text-align: center;
width: 100%;
}
.aboutLink a {
display: table-cell;
padding: 14px;
min-width: 50%;
}
main { main {
display: block; background: #ecf0f5;
width: 80%; font-size: 1.65rem;
padding: 10px; padding: 10px;
font-size: 1em; }
background-color: rgba(255,255,255,0.85);
margin: 8px auto; #bpOutput {
box-sizing: border-box; background: #00c0ef;
border: 1px solid rgba(0,0,0,0.25); border-radius: 3px;
box-shadow: 4px 4px rgba(0,0,0,0.1); border: 1px solid rgba(0,0,0,0.1);
line-height: 1.2em; color: #fff;
border-radius: 8px; font-size: 1.4rem;
} margin-bottom: 10px;
margin-top: 5px;
h2 { /* Rgba is shared with .transparent th */ padding: 15px;
font: 1.15em sans-serif; }
background-color: rgba(255,0,0,0.4);
text-shadow: none; #bpOutput:before {
line-height: 1.1em; background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='7' height='14' viewBox='0 0 7 14'%3E%3Cpath fill='%23fff' d='M6,11a1.371,1.371,0,0,1,1,1v1a1.371,1.371,0,0,1-1,1H1a1.371,1.371,0,0,1-1-1V12a1.371,1.371,0,0,1,1-1H2V8H1A1.371,1.371,0,0,1,0,7V6A1.371,1.371,0,0,1,1,5H4A1.371,1.371,0,0,1,5,6v5H6ZM3.5,0A1.5,1.5,0,1,1,2,1.5,1.5,1.5,0,0,1,3.5,0Z'/%3E%3C/svg%3E") no-repeat center left;
padding-bottom: 1px; display: block;
margin-top: 8px; font-size: 1.8rem;
margin-bottom: 4px; text-indent: 15px;
background: -webkit-linear-gradient(left, rgba(0,0,0,0.25), transparent 80%) no-repeat; }
background: linear-gradient(to right, rgba(0,0,0,0.25), transparent 80%) no-repeat;
background-size: 100% 1px; #bpOutput.hidden { display: none; }
background-position: 0 17px; #bpOutput.success { background: #00a65a; }
} #bpOutput.error { background: #dd4b39; }
h2:first-child { margin-top: 0; } .blockMsg, .flagMsg {
h2 ~ *:not(h2) { margin-left: 4px; } font: bold 1.8rem Consolas, Courier, monospace;
li { padding: 2px 0; } padding: 5px 10px 10px 10px;
li::before { content: "\00BB\00a0"; } text-indent: 15px;
li a { position: relative; top: 1px; } /* Center bullet-point arrows */ }
/* Button Style */ #bpHelpTxt { padding-bottom: 10px; }
.buttons a, button, input, .transparent th a { /* Swapped rgba is shared with input[type='url'] */
display: inline-block; .buttons {
color: rgba(32,32,32,0.9); border-spacing: 5px 0;
font-weight: bold; display: table;
width: 100%;
}
.buttons * {
-moz-appearance: none;
-webkit-appearance: none;
border-radius: 3px;
border: 1px solid rgba(0,0,0,0.1);
box-sizing: content-box;
display: table-cell;
font-size: 1.65rem;
margin-right: 5px;
min-height: 20px;
padding: 6px 12px;
position: relative;
text-align: center; text-align: center;
cursor: pointer; vertical-align: top;
text-shadow: 0 1px rgba(255,255,255,0.2); white-space: nowrap;
line-height: 0.86em; width: auto;
font-size: 1em; }
padding: 4px 8px;
background: #FAFAFA; .buttons a:hover { text-decoration: none; }
background-image: -webkit-linear-gradient(top, rgba(255,255,255,0.05), rgba(0,0,0,0.05));
background-image: linear-gradient(to bottom, rgba(255,255,255,0.05), rgba(0,0,0,0.05)); /* Button hover dark overlay */
border: 1px solid rgba(0,0,0,0.25); .buttons *:not(input):not([disabled]):hover {
border-radius: 4px; background-image: linear-gradient(to bottom, rgba(0,0,0,0.1), rgba(0,0,0,0.1));
box-shadow: 0 1px 0 rgba(0,0,0,0.04); color: #FFF;
} }
.buttons { white-space: nowrap; width: 100%; display: table; } /* Button active shadow inset */
.buttons33 { white-space: nowrap; width: 33.333%; display: table; text-align: center; margin-left: 33.333% } .buttons *:not([disabled]):not(input):active {
.mini a { width: 50%; } box-shadow: inset 0 3px 5px rgba(0,0,0,0.125);
a.safe { background-color: rgba(0,220,0,0.5); } }
button.safe { background-color: rgba(0,220,0,0.5); }
a.warn { background-color: rgba(220,0,0,0.5); } /* Input border colour */
.buttons *:not([disabled]):hover, .buttons input:focus {
.blocked a, .mini a { display: table-cell; } border-color: rgba(0,0,0,0.25);
.blocked a.safe50 { width: 50%; background-color: rgba(0,220,0,0.5); } }
.blocked a.safe33 { width: 33.333%; background-color: rgba(0,220,0,0.5); }
#bpButtons * { width: 50%; color: #FFF; }
/* Types of text */ #bpBack { background-color: #00a65a; }
.msg { white-space: pre; overflow: auto; -webkit-overflow-scrolling: touch; display: block; line-height: 1.2em; font-weight: bold; font-size: 1.15em; margin: 4px 8px 8px 8px; white-space: pre-line; } #bpInfo { background-color: #3c8dbc; }
#bpWhitelist { background-color: #dd4b39; }
footer { font-size: 0.8em; text-align: center; width: 87%; margin: 4px auto; }
#blockpage .buttons [type=password][disabled] { color: rgba(0,0,0,1); }
#blockpage .buttons [disabled] { color: rgba(0,0,0,0.55); background-color: #e3e3e3; }
#blockpage .buttons [type=password]:-ms-input-placeholder { color: rgba(51,51,51,0.8); }
input[type=password] { font-size: 1.5rem; }
@keyframes slidein { from { max-height: 0; opacity: 0; } to { max-height: 300px; opacity: 1; } }
#bpMoreToggle:checked ~ #bpMoreInfo { display: block; margin-top: 8px; animation: slidein 0.05s linear; }
#bpMoreInfo { display: none; margin-top: 10px; }
#bpQueryOutput {
font-size: 1.2rem;
line-height: 1.65rem;
margin: 5px 0 0 0;
overflow: auto;
padding: 0 5px;
-webkit-overflow-scrolling: touch;
}
#bpQueryOutput span { margin-right: 4px; }
#bpWLButtons { width: auto; margin-top: 10px; }
#bpWLButtons * { display: inline-block; }
#bpWLDomain { display: none; }
#bpWLPassword { width: 160px; }
#bpWhitelist { color: #fff; }
footer {
background: #fff;
border-top: 1px solid #d2d6de;
color: #444;
font: 1.2rem Consolas, Courier, monospace;
padding: 8px;
}
/* Responsive Content */
@media only screen and (max-width: 500px) {
h1 a { font-size: 1.8rem; min-width: 170px; }
footer span:before { content: "Generated "; }
footer span { display: block; }
}
@media only screen and (min-width: 1251px) {
#bpWrapper, footer { border-radius: 0 0 5px 5px; }
#bpAbout { border-right-width: 1px; }
}

@ -1 +1 @@
var x = "Pi-hole: A black hole for Internet advertisements." var x = ""

@ -1,225 +1,319 @@
<?php <?php
/* Detailed Pi-hole Block Page: Show "Website Blocked" if user browses to site, but not to image/file requests based on the work of WaLLy3K for DietPi & Pi-Hole */ /* Pi-hole: A black hole for Internet advertisements
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
* Network-wide ad blocking via your own hardware.
*
* This file is copyright under the latest version of the EUPL.
* Please see LICENSE file for your rights under this license. */
function validIP($address){ // Sanitise HTTP_HOST output
if (preg_match('/[.:0]/', $address) && !preg_match('/[1-9a-f]/', $address)) { $serverName = htmlspecialchars($_SERVER["HTTP_HOST"]);
// Test if address contains either `:` or `0` but not 1-9 or a-f
return false; // Get values from setupVars.conf
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>");
} }
return !filter_var($address, FILTER_VALIDATE_IP) === false;
// 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
$authorizedHosts = [];
// Append FQDN to $authorizedHosts
if (!empty($svFQDN)) array_push($authorizedHosts, $svFQDN);
// Append virtual hostname to $authorizedHosts
if (!empty($_SERVER["VIRTUAL_HOST"])) {
array_push($authorizedHosts, $_SERVER["VIRTUAL_HOST"]);
}
// 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
$currentUrlExt = pathinfo($_SERVER["REQUEST_URI"], PATHINFO_EXTENSION);
// Set mobile friendly viewport
$viewPort = '<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>';
// Set response header
function setHeader($type = "x") {
header("X-Pi-hole: A black hole for Internet advertisements.");
if (isset($type) && $type === "js") header("Content-Type: application/javascript");
} }
$uri = escapeshellcmd($_SERVER['REQUEST_URI']); // Determine block page redirect type
$serverName = escapeshellcmd($_SERVER['SERVER_NAME']); if ($serverName === "pi.hole") {
exit(header("Location: /admin"));
} elseif (filter_var($serverName, FILTER_VALIDATE_IP) || in_array($serverName, $authorizedHosts)) {
// 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>
";
// If the server name is 'pi.hole', it's likely a user trying to get to the admin panel. // Render splash page or landing page when directly browsing via IP or auth'd hostname
// Let's be nice and redirect them. $renderPage = is_file(getcwd()."/$landPage") ? include $landPage : "$splashPage";
if ($serverName === 'pi.hole') unset($serverName, $svFQDN, $svPasswd, $svEmail, $authorizedHosts, $validExtTypes, $currentUrlExt, $viewPort);
{ exit($renderPage);
header('HTTP/1.1 301 Moved Permanently'); } elseif ($currentUrlExt === "js") {
header("Location: /admin/"); // 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"])) {
// 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"], "?")) {
// 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>
<body>$blockImg</body>
</html>");
} }
// Retrieve server URI extension (EG: jpg, exe, php) /* Start processing Block Page from here */
// strtok($uri, '\?') splits the querystring from the path (if there is a querystring)
ini_set('pcre.recursion_limit',100);
$uriExt = pathinfo(strtok($uri,'\?'), PATHINFO_EXTENSION);
// Define which URL extensions get rendered as "Website Blocked" // Determine placeholder text based off $svPasswd presence
$webExt = array('asp', 'htm', 'html', 'php', 'rss', 'xml'); $wlPlaceHolder = empty($svPasswd) ? "No admin password set" : "Javascript disabled";
// Get IPv4 and IPv6 addresses from setupVars.conf (if available) // Define admin email address text
$setupVars = parse_ini_file("/etc/pihole/setupVars.conf"); $bpAskAdmin = !empty($svEmail) ? '<a href="mailto:'.$svEmail.'?subject=Site Blocked: '.$serverName.'"></a>' : "<span/>";
$ipv4 = isset($setupVars["IPV4_ADDRESS"]) ? explode("/", $setupVars["IPV4_ADDRESS"])[0] : $_SERVER['SERVER_ADDR'];
$ipv6 = isset($setupVars["IPV6_ADDRESS"]) ? explode("/", $setupVars["IPV6_ADDRESS"])[0] : $_SERVER['SERVER_ADDR']; // Determine if at least one block list has been generated
if (empty(glob("/etc/pihole/list.0.*.domains")))
$AUTHORIZED_HOSTNAMES = array( 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>.");
$ipv4,
$ipv6, // Set location of adlists file
str_replace(array("[","]"), array("",""), $_SERVER["SERVER_ADDR"]), if (is_file("/etc/pihole/adlists.list")) {
"pi.hole", $adLists = "/etc/pihole/adlists.list";
"localhost"); } elseif (is_file("/etc/pihole/adlists.default")) {
// Allow user set virtual hostnames $adLists = "/etc/pihole/adlists.default";
$virtual_host = getenv('VIRTUAL_HOST'); } else {
if (!empty($virtual_host)) die("[ERROR] File not found: <code>/etc/pihole/adlists.list</code>");
array_push($AUTHORIZED_HOSTNAMES, $virtual_host);
// Immediately quit since we didn't block this page (the IP address or pi.hole is explicitly requested)
if(validIP($serverName) || in_array($serverName,$AUTHORIZED_HOSTNAMES))
{
http_response_code(404);
die();
}
if(in_array($uriExt, $webExt) || empty($uriExt))
{
// Requested resource has an extension listed in $webExt
// or no extension (index access to some folder incl. the root dir)
$showPage = true;
}
else
{
// Something else
$showPage = false;
}
// Handle incoming URI types
if (!$showPage)
{
?>
<html>
<head>
<script>window.close();</script></head>
<body>
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">
</body>
</html>
<?php
die();
} }
// Get Pi-hole version // Get all URLs starting with "http" or "www" from adlists and re-index array numerically
$piHoleVersion = exec('cd /etc/.pihole/ && git describe --tags --abbrev=0'); $adlistsUrls = array_values(preg_grep("/(^http)|(^www)/i", file($adLists, FILE_IGNORE_NEW_LINES)));
// Don't show the URI if it is the root directory if (empty($adlistsUrls))
if($uri == "/") die("[ERROR]: There are no adlist URL's found within <code>$adLists</code>");
{
$uri = ""; // 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&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 (!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>)");
}
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>");
} 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, whitelisted, wildcarded or CNAME blocked
if (strpos($queryAds[0], "blacklist") !== FALSE) {
$notableFlagClass = "blacklist";
$adlistsUrls = array("π" => substr($queryAds[0], 2));
} elseif (strpos($queryAds[0], "whitelist") !== FALSE) {
$notableFlagClass = "noblock";
$adlistsUrls = array("π" => substr($queryAds[0], 2));
$wlInfo = "recentwl";
} elseif (strpos($queryAds[0], "wildcard") !== FALSE) {
$notableFlagClass = "wildcard";
$adlistsUrls = array("π" => substr($queryAds[0], 2));
} elseif ($queryAds[0] === "none") {
$featuredTotal = "0";
$notableFlagClass = "noblock";
// Determine appropriate info message if CNAME exists
$dnsRecord = dns_get_record("$serverName")[0];
if (array_key_exists("target", $dnsRecord)) {
$wlInfo = $dnsRecord['target'];
} else {
$wlInfo = "unknown";
}
}
// 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
$phVersion = exec("cd /etc/.pihole/ && git describe --long --tags");
// Print $execTime on development branches
// Marginally faster than "git rev-parse --abbrev-ref HEAD"
if (explode("-", $phVersion)[1] != "0")
$execTime = microtime(true)-$_SERVER["REQUEST_TIME_FLOAT"];
?> ?>
<!DOCTYPE html> <!DOCTYPE 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> <html>
<head> <head>
<meta charset='UTF-8'/> <meta charset="UTF-8">
<title>Website Blocked</title> <?=$viewPort ?>
<link rel='stylesheet' href='http://pi.hole/pihole/blockingpage.css'/> <?=setHeader() ?>
<link rel='shortcut icon' href='http://pi.hole/admin/img/favicon.png' type='image/png'/> <meta name="robots" content="noindex,nofollow"/>
<meta name='viewport' content='width=device-width,initial-scale=1.0,maximum-scale=1.0, user-scalable=no'/> <meta http-equiv="x-dns-prefetch-control" content="off">
<meta name='robots' content='noindex,nofollow'/> <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://pi.hole/admin/scripts/vendor/jquery.min.js"></script>
<script>
window.onload = function () {
<?php
// Remove href fallback from "Back to safety" button
if ($featuredTotal > 0) echo '$("#bpBack").removeAttr("href");';
// Enable whitelisting if $svPasswd is present & JS is available
if (!empty($svPasswd) && $featuredTotal > 0) {
echo '$("#bpWLPassword, #bpWhitelist").prop("disabled", false);';
echo '$("#bpWLPassword").attr("placeholder", "Password");';
}
?>
}
</script>
</head> </head>
<body id="body"> <body id="blockpage"><div id="bpWrapper">
<header> <header>
<h1><a href='/'>Website Blocked</a></h1> <h1 id="bpTitle">
<a class="title" href="/"><?php //Website Blocked ?></a>
</h1>
<div class="spc"></div>
<input id="bpAboutToggle" type="checkbox"/>
<div id="bpAbout">
<div class="aboutPH">
<div class="aboutImg"/></div>
<p>Open Source Ad Blocker
<small>Designed for Raspberry Pi</small>
</p>
</div>
<div class="aboutLink">
<a class="linkPH" href="https://github.com/pi-hole/pi-hole/wiki/What-is-Pi-hole%3F-A-simple-explanation"><?php //About PH ?></a>
<?php if (!empty($svEmail)) echo '<a class="linkEmail" href="mailto:'.$svEmail.'"></a>'; ?>
</div>
</div>
<div id="bpAlt">
<label class="altBtn" for="bpAboutToggle"><?php //Why am I here? ?></label>
</div>
</header> </header>
<main> <main>
<div>Access to the following site has been blocked:<br/> <div id="bpOutput" class="<?=$wlOutputClass ?>"><?=$wlOutput ?></div>
<span class='pre msg'><?php echo $serverName.$uri; ?></span></div> <div id="bpBlock">
<div>If you have an ongoing use for this website, please ask the owner of the Pi-hole in your network to have it whitelisted.</div> <p class="blockMsg"><?=$serverName ?></p>
<input id="domain" type="hidden" value="<?php echo $serverName; ?>">
<input id="quiet" type="hidden" value="yes">
<button id="btnSearch" class="buttons blocked" type="button" style="visibility: hidden;"></button>
This page is blocked because it is explicitly contained within the following block list(s):
<pre id="output" style="width: 100%; height: 100%;" hidden="true"></pre><br/>
<div class='buttons blocked'>
<a class='safe33' href='javascript:history.back()'>Go back</a>
<a class='safe33' id="whitelisting">Whitelist this page</a>
<a class='safe33' href='javascript:window.close()'>Close window</a>
</div> </div>
<div style="width: 98%; text-align: center; padding: 10px;" hidden="true" id="whitelistingform"> <?php if(isset($notableFlagClass)) { ?>
<p>Note that whitelisting domains which are blocked using the wildcard method won't work.</p> <div id="bpFlag">
<p>Password required!</p><br/> <p class="flagMsg <?=$notableFlagClass ?>"></p>
<form>
<input name="list" type="hidden" value="white"><br/>
Domain:<br/>
<input name="domain" value="<?php echo $serverName ?>" disabled><br/><br/>
Password:<br/>
<input type="password" id="pw" name="pw"><br/><br/>
<button class="buttons33 safe" id="btnAdd" type="button">Whitelist</button>
</form><br/>
<pre id="whitelistingoutput" style="width: 100%; height: 100%; padding: 5px;" hidden="true"></pre><br/>
</div> </div>
</main> <?php } ?>
<footer>Generated <?php echo date('D g:i A, M d'); ?> by Pi-hole <?php echo $piHoleVersion; ?></footer> <div id="bpHelpTxt"><?=$bpAskAdmin ?></div>
<script src="http://pi.hole/admin/scripts/vendor/jquery.min.js"></script> <div id="bpButtons" class="buttons">
<script> <a id="bpBack" onclick="javascript:history.back()" href="about:home"></a>
// Create event for when the output is appended to <?php if ($featuredTotal > 0) echo '<label id="bpInfo" for="bpMoreToggle"></label>'; ?>
(function($) { </div>
var origAppend = $.fn.append; <input id="bpMoreToggle" type="checkbox">
<div id="bpMoreInfo">
$.fn.append = function () { <span id="bpFoundIn"><span><?=$featuredTotal ?></span><?=$adlistsCount ?></span>
return origAppend.apply(this, arguments).trigger("append"); <pre id='bpQueryOutput'><?php if ($featuredTotal > 0) foreach ($queryResults as $num => $value) { echo "<span>[$num]:</span>$adlistsUrls[$num]\n"; } ?></pre>
};
})(jQuery);
</script>
<script src="http://pi.hole/admin/scripts/pi-hole/js/queryads.js"></script>
<script>
function inIframe () {
try {
return window.self !== window.top;
} catch (e) {
return true;
}
}
// Try to detect if page is loaded within iframe
if(inIframe())
{
// Within iframe
// hide content of page
$('#body').hide();
// remove background
document.body.style.backgroundImage = "none";
}
else
{
// Query adlists
$( "#btnSearch" ).click();
}
$( "#whitelisting" ).on( "click", function(){ $( "#whitelistingform" ).removeAttr( "hidden" ); }); <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>
</form>
</div>
</main>
// Remove whitelist functionality if the domain was blocked because of a wildcard <footer><span><?=date("l g:i A, F dS"); ?>.</span> Pi-hole <?=$phVersion ?> (<?=gethostname()."/".$_SERVER["SERVER_ADDR"]; if (isset($execTime)) printf("/%.2fs", $execTime); ?>)</footer>
$( "#output" ).bind("append", function(){ </div>
if($( "#output" ).contents()[0].data.indexOf("Wildcard blocking") !== -1)
{
$( "#whitelisting" ).hide();
$( "#whitelistingform" ).hide();
}
});
<script>
function add() { function add() {
var domain = $("#domain"); $("#bpOutput").removeClass("hidden error exception");
var pw = $("#pw"); $("#bpOutput").addClass("add");
if(domain.val().length === 0){ var domain = "<?=$serverName ?>";
var pw = $("#bpWLPassword");
if(domain.length === 0) {
return; return;
} }
$.ajax({ $.ajax({
url: "/admin/scripts/pi-hole/php/add.php", url: "/admin/scripts/pi-hole/php/add.php",
method: "post", method: "post",
data: {"domain":domain.val(), "list":"white", "pw":pw.val()}, data: {"domain":domain, "list":"white", "pw":pw.val()},
success: function(response) { success: function(response) {
$( "#whitelistingoutput" ).removeAttr( "hidden" ); if(response.indexOf("Pi-hole blocking") !== -1) {
if(response.indexOf("Pi-hole blocking") !== -1) setTimeout(function(){window.location.reload(1);}, 10000);
{ $("#bpOutput").removeClass("add");
// Reload page after 5 seconds $("#bpOutput").addClass("success");
setTimeout(function(){window.location.reload(1);}, 5000); } else {
$( "#whitelistingoutput" ).html("---> Success <---<br/>You may have to flush your DNS cache"); $("#bpOutput").removeClass("add");
} $("#bpOutput").addClass("error");
else $("#bpOutput").html(""+response+"");
{
$( "#whitelistingoutput" ).html("---> "+response+" <---");
} }
}, },
error: function(jqXHR, exception) { error: function(jqXHR, exception) {
$( "#whitelistingoutput" ).removeAttr( "hidden" ); $("#bpOutput").removeClass("add");
$( "#whitelistingoutput" ).html("---> Unknown Error <---"); $("#bpOutput").addClass("exception");
} }
}); });
} }
// Handle enter button for adding domains <?php if ($featuredTotal > 0) { ?>
$(document).keypress(function(e) { $(document).keypress(function(e) {
if(e.which === 13 && $("#pw").is(":focus")) { if(e.which === 13 && $("#bpWLPassword").is(":focus")) {
add(); add();
} }
}); });
$("#bpWhitelist").on("click", function() {
// Handle buttons
$("#btnAdd").on("click", function() {
add(); add();
}); });
<?php } ?>
</script> </script>
</body> </body></html>
</html>

Loading…
Cancel
Save