Fix merge conflict

Signed-off-by: Adam Warner <adamw@rner.email>
This commit is contained in:
Adam Warner
2018-04-14 00:43:27 +01:00
9 changed files with 316 additions and 83 deletions
+174 -20
View File
@@ -1,32 +1,186 @@
Pi-hole Admin Dashboard
============
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/938b4d9e61b7487da77cf63ba05c683d)](https://www.codacy.com/app/Pi-hole/AdminLTE?utm_source=github.com&utm_medium=referral&utm_content=pi-hole/AdminLTE&utm_campaign=badger)
[![Join the chat at https://gitter.im/pi-hole/AdminLTE](https://badges.gitter.im/pi-hole/AdminLTE.svg)](https://gitter.im/pi-hole/AdminLTE?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
<p align="center">
<a href="https://pi-hole.net"><img src="https://pi-hole.github.io/graphics/Vortex/Vortex_with_text.png" width="150" height="255" alt="Pi-hole"></a><br/></br>
<b>Network-wide ad blocking via your own Linux hardware</b><br/>
</br>
<a href="https://pi-hole.net"><img src="https://pi-hole.github.io/graphics/Screenshots/pihole-dashboard.png" alt="Pi-hole Web interface"></a><br/>
</p>
[![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif "AdminLTE Presentation")](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3J2L3Z4DHW9UY "Donate")
Pi-hole[®](https://pi-hole.net/trademark-rules-and-brand-guidelines/)'s Web interface (based off of [AdminLTE](https://almsaeedstudio.com)) provides a central location to manage your Pi-hole and review the statistics generated by FTLDNS[](https://pi-hole.net/trademark-rules-and-brand-guidelines/).
Using **[AdminLTE](https://almsaeedstudio.com)**, this project will create a Web interface for the ad-blocking Pi-hole: **a black hole for Internet advertisements**.
- **Easy-to-interpret**: simple graphs and beautiful colors make Pi-hole's stats easy to understand
- **Responsive**: looks great on desktop, tablets, and mobile devices
- **Useful**: control and configure your Pi-hole with our settings
- **Insightful**: use the query log, audit log, or long-term stats to gain insight into your networks activity
From this interface, you will be able to see stats on how well your Pi-hole is performing. You will also be able to update the lists used to block ads.
---
<a class="badge-align" href="https://www.codacy.com/app/Pi-hole/AdminLTE?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=pi-hole/AdminLTE&amp;utm_campaign=Badge_Grade"><img src="https://api.codacy.com/project/badge/Grade/10540ea45a3b4d5f992c05a2c9714609"/></a>
<img src="https://pi-hole.github.io/graphics/Badges/browserstack-badge.png" height="80"><br>
![Pi-hole Web interface](http://i.imgur.com/EgGZXbT.png)
# Installation
The Web interface is enabled by default when you install Pi-hole.
## Post-installation: access the Web interface and gain insight into your network's activity
There are several ways to [access the dashboard](https://discourse.pi-hole.net/t/how-do-i-access-pi-holes-dashboard-admin-interface/3168):
1. `http://<IP_ADDPRESS_OF_YOUR_PI_HOLE>/admin/`
2. `http:/pi.hole/admin/` (when using Pi-hole as your DNS server)
3. `http://pi.hole/` (when using Pi-hole as your DNS server)
Once logged in (forgot your password?), you can view your network stats to see things like:
- the domains being queried on your network
- the time the queries were initiated
- the amount of domains that were blocked
- the upstream server queries were sent to
- the type of queries (`A`, `AAAA`, `CNAME`, `SRV`, `TXT`, etc.)
---
## Pi-hole is free, but powered by your support
There are many reoccurring costs involved with maintaining free, open source, and privacy respecting software; expenses which [our volunteer developers](https://github.com/orgs/pi-hole/people) pitch in to cover out-of-pocket. This is just one example of how strongly we feel about our software, as well as the importance of keeping it maintained.
Make no mistake: **your support is absolutely vital to help keep us innovating!**
### Donations
Sending a donation using our links below is **extremely helpful** in offsetting a portion of our monthly expenses:
- <img src="https://pi-hole.github.io/graphics/Badges/paypal-badge-black.svg" width="24" height="24" alt="PP"/> <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3J2L3Z4DHW9UY">Donate via PayPal</a><br/>
- <img src="https://pi-hole.github.io/graphics/Badges/bitcoin-badge-black.svg" width="24" height="24" alt="BTC"/> [Bitcoin](https://commerce.coinbase.com/checkout/fb7facaf-bebd-46be-bb77-b358f4546763): <code>1GKnevUnVaQM2pQieMyeHkpr8DXfkpfAtL</code></br>
- <img src="https://pi-hole.github.io/graphics/Badges/bitcoin-badge-black.svg" width="24" height="24" alt="BTC"/> [Bitcoin Cash](https://commerce.coinbase.com/checkout/fb7facaf-bebd-46be-bb77-b358f4546763): <code>qqh25hlmqaj99xraw00e47xmf8sysnyxhyww2d7dnh</code></br>
- <img src="https://pi-hole.github.io/graphics/Badges/ethereum-badge-black.svg" width="24" height="24" alt="BTC"/> [Ethereum](https://commerce.coinbase.com/checkout/fb7facaf-bebd-46be-bb77-b358f4546763): <code>0xF00aF43d2431BAD585056492b310e48eC40D87e8</code>
### Alternative support
If you'd rather not [donate](https://pi-hole.net/donate/) (_which is okay!_), there are other ways you can help support us:
- [Digital Ocean](http://www.digitalocean.com/?refcode=344d234950e1) _affiliate link_
- [UNIXstickers.com](http://unixstickers.refr.cc/jacobs) _save $5 when you spend $9 using our affiliate link_
- [Pi-hole Swag Store](https://pi-hole.net/shop/) _affiliate link_
- [Amazon](http://www.amazon.com/exec/obidos/redirect-home/pihole09-20) _affiliate link_
- [Ho-ost](https://clients.ho-ost.com/aff.php?aff=19) _save 50% with our affiliate link_
- [DNS Made Easy](https://cp.dnsmadeeasy.com/u/133706) _affiliate link_
- [Vultr](http://www.vultr.com/?ref=7190426) _affiliate link_
- Spreading the word about our software, and how you have benefited from it
### Contributing via GitHub
We welcome _everyone_ to contribute to issue reports, suggest new features, and create pull requests.
If you have something to add - anything from a typo through to a whole new feature, we're happy to check it out! Just make sure to fill out our template when submitting your request; the questions that it asks will help the volunteers quickly understand what you're aiming to achieve.
### Presentations about Pi-hole
Word-of-mouth continues to help our project grow immensely, and so we are helping make this easier for people.
If you are going to be presenting Pi-hole at a conference, meetup or even a school project, [get in touch with us](https://pi-hole.net/2017/05/17/giving-a-presentation-on-pi-hole-contact-us-first-for-some-goodies-and-support/) so we can hook you up with free swag to hand out to your audience!
-----
## Getting in touch with us
While we are primarily reachable on our <a href="https://discourse.pi-hole.net/">Discourse User Forum</a>, we can also be found on a variety of social media outlets. **Please be sure to check the FAQ's** before starting a new discussion, as we do not have the spare time to reply to every request for assistance.
<ul>
<li><b><a href="https://discourse.pi-hole.net/c/faqs">Frequently Asked Questions</a></b></li>
<li><b><a href="https://github.com/pi-hole/pi-hole/wiki">Pi-hole Wiki</a></b></li>
<li><b><a href="https://discourse.pi-hole.net/c/feature-requests?order=votes">Feature Requests</a></b></li>
<li><a href="https://discourse.pi-hole.net/">Discourse User Forum</a></li>
<li><a href="https://www.reddit.com/r/pihole/">Reddit</a></li>
<li><a href="https://twitter.com/The_Pi_Hole">Twitter</a></li>
<li><a href="https://www.facebook.com/ThePiHole/">Facebook</a></li>
<li><a href="https://gitter.im/pi-hole/pi-hole">Gitter</a> (Real-time chat)</li>
<li><a href="https://www.youtube.com/channel/UCT5kq9w0wSjogzJb81C9U0w">YouTube</a></li>
</ul>
# Features
## Mobile friendly interface
<p align="center">
<img src="https://pi-hole.github.io/graphics/Screenshots/mobile-friendly.png" height="300" alt="Mobile friendly"></a>
</p>
## Password protection
<p align="center">
<img src="https://pi-hole.github.io/graphics/Screenshots/password-protection.png" height="400" alt="Password protection"></a>
</p>
## Detailed graphs and doughnut charts
<p align="center">
<img src="https://pi-hole.github.io/graphics/Screenshots/piecharts.png" alt="Pie charts"></a>
</p>
## Top lists of domains and clients
<p align="center">
<img src="https://pi-hole.github.io/graphics/Screenshots/topdomains-clients.png" alt="Top domains/top clients"></a>
</p>
## A filterable and sortable query log
<p align="center">
<img src="https://pi-hole.github.io/graphics/Screenshots/query-log-sorted.png" alt="Query log"></a>
</p>
## An audit log
<p align="center">
<img src="https://pi-hole.github.io/graphics/Screenshots/audit-log.png" alt="Pi-hole Web interface"></a>
</p>
## Long Term Statistics to view data over user defined time ranges
<p align="center">
<img src="https://pi-hole.github.io/graphics/Screenshots/long-term-stats.png" alt="Long-term stats"></a>
</p>
## A built-in debugger
<p align="center">
<img src="https://pi-hole.github.io/graphics/Screenshots/debug.png" alt="Debugger"></a>
</p>
## Black and white lists
<p align="center">
<img src="https://pi-hole.github.io/graphics/Screenshots/blacklist.png" alt="Blacklist"></a>
</br></br>
<img src="https://pi-hole.github.io/graphics/Screenshots/whitelist.png" alt="Whitelist"></a>
</p>
## The ability to easily manage and configure Pi-hole features
<p align="center">
<img src="https://pi-hole.github.io/graphics/Screenshots/dashboard-settings.gif" alt="Settings"></a>
</p>
## ... and all the main features of the Command Line Interface!
<p align="center">
<img src="https://pi-hole.github.io/graphics/Screenshots/pihole-t.png" alt="Tail the log"></a>
</br></br>
<img src="https://pi-hole.github.io/graphics/Screenshots/pihole-q.png" alt="Query ad lists"></a>
</p>
## API
A read-only API can be accessed at `/admin/api.php`. With either no parameters or `api.php?summary` it returns the following JSON:
Full usage available [here](https://discourse.pi-hole.net/t/pi-hole-api/1863). can be accessed at `/admin/api.php`. With either no parameters or `/admin/api.php?summary` it returns the following JSON:
```JSON
{
"domains_being_blocked": "136,708",
"dns_queries_today": "18,108",
"ads_blocked_today": "14,648",
"ads_percentage_today": "80.9"
{
"domains_being_blocked":243038,
"dns_queries_today":2385,
"ads_blocked_today":414,
"ads_percentage_today":17.35849,
"unique_domains":429,
"queries_forwarded":1537,
"queries_cached":434,
"clients_ever_seen":5,
"unique_clients":5,
"status":"enabled"
}
```
There are many more parameters, such as `summaryRaw`, `overTimeData10mins`, `topItems`, ` topClients` or `getQuerySources`, `getQueryTypes`, `getForwardDestinations`, and finally `getAllQueries`.
Together with a token it is also possible to enable and disable (also with a set timeout) blocking via the API
[There are many more parameters](https://discourse.pi-hole.net/t/pi-hole-api/1863), such as:
The API returns more information (in a slighly different format if `FTL` is running) - it supports a fall-back to the "old" PHP API if `FTL` is not running. Test the type and/or version of the API by using the parameter `type` and `version`.
- `type & version`
- `summaryRaw`
- `summary`
- `overTimeData10mins`
- `topItems`
- `getQuerySources`
- `getForwardDestinations`
- `getQueryTypes`
- `getAllQueries`
- `enable`
- `disable`
- `recentBlocked`
<hr>
<img src="https://assets.pi-hole.net/static/BStackLogo.png" height="80"><br>
We use BrowserStack for multi-platform multi-browser testing.
Together with a token it is also possible to [enable and disable (also with a set timeout) blocking via the API](https://discourse.pi-hole.net/t/is-there-an-api-command-to-disable-ad-blocking/7693).
The API returns more information (in a slightly different format if `FTL` is running) - it supports a fall-back to the "old" PHP API if `FTL` is not running. Test the type and/or version of the API by using the parameter `type` and `version`.
+4
View File
@@ -230,6 +230,10 @@ if (isset($_GET['getAllQueries']) && $auth)
// Get specific client only
sendRequestFTL("getallqueries-client ".$_GET['client']);
}
else if(is_numeric($_GET['getAllQueries']))
{
sendRequestFTL("getallqueries (".$_GET['getAllQueries'].")");
}
else
{
// Get all queries
+42 -39
View File
@@ -16,6 +16,37 @@ check_cors();
ini_set("max_execution_time","600");
$data = array();
$clients = array();
function resolveHostname($clientip, $printIP)
{
global $clients;
$ipaddr = strtolower($clientip);
if(array_key_exists($clientip, $clients))
{
// Entry already exists
$clientname = $clients[$ipaddr];
if($printIP)
return $clientname."|".$clientip;
return $clientname;
}
else if(filter_var($clientip, FILTER_VALIDATE_IP))
{
// Get host name of client and convert to lower case
$clientname = strtolower(gethostbyaddr($ipaddr));
}
else
{
// This is already a host name
$clientname = $ipaddr;
}
// Buffer result
$clients[$ipaddr] = $clientname;
if($printIP)
return $clientname."|".$clientip;
return $clientname;
}
// Get posible non-standard location of FTL's database
$FTLsettings = parse_ini_file("/etc/pihole/pihole-FTL.conf");
@@ -74,31 +105,10 @@ if (isset($_GET['getAllQueries']) && $auth)
$stmt->bindValue(":from", intval($from), SQLITE3_INTEGER);
$stmt->bindValue(":until", intval($until), SQLITE3_INTEGER);
$results = $stmt->execute();
$clients = array();
if(!is_bool($results))
while ($row = $results->fetchArray())
{
$c = $row[3];
if(array_key_exists($row[3], $clients))
{
// Entry already exists
$c = $clients[$row[3]];
}
else
{
if(filter_var($row[3], FILTER_VALIDATE_IP))
{
// Get host name of client and convert to lower case
$c = strtolower(gethostbyaddr($row[3]));
}
else
{
// This is already a host name
$c = strtolower($row[3]);
}
// Buffer result
$clients[$row[3]] = $c;
}
$c = resolveHostname($row[3],false);
$allQueries[] = [$row[0],$row[1] == 1 ? "IPv4" : "IPv6",$row[2],$c,$row[4]];
}
}
@@ -127,40 +137,33 @@ if (isset($_GET['topClients']) && $auth)
$stmt->bindValue(":until", intval($_GET['until']), SQLITE3_INTEGER);
$results = $stmt->execute();
$clients = array();
$clientnums = array();
if(!is_bool($results))
while ($row = $results->fetchArray())
{
if(filter_var($row[0], FILTER_VALIDATE_IP))
{
// Get host name of client and convert to lower case
$c = strtolower(gethostbyaddr($row[0]));
}
else
{
// This is already a host name
$c = strtolower($row[0]);
}
if(array_key_exists($c, $clients))
$c = resolveHostname($row[0],false);
if(array_key_exists($c, $clientnums))
{
// Entry already exists, add to it (might appear multiple times due to mixed capitalization in the database)
$clients[$c] += intval($row[1]);
$clientnums[$c] += intval($row[1]);
}
else
{
// Entry does not yet exist
$clients[$c] = intval($row[1]);
$clientnums[$c] = intval($row[1]);
}
}
// Sort by number of hits
arsort($clients);
arsort($clientnums);
// Extract only the first ten entries
$clients = array_slice($clients, 0, 10);
$clientnums = array_slice($clientnums, 0, 10);
$result = array('top_sources' => $clients);
$result = array('top_sources' => $clientnums);
$data = array_merge($data, $result);
}
+10 -4
View File
@@ -132,8 +132,11 @@ else
<h3 class="box-title">Query Types (integrated)</h3>
</div>
<div class="box-body">
<div class="chart">
<canvas id="queryTypePieChart" width="400" height="150"></canvas>
<div class="float-left" style="width:50%">
<canvas id="queryTypePieChart" width="120" height="120"></canvas>
</div>
<div class="float-left" style="width:50%">
<div id="query-types-legend" class="chart-legend"></div>
</div>
</div>
<div class="overlay">
@@ -148,8 +151,11 @@ else
<h3 class="box-title">Forward Destinations (integrated)</h3>
</div>
<div class="box-body">
<div class="chart">
<canvas id="forwardDestinationPieChart" width="400" height="150"></canvas>
<div class="float-left" style="width:50%">
<canvas id="forwardDestinationPieChart" width="120" height="120"></canvas>
</div>
<div class="float-left" style="width:50%">
<div id="forward-destinations-legend" class="chart-legend"></div>
</div>
</div>
<div class="overlay">
+15 -11
View File
@@ -19,47 +19,49 @@ if(isset($setupVars["API_QUERY_LOG_SHOW"]))
{
if($setupVars["API_QUERY_LOG_SHOW"] === "all")
{
$showing = "showing all queries";
$showing = "showing";
}
elseif($setupVars["API_QUERY_LOG_SHOW"] === "permittedonly")
{
$showing = "showing permitted queries only";
$showing = "showing permitted";
}
elseif($setupVars["API_QUERY_LOG_SHOW"] === "blockedonly")
{
$showing = "showing blocked queries only";
$showing = "showing blocked";
}
elseif($setupVars["API_QUERY_LOG_SHOW"] === "nothing")
{
$showing = "showing no queries at all";
$showing = "showing no queries (due to setting)";
}
}
else
{
// If filter variable is not set, we
// automatically show all queries
$showing = "showing all queries";
$showing = "showing queries";
}
$showall = false;
if(isset($_GET["all"]))
{
$showing .= " within the Pi-hole log";
$showing .= " all queries within the Pi-hole log";
}
else if(isset($_GET["client"]))
{
$showing .= " for client ".htmlentities($_GET["client"]);
$showing .= " queries for client ".htmlentities($_GET["client"]);
}
else if(isset($_GET["domain"]))
{
$showing .= " for domain ".htmlentities($_GET["domain"]);
$showing .= " queries for domain ".htmlentities($_GET["domain"]);
}
else if(isset($_GET["from"]) && isset($_GET["until"]))
else if(isset($_GET["from"]) || isset($_GET["until"]))
{
$showing .= " within limited time interval";
$showing .= " queries within specified time interval";
}
else
{
$showing .= " within recent 10 minutes, <a href=\"?all\">show all</a>";
$showing .= " up to 100 queries";
$showall = true;
}
if(isset($setupVars["API_PRIVACY_MODE"]))
@@ -74,6 +76,8 @@ if(isset($setupVars["API_PRIVACY_MODE"]))
if(strlen($showing) > 0)
{
$showing = "(".$showing.")";
if($showall)
$showing .= ", <a href=\"?all\">show all</a>";
}
?>
<!-- Send PHP info to JS -->
+36 -4
View File
@@ -255,6 +255,23 @@ function updateQueryTypesPie() {
queryTypePieChart.update();
// Don't use rotation animation for further updates
queryTypePieChart.options.animation.duration=0;
// Generate legend in separate div
$("#query-types-legend").html(queryTypePieChart.generateLegend());
$("#query-types-legend > ul > li").on("click",function(e){
$(this).toggleClass("strike");
var index = $(this).index();
var ci = e.view.queryTypePieChart;
var meta = ci.data.datasets[0]._meta;
for(let i in meta)
{
if ({}.hasOwnProperty.call(meta, i))
{
var curr = meta[i].data[index];
curr.hidden = !curr.hidden;
}
}
ci.update();
});
}).done(function() {
// Reload graph after minute
setTimeout(updateQueryTypesPie, 60000);
@@ -469,6 +486,23 @@ function updateForwardDestinationsPie() {
forwardDestinationPieChart.update();
// Don't use rotation animation for further updates
forwardDestinationPieChart.options.animation.duration=0;
// Generate legend in separate div
$("#forward-destinations-legend").html(forwardDestinationPieChart.generateLegend());
$("#forward-destinations-legend > ul > li").on("click",function(e){
$(this).toggleClass("strike");
var index = $(this).index();
var ci = e.view.forwardDestinationPieChart;
var meta = ci.data.datasets[0]._meta;
for(let i in meta)
{
if ({}.hasOwnProperty.call(meta, i))
{
var curr = meta[i].data[index];
curr.hidden = !curr.hidden;
}
}
ci.update();
});
}).done(function() {
// Reload graph after one minute
setTimeout(updateForwardDestinationsPie, 60000);
@@ -1041,8 +1075,7 @@ $(document).ready(function() {
},
options: {
legend: {
display: true,
position: "right"
display: false
},
tooltips: {
enabled: true,
@@ -1079,8 +1112,7 @@ $(document).ready(function() {
},
options: {
legend: {
display: true,
position: "right"
display: false
},
tooltips: {
enabled: true,
+3 -4
View File
@@ -82,7 +82,7 @@ function add(domain,list) {
}
});
});
// Reset Modal after it has faded out
alertModal.one("hidden.bs.modal", function() {
alProcessing.show();
@@ -136,11 +136,10 @@ $(document).ready(function() {
{
APIstring += "&domain="+GETDict["domain"];
}
// If we don't ask filtering and also not for all queries, just request the most recent 100 queries
else if(!("all" in GETDict))
{
var timestamp = Math.floor(Date.now() / 1000);
APIstring += "&from="+(timestamp - 600);
APIstring += "&until="+(timestamp + 100);
APIstring += "=100";
}
tableApi = $("#all-queries").DataTable( {
+2 -1
View File
@@ -123,7 +123,8 @@ function isinserverlist($addr) {
"Norton" => ["v4_1" => "199.85.126.10", "v4_2" => "199.85.127.10"],
"Comodo" => ["v4_1" => "8.26.56.26", "v4_2" => "8.20.247.20"],
"DNS.WATCH" => ["v4_1" => "84.200.69.80", "v4_2" => "84.200.70.40", "v6_1" => "2001:1608:10:25:0:0:1c04:b12f", "v6_2" => "2001:1608:10:25:0:0:9249:d69b"],
"Quad9" => ["v4_1" => "9.9.9.9", "v4_2" => "149.112.112.112", "v6_1" => "2620:fe::fe"]
"Quad9" => ["v4_1" => "9.9.9.9", "v4_2" => "149.112.112.112", "v6_1" => "2620:fe::fe"],
"Cloudflare" => ["v4_1" => "1.1.1.1", "v4_2" => "1.0.0.1", "v6_1" => "2606:4700:4700::1111", "v6_2" => "2606:4700:4700::1001"]
];
$adlist = [];
+30
View File
@@ -121,6 +121,7 @@ a.lookatme {
-webkit-user-select: none;
-ms-user-select: none;
}
#chartjs-tooltip {
opacity: 1;
position: absolute;
@@ -133,9 +134,38 @@ a.lookatme {
-webkit-transform: translate(-50%, 0);
transform: translate(-50%, 0);
}
.chartjs-tooltip-key {
display: inline-block;
width: 20px;
height: 10px;
margin-right: 10px;
}
.chart-legend {
height:250px;
overflow:auto;
}
.chart-legend ul {
list-style-type: none;
}
.chart-legend li {
cursor:pointer;
}
.chart-legend li span {
display: inline-block;
width: 20px;
height: 12px;
margin-right: 5px;
}
.strike {
text-decoration: line-through !important;
}
.float-left{
float:left;
}