mirror of
https://github.com/pi-hole/pi-hole.git
synced 2024-11-15 10:43:55 +00:00
Merge branch 'development' into tweak/gravity
This commit is contained in:
commit
ee2169dd13
7 changed files with 683 additions and 338 deletions
|
@ -1,4 +1,6 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
|
||||||
# Pi-hole: A black hole for Internet advertisements
|
# Pi-hole: A black hole for Internet advertisements
|
||||||
# (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
# (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||||
# Network-wide ad blocking via your own hardware.
|
# Network-wide ad blocking via your own hardware.
|
||||||
|
@ -30,6 +32,7 @@ Options:
|
||||||
-f, fahrenheit Set Fahrenheit as preferred temperature unit
|
-f, fahrenheit Set Fahrenheit as preferred temperature unit
|
||||||
-k, kelvin Set Kelvin as preferred temperature unit
|
-k, kelvin Set Kelvin as preferred temperature unit
|
||||||
-r, hostrecord Add a name to the DNS associated to an IPv4/IPv6 address
|
-r, hostrecord Add a name to the DNS associated to an IPv4/IPv6 address
|
||||||
|
-e, email Set an administrative contact address for the Block Page
|
||||||
-h, --help Show this help dialog
|
-h, --help Show this help dialog
|
||||||
-i, interface Specify dnsmasq's interface listening behavior
|
-i, interface Specify dnsmasq's interface listening behavior
|
||||||
Add '-h' for more info on interface usage"
|
Add '-h' for more info on interface usage"
|
||||||
|
@ -414,6 +417,27 @@ Options:
|
||||||
RestartDNS
|
RestartDNS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SetAdminEmail() {
|
||||||
|
if [[ "${1}" == *"-h"* ]]; then
|
||||||
|
echo "Usage: pihole -a email <address>
|
||||||
|
Example: 'pihole -a email admin@address.com'
|
||||||
|
Set an administrative contact address for the Block Page
|
||||||
|
|
||||||
|
Options:
|
||||||
|
\"\" Empty: Remove admin contact
|
||||||
|
-h, --help Show this help dialog"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "${args[2]}" ]]; then
|
||||||
|
change_setting "ADMIN_EMAIL" "${args[2]}"
|
||||||
|
echo -e " ${TICK} Setting admin contact to ${args[2]}"
|
||||||
|
else
|
||||||
|
change_setting "ADMIN_EMAIL" ""
|
||||||
|
echo -e " ${TICK} Removing admin contact"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
SetListeningMode() {
|
SetListeningMode() {
|
||||||
source "${setupVars}"
|
source "${setupVars}"
|
||||||
|
|
||||||
|
@ -484,6 +508,7 @@ main() {
|
||||||
"addstaticdhcp" ) AddDHCPStaticAddress;;
|
"addstaticdhcp" ) AddDHCPStaticAddress;;
|
||||||
"removestaticdhcp" ) RemoveDHCPStaticAddress;;
|
"removestaticdhcp" ) RemoveDHCPStaticAddress;;
|
||||||
"-r" | "hostrecord" ) SetHostRecord "$3";;
|
"-r" | "hostrecord" ) SetHostRecord "$3";;
|
||||||
|
"-e" | "email" ) SetAdminEmail "$3";;
|
||||||
"-i" | "interface" ) SetListeningMode "$@";;
|
"-i" | "interface" ) SetListeningMode "$@";;
|
||||||
"-t" | "teleporter" ) Teleporter;;
|
"-t" | "teleporter" ) Teleporter;;
|
||||||
"adlist" ) CustomizeAdLists;;
|
"adlist" ) CustomizeAdLists;;
|
||||||
|
|
|
@ -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; }
|
|
||||||
html { height: 100%; overflow-x: hidden; }
|
|
||||||
|
|
||||||
/* General Style */
|
/* Text Customisation Options ======> */
|
||||||
a { color: rgba(0,60,120,0.95); text-decoration: none; } /* 1E3C5A */
|
.title:before { content: "Website Blocked"; }
|
||||||
a:hover { color: rgba(210,120,0,0.95); transition-duration: .2s; } /* 255, 128, 0 */
|
.altBtn:before { content: "Why am I here?"; }
|
||||||
divs a { border-bottom: 1px dashed rgba(30,60,90,0.3); }
|
.linkPH:before { content: "About Pi-hole"; }
|
||||||
b { font-weight: bold; }
|
.linkEmail:before { content: "Contact Admin"; }
|
||||||
i { font-style: italic; }
|
|
||||||
|
|
||||||
footer, pre, td { font-family: monospace; padding-left: 15px; }
|
#bpOutput.add:before { content: "Info"; }
|
||||||
/*body, header { background: #E1E1E1; }*/
|
#bpOutput.add:after { content: "The domain is being whitelisted..."; }
|
||||||
|
#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."; }
|
||||||
|
#bpOutput.success:before { content: "Success"; }
|
||||||
|
#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%;
|
display: table;
|
||||||
text-shadow: 0 1px rgba(255,255,255,0.6);
|
position: relative;
|
||||||
display: table;
|
width: 100%;
|
||||||
table-layout: fixed;
|
|
||||||
border: 1px solid rgba(0,0,0,0.25);
|
|
||||||
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;
|
white-space: nowrap;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
white-space: nowrap;
|
height: 50px; /* Must match #bpAbout top value */
|
||||||
overflow: hidden;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
header h1 {
|
h1 a {
|
||||||
font-size: 22px;
|
background-color: rgba(0,0,0,0.1);
|
||||||
font-weight: bold;
|
font-family: "Helvetica Neue", Helvetica, Arial ,sans-serif;
|
||||||
width: 100%;
|
font-size: 2rem;
|
||||||
padding: 8px 0;
|
font-weight: normal;
|
||||||
text-indent: 32px;
|
min-width: 230px;
|
||||||
background: url("http://pi.hole/admin/img/logo.svg") left no-repeat;
|
text-align: center;
|
||||||
background-size: 30px 22px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
header h1 a, h1 a:hover { color: inherit; }
|
h1 a:hover, header #bpAlt:hover { background-color: rgba(0,0,0,0.12); color: inherit; text-decoration: none; }
|
||||||
header .alt { width: 85px; font-size: 0.8em; padding-right: 4px; text-align: right; line-height: 1.25em; }
|
|
||||||
.active { color: green; }
|
header .spc { width: 100%; }
|
||||||
.inactive { color: red; }
|
|
||||||
|
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;
|
||||||
|
display: none;
|
||||||
|
font-size: 1.7rem;
|
||||||
|
top: 50px;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
width: 280px;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aboutPH {
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: rgba(255,255,255,0.8);
|
||||||
|
display: block;
|
||||||
|
padding: 10px;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aboutImg {
|
||||||
|
background: url("/admin/img/logo.svg") no-repeat center;
|
||||||
|
background-size: 90px 90px;
|
||||||
|
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;
|
|
||||||
box-sizing: border-box;
|
|
||||||
border: 1px solid rgba(0,0,0,0.25);
|
|
||||||
box-shadow: 4px 4px rgba(0,0,0,0.1);
|
|
||||||
line-height: 1.2em;
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 { /* Rgba is shared with .transparent th */
|
#bpOutput {
|
||||||
font: 1.15em sans-serif;
|
background: #00c0ef;
|
||||||
background-color: rgba(255,0,0,0.4);
|
border-radius: 3px;
|
||||||
text-shadow: none;
|
border: 1px solid rgba(0,0,0,0.1);
|
||||||
line-height: 1.1em;
|
color: #fff;
|
||||||
padding-bottom: 1px;
|
font-size: 1.4rem;
|
||||||
margin-top: 8px;
|
margin-bottom: 10px;
|
||||||
margin-bottom: 4px;
|
margin-top: 5px;
|
||||||
background: -webkit-linear-gradient(left, rgba(0,0,0,0.25), transparent 80%) no-repeat;
|
padding: 15px;
|
||||||
background: linear-gradient(to right, rgba(0,0,0,0.25), transparent 80%) no-repeat;
|
|
||||||
background-size: 100% 1px;
|
|
||||||
background-position: 0 17px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h2:first-child { margin-top: 0; }
|
#bpOutput:before {
|
||||||
h2 ~ *:not(h2) { margin-left: 4px; }
|
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;
|
||||||
li { padding: 2px 0; }
|
display: block;
|
||||||
li::before { content: "\00BB\00a0"; }
|
font-size: 1.8rem;
|
||||||
li a { position: relative; top: 1px; } /* Center bullet-point arrows */
|
text-indent: 15px;
|
||||||
|
|
||||||
/* Button Style */
|
|
||||||
.buttons a, button, input, .transparent th a { /* Swapped rgba is shared with input[type='url'] */
|
|
||||||
display: inline-block;
|
|
||||||
color: rgba(32,32,32,0.9);
|
|
||||||
font-weight: bold;
|
|
||||||
text-align: center;
|
|
||||||
cursor: pointer;
|
|
||||||
text-shadow: 0 1px rgba(255,255,255,0.2);
|
|
||||||
line-height: 0.86em;
|
|
||||||
font-size: 1em;
|
|
||||||
padding: 4px 8px;
|
|
||||||
background: #FAFAFA;
|
|
||||||
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));
|
|
||||||
border: 1px solid rgba(0,0,0,0.25);
|
|
||||||
border-radius: 4px;
|
|
||||||
box-shadow: 0 1px 0 rgba(0,0,0,0.04);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.buttons { white-space: nowrap; width: 100%; display: table; }
|
#bpOutput.hidden { display: none; }
|
||||||
.buttons33 { white-space: nowrap; width: 33.333%; display: table; text-align: center; margin-left: 33.333% }
|
#bpOutput.success { background: #00a65a; }
|
||||||
.mini a { width: 50%; }
|
#bpOutput.error { background: #dd4b39; }
|
||||||
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); }
|
|
||||||
|
|
||||||
.blocked a, .mini a { display: table-cell; }
|
.blockMsg, .flagMsg {
|
||||||
.blocked a.safe50 { width: 50%; background-color: rgba(0,220,0,0.5); }
|
font: bold 1.8rem Consolas, Courier, monospace;
|
||||||
.blocked a.safe33 { width: 33.333%; background-color: rgba(0,220,0,0.5); }
|
padding: 5px 10px 10px 10px;
|
||||||
|
text-indent: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Types of text */
|
#bpHelpTxt { padding-bottom: 10px; }
|
||||||
.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; }
|
|
||||||
|
|
||||||
footer { font-size: 0.8em; text-align: center; width: 87%; margin: 4px auto; }
|
.buttons {
|
||||||
|
border-spacing: 5px 0;
|
||||||
|
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;
|
||||||
|
vertical-align: top;
|
||||||
|
white-space: nowrap;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons a:hover { text-decoration: none; }
|
||||||
|
|
||||||
|
/* Button hover dark overlay */
|
||||||
|
.buttons *:not(input):not([disabled]):hover {
|
||||||
|
background-image: linear-gradient(to bottom, rgba(0,0,0,0.1), rgba(0,0,0,0.1));
|
||||||
|
color: #FFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Button active shadow inset */
|
||||||
|
.buttons *:not([disabled]):not(input):active {
|
||||||
|
box-shadow: inset 0 3px 5px rgba(0,0,0,0.125);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Input border colour */
|
||||||
|
.buttons *:not([disabled]):hover, .buttons input:focus {
|
||||||
|
border-color: rgba(0,0,0,0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
#bpButtons * { width: 50%; color: #FFF; }
|
||||||
|
#bpBack { background-color: #00a65a; }
|
||||||
|
#bpInfo { background-color: #3c8dbc; }
|
||||||
|
#bpWhitelist { background-color: #dd4b39; }
|
||||||
|
|
||||||
|
#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 +0,0 @@
|
||||||
var x = "Pi-hole: A black hole for Internet advertisements."
|
|
|
@ -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")) {
|
||||||
return !filter_var($address, FILTER_VALIDATE_IP) === false;
|
$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>");
|
||||||
}
|
}
|
||||||
|
|
||||||
$uri = escapeshellcmd($_SERVER['REQUEST_URI']);
|
// Set landing page location, found within /var/www/html/
|
||||||
$serverName = escapeshellcmd($_SERVER['SERVER_NAME']);
|
$landPage = "../landing.php";
|
||||||
|
|
||||||
// If the server name is 'pi.hole', it's likely a user trying to get to the admin panel.
|
// Set empty array for hostnames to be accepted as self address for splash page
|
||||||
// Let's be nice and redirect them.
|
$authorizedHosts = [];
|
||||||
if ($serverName === 'pi.hole')
|
|
||||||
{
|
// Append FQDN to $authorizedHosts
|
||||||
header('HTTP/1.1 301 Moved Permanently');
|
if (!empty($svFQDN)) array_push($authorizedHosts, $svFQDN);
|
||||||
header("Location: /admin/");
|
|
||||||
|
// Append virtual hostname to $authorizedHosts
|
||||||
|
if (!empty($_SERVER["VIRTUAL_HOST"])) {
|
||||||
|
array_push($authorizedHosts, $_SERVER["VIRTUAL_HOST"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve server URI extension (EG: jpg, exe, php)
|
// Set which extension types render as Block Page (Including "" for index.wxyz)
|
||||||
// strtok($uri, '\?') splits the querystring from the path (if there is a querystring)
|
$validExtTypes = array("asp", "htm", "html", "php", "rss", "xml", "");
|
||||||
ini_set('pcre.recursion_limit',100);
|
|
||||||
$uriExt = pathinfo(strtok($uri,'\?'), PATHINFO_EXTENSION);
|
|
||||||
|
|
||||||
// Define which URL extensions get rendered as "Website Blocked"
|
// Get extension of current URL
|
||||||
$webExt = array('asp', 'htm', 'html', 'php', 'rss', 'xml');
|
$currentUrlExt = pathinfo($_SERVER["REQUEST_URI"], PATHINFO_EXTENSION);
|
||||||
|
|
||||||
// Get IPv4 and IPv6 addresses from setupVars.conf (if available)
|
// Set mobile friendly viewport
|
||||||
$setupVars = parse_ini_file("/etc/pihole/setupVars.conf");
|
$viewPort = '<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>';
|
||||||
$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'];
|
|
||||||
|
|
||||||
$AUTHORIZED_HOSTNAMES = array(
|
// Set response header
|
||||||
$ipv4,
|
function setHeader($type = "x") {
|
||||||
$ipv6,
|
header("X-Pi-hole: A black hole for Internet advertisements.");
|
||||||
str_replace(array("[","]"), array("",""), $_SERVER["SERVER_ADDR"]),
|
if (isset($type) && $type === "js") header("Content-Type: application/javascript");
|
||||||
"pi.hole",
|
|
||||||
"localhost");
|
|
||||||
// Allow user set virtual hostnames
|
|
||||||
$virtual_host = getenv('VIRTUAL_HOST');
|
|
||||||
if (!empty($virtual_host))
|
|
||||||
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))
|
// Determine block page redirect type
|
||||||
{
|
if ($serverName === "pi.hole") {
|
||||||
// Requested resource has an extension listed in $webExt
|
exit(header("Location: /admin"));
|
||||||
// or no extension (index access to some folder incl. the root dir)
|
} elseif (filter_var($serverName, FILTER_VALIDATE_IP) || in_array($serverName, $authorizedHosts)) {
|
||||||
$showPage = true;
|
// Set Splash Page output
|
||||||
}
|
$splashPage = "
|
||||||
else
|
<html><head>
|
||||||
{
|
$viewPort
|
||||||
// Something else
|
<link rel='stylesheet' href='/pihole/blockingpage.css' type='text/css'/>
|
||||||
$showPage = false;
|
</head><body id='splashpage'><img src='/admin/img/logo.svg'/><br/>Pi-<b>hole</b>: Your black hole for Internet advertisements</body></html>
|
||||||
|
";
|
||||||
|
|
||||||
|
// 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($renderPage);
|
||||||
|
} elseif ($currentUrlExt === "js") {
|
||||||
|
// 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>");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle incoming URI types
|
/* Start processing Block Page from here */
|
||||||
if (!$showPage)
|
|
||||||
{
|
// Determine placeholder text based off $svPasswd presence
|
||||||
?>
|
$wlPlaceHolder = empty($svPasswd) ? "No admin password set" : "Javascript disabled";
|
||||||
<html>
|
|
||||||
<head>
|
// Define admin email address text
|
||||||
<script>window.close();</script></head>
|
$bpAskAdmin = !empty($svEmail) ? '<a href="mailto:'.$svEmail.'?subject=Site Blocked: '.$serverName.'"></a>' : "<span/>";
|
||||||
<body>
|
|
||||||
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">
|
// Determine if at least one block list has been generated
|
||||||
</body>
|
if (empty(glob("/etc/pihole/list.0.*.domains")))
|
||||||
</html>
|
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>.");
|
||||||
<?php
|
|
||||||
die();
|
// 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 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)));
|
||||||
|
|
||||||
|
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&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());
|
||||||
|
}
|
||||||
|
|
||||||
// Don't show the URI if it is the root directory
|
|
||||||
if($uri == "/")
|
|
||||||
{
|
|
||||||
$uri = "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$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; ?>">
|
</div>
|
||||||
<input id="quiet" type="hidden" value="yes">
|
<?php if(isset($notableFlagClass)) { ?>
|
||||||
<button id="btnSearch" class="buttons blocked" type="button" style="visibility: hidden;"></button>
|
<div id="bpFlag">
|
||||||
This page is blocked because it is explicitly contained within the following block list(s):
|
<p class="flagMsg <?=$notableFlagClass ?>"></p>
|
||||||
<pre id="output" style="width: 100%; height: 100%;" hidden="true"></pre><br/>
|
</div>
|
||||||
<div class='buttons blocked'>
|
<?php } ?>
|
||||||
<a class='safe33' href='javascript:history.back()'>Go back</a>
|
<div id="bpHelpTxt"><?=$bpAskAdmin ?></div>
|
||||||
<a class='safe33' id="whitelisting">Whitelist this page</a>
|
<div id="bpButtons" class="buttons">
|
||||||
<a class='safe33' href='javascript:window.close()'>Close window</a>
|
<a id="bpBack" onclick="javascript:history.back()" href="about:home"></a>
|
||||||
</div>
|
<?php if ($featuredTotal > 0) echo '<label id="bpInfo" for="bpMoreToggle"></label>'; ?>
|
||||||
<div style="width: 98%; text-align: center; padding: 10px;" hidden="true" id="whitelistingform">
|
</div>
|
||||||
<p>Note that whitelisting domains which are blocked using the wildcard method won't work.</p>
|
<input id="bpMoreToggle" type="checkbox">
|
||||||
<p>Password required!</p><br/>
|
<div id="bpMoreInfo">
|
||||||
<form>
|
<span id="bpFoundIn"><span><?=$featuredTotal ?></span><?=$adlistsCount ?></span>
|
||||||
<input name="list" type="hidden" value="white"><br/>
|
<pre id='bpQueryOutput'><?php if ($featuredTotal > 0) foreach ($queryResults as $num => $value) { echo "<span>[$num]:</span>$adlistsUrls[$num]\n"; } ?></pre>
|
||||||
Domain:<br/>
|
|
||||||
<input name="domain" value="<?php echo $serverName ?>" disabled><br/><br/>
|
<form id="bpWLButtons" class="buttons">
|
||||||
Password:<br/>
|
<input id="bpWLDomain" type="text" value="<?=$serverName ?>" disabled/>
|
||||||
<input type="password" id="pw" name="pw"><br/><br/>
|
<input id="bpWLPassword" type="password" placeholder="<?=$wlPlaceHolder ?>" disabled/><button id="bpWhitelist" type="button" disabled></button>
|
||||||
<button class="buttons33 safe" id="btnAdd" type="button">Whitelist</button>
|
</form>
|
||||||
</form><br/>
|
</div>
|
||||||
<pre id="whitelistingoutput" style="width: 100%; height: 100%; padding: 5px;" hidden="true"></pre><br/>
|
|
||||||
</div>
|
|
||||||
</main>
|
</main>
|
||||||
<footer>Generated <?php echo date('D g:i A, M d'); ?> by Pi-hole <?php echo $piHoleVersion; ?></footer>
|
|
||||||
<script src="http://pi.hole/admin/scripts/vendor/jquery.min.js"></script>
|
|
||||||
<script>
|
|
||||||
// Create event for when the output is appended to
|
|
||||||
(function($) {
|
|
||||||
var origAppend = $.fn.append;
|
|
||||||
|
|
||||||
$.fn.append = function () {
|
<footer><span><?=date("l g:i A, F dS"); ?>.</span> Pi-hole <?=$phVersion ?> (<?=gethostname()."/".$_SERVER["SERVER_ADDR"]; if (isset($execTime)) printf("/%.2fs", $execTime); ?>)</footer>
|
||||||
return origAppend.apply(this, arguments).trigger("append");
|
</div>
|
||||||
};
|
|
||||||
})(jQuery);
|
|
||||||
</script>
|
|
||||||
<script src="http://pi.hole/admin/scripts/pi-hole/js/queryads.js"></script>
|
|
||||||
<script>
|
<script>
|
||||||
function inIframe () {
|
function add() {
|
||||||
try {
|
$("#bpOutput").removeClass("hidden error exception");
|
||||||
return window.self !== window.top;
|
$("#bpOutput").addClass("add");
|
||||||
} catch (e) {
|
var domain = "<?=$serverName ?>";
|
||||||
return true;
|
var pw = $("#bpWLPassword");
|
||||||
|
if(domain.length === 0) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
$.ajax({
|
||||||
|
url: "/admin/scripts/pi-hole/php/add.php",
|
||||||
// Try to detect if page is loaded within iframe
|
method: "post",
|
||||||
if(inIframe())
|
data: {"domain":domain, "list":"white", "pw":pw.val()},
|
||||||
{
|
success: function(response) {
|
||||||
// Within iframe
|
if(response.indexOf("Pi-hole blocking") !== -1) {
|
||||||
// hide content of page
|
setTimeout(function(){window.location.reload(1);}, 10000);
|
||||||
$('#body').hide();
|
$("#bpOutput").removeClass("add");
|
||||||
// remove background
|
$("#bpOutput").addClass("success");
|
||||||
document.body.style.backgroundImage = "none";
|
} else {
|
||||||
}
|
$("#bpOutput").removeClass("add");
|
||||||
else
|
$("#bpOutput").addClass("error");
|
||||||
{
|
$("#bpOutput").html(""+response+"");
|
||||||
// Query adlists
|
}
|
||||||
$( "#btnSearch" ).click();
|
},
|
||||||
}
|
error: function(jqXHR, exception) {
|
||||||
|
$("#bpOutput").removeClass("add");
|
||||||
$( "#whitelisting" ).on( "click", function(){ $( "#whitelistingform" ).removeAttr( "hidden" ); });
|
$("#bpOutput").addClass("exception");
|
||||||
|
}
|
||||||
// Remove whitelist functionality if the domain was blocked because of a wildcard
|
});
|
||||||
$( "#output" ).bind("append", function(){
|
}
|
||||||
if($( "#output" ).contents()[0].data.indexOf("Wildcard blocking") !== -1)
|
<?php if ($featuredTotal > 0) { ?>
|
||||||
{
|
$(document).keypress(function(e) {
|
||||||
$( "#whitelisting" ).hide();
|
if(e.which === 13 && $("#bpWLPassword").is(":focus")) {
|
||||||
$( "#whitelistingform" ).hide();
|
add();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
$("#bpWhitelist").on("click", function() {
|
||||||
function add() {
|
|
||||||
var domain = $("#domain");
|
|
||||||
var pw = $("#pw");
|
|
||||||
if(domain.val().length === 0){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: "/admin/scripts/pi-hole/php/add.php",
|
|
||||||
method: "post",
|
|
||||||
data: {"domain":domain.val(), "list":"white", "pw":pw.val()},
|
|
||||||
success: function(response) {
|
|
||||||
$( "#whitelistingoutput" ).removeAttr( "hidden" );
|
|
||||||
if(response.indexOf("Pi-hole blocking") !== -1)
|
|
||||||
{
|
|
||||||
// Reload page after 5 seconds
|
|
||||||
setTimeout(function(){window.location.reload(1);}, 5000);
|
|
||||||
$( "#whitelistingoutput" ).html("---> Success <---<br/>You may have to flush your DNS cache");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$( "#whitelistingoutput" ).html("---> "+response+" <---");
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
error: function(jqXHR, exception) {
|
|
||||||
$( "#whitelistingoutput" ).removeAttr( "hidden" );
|
|
||||||
$( "#whitelistingoutput" ).html("---> Unknown Error <---");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// Handle enter button for adding domains
|
|
||||||
$(document).keypress(function(e) {
|
|
||||||
if(e.which === 13 && $("#pw").is(":focus")) {
|
|
||||||
add();
|
add();
|
||||||
}
|
});
|
||||||
});
|
<?php } ?>
|
||||||
|
|
||||||
// Handle buttons
|
|
||||||
$("#btnAdd").on("click", function() {
|
|
||||||
add();
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body></html>
|
||||||
</html>
|
|
||||||
|
|
|
@ -50,7 +50,8 @@ compress.filetype = ( "application/javascript", "text/css", "text/html
|
||||||
# default listening port for IPv6 falls back to the IPv4 port
|
# default listening port for IPv6 falls back to the IPv4 port
|
||||||
include_shell "/usr/share/lighttpd/use-ipv6.pl " + server.port
|
include_shell "/usr/share/lighttpd/use-ipv6.pl " + server.port
|
||||||
include_shell "/usr/share/lighttpd/create-mime.assign.pl"
|
include_shell "/usr/share/lighttpd/create-mime.assign.pl"
|
||||||
include_shell "/usr/share/lighttpd/include-conf-enabled.pl"
|
#include_shell "/usr/share/lighttpd/include-conf-enabled.pl"
|
||||||
|
include_shell "find /etc/lighttpd/conf-enabled -name '*.conf' -a ! -name 'letsencrypt.conf' -printf 'include \"%p\"\n' 2>/dev/null"
|
||||||
|
|
||||||
# If the URL starts with /admin, it is the Web interface
|
# If the URL starts with /admin, it is the Web interface
|
||||||
$HTTP["url"] =~ "^/admin/" {
|
$HTTP["url"] =~ "^/admin/" {
|
||||||
|
@ -59,21 +60,9 @@ $HTTP["url"] =~ "^/admin/" {
|
||||||
"X-Pi-hole" => "The Pi-hole Web interface is working!",
|
"X-Pi-hole" => "The Pi-hole Web interface is working!",
|
||||||
"X-Frame-Options" => "DENY"
|
"X-Frame-Options" => "DENY"
|
||||||
)
|
)
|
||||||
}
|
$HTTP["url"] =~ ".ttf$" {
|
||||||
|
# Allow Block Page access to local fonts
|
||||||
# Rewite js requests, must be out of $HTTP block due to bug #2526
|
setenv.add-response-header = ( "Access-Control-Allow-Origin" => "*" )
|
||||||
url.rewrite = ( "^(?!/admin/).*\.js$" => "pihole/index.js" )
|
|
||||||
|
|
||||||
# If the URL does not start with /admin, then it is a query for an ad domain
|
|
||||||
$HTTP["url"] =~ "^(?!/admin)/.*" {
|
|
||||||
# Create a response header for debugging using curl -I
|
|
||||||
setenv.add-response-header = ( "X-Pi-hole" => "A black hole for Internet advertisements." )
|
|
||||||
}
|
|
||||||
|
|
||||||
# Entering just "pi.hole" into a browser redirects to "pi.hole/admin/"
|
|
||||||
$HTTP["host"] == "pi.hole" {
|
|
||||||
$HTTP["url"] == "/" {
|
|
||||||
url.redirect = ( "" => "/admin/" )
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,22 +75,13 @@ fastcgi.server = ( ".php" =>
|
||||||
# If the URL starts with /admin, it is the Web interface
|
# If the URL starts with /admin, it is the Web interface
|
||||||
$HTTP["url"] =~ "^/admin/" {
|
$HTTP["url"] =~ "^/admin/" {
|
||||||
# Create a response header for debugging using curl -I
|
# Create a response header for debugging using curl -I
|
||||||
setenv.add-response-header = ( "X-Pi-hole" => "The Pi-hole Web interface is working!" )
|
setenv.add-response-header = (
|
||||||
}
|
"X-Pi-hole" => "The Pi-hole Web interface is working!",
|
||||||
|
"X-Frame-Options" => "DENY"
|
||||||
# Rewite js requests, must be out of $HTTP block due to bug #2526
|
)
|
||||||
url.rewrite = ( "^(?!/admin/).*\.js$" => "pihole/index.js" )
|
$HTTP["url"] =~ ".ttf$" {
|
||||||
|
# Allow Block Page access to local fonts
|
||||||
# If the URL does not start with /admin, then it is a query for an ad domain
|
setenv.add-response-header = ( "Access-Control-Allow-Origin" => "*" )
|
||||||
$HTTP["url"] =~ "^(?!/admin)/.*" {
|
|
||||||
# Create a response header for debugging using curl -I
|
|
||||||
setenv.add-response-header = ( "X-Pi-hole" => "A black hole for Internet advertisements." )
|
|
||||||
}
|
|
||||||
|
|
||||||
# Entering just "pi.hole" into a browser redirects to "pi.hole/admin/"
|
|
||||||
$HTTP["host"] == "pi.hole" {
|
|
||||||
$HTTP["url"] == "/" {
|
|
||||||
url.redirect = ( "" => "/admin/" )
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -186,7 +186,6 @@ def test_installPiholeWeb_fresh_install_no_errors(Pihole):
|
||||||
assert tick_box + ' Installing sudoer file' in installWeb.stdout
|
assert tick_box + ' Installing sudoer file' in installWeb.stdout
|
||||||
web_directory = Pihole.run('ls -r /var/www/html/pihole').stdout
|
web_directory = Pihole.run('ls -r /var/www/html/pihole').stdout
|
||||||
assert 'index.php' in web_directory
|
assert 'index.php' in web_directory
|
||||||
assert 'index.js' in web_directory
|
|
||||||
assert 'blockingpage.css' in web_directory
|
assert 'blockingpage.css' in web_directory
|
||||||
|
|
||||||
def test_update_package_cache_success_no_errors(Pihole):
|
def test_update_package_cache_success_no_errors(Pihole):
|
||||||
|
|
Loading…
Reference in a new issue