@@ -0,0 +1,32 @@
|
||||
name: Tests
|
||||
on: [push, pull_request]
|
||||
env:
|
||||
CI: true
|
||||
|
||||
jobs:
|
||||
run:
|
||||
name: Node ${{ matrix.node }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
node: [12]
|
||||
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Set Node.js version
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
|
||||
- run: node --version
|
||||
- run: npm --version
|
||||
|
||||
- name: Install npm dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run tests
|
||||
run: npm test
|
||||
@@ -1,38 +0,0 @@
|
||||
version: 2
|
||||
|
||||
always_pending:
|
||||
title_regex: '(WIP|wip)'
|
||||
labels:
|
||||
- wip
|
||||
explanation: 'This PR is a work in progress...'
|
||||
|
||||
group_defaults:
|
||||
reset_on_push:
|
||||
enabled: true
|
||||
reject_value: -2
|
||||
approve_regex: '^(Approved|:shipit:|:\+1:|Engage|:taco:)'
|
||||
reject_regex: '^(Rejected|:-1:|Borg)'
|
||||
author_approval:
|
||||
auto: true
|
||||
|
||||
|
||||
groups:
|
||||
development:
|
||||
approve_by_comment:
|
||||
enabled: true
|
||||
conditions:
|
||||
branches:
|
||||
- devel
|
||||
required: 2
|
||||
teams:
|
||||
- approvers
|
||||
|
||||
master:
|
||||
approve_by_comment:
|
||||
enabled: true
|
||||
conditions:
|
||||
branches:
|
||||
- master
|
||||
required: 4
|
||||
teams:
|
||||
- approvers
|
||||
@@ -5,7 +5,7 @@
|
||||
<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>
|
||||
|
||||
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/).
|
||||
Pi-hole[®](https://pi-hole.net/trademark-rules-and-brand-guidelines/)'s Web interface (based off of [AdminLTE](https://github.com/ColorlibHQ/AdminLTE)) 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/).
|
||||
|
||||
- **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
|
||||
@@ -13,7 +13,6 @@ Pi-hole[®](https://pi-hole.net/trademark-rules-and-brand-guidelines/)'s Web int
|
||||
- **Insightful**: use the query log, audit log, or long-term stats to gain insight into your networks activity
|
||||
|
||||
---
|
||||
<a class="badge-align" href="https://www.codacy.com/app/Pi-hole/AdminLTE?utm_source=github.com&utm_medium=referral&utm_content=pi-hole/AdminLTE&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>
|
||||
|
||||
# Installation
|
||||
|
||||
@@ -104,7 +104,8 @@ else
|
||||
foreach($return as $line)
|
||||
{
|
||||
$tmp = explode(" ",$line);
|
||||
$top_queries[$tmp[2]] = intval($tmp[1]);
|
||||
$domain = utf8_encode($tmp[2]);
|
||||
$top_queries[$domain] = intval($tmp[1]);
|
||||
}
|
||||
|
||||
if($_GET['topItems'] === "audit")
|
||||
@@ -125,10 +126,11 @@ else
|
||||
foreach($return as $line)
|
||||
{
|
||||
$tmp = explode(" ",$line);
|
||||
$domain = utf8_encode($tmp[2]);
|
||||
if(count($tmp) > 3)
|
||||
$top_ads[$tmp[2]." (".$tmp[3].")"] = intval($tmp[1]);
|
||||
$top_ads[$domain." (".$tmp[3].")"] = intval($tmp[1]);
|
||||
else
|
||||
$top_ads[$tmp[2]] = intval($tmp[1]);
|
||||
$top_ads[$domain] = intval($tmp[1]);
|
||||
}
|
||||
|
||||
$result = array('top_queries' => $top_queries,
|
||||
@@ -163,10 +165,14 @@ else
|
||||
foreach($return as $line)
|
||||
{
|
||||
$tmp = explode(" ",$line);
|
||||
$clientip = utf8_encode($tmp[2]);
|
||||
if(count($tmp) > 3 && strlen($tmp[3]) > 0)
|
||||
$top_clients[$tmp[3]."|".$tmp[2]] = intval($tmp[1]);
|
||||
{
|
||||
$clientname = utf8_encode($tmp[3]);
|
||||
$top_clients[$clientname."|".$clientip] = intval($tmp[1]);
|
||||
}
|
||||
else
|
||||
$top_clients[$tmp[2]] = intval($tmp[1]);
|
||||
$top_clients[$clientip] = intval($tmp[1]);
|
||||
}
|
||||
|
||||
$result = array('top_sources' => $top_clients);
|
||||
@@ -195,10 +201,14 @@ else
|
||||
foreach($return as $line)
|
||||
{
|
||||
$tmp = explode(" ",$line);
|
||||
$clientip = utf8_encode($tmp[2]);
|
||||
if(count($tmp) > 3 && strlen($tmp[3]) > 0)
|
||||
$top_clients[$tmp[3]."|".$tmp[2]] = intval($tmp[1]);
|
||||
{
|
||||
$clientname = utf8_encode($tmp[3]);
|
||||
$top_clients[$clientname."|".$clientip] = intval($tmp[1]);
|
||||
}
|
||||
else
|
||||
$top_clients[$tmp[2]] = intval($tmp[1]);
|
||||
$top_clients[$clientip] = intval($tmp[1]);
|
||||
}
|
||||
|
||||
$result = array('top_sources_blocked' => $top_clients);
|
||||
@@ -220,10 +230,14 @@ else
|
||||
foreach($return as $line)
|
||||
{
|
||||
$tmp = explode(" ",$line);
|
||||
$forwardip = utf8_encode($tmp[2]);
|
||||
if(count($tmp) > 3 && strlen($tmp[3]) > 0)
|
||||
$forward_dest[$tmp[3]."|".$tmp[2]] = floatval($tmp[1]);
|
||||
{
|
||||
$forwardname = utf8_encode($tmp[3]);
|
||||
$forward_dest[$forwardname."|".$forwardip] = floatval($tmp[1]);
|
||||
}
|
||||
else
|
||||
$forward_dest[$tmp[2]] = floatval($tmp[1]);
|
||||
$forward_dest[$forwardip] = floatval($tmp[1]);
|
||||
}
|
||||
|
||||
$result = array('forward_destinations' => $forward_dest);
|
||||
@@ -238,6 +252,7 @@ else
|
||||
foreach($return as $ret)
|
||||
{
|
||||
$tmp = explode(": ",$ret);
|
||||
// Reply cannot contain non-ASCII characters
|
||||
$querytypes[$tmp[0]] = floatval($tmp[1]);
|
||||
}
|
||||
|
||||
@@ -253,6 +268,7 @@ else
|
||||
foreach($return as $ret)
|
||||
{
|
||||
$tmp = explode(": ",$ret);
|
||||
// Reply cannot contain non-ASCII characters
|
||||
$cacheinfo[$tmp[0]] = floatval($tmp[1]);
|
||||
}
|
||||
|
||||
@@ -301,6 +317,10 @@ else
|
||||
foreach($return as $line)
|
||||
{
|
||||
$tmp = explode(" ",$line);
|
||||
// UTF-8 encode domain
|
||||
$tmp[2] = utf8_encode($tmp[2]);
|
||||
// UTF-8 encode client host name
|
||||
$tmp[3] = utf8_encode($tmp[3]);;
|
||||
array_push($allQueries,$tmp);
|
||||
}
|
||||
|
||||
@@ -311,7 +331,7 @@ else
|
||||
if(isset($_GET["recentBlocked"]))
|
||||
{
|
||||
sendRequestFTL("recentBlocked");
|
||||
die(getResponseFTL()[0]);
|
||||
die(utf8_encode(getResponseFTL()[0]));
|
||||
unset($data);
|
||||
}
|
||||
|
||||
@@ -323,13 +343,15 @@ else
|
||||
foreach($return as $line)
|
||||
{
|
||||
$tmp = explode(" ",$line);
|
||||
$forwardip = utf8_encode($tmp[2]);
|
||||
if(count($tmp) > 3)
|
||||
{
|
||||
$forward_dest[$tmp[3]."|".$tmp[2]] = floatval($tmp[1]);
|
||||
$forwardname = utf8_encode($tmp[3]);
|
||||
$forward_dest[$forwardname."|".$forwardip] = floatval($tmp[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$forward_dest[$tmp[2]] = floatval($tmp[1]);
|
||||
$forward_dest[$forwardip] = floatval($tmp[1]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,8 +385,8 @@ else
|
||||
{
|
||||
$tmp = explode(" ", $line);
|
||||
$client_names[] = array(
|
||||
"name" => $tmp[0],
|
||||
"ip" => $tmp[1]
|
||||
"name" => utf8_encode($tmp[0]),
|
||||
"ip" => utf8_encode($tmp[1])
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
$api = true;
|
||||
header('Content-type: application/json');
|
||||
require("scripts/pi-hole/php/database.php");
|
||||
require("scripts/pi-hole/php/password.php");
|
||||
require("scripts/pi-hole/php/auth.php");
|
||||
check_cors();
|
||||
@@ -48,51 +49,11 @@ function resolveHostname($clientip, $printIP)
|
||||
return $clientname;
|
||||
}
|
||||
|
||||
// Get posible non-standard location of FTL's database
|
||||
$FTLsettings = parse_ini_file("/etc/pihole/pihole-FTL.conf");
|
||||
if(isset($FTLsettings["DBFILE"]))
|
||||
{
|
||||
$DBFILE = $FTLsettings["DBFILE"];
|
||||
}
|
||||
else
|
||||
{
|
||||
$DBFILE = "/etc/pihole/pihole-FTL.db";
|
||||
}
|
||||
|
||||
// Needs package php5-sqlite, e.g.
|
||||
// sudo apt-get install php5-sqlite
|
||||
|
||||
function SQLite3_connect($trytoreconnect)
|
||||
{
|
||||
global $DBFILE;
|
||||
try
|
||||
{
|
||||
// connect to database
|
||||
return new SQLite3($DBFILE, SQLITE3_OPEN_READONLY);
|
||||
}
|
||||
catch (Exception $exception)
|
||||
{
|
||||
// sqlite3 throws an exception when it is unable to connect, try to reconnect after 3 seconds
|
||||
if($trytoreconnect)
|
||||
{
|
||||
sleep(3);
|
||||
$db = SQLite3_connect(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(strlen($DBFILE) > 0)
|
||||
{
|
||||
$db = SQLite3_connect(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
die("No database available");
|
||||
}
|
||||
if(!$db)
|
||||
{
|
||||
die("Error connecting to database");
|
||||
}
|
||||
$QUERYDB = getQueriesDBFilename();
|
||||
$db = SQLite3_connect($QUERYDB);
|
||||
|
||||
if(isset($_GET["network"]) && $auth)
|
||||
{
|
||||
@@ -100,7 +61,19 @@ if(isset($_GET["network"]) && $auth)
|
||||
$results = $db->query('SELECT * FROM network');
|
||||
|
||||
while($results !== false && $res = $results->fetchArray(SQLITE3_ASSOC))
|
||||
{
|
||||
$id = $res["id"];
|
||||
// Empty array for holding the IP addresses
|
||||
$res["ip"] = array();
|
||||
// Get IP addresses for this device
|
||||
$network_addresses = $db->query("SELECT ip FROM network_addresses WHERE network_id = $id ORDER BY lastSeen DESC");
|
||||
while($network_addresses !== false && $ip = $network_addresses->fetchArray(SQLITE3_ASSOC))
|
||||
array_push($res["ip"],$ip["ip"]);
|
||||
// UTF-8 encode host name and vendor
|
||||
$res["name"] = utf8_encode($res["name"]);
|
||||
$res["macVendor"] = utf8_encode($res["macVendor"]);
|
||||
array_push($network, $res);
|
||||
}
|
||||
|
||||
$data = array_merge($data, array('network' => $network));
|
||||
}
|
||||
@@ -164,12 +137,15 @@ if (isset($_GET['getAllQueries']) && $auth)
|
||||
case 7:
|
||||
$query_type = "TXT";
|
||||
break;
|
||||
case 8:
|
||||
$query_type = "NAPTR";
|
||||
break;
|
||||
default:
|
||||
$query_type = "UNKN";
|
||||
break;
|
||||
}
|
||||
|
||||
$allQueries[] = [$row[0], $query_type, $row[2], $c, $row[4]];
|
||||
// array: time type domain client status
|
||||
$allQueries[] = [$row[0], $query_type, utf8_encode($row[2]), utf8_encode($c), $row[4]];
|
||||
}
|
||||
}
|
||||
$result = array('data' => $allQueries);
|
||||
@@ -202,8 +178,8 @@ if (isset($_GET['topClients']) && $auth)
|
||||
if(!is_bool($results))
|
||||
while ($row = $results->fetchArray())
|
||||
{
|
||||
|
||||
$c = resolveHostname($row[0],false);
|
||||
// Try to resolve host name and convert to UTF-8
|
||||
$c = utf8_encode(resolveHostname($row[0],false));
|
||||
|
||||
if(array_key_exists($c, $clientnums))
|
||||
{
|
||||
@@ -253,8 +229,8 @@ if (isset($_GET['topDomains']) && $auth)
|
||||
if(!is_bool($results))
|
||||
while ($row = $results->fetchArray())
|
||||
{
|
||||
// Convert client to lower case
|
||||
$c = strtolower($row[0]);
|
||||
// Convert domain to lower case UTF-8
|
||||
$c = utf8_encode(strtolower($row[0]));
|
||||
if(array_key_exists($c, $domains))
|
||||
{
|
||||
// Entry already exists, add to it (might appear multiple times due to mixed capitalization in the database)
|
||||
@@ -303,7 +279,7 @@ if (isset($_GET['topAds']) && $auth)
|
||||
if(!is_bool($results))
|
||||
while ($row = $results->fetchArray())
|
||||
{
|
||||
$addomains[$row[0]] = intval($row[1]);
|
||||
$addomains[utf8_encode($row[0])] = intval($row[1]);
|
||||
}
|
||||
$result = array('top_ads' => $addomains);
|
||||
$data = array_merge($data, $result);
|
||||
@@ -392,20 +368,28 @@ if (isset($_GET['getGraphData']) && $auth)
|
||||
// Parse the DB result into graph data, filling in missing interval sections with zero
|
||||
function parseDBData($results, $interval, $from, $until) {
|
||||
$data = array();
|
||||
$first_db_timestamp = -1;
|
||||
|
||||
if(!is_bool($results)) {
|
||||
// Read in the data
|
||||
while($row = $results->fetchArray()) {
|
||||
// $data[timestamp] = value_in_this_interval
|
||||
$data[$row[0]] = intval($row[1]);
|
||||
if($first_db_timestamp === -1)
|
||||
$first_db_timestamp = intval($row[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// Fill the missing intervals with zero
|
||||
// Advance in steps of interval
|
||||
for($i = $from; $i < $until; $i += $interval) {
|
||||
if(!array_key_exists($i, $data))
|
||||
$data[$i] = 0;
|
||||
}
|
||||
// It is unpredictable what the first timestamp returned by the database
|
||||
// will be. This depends on live data. Hence, we re-align the FROM
|
||||
// timestamp to avoid unaligned holes appearing as additional
|
||||
// (incorrect) data points
|
||||
$aligned_from = $from + (($first_db_timestamp - $from) % $interval);
|
||||
|
||||
// Fill gaps in returned data
|
||||
for($i = $aligned_from; $i < $until; $i += $interval) {
|
||||
if(!array_key_exists($i, $data))
|
||||
$data[$i] = 0;
|
||||
}
|
||||
|
||||
return $data;
|
||||
|
||||
@@ -68,14 +68,9 @@
|
||||
</div>
|
||||
<!-- /.box -->
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<p><strong>Important:</strong> Note that black- and whitelisted domains are not automatically applied on this page to avoid restarting the DNS service too often. Instead, click on this button, to have the new settings become effective:</p>
|
||||
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
</div>
|
||||
<!-- /.row -->
|
||||
<button class="btn btn-lg btn-primary btn-block" id="gravityBtn" disabled="true">Update black-/whitelists</button>
|
||||
|
||||
<script src="scripts/pi-hole/js/auditlog.js"></script>
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ $token = $_SESSION['token'];
|
||||
<div class="input-group-addon">
|
||||
<i class="far fa-clock"></i>
|
||||
</div>
|
||||
<input type="text" class="form-control pull-right" id="querytime" value="Click to select date and time range">
|
||||
<input type="button" class="form-control pull-right" id="querytime" value="Click to select date and time range">
|
||||
</div>
|
||||
<!-- /.input group -->
|
||||
</div>
|
||||
|
||||
@@ -33,7 +33,7 @@ $token = $_SESSION['token'];
|
||||
<div class="input-group-addon">
|
||||
<i class="far fa-clock"></i>
|
||||
</div>
|
||||
<input type="text" class="form-control pull-right" id="querytime" value="Click to select date and time range">
|
||||
<input type="button" class="form-control pull-right" id="querytime" value="Click to select date and time range">
|
||||
</div>
|
||||
<!-- /.input group -->
|
||||
</div>
|
||||
|
||||
@@ -33,7 +33,7 @@ $token = $_SESSION['token'];
|
||||
<div class="input-group-addon">
|
||||
<i class="far fa-clock"></i>
|
||||
</div>
|
||||
<input type="text" class="form-control pull-right" id="querytime" value="Click to select date and time range">
|
||||
<input type="button" class="form-control pull-right" id="querytime" value="Click to select date and time range">
|
||||
</div>
|
||||
<!-- /.input group -->
|
||||
</div>
|
||||
@@ -45,34 +45,39 @@ $token = $_SESSION['token'];
|
||||
<label>Query status:</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-md-2">
|
||||
<div class="col-md-3">
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" id="type_gravity" checked>Blocked (exact)</label>
|
||||
<label><input type="checkbox" id="type_forwarded" checked><strong>Permitted: </strong>forwarded</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" id="type_cached" checked><strong>Permitted: </strong>cached</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<div class="col-md-3">
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" id="type_forwarded" checked>OK (forwarded)</label>
|
||||
<label><input type="checkbox" id="type_gravity" checked><strong>Blocked: </strong>gravity</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" id="type_external" checked><strong>Blocked: </strong>external</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<div class="col-md-3">
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" id="type_cached" checked>OK (cached)</label>
|
||||
<label><input type="checkbox" id="type_blacklist" checked><strong>Blocked: </strong>exact blacklist</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" id="type_regex" checked><strong>Blocked: </strong>regex blacklist</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<div class="col-md-3">
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" id="type_regex" checked>Blocked (regex/wildcard)</label>
|
||||
<label><input type="checkbox" id="type_gravity_CNAME" checked><strong>Blocked: </strong>gravity (CNAME)</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" id="type_blacklist" checked>Blocked (blacklist)</label>
|
||||
<label><input type="checkbox" id="type_blacklist_CNAME" checked><strong>Blocked: </strong>exact blacklist (CNAME)</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" id="type_external" checked>Blocked (external)</label>
|
||||
<label><input type="checkbox" id="type_regex_CNAME" checked><strong>Blocked: </strong>regex blacklist (CNAME)</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -92,7 +97,7 @@ $token = $_SESSION['token'];
|
||||
<p>Queries Blocked</p>
|
||||
</div>
|
||||
<div class="icon">
|
||||
<i class="ion ion-android-hand"></i>
|
||||
<i class="fas fa-hand-paper"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -105,7 +110,7 @@ $token = $_SESSION['token'];
|
||||
<p>Queries Blocked (Wildcards)</p>
|
||||
</div>
|
||||
<div class="icon">
|
||||
<i class="ion ion-android-hand"></i>
|
||||
<i class="fas fa-hand-paper"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -118,7 +123,7 @@ $token = $_SESSION['token'];
|
||||
<p>Queries Total</p>
|
||||
</div>
|
||||
<div class="icon">
|
||||
<i class="ion ion-earth"></i>
|
||||
<i class="fas fa-globe-americas"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -131,7 +136,7 @@ $token = $_SESSION['token'];
|
||||
<p>Queries Blocked</p>
|
||||
</div>
|
||||
<div class="icon">
|
||||
<i class="ion ion-pie-graph"></i>
|
||||
<i class="fas fa-chart-pie"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?php /*
|
||||
<?php /*
|
||||
* 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.
|
||||
@@ -12,7 +12,7 @@
|
||||
<h1>Generate debug log</h1>
|
||||
</div>
|
||||
|
||||
<p><input type="checkbox" id="upload" checked> Upload debug log and provide token once finished</p>
|
||||
<p><input type="checkbox" id="upload"> Upload debug log and provide token once finished</p>
|
||||
<p>Once you click this button a debug log will be generated and can automatically be uploaded if we detect a working internet connection.</p>
|
||||
<button class="btn btn-lg btn-primary btn-block" id="debugBtn">Generate debug log</button>
|
||||
<pre id="output" style="width: 100%; height: 100%;" hidden="true"></pre>
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php /*
|
||||
* 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. */
|
||||
require "scripts/pi-hole/php/header.php";
|
||||
|
||||
?>
|
||||
|
||||
<!-- Title -->
|
||||
<div class="page-header">
|
||||
<h1>Local DNS Records</h1>
|
||||
<small>On this page, you can add domain/IP associations</small>
|
||||
</div>
|
||||
|
||||
<!-- Domain Input -->
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="box">
|
||||
<!-- /.box-header -->
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">
|
||||
Add a new domain/IP combination
|
||||
</h3>
|
||||
</div>
|
||||
<!-- /.box-header -->
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="form-group col-md-6">
|
||||
<label for="domain">Domain:</label>
|
||||
<input id="domain" type="text" class="form-control" placeholder="Add a domain (example.com or sub.example.com)">
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="ip">IP Address:</label>
|
||||
<input id="ip" type="text" class="form-control" placeholder="Associated IP address">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer clearfix">
|
||||
<button id="btnAdd" class="btn btn-primary pull-right">Add</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Alerts -->
|
||||
<div id="alInfo" class="alert alert-info alert-dismissible fade in" role="alert" hidden="true">
|
||||
<button type="button" class="close" data-hide="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
Updating the custom DNS entries...
|
||||
</div>
|
||||
<div id="alSuccess" class="alert alert-success alert-dismissible fade in" role="alert" hidden="true">
|
||||
<button type="button" class="close" data-hide="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
Success! The list will refresh.
|
||||
</div>
|
||||
<div id="alFailure" class="alert alert-danger alert-dismissible fade in" role="alert" hidden="true">
|
||||
<button type="button" class="close" data-hide="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
Failure! Something went wrong, see output below:<br/><br/><pre><span id="err"></span></pre>
|
||||
</div>
|
||||
<div id="alWarning" class="alert alert-warning alert-dismissible fade in" role="alert" hidden="true">
|
||||
<button type="button" class="close" data-hide="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
At least one domain was already present, see output below:<br/><br/><pre><span id="warn"></span></pre>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="box" id="recent-queries">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">
|
||||
List of local DNS domains
|
||||
</h3>
|
||||
</div>
|
||||
<!-- /.box-header -->
|
||||
<div class="box-body">
|
||||
<table id="customDNSTable" class="display table table-striped table-bordered" cellspacing="0" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Domain</th>
|
||||
<th>IP</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
<button type="button" id="resetButton" hidden="true">Clear Filters</button>
|
||||
</div>
|
||||
<!-- /.box-body -->
|
||||
</div>
|
||||
<!-- /.box -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="scripts/pi-hole/js/customdns.js"></script>
|
||||
|
||||
<?php
|
||||
require "scripts/pi-hole/php/footer.php";
|
||||
?>
|
||||
@@ -15,7 +15,7 @@
|
||||
<!-- Alerts -->
|
||||
<div id="alInfo" class="alert alert-info alert-dismissible fade in" role="alert" hidden="true">
|
||||
<button type="button" class="close" data-hide="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
Updating...
|
||||
Updating...this may take a while. <strong>Please do not navigate away from or close this page.</strong>
|
||||
</div>
|
||||
<div id="alSuccess" class="alert alert-success alert-dismissible fade in" role="alert" hidden="true">
|
||||
<button type="button" class="close" data-hide="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php /*
|
||||
* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2019 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. */
|
||||
require "scripts/pi-hole/php/header.php";
|
||||
?>
|
||||
|
||||
<!-- Title -->
|
||||
<div class="page-header">
|
||||
<h1>Adlist group management</h1>
|
||||
</div>
|
||||
|
||||
<!-- Domain Input -->
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="box" id="add-group">
|
||||
<!-- /.box-header -->
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">
|
||||
Add a new adlist
|
||||
</h3>
|
||||
</div>
|
||||
<!-- /.box-header -->
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="form-group col-md-6">
|
||||
<label for="new_address">Address:</label>
|
||||
<input id="new_address" type="text" class="form-control" placeholder="http://..., https://..., file://...">
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="new_comment">Comment:</label>
|
||||
<input id="new_comment" type="text" class="form-control" placeholder="Adlist description (optional)">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer clearfix">
|
||||
<strong>Hint:</strong> Please run <code>pihole -g</code> or update your gravity list <a href="gravity.php">online</a> after modifying your adlists.
|
||||
<button id="btnAdd" class="btn btn-primary pull-right">Add</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="box" id="adlists-list">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">
|
||||
List of configured adlists
|
||||
</h3>
|
||||
</div>
|
||||
<!-- /.box-header -->
|
||||
<div class="box-body">
|
||||
<table id="adlistsTable" class="display table table-striped table-bordered" cellspacing="0" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Address</th>
|
||||
<th>Status</th>
|
||||
<th>Comment</th>
|
||||
<th>Group assignment</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
<button type="button" id="resetButton" hidden="true">Reset sorting</button>
|
||||
</div>
|
||||
<!-- /.box-body -->
|
||||
</div>
|
||||
<!-- /.box -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="scripts/pi-hole/js/groups-common.js"></script>
|
||||
<script src="scripts/pi-hole/js/groups-adlists.js"></script>
|
||||
|
||||
<?php
|
||||
require "scripts/pi-hole/php/footer.php";
|
||||
?>
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php /*
|
||||
* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2019 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. */
|
||||
require "scripts/pi-hole/php/header.php";
|
||||
?>
|
||||
|
||||
<!-- Title -->
|
||||
<div class="page-header">
|
||||
<h1>Client group management</h1>
|
||||
</div>
|
||||
|
||||
<!-- Domain Input -->
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="box" id="add-client">
|
||||
<!-- /.box-header -->
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">
|
||||
Add a new client
|
||||
</h3>
|
||||
</div>
|
||||
<!-- /.box-header -->
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="form-group col-md-6">
|
||||
<label for="select">Known clients:</label>
|
||||
<select id="select" class="form-control" placeholder="">
|
||||
<option disabled selected>Loading...</option>
|
||||
</select><br>
|
||||
<input id="ip-custom" type="text" class="form-control" disabled placeholder="Client IP address (IPv4 or IPv6, CIDR subnetting available, optional)">
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="new_comment">Comment:</label>
|
||||
<input id="new_comment" type="text" class="form-control" placeholder="Client description (optional)">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer clearfix">
|
||||
<button id="btnAdd" class="btn btn-primary pull-right">Add</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="box" id="clients-list">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">
|
||||
List of configured clients
|
||||
</h3>
|
||||
</div>
|
||||
<!-- /.box-header -->
|
||||
<div class="box-body">
|
||||
<table id="clientsTable" class="display table table-striped table-bordered" cellspacing="0" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>IP address</th>
|
||||
<th>Comment</th>
|
||||
<th>Group assignment</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
<button type="button" id="resetButton" hidden="true">Reset sorting</button>
|
||||
</div>
|
||||
<!-- /.box-body -->
|
||||
</div>
|
||||
<!-- /.box -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="scripts/pi-hole/js/groups-common.js"></script>
|
||||
<script src="scripts/pi-hole/js/groups-clients.js"></script>
|
||||
|
||||
<?php
|
||||
require "scripts/pi-hole/php/footer.php";
|
||||
?>
|
||||
@@ -0,0 +1,143 @@
|
||||
<?php /*
|
||||
* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2019 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. */
|
||||
require "scripts/pi-hole/php/header.php";
|
||||
$type = "all";
|
||||
$pagetitle = "Domain";
|
||||
$adjective = "";
|
||||
if (isset($_GET['type']) && ($_GET['type'] === "white" || $_GET['type'] === "black")) {
|
||||
$type = $_GET['type'];
|
||||
$pagetitle = ucfirst($type)."list";
|
||||
$adjective = $type."listed";
|
||||
}
|
||||
?>
|
||||
|
||||
<!-- Title -->
|
||||
<div class="page-header">
|
||||
<h1><?php echo $pagetitle; ?> management</h1>
|
||||
</div>
|
||||
|
||||
<!-- Domain Input -->
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="box" id="add-group">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">
|
||||
Add a new <?php echo $adjective; ?> domain or regex filter
|
||||
</h3>
|
||||
</div>
|
||||
<!-- /.box-header -->
|
||||
<div class="box-body">
|
||||
<div class="nav-tabs-custom">
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="active"><a aria-expanded="true" href="#tab_domain" data-toggle="tab">Domain</a></li>
|
||||
<li class=""><a aria-expanded="false" href="#tab_regex" data-toggle="tab">RegEx filter</a></li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<!-- Domain tab -->
|
||||
<div id="tab_domain" class="tab-pane active in">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="new_domain">Domain:</label>
|
||||
<div class="input-group">
|
||||
<input id="new_domain" type="text" class="form-control active" placeholder="Domain to be added">
|
||||
<span class="input-group-addon">
|
||||
<input type="checkbox" id="wildcard_checkbox">
|
||||
wildcard</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<strong><i class="fa fa-question-circle"></i> Checkbox "wildcard":</span></strong> Check this box if you want to involve
|
||||
all subdomains. The entered domain will be converted to a RegEx filter while adding.
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 form-group">
|
||||
<label for="new_domain_comment">Comment:</label>
|
||||
<input id="new_domain_comment" type="text" class="form-control" placeholder="Description (optional)">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- RegEx tab -->
|
||||
<div id="tab_regex" class="tab-pane">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="new_regex">Regular Expression:</label>
|
||||
<input id="new_regex" type="text" class="form-control active" placeholder="RegEx to be added">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<strong>Hint:</strong> Need help to write a proper RegEx rule? Have a look at our online
|
||||
<a href="https://docs.pi-hole.net/ftldns/regex/tutorial" rel="noopener" target="_blank">
|
||||
regular expressions tutorial</a>.
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="new_regex_comment">Comment:</label>
|
||||
<input id="new_regex_comment" type="text" class="form-control" placeholder="Description (optional)">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-toolbar pull-right" role="toolbar" aria-label="Toolbar with buttons">
|
||||
<?php if ( $type !== "white" ) { ?>
|
||||
<div class="btn-group" role="group" aria-label="Third group">
|
||||
<button type="button" class="btn btn-primary" id="add2black">Add to Blacklist</button>
|
||||
</div>
|
||||
<?php } if ( $type !== "black" ) { ?>
|
||||
<div class="btn-group" role="group" aria-label="Third group">
|
||||
<button type="button" class="btn btn-primary" id="add2white">Add to Whitelist</button>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.box-body -->
|
||||
</div>
|
||||
<!-- /.box -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Domain List -->
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="box" id="domains-list">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">
|
||||
List of <?php echo $adjective; ?> entries
|
||||
</h3>
|
||||
</div>
|
||||
<!-- /.box-header -->
|
||||
<div class="box-body">
|
||||
<table id="domainsTable" class="display table table-striped table-bordered" cellspacing="0" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Domain/RegEx</th>
|
||||
<th>Type</th>
|
||||
<th>Status</th>
|
||||
<th>Comment</th>
|
||||
<th>Group assignment</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
<button type="button" id="resetButton" hidden="true">Reset sorting</button>
|
||||
</div>
|
||||
<!-- /.box-body -->
|
||||
</div>
|
||||
<!-- /.box -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="scripts/pi-hole/js/groups-common.js"></script>
|
||||
<script src="scripts/pi-hole/js/groups-domains.js"></script>
|
||||
|
||||
<?php
|
||||
require "scripts/pi-hole/php/footer.php";
|
||||
?>
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php /*
|
||||
* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2019 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. */
|
||||
require "scripts/pi-hole/php/header.php";
|
||||
?>
|
||||
|
||||
<!-- Title -->
|
||||
<div class="page-header">
|
||||
<h1>Group management</h1>
|
||||
</div>
|
||||
|
||||
<!-- Group Input -->
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="box" id="add-group">
|
||||
<!-- /.box-header -->
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">
|
||||
Add a new group
|
||||
</h3>
|
||||
</div>
|
||||
<!-- /.box-header -->
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="form-group col-md-6">
|
||||
<label for="new_name">Name:</label>
|
||||
<input id="new_name" type="text" class="form-control" placeholder="Group name">
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="new_desc">Description:</label>
|
||||
<input id="new_desc" type="text" class="form-control" placeholder="Group description (optional)">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer clearfix">
|
||||
<button id="btnAdd" class="btn btn-primary pull-right">Add</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="box" id="groups-list">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">
|
||||
List of configured groups
|
||||
</h3>
|
||||
</div>
|
||||
<!-- /.box-header -->
|
||||
<div class="box-body">
|
||||
<table id="groupsTable" class="display table table-striped table-bordered" cellspacing="0" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Name</th>
|
||||
<th>Status</th>
|
||||
<th>Description</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
<button type="button" id="resetButton" hidden="true">Reset sorting</button>
|
||||
</div>
|
||||
<!-- /.box-body -->
|
||||
</div>
|
||||
<!-- /.box -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="scripts/pi-hole/js/groups-common.js"></script>
|
||||
<script src="scripts/pi-hole/js/groups.js"></script>
|
||||
|
||||
<?php
|
||||
require "scripts/pi-hole/php/footer.php";
|
||||
?>
|
||||
@@ -24,7 +24,7 @@
|
||||
<h4>Top left: Status display</h4>
|
||||
<p>Shows different status messages:</p>
|
||||
<ul>
|
||||
<li>Status: Current status of the Pi-hole - Active (<i class="fa fa-circle" style="color:#7FFF00"></i>), Offline (<i class="fa fa-circle" style="color:#FF0000"></i>), or Starting (<i class="fa fa-circle" style="color:#ff9900"></i>)</li>
|
||||
<li>Status: Current status of the Pi-hole - Active (<i class="fa fa-circle text-green-light"></i>), Offline (<i class="fa fa-circle text-red"></i>), or Starting (<i class="fa fa-circle text-orange"></i>)</li>
|
||||
<li>Temp: Current CPU temperature</li>
|
||||
<li>Load: load averages for the last minute, 5 minutes and 15 minutes, respectively. A load average of 1 reflects the full workload of a single processor on the system. We show a red icon if the current load exceeds the number of available processors on this machine (which is <?php echo $nproc; ?>)</li>
|
||||
<li>Memory usage: Shows the percentage of memory actually blocked by applications. We show a red icon if the memory usage exceeds 75%</li>
|
||||
@@ -70,7 +70,7 @@
|
||||
<div class="col-md-12">
|
||||
<h2>White- / Blacklist</h2>
|
||||
<p>Add or remove domains (or subdomains) from the white-/blacklist. If a domain is added to e.g. the whitelist, any possible entry of the same domain will be automatically removed from the blacklist and vice versa.</p>
|
||||
<p>Regex blacklisting is supported (entering <samp>^example</samp> will block any domain starting with <samp>example</samp>, see also our <a href="https://docs.pi-hole.net/ftldns/regex/" target="_blank">Regex documentation</a>). You can still whitelist specific domains even if they fall under a regex pattern.</p>
|
||||
<p>Regex blacklisting is supported (entering <code>^example</code> will block any domain starting with <code>example</code>, see also our <a href="https://docs.pi-hole.net/ftldns/regex/" rel="noopener" target="_blank">Regex documentation</a>). You can still whitelist specific domains even if they fall under a regex pattern.</p>
|
||||
<p>You can white-/blacklist multiple entries at a time if you separate the domains by spaces.</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -89,7 +89,7 @@
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h2>Tools → Query Lists</h2>
|
||||
This function is useful to find out what list a domain appears on. Since we don't control what the third-parties put on the blocklists, you may find that a domain you normally visit stops working. If this is the case, you could run this command to scan for strings in the list of blocked domains and it will return the list the domain is found on. This proved useful a while back when the Mahakala list was adding <samp>apple.com</samp> and <samp>microsoft.com</samp> to their block list.</p>
|
||||
This function is useful to find out what list a domain appears on. Since we don't control what the third-parties put on the blocklists, you may find that a domain you normally visit stops working. If this is the case, you could run this command to scan for strings in the list of blocked domains and it will return the list the domain is found on. This proved useful a while back when the Mahakala list was adding <code>apple.com</code> and <code>microsoft.com</code> to their block list.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
|
||||
|
Before Width: | Height: | Size: 8.5 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 508 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 15 KiB |
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "Pi-hole Admin Console",
|
||||
"short_name": "Pi-hole",
|
||||
"icons": [
|
||||
{
|
||||
"src": "android-chrome-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "android-chrome-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"theme_color": "#367fa9",
|
||||
"background_color": "#367fa9",
|
||||
"display": "standalone"
|
||||
}
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 88.32 129.93"><defs><style>.cls-1{fill:url(#New_Gradient_Swatch_1);}.cls-2{fill:#980200;}.cls-3{fill:red;}</style><linearGradient id="New_Gradient_Swatch_1" x1="2.71" y1="20.04" x2="69.77" y2="20.04" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#12b212"/><stop offset="1" stop-color="lime"/></linearGradient></defs><title>NewVortex</title><g id="Layer_2" data-name="Layer 2"><g id="RedBerry"><path id="Leaf_Path" data-name="Leaf Path" class="cls-1" d="M36.56,39.93m0,0C20.34,38.2,4,25.94,2.71,0,27.88,0,41.34,14.9,42.64,38.51c4.76-28.32,27.07-25,27.07-25,1.06,16.05-12.12,25.78-27.07,26.59C38.44,31.25,13.28,9.54,13.28,9.54a.07.07,0,0,0-.11.08S37.45,30.77,36.56,39.93"/><path id="LeftBerry" class="cls-2" d="M44.16,129.93c-1.57-.09-16.22-.65-17.11-17.11-.72-10,7.18-17.37,7.18-27.08C32.44,61.53,0,64.53,0,85.74H0A19.94,19.94,0,0,0,5.83,99.88L30,124.06a19.94,19.94,0,0,0,14.14,5.83"/><path id="BottomBerry" class="cls-3" d="M88.32,85.75c-.09,1.57-.65,16.22-17.11,17.11-10,.72-17.38-7.18-27.08-7.18-24.21,1.79-21.21,34.22,0,34.22h0a19.94,19.94,0,0,0,14.14-5.83L82.46,99.9a19.94,19.94,0,0,0,5.83-14.14"/><path id="RightBerry" class="cls-2" d="M44.16,41.59c1.57.09,16.22.65,17.11,17.11.72,10-7.18,17.37-7.18,27.08,1.79,24.21,34.22,21.21,34.22,0h0a19.94,19.94,0,0,0-5.83-14.14L58.3,47.45a19.94,19.94,0,0,0-14.14-5.83"/><path id="TopBerry" class="cls-3" d="M.08,85.75c.09-1.57.65-16.22,17.11-17.11,10-.72,17.38,7.18,27.08,7.18C68.48,74,65.48,41.6,44.27,41.6h0a19.94,19.94,0,0,0-14.14,5.83L5.94,71.61A19.94,19.94,0,0,0,.11,85.75"/></g></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 88.32 129.93"><defs><linearGradient id="New_Gradient_Swatch_1" x1="2.71" x2="69.77" y1="20.04" y2="20.04" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#12b212"/><stop offset="1" stop-color="#0f0"/></linearGradient><style>.cls-2{fill:#980200}.cls-3{fill:red}</style></defs><title>NewVortex</title><path fill="url(#New_Gradient_Swatch_1)" d="M36.56 39.93C20.34 38.2 4 25.94 2.71 0c25.17 0 38.63 14.9 39.93 38.51 4.76-28.32 27.07-25 27.07-25 1.06 16.05-12.12 25.78-27.07 26.59-4.2-8.85-29.36-30.56-29.36-30.56a.07.07 0 00-.11.08s24.28 21.15 23.39 30.31"/><path d="M44.16 129.93c-1.57-.09-16.22-.65-17.11-17.11-.72-10 7.18-17.37 7.18-27.08C32.44 61.53 0 64.53 0 85.74a19.94 19.94 0 005.83 14.14L30 124.06a19.94 19.94 0 0014.14 5.83" class="cls-2"/><path d="M88.32 85.75c-.09 1.57-.65 16.22-17.11 17.11-10 .72-17.38-7.18-27.08-7.18-24.21 1.79-21.21 34.22 0 34.22a19.94 19.94 0 0014.14-5.83L82.46 99.9a19.94 19.94 0 005.83-14.14" class="cls-3"/><path d="M44.16 41.59c1.57.09 16.22.65 17.11 17.11.72 10-7.18 17.37-7.18 27.08 1.79 24.21 34.22 21.21 34.22 0a19.94 19.94 0 00-5.83-14.14L58.3 47.45a19.94 19.94 0 00-14.14-5.83" class="cls-2"/><path d="M.08 85.75c.09-1.57.65-16.22 17.11-17.11 10-.72 17.38 7.18 27.08 7.18 24.21-1.82 21.21-34.22 0-34.22a19.94 19.94 0 00-14.14 5.83L5.94 71.61A19.94 19.94 0 00.11 85.75" class="cls-3"/></svg>
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.4 KiB |
@@ -32,7 +32,7 @@
|
||||
<h3 class="statistic"><span id="dns_queries_today">---</span></h3>
|
||||
</div>
|
||||
<div class="icon">
|
||||
<i class="ion ion-earth"></i>
|
||||
<i class="fas fa-globe-americas"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -45,7 +45,7 @@
|
||||
<h3 class="statistic"><span id="ads_blocked_today">---</span></h3>
|
||||
</div>
|
||||
<div class="icon">
|
||||
<i class="ion ion-android-hand"></i>
|
||||
<i class="fas fa-hand-paper"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -58,7 +58,7 @@
|
||||
<h3 class="statistic"><span id="ads_percentage_today">---</span></h3>
|
||||
</div>
|
||||
<div class="icon">
|
||||
<i class="ion ion-pie-graph"></i>
|
||||
<i class="fas fa-chart-pie"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -71,7 +71,7 @@
|
||||
<h3 class="statistic"><span id="domains_being_blocked">---</span></h3>
|
||||
</div>
|
||||
<div class="icon">
|
||||
<i class="ion ion-ios-list"></i>
|
||||
<i class="fas fa-list-alt"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -82,7 +82,7 @@
|
||||
<div class="col-md-12">
|
||||
<div class="box" id="queries-over-time">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">Queries over last <?php echo getinterval(); ?> hours</h3>
|
||||
<h3 class="box-title">Total queries over last <?php echo getinterval(); ?> hours</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="chart">
|
||||
@@ -107,7 +107,7 @@
|
||||
<div class="col-md-12">
|
||||
<div class="box" id="clients">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">Clients (over time)</h3>
|
||||
<h3 class="box-title">Client activity over last <?php echo getinterval(); ?> hours</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="chart">
|
||||
@@ -129,10 +129,10 @@
|
||||
<h3 class="box-title">Query Types</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="float-left" style="width:50%">
|
||||
<div class="pull-left" style="width:50%">
|
||||
<canvas id="queryTypePieChart" width="120" height="120"></canvas>
|
||||
</div>
|
||||
<div class="float-left" style="width:50%">
|
||||
<div class="pull-left" style="width:50%">
|
||||
<div id="query-types-legend" class="chart-legend"></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -148,10 +148,10 @@
|
||||
<h3 class="box-title">Queries answered by</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="float-left" style="width:50%">
|
||||
<div class="pull-left" style="width:50%">
|
||||
<canvas id="forwardDestinationPieChart" width="120" height="120" class="extratooltipcanvas"></canvas>
|
||||
</div>
|
||||
<div class="float-left" style="width:50%">
|
||||
<div class="pull-left" style="width:50%">
|
||||
<div id="forward-destinations-legend" class="chart-legend" class="extratooltipcanvas"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
<?php /*
|
||||
* 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. */
|
||||
require "scripts/pi-hole/php/header.php";
|
||||
|
||||
$list = $_GET['l'];
|
||||
|
||||
if($list !== "white" && $list !== "black"){
|
||||
echo "Invalid list parameter";
|
||||
require "scripts/pi-hole/php/footer.php";
|
||||
die();
|
||||
}
|
||||
|
||||
function getFullName() {
|
||||
global $list;
|
||||
if($list == "white")
|
||||
echo "Whitelist";
|
||||
else
|
||||
echo "Blacklist";
|
||||
}
|
||||
?>
|
||||
<!-- Send list type to JS -->
|
||||
<div id="list-type" hidden><?php echo $list ?></div>
|
||||
|
||||
<!-- Title -->
|
||||
<div class="page-header">
|
||||
<h1><?php getFullName(); ?></h1>
|
||||
</div>
|
||||
|
||||
<!-- Domain Input -->
|
||||
<div class="form-group input-group">
|
||||
<input id="domain" type="text" class="form-control" placeholder="Add a domain (example.com or sub.example.com)">
|
||||
<span class="input-group-btn">
|
||||
<?php if($list === "black") { ?>
|
||||
<button id="btnAdd" class="btn btn-default" type="button">Add (exact)</button>
|
||||
<button id="btnAddWildcard" class="btn btn-default" type="button">Add (wildcard)</button>
|
||||
<button id="btnAddRegex" class="btn btn-default" type="button">Add (regex)</button>
|
||||
<?php }else{ ?>
|
||||
<button id="btnAdd" class="btn btn-default" type="button">Add</button>
|
||||
<?php } ?>
|
||||
<button id="btnRefresh" class="btn btn-default" type="button"><i class="fa fa-sync"></i></button>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Alerts -->
|
||||
<div id="alInfo" class="alert alert-info alert-dismissible fade in" role="alert" hidden="true">
|
||||
<button type="button" class="close" data-hide="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
Adding to the <?php getFullName(); ?>...
|
||||
</div>
|
||||
<div id="alSuccess" class="alert alert-success alert-dismissible fade in" role="alert" hidden="true">
|
||||
<button type="button" class="close" data-hide="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
Success! The list will refresh.
|
||||
</div>
|
||||
<div id="alFailure" class="alert alert-danger alert-dismissible fade in" role="alert" hidden="true">
|
||||
<button type="button" class="close" data-hide="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
Failure! Something went wrong, see output below:<br/><br/><pre><span id="err"></span></pre>
|
||||
</div>
|
||||
<div id="alWarning" class="alert alert-warning alert-dismissible fade in" role="alert" hidden="true">
|
||||
<button type="button" class="close" data-hide="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
At least one domain was already present, see output below:<br/><br/><pre><span id="warn"></span></pre>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Domain List -->
|
||||
<?php if($list === "black") { ?>
|
||||
<h3>Exact blocking</h3>
|
||||
<?php } ?>
|
||||
<ul class="list-group" id="list"></ul>
|
||||
<?php if($list === "black") { ?>
|
||||
<h3><a href="https://docs.pi-hole.net/ftldns/regex/overview/" target="_blank" title="Click for Pi-hole Regex documentation">Regex</a> & Wildcard blocking</h3>
|
||||
<ul class="list-group" id="list-regex"></ul>
|
||||
<?php } ?>
|
||||
|
||||
<script src="scripts/pi-hole/js/list.js"></script>
|
||||
|
||||
<?php
|
||||
require "scripts/pi-hole/php/footer.php";
|
||||
?>
|
||||
@@ -52,12 +52,12 @@ $token = $_SESSION['token'];
|
||||
</table>
|
||||
<label>Background color: Last query from this device seen ...</label>
|
||||
<table width="100%">
|
||||
<tr style="text-align: center;">
|
||||
<td style="background: #E7FFDE;" width="15%">just now</td>
|
||||
<td style="background-image: linear-gradient(to right, #E7FFDE 0%, #FFFFDF 100%)" width="30%"><center>... to ...</center></td>
|
||||
<td style="background: #FFFFDF;" width="15%">24 hours ago</td>
|
||||
<td style="background: #FFEDD9;" width="20%">> 24 hours ago</td>
|
||||
<td style="background: #FFBFAA;" width="20%">Device does not use Pi-hole</td>
|
||||
<tr class="text-center">
|
||||
<td style="background: #e7ffde;" width="15%">just now</td>
|
||||
<td style="background-image: linear-gradient(to right, #e7ffde 0%, #ffffdf 100%)" width="30%"><center>... to ...</center></td>
|
||||
<td style="background: #ffffdf;" width="15%">24 hours ago</td>
|
||||
<td style="background: #ffedd9;" width="20%">> 24 hours ago</td>
|
||||
<td style="background: #ffbfaa;" width="20%">Device does not use Pi-hole</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"name": "AdminLTE",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/pi-hole/AdminLTE.git"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "EUPL-1.2",
|
||||
"bugs": {
|
||||
"url": "https://github.com/pi-hole/AdminLTE/issues"
|
||||
},
|
||||
"homepage": "https://github.com/pi-hole/AdminLTE#readme",
|
||||
"scripts": {
|
||||
"xo": "xo",
|
||||
"xo:fix": "npm run xo -- --fix",
|
||||
"test": "npm run xo"
|
||||
},
|
||||
"devDependencies": {
|
||||
"xo": "^0.25.3"
|
||||
},
|
||||
"prettier": {
|
||||
"bracketSpacing": true,
|
||||
"printWidth": 100,
|
||||
"singleQuote": false,
|
||||
"trailingComma": "none"
|
||||
},
|
||||
"xo": {
|
||||
"space": 2,
|
||||
"envs": [
|
||||
"browser",
|
||||
"jquery"
|
||||
],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 3,
|
||||
"sourceType": "script"
|
||||
},
|
||||
"esnext": false,
|
||||
"prettier": true,
|
||||
"ignores": [
|
||||
"**/vendor/**"
|
||||
],
|
||||
"rules": {
|
||||
"camelcase": "off",
|
||||
"capitalized-comments": "off",
|
||||
"new-cap": "off",
|
||||
"no-alert": "off",
|
||||
"no-negated-condition": "off",
|
||||
"one-var": "off",
|
||||
"radix": "off",
|
||||
"spaced-comment": "off",
|
||||
"unicorn/explicit-length-check": "off",
|
||||
"unicorn/filename-case": "off",
|
||||
"unicorn/no-for-loop": "off",
|
||||
"unicorn/no-zero-fractions": "off",
|
||||
"unicorn/prefer-includes": "off",
|
||||
"unicorn/prefer-node-append": "off",
|
||||
"unicorn/prefer-query-selector": "off",
|
||||
"unicorn/prefer-string-slice": "off"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -155,7 +155,7 @@ if(strlen($showing) > 0)
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
<label><input type="checkbox" id="autofilter" checked="true"> Apply filtering on click on Type, Domain, and Clients</label><br/>
|
||||
<label><input type="checkbox" id="autofilter"> Apply filtering on click on Type, Domain, and Clients</label><br/>
|
||||
<button type="button" id="resetButton" hidden="true">Clear Filters</button>
|
||||
</div>
|
||||
<!-- /.box-body -->
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
/* 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. */
|
||||
* (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. */
|
||||
|
||||
// Define global variables
|
||||
var timeLineChart, queryTypeChart, forwardDestinationChart, auditList = [], auditTimeout;
|
||||
var auditTimeout = null;
|
||||
|
||||
// Credit: http://stackoverflow.com/questions/1787322/htmlspecialchars-equivalent-in-javascript/4835406#4835406
|
||||
function escapeHtml(text) {
|
||||
@@ -13,124 +14,145 @@ function escapeHtml(text) {
|
||||
"&": "&",
|
||||
"<": "<",
|
||||
">": ">",
|
||||
"\"": """,
|
||||
"\'": "'"
|
||||
'"': """,
|
||||
"'": "'"
|
||||
};
|
||||
|
||||
return text.replace(/[&<>"']/g, function(m) { return map[m]; });
|
||||
return text.replace(/[&<>"']/g, function(m) {
|
||||
return map[m];
|
||||
});
|
||||
}
|
||||
|
||||
function updateTopLists() {
|
||||
$.getJSON("api.php?topItems=audit", function(data) {
|
||||
$.getJSON("api.php?topItems=audit", function(data) {
|
||||
if ("FTLnotrunning" in data) {
|
||||
return;
|
||||
}
|
||||
|
||||
if("FTLnotrunning" in data)
|
||||
{
|
||||
return;
|
||||
// Clear tables before filling them with data
|
||||
$("#domain-frequency td")
|
||||
.parent()
|
||||
.remove();
|
||||
$("#ad-frequency td")
|
||||
.parent()
|
||||
.remove();
|
||||
var domaintable = $("#domain-frequency").find("tbody:last");
|
||||
var adtable = $("#ad-frequency").find("tbody:last");
|
||||
var url, domain;
|
||||
for (domain in data.top_queries) {
|
||||
if (Object.prototype.hasOwnProperty.call(data.top_queries, domain)) {
|
||||
// Sanitize domain
|
||||
domain = escapeHtml(domain);
|
||||
url = '<a href="queries.php?domain=' + domain + '">' + domain + "</a>";
|
||||
domaintable.append(
|
||||
"<tr><td>" +
|
||||
url +
|
||||
"</td> <td>" +
|
||||
data.top_queries[domain] +
|
||||
'</td> <td> <button type="button" class="btn btn-default btn-sm text-red"><i class="fa fa-ban"></i> Blacklist</button> <button class="btn btn-default btn-sm text-orange"><i class="fa fa-balance-scale"></i> Audit</button> </td> </tr> '
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for (domain in data.top_ads) {
|
||||
if (Object.prototype.hasOwnProperty.call(data.top_ads, domain)) {
|
||||
var input = domain.split(" ");
|
||||
// Sanitize domain
|
||||
var printdomain = escapeHtml(input[0]);
|
||||
if (input.length > 1) {
|
||||
url =
|
||||
'<a href="queries.php?domain=' +
|
||||
printdomain +
|
||||
'">' +
|
||||
printdomain +
|
||||
"</a> (wildcard blocked)";
|
||||
adtable.append(
|
||||
"<tr><td>" +
|
||||
url +
|
||||
"</td> <td>" +
|
||||
data.top_ads[domain] +
|
||||
'</td> <td> <button type="button" class="btn btn-default btn-sm text-orange"><i class="fa fa-balance-scale"></i> Audit</button> </td> </tr> '
|
||||
);
|
||||
} else {
|
||||
url = '<a href="queries.php?domain=' + printdomain + '">' + printdomain + "</a>";
|
||||
adtable.append(
|
||||
"<tr><td>" +
|
||||
url +
|
||||
"</td> <td>" +
|
||||
data.top_ads[domain] +
|
||||
'</td> <td> <button type="button" class="btn btn-default btn-sm text-green"><i class="fas fa-check"></i> Whitelist</button> <button class="btn btn-default btn-sm text-orange"><i class="fa fa-balance-scale"></i> Audit</button> </td> </tr> '
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear tables before filling them with data
|
||||
$("#domain-frequency td").parent().remove();
|
||||
$("#ad-frequency td").parent().remove();
|
||||
var domaintable = $("#domain-frequency").find("tbody:last");
|
||||
var adtable = $("#ad-frequency").find("tbody:last");
|
||||
var url, domain, percentage;
|
||||
for (domain in data.top_queries) {
|
||||
if ({}.hasOwnProperty.call(data.top_queries,domain)){
|
||||
// Sanitize domain
|
||||
domain = escapeHtml(domain);
|
||||
url = "<a href=\"queries.php?domain="+domain+"\">"+domain+"</a>";
|
||||
percentage = data.top_queries[domain] / data.dns_queries_today * 100;
|
||||
domaintable.append("<tr> <td>" + url +
|
||||
"</td> <td>" + data.top_queries[domain] + "</td> <td> <button style=\"color:red; white-space: nowrap;\"><i class=\"fa fa-ban\"></i> Blacklist</button> <button style=\"color:orange; white-space: nowrap;\"><i class=\"fa fa-balance-scale\"></i> Audit</button> </td> </tr> ");
|
||||
}
|
||||
}
|
||||
$("#domain-frequency .overlay").hide();
|
||||
$("#ad-frequency .overlay").hide();
|
||||
// Update top lists data every ten seconds
|
||||
// Updates are also triggered by button actions
|
||||
// and reset the running timer
|
||||
if (auditTimeout !== null) {
|
||||
window.clearTimeout(auditTimeout);
|
||||
}
|
||||
|
||||
for (domain in data.top_ads) {
|
||||
if ({}.hasOwnProperty.call(data.top_ads,domain)){
|
||||
var input = domain.split(" ");
|
||||
// Sanitize domain
|
||||
var printdomain = escapeHtml(input[0]);
|
||||
if(input.length > 1)
|
||||
{
|
||||
url = "<a href=\"queries.php?domain="+printdomain+"\">"+printdomain+"</a> (wildcard blocked)";
|
||||
adtable.append("<tr> <td>" + url +
|
||||
"</td> <td>" + data.top_ads[domain] + "</td> <td> <button style=\"color:orange; white-space: nowrap;\"><i class=\"fa fa-balance-scale\"></i> Audit</button> </td> </tr> ");
|
||||
}
|
||||
else
|
||||
{
|
||||
url = "<a href=\"queries.php?domain="+printdomain+"\">"+printdomain+"</a>";
|
||||
adtable.append("<tr> <td>" + url +
|
||||
"</td> <td>" + data.top_ads[domain] + "</td> <td> <button style=\"color:green; white-space: nowrap;\"><i class=\"fas fa-check\"></i> Whitelist</button> <button style=\"color:orange; white-space: nowrap;\"><i class=\"fa fa-balance-scale\"></i> Audit</button> </td> </tr> ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$("#domain-frequency .overlay").hide();
|
||||
$("#ad-frequency .overlay").hide();
|
||||
// Update top lists data every second
|
||||
setTimeout(updateTopLists, 1000);
|
||||
});
|
||||
auditTimeout = setTimeout(updateTopLists, 10000);
|
||||
});
|
||||
}
|
||||
|
||||
function add(domain, list) {
|
||||
var token = $("#token").text();
|
||||
$.ajax({
|
||||
url: "scripts/pi-hole/php/add.php",
|
||||
method: "post",
|
||||
data: { domain: domain, list: list, token: token },
|
||||
success: function() {
|
||||
updateTopLists();
|
||||
},
|
||||
error: function(jqXHR, exception) {
|
||||
console.log(exception);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function add(domain,list) {
|
||||
var token = $("#token").html();
|
||||
$.ajax({
|
||||
url: "scripts/pi-hole/php/add.php",
|
||||
method: "post",
|
||||
data: {"domain":domain, "list":list, "token":token, "auditlog":1}
|
||||
});
|
||||
function blacklistUrl(url) {
|
||||
// We add to audit last as it will reload the table on success
|
||||
add(url, "black");
|
||||
add(url, "audit");
|
||||
}
|
||||
|
||||
function whitelistUrl(url) {
|
||||
// We add to audit last as it will reload the table on success
|
||||
add(url, "white");
|
||||
add(url, "audit");
|
||||
}
|
||||
|
||||
function auditUrl(url) {
|
||||
add(url, "audit");
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
// Pull in data via AJAX
|
||||
updateTopLists();
|
||||
|
||||
// Pull in data via AJAX
|
||||
updateTopLists();
|
||||
|
||||
$("#domain-frequency tbody").on( "click", "button", function () {
|
||||
var url = ($(this).parents("tr"))[0].innerText.split(" ")[0];
|
||||
if($(this).context.innerText === " Blacklist")
|
||||
{
|
||||
add(url,"black");
|
||||
$("#gravityBtn").prop("disabled", false);
|
||||
}
|
||||
else
|
||||
{
|
||||
auditUrl(url);
|
||||
}
|
||||
});
|
||||
|
||||
$("#ad-frequency tbody").on( "click", "button", function () {
|
||||
var url = ($(this).parents("tr"))[0].innerText.split(" ")[0].split(" ")[0];
|
||||
if($(this).context.innerText === " Whitelist")
|
||||
{
|
||||
add(url,"white");
|
||||
$("#gravityBtn").prop("disabled", false);
|
||||
}
|
||||
else
|
||||
{
|
||||
auditUrl(url);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function auditUrl(url) {
|
||||
if (auditList.indexOf(url) > -1) {
|
||||
return;
|
||||
$("#domain-frequency tbody").on("click", "button", function() {
|
||||
var url = $(this)
|
||||
.parents("tr")[0]
|
||||
.textContent.split(" ")[0];
|
||||
if ($(this).context.textContent === " Blacklist") {
|
||||
blacklistUrl(url);
|
||||
} else {
|
||||
auditUrl(url);
|
||||
}
|
||||
if (auditTimeout) {
|
||||
clearTimeout(auditTimeout);
|
||||
});
|
||||
|
||||
$("#ad-frequency tbody").on("click", "button", function() {
|
||||
var url = $(this)
|
||||
.parents("tr")[0]
|
||||
.textContent.split(" ")[0];
|
||||
if ($(this).context.textContent === " Whitelist") {
|
||||
whitelistUrl(url);
|
||||
} else {
|
||||
auditUrl(url);
|
||||
}
|
||||
auditList.push(url);
|
||||
// wait 3 seconds to see if more domains need auditing
|
||||
// and batch them all into a single request
|
||||
auditTimeout = setTimeout(function() {
|
||||
add(auditList.join(' '), "audit");
|
||||
auditList = [];
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
|
||||
$("#gravityBtn").on("click", function() {
|
||||
window.location.replace("gravity.php?go");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
/* 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. */
|
||||
|
||||
var table;
|
||||
|
||||
function showAlert(type, message) {
|
||||
var alertElement = null;
|
||||
var messageElement = null;
|
||||
|
||||
switch (type) {
|
||||
case "info":
|
||||
alertElement = $("#alInfo");
|
||||
break;
|
||||
case "success":
|
||||
alertElement = $("#alSuccess");
|
||||
break;
|
||||
case "warning":
|
||||
alertElement = $("#alWarning");
|
||||
messageElement = $("#warn");
|
||||
break;
|
||||
case "error":
|
||||
alertElement = $("#alFailure");
|
||||
messageElement = $("#err");
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (messageElement !== null) messageElement.html(message);
|
||||
|
||||
alertElement.fadeIn(200);
|
||||
alertElement.delay(8000).fadeOut(2000);
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
$("#btnAdd").on("click", addCustomDNS);
|
||||
|
||||
table = $("#customDNSTable").DataTable({
|
||||
ajax: "scripts/pi-hole/php/customdns.php?action=get",
|
||||
columns: [{}, {}, { orderable: false, searchable: false }],
|
||||
columnDefs: [
|
||||
{
|
||||
targets: 2,
|
||||
render: function(data, type, row) {
|
||||
return (
|
||||
'<button class="btn btn-danger btn-xs deleteCustomDNS" type="button" data-domain=\'' +
|
||||
row[0] +
|
||||
"' data-ip='" +
|
||||
row[1] +
|
||||
"'>" +
|
||||
'<span class="glyphicon glyphicon-trash"></span>' +
|
||||
"</button>"
|
||||
);
|
||||
}
|
||||
}
|
||||
],
|
||||
drawCallback: function() {
|
||||
$(".deleteCustomDNS").on("click", deleteCustomDNS);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function addCustomDNS() {
|
||||
var ip = $("#ip").val();
|
||||
var domain = $("#domain").val();
|
||||
|
||||
showAlert("info");
|
||||
$.ajax({
|
||||
url: "scripts/pi-hole/php/customdns.php",
|
||||
method: "post",
|
||||
dataType: "json",
|
||||
data: { action: "add", ip: ip, domain: domain },
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
showAlert("success");
|
||||
table.ajax.reload();
|
||||
} else showAlert("error", response.message);
|
||||
},
|
||||
error: function() {
|
||||
showAlert("error", "Error while adding this custom DNS entry");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function deleteCustomDNS() {
|
||||
var ip = $(this).attr("data-ip");
|
||||
var domain = $(this).attr("data-domain");
|
||||
|
||||
showAlert("info");
|
||||
$.ajax({
|
||||
url: "scripts/pi-hole/php/customdns.php",
|
||||
method: "post",
|
||||
dataType: "json",
|
||||
data: { action: "delete", domain: domain, ip: ip },
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
showAlert("success");
|
||||
table.ajax.reload();
|
||||
} else showAlert("error", response.message);
|
||||
},
|
||||
error: function(jqXHR, exception) {
|
||||
showAlert("error", "Error while deleting this custom DNS entry");
|
||||
console.log(exception);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,81 +1,97 @@
|
||||
/* 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. */
|
||||
* (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. */
|
||||
|
||||
/*global
|
||||
moment
|
||||
*/
|
||||
/* global Chart:false, moment:false */
|
||||
|
||||
var start__ = moment().subtract(6, "days");
|
||||
var from = moment(start__).utc().valueOf()/1000;
|
||||
var from =
|
||||
moment(start__)
|
||||
.utc()
|
||||
.valueOf() / 1000;
|
||||
var end__ = moment();
|
||||
var until = moment(end__).utc().valueOf()/1000;
|
||||
var until =
|
||||
moment(end__)
|
||||
.utc()
|
||||
.valueOf() / 1000;
|
||||
var interval = 0;
|
||||
|
||||
var timeoutWarning = $("#timeoutWarning");
|
||||
|
||||
var dateformat = "MMMM Do YYYY, HH:mm";
|
||||
|
||||
$(function () {
|
||||
$("#querytime").daterangepicker(
|
||||
$(function() {
|
||||
$("#querytime").daterangepicker(
|
||||
{
|
||||
timePicker: true, timePickerIncrement: 15,
|
||||
timePicker: true,
|
||||
timePickerIncrement: 15,
|
||||
locale: { format: dateformat },
|
||||
startDate: start__, endDate: end__,
|
||||
startDate: start__,
|
||||
endDate: end__,
|
||||
ranges: {
|
||||
"Today": [moment().startOf("day"), moment()],
|
||||
"Yesterday": [moment().subtract(1, "days").startOf("day"), moment().subtract(1, "days").endOf("day")],
|
||||
Today: [moment().startOf("day"), moment()],
|
||||
Yesterday: [
|
||||
moment()
|
||||
.subtract(1, "days")
|
||||
.startOf("day"),
|
||||
moment()
|
||||
.subtract(1, "days")
|
||||
.endOf("day")
|
||||
],
|
||||
"Last 7 Days": [moment().subtract(6, "days"), moment()],
|
||||
"Last 30 Days": [moment().subtract(29, "days"), moment()],
|
||||
"This Month": [moment().startOf("month"), moment()],
|
||||
"Last Month": [moment().subtract(1, "month").startOf("month"), moment().subtract(1, "month").endOf("month")],
|
||||
"Last Month": [
|
||||
moment()
|
||||
.subtract(1, "month")
|
||||
.startOf("month"),
|
||||
moment()
|
||||
.subtract(1, "month")
|
||||
.endOf("month")
|
||||
],
|
||||
"This Year": [moment().startOf("year"), moment()],
|
||||
"All Time": [moment(0), moment()]
|
||||
},
|
||||
"opens": "center", "showDropdowns": true,
|
||||
"autoUpdateInput": false
|
||||
opens: "center",
|
||||
showDropdowns: true,
|
||||
autoUpdateInput: false
|
||||
},
|
||||
function (startt, endt) {
|
||||
from = moment(startt).utc().valueOf()/1000;
|
||||
until = moment(endt).utc().valueOf()/1000;
|
||||
});
|
||||
|
||||
|
||||
function(startt, endt) {
|
||||
from =
|
||||
moment(startt)
|
||||
.utc()
|
||||
.valueOf() / 1000;
|
||||
until =
|
||||
moment(endt)
|
||||
.utc()
|
||||
.valueOf() / 1000;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// Credit: http://stackoverflow.com/questions/1787322/htmlspecialchars-equivalent-in-javascript/4835406#4835406
|
||||
function escapeHtml(text) {
|
||||
var map = {
|
||||
"&": "&",
|
||||
"<": "<",
|
||||
">": ">",
|
||||
"\"": """,
|
||||
"\'": "'"
|
||||
};
|
||||
|
||||
return text.replace(/[&<>"']/g, function(m) { return map[m]; });
|
||||
}
|
||||
|
||||
function padNumber(num) {
|
||||
return ("00" + num).substr(-2,2);
|
||||
return ("00" + num).substr(-2, 2);
|
||||
}
|
||||
|
||||
// Helper function needed for converting the Objects to Arrays
|
||||
|
||||
function objectToArray(p){
|
||||
var keys = Object.keys(p);
|
||||
keys.sort(function(a, b) {
|
||||
return a - b;
|
||||
});
|
||||
function objectToArray(p) {
|
||||
var keys = Object.keys(p);
|
||||
keys.sort(function(a, b) {
|
||||
return a - b;
|
||||
});
|
||||
|
||||
var arr = [], idx = [];
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
arr.push(p[keys[i]]);
|
||||
idx.push(keys[i]);
|
||||
}
|
||||
return [idx,arr];
|
||||
var arr = [],
|
||||
idx = [];
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
arr.push(p[keys[i]]);
|
||||
idx.push(keys[i]);
|
||||
}
|
||||
|
||||
return [idx, arr];
|
||||
}
|
||||
|
||||
var timeLineChart;
|
||||
@@ -85,187 +101,271 @@ function compareNumbers(a, b) {
|
||||
}
|
||||
|
||||
function updateQueriesOverTime() {
|
||||
$("#queries-over-time .overlay").show();
|
||||
timeoutWarning.show();
|
||||
$.getJSON("api_db.php?getGraphData&from="+from+"&until="+until, function(data) {
|
||||
$("#queries-over-time .overlay").show();
|
||||
timeoutWarning.show();
|
||||
|
||||
// convert received objects to arrays
|
||||
data.domains_over_time = objectToArray(data.domains_over_time);
|
||||
data.ads_over_time = objectToArray(data.ads_over_time);
|
||||
// Remove possibly already existing data
|
||||
timeLineChart.data.labels = [];
|
||||
timeLineChart.data.datasets[0].data = [];
|
||||
timeLineChart.data.datasets[1].data = [];
|
||||
// Compute interval to obtain about 200 values
|
||||
var num = 200;
|
||||
interval = (until - from) / num;
|
||||
// Default displaying axis scaling
|
||||
timeLineChart.options.scales.xAxes[0].time.unit = "hour";
|
||||
|
||||
var dates = [], hour;
|
||||
if (num * interval >= 6 * 29 * 24 * 60 * 60) {
|
||||
// If the requested data is more than 3 months, set ticks interval to quarterly
|
||||
timeLineChart.options.scales.xAxes[0].time.unit = "quarter";
|
||||
} else if (num * interval >= 3 * 29 * 24 * 60 * 60) {
|
||||
// If the requested data is more than 3 months, set ticks interval to months
|
||||
timeLineChart.options.scales.xAxes[0].time.unit = "month";
|
||||
}
|
||||
|
||||
for (hour in data.domains_over_time[0]) {
|
||||
if ({}.hasOwnProperty.call(data.domains_over_time[0], hour)) {
|
||||
dates.push(parseInt(data.domains_over_time[0][hour]));
|
||||
}
|
||||
if (num * interval >= 29 * 24 * 60 * 60) {
|
||||
// If the requested data is more than 1 month, set ticks interval to weeks
|
||||
timeLineChart.options.scales.xAxes[0].time.unit = "week";
|
||||
} else if (num * interval >= 6 * 24 * 60 * 60) {
|
||||
// If the requested data is more than 1 week, set ticks interval to days
|
||||
timeLineChart.options.scales.xAxes[0].time.unit = "day";
|
||||
}
|
||||
|
||||
$.getJSON(
|
||||
"api_db.php?getGraphData&from=" + from + "&until=" + until + "&interval=" + interval,
|
||||
function(data) {
|
||||
// convert received objects to arrays
|
||||
data.domains_over_time = objectToArray(data.domains_over_time);
|
||||
data.ads_over_time = objectToArray(data.ads_over_time);
|
||||
// Remove possibly already existing data
|
||||
timeLineChart.data.labels = [];
|
||||
timeLineChart.data.datasets[0].data = [];
|
||||
timeLineChart.data.datasets[1].data = [];
|
||||
|
||||
var dates = [],
|
||||
hour;
|
||||
|
||||
for (hour in data.domains_over_time[0]) {
|
||||
if (Object.prototype.hasOwnProperty.call(data.domains_over_time[0], hour)) {
|
||||
dates.push(parseInt(data.domains_over_time[0][hour]));
|
||||
}
|
||||
}
|
||||
|
||||
for (hour in data.ads_over_time[0]) {
|
||||
if ({}.hasOwnProperty.call(data.ads_over_time[0], hour)) {
|
||||
if(!dates.includes(parseInt(data.ads_over_time[0][hour])))
|
||||
{
|
||||
dates.push(parseInt(data.ads_over_time[0][hour]));
|
||||
}
|
||||
}
|
||||
for (hour in data.ads_over_time[0]) {
|
||||
if (Object.prototype.hasOwnProperty.call(data.ads_over_time[0], hour)) {
|
||||
if (dates.indexOf(parseInt(data.ads_over_time[0][hour])) === -1) {
|
||||
dates.push(parseInt(data.ads_over_time[0][hour]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dates.sort(compareNumbers);
|
||||
dates.sort(compareNumbers);
|
||||
|
||||
// Add data for each hour that is available
|
||||
for (hour in dates) {
|
||||
if ({}.hasOwnProperty.call(dates, hour)) {
|
||||
var d, dom = 0, ads = 0;
|
||||
d = new Date(1000*dates[hour]);
|
||||
// Add data for each hour that is available
|
||||
for (hour in dates) {
|
||||
if (Object.prototype.hasOwnProperty.call(dates, hour)) {
|
||||
var date,
|
||||
total = 0,
|
||||
blocked = 0;
|
||||
date = new Date(1000 * dates[hour]);
|
||||
|
||||
var idx = data.domains_over_time[0].indexOf(dates[hour].toString());
|
||||
if (idx > -1)
|
||||
{
|
||||
dom = data.domains_over_time[1][idx];
|
||||
}
|
||||
var idx = data.domains_over_time[0].indexOf(dates[hour].toString());
|
||||
if (idx > -1) {
|
||||
total = data.domains_over_time[1][idx];
|
||||
}
|
||||
|
||||
idx = data.ads_over_time[0].indexOf(dates[hour].toString());
|
||||
if (idx > -1)
|
||||
{
|
||||
ads = data.ads_over_time[1][idx];
|
||||
}
|
||||
idx = data.ads_over_time[0].indexOf(dates[hour].toString());
|
||||
if (idx > -1) {
|
||||
blocked = data.ads_over_time[1][idx];
|
||||
}
|
||||
|
||||
timeLineChart.data.labels.push(d);
|
||||
timeLineChart.data.datasets[0].data.push(dom);
|
||||
timeLineChart.data.datasets[1].data.push(ads);
|
||||
}
|
||||
timeLineChart.data.labels.push(date);
|
||||
timeLineChart.data.datasets[0].data.push(blocked);
|
||||
timeLineChart.data.datasets[1].data.push(total - blocked);
|
||||
}
|
||||
}
|
||||
|
||||
timeLineChart.options.scales.xAxes[0].display=true;
|
||||
$("#queries-over-time .overlay").hide();
|
||||
timeoutWarning.hide();
|
||||
timeLineChart.update();
|
||||
});
|
||||
timeLineChart.options.scales.xAxes[0].display = true;
|
||||
$("#queries-over-time .overlay").hide();
|
||||
timeoutWarning.hide();
|
||||
timeLineChart.update();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/* global Chart */
|
||||
$(document).ready(function() {
|
||||
var ctx = document.getElementById("queryOverTimeChart").getContext("2d");
|
||||
timeLineChart = new Chart(ctx, {
|
||||
type: "line",
|
||||
data: {
|
||||
labels: [ 0 ],
|
||||
datasets: [
|
||||
{
|
||||
label: "Total DNS Queries",
|
||||
fill: true,
|
||||
backgroundColor: "rgba(220,220,220,0.5)",
|
||||
borderColor: "rgba(0, 166, 90,.8)",
|
||||
pointBorderColor: "rgba(0, 166, 90,.8)",
|
||||
pointRadius: 1,
|
||||
pointHoverRadius: 5,
|
||||
data: [],
|
||||
pointHitRadius: 5,
|
||||
cubicInterpolationMode: "monotone"
|
||||
},
|
||||
{
|
||||
label: "Blocked DNS Queries",
|
||||
fill: true,
|
||||
backgroundColor: "rgba(0,192,239,0.5)",
|
||||
borderColor: "rgba(0,192,239,1)",
|
||||
pointBorderColor: "rgba(0,192,239,1)",
|
||||
pointRadius: 1,
|
||||
pointHoverRadius: 5,
|
||||
data: [],
|
||||
pointHitRadius: 5,
|
||||
cubicInterpolationMode: "monotone"
|
||||
}
|
||||
]
|
||||
var ctx = document.getElementById("queryOverTimeChart").getContext("2d");
|
||||
var blockedColor = "#999";
|
||||
var permittedColor = "#00a65a";
|
||||
timeLineChart = new Chart(ctx, {
|
||||
type: "bar",
|
||||
data: {
|
||||
labels: [],
|
||||
datasets: [
|
||||
{
|
||||
label: "Blocked DNS Queries",
|
||||
fill: true,
|
||||
backgroundColor: blockedColor,
|
||||
borderColor: blockedColor,
|
||||
pointBorderColor: blockedColor,
|
||||
pointRadius: 1,
|
||||
pointHoverRadius: 5,
|
||||
data: [],
|
||||
pointHitRadius: 5
|
||||
},
|
||||
options: {
|
||||
tooltips: {
|
||||
enabled: true,
|
||||
responsive: true,
|
||||
mode: "x-axis",
|
||||
callbacks: {
|
||||
title: function(tooltipItem, data) {
|
||||
var label = tooltipItem[0].xLabel;
|
||||
var time = new Date(label);
|
||||
var date = time.getFullYear()+"-"+padNumber(time.getMonth()+1)+"-"+padNumber(time.getDate());
|
||||
var h = time.getHours();
|
||||
var m = time.getMinutes();
|
||||
var from = padNumber(h)+":"+padNumber(m)+":00";
|
||||
var to = padNumber(h)+":"+padNumber(m+9)+":59";
|
||||
return "Queries from "+from+" to "+to+" on "+date;
|
||||
},
|
||||
label: function(tooltipItems, data) {
|
||||
if(tooltipItems.datasetIndex === 1)
|
||||
{
|
||||
var percentage = 0.0;
|
||||
var total = parseInt(data.datasets[0].data[tooltipItems.index]);
|
||||
var blocked = parseInt(data.datasets[1].data[tooltipItems.index]);
|
||||
if(total > 0)
|
||||
{
|
||||
percentage = 100.0*blocked/total;
|
||||
}
|
||||
return data.datasets[tooltipItems.datasetIndex].label + ": " + tooltipItems.yLabel + " (" + percentage.toFixed(1) + "%)";
|
||||
}
|
||||
else
|
||||
{
|
||||
return data.datasets[tooltipItems.datasetIndex].label + ": " + tooltipItems.yLabel;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: "time",
|
||||
display: false,
|
||||
time: {
|
||||
displayFormats: {
|
||||
"minute": "HH:mm",
|
||||
"hour": "HH:mm",
|
||||
"day": "HH:mm",
|
||||
"week": "MMM DD HH:mm",
|
||||
"month": "MMM DD",
|
||||
"quarter": "MMM DD",
|
||||
"year": "MMM DD"
|
||||
}
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
beginAtZero: true
|
||||
}
|
||||
}]
|
||||
},
|
||||
maintainAspectRatio: false
|
||||
{
|
||||
label: "Permitted DNS Queries",
|
||||
fill: true,
|
||||
backgroundColor: permittedColor,
|
||||
borderColor: permittedColor,
|
||||
pointBorderColor: permittedColor,
|
||||
pointRadius: 1,
|
||||
pointHoverRadius: 5,
|
||||
data: [],
|
||||
pointHitRadius: 5
|
||||
}
|
||||
});
|
||||
]
|
||||
},
|
||||
options: {
|
||||
tooltips: {
|
||||
enabled: true,
|
||||
itemSort: function(a, b) {
|
||||
return b.datasetIndex - a.datasetIndex;
|
||||
},
|
||||
mode: "x-axis",
|
||||
callbacks: {
|
||||
title: function(tooltipItem) {
|
||||
var label = tooltipItem[0].xLabel;
|
||||
var time = new Date(label);
|
||||
var from_date =
|
||||
time.getFullYear() +
|
||||
"-" +
|
||||
padNumber(time.getMonth() + 1) +
|
||||
"-" +
|
||||
padNumber(time.getDate());
|
||||
var from_time =
|
||||
padNumber(time.getHours()) +
|
||||
":" +
|
||||
padNumber(time.getMinutes()) +
|
||||
":" +
|
||||
padNumber(time.getSeconds());
|
||||
time = new Date(time.valueOf() + 1000 * interval);
|
||||
var until_date =
|
||||
time.getFullYear() +
|
||||
"-" +
|
||||
padNumber(time.getMonth() + 1) +
|
||||
"-" +
|
||||
padNumber(time.getDate());
|
||||
var until_time =
|
||||
padNumber(time.getHours()) +
|
||||
":" +
|
||||
padNumber(time.getMinutes()) +
|
||||
":" +
|
||||
padNumber(time.getSeconds());
|
||||
|
||||
if (from_date === until_date) {
|
||||
// Abbreviated form for intervals on the same day
|
||||
// We split title in two lines on small screens
|
||||
if ($(window).width() < 992) {
|
||||
until_time += "\n";
|
||||
}
|
||||
|
||||
return ("Queries from " + from_time + " to " + until_time + " on " + from_date).split(
|
||||
"\n "
|
||||
);
|
||||
}
|
||||
|
||||
// Full tooltip for intervals spanning more than one day
|
||||
// We split title in two lines on small screens
|
||||
if ($(window).width() < 992) {
|
||||
from_date += "\n";
|
||||
}
|
||||
|
||||
return (
|
||||
"Queries from " +
|
||||
from_date +
|
||||
" " +
|
||||
from_time +
|
||||
" to " +
|
||||
until_date +
|
||||
" " +
|
||||
until_time
|
||||
).split("\n ");
|
||||
},
|
||||
label: function(tooltipItems, data) {
|
||||
if (tooltipItems.datasetIndex === 0) {
|
||||
var percentage = 0.0;
|
||||
var permitted = parseInt(data.datasets[1].data[tooltipItems.index]);
|
||||
var blocked = parseInt(data.datasets[0].data[tooltipItems.index]);
|
||||
if (permitted + blocked > 0) {
|
||||
percentage = (100.0 * blocked) / (permitted + blocked);
|
||||
}
|
||||
|
||||
return (
|
||||
data.datasets[tooltipItems.datasetIndex].label +
|
||||
": " +
|
||||
tooltipItems.yLabel +
|
||||
" (" +
|
||||
percentage.toFixed(1) +
|
||||
"%)"
|
||||
);
|
||||
}
|
||||
|
||||
return data.datasets[tooltipItems.datasetIndex].label + ": " + tooltipItems.yLabel;
|
||||
}
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
scales: {
|
||||
xAxes: [
|
||||
{
|
||||
type: "time",
|
||||
stacked: true,
|
||||
time: {
|
||||
unit: "hour",
|
||||
displayFormats: {
|
||||
minute: "HH:mm",
|
||||
hour: "HH:mm",
|
||||
day: "MMM DD",
|
||||
week: "MMM DD",
|
||||
month: "MMM",
|
||||
quarter: "MMM",
|
||||
year: "YYYY MMM"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
yAxes: [
|
||||
{
|
||||
stacked: true,
|
||||
ticks: {
|
||||
beginAtZero: true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
maintainAspectRatio: false
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$("#querytime").on("apply.daterangepicker", function(ev, picker) {
|
||||
$(this).val(picker.startDate.format(dateformat) + " to " + picker.endDate.format(dateformat));
|
||||
$("#queries-over-time").show();
|
||||
updateQueriesOverTime();
|
||||
$(this).val(picker.startDate.format(dateformat) + " to " + picker.endDate.format(dateformat));
|
||||
$("#queries-over-time").show();
|
||||
updateQueriesOverTime();
|
||||
});
|
||||
|
||||
$("#queryOverTimeChart").click(function(evt){
|
||||
var activePoints = timeLineChart.getElementAtEvent(evt);
|
||||
if(activePoints.length > 0)
|
||||
{
|
||||
//get the internal index in the chart
|
||||
var clickedElementindex = activePoints[0]["_index"];
|
||||
$("#queryOverTimeChart").click(function(evt) {
|
||||
var activePoints = timeLineChart.getElementAtEvent(evt);
|
||||
if (activePoints.length > 0) {
|
||||
//get the internal index in the chart
|
||||
var clickedElementindex = activePoints[0]._index;
|
||||
|
||||
//get specific label by index
|
||||
var label = timeLineChart.data.labels[clickedElementindex];
|
||||
//get specific label by index
|
||||
var label = timeLineChart.data.labels[clickedElementindex];
|
||||
|
||||
//get value by index
|
||||
var from = label/1000;
|
||||
var until = label/1000 + 600;
|
||||
window.location.href = "db_queries.php?from="+from+"&until="+until;
|
||||
}
|
||||
return false;
|
||||
//get value by index
|
||||
var from = label / 1000;
|
||||
var until = label / 1000 + interval;
|
||||
window.location.href = "db_queries.php?from=" + from + "&until=" + until;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
@@ -1,47 +1,75 @@
|
||||
/* 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. */
|
||||
* (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. */
|
||||
|
||||
/*global
|
||||
moment
|
||||
*/
|
||||
/* global moment:false */
|
||||
|
||||
var start__ = moment().subtract(6, "days");
|
||||
var from = moment(start__).utc().valueOf()/1000;
|
||||
var from =
|
||||
moment(start__)
|
||||
.utc()
|
||||
.valueOf() / 1000;
|
||||
var end__ = moment();
|
||||
var until = moment(end__).utc().valueOf()/1000;
|
||||
var until =
|
||||
moment(end__)
|
||||
.utc()
|
||||
.valueOf() / 1000;
|
||||
|
||||
var timeoutWarning = $("#timeoutWarning");
|
||||
var listsStillLoading = 0;
|
||||
|
||||
var dateformat = "MMMM Do YYYY, HH:mm";
|
||||
|
||||
$(function () {
|
||||
$("#querytime").daterangepicker(
|
||||
$(function() {
|
||||
$("#querytime").daterangepicker(
|
||||
{
|
||||
timePicker: true, timePickerIncrement: 15,
|
||||
locale: { format: "MMMM Do YYYY, HH:mm" },
|
||||
startDate: start__, endDate: end__,
|
||||
timePicker: true,
|
||||
timePickerIncrement: 15,
|
||||
locale: { format: dateformat },
|
||||
startDate: start__,
|
||||
endDate: end__,
|
||||
ranges: {
|
||||
"Today": [moment().startOf("day"), moment()],
|
||||
"Yesterday": [moment().subtract(1, "days").startOf("day"), moment().subtract(1, "days").endOf("day")],
|
||||
Today: [moment().startOf("day"), moment()],
|
||||
Yesterday: [
|
||||
moment()
|
||||
.subtract(1, "days")
|
||||
.startOf("day"),
|
||||
moment()
|
||||
.subtract(1, "days")
|
||||
.endOf("day")
|
||||
],
|
||||
"Last 7 Days": [moment().subtract(6, "days"), moment()],
|
||||
"Last 30 Days": [moment().subtract(29, "days"), moment()],
|
||||
"This Month": [moment().startOf("month"), moment()],
|
||||
"Last Month": [moment().subtract(1, "month").startOf("month"), moment().subtract(1, "month").endOf("month")],
|
||||
"Last Month": [
|
||||
moment()
|
||||
.subtract(1, "month")
|
||||
.startOf("month"),
|
||||
moment()
|
||||
.subtract(1, "month")
|
||||
.endOf("month")
|
||||
],
|
||||
"This Year": [moment().startOf("year"), moment()],
|
||||
"All Time": [moment(0), moment()]
|
||||
},
|
||||
"opens": "center", "showDropdowns": true,
|
||||
"autoUpdateInput": false
|
||||
opens: "center",
|
||||
showDropdowns: true,
|
||||
autoUpdateInput: false
|
||||
},
|
||||
function (startt, endt) {
|
||||
from = moment(startt).utc().valueOf()/1000;
|
||||
until = moment(endt).utc().valueOf()/1000;
|
||||
});
|
||||
function(startt, endt) {
|
||||
from =
|
||||
moment(startt)
|
||||
.utc()
|
||||
.valueOf() / 1000;
|
||||
until =
|
||||
moment(endt)
|
||||
.utc()
|
||||
.valueOf() / 1000;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// Credit: http://stackoverflow.com/questions/1787322/htmlspecialchars-equivalent-in-javascript/4835406#4835406
|
||||
@@ -50,154 +78,174 @@ function escapeHtml(text) {
|
||||
"&": "&",
|
||||
"<": "<",
|
||||
">": ">",
|
||||
"\"": """,
|
||||
"\'": "'"
|
||||
'"': """,
|
||||
"'": "'"
|
||||
};
|
||||
|
||||
return text.replace(/[&<>"']/g, function(m) { return map[m]; });
|
||||
return text.replace(/[&<>"']/g, function(m) {
|
||||
return map[m];
|
||||
});
|
||||
}
|
||||
|
||||
function updateTopClientsChart() {
|
||||
$("#client-frequency .overlay").show();
|
||||
$.getJSON("api_db.php?topClients&from="+from+"&until="+until, function(data) {
|
||||
$("#client-frequency .overlay").show();
|
||||
$.getJSON("api_db.php?topClients&from=" + from + "&until=" + until, function(data) {
|
||||
// Clear tables before filling them with data
|
||||
$("#client-frequency td")
|
||||
.parent()
|
||||
.remove();
|
||||
var clienttable = $("#client-frequency").find("tbody:last");
|
||||
var client, percentage, clientname;
|
||||
var sum = 0;
|
||||
for (client in data.top_sources) {
|
||||
if (Object.prototype.hasOwnProperty.call(data.top_sources, client)) {
|
||||
sum += data.top_sources[client];
|
||||
}
|
||||
}
|
||||
|
||||
// Clear tables before filling them with data
|
||||
$("#client-frequency td").parent().remove();
|
||||
var clienttable = $("#client-frequency").find("tbody:last");
|
||||
var client, percentage, clientname, clientip;
|
||||
var sum = 0;
|
||||
for (client in data.top_sources) {
|
||||
if ({}.hasOwnProperty.call(data.top_sources, client)){
|
||||
sum += data.top_sources[client];
|
||||
}
|
||||
for (client in data.top_sources) {
|
||||
if (Object.prototype.hasOwnProperty.call(data.top_sources, client)) {
|
||||
// Sanitize client
|
||||
client = escapeHtml(client);
|
||||
if (escapeHtml(client) !== client) {
|
||||
// Make a copy with the escaped index if necessary
|
||||
data.top_sources[escapeHtml(client)] = data.top_sources[client];
|
||||
}
|
||||
|
||||
for (client in data.top_sources) {
|
||||
|
||||
if ({}.hasOwnProperty.call(data.top_sources, client)){
|
||||
// Sanitize client
|
||||
client = escapeHtml(client);
|
||||
if(escapeHtml(client) !== client)
|
||||
{
|
||||
// Make a copy with the escaped index if necessary
|
||||
data.top_sources[escapeHtml(client)] = data.top_sources[client];
|
||||
}
|
||||
if(client.indexOf("|") > -1)
|
||||
{
|
||||
var idx = client.indexOf("|");
|
||||
clientname = client.substr(0, idx);
|
||||
clientip = client.substr(idx+1, client.length-idx);
|
||||
}
|
||||
else
|
||||
{
|
||||
clientname = client;
|
||||
clientip = client;
|
||||
}
|
||||
|
||||
var url = clientname;
|
||||
percentage = data.top_sources[client] / sum * 100.0;
|
||||
clienttable.append("<tr> <td>" + url +
|
||||
"</td> <td>" + data.top_sources[client] + "</td> <td> <div class=\"progress progress-sm\" title=\""+percentage.toFixed(1)+"% of " + sum + "\"> <div class=\"progress-bar progress-bar-blue\" style=\"width: " +
|
||||
percentage + "%\"></div> </div> </td> </tr> ");
|
||||
}
|
||||
|
||||
if (client.indexOf("|") > -1) {
|
||||
var idx = client.indexOf("|");
|
||||
clientname = client.substr(0, idx);
|
||||
} else {
|
||||
clientname = client;
|
||||
}
|
||||
|
||||
$("#client-frequency .overlay").hide();
|
||||
percentage = (data.top_sources[client] / sum) * 100.0;
|
||||
clienttable.append(
|
||||
"<tr> <td>" +
|
||||
clientname +
|
||||
"</td> <td>" +
|
||||
data.top_sources[client] +
|
||||
'</td> <td> <div class="progress progress-sm" title="' +
|
||||
percentage.toFixed(1) +
|
||||
"% of " +
|
||||
sum +
|
||||
'"> <div class="progress-bar progress-bar-blue" style="width: ' +
|
||||
percentage +
|
||||
'%"></div> </div> </td> </tr> '
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
listsStillLoading--;
|
||||
if(listsStillLoading === 0)
|
||||
timeoutWarning.hide();
|
||||
});
|
||||
$("#client-frequency .overlay").hide();
|
||||
|
||||
listsStillLoading--;
|
||||
if (listsStillLoading === 0) timeoutWarning.hide();
|
||||
});
|
||||
}
|
||||
|
||||
function updateTopDomainsChart() {
|
||||
$("#domain-frequency .overlay").show();
|
||||
$.getJSON("api_db.php?topDomains&from="+from+"&until="+until, function(data) {
|
||||
$("#domain-frequency .overlay").show();
|
||||
$.getJSON("api_db.php?topDomains&from=" + from + "&until=" + until, function(data) {
|
||||
// Clear tables before filling them with data
|
||||
$("#domain-frequency td")
|
||||
.parent()
|
||||
.remove();
|
||||
var domaintable = $("#domain-frequency").find("tbody:last");
|
||||
var domain, percentage;
|
||||
var sum = 0;
|
||||
for (domain in data.top_domains) {
|
||||
if (Object.prototype.hasOwnProperty.call(data.top_domains, domain)) {
|
||||
sum += data.top_domains[domain];
|
||||
}
|
||||
}
|
||||
|
||||
// Clear tables before filling them with data
|
||||
$("#domain-frequency td").parent().remove();
|
||||
var domaintable = $("#domain-frequency").find("tbody:last");
|
||||
var domain, percentage;
|
||||
var sum = 0;
|
||||
for (domain in data.top_domains) {
|
||||
if ({}.hasOwnProperty.call(data.top_domains, domain)){
|
||||
sum += data.top_domains[domain];
|
||||
}
|
||||
for (domain in data.top_domains) {
|
||||
if (Object.prototype.hasOwnProperty.call(data.top_domains, domain)) {
|
||||
// Sanitize domain
|
||||
domain = escapeHtml(domain);
|
||||
if (escapeHtml(domain) !== domain) {
|
||||
// Make a copy with the escaped index if necessary
|
||||
data.top_domains[escapeHtml(domain)] = data.top_domains[domain];
|
||||
}
|
||||
|
||||
for (domain in data.top_domains) {
|
||||
percentage = (data.top_domains[domain] / sum) * 100.0;
|
||||
domaintable.append(
|
||||
"<tr> <td>" +
|
||||
domain +
|
||||
"</td> <td>" +
|
||||
data.top_domains[domain] +
|
||||
'</td> <td> <div class="progress progress-sm" title="' +
|
||||
percentage.toFixed(1) +
|
||||
"% of " +
|
||||
sum +
|
||||
'"> <div class="progress-bar progress-bar-blue" style="width: ' +
|
||||
percentage +
|
||||
'%"></div> </div> </td> </tr> '
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ({}.hasOwnProperty.call(data.top_domains, domain)){
|
||||
// Sanitize domain
|
||||
domain = escapeHtml(domain);
|
||||
if(escapeHtml(domain) !== domain)
|
||||
{
|
||||
// Make a copy with the escaped index if necessary
|
||||
data.top_domains[escapeHtml(domain)] = data.top_domains[domain];
|
||||
}
|
||||
$("#domain-frequency .overlay").hide();
|
||||
|
||||
percentage = data.top_domains[domain] / sum * 100.0;
|
||||
domaintable.append("<tr> <td>" + domain +
|
||||
"</td> <td>" + data.top_domains[domain] + "</td> <td> <div class=\"progress progress-sm\" title=\""+percentage.toFixed(1)+"% of " + sum + "\"> <div class=\"progress-bar progress-bar-blue\" style=\"width: " +
|
||||
percentage + "%\"></div> </div> </td> </tr> ");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$("#domain-frequency .overlay").hide();
|
||||
|
||||
listsStillLoading--;
|
||||
if(listsStillLoading === 0)
|
||||
timeoutWarning.hide();
|
||||
});
|
||||
listsStillLoading--;
|
||||
if (listsStillLoading === 0) timeoutWarning.hide();
|
||||
});
|
||||
}
|
||||
|
||||
function updateTopAdsChart() {
|
||||
$("#ad-frequency .overlay").show();
|
||||
$.getJSON("api_db.php?topAds&from="+from+"&until="+until, function(data) {
|
||||
$("#ad-frequency .overlay").show();
|
||||
$.getJSON("api_db.php?topAds&from=" + from + "&until=" + until, function(data) {
|
||||
// Clear tables before filling them with data
|
||||
$("#ad-frequency td")
|
||||
.parent()
|
||||
.remove();
|
||||
var adtable = $("#ad-frequency").find("tbody:last");
|
||||
var ad, percentage;
|
||||
var sum = 0;
|
||||
for (ad in data.top_ads) {
|
||||
if (Object.prototype.hasOwnProperty.call(data.top_ads, ad)) {
|
||||
sum += data.top_ads[ad];
|
||||
}
|
||||
}
|
||||
|
||||
// Clear tables before filling them with data
|
||||
$("#ad-frequency td").parent().remove();
|
||||
var adtable = $("#ad-frequency").find("tbody:last");
|
||||
var ad, percentage;
|
||||
var sum = 0;
|
||||
for (ad in data.top_ads) {
|
||||
if ({}.hasOwnProperty.call(data.top_ads, ad)){
|
||||
sum += data.top_ads[ad];
|
||||
}
|
||||
for (ad in data.top_ads) {
|
||||
if (Object.prototype.hasOwnProperty.call(data.top_ads, ad)) {
|
||||
// Sanitize ad
|
||||
ad = escapeHtml(ad);
|
||||
if (escapeHtml(ad) !== ad) {
|
||||
// Make a copy with the escaped index if necessary
|
||||
data.top_ads[escapeHtml(ad)] = data.top_ads[ad];
|
||||
}
|
||||
|
||||
for (ad in data.top_ads) {
|
||||
percentage = (data.top_ads[ad] / sum) * 100.0;
|
||||
adtable.append(
|
||||
"<tr> <td>" +
|
||||
ad +
|
||||
"</td> <td>" +
|
||||
data.top_ads[ad] +
|
||||
'</td> <td> <div class="progress progress-sm" title="' +
|
||||
percentage.toFixed(1) +
|
||||
"% of " +
|
||||
sum +
|
||||
'"> <div class="progress-bar progress-bar-blue" style="width: ' +
|
||||
percentage +
|
||||
'%"></div> </div> </td> </tr> '
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ({}.hasOwnProperty.call(data.top_ads, ad)){
|
||||
// Sanitize ad
|
||||
ad = escapeHtml(ad);
|
||||
if(escapeHtml(ad) !== ad)
|
||||
{
|
||||
// Make a copy with the escaped index if necessary
|
||||
data.top_ads[escapeHtml(ad)] = data.top_ads[ad];
|
||||
}
|
||||
$("#ad-frequency .overlay").hide();
|
||||
|
||||
percentage = data.top_ads[ad] / sum * 100.0;
|
||||
adtable.append("<tr> <td>" + ad + "</td> <td>" + data.top_ads[ad] + "</td> <td> <div class=\"progress progress-sm\" title=\""+percentage.toFixed(1)+"% of " + sum + "\"> <div class=\"progress-bar progress-bar-blue\" style=\"width: " + percentage + "%\"></div> </div> </td> </tr> ");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$("#ad-frequency .overlay").hide();
|
||||
|
||||
listsStillLoading--;
|
||||
if(listsStillLoading === 0)
|
||||
timeoutWarning.hide();
|
||||
});
|
||||
listsStillLoading--;
|
||||
if (listsStillLoading === 0) timeoutWarning.hide();
|
||||
});
|
||||
}
|
||||
|
||||
$("#querytime").on("apply.daterangepicker", function(ev, picker) {
|
||||
$(this).val(picker.startDate.format(dateformat) + " to " + picker.endDate.format(dateformat));
|
||||
timeoutWarning.show();
|
||||
listsStillLoading = 3;
|
||||
updateTopClientsChart();
|
||||
updateTopDomainsChart();
|
||||
updateTopAdsChart();
|
||||
$(this).val(picker.startDate.format(dateformat) + " to " + picker.endDate.format(dateformat));
|
||||
timeoutWarning.show();
|
||||
listsStillLoading = 3;
|
||||
updateTopClientsChart();
|
||||
updateTopDomainsChart();
|
||||
updateTopAdsChart();
|
||||
});
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
/* 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. */
|
||||
* (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. */
|
||||
|
||||
/*global
|
||||
moment
|
||||
*/
|
||||
/* global moment:false */
|
||||
|
||||
var start__ = moment().subtract(6, "days");
|
||||
var from = moment(start__).utc().valueOf()/1000;
|
||||
var from =
|
||||
moment(start__)
|
||||
.utc()
|
||||
.valueOf() / 1000;
|
||||
var end__ = moment();
|
||||
var until = moment(end__).utc().valueOf()/1000;
|
||||
var until =
|
||||
moment(end__)
|
||||
.utc()
|
||||
.valueOf() / 1000;
|
||||
var instantquery = false;
|
||||
var daterange;
|
||||
|
||||
@@ -22,343 +26,402 @@ var dateformat = "MMMM Do YYYY, HH:mm";
|
||||
|
||||
// Do we want to filter queries?
|
||||
var GETDict = {};
|
||||
location.search.substr(1).split("&").forEach(function(item) {GETDict[item.split("=")[0]] = item.split("=")[1];});
|
||||
window.location.search
|
||||
.substr(1)
|
||||
.split("&")
|
||||
.forEach(function(item) {
|
||||
GETDict[item.split("=")[0]] = item.split("=")[1];
|
||||
});
|
||||
|
||||
if("from" in GETDict && "until" in GETDict)
|
||||
{
|
||||
from = parseInt(GETDict["from"]);
|
||||
until = parseInt(GETDict["until"]);
|
||||
start__ = moment(1000*from);
|
||||
end__ = moment(1000*until);
|
||||
instantquery = true;
|
||||
if ("from" in GETDict && "until" in GETDict) {
|
||||
from = parseInt(GETDict.from);
|
||||
until = parseInt(GETDict.until);
|
||||
start__ = moment(1000 * from);
|
||||
end__ = moment(1000 * until);
|
||||
instantquery = true;
|
||||
}
|
||||
|
||||
$(function () {
|
||||
daterange = $("#querytime").daterangepicker(
|
||||
$(function() {
|
||||
daterange = $("#querytime").daterangepicker(
|
||||
{
|
||||
timePicker: true, timePickerIncrement: 15,
|
||||
locale: { format: "MMMM Do YYYY, HH:mm" },
|
||||
startDate: start__, endDate: end__,
|
||||
timePicker: true,
|
||||
timePickerIncrement: 15,
|
||||
locale: { format: dateformat },
|
||||
startDate: start__,
|
||||
endDate: end__,
|
||||
ranges: {
|
||||
"Today": [moment().startOf("day"), moment()],
|
||||
"Yesterday": [moment().subtract(1, "days").startOf("day"), moment().subtract(1, "days").endOf("day")],
|
||||
Today: [moment().startOf("day"), moment()],
|
||||
Yesterday: [
|
||||
moment()
|
||||
.subtract(1, "days")
|
||||
.startOf("day"),
|
||||
moment()
|
||||
.subtract(1, "days")
|
||||
.endOf("day")
|
||||
],
|
||||
"Last 7 Days": [moment().subtract(6, "days"), moment()],
|
||||
"Last 30 Days": [moment().subtract(29, "days"), moment()],
|
||||
"This Month": [moment().startOf("month"), moment()],
|
||||
"Last Month": [moment().subtract(1, "month").startOf("month"), moment().subtract(1, "month").endOf("month")],
|
||||
"Last Month": [
|
||||
moment()
|
||||
.subtract(1, "month")
|
||||
.startOf("month"),
|
||||
moment()
|
||||
.subtract(1, "month")
|
||||
.endOf("month")
|
||||
],
|
||||
"This Year": [moment().startOf("year"), moment()],
|
||||
"All Time": [moment(0), moment()]
|
||||
},
|
||||
"opens": "center", "showDropdowns": true,
|
||||
"autoUpdateInput": false
|
||||
opens: "center",
|
||||
showDropdowns: true,
|
||||
autoUpdateInput: false
|
||||
},
|
||||
function (startt, endt) {
|
||||
from = moment(startt).utc().valueOf()/1000;
|
||||
until = moment(endt).utc().valueOf()/1000;
|
||||
});
|
||||
function(startt, endt) {
|
||||
from =
|
||||
moment(startt)
|
||||
.utc()
|
||||
.valueOf() / 1000;
|
||||
until =
|
||||
moment(endt)
|
||||
.utc()
|
||||
.valueOf() / 1000;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
var tableApi, statistics;
|
||||
|
||||
function escapeRegex(text) {
|
||||
var map = {
|
||||
"(": "\\(",
|
||||
")": "\\)",
|
||||
".": "\\.",
|
||||
};
|
||||
return text.replace(/[().]/g, function(m) { return map[m]; });
|
||||
function add(domain, list) {
|
||||
var token = $("#token").text();
|
||||
var alInfo = $("#alInfo");
|
||||
var alList = $("#alList");
|
||||
var alDomain = $("#alDomain");
|
||||
alDomain.html(domain);
|
||||
var alSuccess = $("#alSuccess");
|
||||
var alFailure = $("#alFailure");
|
||||
var err = $("#err");
|
||||
|
||||
if (list === "white") {
|
||||
alList.html("Whitelist");
|
||||
} else {
|
||||
alList.html("Blacklist");
|
||||
}
|
||||
|
||||
alInfo.show();
|
||||
alSuccess.hide();
|
||||
alFailure.hide();
|
||||
$.ajax({
|
||||
url: "scripts/pi-hole/php/add.php",
|
||||
method: "post",
|
||||
data: { domain: domain, list: list, token: token },
|
||||
success: function(response) {
|
||||
if (
|
||||
response.indexOf("not a valid argument") >= 0 ||
|
||||
response.indexOf("is not a valid domain") >= 0
|
||||
) {
|
||||
alFailure.show();
|
||||
err.html(response);
|
||||
alFailure.delay(4000).fadeOut(2000, function() {
|
||||
alFailure.hide();
|
||||
});
|
||||
} else {
|
||||
alSuccess.show();
|
||||
alSuccess.delay(1000).fadeOut(2000, function() {
|
||||
alSuccess.hide();
|
||||
});
|
||||
}
|
||||
|
||||
alInfo.delay(1000).fadeOut(2000, function() {
|
||||
alInfo.hide();
|
||||
alList.html("");
|
||||
alDomain.html("");
|
||||
});
|
||||
},
|
||||
error: function() {
|
||||
alFailure.show();
|
||||
err.html("");
|
||||
alFailure.delay(1000).fadeOut(2000, function() {
|
||||
alFailure.hide();
|
||||
});
|
||||
alInfo.delay(1000).fadeOut(2000, function() {
|
||||
alInfo.hide();
|
||||
alList.html("");
|
||||
alDomain.html("");
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function add(domain,list) {
|
||||
var token = $("#token").html();
|
||||
var alInfo = $("#alInfo");
|
||||
var alList = $("#alList");
|
||||
var alDomain = $("#alDomain");
|
||||
alDomain.html(domain);
|
||||
var alSuccess = $("#alSuccess");
|
||||
var alFailure = $("#alFailure");
|
||||
var err = $("#err");
|
||||
function handleAjaxError(xhr, textStatus) {
|
||||
if (textStatus === "timeout") {
|
||||
alert("The server took too long to send the data.");
|
||||
} else if (xhr.responseText.indexOf("Connection refused") >= 0) {
|
||||
alert("An error occurred while loading the data: Connection refused. Is FTL running?");
|
||||
} else {
|
||||
alert("An unknown error occurred while loading the data.\n" + xhr.responseText);
|
||||
}
|
||||
|
||||
if(list === "white")
|
||||
{
|
||||
alList.html("Whitelist");
|
||||
}
|
||||
else
|
||||
{
|
||||
alList.html("Blacklist");
|
||||
}
|
||||
|
||||
alInfo.show();
|
||||
alSuccess.hide();
|
||||
alFailure.hide();
|
||||
$.ajax({
|
||||
url: "scripts/pi-hole/php/add.php",
|
||||
method: "post",
|
||||
data: {"domain":domain, "list":list, "token":token},
|
||||
success: function(response) {
|
||||
if (response.indexOf("not a valid argument") >= 0 || response.indexOf("is not a valid domain") >= 0)
|
||||
{
|
||||
alFailure.show();
|
||||
err.html(response);
|
||||
alFailure.delay(4000).fadeOut(2000, function() { alFailure.hide(); });
|
||||
}
|
||||
else
|
||||
{
|
||||
alSuccess.show();
|
||||
alSuccess.delay(1000).fadeOut(2000, function() { alSuccess.hide(); });
|
||||
}
|
||||
alInfo.delay(1000).fadeOut(2000, function() {
|
||||
alInfo.hide();
|
||||
alList.html("");
|
||||
alDomain.html("");
|
||||
});
|
||||
},
|
||||
error: function(jqXHR, exception) {
|
||||
alFailure.show();
|
||||
err.html("");
|
||||
alFailure.delay(1000).fadeOut(2000, function() {
|
||||
alFailure.hide();
|
||||
});
|
||||
alInfo.delay(1000).fadeOut(2000, function() {
|
||||
alInfo.hide();
|
||||
alList.html("");
|
||||
alDomain.html("");
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
function handleAjaxError( xhr, textStatus, error ) {
|
||||
if ( textStatus === "timeout" )
|
||||
{
|
||||
alert( "The server took too long to send the data." );
|
||||
}
|
||||
else if(xhr.responseText.indexOf("Connection refused") >= 0)
|
||||
{
|
||||
alert( "An error occurred while loading the data: Connection refused. Is FTL running?" );
|
||||
}
|
||||
else
|
||||
{
|
||||
alert( "An unknown error occurred while loading the data.\n"+xhr.responseText );
|
||||
}
|
||||
$("#all-queries_processing").hide();
|
||||
tableApi.clear();
|
||||
tableApi.draw();
|
||||
$("#all-queries_processing").hide();
|
||||
tableApi.clear();
|
||||
tableApi.draw();
|
||||
}
|
||||
|
||||
function getQueryTypes()
|
||||
{
|
||||
var queryType = [];
|
||||
if($("#type_gravity").prop("checked"))
|
||||
{
|
||||
queryType.push(1);
|
||||
}
|
||||
if($("#type_forwarded").prop("checked"))
|
||||
{
|
||||
queryType.push(2);
|
||||
}
|
||||
if($("#type_cached").prop("checked"))
|
||||
{
|
||||
queryType.push(3);
|
||||
}
|
||||
if($("#type_regex").prop("checked"))
|
||||
{
|
||||
queryType.push(4);
|
||||
}
|
||||
if($("#type_blacklist").prop("checked"))
|
||||
{
|
||||
queryType.push(5);
|
||||
}
|
||||
if($("#type_external").prop("checked"))
|
||||
{
|
||||
// Multiple IDs correspond to this status
|
||||
// We request queries with all of them
|
||||
queryType.push([6,7,8]);
|
||||
}
|
||||
return queryType.join(",");
|
||||
function getQueryTypes() {
|
||||
var queryType = [];
|
||||
if ($("#type_gravity").prop("checked")) {
|
||||
queryType.push(1);
|
||||
}
|
||||
|
||||
if ($("#type_forwarded").prop("checked")) {
|
||||
queryType.push(2);
|
||||
}
|
||||
|
||||
if ($("#type_cached").prop("checked")) {
|
||||
queryType.push(3);
|
||||
}
|
||||
|
||||
if ($("#type_regex").prop("checked")) {
|
||||
queryType.push(4);
|
||||
}
|
||||
|
||||
if ($("#type_blacklist").prop("checked")) {
|
||||
queryType.push(5);
|
||||
}
|
||||
|
||||
if ($("#type_external").prop("checked")) {
|
||||
// Multiple IDs correspond to this status
|
||||
// We request queries with all of them
|
||||
queryType.push([6, 7, 8]);
|
||||
}
|
||||
|
||||
if ($("#type_gravity_CNAME").prop("checked")) {
|
||||
queryType.push(9);
|
||||
}
|
||||
|
||||
if ($("#type_regex_CNAME").prop("checked")) {
|
||||
queryType.push(10);
|
||||
}
|
||||
|
||||
if ($("#type_blacklist_CNAME").prop("checked")) {
|
||||
queryType.push(11);
|
||||
}
|
||||
|
||||
return queryType.join(",");
|
||||
}
|
||||
|
||||
var reloadCallback = function()
|
||||
{
|
||||
timeoutWarning.hide();
|
||||
statistics = [0,0,0,0];
|
||||
var data = tableApi.rows().data();
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
statistics[0]++;
|
||||
if(data[i][4] === 1)
|
||||
{
|
||||
statistics[2]++;
|
||||
}
|
||||
else if(data[i][4] === 3)
|
||||
{
|
||||
statistics[1]++;
|
||||
}
|
||||
else if(data[i][4] === 4)
|
||||
{
|
||||
statistics[3]++;
|
||||
}
|
||||
var reloadCallback = function() {
|
||||
timeoutWarning.hide();
|
||||
statistics = [0, 0, 0, 0];
|
||||
var data = tableApi.rows().data();
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
statistics[0]++;
|
||||
if (data[i][4] === 1) {
|
||||
statistics[2]++;
|
||||
} else if (data[i][4] === 3) {
|
||||
statistics[1]++;
|
||||
} else if (data[i][4] === 4) {
|
||||
statistics[3]++;
|
||||
}
|
||||
$("h3#dns_queries").text(statistics[0].toLocaleString());
|
||||
$("h3#ads_blocked_exact").text(statistics[2].toLocaleString());
|
||||
$("h3#ads_wildcard_blocked").text(statistics[3].toLocaleString());
|
||||
}
|
||||
|
||||
var percent = 0.0;
|
||||
if(statistics[2] + statistics[3] > 0)
|
||||
{
|
||||
percent = 100.0*(statistics[2] + statistics[3]) / statistics[0];
|
||||
}
|
||||
$("h3#ads_percentage_today").text(parseFloat(percent).toFixed(1).toLocaleString()+" %");
|
||||
$("h3#dns_queries").text(statistics[0].toLocaleString());
|
||||
$("h3#ads_blocked_exact").text(statistics[2].toLocaleString());
|
||||
$("h3#ads_wildcard_blocked").text(statistics[3].toLocaleString());
|
||||
|
||||
var percent = 0.0;
|
||||
if (statistics[2] + statistics[3] > 0) {
|
||||
percent = (100.0 * (statistics[2] + statistics[3])) / statistics[0];
|
||||
}
|
||||
|
||||
$("h3#ads_percentage_today").text(
|
||||
parseFloat(percent)
|
||||
.toFixed(1)
|
||||
.toLocaleString() + " %"
|
||||
);
|
||||
};
|
||||
|
||||
function refreshTableData() {
|
||||
timeoutWarning.show();
|
||||
var APIstring = "api_db.php?getAllQueries&from="+from+"&until="+until;
|
||||
// Check if query type filtering is enabled
|
||||
var queryType = getQueryTypes();
|
||||
if(queryType !== "1,2,3,4,5,6")
|
||||
{
|
||||
APIstring += "&types="+queryType;
|
||||
}
|
||||
statistics = [0,0,0];
|
||||
tableApi.ajax.url(APIstring).load(reloadCallback);
|
||||
timeoutWarning.show();
|
||||
var APIstring = "api_db.php?getAllQueries&from=" + from + "&until=" + until;
|
||||
// Check if query type filtering is enabled
|
||||
var queryType = getQueryTypes();
|
||||
if (queryType !== "1,2,3,4,5,6") {
|
||||
APIstring += "&types=" + queryType;
|
||||
}
|
||||
|
||||
statistics = [0, 0, 0];
|
||||
tableApi.ajax.url(APIstring).load(reloadCallback);
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
var status;
|
||||
var APIstring;
|
||||
|
||||
var APIstring;
|
||||
if(instantquery)
|
||||
{
|
||||
APIstring = "api_db.php?getAllQueries&from="+from+"&until="+until;
|
||||
}
|
||||
else
|
||||
{
|
||||
APIstring = "api_db.php?getAllQueries=empty";
|
||||
}
|
||||
// Check if query type filtering is enabled
|
||||
var queryType = getQueryTypes();
|
||||
if(queryType !== 63) // 63 (0b00111111) = all possible query types are selected
|
||||
{
|
||||
APIstring += "&types="+queryType;
|
||||
}
|
||||
if (instantquery) {
|
||||
APIstring = "api_db.php?getAllQueries&from=" + from + "&until=" + until;
|
||||
} else {
|
||||
APIstring = "api_db.php?getAllQueries=empty";
|
||||
}
|
||||
|
||||
tableApi = $("#all-queries").DataTable( {
|
||||
"rowCallback": function( row, data, index ){
|
||||
var blocked, fieldtext, buttontext, color;
|
||||
switch (data[4])
|
||||
{
|
||||
case 1:
|
||||
blocked = true;
|
||||
color = "red";
|
||||
fieldtext = "Blocked (gravity)";
|
||||
buttontext = "<button style=\"color:green; white-space: nowrap;\"><i class=\"fas fa-check\"></i> Whitelist</button>";
|
||||
break;
|
||||
case 2:
|
||||
blocked = false;
|
||||
color = "green";
|
||||
fieldtext = "OK <br class='hidden-lg'>(forwarded)";
|
||||
buttontext = "<button style=\"color:red; white-space: nowrap;\"><i class=\"fa fa-ban\"></i> Blacklist</button>";
|
||||
break;
|
||||
case 3:
|
||||
blocked = false;
|
||||
color = "green";
|
||||
fieldtext = "OK <br class='hidden-lg'>(cached)";
|
||||
buttontext = "<button style=\"color:red; white-space: nowrap;\"><i class=\"fa fa-ban\"></i> Blacklist</button>";
|
||||
break;
|
||||
case 4:
|
||||
blocked = true;
|
||||
color = "red";
|
||||
fieldtext = "Blocked <br class='hidden-lg'>(regex/wildcard)";
|
||||
buttontext = "<button style=\"color:green; white-space: nowrap;\"><i class=\"fas fa-check\"></i> Whitelist</button>" ;
|
||||
break;
|
||||
case 5:
|
||||
blocked = true;
|
||||
color = "red";
|
||||
fieldtext = "Blocked <br class='hidden-lg'>(blacklist)";
|
||||
buttontext = "<button style=\"color:green; white-space: nowrap;\"><i class=\"fas fa-check\"></i> Whitelist</button>" ;
|
||||
break;
|
||||
case 6:
|
||||
blocked = true;
|
||||
color = "red";
|
||||
fieldtext = "Blocked <br class='hidden-lg'>(external, IP)";
|
||||
buttontext = "" ;
|
||||
break;
|
||||
case 7:
|
||||
blocked = true;
|
||||
color = "red";
|
||||
fieldtext = "Blocked <br class='hidden-lg'>(external, NULL)";
|
||||
buttontext = "" ;
|
||||
break;
|
||||
case 8:
|
||||
blocked = true;
|
||||
color = "red";
|
||||
fieldtext = "Blocked <br class='hidden-lg'>(external, NXRA)";
|
||||
buttontext = "" ;
|
||||
break;
|
||||
default:
|
||||
blocked = false;
|
||||
color = "black";
|
||||
fieldtext = "Unknown";
|
||||
buttontext = "";
|
||||
}
|
||||
// Check if query type filtering is enabled
|
||||
var queryType = getQueryTypes();
|
||||
if (queryType !== 63) {
|
||||
// 63 (0b00111111) = all possible query types are selected
|
||||
APIstring += "&types=" + queryType;
|
||||
}
|
||||
|
||||
$(row).css("color", color);
|
||||
$("td:eq(4)", row).html(fieldtext);
|
||||
$("td:eq(5)", row).html(buttontext);
|
||||
},
|
||||
dom: "<'row'<'col-sm-12'f>>" +
|
||||
"<'row'<'col-sm-4'l><'col-sm-8'p>>" +
|
||||
"<'row'<'col-sm-12'<'table-responsive'tr>>>" +
|
||||
"<'row'<'col-sm-5'i><'col-sm-7'p>>",
|
||||
"ajax": {
|
||||
"url": APIstring,
|
||||
"error": handleAjaxError,
|
||||
"dataSrc": function(data){
|
||||
var dataIndex = 0;
|
||||
return data.data.map(function(x){
|
||||
x[0] = x[0] * 1e6 + (dataIndex++);
|
||||
return x;
|
||||
});
|
||||
}
|
||||
},
|
||||
"autoWidth" : false,
|
||||
"processing": true,
|
||||
"deferRender": true,
|
||||
"order" : [[0, "desc"]],
|
||||
"columns": [
|
||||
{ "width" : "15%", "render": function (data, type, full, meta) { if(type === "display"){return moment.unix(Math.floor(data/1e6)).format("Y-MM-DD [<br class='hidden-lg'>]HH:mm:ss z");}else{return data;} }},
|
||||
{ "width" : "10%" },
|
||||
{ "width" : "40%" },
|
||||
{ "width" : "20%" },
|
||||
{ "width" : "10%" },
|
||||
{ "width" : "5%" },
|
||||
],
|
||||
"lengthMenu": [[10, 25, 50, 100, -1], [10, 25, 50, 100, "All"]],
|
||||
"columnDefs": [ {
|
||||
"targets": -1,
|
||||
"data": null,
|
||||
"defaultContent": ""
|
||||
} ],
|
||||
"initComplete": reloadCallback
|
||||
});
|
||||
$("#all-queries tbody").on( "click", "button", function () {
|
||||
var data = tableApi.row( $(this).parents("tr") ).data();
|
||||
if (data[4] === 1 || data[4] === 4 || data[5] === 5)
|
||||
{
|
||||
add(data[2],"white");
|
||||
tableApi = $("#all-queries").DataTable({
|
||||
rowCallback: function(row, data) {
|
||||
var fieldtext, buttontext, color;
|
||||
switch (data[4]) {
|
||||
case 1:
|
||||
color = "red";
|
||||
fieldtext = "Blocked (gravity)";
|
||||
buttontext =
|
||||
'<button type="button" class="btn btn-default btn-sm text-green"><i class="fas fa-check"></i> Whitelist</button>';
|
||||
break;
|
||||
case 2:
|
||||
color = "green";
|
||||
fieldtext = "OK <br class='hidden-lg'>(forwarded)";
|
||||
buttontext =
|
||||
'<button type="button" class="btn btn-default btn-sm text-red"><i class="fa fa-ban"></i> Blacklist</button>';
|
||||
break;
|
||||
case 3:
|
||||
color = "green";
|
||||
fieldtext = "OK <br class='hidden-lg'>(cached)";
|
||||
buttontext =
|
||||
'<button type="button" class="btn btn-default btn-sm text-red"><i class="fa fa-ban"></i> Blacklist</button>';
|
||||
break;
|
||||
case 4:
|
||||
color = "red";
|
||||
fieldtext = "Blocked <br class='hidden-lg'>(regex blacklist)";
|
||||
buttontext =
|
||||
'<button type="button" class="btn btn-default btn-sm text-green"><i class="fas fa-check"></i> Whitelist</button>';
|
||||
break;
|
||||
case 5:
|
||||
color = "red";
|
||||
fieldtext = "Blocked <br class='hidden-lg'>(exact blacklist)";
|
||||
buttontext =
|
||||
'<button type="button" class="btn btn-default btn-sm text-green"><i class="fas fa-check"></i> Whitelist</button>';
|
||||
break;
|
||||
case 6:
|
||||
color = "red";
|
||||
fieldtext = "Blocked <br class='hidden-lg'>(external, IP)";
|
||||
buttontext = "";
|
||||
break;
|
||||
case 7:
|
||||
color = "red";
|
||||
fieldtext = "Blocked <br class='hidden-lg'>(external, NULL)";
|
||||
buttontext = "";
|
||||
break;
|
||||
case 8:
|
||||
color = "red";
|
||||
fieldtext = "Blocked <br class='hidden-lg'>(external, NXRA)";
|
||||
buttontext = "";
|
||||
break;
|
||||
case 9:
|
||||
color = "red";
|
||||
fieldtext = "Blocked (gravity, CNAME)";
|
||||
buttontext =
|
||||
'<button type="button" class="btn btn-default btn-sm text-green"><i class="fas fa-check"></i> Whitelist</button>';
|
||||
break;
|
||||
case 10:
|
||||
color = "red";
|
||||
fieldtext = "Blocked <br class='hidden-lg'>(regex blacklist, CNAME)";
|
||||
buttontext =
|
||||
'<button type="button" class="btn btn-default btn-sm text-green"><i class="fas fa-check"></i> Whitelist</button>';
|
||||
break;
|
||||
case 11:
|
||||
color = "red";
|
||||
fieldtext = "Blocked <br class='hidden-lg'>(exact blacklist, CNAME)";
|
||||
buttontext =
|
||||
'<button type="button" class="btn btn-default btn-sm text-green"><i class="fas fa-check"></i> Whitelist</button>';
|
||||
break;
|
||||
default:
|
||||
color = "black";
|
||||
fieldtext = "Unknown";
|
||||
buttontext = "";
|
||||
}
|
||||
|
||||
$(row).css("color", color);
|
||||
$("td:eq(4)", row).html(fieldtext);
|
||||
$("td:eq(5)", row).html(buttontext);
|
||||
|
||||
// Substitute domain by "." if empty
|
||||
var domain = data[2];
|
||||
if (domain.length === 0) {
|
||||
domain = ".";
|
||||
}
|
||||
|
||||
$("td:eq(2)", row).text(domain);
|
||||
},
|
||||
dom:
|
||||
"<'row'<'col-sm-12'f>>" +
|
||||
"<'row'<'col-sm-4'l><'col-sm-8'p>>" +
|
||||
"<'row'<'col-sm-12'<'table-responsive'tr>>>" +
|
||||
"<'row'<'col-sm-5'i><'col-sm-7'p>>",
|
||||
ajax: {
|
||||
url: APIstring,
|
||||
error: handleAjaxError,
|
||||
dataSrc: function(data) {
|
||||
var dataIndex = 0;
|
||||
return data.data.map(function(x) {
|
||||
x[0] = x[0] * 1e6 + dataIndex++;
|
||||
return x;
|
||||
});
|
||||
}
|
||||
},
|
||||
autoWidth: false,
|
||||
processing: true,
|
||||
deferRender: true,
|
||||
order: [[0, "desc"]],
|
||||
columns: [
|
||||
{
|
||||
width: "15%",
|
||||
render: function(data, type) {
|
||||
if (type === "display") {
|
||||
return moment
|
||||
.unix(Math.floor(data / 1e6))
|
||||
.format("Y-MM-DD [<br class='hidden-lg'>]HH:mm:ss z");
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
else
|
||||
{
|
||||
add(data[2],"black");
|
||||
}
|
||||
} );
|
||||
|
||||
if(instantquery)
|
||||
{
|
||||
daterange.val(start__.format("MMMM Do YYYY, HH:mm") + " - " + end__.format("MMMM Do YYYY, HH:mm"));
|
||||
},
|
||||
{ width: "10%" },
|
||||
{ width: "40%" },
|
||||
{ width: "20%" },
|
||||
{ width: "10%" },
|
||||
{ width: "5%" }
|
||||
],
|
||||
lengthMenu: [
|
||||
[10, 25, 50, 100, -1],
|
||||
[10, 25, 50, 100, "All"]
|
||||
],
|
||||
columnDefs: [
|
||||
{
|
||||
targets: -1,
|
||||
data: null,
|
||||
defaultContent: ""
|
||||
}
|
||||
],
|
||||
initComplete: reloadCallback
|
||||
});
|
||||
$("#all-queries tbody").on("click", "button", function() {
|
||||
var data = tableApi.row($(this).parents("tr")).data();
|
||||
if (data[4] === 1 || data[4] === 4 || data[5] === 5) {
|
||||
add(data[2], "white");
|
||||
} else {
|
||||
add(data[2], "black");
|
||||
}
|
||||
} );
|
||||
});
|
||||
|
||||
if (instantquery) {
|
||||
daterange.val(start__.format(dateformat) + " - " + end__.format(dateformat));
|
||||
}
|
||||
});
|
||||
|
||||
$("#querytime").on("apply.daterangepicker", function(ev, picker) {
|
||||
$(this).val(picker.startDate.format(dateformat) + " to " + picker.endDate.format(dateformat));
|
||||
refreshTableData();
|
||||
$(this).val(picker.startDate.format(dateformat) + " to " + picker.endDate.format(dateformat));
|
||||
refreshTableData();
|
||||
});
|
||||
|
||||
@@ -1,66 +1,77 @@
|
||||
/* 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. */
|
||||
|
||||
/* global ActiveXObject: false */
|
||||
|
||||
// Credit: http://stackoverflow.com/a/10642418/2087442
|
||||
function httpGet(ta,theUrl)
|
||||
{
|
||||
var xmlhttp;
|
||||
if (window.XMLHttpRequest)
|
||||
{
|
||||
function httpGet(ta, theUrl) {
|
||||
var xmlhttp;
|
||||
if (window.XMLHttpRequest) {
|
||||
// code for IE7+
|
||||
xmlhttp = new XMLHttpRequest();
|
||||
}
|
||||
else
|
||||
{
|
||||
xmlhttp = new XMLHttpRequest();
|
||||
} else {
|
||||
// code for IE6, IE5
|
||||
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
|
||||
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
|
||||
}
|
||||
|
||||
xmlhttp.onreadystatechange = function() {
|
||||
if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
|
||||
ta.show();
|
||||
ta.empty();
|
||||
ta.append(xmlhttp.responseText);
|
||||
}
|
||||
xmlhttp.onreadystatechange=function()
|
||||
{
|
||||
if (xmlhttp.readyState === 4 && xmlhttp.status === 200)
|
||||
{
|
||||
ta.show();
|
||||
ta.empty();
|
||||
ta.append(xmlhttp.responseText);
|
||||
}
|
||||
};
|
||||
xmlhttp.open("GET", theUrl, false);
|
||||
xmlhttp.send();
|
||||
};
|
||||
|
||||
xmlhttp.open("GET", theUrl, false);
|
||||
xmlhttp.send();
|
||||
}
|
||||
|
||||
function eventsource() {
|
||||
var ta = $("#output");
|
||||
var upload = $( "#upload" );
|
||||
var checked = "";
|
||||
var token = encodeURIComponent($("#token").html());
|
||||
var ta = $("#output");
|
||||
var upload = $("#upload");
|
||||
var checked = "";
|
||||
var token = encodeURIComponent($("#token").text());
|
||||
|
||||
if(upload.prop("checked"))
|
||||
{
|
||||
checked = "upload";
|
||||
}
|
||||
if (upload.prop("checked")) {
|
||||
checked = "upload";
|
||||
}
|
||||
|
||||
// IE does not support EventSource - load whole content at once
|
||||
if (typeof EventSource !== "function") {
|
||||
httpGet(ta,"/admin/scripts/pi-hole/php/debug.php?IE&token="+token+"&"+checked);
|
||||
return;
|
||||
}
|
||||
// IE does not support EventSource - load whole content at once
|
||||
if (typeof EventSource !== "function") {
|
||||
httpGet(ta, "scripts/pi-hole/php/debug.php?IE&token=" + token + "&" + checked);
|
||||
return;
|
||||
}
|
||||
|
||||
var host = window.location.host;
|
||||
var source = new EventSource("/admin/scripts/pi-hole/php/debug.php?&token="+token+"&"+checked);
|
||||
var source = new EventSource("scripts/pi-hole/php/debug.php?&token=" + token + "&" + checked);
|
||||
|
||||
// Reset and show field
|
||||
ta.empty();
|
||||
ta.show();
|
||||
// Reset and show field
|
||||
ta.empty();
|
||||
ta.show();
|
||||
|
||||
source.addEventListener("message", function(e) {
|
||||
ta.append(e.data);
|
||||
}, false);
|
||||
source.addEventListener(
|
||||
"message",
|
||||
function(e) {
|
||||
ta.append(e.data);
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
// Will be called when script has finished
|
||||
source.addEventListener("error", function(e) {
|
||||
source.close();
|
||||
}, false);
|
||||
// Will be called when script has finished
|
||||
source.addEventListener(
|
||||
"error",
|
||||
function() {
|
||||
source.close();
|
||||
},
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
$("#debugBtn").on("click", function(){
|
||||
$("#debugBtn").attr("disabled", true);
|
||||
$("#upload").attr("disabled", true);
|
||||
eventsource();
|
||||
$("#debugBtn").on("click", function() {
|
||||
$("#debugBtn").attr("disabled", true);
|
||||
$("#upload").attr("disabled", true);
|
||||
eventsource();
|
||||
});
|
||||
|
||||
@@ -1,208 +1,198 @@
|
||||
/* 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. */
|
||||
* (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. */
|
||||
|
||||
//The following functions allow us to display time until pi-hole is enabled after disabling.
|
||||
//Works between all pages
|
||||
|
||||
function secondsTimeSpanToHMS(s) {
|
||||
var h = Math.floor(s/3600); //Get whole hours
|
||||
s -= h*3600;
|
||||
var m = Math.floor(s/60); //Get remaining minutes
|
||||
s -= m*60;
|
||||
return h+":"+(m < 10 ? "0"+m : m)+":"+(s < 10 ? "0"+s : s); //zero padding on minutes and seconds
|
||||
var h = Math.floor(s / 3600); //Get whole hours
|
||||
s -= h * 3600;
|
||||
var m = Math.floor(s / 60); //Get remaining minutes
|
||||
s -= m * 60;
|
||||
return h + ":" + (m < 10 ? "0" + m : m) + ":" + (s < 10 ? "0" + s : s); //zero padding on minutes and seconds
|
||||
}
|
||||
|
||||
function piholeChanged(action)
|
||||
{
|
||||
var status = $("#status");
|
||||
var ena = $("#pihole-enable");
|
||||
var dis = $("#pihole-disable");
|
||||
function piholeChanged(action) {
|
||||
var status = $("#status");
|
||||
var ena = $("#pihole-enable");
|
||||
var dis = $("#pihole-disable");
|
||||
|
||||
switch(action) {
|
||||
case "enabled":
|
||||
status.html("<i class='fa fa-circle' style='color:#7FFF00'></i> Active");
|
||||
ena.hide();
|
||||
dis.show();
|
||||
dis.removeClass("active");
|
||||
break;
|
||||
switch (action) {
|
||||
case "enabled":
|
||||
status.html("<i class='fa fa-circle text-green-light'></i> Active");
|
||||
ena.hide();
|
||||
dis.show();
|
||||
dis.removeClass("active");
|
||||
break;
|
||||
|
||||
case "disabled":
|
||||
status.html("<i class='fa fa-circle' style='color:#FF0000'></i> Offline");
|
||||
ena.show();
|
||||
dis.hide();
|
||||
break;
|
||||
}
|
||||
case "disabled":
|
||||
status.html("<i class='fa fa-circle text-red'></i> Offline");
|
||||
ena.show();
|
||||
dis.hide();
|
||||
break;
|
||||
|
||||
default:
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
|
||||
function countDown(){
|
||||
var ena = $("#enableLabel");
|
||||
var enaT = $("#enableTimer");
|
||||
var target = new Date(parseInt(enaT.html()));
|
||||
var seconds = Math.round((target.getTime() - new Date().getTime()) / 1000);
|
||||
function countDown() {
|
||||
var ena = $("#enableLabel");
|
||||
var enaT = $("#enableTimer");
|
||||
var target = new Date(parseInt(enaT.html()));
|
||||
var seconds = Math.round((target.getTime() - new Date().getTime()) / 1000);
|
||||
|
||||
if(seconds > 0){
|
||||
setTimeout(countDown,1000);
|
||||
ena.text("Enable (" + secondsTimeSpanToHMS(seconds) + ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
ena.text("Enable");
|
||||
piholeChanged("enabled");
|
||||
localStorage.removeItem("countDownTarget");
|
||||
}
|
||||
if (seconds > 0) {
|
||||
setTimeout(countDown, 1000);
|
||||
ena.text("Enable (" + secondsTimeSpanToHMS(seconds) + ")");
|
||||
} else {
|
||||
ena.text("Enable");
|
||||
piholeChanged("enabled");
|
||||
localStorage.removeItem("countDownTarget");
|
||||
}
|
||||
}
|
||||
|
||||
function piholeChange(action, duration)
|
||||
{
|
||||
var token = encodeURIComponent($("#token").html());
|
||||
var enaT = $("#enableTimer");
|
||||
var btnStatus;
|
||||
function piholeChange(action, duration) {
|
||||
var token = encodeURIComponent($("#token").text());
|
||||
var enaT = $("#enableTimer");
|
||||
var btnStatus;
|
||||
|
||||
switch(action) {
|
||||
case "enable":
|
||||
btnStatus = $("#flip-status-enable");
|
||||
btnStatus.html("<i class='fa fa-spinner'> </i>");
|
||||
$.getJSON("api.php?enable&token=" + token, function(data) {
|
||||
if(data.status === "enabled") {
|
||||
btnStatus.html("");
|
||||
piholeChanged("enabled");
|
||||
}
|
||||
});
|
||||
break;
|
||||
switch (action) {
|
||||
case "enable":
|
||||
btnStatus = $("#flip-status-enable");
|
||||
btnStatus.html("<i class='fa fa-spinner'> </i>");
|
||||
$.getJSON("api.php?enable&token=" + token, function(data) {
|
||||
if (data.status === "enabled") {
|
||||
btnStatus.html("");
|
||||
piholeChanged("enabled");
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case "disable":
|
||||
btnStatus = $("#flip-status-disable");
|
||||
btnStatus.html("<i class='fa fa-spinner'> </i>");
|
||||
$.getJSON("api.php?disable=" + duration + "&token=" + token, function(data) {
|
||||
if(data.status === "disabled") {
|
||||
btnStatus.html("");
|
||||
piholeChanged("disabled");
|
||||
if(duration > 0)
|
||||
{
|
||||
enaT.html(new Date().getTime() + duration * 1000);
|
||||
setTimeout(countDown,100);
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "disable":
|
||||
btnStatus = $("#flip-status-disable");
|
||||
btnStatus.html("<i class='fa fa-spinner'> </i>");
|
||||
$.getJSON("api.php?disable=" + duration + "&token=" + token, function(data) {
|
||||
if (data.status === "disabled") {
|
||||
btnStatus.html("");
|
||||
piholeChanged("disabled");
|
||||
if (duration > 0) {
|
||||
enaT.html(new Date().getTime() + duration * 1000);
|
||||
setTimeout(countDown, 100);
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
|
||||
$( document ).ready(function() {
|
||||
var enaT = $("#enableTimer");
|
||||
var target = new Date(parseInt(enaT.html()));
|
||||
var seconds = Math.round((target.getTime() - new Date().getTime()) / 1000);
|
||||
if (seconds > 0)
|
||||
{
|
||||
setTimeout(countDown,100);
|
||||
}
|
||||
$(document).ready(function() {
|
||||
var enaT = $("#enableTimer");
|
||||
var target = new Date(parseInt(enaT.html()));
|
||||
var seconds = Math.round((target.getTime() - new Date().getTime()) / 1000);
|
||||
if (seconds > 0) {
|
||||
setTimeout(countDown, 100);
|
||||
}
|
||||
});
|
||||
|
||||
// Handle Enable/Disable
|
||||
$("#pihole-enable").on("click", function(e){
|
||||
e.preventDefault();
|
||||
localStorage.removeItem("countDownTarget");
|
||||
piholeChange("enable","");
|
||||
$("#pihole-enable").on("click", function(e) {
|
||||
e.preventDefault();
|
||||
localStorage.removeItem("countDownTarget");
|
||||
piholeChange("enable", "");
|
||||
});
|
||||
$("#pihole-disable-permanently").on("click", function(e){
|
||||
e.preventDefault();
|
||||
piholeChange("disable","0");
|
||||
$("#pihole-disable-permanently").on("click", function(e) {
|
||||
e.preventDefault();
|
||||
piholeChange("disable", "0");
|
||||
});
|
||||
$("#pihole-disable-10s").on("click", function(e){
|
||||
e.preventDefault();
|
||||
piholeChange("disable","10");
|
||||
$("#pihole-disable-10s").on("click", function(e) {
|
||||
e.preventDefault();
|
||||
piholeChange("disable", "10");
|
||||
});
|
||||
$("#pihole-disable-30s").on("click", function(e){
|
||||
e.preventDefault();
|
||||
piholeChange("disable","30");
|
||||
$("#pihole-disable-30s").on("click", function(e) {
|
||||
e.preventDefault();
|
||||
piholeChange("disable", "30");
|
||||
});
|
||||
$("#pihole-disable-5m").on("click", function(e){
|
||||
e.preventDefault();
|
||||
piholeChange("disable","300");
|
||||
$("#pihole-disable-5m").on("click", function(e) {
|
||||
e.preventDefault();
|
||||
piholeChange("disable", "300");
|
||||
});
|
||||
$("#pihole-disable-custom").on("click", function(e){
|
||||
e.preventDefault();
|
||||
var custVal = $("#customTimeout").val();
|
||||
custVal = $("#btnMins").hasClass("active") ? custVal * 60 : custVal;
|
||||
piholeChange("disable",custVal);
|
||||
$("#pihole-disable-custom").on("click", function(e) {
|
||||
e.preventDefault();
|
||||
var custVal = $("#customTimeout").val();
|
||||
custVal = $("#btnMins").hasClass("active") ? custVal * 60 : custVal;
|
||||
piholeChange("disable", custVal);
|
||||
});
|
||||
|
||||
// Session timer
|
||||
var sessionvalidity = parseInt(document.getElementById("sessiontimercounter").textContent);
|
||||
var start = new Date;
|
||||
var sessionTimerCounter = document.getElementById("sessiontimercounter");
|
||||
var sessionvalidity = parseInt(sessionTimerCounter.textContent);
|
||||
var start = new Date();
|
||||
|
||||
function updateSessionTimer()
|
||||
{
|
||||
start = new Date;
|
||||
start.setSeconds(start.getSeconds() + sessionvalidity);
|
||||
function updateSessionTimer() {
|
||||
start = new Date();
|
||||
start.setSeconds(start.getSeconds() + sessionvalidity);
|
||||
}
|
||||
|
||||
if(sessionvalidity > 0)
|
||||
{
|
||||
// setSeconds will correctly handle wrap-around cases
|
||||
updateSessionTimer();
|
||||
if (sessionvalidity > 0) {
|
||||
// setSeconds will correctly handle wrap-around cases
|
||||
updateSessionTimer();
|
||||
|
||||
setInterval(function() {
|
||||
var current = new Date;
|
||||
var totalseconds = (start - current) / 1000;
|
||||
setInterval(function() {
|
||||
var current = new Date();
|
||||
var totalseconds = (start - current) / 1000;
|
||||
var minutes = Math.floor(totalseconds / 60);
|
||||
if (minutes < 10) {
|
||||
minutes = "0" + minutes;
|
||||
}
|
||||
|
||||
// var hours = Math.floor(totalseconds / 3600);
|
||||
// totalseconds = totalseconds % 3600;
|
||||
var seconds = Math.floor(totalseconds % 60);
|
||||
if (seconds < 10) {
|
||||
seconds = "0" + seconds;
|
||||
}
|
||||
|
||||
var minutes = Math.floor(totalseconds / 60);
|
||||
if(minutes < 10){ minutes = "0" + minutes; }
|
||||
|
||||
var seconds = Math.floor(totalseconds % 60);
|
||||
if(seconds < 10){ seconds = "0" + seconds; }
|
||||
|
||||
if(totalseconds > 0)
|
||||
{
|
||||
document.getElementById("sessiontimercounter").textContent = minutes + ":" + seconds;
|
||||
}
|
||||
else
|
||||
{
|
||||
document.getElementById("sessiontimercounter").textContent = "-- : --";
|
||||
}
|
||||
|
||||
}, 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
document.getElementById("sessiontimer").style.display = "none";
|
||||
if (totalseconds > 0) {
|
||||
sessionTimerCounter.textContent = minutes + ":" + seconds;
|
||||
} else {
|
||||
sessionTimerCounter.textContent = "-- : --";
|
||||
}
|
||||
}, 1000);
|
||||
} else {
|
||||
document.getElementById("sessiontimer").style.display = "none";
|
||||
}
|
||||
|
||||
// Handle Strg + Enter button on Login page
|
||||
$(document).keypress(function(e) {
|
||||
if((e.keyCode === 10 || e.keyCode === 13) && e.ctrlKey && $("#loginpw").is(":focus")) {
|
||||
$("#loginform").attr("action", "settings.php");
|
||||
$("#loginform").submit();
|
||||
}
|
||||
if ((e.keyCode === 10 || e.keyCode === 13) && e.ctrlKey && $("#loginpw").is(":focus")) {
|
||||
$("#loginform").attr("action", "settings.php");
|
||||
$("#loginform").submit();
|
||||
}
|
||||
});
|
||||
|
||||
function testCookies()
|
||||
{
|
||||
if (navigator.cookieEnabled)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
function testCookies() {
|
||||
if (navigator.cookieEnabled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// set and read cookie
|
||||
document.cookie = "cookietest=1";
|
||||
var ret = document.cookie.indexOf("cookietest=") !== -1;
|
||||
// set and read cookie
|
||||
document.cookie = "cookietest=1";
|
||||
var ret = document.cookie.indexOf("cookietest=") !== -1;
|
||||
|
||||
// delete cookie
|
||||
document.cookie = "cookietest=1; expires=Thu, 01-Jan-1970 00:00:01 GMT";
|
||||
// delete cookie
|
||||
document.cookie = "cookietest=1; expires=Thu, 01-Jan-1970 00:00:01 GMT";
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
$(function() {
|
||||
if(!testCookies() && $("#cookieInfo").length)
|
||||
{
|
||||
$("#cookieInfo").show();
|
||||
}
|
||||
if (!testCookies() && $("#cookieInfo").length) {
|
||||
$("#cookieInfo").show();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,72 +1,80 @@
|
||||
/* 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. */
|
||||
* (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 eventsource() {
|
||||
var alInfo = $("#alInfo");
|
||||
var alSuccess = $("#alSuccess");
|
||||
var ta = $("#output");
|
||||
var alInfo = $("#alInfo");
|
||||
var alSuccess = $("#alSuccess");
|
||||
var ta = $("#output");
|
||||
|
||||
// IE does not support EventSource - exit early
|
||||
if (typeof EventSource !== "function") {
|
||||
ta.show();
|
||||
ta.html("Updating lists of ad-serving domains is not supported with this browser!");
|
||||
return;
|
||||
}
|
||||
var source = new EventSource("scripts/pi-hole/php/gravity.sh.php");
|
||||
|
||||
ta.html("");
|
||||
// IE does not support EventSource - exit early
|
||||
if (typeof EventSource !== "function") {
|
||||
ta.show();
|
||||
alInfo.show();
|
||||
alSuccess.hide();
|
||||
ta.html("Updating lists of ad-serving domains is not supported with this browser!");
|
||||
return;
|
||||
}
|
||||
|
||||
source.addEventListener("message", function(e) {
|
||||
if(e.data.indexOf("Pi-hole blocking is") !== -1)
|
||||
{
|
||||
alSuccess.show();
|
||||
}
|
||||
var source = new EventSource("scripts/pi-hole/php/gravity.sh.php");
|
||||
|
||||
// Detect ${OVER}
|
||||
if(e.data.indexOf("<------") !== -1)
|
||||
{
|
||||
ta.text(ta.text().substring(0, ta.text().lastIndexOf("\n")) + "\n");
|
||||
var new_string = e.data.replace("<------", "");
|
||||
ta.append(new_string);
|
||||
}
|
||||
else
|
||||
{
|
||||
ta.append(e.data);
|
||||
}
|
||||
ta.html("");
|
||||
ta.show();
|
||||
alInfo.show();
|
||||
alSuccess.hide();
|
||||
|
||||
}, false);
|
||||
source.addEventListener(
|
||||
"message",
|
||||
function(e) {
|
||||
if (e.data.indexOf("Pi-hole blocking is") !== -1) {
|
||||
alSuccess.show();
|
||||
}
|
||||
|
||||
// Will be called when script has finished
|
||||
source.addEventListener("error", function(e) {
|
||||
alInfo.delay(1000).fadeOut(2000, function() { alInfo.hide(); });
|
||||
source.close();
|
||||
$("#gravityBtn").removeAttr("disabled");
|
||||
}, false);
|
||||
// Detect ${OVER}
|
||||
if (e.data.indexOf("<------") !== -1) {
|
||||
ta.text(ta.text().substring(0, ta.text().lastIndexOf("\n")) + "\n");
|
||||
var new_string = e.data.replace("<------", "");
|
||||
ta.append(new_string);
|
||||
} else {
|
||||
ta.append(e.data);
|
||||
}
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
// Will be called when script has finished
|
||||
source.addEventListener(
|
||||
"error",
|
||||
function() {
|
||||
alInfo.delay(1000).fadeOut(2000, function() {
|
||||
alInfo.hide();
|
||||
});
|
||||
source.close();
|
||||
$("#gravityBtn").removeAttr("disabled");
|
||||
},
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
$("#gravityBtn").on("click", function(){
|
||||
$("#gravityBtn").attr("disabled", true);
|
||||
eventsource();
|
||||
$("#gravityBtn").on("click", function() {
|
||||
$("#gravityBtn").attr("disabled", true);
|
||||
eventsource();
|
||||
});
|
||||
|
||||
// Handle hiding of alerts
|
||||
$(function(){
|
||||
$("[data-hide]").on("click", function(){
|
||||
$(this).closest("." + $(this).attr("data-hide")).hide();
|
||||
});
|
||||
$(function() {
|
||||
$("[data-hide]").on("click", function() {
|
||||
$(this)
|
||||
.closest("." + $(this).attr("data-hide"))
|
||||
.hide();
|
||||
});
|
||||
|
||||
// Do we want to start updating immediately?
|
||||
// gravity.php?go
|
||||
var searchString = window.location.search.substring(1);
|
||||
if(searchString.indexOf("go") !== -1)
|
||||
{
|
||||
$("#gravityBtn").attr("disabled", true);
|
||||
eventsource();
|
||||
}
|
||||
// Do we want to start updating immediately?
|
||||
// gravity.php?go
|
||||
var searchString = window.location.search.substring(1);
|
||||
if (searchString.indexOf("go") !== -1) {
|
||||
$("#gravityBtn").attr("disabled", true);
|
||||
eventsource();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,382 @@
|
||||
/* 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. */
|
||||
|
||||
/* global utils:false */
|
||||
|
||||
var table;
|
||||
var groups = [];
|
||||
var token = $("#token").html();
|
||||
|
||||
function get_groups() {
|
||||
$.post(
|
||||
"scripts/pi-hole/php/groups.php",
|
||||
{ action: "get_groups", token: token },
|
||||
function(data) {
|
||||
groups = data.data;
|
||||
initTable();
|
||||
},
|
||||
"json"
|
||||
);
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
$("#btnAdd").on("click", addAdlist);
|
||||
|
||||
utils.bsSelect_defaults();
|
||||
get_groups();
|
||||
});
|
||||
|
||||
function initTable() {
|
||||
table = $("#adlistsTable").DataTable({
|
||||
ajax: {
|
||||
url: "scripts/pi-hole/php/groups.php",
|
||||
data: { action: "get_adlists", token: token },
|
||||
type: "POST"
|
||||
},
|
||||
order: [[0, "asc"]],
|
||||
columns: [
|
||||
{ data: "id", visible: false },
|
||||
{ data: "address" },
|
||||
{ data: "enabled", searchable: false },
|
||||
{ data: "comment" },
|
||||
{ data: "groups", searchable: false },
|
||||
{ data: null, width: "80px", orderable: false }
|
||||
],
|
||||
drawCallback: function() {
|
||||
$('button[id^="deleteAdlist_"]').on("click", deleteAdlist);
|
||||
// Remove visible dropdown to prevent orphaning
|
||||
$("body > .bootstrap-select.dropdown").remove();
|
||||
},
|
||||
rowCallback: function(row, data) {
|
||||
$(row).attr("data-id", data.id);
|
||||
var tooltip =
|
||||
"Added: " +
|
||||
utils.datetime(data.date_added) +
|
||||
"\nLast modified: " +
|
||||
utils.datetime(data.date_modified) +
|
||||
"\nDatabase ID: " +
|
||||
data.id;
|
||||
$("td:eq(0)", row).html(
|
||||
'<code id="address_' +
|
||||
data.id +
|
||||
'" title="' +
|
||||
tooltip +
|
||||
'" class="breakall">' +
|
||||
data.address +
|
||||
"</code>"
|
||||
);
|
||||
|
||||
var disabled = data.enabled === 0;
|
||||
$("td:eq(1)", row).html(
|
||||
'<input type="checkbox" id="status_' + data.id + '"' + (disabled ? "" : " checked") + ">"
|
||||
);
|
||||
var statusEl = $("#status_" + data.id, row);
|
||||
statusEl.bootstrapToggle({
|
||||
on: "Enabled",
|
||||
off: "Disabled",
|
||||
size: "small",
|
||||
onstyle: "success",
|
||||
width: "80px"
|
||||
});
|
||||
statusEl.on("change", editAdlist);
|
||||
|
||||
$("td:eq(2)", row).html('<input id="comment_' + data.id + '" class="form-control">');
|
||||
var commentEl = $("#comment_" + data.id, row);
|
||||
commentEl.val(data.comment);
|
||||
commentEl.on("change", editAdlist);
|
||||
|
||||
$("td:eq(3)", row).empty();
|
||||
$("td:eq(3)", row).append(
|
||||
'<select class="selectpicker" id="multiselect_' + data.id + '" multiple></select>'
|
||||
);
|
||||
var selectEl = $("#multiselect_" + data.id, row);
|
||||
// Add all known groups
|
||||
for (var i = 0; i < groups.length; i++) {
|
||||
var data_sub = "";
|
||||
if (!groups[i].enabled) {
|
||||
data_sub = 'data-subtext="(disabled)"';
|
||||
}
|
||||
|
||||
selectEl.append(
|
||||
$("<option " + data_sub + "/>")
|
||||
.val(groups[i].id)
|
||||
.text(groups[i].name)
|
||||
);
|
||||
}
|
||||
|
||||
// Select assigned groups
|
||||
selectEl.val(data.groups);
|
||||
// Initialize bootstrap-select
|
||||
selectEl
|
||||
// fix dropdown if it would stick out right of the viewport
|
||||
.on("show.bs.select", function() {
|
||||
var winWidth = $(window).width();
|
||||
var dropdownEl = $("body > .bootstrap-select.dropdown");
|
||||
if (dropdownEl.length > 0) {
|
||||
dropdownEl.removeClass("align-right");
|
||||
var width = dropdownEl.width();
|
||||
var left = dropdownEl.offset().left;
|
||||
if (left + width > winWidth) {
|
||||
dropdownEl.addClass("align-right");
|
||||
}
|
||||
}
|
||||
})
|
||||
.on("changed.bs.select", function() {
|
||||
// enable Apply button
|
||||
if ($(ApplyBtn).prop("disabled")) {
|
||||
$(ApplyBtn)
|
||||
.addClass("btn-success")
|
||||
.prop("disabled", false)
|
||||
.on("click", function() {
|
||||
editAdlist.call(selectEl);
|
||||
});
|
||||
}
|
||||
})
|
||||
.on("hide.bs.select", function() {
|
||||
// Restore values if drop-down menu is closed without clicking the Apply button
|
||||
if (!$(ApplyBtn).prop("disabled")) {
|
||||
$(this)
|
||||
.val(data.groups)
|
||||
.selectpicker("refresh");
|
||||
$(ApplyBtn)
|
||||
.removeClass("btn-success")
|
||||
.prop("disabled", true)
|
||||
.off("click");
|
||||
}
|
||||
})
|
||||
.selectpicker()
|
||||
.siblings(".dropdown-menu")
|
||||
.find(".bs-actionsbox")
|
||||
.prepend(
|
||||
'<button type="button" id=btn_apply_' +
|
||||
data.id +
|
||||
' class="btn btn-block btn-sm" disabled>Apply</button>'
|
||||
);
|
||||
|
||||
var ApplyBtn = "#btn_apply_" + data.id;
|
||||
|
||||
var button =
|
||||
'<button class="btn btn-danger btn-xs" type="button" id="deleteAdlist_' +
|
||||
data.id +
|
||||
'">' +
|
||||
'<span class="glyphicon glyphicon-trash"></span>' +
|
||||
"</button>";
|
||||
$("td:eq(4)", row).html(button);
|
||||
},
|
||||
dom:
|
||||
"<'row'<'col-sm-4'l><'col-sm-8'f>>" +
|
||||
"<'row'<'col-sm-12'<'table-responsive'tr>>>" +
|
||||
"<'row'<'col-sm-5'i><'col-sm-7'p>>",
|
||||
lengthMenu: [
|
||||
[10, 25, 50, 100, -1],
|
||||
[10, 25, 50, 100, "All"]
|
||||
],
|
||||
stateSave: true,
|
||||
stateSaveCallback: function(settings, data) {
|
||||
// Store current state in client's local storage area
|
||||
localStorage.setItem("groups-adlists-table", JSON.stringify(data));
|
||||
},
|
||||
stateLoadCallback: function() {
|
||||
// Receive previous state from client's local storage area
|
||||
var data = localStorage.getItem("groups-adlists-table");
|
||||
// Return if not available
|
||||
if (data === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
data = JSON.parse(data);
|
||||
// Always start on the first page to show most recent queries
|
||||
data.start = 0;
|
||||
// Always start with empty search field
|
||||
data.search.search = "";
|
||||
// Reset visibility of ID column
|
||||
data.columns[0].visible = false;
|
||||
// Apply loaded state to table
|
||||
return data;
|
||||
}
|
||||
});
|
||||
|
||||
table.on("order.dt", function() {
|
||||
var order = table.order();
|
||||
if (order[0][0] !== 0 || order[0][1] !== "asc") {
|
||||
$("#resetButton").show();
|
||||
} else {
|
||||
$("#resetButton").hide();
|
||||
}
|
||||
});
|
||||
$("#resetButton").on("click", function() {
|
||||
table.order([[0, "asc"]]).draw();
|
||||
$("#resetButton").hide();
|
||||
});
|
||||
}
|
||||
|
||||
function addAdlist() {
|
||||
var address = $("#new_address").val();
|
||||
var comment = $("#new_comment").val();
|
||||
|
||||
utils.disableAll();
|
||||
utils.showAlert("info", "", "Adding adlist...", address);
|
||||
|
||||
if (address.length === 0) {
|
||||
utils.showAlert("warning", "", "Warning", "Please specify an adlist address");
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: "scripts/pi-hole/php/groups.php",
|
||||
method: "post",
|
||||
dataType: "json",
|
||||
data: {
|
||||
action: "add_adlist",
|
||||
address: address,
|
||||
comment: comment,
|
||||
token: token
|
||||
},
|
||||
success: function(response) {
|
||||
utils.enableAll();
|
||||
if (response.success) {
|
||||
utils.showAlert(
|
||||
"success",
|
||||
"glyphicon glyphicon-plus",
|
||||
"Successfully added adlist",
|
||||
address
|
||||
);
|
||||
table.ajax.reload(null, false);
|
||||
$("#new_address").val("");
|
||||
$("#new_comment").val("");
|
||||
table.ajax.reload();
|
||||
} else {
|
||||
utils.showAlert("error", "", "Error while adding new adlist: ", response.message);
|
||||
}
|
||||
},
|
||||
error: function(jqXHR, exception) {
|
||||
utils.enableAll();
|
||||
utils.showAlert("error", "", "Error while adding new adlist: ", jqXHR.responseText);
|
||||
console.log(exception);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function editAdlist() {
|
||||
var elem = $(this).attr("id");
|
||||
var tr = $(this).closest("tr");
|
||||
var id = tr.attr("data-id");
|
||||
var status = tr.find("#status_" + id).is(":checked") ? 1 : 0;
|
||||
var comment = tr.find("#comment_" + id).val();
|
||||
var groups = tr.find("#multiselect_" + id).val();
|
||||
var address = tr.find("#address_" + id).text();
|
||||
|
||||
var done = "edited";
|
||||
var not_done = "editing";
|
||||
switch (elem) {
|
||||
case "status_" + id:
|
||||
if (status === 0) {
|
||||
done = "disabled";
|
||||
not_done = "disabling";
|
||||
} else if (status === 1) {
|
||||
done = "enabled";
|
||||
not_done = "enabling";
|
||||
}
|
||||
|
||||
break;
|
||||
case "comment_" + id:
|
||||
done = "edited comment of";
|
||||
not_done = "editing comment of";
|
||||
break;
|
||||
case "multiselect_" + id:
|
||||
done = "edited groups of";
|
||||
not_done = "editing groups of";
|
||||
break;
|
||||
default:
|
||||
alert("bad element or invalid data-id!");
|
||||
return;
|
||||
}
|
||||
|
||||
utils.disableAll();
|
||||
utils.showAlert("info", "", "Editing adlist...", address);
|
||||
|
||||
$.ajax({
|
||||
url: "scripts/pi-hole/php/groups.php",
|
||||
method: "post",
|
||||
dataType: "json",
|
||||
data: {
|
||||
action: "edit_adlist",
|
||||
id: id,
|
||||
comment: comment,
|
||||
status: status,
|
||||
groups: groups,
|
||||
token: token
|
||||
},
|
||||
success: function(response) {
|
||||
utils.enableAll();
|
||||
if (response.success) {
|
||||
utils.showAlert(
|
||||
"success",
|
||||
"glyphicon glyphicon-pencil",
|
||||
"Successfully " + done + " adlist ",
|
||||
address
|
||||
);
|
||||
table.ajax.reload(null, false);
|
||||
} else {
|
||||
utils.showAlert(
|
||||
"error",
|
||||
"",
|
||||
"Error while " + not_done + " adlist with ID " + id,
|
||||
Number(response.message)
|
||||
);
|
||||
}
|
||||
},
|
||||
error: function(jqXHR, exception) {
|
||||
utils.enableAll();
|
||||
utils.showAlert(
|
||||
"error",
|
||||
"",
|
||||
"Error while " + not_done + " adlist with ID " + id,
|
||||
jqXHR.responseText
|
||||
);
|
||||
console.log(exception);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function deleteAdlist() {
|
||||
var tr = $(this).closest("tr");
|
||||
var id = tr.attr("data-id");
|
||||
var address = tr.find("#address_" + id).text();
|
||||
|
||||
utils.disableAll();
|
||||
utils.showAlert("info", "", "Deleting adlist...", address);
|
||||
$.ajax({
|
||||
url: "scripts/pi-hole/php/groups.php",
|
||||
method: "post",
|
||||
dataType: "json",
|
||||
data: { action: "delete_adlist", id: id, token: token },
|
||||
success: function(response) {
|
||||
utils.enableAll();
|
||||
if (response.success) {
|
||||
utils.showAlert(
|
||||
"success",
|
||||
"glyphicon glyphicon-trash",
|
||||
"Successfully deleted adlist ",
|
||||
address
|
||||
);
|
||||
table
|
||||
.row(tr)
|
||||
.remove()
|
||||
.draw(false)
|
||||
.ajax.reload(null, false);
|
||||
} else {
|
||||
utils.showAlert("error", "", "Error while deleting adlist with ID " + id, response.message);
|
||||
}
|
||||
},
|
||||
error: function(jqXHR, exception) {
|
||||
utils.enableAll();
|
||||
utils.showAlert("error", "", "Error while deleting adlist with ID " + id, jqXHR.responseText);
|
||||
console.log(exception);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,426 @@
|
||||
/* 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. */
|
||||
|
||||
/* global utils:false */
|
||||
|
||||
var table;
|
||||
var groups = [];
|
||||
var token = $("#token").html();
|
||||
|
||||
function reload_client_suggestions() {
|
||||
$.post(
|
||||
"scripts/pi-hole/php/groups.php",
|
||||
{ action: "get_unconfigured_clients", token: token },
|
||||
function(data) {
|
||||
var sel = $("#select");
|
||||
var customWasSelected = sel.val() === "custom";
|
||||
sel.empty();
|
||||
for (var key in data) {
|
||||
if (!Object.prototype.hasOwnProperty.call(data, key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var text = key;
|
||||
if (data[key].length > 0) {
|
||||
text += " (" + data[key] + ")";
|
||||
}
|
||||
|
||||
sel.append(
|
||||
$("<option />")
|
||||
.val(key)
|
||||
.text(text)
|
||||
);
|
||||
}
|
||||
|
||||
sel.append(
|
||||
$("<option />")
|
||||
.val("custom")
|
||||
.text("Custom, specified below...")
|
||||
);
|
||||
if (customWasSelected) {
|
||||
sel.val("custom");
|
||||
}
|
||||
},
|
||||
"json"
|
||||
);
|
||||
}
|
||||
|
||||
function get_groups() {
|
||||
$.post(
|
||||
"scripts/pi-hole/php/groups.php",
|
||||
{ action: "get_groups", token: token },
|
||||
function(data) {
|
||||
groups = data.data;
|
||||
initTable();
|
||||
},
|
||||
"json"
|
||||
);
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
$("#btnAdd").on("click", addClient);
|
||||
|
||||
reload_client_suggestions();
|
||||
utils.bsSelect_defaults();
|
||||
get_groups();
|
||||
|
||||
$("#select").on("change", function() {
|
||||
$("#ip-custom").val("");
|
||||
$("#ip-custom").prop("disabled", $("#select option:selected").val() !== "custom");
|
||||
});
|
||||
});
|
||||
|
||||
function initTable() {
|
||||
table = $("#clientsTable").DataTable({
|
||||
ajax: {
|
||||
url: "scripts/pi-hole/php/groups.php",
|
||||
data: { action: "get_clients", token: token },
|
||||
type: "POST"
|
||||
},
|
||||
order: [[0, "asc"]],
|
||||
columns: [
|
||||
{ data: "id", visible: false },
|
||||
{ data: "ip" },
|
||||
{ data: "comment" },
|
||||
{ data: "groups", searchable: false },
|
||||
{ data: "name", width: "80px", orderable: false }
|
||||
],
|
||||
drawCallback: function() {
|
||||
$('button[id^="deleteClient_"]').on("click", deleteClient);
|
||||
// Remove visible dropdown to prevent orphaning
|
||||
$("body > .bootstrap-select.dropdown").remove();
|
||||
},
|
||||
rowCallback: function(row, data) {
|
||||
$(row).attr("data-id", data.id);
|
||||
var tooltip =
|
||||
"Added: " +
|
||||
utils.datetime(data.date_added) +
|
||||
"\nLast modified: " +
|
||||
utils.datetime(data.date_modified) +
|
||||
"\nDatabase ID: " +
|
||||
data.id;
|
||||
var ip_name =
|
||||
'<code id="ip_' +
|
||||
data.id +
|
||||
'" title="' +
|
||||
tooltip +
|
||||
'" class="breakall">' +
|
||||
data.ip +
|
||||
"</code>";
|
||||
if (data.name !== null && data.name.length > 0)
|
||||
ip_name +=
|
||||
'<br><code id="name_' +
|
||||
data.id +
|
||||
'" title="' +
|
||||
tooltip +
|
||||
'" class="breakall">' +
|
||||
data.name +
|
||||
"</code>";
|
||||
$("td:eq(0)", row).html(ip_name);
|
||||
|
||||
$("td:eq(1)", row).html('<input id="comment_' + data.id + '" class="form-control">');
|
||||
var commentEl = $("#comment_" + data.id, row);
|
||||
commentEl.val(data.comment);
|
||||
commentEl.on("change", editClient);
|
||||
|
||||
$("td:eq(2)", row).empty();
|
||||
$("td:eq(2)", row).append(
|
||||
'<select class="selectpicker" id="multiselect_' + data.id + '" multiple></select>'
|
||||
);
|
||||
var selectEl = $("#multiselect_" + data.id, row);
|
||||
// Add all known groups
|
||||
for (var i = 0; i < groups.length; i++) {
|
||||
var data_sub = "";
|
||||
if (!groups[i].enabled) {
|
||||
data_sub = 'data-subtext="(disabled)"';
|
||||
}
|
||||
|
||||
selectEl.append(
|
||||
$("<option " + data_sub + "/>")
|
||||
.val(groups[i].id)
|
||||
.text(groups[i].name)
|
||||
);
|
||||
}
|
||||
|
||||
// Select assigned groups
|
||||
selectEl.val(data.groups);
|
||||
// Initialize bootstrap-select
|
||||
selectEl
|
||||
// fix dropdown if it would stick out right of the viewport
|
||||
.on("show.bs.select", function() {
|
||||
var winWidth = $(window).width();
|
||||
var dropdownEl = $("body > .bootstrap-select.dropdown");
|
||||
if (dropdownEl.length > 0) {
|
||||
dropdownEl.removeClass("align-right");
|
||||
var width = dropdownEl.width();
|
||||
var left = dropdownEl.offset().left;
|
||||
if (left + width > winWidth) {
|
||||
dropdownEl.addClass("align-right");
|
||||
}
|
||||
}
|
||||
})
|
||||
.on("changed.bs.select", function() {
|
||||
// enable Apply button
|
||||
if ($(ApplyBtn).prop("disabled")) {
|
||||
$(ApplyBtn)
|
||||
.addClass("btn-success")
|
||||
.prop("disabled", false)
|
||||
.on("click", function() {
|
||||
editClient.call(selectEl);
|
||||
});
|
||||
}
|
||||
})
|
||||
.on("hide.bs.select", function() {
|
||||
// Restore values if drop-down menu is closed without clicking the Apply button
|
||||
if (!$(ApplyBtn).prop("disabled")) {
|
||||
$(this)
|
||||
.val(data.groups)
|
||||
.selectpicker("refresh");
|
||||
$(ApplyBtn)
|
||||
.removeClass("btn-success")
|
||||
.prop("disabled", true)
|
||||
.off("click");
|
||||
}
|
||||
})
|
||||
.selectpicker()
|
||||
.siblings(".dropdown-menu")
|
||||
.find(".bs-actionsbox")
|
||||
.prepend(
|
||||
'<button type="button" id=btn_apply_' +
|
||||
data.id +
|
||||
' class="btn btn-block btn-sm" disabled>Apply</button>'
|
||||
);
|
||||
|
||||
var ApplyBtn = "#btn_apply_" + data.id;
|
||||
|
||||
var button =
|
||||
'<button class="btn btn-danger btn-xs" type="button" id="deleteClient_' +
|
||||
data.id +
|
||||
'">' +
|
||||
'<span class="glyphicon glyphicon-trash"></span>' +
|
||||
"</button>";
|
||||
$("td:eq(3)", row).html(button);
|
||||
},
|
||||
dom:
|
||||
"<'row'<'col-sm-4'l><'col-sm-8'f>>" +
|
||||
"<'row'<'col-sm-12'<'table-responsive'tr>>>" +
|
||||
"<'row'<'col-sm-5'i><'col-sm-7'p>>",
|
||||
lengthMenu: [
|
||||
[10, 25, 50, 100, -1],
|
||||
[10, 25, 50, 100, "All"]
|
||||
],
|
||||
stateSave: true,
|
||||
stateSaveCallback: function(settings, data) {
|
||||
// Store current state in client's local storage area
|
||||
localStorage.setItem("groups-clients-table", JSON.stringify(data));
|
||||
},
|
||||
stateLoadCallback: function() {
|
||||
// Receive previous state from client's local storage area
|
||||
var data = localStorage.getItem("groups-clients-table");
|
||||
// Return if not available
|
||||
if (data === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
data = JSON.parse(data);
|
||||
// Always start on the first page to show most recent queries
|
||||
data.start = 0;
|
||||
// Always start with empty search field
|
||||
data.search.search = "";
|
||||
// Reset visibility of ID column
|
||||
data.columns[0].visible = false;
|
||||
// Apply loaded state to table
|
||||
return data;
|
||||
}
|
||||
});
|
||||
|
||||
table.on("order.dt", function() {
|
||||
var order = table.order();
|
||||
if (order[0][0] !== 0 || order[0][1] !== "asc") {
|
||||
$("#resetButton").show();
|
||||
} else {
|
||||
$("#resetButton").hide();
|
||||
}
|
||||
});
|
||||
$("#resetButton").on("click", function() {
|
||||
table.order([[0, "asc"]]).draw();
|
||||
$("#resetButton").hide();
|
||||
});
|
||||
}
|
||||
|
||||
function addClient() {
|
||||
var ip = $("#select").val();
|
||||
var comment = $("#new_comment").val();
|
||||
if (ip === "custom") {
|
||||
ip = $("#ip-custom").val();
|
||||
}
|
||||
|
||||
utils.disableAll();
|
||||
utils.showAlert("info", "", "Adding client...", ip);
|
||||
|
||||
if (ip.length === 0) {
|
||||
utils.enableAll();
|
||||
utils.showAlert("warning", "", "Warning", "Please specify a client IP address");
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate IP address (may contain CIDR details)
|
||||
var ipv6format = ip.includes(":");
|
||||
|
||||
if (!ipv6format && !utils.validateIPv4CIDR(ip)) {
|
||||
utils.enableAll();
|
||||
utils.showAlert("warning", "", "Warning", "Invalid IPv4 address!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ipv6format && !utils.validateIPv6CIDR(ip)) {
|
||||
utils.enableAll();
|
||||
utils.showAlert("warning", "", "Warning", "Invalid IPv6 address!");
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: "scripts/pi-hole/php/groups.php",
|
||||
method: "post",
|
||||
dataType: "json",
|
||||
data: { action: "add_client", ip: ip, comment: comment, token: token },
|
||||
success: function(response) {
|
||||
utils.enableAll();
|
||||
if (response.success) {
|
||||
utils.showAlert("success", "glyphicon glyphicon-plus", "Successfully added client", ip);
|
||||
reload_client_suggestions();
|
||||
table.ajax.reload(null, false);
|
||||
} else {
|
||||
utils.showAlert("error", "", "Error while adding new client", response.message);
|
||||
}
|
||||
},
|
||||
error: function(jqXHR, exception) {
|
||||
utils.enableAll();
|
||||
utils.showAlert("error", "", "Error while adding new client", jqXHR.responseText);
|
||||
console.log(exception);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function editClient() {
|
||||
var elem = $(this).attr("id");
|
||||
var tr = $(this).closest("tr");
|
||||
var id = tr.attr("data-id");
|
||||
var groups = tr.find("#multiselect_" + id).val();
|
||||
var ip = tr.find("#ip_" + id).text();
|
||||
var name = tr.find("#name_" + id).text();
|
||||
var comment = tr.find("#comment_" + id).val();
|
||||
|
||||
var done = "edited";
|
||||
var not_done = "editing";
|
||||
switch (elem) {
|
||||
case "multiselect_" + id:
|
||||
done = "edited groups of";
|
||||
not_done = "editing groups of";
|
||||
break;
|
||||
case "comment_" + id:
|
||||
done = "edited comment of";
|
||||
not_done = "editing comment of";
|
||||
break;
|
||||
default:
|
||||
alert("bad element or invalid data-id!");
|
||||
return;
|
||||
}
|
||||
|
||||
var ip_name = ip;
|
||||
if (name.length > 0) {
|
||||
ip_name += " (" + name + ")";
|
||||
}
|
||||
|
||||
utils.disableAll();
|
||||
utils.showAlert("info", "", "Editing client...", ip_name);
|
||||
$.ajax({
|
||||
url: "scripts/pi-hole/php/groups.php",
|
||||
method: "post",
|
||||
dataType: "json",
|
||||
data: {
|
||||
action: "edit_client",
|
||||
id: id,
|
||||
groups: groups,
|
||||
token: token,
|
||||
comment: comment
|
||||
},
|
||||
success: function(response) {
|
||||
utils.enableAll();
|
||||
if (response.success) {
|
||||
utils.showAlert(
|
||||
"success",
|
||||
"glyphicon glyphicon-pencil",
|
||||
"Successfully " + done + " client",
|
||||
ip_name
|
||||
);
|
||||
table.ajax.reload(null, false);
|
||||
} else {
|
||||
utils.showAlert(
|
||||
"error",
|
||||
"Error while " + not_done + " client with ID " + id,
|
||||
response.message
|
||||
);
|
||||
}
|
||||
},
|
||||
error: function(jqXHR, exception) {
|
||||
utils.enableAll();
|
||||
utils.showAlert(
|
||||
"error",
|
||||
"",
|
||||
"Error while " + not_done + " client with ID " + id,
|
||||
jqXHR.responseText
|
||||
);
|
||||
console.log(exception);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function deleteClient() {
|
||||
var tr = $(this).closest("tr");
|
||||
var id = tr.attr("data-id");
|
||||
var ip = tr.find("#ip_" + id).text();
|
||||
var name = tr.find("#name_" + id).text();
|
||||
|
||||
var ip_name = ip;
|
||||
if (name.length > 0) {
|
||||
ip_name += " (" + name + ")";
|
||||
}
|
||||
|
||||
utils.disableAll();
|
||||
utils.showAlert("info", "", "Deleting client...", ip_name);
|
||||
$.ajax({
|
||||
url: "scripts/pi-hole/php/groups.php",
|
||||
method: "post",
|
||||
dataType: "json",
|
||||
data: { action: "delete_client", id: id, token: token },
|
||||
success: function(response) {
|
||||
utils.enableAll();
|
||||
if (response.success) {
|
||||
utils.showAlert(
|
||||
"success",
|
||||
"glyphicon glyphicon-trash",
|
||||
"Successfully deleted client ",
|
||||
ip_name
|
||||
);
|
||||
table
|
||||
.row(tr)
|
||||
.remove()
|
||||
.draw(false)
|
||||
.ajax.reload(null, false);
|
||||
reload_client_suggestions();
|
||||
} else {
|
||||
utils.showAlert("error", "", "Error while deleting client with ID " + id, response.message);
|
||||
}
|
||||
},
|
||||
error: function(jqXHR, exception) {
|
||||
utils.enableAll();
|
||||
utils.showAlert("error", "", "Error while deleting client with ID " + id, jqXHR.responseText);
|
||||
console.log(exception);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
/* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2020 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. */
|
||||
|
||||
/* global moment:false */
|
||||
|
||||
var info = null;
|
||||
function showAlert(type, icon, title, message) {
|
||||
var opts = {};
|
||||
title = " <strong>" + title + "</strong><br>";
|
||||
switch (type) {
|
||||
case "info":
|
||||
opts = {
|
||||
type: "info",
|
||||
icon: "glyphicon glyphicon-time",
|
||||
title: title,
|
||||
message: message
|
||||
};
|
||||
info = $.notify(opts);
|
||||
break;
|
||||
case "success":
|
||||
opts = {
|
||||
type: "success",
|
||||
icon: icon,
|
||||
title: title,
|
||||
message: message
|
||||
};
|
||||
if (info) {
|
||||
info.update(opts);
|
||||
} else {
|
||||
$.notify(opts);
|
||||
}
|
||||
|
||||
break;
|
||||
case "warning":
|
||||
opts = {
|
||||
type: "warning",
|
||||
icon: "glyphicon glyphicon-warning-sign",
|
||||
title: title,
|
||||
message: message
|
||||
};
|
||||
if (info) {
|
||||
info.update(opts);
|
||||
} else {
|
||||
$.notify(opts);
|
||||
}
|
||||
|
||||
break;
|
||||
case "error":
|
||||
opts = {
|
||||
type: "danger",
|
||||
icon: "glyphicon glyphicon-remove",
|
||||
title: " <strong>Error, something went wrong!</strong><br>",
|
||||
message: message
|
||||
};
|
||||
if (info) {
|
||||
info.update(opts);
|
||||
} else {
|
||||
$.notify(opts);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
function datetime(date) {
|
||||
return moment.unix(Math.floor(date)).format("Y-MM-DD HH:mm:ss z");
|
||||
}
|
||||
|
||||
function disableAll() {
|
||||
$("input").attr("disabled", true);
|
||||
$("select").attr("disabled", true);
|
||||
$("button").attr("disabled", true);
|
||||
$("textarea").attr("disabled", true);
|
||||
}
|
||||
|
||||
function enableAll() {
|
||||
$("input").attr("disabled", false);
|
||||
$("select").attr("disabled", false);
|
||||
$("button").attr("disabled", false);
|
||||
$("textarea").attr("disabled", false);
|
||||
|
||||
// Enable custom input field only if applicable
|
||||
var ip = $("#select") ? $("#select").val() : null;
|
||||
if (ip !== null && ip !== "custom") {
|
||||
ip = $("#ip-custom").attr("disabled", true);
|
||||
}
|
||||
}
|
||||
|
||||
// Pi-hole IPv4/CIDR validator by DL6ER, see regexr.com/50csh
|
||||
function validateIPv4CIDR(ip) {
|
||||
// One IPv4 element is 8bit: 0 - 256
|
||||
var ipv4elem = "(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)";
|
||||
// CIDR for IPv4 is 1 - 32 bit
|
||||
var v4cidr = "(\\/([1-9]|[1-2][0-9]|3[0-2])){0,1}";
|
||||
var ipv4validator = new RegExp(
|
||||
"^" + ipv4elem + "\\." + ipv4elem + "\\." + ipv4elem + "\\." + ipv4elem + v4cidr + "$"
|
||||
);
|
||||
return ipv4validator.test(ip);
|
||||
}
|
||||
|
||||
// Pi-hole IPv6/CIDR validator by DL6ER, see regexr.com/50csn
|
||||
function validateIPv6CIDR(ip) {
|
||||
// One IPv6 element is 16bit: 0000 - FFFF
|
||||
var ipv6elem = "[0-9A-Fa-f]{1,4}";
|
||||
// CIDR for IPv6 is 1- 128 bit
|
||||
var v6cidr = "(\\/([1-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])){0,1}";
|
||||
var ipv6validator = new RegExp(
|
||||
"^(((?:" +
|
||||
ipv6elem +
|
||||
"))((?::" +
|
||||
ipv6elem +
|
||||
"))*::((?:" +
|
||||
ipv6elem +
|
||||
"))*((?::" +
|
||||
ipv6elem +
|
||||
"))*|((?:" +
|
||||
ipv6elem +
|
||||
"))((?::" +
|
||||
ipv6elem +
|
||||
")){7})" +
|
||||
v6cidr +
|
||||
"$"
|
||||
);
|
||||
return ipv6validator.test(ip);
|
||||
}
|
||||
|
||||
function bsSelect_defaults() {
|
||||
// set bootstrap-select defaults
|
||||
var pickerDEFAULTS = $.fn.selectpicker.Constructor.DEFAULTS;
|
||||
pickerDEFAULTS.noneSelectedText = "none selected";
|
||||
pickerDEFAULTS.selectedTextFormat = "count > 1";
|
||||
pickerDEFAULTS.actionsBox = true;
|
||||
pickerDEFAULTS.width = "fit";
|
||||
pickerDEFAULTS.container = "body";
|
||||
pickerDEFAULTS.dropdownAlignRight = "auto";
|
||||
pickerDEFAULTS.selectAllText = "All";
|
||||
pickerDEFAULTS.deselectAllText = "None";
|
||||
pickerDEFAULTS.countSelectedText = function(num, total) {
|
||||
if (num === total) {
|
||||
return "All selected (" + num + ")";
|
||||
}
|
||||
|
||||
return num + " selected";
|
||||
};
|
||||
}
|
||||
|
||||
window.utils = (function() {
|
||||
return {
|
||||
showAlert: showAlert,
|
||||
datetime: datetime,
|
||||
disableAll: disableAll,
|
||||
enableAll: enableAll,
|
||||
validateIPv4CIDR: validateIPv4CIDR,
|
||||
validateIPv6CIDR: validateIPv6CIDR,
|
||||
bsSelect_defaults: bsSelect_defaults
|
||||
};
|
||||
})();
|
||||
@@ -0,0 +1,550 @@
|
||||
/* 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. */
|
||||
|
||||
/* global utils:false */
|
||||
|
||||
var table;
|
||||
var groups = [];
|
||||
var token = $("#token").html();
|
||||
var GETDict = {};
|
||||
var showtype = "all";
|
||||
|
||||
function get_groups() {
|
||||
$.post(
|
||||
"scripts/pi-hole/php/groups.php",
|
||||
{ action: "get_groups", token: token },
|
||||
function(data) {
|
||||
groups = data.data;
|
||||
initTable();
|
||||
},
|
||||
"json"
|
||||
);
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
window.location.search
|
||||
.substr(1)
|
||||
.split("&")
|
||||
.forEach(function(item) {
|
||||
GETDict[item.split("=")[0]] = item.split("=")[1];
|
||||
});
|
||||
|
||||
if ("type" in GETDict && (GETDict.type === "white" || GETDict.type === "black")) {
|
||||
showtype = GETDict.type;
|
||||
}
|
||||
|
||||
// sync description fields, reset inactive inputs on tab change
|
||||
$('a[data-toggle="tab"]').on("shown.bs.tab", function() {
|
||||
var tabHref = $(this).attr("href");
|
||||
var val;
|
||||
if (tabHref === "#tab_domain") {
|
||||
val = $("#new_regex_comment").val();
|
||||
$("#new_domain_comment").val(val);
|
||||
$("#new_regex").val("");
|
||||
} else if (tabHref === "#tab_regex") {
|
||||
val = $("#new_domain_comment").val();
|
||||
$("#new_regex_comment").val(val);
|
||||
$("#new_domain").val("");
|
||||
$("#wildcard_checkbox").prop("checked", false);
|
||||
}
|
||||
});
|
||||
|
||||
$("#add2black, #add2white").on("click", addDomain);
|
||||
|
||||
utils.bsSelect_defaults();
|
||||
get_groups();
|
||||
});
|
||||
|
||||
function initTable() {
|
||||
table = $("#domainsTable").DataTable({
|
||||
ajax: {
|
||||
url: "scripts/pi-hole/php/groups.php",
|
||||
data: { action: "get_domains", showtype: showtype, token: token },
|
||||
type: "POST"
|
||||
},
|
||||
order: [[0, "asc"]],
|
||||
columns: [
|
||||
{ data: "id", visible: false },
|
||||
{ data: "domain" },
|
||||
{ data: "type", searchable: false },
|
||||
{ data: "enabled", searchable: false },
|
||||
{ data: "comment" },
|
||||
{ data: "groups", searchable: false },
|
||||
{ data: null, width: "80px", orderable: false }
|
||||
],
|
||||
drawCallback: function() {
|
||||
$('button[id^="deleteDomain_"]').on("click", deleteDomain);
|
||||
// Remove visible dropdown to prevent orphaning
|
||||
$("body > .bootstrap-select.dropdown").remove();
|
||||
},
|
||||
rowCallback: function(row, data) {
|
||||
$(row).attr("data-id", data.id);
|
||||
var tooltip =
|
||||
"Added: " +
|
||||
utils.datetime(data.date_added) +
|
||||
"\nLast modified: " +
|
||||
utils.datetime(data.date_modified) +
|
||||
"\nDatabase ID: " +
|
||||
data.id;
|
||||
$("td:eq(0)", row).html(
|
||||
'<code id="domain_' +
|
||||
data.id +
|
||||
'" title="' +
|
||||
tooltip +
|
||||
'" class="breakall">' +
|
||||
data.domain +
|
||||
"</code>"
|
||||
);
|
||||
|
||||
var whitelist_options = "";
|
||||
if (showtype === "all" || showtype === "white") {
|
||||
whitelist_options =
|
||||
'<option value="0"' +
|
||||
(data.type === 0 ? " selected" : "") +
|
||||
">Exact whitelist</option>" +
|
||||
'<option value="2"' +
|
||||
(data.type === 2 ? " selected" : "") +
|
||||
">Regex whitelist</option>";
|
||||
}
|
||||
|
||||
var blacklist_options = "";
|
||||
if (showtype === "all" || showtype === "black") {
|
||||
blacklist_options =
|
||||
'<option value="1"' +
|
||||
(data.type === 1 ? " selected " : " ") +
|
||||
">Exact blacklist</option>" +
|
||||
'<option value="3"' +
|
||||
(data.type === 3 ? " selected" : "") +
|
||||
">Regex blacklist</option>";
|
||||
}
|
||||
|
||||
$("td:eq(1)", row).html(
|
||||
'<select id="type_' +
|
||||
data.id +
|
||||
'" class="form-control">' +
|
||||
whitelist_options +
|
||||
blacklist_options +
|
||||
"</select>"
|
||||
);
|
||||
var typeEl = $("#type_" + data.id, row);
|
||||
typeEl.on("change", editDomain);
|
||||
|
||||
var disabled = data.enabled === 0;
|
||||
$("td:eq(2)", row).html(
|
||||
'<input type="checkbox" id="status_' + data.id + '"' + (disabled ? "" : " checked") + ">"
|
||||
);
|
||||
var statusEl = $("#status_" + data.id, row);
|
||||
statusEl.bootstrapToggle({
|
||||
on: "Enabled",
|
||||
off: "Disabled",
|
||||
size: "small",
|
||||
onstyle: "success",
|
||||
width: "80px"
|
||||
});
|
||||
statusEl.on("change", editDomain);
|
||||
|
||||
$("td:eq(3)", row).html('<input id="comment_' + data.id + '" class="form-control">');
|
||||
var commentEl = $("#comment_" + data.id, row);
|
||||
commentEl.val(data.comment);
|
||||
commentEl.on("change", editDomain);
|
||||
|
||||
// Show group assignment field only if in full domain management mode
|
||||
if (table.column(5).visible()) {
|
||||
$("td:eq(4)", row).empty();
|
||||
$("td:eq(4)", row).append(
|
||||
'<select class="selectpicker" id="multiselect_' + data.id + '" multiple></select>'
|
||||
);
|
||||
var selectEl = $("#multiselect_" + data.id, row);
|
||||
// Add all known groups
|
||||
for (var i = 0; i < groups.length; i++) {
|
||||
var data_sub = "";
|
||||
if (!groups[i].enabled) {
|
||||
data_sub = 'data-subtext="(disabled)"';
|
||||
}
|
||||
|
||||
selectEl.append(
|
||||
$("<option " + data_sub + "/>")
|
||||
.val(groups[i].id)
|
||||
.text(groups[i].name)
|
||||
);
|
||||
}
|
||||
|
||||
// Select assigned groups
|
||||
selectEl.val(data.groups);
|
||||
// Initialize bootstrap-select
|
||||
selectEl
|
||||
// fix dropdown if it would stick out right of the viewport
|
||||
.on("show.bs.select", function() {
|
||||
var winWidth = $(window).width();
|
||||
var dropdownEl = $("body > .bootstrap-select.dropdown");
|
||||
if (dropdownEl.length > 0) {
|
||||
dropdownEl.removeClass("align-right");
|
||||
var width = dropdownEl.width();
|
||||
var left = dropdownEl.offset().left;
|
||||
if (left + width > winWidth) {
|
||||
dropdownEl.addClass("align-right");
|
||||
}
|
||||
}
|
||||
})
|
||||
.on("changed.bs.select", function() {
|
||||
// enable Apply button
|
||||
if ($(ApplyBtn).prop("disabled")) {
|
||||
$(ApplyBtn)
|
||||
.addClass("btn-success")
|
||||
.prop("disabled", false)
|
||||
.on("click", function() {
|
||||
editDomain.call(selectEl);
|
||||
});
|
||||
}
|
||||
})
|
||||
.on("hide.bs.select", function() {
|
||||
// Restore values if drop-down menu is closed without clicking the Apply button
|
||||
if (!$(ApplyBtn).prop("disabled")) {
|
||||
$(this)
|
||||
.val(data.groups)
|
||||
.selectpicker("refresh");
|
||||
$(ApplyBtn)
|
||||
.removeClass("btn-success")
|
||||
.prop("disabled", true)
|
||||
.off("click");
|
||||
}
|
||||
})
|
||||
.selectpicker()
|
||||
.siblings(".dropdown-menu")
|
||||
.find(".bs-actionsbox")
|
||||
.prepend(
|
||||
'<button type="button" id=btn_apply_' +
|
||||
data.id +
|
||||
' class="btn btn-block btn-sm" disabled>Apply</button>'
|
||||
);
|
||||
}
|
||||
|
||||
var ApplyBtn = "#btn_apply_" + data.id;
|
||||
|
||||
// Highlight row (if url parameter "domainid=" is used)
|
||||
if ("domainid" in GETDict && data.id === parseInt(GETDict.domainid)) {
|
||||
$(row)
|
||||
.find("td")
|
||||
.addClass("highlight");
|
||||
}
|
||||
|
||||
var button =
|
||||
'<button class="btn btn-danger btn-xs" type="button" id="deleteDomain_' +
|
||||
data.id +
|
||||
'">' +
|
||||
'<span class="glyphicon glyphicon-trash"></span>' +
|
||||
"</button>";
|
||||
if (table.column(5).visible()) {
|
||||
$("td:eq(5)", row).html(button);
|
||||
} else {
|
||||
$("td:eq(4)", row).html(button);
|
||||
}
|
||||
},
|
||||
dom:
|
||||
"<'row'<'col-sm-4'l><'col-sm-8'f>>" +
|
||||
"<'row'<'col-sm-12'<'table-responsive'tr>>>" +
|
||||
"<'row'<'col-sm-5'i><'col-sm-7'p>>",
|
||||
lengthMenu: [
|
||||
[10, 25, 50, 100, -1],
|
||||
[10, 25, 50, 100, "All"]
|
||||
],
|
||||
stateSave: true,
|
||||
stateSaveCallback: function(settings, data) {
|
||||
// Store current state in client's local storage area
|
||||
localStorage.setItem("groups-domains-table", JSON.stringify(data));
|
||||
},
|
||||
stateLoadCallback: function() {
|
||||
// Receive previous state from client's local storage area
|
||||
var data = localStorage.getItem("groups-domains-table");
|
||||
// Return if not available
|
||||
if (data === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
data = JSON.parse(data);
|
||||
// Always start on the first page to show most recent queries
|
||||
data.start = 0;
|
||||
// Always start with empty search field
|
||||
data.search.search = "";
|
||||
// Reset visibility of ID column
|
||||
data.columns[0].visible = false;
|
||||
// Show group assignment column only on full page
|
||||
data.columns[5].visible = showtype === "all";
|
||||
// Apply loaded state to table
|
||||
return data;
|
||||
},
|
||||
initComplete: function() {
|
||||
if ("domainid" in GETDict) {
|
||||
var pos = table
|
||||
.column(0, { order: "current" })
|
||||
.data()
|
||||
.indexOf(parseInt(GETDict.domainid));
|
||||
if (pos >= 0) {
|
||||
var page = Math.floor(pos / table.page.info().length);
|
||||
table.page(page).draw(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
table.on("order.dt", function() {
|
||||
var order = table.order();
|
||||
if (order[0][0] !== 0 || order[0][1] !== "asc") {
|
||||
$("#resetButton").show();
|
||||
} else {
|
||||
$("#resetButton").hide();
|
||||
}
|
||||
});
|
||||
$("#resetButton").on("click", function() {
|
||||
table.order([[0, "asc"]]).draw();
|
||||
$("#resetButton").hide();
|
||||
});
|
||||
}
|
||||
|
||||
function addDomain() {
|
||||
var action = this.id;
|
||||
var tabHref = $('a[data-toggle="tab"][aria-expanded="true"]').attr("href");
|
||||
var wildcardEl = $("#wildcard_checkbox");
|
||||
var wildcard_checked = wildcardEl.prop("checked");
|
||||
var type;
|
||||
|
||||
// current tab's inputs
|
||||
var domain_regex, domainEl, commentEl;
|
||||
if (tabHref === "#tab_domain") {
|
||||
domain_regex = "domain";
|
||||
domainEl = $("#new_domain");
|
||||
commentEl = $("#new_domain_comment");
|
||||
} else if (tabHref === "#tab_regex") {
|
||||
domain_regex = "regex";
|
||||
domainEl = $("#new_regex");
|
||||
commentEl = $("#new_regex_comment");
|
||||
}
|
||||
|
||||
var domain = domainEl.val();
|
||||
var comment = commentEl.val();
|
||||
|
||||
utils.disableAll();
|
||||
utils.showAlert("info", "", "Adding " + domain_regex + "...", domain);
|
||||
|
||||
if (domain.length > 0) {
|
||||
// strip "*." if specified by user in wildcard mode
|
||||
if (domain_regex === "domain" && wildcard_checked && domain.startsWith("*.")) {
|
||||
domain = domain.substr(2);
|
||||
}
|
||||
|
||||
// determine list type
|
||||
if (domain_regex === "domain" && action === "add2black" && wildcard_checked) {
|
||||
type = "3W";
|
||||
} else if (domain_regex === "domain" && action === "add2black" && !wildcard_checked) {
|
||||
type = "1";
|
||||
} else if (domain_regex === "domain" && action === "add2white" && wildcard_checked) {
|
||||
type = "2W";
|
||||
} else if (domain_regex === "domain" && action === "add2white" && !wildcard_checked) {
|
||||
type = "0";
|
||||
} else if (domain_regex === "regex" && action === "add2black") {
|
||||
type = "3";
|
||||
} else if (domain_regex === "regex" && action === "add2white") {
|
||||
type = "2";
|
||||
}
|
||||
} else {
|
||||
utils.enableAll();
|
||||
utils.showAlert("warning", "", "Warning", "Please specify a " + domain_regex);
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: "scripts/pi-hole/php/groups.php",
|
||||
method: "post",
|
||||
dataType: "json",
|
||||
data: {
|
||||
action: "add_domain",
|
||||
domain: domain,
|
||||
type: type,
|
||||
comment: comment,
|
||||
token: token
|
||||
},
|
||||
success: function(response) {
|
||||
utils.enableAll();
|
||||
if (response.success) {
|
||||
utils.showAlert(
|
||||
"success",
|
||||
"glyphicon glyphicon-plus",
|
||||
"Successfully added " + domain_regex,
|
||||
domain
|
||||
);
|
||||
domainEl.val("");
|
||||
commentEl.val("");
|
||||
wildcardEl.prop("checked", false);
|
||||
table.ajax.reload(null, false);
|
||||
} else {
|
||||
utils.showAlert("error", "", "Error while adding new " + domain_regex, response.message);
|
||||
}
|
||||
},
|
||||
error: function(jqXHR, exception) {
|
||||
utils.enableAll();
|
||||
utils.showAlert("error", "", "Error while adding new " + domain_regex, jqXHR.responseText);
|
||||
console.log(exception);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function editDomain() {
|
||||
var elem = $(this).attr("id");
|
||||
var tr = $(this).closest("tr");
|
||||
var id = tr.attr("data-id");
|
||||
var domain = tr.find("#domain_" + id).text();
|
||||
var type = tr.find("#type_" + id).val();
|
||||
var status = tr.find("#status_" + id).is(":checked") ? 1 : 0;
|
||||
var comment = tr.find("#comment_" + id).val();
|
||||
|
||||
// Show group assignment field only if in full domain management mode
|
||||
// if not included, just use the row data.
|
||||
var rowData = table.row(tr).data();
|
||||
var groups = table.column(5).visible() ? tr.find("#multiselect_" + id).val() : rowData.groups;
|
||||
|
||||
var domain_regex;
|
||||
if (type === "0" || type === "1") {
|
||||
domain_regex = "domain";
|
||||
} else if (type === "2" || type === "3") {
|
||||
domain_regex = "regex";
|
||||
}
|
||||
|
||||
var done = "edited";
|
||||
var not_done = "editing";
|
||||
switch (elem) {
|
||||
case "status_" + id:
|
||||
if (status === 0) {
|
||||
done = "disabled";
|
||||
not_done = "disabling";
|
||||
} else if (status === 1) {
|
||||
done = "enabled";
|
||||
not_done = "enabling";
|
||||
}
|
||||
|
||||
break;
|
||||
case "name_" + id:
|
||||
done = "edited name of";
|
||||
not_done = "editing name of";
|
||||
break;
|
||||
case "comment_" + id:
|
||||
done = "edited comment of";
|
||||
not_done = "editing comment of";
|
||||
break;
|
||||
case "type_" + id:
|
||||
done = "edited type of";
|
||||
not_done = "editing type of";
|
||||
break;
|
||||
case "multiselect_" + id:
|
||||
done = "edited groups of";
|
||||
not_done = "editing groups of";
|
||||
break;
|
||||
default:
|
||||
alert("bad element or invalid data-id!");
|
||||
return;
|
||||
}
|
||||
|
||||
utils.disableAll();
|
||||
utils.showAlert("info", "", "Editing " + domain_regex + "...", name);
|
||||
$.ajax({
|
||||
url: "scripts/pi-hole/php/groups.php",
|
||||
method: "post",
|
||||
dataType: "json",
|
||||
data: {
|
||||
action: "edit_domain",
|
||||
id: id,
|
||||
type: type,
|
||||
comment: comment,
|
||||
status: status,
|
||||
groups: groups,
|
||||
token: token
|
||||
},
|
||||
success: function(response) {
|
||||
utils.enableAll();
|
||||
if (response.success) {
|
||||
utils.showAlert(
|
||||
"success",
|
||||
"glyphicon glyphicon-pencil",
|
||||
"Successfully " + done + " " + domain_regex,
|
||||
domain
|
||||
);
|
||||
table.ajax.reload(null, false);
|
||||
} else
|
||||
utils.showAlert(
|
||||
"error",
|
||||
"",
|
||||
"Error while " + not_done + " " + domain_regex + " with ID " + id,
|
||||
response.message
|
||||
);
|
||||
},
|
||||
error: function(jqXHR, exception) {
|
||||
utils.enableAll();
|
||||
utils.showAlert(
|
||||
"error",
|
||||
"",
|
||||
"Error while " + not_done + " " + domain_regex + " with ID " + id,
|
||||
jqXHR.responseText
|
||||
);
|
||||
console.log(exception);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function deleteDomain() {
|
||||
var tr = $(this).closest("tr");
|
||||
var id = tr.attr("data-id");
|
||||
var domain = tr.find("#domain_" + id).text();
|
||||
var type = tr.find("#type_" + id).val();
|
||||
|
||||
var domain_regex;
|
||||
if (type === "0" || type === "1") {
|
||||
domain_regex = "domain";
|
||||
} else if (type === "2" || type === "3") {
|
||||
domain_regex = "regex";
|
||||
}
|
||||
|
||||
utils.disableAll();
|
||||
utils.showAlert("info", "", "Deleting " + domain_regex + "...", domain);
|
||||
$.ajax({
|
||||
url: "scripts/pi-hole/php/groups.php",
|
||||
method: "post",
|
||||
dataType: "json",
|
||||
data: { action: "delete_domain", id: id, token: token },
|
||||
success: function(response) {
|
||||
utils.enableAll();
|
||||
if (response.success) {
|
||||
utils.showAlert(
|
||||
"success",
|
||||
"glyphicon glyphicon-trash",
|
||||
"Successfully deleted " + domain_regex,
|
||||
domain
|
||||
);
|
||||
table
|
||||
.row(tr)
|
||||
.remove()
|
||||
.draw(false)
|
||||
.ajax.reload(null, false);
|
||||
} else {
|
||||
utils.showAlert(
|
||||
"error",
|
||||
"",
|
||||
"Error while deleting " + domain_regex + " with ID " + id,
|
||||
response.message
|
||||
);
|
||||
}
|
||||
},
|
||||
error: function(jqXHR, exception) {
|
||||
utils.enableAll();
|
||||
utils.showAlert(
|
||||
"error",
|
||||
"",
|
||||
"Error while deleting " + domain_regex + " with ID " + id,
|
||||
jqXHR.responseText
|
||||
);
|
||||
console.log(exception);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,277 @@
|
||||
/* 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. */
|
||||
|
||||
/* global utils:false */
|
||||
|
||||
var table;
|
||||
var token = $("#token").html();
|
||||
|
||||
$(document).ready(function() {
|
||||
$("#btnAdd").on("click", addGroup);
|
||||
|
||||
table = $("#groupsTable").DataTable({
|
||||
ajax: {
|
||||
url: "scripts/pi-hole/php/groups.php",
|
||||
data: { action: "get_groups", token: token },
|
||||
type: "POST"
|
||||
},
|
||||
order: [[0, "asc"]],
|
||||
columns: [
|
||||
{ data: "id", visible: false },
|
||||
{ data: "name" },
|
||||
{ data: "enabled", searchable: false },
|
||||
{ data: "description" },
|
||||
{ data: null, width: "60px", orderable: false }
|
||||
],
|
||||
drawCallback: function() {
|
||||
$('button[id^="deleteGroup_"]').on("click", deleteGroup);
|
||||
},
|
||||
rowCallback: function(row, data) {
|
||||
$(row).attr("data-id", data.id);
|
||||
var tooltip =
|
||||
"Added: " +
|
||||
utils.datetime(data.date_added) +
|
||||
"\nLast modified: " +
|
||||
utils.datetime(data.date_modified) +
|
||||
"\nDatabase ID: " +
|
||||
data.id;
|
||||
$("td:eq(0)", row).html(
|
||||
'<input id="name_' + data.id + '" title="' + tooltip + '" class="form-control">'
|
||||
);
|
||||
var nameEl = $("#name_" + data.id, row);
|
||||
nameEl.val(data.name);
|
||||
nameEl.on("change", editGroup);
|
||||
|
||||
var disabled = data.enabled === 0;
|
||||
$("td:eq(1)", row).html(
|
||||
'<input type="checkbox" id="status_' + data.id + '"' + (disabled ? "" : " checked") + ">"
|
||||
);
|
||||
var statusEl = $("#status_" + data.id, row);
|
||||
statusEl.bootstrapToggle({
|
||||
on: "Enabled",
|
||||
off: "Disabled",
|
||||
size: "small",
|
||||
onstyle: "success",
|
||||
width: "80px"
|
||||
});
|
||||
statusEl.on("change", editGroup);
|
||||
|
||||
$("td:eq(2)", row).html('<input id="desc_' + data.id + '" class="form-control">');
|
||||
var desc = data.description !== null ? data.description : "";
|
||||
var descEl = $("#desc_" + data.id, row);
|
||||
descEl.val(desc);
|
||||
descEl.on("change", editGroup);
|
||||
|
||||
$("td:eq(3)", row).empty();
|
||||
if (data.id !== 0) {
|
||||
var button =
|
||||
'<button class="btn btn-danger btn-xs" type="button" id="deleteGroup_' +
|
||||
data.id +
|
||||
'">' +
|
||||
'<span class="glyphicon glyphicon-trash"></span>' +
|
||||
"</button>";
|
||||
$("td:eq(3)", row).html(button);
|
||||
}
|
||||
},
|
||||
dom:
|
||||
"<'row'<'col-sm-4'l><'col-sm-8'f>>" +
|
||||
"<'row'<'col-sm-12'<'table-responsive'tr>>>" +
|
||||
"<'row'<'col-sm-5'i><'col-sm-7'p>>",
|
||||
lengthMenu: [
|
||||
[10, 25, 50, 100, -1],
|
||||
[10, 25, 50, 100, "All"]
|
||||
],
|
||||
stateSave: true,
|
||||
stateSaveCallback: function(settings, data) {
|
||||
// Store current state in client's local storage area
|
||||
localStorage.setItem("groups-table", JSON.stringify(data));
|
||||
},
|
||||
stateLoadCallback: function() {
|
||||
// Receive previous state from client's local storage area
|
||||
var data = localStorage.getItem("groups-table");
|
||||
// Return if not available
|
||||
if (data === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
data = JSON.parse(data);
|
||||
// Always start on the first page to show most recent queries
|
||||
data.start = 0;
|
||||
// Always start with empty search field
|
||||
data.search.search = "";
|
||||
// Reset visibility of ID column
|
||||
data.columns[0].visible = false;
|
||||
// Apply loaded state to table
|
||||
return data;
|
||||
}
|
||||
});
|
||||
|
||||
table.on("order.dt", function() {
|
||||
var order = table.order();
|
||||
if (order[0][0] !== 0 || order[0][1] !== "asc") {
|
||||
$("#resetButton").show();
|
||||
} else {
|
||||
$("#resetButton").hide();
|
||||
}
|
||||
});
|
||||
$("#resetButton").on("click", function() {
|
||||
table.order([[0, "asc"]]).draw();
|
||||
$("#resetButton").hide();
|
||||
});
|
||||
});
|
||||
|
||||
function addGroup() {
|
||||
var name = $("#new_name").val();
|
||||
var desc = $("#new_desc").val();
|
||||
|
||||
utils.disableAll();
|
||||
utils.showAlert("info", "", "Adding group...", name);
|
||||
|
||||
if (name.length === 0) {
|
||||
utils.showAlert("warning", "", "Warning", "Please specify a group name");
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: "scripts/pi-hole/php/groups.php",
|
||||
method: "post",
|
||||
dataType: "json",
|
||||
data: { action: "add_group", name: name, desc: desc, token: token },
|
||||
success: function(response) {
|
||||
utils.enableAll();
|
||||
if (response.success) {
|
||||
utils.showAlert("success", "glyphicon glyphicon-plus", "Successfully added group", name);
|
||||
$("#new_name").val("");
|
||||
$("#new_desc").val("");
|
||||
table.ajax.reload();
|
||||
} else {
|
||||
utils.showAlert("error", "", "Error while adding new group", response.message);
|
||||
}
|
||||
},
|
||||
error: function(jqXHR, exception) {
|
||||
utils.enableAll();
|
||||
utils.showAlert("error", "", "Error while adding new group", jqXHR.responseText);
|
||||
console.log(exception);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function editGroup() {
|
||||
var elem = $(this).attr("id");
|
||||
var tr = $(this).closest("tr");
|
||||
var id = tr.attr("data-id");
|
||||
var name = tr.find("#name_" + id).val();
|
||||
var status = tr.find("#status_" + id).is(":checked") ? 1 : 0;
|
||||
var desc = tr.find("#desc_" + id).val();
|
||||
|
||||
var done = "edited";
|
||||
var not_done = "editing";
|
||||
switch (elem) {
|
||||
case "status_" + id:
|
||||
if (status === 0) {
|
||||
done = "disabled";
|
||||
not_done = "disabling";
|
||||
} else if (status === 1) {
|
||||
done = "enabled";
|
||||
not_done = "enabling";
|
||||
}
|
||||
|
||||
break;
|
||||
case "name_" + id:
|
||||
done = "edited name of";
|
||||
not_done = "editing name of";
|
||||
break;
|
||||
case "desc_" + id:
|
||||
done = "edited description of";
|
||||
not_done = "editing description of";
|
||||
break;
|
||||
default:
|
||||
alert("bad element or invalid data-id!");
|
||||
return;
|
||||
}
|
||||
|
||||
utils.disableAll();
|
||||
utils.showAlert("info", "", "Editing group...", name);
|
||||
$.ajax({
|
||||
url: "scripts/pi-hole/php/groups.php",
|
||||
method: "post",
|
||||
dataType: "json",
|
||||
data: {
|
||||
action: "edit_group",
|
||||
id: id,
|
||||
name: name,
|
||||
desc: desc,
|
||||
status: status,
|
||||
token: token
|
||||
},
|
||||
success: function(response) {
|
||||
utils.enableAll();
|
||||
if (response.success) {
|
||||
utils.showAlert(
|
||||
"success",
|
||||
"glyphicon glyphicon-pencil",
|
||||
"Successfully " + done + " group",
|
||||
name
|
||||
);
|
||||
} else {
|
||||
utils.showAlert(
|
||||
"error",
|
||||
"",
|
||||
"Error while " + not_done + " group with ID " + id,
|
||||
response.message
|
||||
);
|
||||
}
|
||||
},
|
||||
error: function(jqXHR, exception) {
|
||||
utils.enableAll();
|
||||
utils.showAlert(
|
||||
"error",
|
||||
"",
|
||||
"Error while " + not_done + " group with ID " + id,
|
||||
jqXHR.responseText
|
||||
);
|
||||
console.log(exception);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function deleteGroup() {
|
||||
var tr = $(this).closest("tr");
|
||||
var id = tr.attr("data-id");
|
||||
var name = tr.find("#name_" + id).val();
|
||||
|
||||
utils.disableAll();
|
||||
utils.showAlert("info", "", "Deleting group...", name);
|
||||
$.ajax({
|
||||
url: "scripts/pi-hole/php/groups.php",
|
||||
method: "post",
|
||||
dataType: "json",
|
||||
data: { action: "delete_group", id: id, token: token },
|
||||
success: function(response) {
|
||||
utils.enableAll();
|
||||
if (response.success) {
|
||||
utils.showAlert(
|
||||
"success",
|
||||
"glyphicon glyphicon-trash",
|
||||
"Successfully deleted group ",
|
||||
name
|
||||
);
|
||||
table
|
||||
.row(tr)
|
||||
.remove()
|
||||
.draw(false);
|
||||
} else {
|
||||
utils.showAlert("error", "", "Error while deleting group with ID " + id, response.message);
|
||||
}
|
||||
},
|
||||
error: function(jqXHR, exception) {
|
||||
utils.enableAll();
|
||||
utils.showAlert("error", "", "Error while deleting group with ID " + id, jqXHR.responseText);
|
||||
console.log(exception);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
/* 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. */
|
||||
// Remove JS warning
|
||||
var jswarn = document.getElementById("js-warn-exit");
|
||||
jswarn.parentNode.removeChild(jswarn);
|
||||
@@ -1,113 +1,94 @@
|
||||
/* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2019 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. */
|
||||
* (c) 2019 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. */
|
||||
|
||||
// This code has been taken from
|
||||
// https://datatables.net/plug-ins/sorting/ip-address
|
||||
jQuery.extend( jQuery.fn.dataTableExt.oSort,
|
||||
{
|
||||
"ip-address-pre": function ( a )
|
||||
{
|
||||
if (!a) { return 0 }
|
||||
var i, item;
|
||||
var m = a.split("."),
|
||||
n = a.split(":"),
|
||||
x = "",
|
||||
xa = "";
|
||||
if (m.length == 4)
|
||||
{
|
||||
// IPV4
|
||||
for(i = 0; i < m.length; i++)
|
||||
{
|
||||
item = m[i];
|
||||
|
||||
if(item.length == 1)
|
||||
{
|
||||
x += "00" + item;
|
||||
}
|
||||
else if(item.length == 2)
|
||||
{
|
||||
x += "0" + item;
|
||||
}
|
||||
else
|
||||
{
|
||||
x += item;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (n.length > 0)
|
||||
{
|
||||
// IPV6
|
||||
var count = 0;
|
||||
for(i = 0; i < n.length; i++)
|
||||
{
|
||||
item = n[i];
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
xa += ":";
|
||||
}
|
||||
|
||||
if(item.length === 0)
|
||||
{
|
||||
count += 0;
|
||||
}
|
||||
else if(item.length == 1)
|
||||
{
|
||||
xa += "000" + item;
|
||||
count += 4;
|
||||
}
|
||||
else if(item.length == 2)
|
||||
{
|
||||
xa += "00" + item;
|
||||
count += 4;
|
||||
}
|
||||
else if(item.length == 3)
|
||||
{
|
||||
xa += "0" + item;
|
||||
count += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
xa += item;
|
||||
count += 4;
|
||||
}
|
||||
}
|
||||
|
||||
// Padding the ::
|
||||
n = xa.split(":");
|
||||
var paddDone = 0;
|
||||
|
||||
for (i = 0; i < n.length; i++)
|
||||
{
|
||||
item = n[i];
|
||||
if (item.length === 0 && paddDone === 0)
|
||||
{
|
||||
for(var padding = 0 ; padding < (32-count) ; padding++)
|
||||
{
|
||||
x += "0";
|
||||
paddDone = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
x += item;
|
||||
}
|
||||
}
|
||||
}
|
||||
return x;
|
||||
},
|
||||
|
||||
"ip-address-asc": function ( a, b )
|
||||
{
|
||||
return ((a < b) ? -1 : ((a > b) ? 1 : 0));
|
||||
},
|
||||
|
||||
"ip-address-desc": function ( a, b )
|
||||
{
|
||||
return ((a < b) ? 1 : ((a > b) ? -1 : 0));
|
||||
jQuery.extend(jQuery.fn.dataTableExt.oSort, {
|
||||
"ip-address-pre": function(a) {
|
||||
if (!a) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var i, item;
|
||||
// Use the first IP in case there is a list of IPs
|
||||
// for a given device
|
||||
if (Array.isArray(a)) {
|
||||
a = a[0];
|
||||
}
|
||||
|
||||
var m = a.split("."),
|
||||
n = a.split(":"),
|
||||
x = "",
|
||||
xa = "";
|
||||
if (m.length === 4) {
|
||||
// IPV4
|
||||
for (i = 0; i < m.length; i++) {
|
||||
item = m[i];
|
||||
|
||||
if (item.length === 1) {
|
||||
x += "00" + item;
|
||||
} else if (item.length === 2) {
|
||||
x += "0" + item;
|
||||
} else {
|
||||
x += item;
|
||||
}
|
||||
}
|
||||
} else if (n.length > 0) {
|
||||
// IPV6
|
||||
var count = 0;
|
||||
for (i = 0; i < n.length; i++) {
|
||||
item = n[i];
|
||||
|
||||
if (i > 0) {
|
||||
xa += ":";
|
||||
}
|
||||
|
||||
if (item.length === 0) {
|
||||
count += 0;
|
||||
} else if (item.length === 1) {
|
||||
xa += "000" + item;
|
||||
count += 4;
|
||||
} else if (item.length === 2) {
|
||||
xa += "00" + item;
|
||||
count += 4;
|
||||
} else if (item.length === 3) {
|
||||
xa += "0" + item;
|
||||
count += 4;
|
||||
} else {
|
||||
xa += item;
|
||||
count += 4;
|
||||
}
|
||||
}
|
||||
|
||||
// Padding the ::
|
||||
n = xa.split(":");
|
||||
var paddDone = 0;
|
||||
|
||||
for (i = 0; i < n.length; i++) {
|
||||
item = n[i];
|
||||
if (item.length === 0 && paddDone === 0) {
|
||||
for (var padding = 0; padding < 32 - count; padding++) {
|
||||
x += "0";
|
||||
paddDone = 1;
|
||||
}
|
||||
} else {
|
||||
x += item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return x;
|
||||
},
|
||||
|
||||
"ip-address-asc": function(a, b) {
|
||||
return a < b ? -1 : a > b ? 1 : 0;
|
||||
},
|
||||
|
||||
"ip-address-desc": function(a, b) {
|
||||
return a < b ? 1 : a > b ? -1 : 0;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,248 +0,0 @@
|
||||
/* 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. */
|
||||
// IE likes to cache too much :P
|
||||
$.ajaxSetup({cache: false});
|
||||
|
||||
// Get PHP info
|
||||
var token = $("#token").html();
|
||||
var listType = $("#list-type").html();
|
||||
var fullName = listType === "white" ? "Whitelist" : "Blacklist";
|
||||
|
||||
function sub(index, entry, arg) {
|
||||
var domain = $("#list #"+index);
|
||||
var locallistType = listType;
|
||||
if(arg === "regex")
|
||||
{
|
||||
locallistType = "regex";
|
||||
domain = $("#list-regex #"+index);
|
||||
}
|
||||
domain.hide("highlight");
|
||||
$.ajax({
|
||||
url: "scripts/pi-hole/php/sub.php",
|
||||
method: "post",
|
||||
data: {"domain":entry, "list":locallistType, "token":token},
|
||||
success: function(response) {
|
||||
if(response.length !== 0){
|
||||
return;
|
||||
}
|
||||
domain.remove();
|
||||
},
|
||||
error: function(jqXHR, exception) {
|
||||
alert("Failed to remove the domain!");
|
||||
domain.show({queue:true});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function refresh(fade) {
|
||||
var listw;
|
||||
var list = $("#list");
|
||||
if(listType === "black")
|
||||
{
|
||||
listw = $("#list-regex");
|
||||
}
|
||||
if(fade) {
|
||||
list.fadeOut(100);
|
||||
if(listw)
|
||||
{
|
||||
listw.fadeOut(100);
|
||||
}
|
||||
}
|
||||
$.ajax({
|
||||
url: "scripts/pi-hole/php/get.php",
|
||||
method: "get",
|
||||
data: {"list":listType},
|
||||
success: function(response) {
|
||||
list.html("");
|
||||
if(listw)
|
||||
{
|
||||
listw.html("");
|
||||
}
|
||||
var data = JSON.parse(response);
|
||||
|
||||
if(data.length === 0) {
|
||||
$("h3").hide();
|
||||
if(listw)
|
||||
{
|
||||
listw.html("<div class=\"alert alert-info\" role=\"alert\">Your " + fullName + " is empty!</div>");
|
||||
}
|
||||
else
|
||||
{
|
||||
list.html("<div class=\"alert alert-info\" role=\"alert\">Your " + fullName + " is empty!</div>");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$("h3").show();
|
||||
data[0] = data[0].sort();
|
||||
data[0].forEach(function (entry, index) {
|
||||
// Whitelist entry or Blacklist (exact entry) are in the zero-th
|
||||
// array returned by get.php
|
||||
list.append(
|
||||
"<li id=\"" + index + "\" class=\"list-group-item clearfix\">" + entry +
|
||||
"<button class=\"btn btn-danger btn-xs pull-right\" type=\"button\">" +
|
||||
"<span class=\"glyphicon glyphicon-trash\"></span></button></li>");
|
||||
// Handle button
|
||||
$("#list #"+index+"").on("click", "button", function() {
|
||||
sub(index, entry, "exact");
|
||||
});
|
||||
});
|
||||
|
||||
// Add regex domains if present in returned list data
|
||||
if(data.length === 2)
|
||||
{
|
||||
data[1] = data[1].sort();
|
||||
data[1].forEach(function (entry, index) {
|
||||
// Whitelist entry or Blacklist (exact entry) are in the zero-th
|
||||
// array returned by get.php
|
||||
listw.append(
|
||||
"<li id=\"" + index + "\" class=\"list-group-item clearfix\">" + entry +
|
||||
"<button class=\"btn btn-danger btn-xs pull-right\" type=\"button\">" +
|
||||
"<span class=\"glyphicon glyphicon-trash\"></span></button></li>");
|
||||
// Handle button
|
||||
$("#list-regex #"+index+"").on("click", "button", function() {
|
||||
sub(index, entry, "regex");
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
list.fadeIn(100);
|
||||
if(listw)
|
||||
{
|
||||
listw.fadeIn(100);
|
||||
}
|
||||
},
|
||||
error: function(jqXHR, exception) {
|
||||
$("#alFailure").show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
window.onload = refresh(false);
|
||||
|
||||
function add(arg) {
|
||||
var locallistType = listType;
|
||||
var domain = $("#domain");
|
||||
var wild = false;
|
||||
if(domain.val().length === 0){
|
||||
return;
|
||||
}
|
||||
if(arg === "wild" || arg === "regex")
|
||||
{
|
||||
locallistType = arg;
|
||||
wild = true;
|
||||
}
|
||||
|
||||
var alInfo = $("#alInfo");
|
||||
var alSuccess = $("#alSuccess");
|
||||
var alFailure = $("#alFailure");
|
||||
var alWarning = $("#alWarning");
|
||||
var err = $("#err");
|
||||
var warn = $("#warn");
|
||||
alInfo.show();
|
||||
alSuccess.hide();
|
||||
alFailure.hide();
|
||||
alWarning.hide();
|
||||
$.ajax({
|
||||
url: "scripts/pi-hole/php/add.php",
|
||||
method: "post",
|
||||
data: {"domain":domain.val().trim(), "list":locallistType, "token":token},
|
||||
success: function(response) {
|
||||
if (!wild && response.indexOf(" already exists in ") !== -1) {
|
||||
alWarning.show();
|
||||
warn.html(response);
|
||||
alWarning.delay(8000).fadeOut(2000, function() {
|
||||
alWarning.hide();
|
||||
});
|
||||
alInfo.delay(8000).fadeOut(2000, function() {
|
||||
alInfo.hide();
|
||||
});
|
||||
} else if (!wild && response.indexOf("] Pi-hole blocking is ") === -1 ||
|
||||
wild && response.length > 1) {
|
||||
alFailure.show();
|
||||
err.html(response);
|
||||
alFailure.delay(8000).fadeOut(2000, function() {
|
||||
alFailure.hide();
|
||||
});
|
||||
alInfo.delay(8000).fadeOut(2000, function() {
|
||||
alInfo.hide();
|
||||
});
|
||||
} else {
|
||||
alSuccess.show();
|
||||
alSuccess.delay(1000).fadeOut(2000, function() {
|
||||
alSuccess.hide();
|
||||
});
|
||||
alInfo.delay(1000).fadeOut(2000, function() {
|
||||
alInfo.hide();
|
||||
});
|
||||
domain.val("");
|
||||
refresh(true);
|
||||
}
|
||||
},
|
||||
error: function(jqXHR, exception) {
|
||||
alFailure.show();
|
||||
err.html("");
|
||||
alFailure.delay(1000).fadeOut(2000, function() {
|
||||
alFailure.hide();
|
||||
});
|
||||
alInfo.delay(1000).fadeOut(2000, function() {
|
||||
alInfo.hide();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Handle enter button for adding domains
|
||||
$(document).keypress(function(e) {
|
||||
if(e.which === 13 && $("#domain").is(":focus")) {
|
||||
// Enter was pressed, and the input has focus
|
||||
add("exact");
|
||||
}
|
||||
});
|
||||
|
||||
// Handle buttons
|
||||
$("#btnAdd").on("click", function() {
|
||||
add("exact");
|
||||
});
|
||||
|
||||
$("#btnAddWildcard").on("click", function() {
|
||||
add("wild");
|
||||
});
|
||||
|
||||
$("#btnAddRegex").on("click", function() {
|
||||
add("regex");
|
||||
});
|
||||
|
||||
$("#btnRefresh").on("click", function() {
|
||||
refresh(true);
|
||||
});
|
||||
|
||||
// Handle hiding of alerts
|
||||
$(function(){
|
||||
$("[data-hide]").on("click", function(){
|
||||
$(this).closest("." + $(this).attr("data-hide")).hide();
|
||||
});
|
||||
});
|
||||
|
||||
// Wrap form-group's buttons to next line when viewed on a small screen
|
||||
$(window).on("resize",function() {
|
||||
if ($(window).width() < 991) {
|
||||
$(".form-group.input-group").removeClass("input-group").addClass("input-group-block");
|
||||
$(".form-group.input-group-block > input").css("margin-bottom", "5px");
|
||||
$(".form-group.input-group-block > .input-group-btn").removeClass("input-group-btn").addClass("btn-block text-center");
|
||||
}
|
||||
else {
|
||||
$(".form-group.input-group-block").removeClass("input-group-block").addClass( "input-group" );
|
||||
$(".form-group.input-group > input").css("margin-bottom","");
|
||||
$(".form-group.input-group > .btn-block.text-center").removeClass("btn-block text-center").addClass("input-group-btn");
|
||||
}
|
||||
});
|
||||
$(document).ready(function() {
|
||||
$(window).trigger("resize");
|
||||
});
|
||||
@@ -1,173 +1,204 @@
|
||||
/* 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. */
|
||||
* (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. */
|
||||
|
||||
/* global moment:false */
|
||||
|
||||
var tableApi;
|
||||
|
||||
var APIstring = "api_db.php?network";
|
||||
|
||||
function refreshData() {
|
||||
tableApi.ajax.url(APIstring).load();
|
||||
}
|
||||
// How many IPs do we show at most per device?
|
||||
var MAXIPDISPLAY = 3;
|
||||
|
||||
function openInNewTab(url) {
|
||||
var win = window.open(url, "_blank");
|
||||
win.focus();
|
||||
}
|
||||
|
||||
function handleAjaxError( xhr, textStatus, error ) {
|
||||
if ( textStatus === "timeout" )
|
||||
{
|
||||
alert( "The server took too long to send the data." );
|
||||
}
|
||||
else if(xhr.responseText.indexOf("Connection refused") >= 0)
|
||||
{
|
||||
alert( "An error occured while loading the data: Connection refused. Is FTL running?" );
|
||||
}
|
||||
else
|
||||
{
|
||||
alert( "An unknown error occured while loading the data.\n"+xhr.responseText );
|
||||
}
|
||||
$("#network-entries_processing").hide();
|
||||
tableApi.clear();
|
||||
tableApi.draw();
|
||||
}
|
||||
|
||||
function getTimestamp(){
|
||||
if (!Date.now)
|
||||
{
|
||||
Date.now = function() { return new Date().getTime(); };
|
||||
function handleAjaxError(xhr, textStatus) {
|
||||
if (textStatus === "timeout") {
|
||||
alert("The server took too long to send the data.");
|
||||
} else if (xhr.responseText.indexOf("Connection refused") >= 0) {
|
||||
alert("An error occured while loading the data: Connection refused. Is FTL running?");
|
||||
} else {
|
||||
alert("An unknown error occured while loading the data.\n" + xhr.responseText);
|
||||
}
|
||||
|
||||
$("#network-entries_processing").hide();
|
||||
tableApi.clear();
|
||||
tableApi.draw();
|
||||
}
|
||||
|
||||
function getTimestamp() {
|
||||
if (!Date.now) {
|
||||
Date.now = function() {
|
||||
return new Date().getTime();
|
||||
};
|
||||
}
|
||||
|
||||
return Math.floor(Date.now() / 1000);
|
||||
}
|
||||
|
||||
function valueToHex(c) {
|
||||
var hex = Math.round(c).toString(16);
|
||||
return hex.length === 1 ? "0" + hex : hex;
|
||||
var hex = Math.round(c).toString(16);
|
||||
return hex.length === 1 ? "0" + hex : hex;
|
||||
}
|
||||
|
||||
function rgbToHex(values) {
|
||||
return "#" + valueToHex(values[0])
|
||||
+ valueToHex(values[1])
|
||||
+ valueToHex(values[2]);
|
||||
return "#" + valueToHex(values[0]) + valueToHex(values[1]) + valueToHex(values[2]);
|
||||
}
|
||||
|
||||
function mixColors(ratio, rgb1, rgb2)
|
||||
{
|
||||
return [(1.0-ratio)*rgb1[0]+ratio*rgb2[0],
|
||||
(1.0-ratio)*rgb1[1]+ratio*rgb2[1],
|
||||
(1.0-ratio)*rgb1[2]+ratio*rgb2[2]];
|
||||
function mixColors(ratio, rgb1, rgb2) {
|
||||
return [
|
||||
(1.0 - ratio) * rgb1[0] + ratio * rgb2[0],
|
||||
(1.0 - ratio) * rgb1[1] + ratio * rgb2[1],
|
||||
(1.0 - ratio) * rgb1[2] + ratio * rgb2[2]
|
||||
];
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
tableApi = $("#network-entries").DataTable( {
|
||||
"rowCallback": function( row, data, index )
|
||||
{
|
||||
var color, mark, lastQuery = parseInt(data["lastQuery"]);
|
||||
if(lastQuery > 0)
|
||||
{
|
||||
var diff = getTimestamp()-lastQuery;
|
||||
if(diff <= 86400)
|
||||
{
|
||||
// Last query came in within the last 24 hours (24*60*60 = 86400)
|
||||
// Color: light-green to light-yellow
|
||||
var ratio = 1e0*diff/86400;
|
||||
var lightgreen = [0xE7, 0xFF, 0xDE];
|
||||
var lightyellow = [0xFF, 0xFF, 0xDF];
|
||||
color = rgbToHex(mixColors(ratio, lightgreen, lightyellow));
|
||||
mark = "✔";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Last query was longer than 24 hours ago
|
||||
// Color: light-orange
|
||||
color = "#FFEDD9";
|
||||
mark = "<strong>?</strong>";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This client has never sent a query to Pi-hole, color light-red
|
||||
color = "#FFBFAA";
|
||||
mark = "✘";
|
||||
}
|
||||
// Set determined background color
|
||||
$(row).css("background-color", color);
|
||||
$("td:eq(7)", row).html(mark);
|
||||
tableApi = $("#network-entries").DataTable({
|
||||
rowCallback: function(row, data) {
|
||||
var color,
|
||||
mark,
|
||||
lastQuery = parseInt(data.lastQuery);
|
||||
if (lastQuery > 0) {
|
||||
var diff = getTimestamp() - lastQuery;
|
||||
if (diff <= 86400) {
|
||||
// Last query came in within the last 24 hours (24*60*60 = 86400)
|
||||
// Color: light-green to light-yellow
|
||||
var ratio = Number(diff) / 86400;
|
||||
var lightgreen = [0xe7, 0xff, 0xde];
|
||||
var lightyellow = [0xff, 0xff, 0xdf];
|
||||
color = rgbToHex(mixColors(ratio, lightgreen, lightyellow));
|
||||
mark = "✔";
|
||||
} else {
|
||||
// Last query was longer than 24 hours ago
|
||||
// Color: light-orange
|
||||
color = "#ffedd9";
|
||||
mark = "<strong>?</strong>";
|
||||
}
|
||||
} else {
|
||||
// This client has never sent a query to Pi-hole, color light-red
|
||||
color = "#ffbfaa";
|
||||
mark = "✘";
|
||||
}
|
||||
|
||||
// Insert "Never" into Last Query field when we have
|
||||
// never seen a query from this device
|
||||
if(data["lastQuery"] === 0)
|
||||
{
|
||||
$("td:eq(5)", row).html("Never");
|
||||
}
|
||||
// Set determined background color
|
||||
$(row).css("background-color", color);
|
||||
$("td:eq(7)", row).html(mark);
|
||||
|
||||
// Set hostname to "N/A" if not available
|
||||
if(!data["name"] || data["name"].length < 1)
|
||||
{
|
||||
$("td:eq(3)", row).html("N/A");
|
||||
}
|
||||
// Insert "Never" into Last Query field when we have
|
||||
// never seen a query from this device
|
||||
if (data.lastQuery === 0) {
|
||||
$("td:eq(5)", row).html("Never");
|
||||
}
|
||||
|
||||
// Set number of queries to localized string (add thousand separators)
|
||||
$("td:eq(6)", row).html(data["numQueries"].toLocaleString());
|
||||
// Set hostname to "unknown" if not available
|
||||
if (!data.name || data.name.length === 0) {
|
||||
$("td:eq(3)", row).html("<em>unknown</em>");
|
||||
}
|
||||
|
||||
// Client -> jump to Query Log on click
|
||||
$("td:eq(0)", row).click( function () { openInNewTab("/admin/queries.php?client="+this.innerHTML); } );
|
||||
$("td:eq(0)", row).css("cursor","pointer");
|
||||
$("td:eq(0)", row).hover(
|
||||
function () { this.title="Click to show recent queries made by "+this.innerHTML; this.style.color="#72afd2"; },
|
||||
function () { this.style.color=""; } );
|
||||
// Set number of queries to localized string (add thousand separators)
|
||||
$("td:eq(6)", row).html(data.numQueries.toLocaleString());
|
||||
|
||||
// MAC + Vendor field if available
|
||||
if(data["macVendor"] && data["macVendor"].length > 0)
|
||||
{
|
||||
$("td:eq(1)", row).html(data["hwaddr"]+"<br/>"+data["macVendor"]);
|
||||
}
|
||||
var ips = [];
|
||||
var maxiter = Math.min(data.ip.length, MAXIPDISPLAY);
|
||||
for (var index = 0; index < maxiter; index++) {
|
||||
var ip = data.ip[index];
|
||||
ips.push('<a href="queries.php?client=' + ip + '">' + ip + "</a>");
|
||||
}
|
||||
|
||||
},
|
||||
dom: "<'row'<'col-sm-12'f>>" +
|
||||
"<'row'<'col-sm-4'l><'col-sm-8'p>>" +
|
||||
"<'row'<'col-sm-12'<'table-responsive'tr>>>" +
|
||||
"<'row'<'col-sm-5'i><'col-sm-7'p>>",
|
||||
"ajax": {"url": APIstring, "error": handleAjaxError, "dataSrc": "network" },
|
||||
"autoWidth" : false,
|
||||
"processing": true,
|
||||
"order" : [[5, "desc"]],
|
||||
"columns": [
|
||||
{data: "ip", "type": "ip-address", "width" : "10%", "render": $.fn.dataTable.render.text() },
|
||||
{data: "hwaddr", "width" : "10%", "render": $.fn.dataTable.render.text() },
|
||||
{data: "interface", "width" : "4%", "render": $.fn.dataTable.render.text() },
|
||||
{data: "name", "width" : "15%", "render": $.fn.dataTable.render.text() },
|
||||
{data: "firstSeen", "width" : "8%", "render": function (data, type, full, meta) { if(type === "display"){return moment.unix(data).format("Y-MM-DD [<br class='hidden-lg'>]HH:mm:ss z");}else{return data;} }},
|
||||
{data: "lastQuery", "width" : "8%", "render": function (data, type, full, meta) { if(type === "display"){return moment.unix(data).format("Y-MM-DD [<br class='hidden-lg'>]HH:mm:ss z");}else{return data;} }},
|
||||
{data: "numQueries", "width" : "9%", "render": $.fn.dataTable.render.text() },
|
||||
{data: "", "width" : "6%", "orderable" : false }
|
||||
],
|
||||
"lengthMenu": [[10, 25, 50, 100, -1], [10, 25, 50, 100, "All"]],
|
||||
"stateSave": true,
|
||||
stateSaveCallback: function(settings, data) {
|
||||
// Store current state in client's local storage area
|
||||
localStorage.setItem("network_table", JSON.stringify(data));
|
||||
},
|
||||
stateLoadCallback: function(settings) {
|
||||
// Receive previous state from client's local storage area
|
||||
var data = localStorage.getItem("network_table");
|
||||
// Return if not available
|
||||
if(data === null){ return null; }
|
||||
data = JSON.parse(data);
|
||||
// Always start on the first page
|
||||
data["start"] = 0;
|
||||
// Always start with empty search field
|
||||
data["search"]["search"] = "";
|
||||
// Apply loaded state to table
|
||||
return data;
|
||||
},
|
||||
"columnDefs": [ {
|
||||
"targets": -1,
|
||||
"data": null,
|
||||
"defaultContent": ""
|
||||
} ]
|
||||
});
|
||||
} );
|
||||
if (data.ip.length > MAXIPDISPLAY) {
|
||||
// We hit the maximum above, add "..." to symbolize we would
|
||||
// have more to show here
|
||||
ips.push("...");
|
||||
}
|
||||
|
||||
$("td:eq(0)", row).html(ips.join("<br>"));
|
||||
$("td:eq(0)", row).hover(function() {
|
||||
this.title = data.ip.join("\n");
|
||||
});
|
||||
|
||||
// MAC + Vendor field if available
|
||||
if (data.macVendor && data.macVendor.length > 0) {
|
||||
$("td:eq(1)", row).html(data.hwaddr + "<br/>" + data.macVendor);
|
||||
}
|
||||
|
||||
// Hide mock MAC addresses
|
||||
if (data.hwaddr.startsWith("ip-")) {
|
||||
$("td:eq(1)", row).text("N/A");
|
||||
}
|
||||
},
|
||||
dom:
|
||||
"<'row'<'col-sm-12'f>>" +
|
||||
"<'row'<'col-sm-4'l><'col-sm-8'p>>" +
|
||||
"<'row'<'col-sm-12'<'table-responsive'tr>>>" +
|
||||
"<'row'<'col-sm-5'i><'col-sm-7'p>>",
|
||||
ajax: { url: APIstring, error: handleAjaxError, dataSrc: "network" },
|
||||
autoWidth: false,
|
||||
processing: true,
|
||||
order: [[5, "desc"]],
|
||||
columns: [
|
||||
{ data: "ip", type: "ip-address", width: "10%", render: $.fn.dataTable.render.text() },
|
||||
{ data: "hwaddr", width: "10%", render: $.fn.dataTable.render.text() },
|
||||
{ data: "interface", width: "4%", render: $.fn.dataTable.render.text() },
|
||||
{ data: "name", width: "15%", render: $.fn.dataTable.render.text() },
|
||||
{
|
||||
data: "firstSeen",
|
||||
width: "8%",
|
||||
render: function(data, type) {
|
||||
if (type === "display") {
|
||||
return moment.unix(data).format("Y-MM-DD [<br class='hidden-lg'>]HH:mm:ss z");
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
},
|
||||
{
|
||||
data: "lastQuery",
|
||||
width: "8%",
|
||||
render: function(data, type) {
|
||||
if (type === "display") {
|
||||
return moment.unix(data).format("Y-MM-DD [<br class='hidden-lg'>]HH:mm:ss z");
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
},
|
||||
{ data: "numQueries", width: "9%", render: $.fn.dataTable.render.text() },
|
||||
{ data: "", width: "6%", orderable: false }
|
||||
],
|
||||
lengthMenu: [
|
||||
[10, 25, 50, 100, -1],
|
||||
[10, 25, 50, 100, "All"]
|
||||
],
|
||||
stateSave: true,
|
||||
stateSaveCallback: function(settings, data) {
|
||||
// Store current state in client's local storage area
|
||||
localStorage.setItem("network_table", JSON.stringify(data));
|
||||
},
|
||||
stateLoadCallback: function() {
|
||||
// Receive previous state from client's local storage area
|
||||
var data = localStorage.getItem("network_table");
|
||||
// Return if not available
|
||||
if (data === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
data = JSON.parse(data);
|
||||
// Always start on the first page
|
||||
data.start = 0;
|
||||
// Always start with empty search field
|
||||
data.search.search = "";
|
||||
// Apply loaded state to table
|
||||
return data;
|
||||
},
|
||||
columnDefs: [
|
||||
{
|
||||
targets: -1,
|
||||
data: null,
|
||||
defaultContent: ""
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,411 +1,533 @@
|
||||
/* 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. */
|
||||
* (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. */
|
||||
|
||||
/* global moment:false */
|
||||
|
||||
var tableApi;
|
||||
|
||||
function escapeRegex(text) {
|
||||
var map = {
|
||||
"(": "\\(",
|
||||
")": "\\)",
|
||||
".": "\\.",
|
||||
};
|
||||
return text.replace(/[().]/g, function(m) { return map[m]; });
|
||||
}
|
||||
function add(domain, list) {
|
||||
var token = $("#token").text();
|
||||
var alertModal = $("#alertModal");
|
||||
var alProcessing = alertModal.find(".alProcessing");
|
||||
var alSuccess = alertModal.find(".alSuccess");
|
||||
var alFailure = alertModal.find(".alFailure");
|
||||
var alNetworkErr = alertModal.find(".alFailure #alNetErr");
|
||||
var alCustomErr = alertModal.find(".alFailure #alCustomErr");
|
||||
var alList = "#alList";
|
||||
var alDomain = "#alDomain";
|
||||
|
||||
function refreshData() {
|
||||
tableApi.ajax.url("api.php?getAllQueries").load();
|
||||
// updateSessionTimer();
|
||||
}
|
||||
// Exit the function here if the Modal is already shown (multiple running interlock)
|
||||
if (alertModal.css("display") !== "none") {
|
||||
return;
|
||||
}
|
||||
|
||||
function add(domain,list) {
|
||||
var token = $("#token").html();
|
||||
var alertModal = $("#alertModal");
|
||||
var alProcessing = alertModal.find(".alProcessing");
|
||||
var alSuccess = alertModal.find(".alSuccess");
|
||||
var alFailure = alertModal.find(".alFailure");
|
||||
var alNetworkErr = alertModal.find(".alFailure #alNetErr");
|
||||
var alCustomErr = alertModal.find(".alFailure #alCustomErr");
|
||||
var alList = "#alList";
|
||||
var alDomain = "#alDomain";
|
||||
var listtype;
|
||||
if (list === "white") {
|
||||
listtype = "Whitelist";
|
||||
} else {
|
||||
listtype = "Blacklist";
|
||||
}
|
||||
|
||||
// Exit the function here if the Modal is already shown (multiple running interlock)
|
||||
if (alertModal.css("display") !== "none") {
|
||||
return;
|
||||
}
|
||||
alProcessing.children(alDomain).html(domain);
|
||||
alProcessing.children(alList).html(listtype);
|
||||
alertModal.modal("show");
|
||||
|
||||
var listtype;
|
||||
if (list === "white") {
|
||||
listtype = "Whitelist";
|
||||
} else {
|
||||
listtype = "Blacklist";
|
||||
}
|
||||
alProcessing.children(alDomain).html(domain);
|
||||
alProcessing.children(alList).html(listtype);
|
||||
alertModal.modal("show");
|
||||
|
||||
// add Domain to List after Modal has faded in
|
||||
alertModal.one("shown.bs.modal", function() {
|
||||
$.ajax({
|
||||
url: "scripts/pi-hole/php/add.php",
|
||||
method: "post",
|
||||
data: {"domain":domain, "list":list, "token":token},
|
||||
success: function(response) {
|
||||
alProcessing.hide();
|
||||
if (response.indexOf("not a valid argument") >= 0 ||
|
||||
response.indexOf("is not a valid domain") >= 0 ||
|
||||
response.indexOf("Wrong token") >= 0)
|
||||
{
|
||||
// Failure
|
||||
alNetworkErr.hide();
|
||||
alCustomErr.html(response.replace("[✗]", ""));
|
||||
alFailure.fadeIn(1000);
|
||||
setTimeout(function() { alertModal.modal("hide"); }, 3000);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Success
|
||||
alSuccess.children(alDomain).html(domain);
|
||||
alSuccess.children(alList).html(listtype);
|
||||
alSuccess.fadeIn(1000);
|
||||
setTimeout(function() { alertModal.modal("hide"); }, 2000);
|
||||
}
|
||||
},
|
||||
error: function(jqXHR, exception) {
|
||||
// Network Error
|
||||
alProcessing.hide();
|
||||
alNetworkErr.show();
|
||||
alFailure.fadeIn(1000);
|
||||
setTimeout(function() { alertModal.modal("hide"); }, 3000);
|
||||
}
|
||||
});
|
||||
// add Domain to List after Modal has faded in
|
||||
alertModal.one("shown.bs.modal", function() {
|
||||
$.ajax({
|
||||
url: "scripts/pi-hole/php/add.php",
|
||||
method: "post",
|
||||
data: { domain: domain, list: list, token: token },
|
||||
success: function(response) {
|
||||
alProcessing.hide();
|
||||
if (
|
||||
response.indexOf("not a valid argument") >= 0 ||
|
||||
response.indexOf("is not a valid domain") >= 0 ||
|
||||
response.indexOf("Wrong token") >= 0
|
||||
) {
|
||||
// Failure
|
||||
alNetworkErr.hide();
|
||||
alCustomErr.html(response.replace("[✗]", ""));
|
||||
alFailure.fadeIn(1000);
|
||||
setTimeout(function() {
|
||||
alertModal.modal("hide");
|
||||
}, 3000);
|
||||
} else {
|
||||
// Success
|
||||
alSuccess.children(alDomain).html(domain);
|
||||
alSuccess.children(alList).html(listtype);
|
||||
alSuccess.fadeIn(1000);
|
||||
setTimeout(function() {
|
||||
alertModal.modal("hide");
|
||||
}, 2000);
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
// Network Error
|
||||
alProcessing.hide();
|
||||
alNetworkErr.show();
|
||||
alFailure.fadeIn(1000);
|
||||
setTimeout(function() {
|
||||
alertModal.modal("hide");
|
||||
}, 3000);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Reset Modal after it has faded out
|
||||
alertModal.one("hidden.bs.modal", function() {
|
||||
alProcessing.show();
|
||||
alSuccess.add(alFailure).hide();
|
||||
alProcessing.add(alSuccess).children(alDomain).html("").end().children(alList).html("");
|
||||
alCustomErr.html("");
|
||||
});
|
||||
// Reset Modal after it has faded out
|
||||
alertModal.one("hidden.bs.modal", function() {
|
||||
alProcessing.show();
|
||||
alSuccess.add(alFailure).hide();
|
||||
alProcessing
|
||||
.add(alSuccess)
|
||||
.children(alDomain)
|
||||
.html("")
|
||||
.end()
|
||||
.children(alList)
|
||||
.html("");
|
||||
alCustomErr.html("");
|
||||
});
|
||||
}
|
||||
|
||||
function handleAjaxError( xhr, textStatus, error ) {
|
||||
if ( textStatus === "timeout" )
|
||||
{
|
||||
alert( "The server took too long to send the data." );
|
||||
}
|
||||
else if(xhr.responseText.indexOf("Connection refused") >= 0)
|
||||
{
|
||||
alert( "An error occured while loading the data: Connection refused. Is FTL running?" );
|
||||
}
|
||||
else
|
||||
{
|
||||
alert( "An unknown error occured while loading the data.\n"+xhr.responseText );
|
||||
}
|
||||
$("#all-queries_processing").hide();
|
||||
tableApi.clear();
|
||||
tableApi.draw();
|
||||
function handleAjaxError(xhr, textStatus) {
|
||||
if (textStatus === "timeout") {
|
||||
alert("The server took too long to send the data.");
|
||||
} else if (xhr.responseText.indexOf("Connection refused") >= 0) {
|
||||
alert("An error occured while loading the data: Connection refused. Is FTL running?");
|
||||
} else {
|
||||
alert("An unknown error occured while loading the data.\n" + xhr.responseText);
|
||||
}
|
||||
|
||||
$("#all-queries_processing").hide();
|
||||
tableApi.clear();
|
||||
tableApi.draw();
|
||||
}
|
||||
|
||||
function autofilter(){
|
||||
return document.getElementById("autofilter").checked;
|
||||
function autofilter() {
|
||||
return $("#autofilter").prop("checked");
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
var status;
|
||||
|
||||
// Do we want to filter queries?
|
||||
var GETDict = {};
|
||||
location.search.substr(1).split("&").forEach(function(item) {GETDict[item.split("=")[0]] = item.split("=")[1];});
|
||||
|
||||
var APIstring = "api.php?getAllQueries";
|
||||
|
||||
if("from" in GETDict && "until" in GETDict)
|
||||
{
|
||||
APIstring += "&from="+GETDict["from"];
|
||||
APIstring += "&until="+GETDict["until"];
|
||||
}
|
||||
else if("client" in GETDict)
|
||||
{
|
||||
APIstring += "&client="+GETDict["client"];
|
||||
}
|
||||
else if("domain" in GETDict)
|
||||
{
|
||||
APIstring += "&domain="+GETDict["domain"];
|
||||
}
|
||||
else if("querytype" in GETDict)
|
||||
{
|
||||
APIstring += "&querytype="+GETDict["querytype"];
|
||||
}
|
||||
else if("forwarddest" in GETDict)
|
||||
{
|
||||
APIstring += "&forwarddest="+GETDict["forwarddest"];
|
||||
}
|
||||
// If we don't ask filtering and also not for all queries, just request the most recent 100 queries
|
||||
else if(!("all" in GETDict))
|
||||
{
|
||||
APIstring += "=100";
|
||||
}
|
||||
|
||||
tableApi = $("#all-queries").DataTable( {
|
||||
"rowCallback": function( row, data, index ){
|
||||
// DNSSEC status
|
||||
var dnssec_status;
|
||||
switch (data[5])
|
||||
{
|
||||
case "1":
|
||||
dnssec_status = "<br><span style=\"color:green\">SECURE</span>";
|
||||
break;
|
||||
case "2":
|
||||
dnssec_status = "<br><span style=\"color:orange\">INSECURE</span>";
|
||||
break;
|
||||
case "3":
|
||||
dnssec_status = "<br><span style=\"color:red\">BOGUS</span>";
|
||||
break;
|
||||
case "4":
|
||||
dnssec_status = "<br><span style=\"color:red\">ABANDONED</span>";
|
||||
break;
|
||||
case "5":
|
||||
dnssec_status = "<br><span style=\"color:orange\">UNKNOWN</span>";
|
||||
break;
|
||||
default: // No DNSSEC
|
||||
dnssec_status = "";
|
||||
}
|
||||
|
||||
// Query status
|
||||
var blocked, fieldtext, buttontext, color;
|
||||
switch (data[4])
|
||||
{
|
||||
case "1":
|
||||
blocked = true;
|
||||
color = "red";
|
||||
fieldtext = "Blocked (gravity)";
|
||||
buttontext = "<button style=\"color:green; white-space: nowrap;\"><i class=\"fas fa-check\"></i> Whitelist</button>";
|
||||
break;
|
||||
case "2":
|
||||
blocked = false;
|
||||
color = "green";
|
||||
fieldtext = "OK <br class='hidden-lg'>(forwarded)"+dnssec_status;
|
||||
buttontext = "<button style=\"color:red; white-space: nowrap;\"><i class=\"fa fa-ban\"></i> Blacklist</button>";
|
||||
break;
|
||||
case "3":
|
||||
blocked = false;
|
||||
color = "green";
|
||||
fieldtext = "OK <br class='hidden-lg'>(cached)"+dnssec_status;
|
||||
buttontext = "<button style=\"color:red; white-space: nowrap;\"><i class=\"fa fa-ban\"></i> Blacklist</button>";
|
||||
break;
|
||||
case "4":
|
||||
blocked = true;
|
||||
color = "red";
|
||||
fieldtext = "Blocked <br class='hidden-lg'>(regex/wildcard)";
|
||||
buttontext = "<button style=\"color:green; white-space: nowrap;\"><i class=\"fas fa-check\"></i> Whitelist</button>" ;
|
||||
break;
|
||||
case "5":
|
||||
blocked = true;
|
||||
color = "red";
|
||||
fieldtext = "Blocked <br class='hidden-lg'>(blacklist)";
|
||||
buttontext = "<button style=\"color:green; white-space: nowrap;\"><i class=\"fas fa-check\"></i> Whitelist</button>" ;
|
||||
break;
|
||||
case "6":
|
||||
blocked = true;
|
||||
color = "red";
|
||||
fieldtext = "Blocked <br class='hidden-lg'>(external, IP)";
|
||||
buttontext = "" ;
|
||||
break;
|
||||
case "7":
|
||||
blocked = true;
|
||||
color = "red";
|
||||
fieldtext = "Blocked <br class='hidden-lg'>(external, NULL)";
|
||||
buttontext = "" ;
|
||||
break;
|
||||
case "8":
|
||||
blocked = true;
|
||||
color = "red";
|
||||
fieldtext = "Blocked <br class='hidden-lg'>(external, NXRA)";
|
||||
buttontext = "" ;
|
||||
break;
|
||||
default:
|
||||
blocked = false;
|
||||
color = "black";
|
||||
fieldtext = "Unknown ("+parseInt(data[4])+")";
|
||||
buttontext = "";
|
||||
}
|
||||
$(row).css("color", color);
|
||||
$("td:eq(4)", row).html(fieldtext);
|
||||
$("td:eq(6)", row).html(buttontext);
|
||||
|
||||
// Check for existence of sixth column and display only if not Pi-holed
|
||||
var replytext;
|
||||
if(data.length > 6 && !blocked)
|
||||
{
|
||||
switch(data[6])
|
||||
{
|
||||
case "0":
|
||||
replytext = "N/A";
|
||||
break;
|
||||
case "1":
|
||||
replytext = "NODATA";
|
||||
break;
|
||||
case "2":
|
||||
replytext = "NXDOMAIN";
|
||||
break;
|
||||
case "3":
|
||||
replytext = "CNAME";
|
||||
break;
|
||||
case "4":
|
||||
replytext = "IP";
|
||||
break;
|
||||
case "5":
|
||||
replytext = "DOMAIN";
|
||||
break;
|
||||
case "6":
|
||||
replytext = "RRNAME";
|
||||
break;
|
||||
case "7":
|
||||
replytext = "SERVFAIL";
|
||||
break;
|
||||
case "8":
|
||||
replytext = "REFUSED";
|
||||
break;
|
||||
case "9":
|
||||
replytext = "NOTIMP";
|
||||
break;
|
||||
case "10":
|
||||
replytext = "upstream error";
|
||||
break;
|
||||
default:
|
||||
replytext = "? ("+parseInt(data[6])+")";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
replytext = "-";
|
||||
}
|
||||
$("td:eq(5)", row).css("color","black");
|
||||
$("td:eq(5)", row).html(replytext);
|
||||
|
||||
if(data.length > 7 && data[7] > 0)
|
||||
{
|
||||
var content = $("td:eq(5)", row).html();
|
||||
$("td:eq(5)", row).html(content + " (" + (0.1*data[7]).toFixed(1)+"ms)");
|
||||
}
|
||||
|
||||
},
|
||||
dom: "<'row'<'col-sm-12'f>>" +
|
||||
"<'row'<'col-sm-4'l><'col-sm-8'p>>" +
|
||||
"<'row'<'col-sm-12'<'table-responsive'tr>>>" +
|
||||
"<'row'<'col-sm-5'i><'col-sm-7'p>>",
|
||||
"ajax": {
|
||||
"url": APIstring,
|
||||
"error": handleAjaxError,
|
||||
"dataSrc": function(data){
|
||||
var dataIndex = 0;
|
||||
return data.data.map(function(x){
|
||||
x[0] = x[0] * 1e6 + (dataIndex++);
|
||||
return x;
|
||||
});
|
||||
}
|
||||
},
|
||||
"autoWidth" : false,
|
||||
"processing": true,
|
||||
"order" : [[0, "desc"]],
|
||||
"columns": [
|
||||
{ "width" : "15%", "render": function (data, type, full, meta) { if(type === "display"){return moment.unix(Math.floor(data/1e6)).format("Y-MM-DD [<br class='hidden-lg'>]HH:mm:ss z");}else{return data;} }},
|
||||
{ "width" : "4%" },
|
||||
{ "width" : "36%", "render": $.fn.dataTable.render.text() },
|
||||
{ "width" : "8%", "render": $.fn.dataTable.render.text() },
|
||||
{ "width" : "14%", "orderData": 4 },
|
||||
{ "width" : "8%", "orderData": 6 },
|
||||
{ "width" : "10%", "orderData": 4 }
|
||||
],
|
||||
"lengthMenu": [[10, 25, 50, 100, -1], [10, 25, 50, 100, "All"]],
|
||||
"stateSave": true,
|
||||
stateSaveCallback: function(settings, data) {
|
||||
// Store current state in client's local storage area
|
||||
localStorage.setItem("query_log_table", JSON.stringify(data));
|
||||
},
|
||||
stateLoadCallback: function(settings) {
|
||||
// Receive previous state from client's local storage area
|
||||
var data = localStorage.getItem("query_log_table");
|
||||
// Return if not available
|
||||
if(data === null){ return null; }
|
||||
data = JSON.parse(data);
|
||||
// Always start on the first page to show most recent queries
|
||||
data["start"] = 0;
|
||||
// Always start with empty search field
|
||||
data["search"]["search"] = "";
|
||||
// Apply loaded state to table
|
||||
return data;
|
||||
},
|
||||
"columnDefs": [ {
|
||||
"targets": -1,
|
||||
"data": null,
|
||||
"defaultContent": ""
|
||||
} ],
|
||||
"initComplete": function () {
|
||||
var api = this.api();
|
||||
// Query type IPv4 / IPv6
|
||||
api.$("td:eq(1)").click( function () { if(autofilter()){ api.search( this.innerHTML ).draw(); $("#resetButton").show(); }});
|
||||
api.$("td:eq(1)").hover(
|
||||
function () {
|
||||
if(autofilter()) {
|
||||
this.title = "Click to show only " + this.innerHTML + " queries";
|
||||
this.style.color = "#72afd2";
|
||||
} else {
|
||||
this.title = "";
|
||||
this.style.color = "";
|
||||
}
|
||||
},
|
||||
function () { this.style.color=""; }
|
||||
);
|
||||
api.$("td:eq(1)").css("cursor","pointer");
|
||||
// Domain
|
||||
api.$("td:eq(2)").click( function () { if(autofilter()){ api.search( this.innerHTML ).draw(); $("#resetButton").show(); }});
|
||||
api.$("td:eq(2)").hover(
|
||||
function () {
|
||||
if(autofilter()) {
|
||||
this.title = "Click to show only queries with domain " + this.innerHTML;
|
||||
this.style.color = "#72afd2";
|
||||
} else {
|
||||
this.title = "";
|
||||
this.style.color = "";
|
||||
}
|
||||
},
|
||||
function () { this.style.color=""; }
|
||||
);
|
||||
api.$("td:eq(2)").css("cursor","pointer");
|
||||
// Client
|
||||
api.$("td:eq(3)").click( function () { if(autofilter()){ api.search( this.innerHTML ).draw(); $("#resetButton").show(); }});
|
||||
api.$("td:eq(3)").hover(
|
||||
function () {
|
||||
if(autofilter()) {
|
||||
this.title = "Click to show only queries made by " + this.innerHTML;
|
||||
this.style.color = "#72afd2";
|
||||
} else {
|
||||
this.title = "";
|
||||
this.style.color = "";
|
||||
}
|
||||
},
|
||||
function () { this.style.color=""; }
|
||||
);
|
||||
api.$("td:eq(3)").css("cursor","pointer");
|
||||
}
|
||||
// Do we want to filter queries?
|
||||
var GETDict = {};
|
||||
window.location.search
|
||||
.substr(1)
|
||||
.split("&")
|
||||
.forEach(function(item) {
|
||||
GETDict[item.split("=")[0]] = item.split("=")[1];
|
||||
});
|
||||
|
||||
$("#all-queries tbody").on( "click", "button", function () {
|
||||
var data = tableApi.row( $(this).parents("tr") ).data();
|
||||
if (data[4] === "1" || data[4] === "4" || data[4] === "5")
|
||||
{
|
||||
add(data[2],"white");
|
||||
}
|
||||
else
|
||||
{
|
||||
add(data[2],"black");
|
||||
}
|
||||
} );
|
||||
var APIstring = "api.php?getAllQueries";
|
||||
|
||||
$("#resetButton").click( function () { tableApi.search("").draw(); $("#resetButton").hide(); } );
|
||||
} );
|
||||
if ("from" in GETDict && "until" in GETDict) {
|
||||
APIstring += "&from=" + GETDict.from;
|
||||
APIstring += "&until=" + GETDict.until;
|
||||
} else if ("client" in GETDict) {
|
||||
APIstring += "&client=" + GETDict.client;
|
||||
} else if ("domain" in GETDict) {
|
||||
APIstring += "&domain=" + GETDict.domain;
|
||||
} else if ("querytype" in GETDict) {
|
||||
APIstring += "&querytype=" + GETDict.querytype;
|
||||
} else if ("forwarddest" in GETDict) {
|
||||
APIstring += "&forwarddest=" + GETDict.forwarddest;
|
||||
}
|
||||
// If we don't ask filtering and also not for all queries, just request the most recent 100 queries
|
||||
else if (!("all" in GETDict)) {
|
||||
APIstring += "=100";
|
||||
}
|
||||
|
||||
tableApi = $("#all-queries").DataTable({
|
||||
rowCallback: function(row, data) {
|
||||
// DNSSEC status
|
||||
var dnssec_status;
|
||||
switch (data[5]) {
|
||||
case "1":
|
||||
dnssec_status = '<br><span class="text-green">SECURE</span>';
|
||||
break;
|
||||
case "2":
|
||||
dnssec_status = '<br><span class="text-orange">INSECURE</span>';
|
||||
break;
|
||||
case "3":
|
||||
dnssec_status = '<br><span class="text-red">BOGUS</span>';
|
||||
break;
|
||||
case "4":
|
||||
dnssec_status = '<br><span class="text-red">ABANDONED</span>';
|
||||
break;
|
||||
case "5":
|
||||
dnssec_status = '<br><span class="text-orange">UNKNOWN</span>';
|
||||
break;
|
||||
default:
|
||||
// No DNSSEC
|
||||
dnssec_status = "";
|
||||
}
|
||||
|
||||
// Query status
|
||||
var blocked,
|
||||
fieldtext,
|
||||
buttontext,
|
||||
colorClass,
|
||||
isCNAME = false,
|
||||
regexLink = false;
|
||||
|
||||
switch (data[4]) {
|
||||
case "1":
|
||||
blocked = true;
|
||||
colorClass = "text-red";
|
||||
fieldtext = "Blocked (gravity)";
|
||||
buttontext =
|
||||
'<button type="button" class="btn btn-default btn-sm text-green"><i class="fas fa-check"></i> Whitelist</button>';
|
||||
break;
|
||||
case "2":
|
||||
blocked = false;
|
||||
colorClass = "text-green";
|
||||
fieldtext = "OK <br class='hidden-lg'>(forwarded)" + dnssec_status;
|
||||
buttontext =
|
||||
'<button type="button" class="btn btn-default btn-sm text-red"><i class="fa fa-ban"></i> Blacklist</button>';
|
||||
break;
|
||||
case "3":
|
||||
blocked = false;
|
||||
colorClass = "text-green";
|
||||
fieldtext = "OK <br class='hidden-lg'>(cached)" + dnssec_status;
|
||||
buttontext =
|
||||
'<button type="button" class="btn btn-default btn-sm text-red"><i class="fa fa-ban"></i> Blacklist</button>';
|
||||
break;
|
||||
case "4":
|
||||
blocked = true;
|
||||
colorClass = "text-red";
|
||||
fieldtext = "Blocked <br class='hidden-lg'>(regex blacklist)";
|
||||
|
||||
if (data.length > 9 && data[9] > 0) {
|
||||
regexLink = true;
|
||||
}
|
||||
|
||||
buttontext =
|
||||
'<button type="button" class="btn btn-default btn-sm text-green"><i class="fas fa-check"></i> Whitelist</button>';
|
||||
break;
|
||||
case "5":
|
||||
blocked = true;
|
||||
colorClass = "text-red";
|
||||
fieldtext = "Blocked <br class='hidden-lg'>(exact blacklist)";
|
||||
buttontext =
|
||||
'<button type="button" class="btn btn-default btn-sm text-green"><i class="fas fa-check"></i> Whitelist</button>';
|
||||
break;
|
||||
case "6":
|
||||
blocked = true;
|
||||
colorClass = "text-red";
|
||||
fieldtext = "Blocked <br class='hidden-lg'>(external, IP)";
|
||||
buttontext = "";
|
||||
break;
|
||||
case "7":
|
||||
blocked = true;
|
||||
colorClass = "text-red";
|
||||
fieldtext = "Blocked <br class='hidden-lg'>(external, NULL)";
|
||||
buttontext = "";
|
||||
break;
|
||||
case "8":
|
||||
blocked = true;
|
||||
colorClass = "text-red";
|
||||
fieldtext = "Blocked <br class='hidden-lg'>(external, NXRA)";
|
||||
buttontext = "";
|
||||
break;
|
||||
case "9":
|
||||
blocked = true;
|
||||
colorClass = "text-red";
|
||||
fieldtext = "Blocked (gravity, CNAME)";
|
||||
buttontext =
|
||||
'<button type="button" class="btn btn-default btn-sm text-green"><i class="fas fa-check"></i> Whitelist</button>';
|
||||
isCNAME = true;
|
||||
break;
|
||||
case "10":
|
||||
blocked = true;
|
||||
colorClass = "text-red";
|
||||
fieldtext = "Blocked <br class='hidden-lg'>(regex blacklist, CNAME)";
|
||||
|
||||
if (data.length > 9 && data[9] > 0) {
|
||||
regexLink = true;
|
||||
}
|
||||
|
||||
buttontext =
|
||||
'<button type="button" class="btn btn-default btn-sm text-green"><i class="fas fa-check"></i> Whitelist</button>';
|
||||
isCNAME = true;
|
||||
break;
|
||||
case "11":
|
||||
blocked = true;
|
||||
colorClass = "text-red";
|
||||
fieldtext = "Blocked <br class='hidden-lg'>(exact blacklist, CNAME)";
|
||||
buttontext =
|
||||
'<button type="button" class="btn btn-default btn-sm text-green"><i class="fas fa-check"></i> Whitelist</button>';
|
||||
isCNAME = true;
|
||||
break;
|
||||
default:
|
||||
blocked = false;
|
||||
colorClass = "text-black";
|
||||
fieldtext = "Unknown (" + parseInt(data[4]) + ")";
|
||||
buttontext = "";
|
||||
}
|
||||
|
||||
$(row).addClass(colorClass);
|
||||
$("td:eq(4)", row).html(fieldtext);
|
||||
$("td:eq(6)", row).html(buttontext);
|
||||
|
||||
if (regexLink) {
|
||||
$("td:eq(4)", row).hover(
|
||||
function() {
|
||||
this.title = "Click to show matching regex filter";
|
||||
this.style.color = "#72afd2";
|
||||
},
|
||||
function() {
|
||||
this.style.color = "";
|
||||
}
|
||||
);
|
||||
$("td:eq(4)", row).off(); // Release any possible previous onClick event handlers
|
||||
$("td:eq(4)", row).click(function() {
|
||||
var new_tab = window.open("groups-domains.php?domainid=" + data[9], "_blank");
|
||||
if (new_tab) {
|
||||
new_tab.focus();
|
||||
}
|
||||
});
|
||||
$("td:eq(4)", row).addClass("underline");
|
||||
$("td:eq(4)", row).addClass("pointer");
|
||||
}
|
||||
|
||||
// Substitute domain by "." if empty
|
||||
var domain = data[2];
|
||||
if (domain.length === 0) {
|
||||
domain = ".";
|
||||
}
|
||||
|
||||
if (isCNAME) {
|
||||
var CNAME_domain = data[8];
|
||||
// Add domain in CNAME chain causing the query to have been blocked
|
||||
$("td:eq(2)", row).text(domain + "\n(blocked " + CNAME_domain + ")");
|
||||
} else {
|
||||
$("td:eq(2)", row).text(domain);
|
||||
}
|
||||
|
||||
// Check for existence of sixth column and display only if not Pi-holed
|
||||
var replytext;
|
||||
if (data.length > 6 && !blocked) {
|
||||
switch (data[6]) {
|
||||
case "0":
|
||||
replytext = "N/A";
|
||||
break;
|
||||
case "1":
|
||||
replytext = "NODATA";
|
||||
break;
|
||||
case "2":
|
||||
replytext = "NXDOMAIN";
|
||||
break;
|
||||
case "3":
|
||||
replytext = "CNAME";
|
||||
break;
|
||||
case "4":
|
||||
replytext = "IP";
|
||||
break;
|
||||
case "5":
|
||||
replytext = "DOMAIN";
|
||||
break;
|
||||
case "6":
|
||||
replytext = "RRNAME";
|
||||
break;
|
||||
case "7":
|
||||
replytext = "SERVFAIL";
|
||||
break;
|
||||
case "8":
|
||||
replytext = "REFUSED";
|
||||
break;
|
||||
case "9":
|
||||
replytext = "NOTIMP";
|
||||
break;
|
||||
case "10":
|
||||
replytext = "upstream error";
|
||||
break;
|
||||
default:
|
||||
replytext = "? (" + parseInt(data[6]) + ")";
|
||||
}
|
||||
} else {
|
||||
replytext = "-";
|
||||
}
|
||||
|
||||
$("td:eq(5)", row).addClass("text-black");
|
||||
$("td:eq(5)", row).html(replytext);
|
||||
|
||||
if (data.length > 7 && data[7] > 0) {
|
||||
var content = $("td:eq(5)", row).html();
|
||||
$("td:eq(5)", row).html(content + " (" + (0.1 * data[7]).toFixed(1) + "ms)");
|
||||
}
|
||||
},
|
||||
dom:
|
||||
"<'row'<'col-sm-12'f>>" +
|
||||
"<'row'<'col-sm-4'l><'col-sm-8'p>>" +
|
||||
"<'row'<'col-sm-12'<'table-responsive'tr>>>" +
|
||||
"<'row'<'col-sm-5'i><'col-sm-7'p>>",
|
||||
ajax: {
|
||||
url: APIstring,
|
||||
error: handleAjaxError,
|
||||
dataSrc: function(data) {
|
||||
var dataIndex = 0;
|
||||
return data.data.map(function(x) {
|
||||
x[0] = x[0] * 1e6 + dataIndex++;
|
||||
return x;
|
||||
});
|
||||
}
|
||||
},
|
||||
autoWidth: false,
|
||||
processing: true,
|
||||
order: [[0, "desc"]],
|
||||
columns: [
|
||||
{
|
||||
width: "15%",
|
||||
render: function(data, type) {
|
||||
if (type === "display") {
|
||||
return moment
|
||||
.unix(Math.floor(data / 1e6))
|
||||
.format("Y-MM-DD [<br class='hidden-lg'>]HH:mm:ss z");
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
},
|
||||
{ width: "4%" },
|
||||
{ width: "36%", render: $.fn.dataTable.render.text() },
|
||||
{ width: "8%", render: $.fn.dataTable.render.text() },
|
||||
{ width: "14%", orderData: 4 },
|
||||
{ width: "8%", orderData: 6 },
|
||||
{ width: "10%", orderData: 4 }
|
||||
],
|
||||
lengthMenu: [
|
||||
[10, 25, 50, 100, -1],
|
||||
[10, 25, 50, 100, "All"]
|
||||
],
|
||||
stateSave: true,
|
||||
stateSaveCallback: function(settings, data) {
|
||||
// Store current state in client's local storage area
|
||||
localStorage.setItem("query_log_table", JSON.stringify(data));
|
||||
},
|
||||
stateLoadCallback: function() {
|
||||
// Receive previous state from client's local storage area
|
||||
var data = localStorage.getItem("query_log_table");
|
||||
// Return if not available
|
||||
if (data === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
data = JSON.parse(data);
|
||||
// Always start on the first page to show most recent queries
|
||||
data.start = 0;
|
||||
// Always start with empty search field
|
||||
data.search.search = "";
|
||||
// Apply loaded state to table
|
||||
return data;
|
||||
},
|
||||
columnDefs: [
|
||||
{
|
||||
targets: -1,
|
||||
data: null,
|
||||
defaultContent: ""
|
||||
}
|
||||
],
|
||||
initComplete: function() {
|
||||
var api = this.api();
|
||||
// Query type IPv4 / IPv6
|
||||
api.$("td:eq(1)").click(function() {
|
||||
if (autofilter()) {
|
||||
api.search(this.textContent).draw();
|
||||
$("#resetButton").show();
|
||||
}
|
||||
});
|
||||
api.$("td:eq(1)").hover(
|
||||
function() {
|
||||
if (autofilter()) {
|
||||
this.title = "Click to show only " + this.textContent + " queries";
|
||||
this.style.color = "#72afd2";
|
||||
} else {
|
||||
this.title = "";
|
||||
this.style.color = "";
|
||||
}
|
||||
},
|
||||
function() {
|
||||
this.style.color = "";
|
||||
}
|
||||
);
|
||||
api.$("td:eq(1)").css("cursor", "pointer");
|
||||
// Domain
|
||||
api.$("td:eq(2)").click(function() {
|
||||
if (autofilter()) {
|
||||
var domain = this.textContent.split("\n")[0];
|
||||
api.search(domain).draw();
|
||||
$("#resetButton").show();
|
||||
}
|
||||
});
|
||||
api.$("td:eq(2)").hover(
|
||||
function() {
|
||||
if (autofilter()) {
|
||||
var domain = this.textContent.split("\n")[0];
|
||||
this.title = "Click to show only queries with domain " + domain;
|
||||
this.style.color = "#72afd2";
|
||||
} else {
|
||||
this.title = "";
|
||||
this.style.color = "";
|
||||
}
|
||||
},
|
||||
function() {
|
||||
this.style.color = "";
|
||||
}
|
||||
);
|
||||
api.$("td:eq(2)").css("cursor", "pointer");
|
||||
// Client
|
||||
api.$("td:eq(3)").click(function() {
|
||||
if (autofilter()) {
|
||||
api.search(this.textContent).draw();
|
||||
$("#resetButton").show();
|
||||
}
|
||||
});
|
||||
api.$("td:eq(3)").hover(
|
||||
function() {
|
||||
if (autofilter()) {
|
||||
this.title = "Click to show only queries made by " + this.textContent;
|
||||
this.style.color = "#72afd2";
|
||||
} else {
|
||||
this.title = "";
|
||||
this.style.color = "";
|
||||
}
|
||||
},
|
||||
function() {
|
||||
this.style.color = "";
|
||||
}
|
||||
);
|
||||
api.$("td:eq(3)").css("cursor", "pointer");
|
||||
}
|
||||
});
|
||||
|
||||
$("#all-queries tbody").on("click", "button", function() {
|
||||
var data = tableApi.row($(this).parents("tr")).data();
|
||||
if (data[4] === "2" || data[4] === "3") {
|
||||
add(data[2], "black");
|
||||
} else {
|
||||
add(data[2], "white");
|
||||
}
|
||||
});
|
||||
|
||||
$("#resetButton").click(function() {
|
||||
tableApi.search("").draw();
|
||||
$("#resetButton").hide();
|
||||
});
|
||||
|
||||
var chkbox_data = localStorage.getItem("query_log_filter_chkbox");
|
||||
if (chkbox_data !== null) {
|
||||
// Restore checkbox state
|
||||
$("#autofilter").prop("checked", chkbox_data === "true");
|
||||
} else {
|
||||
// Initialize checkbox
|
||||
$("#autofilter").prop("checked", true);
|
||||
localStorage.setItem("query_log_filter_chkbox", true);
|
||||
}
|
||||
|
||||
$("#autofilter").click(function() {
|
||||
localStorage.setItem("query_log_filter_chkbox", $("#autofilter").prop("checked"));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,142 +1,152 @@
|
||||
/* 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. */
|
||||
* (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. */
|
||||
|
||||
/* global ActiveXObject: false */
|
||||
|
||||
var exact = "";
|
||||
|
||||
function quietfilter(ta,data)
|
||||
{
|
||||
var lines = data.split("\n");
|
||||
for(var i = 0;i<lines.length;i++)
|
||||
{
|
||||
if(lines[i].indexOf("results") !== -1 && lines[i].indexOf("0 results") === -1)
|
||||
{
|
||||
var shortstring = lines[i].replace("::: /etc/pihole/","");
|
||||
// Remove "(x results)"
|
||||
shortstring = shortstring.replace(/\(.*/,"");
|
||||
ta.append(shortstring+"\n");
|
||||
}
|
||||
function quietfilter(ta, data) {
|
||||
var lines = data.split("\n");
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
if (lines[i].indexOf("results") !== -1 && lines[i].indexOf("0 results") === -1) {
|
||||
var shortstring = lines[i].replace("::: /etc/pihole/", "");
|
||||
// Remove "(x results)"
|
||||
shortstring = shortstring.replace(/\(.*/, "");
|
||||
ta.append(shortstring + "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Credit: http://stackoverflow.com/a/10642418/2087442
|
||||
function httpGet(ta,quiet,theUrl)
|
||||
{
|
||||
var xmlhttp;
|
||||
if (window.XMLHttpRequest)
|
||||
{
|
||||
function httpGet(ta, quiet, theUrl) {
|
||||
var xmlhttp;
|
||||
if (window.XMLHttpRequest) {
|
||||
// code for IE7+
|
||||
xmlhttp = new XMLHttpRequest();
|
||||
}
|
||||
else
|
||||
{
|
||||
xmlhttp = new XMLHttpRequest();
|
||||
} else {
|
||||
// code for IE6, IE5
|
||||
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
|
||||
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
|
||||
}
|
||||
|
||||
xmlhttp.onreadystatechange = function() {
|
||||
if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
|
||||
ta.show();
|
||||
ta.empty();
|
||||
if (!quiet) {
|
||||
ta.append(xmlhttp.responseText);
|
||||
} else {
|
||||
quietfilter(ta, xmlhttp.responseText);
|
||||
}
|
||||
}
|
||||
xmlhttp.onreadystatechange=function()
|
||||
{
|
||||
if (xmlhttp.readyState === 4 && xmlhttp.status === 200)
|
||||
{
|
||||
ta.show();
|
||||
ta.empty();
|
||||
if(!quiet)
|
||||
{
|
||||
ta.append(xmlhttp.responseText);
|
||||
}
|
||||
else
|
||||
{
|
||||
quietfilter(ta,xmlhttp.responseText);
|
||||
}
|
||||
}
|
||||
};
|
||||
xmlhttp.open("GET", theUrl, false);
|
||||
xmlhttp.send();
|
||||
};
|
||||
|
||||
xmlhttp.open("GET", theUrl, false);
|
||||
xmlhttp.send();
|
||||
}
|
||||
|
||||
function eventsource() {
|
||||
var ta = $("#output");
|
||||
var domain = $("#domain").val().trim();
|
||||
var q = $("#quiet");
|
||||
var ta = $("#output");
|
||||
var domain = $("#domain")
|
||||
.val()
|
||||
.trim();
|
||||
var q = $("#quiet");
|
||||
|
||||
if(domain.length === 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (domain.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var quiet = false;
|
||||
if(q.val() === "yes")
|
||||
{
|
||||
quiet = true;
|
||||
exact = "exact";
|
||||
}
|
||||
var quiet = false;
|
||||
if (q.val() === "yes") {
|
||||
quiet = true;
|
||||
exact = "exact";
|
||||
}
|
||||
|
||||
// IE does not support EventSource - load whole content at once
|
||||
if (typeof EventSource !== "function") {
|
||||
httpGet(ta,quiet,"/admin/scripts/pi-hole/php/queryads.php?domain="+domain.toLowerCase()+exact+"&IE");
|
||||
return;
|
||||
}
|
||||
// IE does not support EventSource - load whole content at once
|
||||
if (typeof EventSource !== "function") {
|
||||
httpGet(
|
||||
ta,
|
||||
quiet,
|
||||
"scripts/pi-hole/php/queryads.php?domain=" + domain.toLowerCase() + exact + "&IE"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
var host = window.location.host;
|
||||
var source = new EventSource("/admin/scripts/pi-hole/php/queryads.php?domain="+domain.toLowerCase()+"&"+exact);
|
||||
var source = new EventSource(
|
||||
"scripts/pi-hole/php/queryads.php?domain=" + domain.toLowerCase() + "&" + exact
|
||||
);
|
||||
|
||||
// Reset and show field
|
||||
ta.empty();
|
||||
ta.show();
|
||||
// Reset and show field
|
||||
ta.empty();
|
||||
ta.show();
|
||||
|
||||
source.addEventListener("message", function(e) {
|
||||
if(!quiet)
|
||||
{
|
||||
ta.append(e.data);
|
||||
}
|
||||
else
|
||||
{
|
||||
quietfilter(ta,e.data);
|
||||
}
|
||||
}, false);
|
||||
source.addEventListener(
|
||||
"message",
|
||||
function(e) {
|
||||
if (!quiet) {
|
||||
ta.append(e.data);
|
||||
} else {
|
||||
quietfilter(ta, e.data);
|
||||
}
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
// Will be called when script has finished
|
||||
source.addEventListener("error", function(e) {
|
||||
source.close();
|
||||
}, false);
|
||||
// Will be called when script has finished
|
||||
source.addEventListener(
|
||||
"error",
|
||||
function() {
|
||||
source.close();
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
// Reset exact variable
|
||||
exact = "";
|
||||
// Reset exact variable
|
||||
exact = "";
|
||||
}
|
||||
|
||||
// Handle enter button
|
||||
$(document).keypress(function(e) {
|
||||
if(e.which === 13 && $("#domain").is(":focus")) {
|
||||
// Enter was pressed, and the input has focus
|
||||
exact = "";
|
||||
eventsource();
|
||||
}
|
||||
if (e.which === 13 && $("#domain").is(":focus")) {
|
||||
// Enter was pressed, and the input has focus
|
||||
exact = "";
|
||||
eventsource();
|
||||
}
|
||||
});
|
||||
// Handle button
|
||||
$("#btnSearch").on("click", function() {
|
||||
exact = "";
|
||||
eventsource();
|
||||
exact = "";
|
||||
eventsource();
|
||||
});
|
||||
// Handle exact button
|
||||
$("#btnSearchExact").on("click", function() {
|
||||
exact = "exact";
|
||||
eventsource();
|
||||
exact = "exact";
|
||||
eventsource();
|
||||
});
|
||||
|
||||
// Wrap form-group's buttons to next line when viewed on a small screen
|
||||
$(window).on("resize",function() {
|
||||
if ($(window).width() < 991) {
|
||||
$(".form-group.input-group").removeClass("input-group").addClass("input-group-block");
|
||||
$(".form-group.input-group-block > input").css("margin-bottom", "5px");
|
||||
$(".form-group.input-group-block > .input-group-btn").removeClass("input-group-btn").addClass("btn-block text-center");
|
||||
}
|
||||
else {
|
||||
$(".form-group.input-group-block").removeClass("input-group-block").addClass( "input-group" );
|
||||
$(".form-group.input-group > input").css("margin-bottom","");
|
||||
$(".form-group.input-group > .btn-block.text-center").removeClass("btn-block text-center").addClass("input-group-btn");
|
||||
}
|
||||
$(window).on("resize", function() {
|
||||
if ($(window).width() < 991) {
|
||||
$(".form-group.input-group")
|
||||
.removeClass("input-group")
|
||||
.addClass("input-group-block");
|
||||
$(".form-group.input-group-block > input").css("margin-bottom", "5px");
|
||||
$(".form-group.input-group-block > .input-group-btn")
|
||||
.removeClass("input-group-btn")
|
||||
.addClass("btn-block text-center");
|
||||
} else {
|
||||
$(".form-group.input-group-block")
|
||||
.removeClass("input-group-block")
|
||||
.addClass("input-group");
|
||||
$(".form-group.input-group > input").css("margin-bottom", "");
|
||||
$(".form-group.input-group > .btn-block.text-center")
|
||||
.removeClass("btn-block text-center")
|
||||
.addClass("input-group-btn");
|
||||
}
|
||||
});
|
||||
$(document).ready(function() {
|
||||
$(window).trigger("resize");
|
||||
$(window).trigger("resize");
|
||||
});
|
||||
|
||||
@@ -1,248 +1,239 @@
|
||||
/* 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 () {
|
||||
$("[data-static]").on("click", function(){
|
||||
var row = $(this).closest("tr");
|
||||
var mac = row.find("#MAC").text();
|
||||
var ip = row.find("#IP").text();
|
||||
var host = row.find("#HOST").text();
|
||||
$("input[name=\"AddHostname\"]").val(host);
|
||||
$("input[name=\"AddIP\"]").val(ip);
|
||||
$("input[name=\"AddMAC\"]").val(mac);
|
||||
});
|
||||
* (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() {
|
||||
$("[data-static]").on("click", function() {
|
||||
var row = $(this).closest("tr");
|
||||
var mac = row.find("#MAC").text();
|
||||
var ip = row.find("#IP").text();
|
||||
var host = row.find("#HOST").text();
|
||||
$('input[name="AddHostname"]').val(host);
|
||||
$('input[name="AddIP"]').val(ip);
|
||||
$('input[name="AddMAC"]').val(mac);
|
||||
});
|
||||
});
|
||||
$(".confirm-poweroff").confirm({
|
||||
text: "Are you sure you want to send a poweroff command to your Pi-Hole?",
|
||||
title: "Confirmation required",
|
||||
confirm(button) {
|
||||
$("#poweroffform").submit();
|
||||
},
|
||||
cancel(button) {
|
||||
// nothing to do
|
||||
},
|
||||
confirmButton: "Yes, poweroff",
|
||||
cancelButton: "No, go back",
|
||||
post: true,
|
||||
confirmButtonClass: "btn-danger",
|
||||
cancelButtonClass: "btn-success",
|
||||
dialogClass: "modal-dialog modal-mg" // Bootstrap classes for mid-size modal
|
||||
text: "Are you sure you want to send a poweroff command to your Pi-Hole?",
|
||||
title: "Confirmation required",
|
||||
confirm: function() {
|
||||
$("#poweroffform").submit();
|
||||
},
|
||||
cancel: function() {
|
||||
// nothing to do
|
||||
},
|
||||
confirmButton: "Yes, poweroff",
|
||||
cancelButton: "No, go back",
|
||||
post: true,
|
||||
confirmButtonClass: "btn-danger",
|
||||
cancelButtonClass: "btn-success",
|
||||
dialogClass: "modal-dialog modal-mg" // Bootstrap classes for mid-size modal
|
||||
});
|
||||
$(".confirm-reboot").confirm({
|
||||
text: "Are you sure you want to send a reboot command to your Pi-Hole?",
|
||||
title: "Confirmation required",
|
||||
confirm(button) {
|
||||
$("#rebootform").submit();
|
||||
},
|
||||
cancel(button) {
|
||||
// nothing to do
|
||||
},
|
||||
confirmButton: "Yes, reboot",
|
||||
cancelButton: "No, go back",
|
||||
post: true,
|
||||
confirmButtonClass: "btn-danger",
|
||||
cancelButtonClass: "btn-success",
|
||||
dialogClass: "modal-dialog modal-mg" // Bootstrap classes for mid-size modal
|
||||
text: "Are you sure you want to send a reboot command to your Pi-Hole?",
|
||||
title: "Confirmation required",
|
||||
confirm: function() {
|
||||
$("#rebootform").submit();
|
||||
},
|
||||
cancel: function() {
|
||||
// nothing to do
|
||||
},
|
||||
confirmButton: "Yes, reboot",
|
||||
cancelButton: "No, go back",
|
||||
post: true,
|
||||
confirmButtonClass: "btn-danger",
|
||||
cancelButtonClass: "btn-success",
|
||||
dialogClass: "modal-dialog modal-mg" // Bootstrap classes for mid-size modal
|
||||
});
|
||||
|
||||
$(".confirm-restartdns").confirm({
|
||||
text: "Are you sure you want to send a restart command to your DNS server?",
|
||||
title: "Confirmation required",
|
||||
confirm(button) {
|
||||
$("#restartdnsform").submit();
|
||||
},
|
||||
cancel(button) {
|
||||
// nothing to do
|
||||
},
|
||||
confirmButton: "Yes, restart DNS",
|
||||
cancelButton: "No, go back",
|
||||
post: true,
|
||||
confirmButtonClass: "btn-danger",
|
||||
cancelButtonClass: "btn-success",
|
||||
dialogClass: "modal-dialog modal-mg"
|
||||
text: "Are you sure you want to send a restart command to your DNS server?",
|
||||
title: "Confirmation required",
|
||||
confirm: function() {
|
||||
$("#restartdnsform").submit();
|
||||
},
|
||||
cancel: function() {
|
||||
// nothing to do
|
||||
},
|
||||
confirmButton: "Yes, restart DNS",
|
||||
cancelButton: "No, go back",
|
||||
post: true,
|
||||
confirmButtonClass: "btn-danger",
|
||||
cancelButtonClass: "btn-success",
|
||||
dialogClass: "modal-dialog modal-mg"
|
||||
});
|
||||
|
||||
$(".confirm-flushlogs").confirm({
|
||||
text: "Are you sure you want to flush your logs?",
|
||||
title: "Confirmation required",
|
||||
confirm(button) {
|
||||
$("#flushlogsform").submit();
|
||||
},
|
||||
cancel(button) {
|
||||
// nothing to do
|
||||
},
|
||||
confirmButton: "Yes, flush logs",
|
||||
cancelButton: "No, go back",
|
||||
post: true,
|
||||
confirmButtonClass: "btn-danger",
|
||||
cancelButtonClass: "btn-success",
|
||||
dialogClass: "modal-dialog modal-mg"
|
||||
text: "Are you sure you want to flush your logs?",
|
||||
title: "Confirmation required",
|
||||
confirm: function() {
|
||||
$("#flushlogsform").submit();
|
||||
},
|
||||
cancel: function() {
|
||||
// nothing to do
|
||||
},
|
||||
confirmButton: "Yes, flush logs",
|
||||
cancelButton: "No, go back",
|
||||
post: true,
|
||||
confirmButtonClass: "btn-danger",
|
||||
cancelButtonClass: "btn-success",
|
||||
dialogClass: "modal-dialog modal-mg"
|
||||
});
|
||||
|
||||
$(".confirm-disablelogging").confirm({
|
||||
text: "Are you sure you want to disable logging and flush your Pi-hole logs?",
|
||||
title: "Confirmation required",
|
||||
confirm(button) {
|
||||
$("#disablelogsform").submit();
|
||||
},
|
||||
cancel(button) {
|
||||
// nothing to do
|
||||
},
|
||||
confirmButton: "Yes, disable logs and flush my logs",
|
||||
cancelButton: "No, go back",
|
||||
post: true,
|
||||
confirmButtonClass: "btn-danger",
|
||||
cancelButtonClass: "btn-success",
|
||||
dialogClass: "modal-dialog modal-mg"
|
||||
$(".confirm-flusharp").confirm({
|
||||
text: "Are you sure you want to flush your network table?",
|
||||
title: "Confirmation required",
|
||||
confirm: function() {
|
||||
$("#flusharpform").submit();
|
||||
},
|
||||
cancel: function() {
|
||||
// nothing to do
|
||||
},
|
||||
confirmButton: "Yes, flush my network table",
|
||||
cancelButton: "No, go back",
|
||||
post: true,
|
||||
confirmButtonClass: "btn-warning",
|
||||
cancelButtonClass: "btn-success",
|
||||
dialogClass: "modal-dialog modal-mg"
|
||||
});
|
||||
|
||||
$(".confirm-disablelogging-noflush").confirm({
|
||||
text: "Are you sure you want to disable logging?",
|
||||
title: "Confirmation required",
|
||||
confirm(button) {
|
||||
$("#disablelogsform-noflush").submit();
|
||||
},
|
||||
cancel(button) {
|
||||
// nothing to do
|
||||
},
|
||||
confirmButton: "Yes, disable logs",
|
||||
cancelButton: "No, go back",
|
||||
post: true,
|
||||
confirmButtonClass: "btn-warning",
|
||||
cancelButtonClass: "btn-success",
|
||||
dialogClass: "modal-dialog modal-mg"
|
||||
text: "Are you sure you want to disable logging?",
|
||||
title: "Confirmation required",
|
||||
confirm: function() {
|
||||
$("#disablelogsform-noflush").submit();
|
||||
},
|
||||
cancel: function() {
|
||||
// nothing to do
|
||||
},
|
||||
confirmButton: "Yes, disable logs",
|
||||
cancelButton: "No, go back",
|
||||
post: true,
|
||||
confirmButtonClass: "btn-warning",
|
||||
cancelButtonClass: "btn-success",
|
||||
dialogClass: "modal-dialog modal-mg"
|
||||
});
|
||||
|
||||
$(".api-token").confirm({
|
||||
text: "Make sure that nobody else can scan this code around you. They will have full access to the API without having to know the password. Note that the generation of the QR code will take some time.",
|
||||
title: "Confirmation required",
|
||||
confirm(button) {
|
||||
window.open("scripts/pi-hole/php/api_token.php");
|
||||
},
|
||||
cancel(button) {
|
||||
// nothing to do
|
||||
},
|
||||
confirmButton: "Yes, show API token",
|
||||
cancelButton: "No, go back",
|
||||
post: true,
|
||||
confirmButtonClass: "btn-danger",
|
||||
cancelButtonClass: "btn-success",
|
||||
dialogClass: "modal-dialog modal-mg"
|
||||
text:
|
||||
"Make sure that nobody else can scan this code around you. They will have full access to the API without having to know the password. Note that the generation of the QR code will take some time.",
|
||||
title: "Confirmation required",
|
||||
confirm: function() {
|
||||
window.open("scripts/pi-hole/php/api_token.php");
|
||||
},
|
||||
cancel: function() {
|
||||
// nothing to do
|
||||
},
|
||||
confirmButton: "Yes, show API token",
|
||||
cancelButton: "No, go back",
|
||||
post: true,
|
||||
confirmButtonClass: "btn-danger",
|
||||
cancelButtonClass: "btn-success",
|
||||
dialogClass: "modal-dialog modal-mg"
|
||||
});
|
||||
|
||||
$("#DHCPchk").click(function() {
|
||||
$("input.DHCPgroup").prop("disabled", !this.checked);
|
||||
$("#dhcpnotice").prop("hidden", !this.checked).addClass("lookatme");
|
||||
$("input.DHCPgroup").prop("disabled", !this.checked);
|
||||
$("#dhcpnotice")
|
||||
.prop("hidden", !this.checked)
|
||||
.addClass("lookatme");
|
||||
});
|
||||
|
||||
function loadCacheInfo()
|
||||
{
|
||||
$.getJSON("api.php?getCacheInfo", function(data) {
|
||||
if("FTLnotrunning" in data)
|
||||
{
|
||||
return;
|
||||
}
|
||||
function loadCacheInfo() {
|
||||
$.getJSON("api.php?getCacheInfo", function(data) {
|
||||
if ("FTLnotrunning" in data) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Fill table with obtained values
|
||||
$("#cache-size").text(parseInt(data["cacheinfo"]["cache-size"]));
|
||||
$("#cache-inserted").text(parseInt(data["cacheinfo"]["cache-inserted"]));
|
||||
// Fill table with obtained values
|
||||
$("#cache-size").text(parseInt(data.cacheinfo["cache-size"]));
|
||||
$("#cache-inserted").text(parseInt(data.cacheinfo["cache-inserted"]));
|
||||
|
||||
// Highlight early cache removals when present
|
||||
var cachelivefreed = parseInt(data["cacheinfo"]["cache-live-freed"]);
|
||||
$("#cache-live-freed").text(cachelivefreed);
|
||||
if(cachelivefreed > 0)
|
||||
{
|
||||
$("#cache-live-freed").parent("tr").addClass("lookatme");
|
||||
}
|
||||
else
|
||||
{
|
||||
$("#cache-live-freed").parent("tr").removeClass("lookatme");
|
||||
}
|
||||
// Highlight early cache removals when present
|
||||
var cachelivefreed = parseInt(data.cacheinfo["cache-live-freed"]);
|
||||
$("#cache-live-freed").text(cachelivefreed);
|
||||
if (cachelivefreed > 0) {
|
||||
$("#cache-live-freed")
|
||||
.parent("tr")
|
||||
.addClass("lookatme");
|
||||
} else {
|
||||
$("#cache-live-freed")
|
||||
.parent("tr")
|
||||
.removeClass("lookatme");
|
||||
}
|
||||
|
||||
// Update cache info every 10 seconds
|
||||
setTimeout(loadCacheInfo, 10000);
|
||||
});
|
||||
// Update cache info every 10 seconds
|
||||
setTimeout(loadCacheInfo, 10000);
|
||||
});
|
||||
}
|
||||
|
||||
var leasetable, staticleasetable;
|
||||
$(document).ready(function() {
|
||||
if(document.getElementById("DHCPLeasesTable"))
|
||||
{
|
||||
leasetable = $("#DHCPLeasesTable").DataTable({
|
||||
dom: "<'row'<'col-sm-12'tr>><'row'<'col-sm-6'i><'col-sm-6'f>>",
|
||||
"columnDefs": [ { "bSortable": false, "orderable": false, targets: -1} ],
|
||||
"paging": false,
|
||||
"scrollCollapse": true,
|
||||
"scrollY": "200px",
|
||||
"scrollX" : true
|
||||
});
|
||||
}
|
||||
if(document.getElementById("DHCPStaticLeasesTable"))
|
||||
{
|
||||
staticleasetable = $("#DHCPStaticLeasesTable").DataTable({
|
||||
dom: "<'row'<'col-sm-12'tr>><'row'<'col-sm-12'i>>",
|
||||
"columnDefs": [ { "bSortable": false, "orderable": false, targets: -1} ],
|
||||
"paging": false,
|
||||
"scrollCollapse": true,
|
||||
"scrollY": "200px",
|
||||
"scrollX" : true
|
||||
});
|
||||
}
|
||||
//call draw() on each table... they don't render properly with scrollX and scrollY set... ¯\_(ツ)_/¯
|
||||
$("a[data-toggle=\"tab\"]").on("shown.bs.tab", function (e) {
|
||||
leasetable.draw();
|
||||
staticleasetable.draw();
|
||||
if (document.getElementById("DHCPLeasesTable")) {
|
||||
leasetable = $("#DHCPLeasesTable").DataTable({
|
||||
dom: "<'row'<'col-sm-12'tr>><'row'<'col-sm-6'i><'col-sm-6'f>>",
|
||||
columnDefs: [{ bSortable: false, orderable: false, targets: -1 }],
|
||||
paging: false,
|
||||
scrollCollapse: true,
|
||||
scrollY: "200px",
|
||||
scrollX: true
|
||||
});
|
||||
}
|
||||
|
||||
loadCacheInfo();
|
||||
if (document.getElementById("DHCPStaticLeasesTable")) {
|
||||
staticleasetable = $("#DHCPStaticLeasesTable").DataTable({
|
||||
dom: "<'row'<'col-sm-12'tr>><'row'<'col-sm-12'i>>",
|
||||
columnDefs: [{ bSortable: false, orderable: false, targets: -1 }],
|
||||
paging: false,
|
||||
scrollCollapse: true,
|
||||
scrollY: "200px",
|
||||
scrollX: true
|
||||
});
|
||||
}
|
||||
|
||||
} );
|
||||
//call draw() on each table... they don't render properly with scrollX and scrollY set... ¯\_(ツ)_/¯
|
||||
$('a[data-toggle="tab"]').on("shown.bs.tab", function() {
|
||||
leasetable.draw();
|
||||
staticleasetable.draw();
|
||||
});
|
||||
|
||||
loadCacheInfo();
|
||||
});
|
||||
|
||||
// Handle hiding of alerts
|
||||
$(function(){
|
||||
$("[data-hide]").on("click", function(){
|
||||
$(this).closest("." + $(this).attr("data-hide")).hide();
|
||||
});
|
||||
$(function() {
|
||||
$("[data-hide]").on("click", function() {
|
||||
$(this)
|
||||
.closest("." + $(this).attr("data-hide"))
|
||||
.hide();
|
||||
});
|
||||
});
|
||||
|
||||
// DHCP leases tooltips
|
||||
$(document).ready(function(){
|
||||
$("[data-toggle=\"tooltip\"]").tooltip({"html": true, container : "body"});
|
||||
});
|
||||
|
||||
// Handle list deletion
|
||||
$("button[id^='adlist-btn-']").on("click", function (e) {
|
||||
var id = parseInt($(this).context.id.replace(/[^0-9\.]/g, ""), 10);
|
||||
e.preventDefault();
|
||||
|
||||
var status = $("input[name=\"adlist-del-"+id+"\"]").is(":checked");
|
||||
var textType = status ? "none" : "line-through";
|
||||
|
||||
// Check hidden delete box (or reset)
|
||||
$("input[name=\"adlist-del-"+id+"\"]").prop("checked", !status);
|
||||
// Untick and disable check box (or reset)
|
||||
$("input[name=\"adlist-enable-"+id+"\"]").prop("checked", status).prop("disabled", !status);
|
||||
// Strink through text (or reset)
|
||||
$("a[id=\"adlist-text-"+id+"\"]").css("text-decoration", textType);
|
||||
// Highlight that the button has to be clicked in order to make the change live
|
||||
$("button[id=\"blockinglistsaveupdate\"]").addClass("btn-danger").css("font-weight", "bold");
|
||||
|
||||
$(document).ready(function() {
|
||||
$('[data-toggle="tooltip"]').tooltip({ html: true, container: "body" });
|
||||
});
|
||||
|
||||
// Change "?tab=" parameter in URL for save and reload
|
||||
$(".nav-tabs a").on("shown.bs.tab", function (e) {
|
||||
window.history.pushState("", "", "?tab=" + e.target.hash.substring(1));
|
||||
window.scrollTo(0, 0);
|
||||
$(".nav-tabs a").on("shown.bs.tab", function(e) {
|
||||
var tab = e.target.hash.substring(1);
|
||||
window.history.pushState("", "", "?tab=" + tab);
|
||||
if (tab === "piholedhcp") {
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
window.scrollTo(0, 0);
|
||||
});
|
||||
|
||||
// Auto dismissal for info notifications
|
||||
$(document).ready(function(){
|
||||
var alInfo = $("#alInfo");
|
||||
if(alInfo.length)
|
||||
{
|
||||
alInfo.delay(3000).fadeOut(2000, function() { alInfo.hide(); });
|
||||
}
|
||||
$(document).ready(function() {
|
||||
var alInfo = $("#alInfo");
|
||||
if (alInfo.length) {
|
||||
alInfo.delay(3000).fadeOut(2000, function() {
|
||||
alInfo.hide();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,47 +1,49 @@
|
||||
/* 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. */
|
||||
var offset, timer, pre, scrolling = true;
|
||||
* (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. */
|
||||
|
||||
var offset,
|
||||
timer,
|
||||
pre,
|
||||
scrolling = true;
|
||||
|
||||
// Check every 200msec for fresh data
|
||||
var interval = 200;
|
||||
|
||||
// Function that asks the API for new data
|
||||
function reloadData(){
|
||||
clearTimeout(timer);
|
||||
$.getJSON("scripts/pi-hole/php/tailLog.php?FTL&offset="+offset, function (data)
|
||||
{
|
||||
pre.append(data["lines"]);
|
||||
function reloadData() {
|
||||
clearTimeout(timer);
|
||||
$.getJSON("scripts/pi-hole/php/tailLog.php?FTL&offset=" + offset, function(data) {
|
||||
pre.append(data.lines);
|
||||
|
||||
if(scrolling && offset !== data["offset"]) {
|
||||
pre.scrollTop(pre[0].scrollHeight);
|
||||
}
|
||||
if (scrolling && offset !== data.offset) {
|
||||
pre.scrollTop(pre[0].scrollHeight);
|
||||
}
|
||||
|
||||
offset = data["offset"];
|
||||
});
|
||||
offset = data.offset;
|
||||
});
|
||||
|
||||
timer = setTimeout(reloadData, interval);
|
||||
timer = setTimeout(reloadData, interval);
|
||||
}
|
||||
|
||||
$(function(){
|
||||
// Get offset at first loading of page
|
||||
$.getJSON("scripts/pi-hole/php/tailLog.php?FTL", function (data)
|
||||
{
|
||||
offset = data["offset"];
|
||||
});
|
||||
pre = $("#output");
|
||||
// Trigger function that looks for new data
|
||||
reloadData();
|
||||
$(function() {
|
||||
// Get offset at first loading of page
|
||||
$.getJSON("scripts/pi-hole/php/tailLog.php?FTL", function(data) {
|
||||
offset = data.offset;
|
||||
});
|
||||
pre = $("#output");
|
||||
// Trigger function that looks for new data
|
||||
reloadData();
|
||||
});
|
||||
|
||||
$("#chk1").click(function() {
|
||||
$("#chk2").prop("checked",this.checked);
|
||||
scrolling = this.checked;
|
||||
$("#chk2").prop("checked", this.checked);
|
||||
scrolling = this.checked;
|
||||
});
|
||||
$("#chk2").click(function() {
|
||||
$("#chk1").prop("checked",this.checked);
|
||||
scrolling = this.checked;
|
||||
$("#chk1").prop("checked", this.checked);
|
||||
scrolling = this.checked;
|
||||
});
|
||||
|
||||
@@ -1,47 +1,49 @@
|
||||
/* 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. */
|
||||
var offset, timer, pre, scrolling = true;
|
||||
* (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. */
|
||||
|
||||
var offset,
|
||||
timer,
|
||||
pre,
|
||||
scrolling = true;
|
||||
|
||||
// Check every 200msec for fresh data
|
||||
var interval = 200;
|
||||
|
||||
// Function that asks the API for new data
|
||||
function reloadData(){
|
||||
clearTimeout(timer);
|
||||
$.getJSON("scripts/pi-hole/php/tailLog.php?offset="+offset, function (data)
|
||||
{
|
||||
pre.append(data["lines"]);
|
||||
function reloadData() {
|
||||
clearTimeout(timer);
|
||||
$.getJSON("scripts/pi-hole/php/tailLog.php?offset=" + offset, function(data) {
|
||||
pre.append(data.lines);
|
||||
|
||||
if(scrolling && offset !== data["offset"]) {
|
||||
pre.scrollTop(pre[0].scrollHeight);
|
||||
}
|
||||
if (scrolling && offset !== data.offset) {
|
||||
pre.scrollTop(pre[0].scrollHeight);
|
||||
}
|
||||
|
||||
offset = data["offset"];
|
||||
});
|
||||
offset = data.offset;
|
||||
});
|
||||
|
||||
timer = setTimeout(reloadData, interval);
|
||||
timer = setTimeout(reloadData, interval);
|
||||
}
|
||||
|
||||
$(function(){
|
||||
// Get offset at first loading of page
|
||||
$.getJSON("scripts/pi-hole/php/tailLog.php", function (data)
|
||||
{
|
||||
offset = data["offset"];
|
||||
});
|
||||
pre = $("#output");
|
||||
// Trigger function that looks for new data
|
||||
reloadData();
|
||||
$(function() {
|
||||
// Get offset at first loading of page
|
||||
$.getJSON("scripts/pi-hole/php/tailLog.php", function(data) {
|
||||
offset = data.offset;
|
||||
});
|
||||
pre = $("#output");
|
||||
// Trigger function that looks for new data
|
||||
reloadData();
|
||||
});
|
||||
|
||||
$("#chk1").click(function() {
|
||||
$("#chk2").prop("checked",this.checked);
|
||||
scrolling = this.checked;
|
||||
$("#chk2").prop("checked", this.checked);
|
||||
scrolling = this.checked;
|
||||
});
|
||||
$("#chk2").click(function() {
|
||||
$("#chk1").prop("checked",this.checked);
|
||||
scrolling = this.checked;
|
||||
$("#chk1").prop("checked", this.checked);
|
||||
scrolling = this.checked;
|
||||
});
|
||||
|
||||
@@ -26,7 +26,7 @@ function sendRequestFTL($requestin)
|
||||
global $socket;
|
||||
|
||||
$request = ">".$requestin;
|
||||
fwrite($socket, $request) or die("Could not send data to server\n");
|
||||
fwrite($socket, $request) or die('{"error":"Could not send data to server"}');
|
||||
}
|
||||
|
||||
function getResponseFTL()
|
||||
@@ -35,9 +35,15 @@ function getResponseFTL()
|
||||
|
||||
$response = [];
|
||||
|
||||
$errCount = 0;
|
||||
while(true)
|
||||
{
|
||||
$out = fgets($socket);
|
||||
if ($out == "") $errCount++;
|
||||
if ($errCount > 100) {
|
||||
// Tried 100 times, but never got proper reply, fail to prevent busy loop
|
||||
die('{"error":"Tried 100 times to connect to FTL server, but never got proper reply. Please check Port and logs!"}');
|
||||
}
|
||||
if(strrpos($out,"---EOM---") !== false)
|
||||
break;
|
||||
|
||||
|
||||
@@ -8,51 +8,85 @@
|
||||
|
||||
require_once('auth.php');
|
||||
|
||||
$type = $_POST['list'];
|
||||
$list = $_POST['list'];
|
||||
|
||||
// Perform all of the authentication for list editing
|
||||
// when NOT invoked and authenticated from API
|
||||
if (empty($api)) {
|
||||
list_verify($type);
|
||||
list_verify($list);
|
||||
}
|
||||
|
||||
// Don't check if the added item is a valid domain for regex expressions. Regex
|
||||
// filters are validated by FTL on import and skipped if invalid
|
||||
if($type !== "regex") {
|
||||
check_domain();
|
||||
// Split individual domains into array
|
||||
$domains = preg_split('/\s+/', trim($_POST['domain']));
|
||||
|
||||
// Get comment if available
|
||||
$comment = null;
|
||||
if(isset($_POST['comment'])) {
|
||||
$comment = trim($_POST['comment']);
|
||||
}
|
||||
|
||||
switch($type) {
|
||||
case "white":
|
||||
if(!isset($_POST["auditlog"]))
|
||||
echo shell_exec("sudo pihole -w ${_POST['domain']}");
|
||||
else
|
||||
{
|
||||
echo shell_exec("sudo pihole -w -n ${_POST['domain']}");
|
||||
echo shell_exec("sudo pihole -a audit ${_POST['domain']}");
|
||||
}
|
||||
break;
|
||||
case "black":
|
||||
if(!isset($_POST["auditlog"]))
|
||||
echo shell_exec("sudo pihole -b ${_POST['domain']}");
|
||||
else
|
||||
{
|
||||
echo shell_exec("sudo pihole -b -n ${_POST['domain']}");
|
||||
echo shell_exec("sudo pihole -a audit ${_POST['domain']}");
|
||||
}
|
||||
break;
|
||||
case "wild":
|
||||
// Escape "." so it won't be interpreted as the wildcard character
|
||||
$domain = str_replace(".","\.",$_POST['domain']);
|
||||
// Add regex filter for legacy wildcard behavior
|
||||
add_regex("(^|\.)".$domain."$");
|
||||
break;
|
||||
case "regex":
|
||||
add_regex($_POST['domain']);
|
||||
break;
|
||||
case "audit":
|
||||
echo exec("sudo pihole -a audit ${_POST['domain']}");
|
||||
break;
|
||||
// Convert domain name to IDNA ASCII form for international domains
|
||||
// Do this only for exact domains, not for regex filters
|
||||
// Only do it when the php-intl extension is available
|
||||
if (extension_loaded("intl") && ($list === "white" || $list === "black")) {
|
||||
foreach($domains as &$domain)
|
||||
{
|
||||
$domain = idn_to_ascii($domain);
|
||||
}
|
||||
}
|
||||
|
||||
// Only check domains we add to the exact lists.
|
||||
// Regex are validated by FTL during import
|
||||
$check_lists = ["white","black","audit"];
|
||||
if(in_array($list, $check_lists)) {
|
||||
check_domain($domains);
|
||||
}
|
||||
|
||||
require_once("func.php");
|
||||
require_once("database.php");
|
||||
$GRAVITYDB = getGravityDBFilename();
|
||||
$db = SQLite3_connect($GRAVITYDB, SQLITE3_OPEN_READWRITE);
|
||||
|
||||
$reload = true;
|
||||
switch($list) {
|
||||
case "white":
|
||||
$domains = array_map('strtolower', $domains);
|
||||
echo add_to_table($db, "domainlist", $domains, $comment, false, false, ListType::whitelist);
|
||||
break;
|
||||
|
||||
case "black":
|
||||
$domains = array_map('strtolower', $domains);
|
||||
echo add_to_table($db, "domainlist", $domains, $comment, false, false, ListType::blacklist);
|
||||
break;
|
||||
|
||||
case "white_regex":
|
||||
echo add_to_table($db, "domainlist", $domains, $comment, false, false, ListType::regex_whitelist);
|
||||
break;
|
||||
|
||||
case "white_wild":
|
||||
echo add_to_table($db, "domainlist", $domains, $comment, true, false, ListType::regex_whitelist);
|
||||
break;
|
||||
|
||||
case "black_regex":
|
||||
echo add_to_table($db, "domainlist", $domains, $comment, false, false, ListType::regex_blacklist);
|
||||
break;
|
||||
|
||||
case "black_wild":
|
||||
echo add_to_table($db, "domainlist", $domains, $comment, true, false, ListType::regex_blacklist);
|
||||
break;
|
||||
|
||||
case "audit":
|
||||
$reload = false;
|
||||
echo add_to_table($db, "domain_audit", $domains);
|
||||
break;
|
||||
|
||||
default:
|
||||
die("Invalid list!");
|
||||
}
|
||||
|
||||
// Reload lists in pihole-FTL after having added something
|
||||
if ($reload) {
|
||||
echo shell_exec("sudo pihole restartdns reload-lists");
|
||||
}
|
||||
?>
|
||||
|
||||
|
||||
@@ -11,9 +11,7 @@ if($auth)
|
||||
require_once("../../vendor/qrcode.php");
|
||||
$qr = QRCode::getMinimumQRCode($pwhash, QR_ERROR_CORRECT_LEVEL_Q);
|
||||
$qr->printHTML("10px");
|
||||
print("Raw API Token: ");
|
||||
print($pwhash);
|
||||
|
||||
echo "<br>Raw API Token: <code>" . $pwhash . "</code>";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -10,8 +10,15 @@ require_once('func.php');
|
||||
$ERRORLOG = getenv('PHP_ERROR_LOG');
|
||||
if (empty($ERRORLOG)) {
|
||||
$ERRORLOG = '/var/log/lighttpd/error.log';
|
||||
|
||||
if (!file_exists($ERRORLOG) || !is_writable($ERRORLOG)) {
|
||||
$ERRORLOG = '/var/log/apache2/error.log';
|
||||
|
||||
if (!file_exists($ERRORLOG) || !is_writable($ERRORLOG)) {
|
||||
$ERRORLOG = '/tmp/pi-hole-error.log';
|
||||
}
|
||||
}
|
||||
}
|
||||
$regexfile = "/etc/pihole/regex.list";
|
||||
|
||||
function pi_log($message) {
|
||||
error_log(date('Y-m-d H:i:s') . ': ' . $message . "\n", 3, $GLOBALS['ERRORLOG']);
|
||||
@@ -106,15 +113,12 @@ function check_csrf($token) {
|
||||
}
|
||||
}
|
||||
|
||||
function check_domain() {
|
||||
if(isset($_POST['domain'])){
|
||||
$domains = preg_split('/\s+/', $_POST['domain']);
|
||||
foreach($domains as $domain)
|
||||
{
|
||||
$validDomain = is_valid_domain_name($domain);
|
||||
if(!$validDomain){
|
||||
log_and_die(htmlspecialchars($domain. ' is not a valid domain'));
|
||||
}
|
||||
function check_domain(&$domains) {
|
||||
foreach($domains as &$domain)
|
||||
{
|
||||
$validDomain = is_valid_domain_name($domain);
|
||||
if(!$validDomain){
|
||||
log_and_die(htmlspecialchars($domain. ' is not a valid domain'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
require_once "func.php";
|
||||
|
||||
$customDNSFile = "/etc/pihole/custom.list";
|
||||
|
||||
switch ($_REQUEST['action'])
|
||||
{
|
||||
case 'get': echo json_encode(echoCustomDNSEntries()); break;
|
||||
case 'add': echo json_encode(addCustomDNSEntry()); break;
|
||||
case 'delete': echo json_encode(deleteCustomDNSEntry()); break;
|
||||
default:
|
||||
die("Wrong action");
|
||||
}
|
||||
|
||||
function echoCustomDNSEntries()
|
||||
{
|
||||
$entries = getCustomDNSEntries();
|
||||
|
||||
$data = [];
|
||||
foreach ($entries as $entry)
|
||||
$data[] = [ $entry->domain, $entry->ip ];
|
||||
|
||||
return [ "data" => $data ];
|
||||
}
|
||||
|
||||
function getCustomDNSEntries()
|
||||
{
|
||||
global $customDNSFile;
|
||||
|
||||
$entries = [];
|
||||
|
||||
$handle = fopen($customDNSFile, "r");
|
||||
if ($handle)
|
||||
{
|
||||
while (($line = fgets($handle)) !== false) {
|
||||
$line = str_replace("\r","", $line);
|
||||
$line = str_replace("\n","", $line);
|
||||
$explodedLine = explode (" ", $line);
|
||||
|
||||
if (count($explodedLine) != 2)
|
||||
continue;
|
||||
|
||||
$data = new \stdClass();
|
||||
$data->ip = $explodedLine[0];
|
||||
$data->domain = $explodedLine[1];
|
||||
$entries[] = $data;
|
||||
}
|
||||
|
||||
fclose($handle);
|
||||
}
|
||||
|
||||
return $entries;
|
||||
}
|
||||
|
||||
function addCustomDNSEntry()
|
||||
{
|
||||
try
|
||||
{
|
||||
$ip = !empty($_REQUEST['ip']) ? $_REQUEST['ip']: "";
|
||||
$domain = !empty($_REQUEST['domain']) ? $_REQUEST['domain']: "";
|
||||
|
||||
if (empty($ip))
|
||||
return errorJsonResponse("IP must be set");
|
||||
|
||||
$ipType = get_ip_type($ip);
|
||||
|
||||
if (!$ipType)
|
||||
return errorJsonResponse("IP must be valid");
|
||||
|
||||
if (empty($domain))
|
||||
return errorJsonResponse("Domain must be set");
|
||||
|
||||
if (!is_valid_domain_name($domain))
|
||||
return errorJsonResponse("Domain must be valid");
|
||||
|
||||
$existingEntries = getCustomDNSEntries();
|
||||
|
||||
foreach ($existingEntries as $entry)
|
||||
if ($entry->domain == $domain)
|
||||
if (get_ip_type($entry->ip) == $ipType)
|
||||
return errorJsonResponse("This domain already has a custom DNS entry for an IPv" . $ipType);
|
||||
|
||||
exec("sudo pihole -a addcustomdns ".$ip." ".$domain);
|
||||
|
||||
return successJsonResponse();
|
||||
}
|
||||
catch (\Exception $ex)
|
||||
{
|
||||
return errorJsonResponse($ex->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
function deleteCustomDNSEntry()
|
||||
{
|
||||
try
|
||||
{
|
||||
$ip = !empty($_REQUEST['ip']) ? $_REQUEST['ip']: "";
|
||||
$domain = !empty($_REQUEST['domain']) ? $_REQUEST['domain']: "";
|
||||
|
||||
if (empty($ip))
|
||||
return errorJsonResponse("IP must be set");
|
||||
|
||||
if (empty($domain))
|
||||
return errorJsonResponse("Domain must be set");
|
||||
|
||||
$existingEntries = getCustomDNSEntries();
|
||||
|
||||
$found = false;
|
||||
foreach ($existingEntries as $entry)
|
||||
if ($entry->domain == $domain)
|
||||
if ($entry->ip == $ip) {
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!$found)
|
||||
return errorJsonResponse("This domain/ip association does not exist");
|
||||
|
||||
exec("sudo pihole -a removecustomdns ".$ip." ".$domain);
|
||||
|
||||
return successJsonResponse();
|
||||
}
|
||||
catch (\Exception $ex)
|
||||
{
|
||||
return errorJsonResponse($ex->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
function successJsonResponse($message = "")
|
||||
{
|
||||
return [ "success" => true, "message" => $message ];
|
||||
}
|
||||
|
||||
function errorJsonResponse($message = "")
|
||||
{
|
||||
return [ "success" => false, "message" => $message ];
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,319 @@
|
||||
<?php
|
||||
/* 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 getGravityDBFilename()
|
||||
{
|
||||
// Get possible non-standard location of FTL's database
|
||||
$FTLsettings = parse_ini_file("/etc/pihole/pihole-FTL.conf");
|
||||
if(isset($FTLsettings["GRAVITYDB"]))
|
||||
{
|
||||
return $FTLsettings["GRAVITYDB"];
|
||||
}
|
||||
else
|
||||
{
|
||||
return "/etc/pihole/gravity.db";
|
||||
}
|
||||
}
|
||||
|
||||
function getQueriesDBFilename()
|
||||
{
|
||||
// Get possible non-standard location of FTL's database
|
||||
$FTLsettings = parse_ini_file("/etc/pihole/pihole-FTL.conf");
|
||||
if(isset($FTLsettings["DBFILE"]))
|
||||
{
|
||||
return $FTLsettings["DBFILE"];
|
||||
}
|
||||
else
|
||||
{
|
||||
return "/etc/pihole/pihole-FTL.db";
|
||||
}
|
||||
}
|
||||
|
||||
function SQLite3_connect_try($filename, $mode, $trytoreconnect)
|
||||
{
|
||||
try
|
||||
{
|
||||
// connect to database
|
||||
return new SQLite3($filename, $mode);
|
||||
}
|
||||
catch (Exception $exception)
|
||||
{
|
||||
// sqlite3 throws an exception when it is unable to connect, try to reconnect after 3 seconds
|
||||
if($trytoreconnect)
|
||||
{
|
||||
sleep(3);
|
||||
return SQLite3_connect_try($filename, $mode, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we should not try again (or are already trying again!), we return the exception string
|
||||
// so the user gets it on the dashboard
|
||||
return $filename.": ".$exception->getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function SQLite3_connect($filename, $mode=SQLITE3_OPEN_READONLY)
|
||||
{
|
||||
if(strlen($filename) > 0)
|
||||
{
|
||||
$db = SQLite3_connect_try($filename, $mode, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
die("No database available");
|
||||
}
|
||||
if(is_string($db))
|
||||
{
|
||||
die("Error connecting to database\n".$db);
|
||||
}
|
||||
|
||||
// Add busy timeout so methods don't fail immediately when, e.g., FTL is currently reading from the DB
|
||||
$db->busyTimeout(5000);
|
||||
|
||||
return $db;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add domains to a given table
|
||||
*
|
||||
* @param $db object The SQLite3 database connection object
|
||||
* @param $table string The target table
|
||||
* @param $domains array Array of domains (strings) to be added to the table
|
||||
* @param $wildcardstyle boolean Whether to format the input domains in legacy wildcard notation
|
||||
* @param $returnnum boolean Whether to return an integer or a string
|
||||
* @param $type integer The target type (0 = exact whitelist, 1 = exact blacklist, 2 = regex whitelist, 3 = regex blacklist)
|
||||
* @return string Success/error and number of processed domains
|
||||
*/
|
||||
function add_to_table($db, $table, $domains, $comment=null, $wildcardstyle=false, $returnnum=false, $type=-1)
|
||||
{
|
||||
if(!is_int($type))
|
||||
{
|
||||
return "Error: Argument type has to be of type integer (is ".gettype($type).")";
|
||||
}
|
||||
|
||||
// Begin transaction
|
||||
if(!$db->exec("BEGIN TRANSACTION;"))
|
||||
{
|
||||
if($returnnum)
|
||||
return 0;
|
||||
else
|
||||
return "Error: Unable to begin transaction for $table table.";
|
||||
}
|
||||
|
||||
// To which column should the record be added to?
|
||||
if ($table === "adlist")
|
||||
{
|
||||
$field = "address";
|
||||
}
|
||||
else
|
||||
{
|
||||
$field = "domain";
|
||||
}
|
||||
|
||||
// Get initial count of domains in this table
|
||||
if($type === -1)
|
||||
{
|
||||
$countquery = "SELECT COUNT(*) FROM $table;";
|
||||
}
|
||||
else
|
||||
{
|
||||
$countquery = "SELECT COUNT(*) FROM $table WHERE type = $type;";
|
||||
}
|
||||
$initialcount = intval($db->querySingle($countquery));
|
||||
|
||||
// Prepare INSERT SQLite statememt
|
||||
$bindcomment = false;
|
||||
if($table === "domain_audit") {
|
||||
$querystr = "INSERT OR IGNORE INTO $table ($field) VALUES (:$field);";
|
||||
} elseif($type === -1) {
|
||||
$querystr = "INSERT OR IGNORE INTO $table ($field,comment) VALUES (:$field, :comment);";
|
||||
$bindcomment = true;
|
||||
} else {
|
||||
$querystr = "INSERT OR IGNORE INTO $table ($field,comment,type) VALUES (:$field, :comment, $type);";
|
||||
$bindcomment = true;
|
||||
}
|
||||
$stmt = $db->prepare($querystr);
|
||||
|
||||
// Return early if we failed to prepare the SQLite statement
|
||||
if(!$stmt)
|
||||
{
|
||||
if($returnnum)
|
||||
return 0;
|
||||
else
|
||||
return "Error: Failed to prepare statement for $table table (type = $type, field = $field).";
|
||||
}
|
||||
|
||||
// Loop over domains and inject the lines into the database
|
||||
$num = 0;
|
||||
foreach($domains as $domain)
|
||||
{
|
||||
// Limit max length for a domain entry to 253 chars
|
||||
if(strlen($domain) > 253)
|
||||
continue;
|
||||
|
||||
if($wildcardstyle)
|
||||
$domain = "(\\.|^)".str_replace(".","\\.",$domain)."$";
|
||||
|
||||
$stmt->bindValue(":$field", $domain, SQLITE3_TEXT);
|
||||
if($bindcomment) {
|
||||
$stmt->bindValue(":comment", $comment, SQLITE3_TEXT);
|
||||
}
|
||||
|
||||
if($stmt->execute() && $stmt->reset())
|
||||
$num++;
|
||||
else
|
||||
{
|
||||
$stmt->close();
|
||||
if($returnnum)
|
||||
return $num;
|
||||
else
|
||||
{
|
||||
if($num === 1)
|
||||
$plural = "";
|
||||
else
|
||||
$plural = "s";
|
||||
return "Error: ".$db->lastErrorMsg().", added ".$num." domain".$plural;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close prepared statement and return number of processed rows
|
||||
$stmt->close();
|
||||
$db->exec("COMMIT;");
|
||||
|
||||
if($returnnum)
|
||||
return $num;
|
||||
else
|
||||
{
|
||||
$finalcount = intval($db->querySingle($countquery));
|
||||
$modified = $finalcount - $initialcount;
|
||||
|
||||
// If we add less domains than the user specified, then they wanted to add duplicates
|
||||
if($modified !== $num)
|
||||
{
|
||||
$delta = $num - $modified;
|
||||
$extra = " (skipped ".$delta." duplicates)";
|
||||
}
|
||||
else
|
||||
{
|
||||
$extra = "";
|
||||
}
|
||||
|
||||
if($num === 1)
|
||||
$plural = "";
|
||||
else
|
||||
$plural = "s";
|
||||
return "Success, added ".$modified." of ".$num." domain".$plural.$extra;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove domains from a given table
|
||||
*
|
||||
* @param $db object The SQLite3 database connection object
|
||||
* @param $table string The target table
|
||||
* @param $domains array Array of domains (strings) to be removed from the table
|
||||
* @param $returnnum boolean Whether to return an integer or a string
|
||||
* @param $type integer The target type (0 = exact whitelist, 1 = exact blacklist, 2 = regex whitelist, 3 = regex blacklist)
|
||||
* @return string Success/error and number of processed domains
|
||||
*/
|
||||
function remove_from_table($db, $table, $domains, $returnnum=false, $type=-1)
|
||||
{
|
||||
if(!is_int($type))
|
||||
{
|
||||
return "Error: Argument type has to be of type integer (is ".gettype($type).")";
|
||||
}
|
||||
|
||||
// Begin transaction
|
||||
if(!$db->exec("BEGIN TRANSACTION;"))
|
||||
{
|
||||
if($returnnum)
|
||||
return 0;
|
||||
else
|
||||
return "Error: Unable to begin transaction for domainlist table.";
|
||||
}
|
||||
|
||||
// Get initial count of domains in this table
|
||||
if($type === -1)
|
||||
{
|
||||
$countquery = "SELECT COUNT(*) FROM $table;";
|
||||
}
|
||||
else
|
||||
{
|
||||
$countquery = "SELECT COUNT(*) FROM $table WHERE type = $type;";
|
||||
}
|
||||
$initialcount = intval($db->querySingle($countquery));
|
||||
|
||||
// Prepare SQLite statememt
|
||||
if($type === -1)
|
||||
{
|
||||
$querystr = "DELETE FROM $table WHERE domain = :domain AND type = $type;";
|
||||
}
|
||||
else
|
||||
{
|
||||
$querystr = "DELETE FROM $table WHERE domain = :domain;";
|
||||
}
|
||||
$stmt = $db->prepare($querystr);
|
||||
|
||||
// Return early if we failed to prepare the SQLite statement
|
||||
if(!$stmt)
|
||||
{
|
||||
if($returnnum)
|
||||
return 0;
|
||||
else
|
||||
return "Error: Failed to prepare statement for ".$table." table (type = ".$type.").";
|
||||
}
|
||||
|
||||
// Loop over domains and remove the lines from the database
|
||||
$num = 0;
|
||||
foreach($domains as $domain)
|
||||
{
|
||||
$stmt->bindValue(":domain", $domain, SQLITE3_TEXT);
|
||||
|
||||
if($stmt->execute() && $stmt->reset())
|
||||
$num++;
|
||||
else
|
||||
{
|
||||
$stmt->close();
|
||||
if($returnnum)
|
||||
return $num;
|
||||
else
|
||||
{
|
||||
if($num === 1)
|
||||
$plural = "";
|
||||
else
|
||||
$plural = "s";
|
||||
return "Error: ".$db->lastErrorMsg().", removed ".$num." domain".$plural;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close prepared statement and return number or processed rows
|
||||
$stmt->close();
|
||||
$db->exec("COMMIT;");
|
||||
|
||||
if($returnnum)
|
||||
return $num;
|
||||
else
|
||||
{
|
||||
if($num === 1)
|
||||
$plural = "";
|
||||
else
|
||||
$plural = "s";
|
||||
return "Success, removed ".$num." domain".$plural;
|
||||
}
|
||||
}
|
||||
|
||||
class ListType{
|
||||
const whitelist = 0;
|
||||
const blacklist = 1;
|
||||
const regex_whitelist = 2;
|
||||
const regex_blacklist = 3;
|
||||
}
|
||||
@@ -22,10 +22,10 @@
|
||||
<input id="customTimeout" class="form-control" type="number" value="60">
|
||||
<div class="input-group-btn" data-toggle="buttons">
|
||||
<label class="btn btn-default">
|
||||
<input type="radio"/> Secs
|
||||
<input type="radio"> Secs
|
||||
</label>
|
||||
<label id="btnMins" class="btn btn-default active">
|
||||
<input type="radio" /> Mins
|
||||
<input type="radio"> Mins
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -52,17 +52,17 @@
|
||||
<b>Pi-hole Version </b> <?php
|
||||
echo $core_current;
|
||||
if(isset($core_commit)) { echo " (".$core_branch.", ".$core_commit.")"; }
|
||||
if($core_update){ ?> <a class="alert-link lookatme" href="https://github.com/pi-hole/pi-hole/releases" target="_blank">(Update available!)</a><?php } ?>
|
||||
if($core_update){ ?> <a class="alert-link lookatme" href="https://github.com/pi-hole/pi-hole/releases" rel="noopener" target="_blank">(Update available!)</a><?php } ?>
|
||||
<b>Web Interface Version </b><?php
|
||||
echo $web_current;
|
||||
if(isset($web_commit)) { echo " (".$web_branch.", ".$web_commit.")"; }
|
||||
if($web_update){ ?> <a class="alert-link lookatme" href="https://github.com/pi-hole/AdminLTE/releases" target="_blank">(Update available!)</a><?php } ?>
|
||||
if($web_update){ ?> <a class="alert-link lookatme" href="https://github.com/pi-hole/AdminLTE/releases" rel="noopener" target="_blank">(Update available!)</a><?php } ?>
|
||||
<b>FTL Version </b> <?php
|
||||
echo $FTL_current;
|
||||
if(isset($FTL_commit)) { echo " (".$FTL_branch.", ".$FTL_commit.")"; }
|
||||
if($FTL_update){ ?> <a class="alert-link lookatme" href="https://github.com/pi-hole/FTL/releases" target="_blank">(Update available!)</a><?php } ?>
|
||||
if($FTL_update){ ?> <a class="alert-link lookatme" href="https://github.com/pi-hole/FTL/releases" rel="noopener" target="_blank">(Update available!)</a><?php } ?>
|
||||
</div>
|
||||
<div style="display: inline-block"><strong><a href="https://pi-hole.net/donate" target="_blank"><i class="fa fa-heart"></i> Donate</a></strong> if you found this useful.</div>
|
||||
<div style="display: inline-block"><strong><a href="https://pi-hole.net/donate/" rel="noopener" target="_blank"><i class="fa fa-heart"></i> Donate</a></strong> if you found this useful.</div>
|
||||
</footer>
|
||||
</div>
|
||||
<!-- ./wrapper -->
|
||||
|
||||
@@ -13,6 +13,13 @@ function is_valid_domain_name($domain_name)
|
||||
preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name)); // Length of each label
|
||||
}
|
||||
|
||||
function get_ip_type($ip)
|
||||
{
|
||||
return filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) ? 4 :
|
||||
(filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) ? 6 :
|
||||
0);
|
||||
}
|
||||
|
||||
function checkfile($filename) {
|
||||
if(is_readable($filename))
|
||||
{
|
||||
@@ -45,21 +52,4 @@ if(!function_exists('hash_equals')) {
|
||||
}
|
||||
}
|
||||
|
||||
function add_regex($regex, $mode=FILE_APPEND, $append="\n")
|
||||
{
|
||||
global $regexfile;
|
||||
if(file_put_contents($regexfile, $regex.$append, $mode) === FALSE)
|
||||
{
|
||||
$err = error_get_last()["message"];
|
||||
echo "Unable to add regex \"".htmlspecialchars($regex)."\" to ${regexfile}<br>Error message: $err";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Send SIGHUP to pihole-FTL using a frontend command
|
||||
// to force reloading of the regex domains
|
||||
// This will also wipe the resolver's cache
|
||||
echo exec("sudo pihole restartdns reload");
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
<?php
|
||||
/* 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. */
|
||||
|
||||
if(!isset($_GET['list']))
|
||||
die("Missing parameter");
|
||||
|
||||
$listtype = $_GET['list'];
|
||||
|
||||
$basedir = "/etc/pihole/";
|
||||
|
||||
require_once "func.php";
|
||||
|
||||
switch ($listtype) {
|
||||
case "white":
|
||||
$list = array(getListContent("whitelist.txt"));
|
||||
break;
|
||||
|
||||
case "black":
|
||||
$exact = getListContent("blacklist.txt");
|
||||
$regex = getListContent("regex.list");
|
||||
$list = array($exact, $regex);
|
||||
break;
|
||||
|
||||
default:
|
||||
die("Invalid list parameter");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
function getListContent($listname) {
|
||||
global $basedir;
|
||||
$rawList = file_get_contents(checkfile($basedir.$listname));
|
||||
$list = explode("\n", $rawList);
|
||||
|
||||
// Get rid of empty lines and comments
|
||||
for($i = sizeof($list)-1; $i >= 0; $i--) {
|
||||
if(strlen($list[$i]) < 1 || $list[$i][0] === '#')
|
||||
unset($list[$i]);
|
||||
}
|
||||
|
||||
// Re-index list after possible unset() activity
|
||||
$newlist = array_values($list);
|
||||
|
||||
return $newlist;
|
||||
|
||||
}
|
||||
|
||||
function filterArray(&$inArray) {
|
||||
$outArray = array();
|
||||
foreach ($inArray as $key=>$value) {
|
||||
if (is_array($value)) {
|
||||
$outArray[htmlspecialchars($key)] = filterArray($value);
|
||||
} else {
|
||||
$outArray[htmlspecialchars($key)] = htmlspecialchars($value);
|
||||
}
|
||||
}
|
||||
return $outArray;
|
||||
}
|
||||
|
||||
// Protect against XSS attacks
|
||||
$list = filterArray($list);
|
||||
echo json_encode(array_values($list));
|
||||
@@ -1,51 +1,61 @@
|
||||
<?php
|
||||
/* 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 gravity_last_update($raw = false){
|
||||
/*
|
||||
@walter-exit <walter@exclusive-it.nl> | April 23rd, 2018:
|
||||
Checks when the gravity list was last updated, if it exists at all.
|
||||
Returns the info in human-readable format for use on the dashboard,
|
||||
or raw for use by the API.
|
||||
*/
|
||||
$gravitylist = "/etc/pihole/gravity.list";
|
||||
if (file_exists($gravitylist)){
|
||||
$date_file_created_unix = filemtime($gravitylist);
|
||||
$date_file_created = date_create("@".$date_file_created_unix);
|
||||
$date_now = date_create("now");
|
||||
$gravitydiff = date_diff($date_file_created,$date_now);
|
||||
if($raw){
|
||||
$output = array(
|
||||
"file_exists"=> true,
|
||||
"absolute" => $date_file_created_unix,
|
||||
"relative" => array(
|
||||
"days" => $gravitydiff->format("%a"),
|
||||
"hours" => $gravitydiff->format("%H"),
|
||||
"minutes" => $gravitydiff->format("%I"),
|
||||
)
|
||||
);
|
||||
}else{
|
||||
if($gravitydiff->d > 1){
|
||||
$output = $gravitydiff->format("Blocking list updated %a days, %H:%I ago");
|
||||
}elseif($gravitydiff->d == 1){
|
||||
$output = $gravitydiff->format("Blocking list updated one day, %H:%I ago");
|
||||
}else{
|
||||
$output = $gravitydiff->format("Blocking list updated %H:%I ago");
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if($raw){
|
||||
$output = array("file_exists"=>false);
|
||||
}else{
|
||||
$output = "Blocking list not found";
|
||||
}
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
?>
|
||||
<?php
|
||||
/* 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. */
|
||||
|
||||
require "scripts/pi-hole/php/database.php";
|
||||
|
||||
function gravity_last_update($raw = false)
|
||||
{
|
||||
$db = SQLite3_connect(getGravityDBFilename());
|
||||
$date_file_created_unix = $db->querySingle("SELECT value FROM info WHERE property = 'updated';");
|
||||
if($date_file_created_unix === false)
|
||||
{
|
||||
if($raw)
|
||||
{
|
||||
// Array output
|
||||
return array("file_exists" => false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// String output
|
||||
return "Gravity database not available";
|
||||
}
|
||||
}
|
||||
// Now that we know that $date_file_created_unix is a valid response, we can convert it to an integer
|
||||
$date_file_created_unix = intval($date_file_created_unix);
|
||||
$date_file_created = date_create("@".$date_file_created_unix);
|
||||
$date_now = date_create("now");
|
||||
$gravitydiff = date_diff($date_file_created,$date_now);
|
||||
if($raw)
|
||||
{
|
||||
// Array output
|
||||
return array(
|
||||
"file_exists"=> true,
|
||||
"absolute" => $date_file_created_unix,
|
||||
"relative" => array(
|
||||
"days" => intval($gravitydiff->format("%a")),
|
||||
"hours" => intval($gravitydiff->format("%H")),
|
||||
"minutes" => intval($gravitydiff->format("%I")),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if($gravitydiff->d > 1)
|
||||
{
|
||||
// String output (more than one day ago)
|
||||
return $gravitydiff->format("Blocking list updated %a days, %H:%I (hh:mm) ago");
|
||||
}
|
||||
elseif($gravitydiff->d == 1)
|
||||
{
|
||||
// String output (one day ago)
|
||||
return $gravitydiff->format("Blocking list updated one day, %H:%I (hh:mm) ago");
|
||||
}
|
||||
|
||||
// String output (less than one day ago)
|
||||
return $gravitydiff->format("Blocking list updated %H:%I (hh:mm) ago");
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -0,0 +1,812 @@
|
||||
<?php
|
||||
/* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2019 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. */
|
||||
|
||||
require_once('auth.php');
|
||||
|
||||
// Authentication checks
|
||||
if (isset($_POST['token'])) {
|
||||
check_cors();
|
||||
check_csrf($_POST['token']);
|
||||
} else {
|
||||
log_and_die('Not allowed (login session invalid or expired, please relogin on the Pi-hole dashboard)!');
|
||||
}
|
||||
|
||||
$reload = false;
|
||||
|
||||
require_once('func.php');
|
||||
require_once('database.php');
|
||||
$GRAVITYDB = getGravityDBFilename();
|
||||
$db = SQLite3_connect($GRAVITYDB, SQLITE3_OPEN_READWRITE);
|
||||
|
||||
function JSON_success($message = null)
|
||||
{
|
||||
header('Content-type: application/json');
|
||||
echo json_encode(array('success' => true, 'message' => $message));
|
||||
}
|
||||
|
||||
function JSON_error($message = null)
|
||||
{
|
||||
header('Content-type: application/json');
|
||||
$response = array('success' => false, 'message' => $message);
|
||||
if (isset($_POST['action'])) {
|
||||
array_push($response, array('action' => $_POST['action']));
|
||||
}
|
||||
echo json_encode($response);
|
||||
}
|
||||
|
||||
if ($_POST['action'] == 'get_groups') {
|
||||
// List all available groups
|
||||
try {
|
||||
$query = $db->query('SELECT * FROM "group";');
|
||||
$data = array();
|
||||
while (($res = $query->fetchArray(SQLITE3_ASSOC)) !== false) {
|
||||
array_push($data, $res);
|
||||
}
|
||||
echo json_encode(array('data' => $data));
|
||||
} catch (\Exception $ex) {
|
||||
JSON_error($ex->getMessage());
|
||||
}
|
||||
} elseif ($_POST['action'] == 'add_group') {
|
||||
// Add new group
|
||||
try {
|
||||
$names = explode(' ', trim($_POST['name']));
|
||||
$total = count($names);
|
||||
$added = 0;
|
||||
$stmt = $db->prepare('INSERT INTO "group" (name,description) VALUES (:name,:desc)');
|
||||
if (!$stmt) {
|
||||
throw new Exception('While preparing statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':desc', $_POST['desc'], SQLITE3_TEXT)) {
|
||||
throw new Exception('While binding desc: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
foreach ($names as $name) {
|
||||
if (!$stmt->bindValue(':name', $name, SQLITE3_TEXT)) {
|
||||
throw new Exception('While binding name: <strong>' . $db->lastErrorMsg() . '</strong><br>'.
|
||||
'Added ' . $added . " out of ". $total . " groups");
|
||||
}
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
throw new Exception('While executing: <strong>' . $db->lastErrorMsg() . '</strong><br>'.
|
||||
'Added ' . $added . " out of ". $total . " groups");
|
||||
}
|
||||
$added++;
|
||||
}
|
||||
|
||||
$reload = true;
|
||||
JSON_success();
|
||||
} catch (\Exception $ex) {
|
||||
JSON_error($ex->getMessage());
|
||||
}
|
||||
} elseif ($_POST['action'] == 'edit_group') {
|
||||
// Edit group identified by ID
|
||||
try {
|
||||
$stmt = $db->prepare('UPDATE "group" SET enabled=:enabled, name=:name, description=:desc WHERE id = :id');
|
||||
if (!$stmt) {
|
||||
throw new Exception('While preparing statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
$status = ((int) $_POST['status']) !== 0 ? 1 : 0;
|
||||
if (!$stmt->bindValue(':enabled', $status, SQLITE3_INTEGER)) {
|
||||
throw new Exception('While binding enabled: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':name', $_POST['name'], SQLITE3_TEXT)) {
|
||||
throw new Exception('While binding name: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
$desc = $_POST['desc'];
|
||||
if (strlen($desc) == 0) {
|
||||
// Store NULL in database for empty descriptions
|
||||
$desc = null;
|
||||
}
|
||||
if (!$stmt->bindValue(':desc', $desc, SQLITE3_TEXT)) {
|
||||
throw new Exception('While binding desc: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':id', intval($_POST['id']), SQLITE3_INTEGER)) {
|
||||
throw new Exception('While binding id: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
throw new Exception('While executing: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
$reload = true;
|
||||
JSON_success();
|
||||
} catch (\Exception $ex) {
|
||||
JSON_error($ex->getMessage());
|
||||
}
|
||||
} elseif ($_POST['action'] == 'delete_group') {
|
||||
// Delete group identified by ID
|
||||
try {
|
||||
$table_name = ['domainlist_by_group', 'client_by_group', 'adlist_by_group', 'group'];
|
||||
$table_keys = ['group_id', 'group_id', 'group_id', 'id'];
|
||||
for ($i = 0; $i < count($table_name); $i++) {
|
||||
$table = $table_name[$i];
|
||||
$key = $table_keys[$i];
|
||||
|
||||
$stmt = $db->prepare("DELETE FROM \"$table\" WHERE $key = :id;");
|
||||
if (!$stmt) {
|
||||
throw new Exception("While preparing DELETE FROM $table statement: " . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':id', intval($_POST['id']), SQLITE3_INTEGER)) {
|
||||
throw new Exception("While binding id to DELETE FROM $table statement: " . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
throw new Exception("While executing DELETE FROM $table statement: " . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->reset()) {
|
||||
throw new Exception("While resetting DELETE FROM $table statement: " . $db->lastErrorMsg());
|
||||
}
|
||||
}
|
||||
$reload = true;
|
||||
JSON_success();
|
||||
} catch (\Exception $ex) {
|
||||
JSON_error($ex->getMessage());
|
||||
}
|
||||
} elseif ($_POST['action'] == 'get_clients') {
|
||||
// List all available groups
|
||||
try {
|
||||
$QUERYDB = getQueriesDBFilename();
|
||||
$FTLdb = SQLite3_connect($QUERYDB);
|
||||
|
||||
$query = $db->query('SELECT * FROM client;');
|
||||
if (!$query) {
|
||||
throw new Exception('Error while querying gravity\'s client table: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
$data = array();
|
||||
while (($res = $query->fetchArray(SQLITE3_ASSOC)) !== false) {
|
||||
$group_query = $db->query('SELECT group_id FROM client_by_group WHERE client_id = ' . $res['id'] . ';');
|
||||
if (!$group_query) {
|
||||
throw new Exception('Error while querying gravity\'s client_by_group table: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
$stmt = $FTLdb->prepare('SELECT name FROM network WHERE id = (SELECT network_id FROM network_addresses WHERE ip = :ip);');
|
||||
if (!$stmt) {
|
||||
throw new Exception('Error while preparing network table statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':ip', $res['ip'], SQLITE3_TEXT)) {
|
||||
throw new Exception('While binding to network table statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
$result = $stmt->execute();
|
||||
if (!$result) {
|
||||
throw new Exception('While executing network table statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
// There will always be a result. Unknown host names are NULL
|
||||
$name_result = $result->fetchArray(SQLITE3_ASSOC);
|
||||
$res['name'] = $name_result['name'];
|
||||
|
||||
$groups = array();
|
||||
while ($gres = $group_query->fetchArray(SQLITE3_ASSOC)) {
|
||||
array_push($groups, $gres['group_id']);
|
||||
}
|
||||
$res['groups'] = $groups;
|
||||
array_push($data, $res);
|
||||
}
|
||||
|
||||
echo json_encode(array('data' => $data));
|
||||
} catch (\Exception $ex) {
|
||||
JSON_error($ex->getMessage());
|
||||
}
|
||||
} elseif ($_POST['action'] == 'get_unconfigured_clients') {
|
||||
// List all available clients WITHOUT already configured clients
|
||||
try {
|
||||
$QUERYDB = getQueriesDBFilename();
|
||||
$FTLdb = SQLite3_connect($QUERYDB);
|
||||
|
||||
$query = $FTLdb->query('SELECT DISTINCT ip,network.name FROM network_addresses AS name LEFT JOIN network ON network.id = network_id ORDER BY ip ASC;');
|
||||
if (!$query) {
|
||||
throw new Exception('Error while querying FTL\'s database: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
// Loop over results
|
||||
$ips = array();
|
||||
while ($res = $query->fetchArray(SQLITE3_ASSOC)) {
|
||||
$ips[$res['ip']] = $res['name'] !== null ? $res['name'] : '';
|
||||
}
|
||||
$FTLdb->close();
|
||||
|
||||
$query = $db->query('SELECT ip FROM client;');
|
||||
if (!$query) {
|
||||
throw new Exception('Error while querying gravity\'s database: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
// Loop over results, remove already configured clients
|
||||
while (($res = $query->fetchArray(SQLITE3_ASSOC)) !== false) {
|
||||
if (isset($ips[$res['ip']])) {
|
||||
unset($ips[$res['ip']]);
|
||||
}
|
||||
}
|
||||
|
||||
echo json_encode($ips);
|
||||
} catch (\Exception $ex) {
|
||||
JSON_error($ex->getMessage());
|
||||
}
|
||||
} elseif ($_POST['action'] == 'add_client') {
|
||||
// Add new client
|
||||
try {
|
||||
$ips = explode(' ', trim($_POST['ip']));
|
||||
$total = count($ips);
|
||||
$added = 0;
|
||||
$stmt = $db->prepare('INSERT INTO client (ip,comment) VALUES (:ip,:comment)');
|
||||
if (!$stmt) {
|
||||
throw new Exception('While preparing statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
foreach ($ips as $ip) {
|
||||
if (!$stmt->bindValue(':ip', $ip, SQLITE3_TEXT)) {
|
||||
throw new Exception('While binding ip: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
$comment = $_POST['comment'];
|
||||
if (strlen($comment) == 0) {
|
||||
// Store NULL in database for empty comments
|
||||
$comment = null;
|
||||
}
|
||||
if (!$stmt->bindValue(':comment', $comment, SQLITE3_TEXT)) {
|
||||
throw new Exception('While binding comment: <strong>' . $db->lastErrorMsg() . '</strong><br>'.
|
||||
'Added ' . $added . " out of ". $total . " clients");
|
||||
}
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
throw new Exception('While executing: <strong>' . $db->lastErrorMsg() . '</strong><br>'.
|
||||
'Added ' . $added . " out of ". $total . " clients");
|
||||
}
|
||||
$added++;
|
||||
}
|
||||
|
||||
$reload = true;
|
||||
JSON_success();
|
||||
} catch (\Exception $ex) {
|
||||
JSON_error($ex->getMessage());
|
||||
}
|
||||
} elseif ($_POST['action'] == 'edit_client') {
|
||||
// Edit client identified by ID
|
||||
try {
|
||||
$stmt = $db->prepare('UPDATE client SET comment=:comment WHERE id = :id');
|
||||
if (!$stmt) {
|
||||
throw new Exception('While preparing statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
$comment = $_POST['comment'];
|
||||
if (strlen($comment) == 0) {
|
||||
// Store NULL in database for empty comments
|
||||
$comment = null;
|
||||
}
|
||||
if (!$stmt->bindValue(':comment', $comment, SQLITE3_TEXT)) {
|
||||
throw new Exception('While binding comment: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':id', intval($_POST['id']), SQLITE3_INTEGER)) {
|
||||
throw new Exception('While binding id: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
throw new Exception('While executing: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
$stmt = $db->prepare('DELETE FROM client_by_group WHERE client_id = :id');
|
||||
if (!$stmt) {
|
||||
throw new Exception('While preparing DELETE statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':id', intval($_POST['id']), SQLITE3_INTEGER)) {
|
||||
throw new Exception('While binding id: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
throw new Exception('While executing DELETE statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
$db->query('BEGIN TRANSACTION;');
|
||||
foreach ($_POST['groups'] as $gid) {
|
||||
$stmt = $db->prepare('INSERT INTO client_by_group (client_id,group_id) VALUES(:id,:gid);');
|
||||
if (!$stmt) {
|
||||
throw new Exception('While preparing INSERT INTO statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':id', intval($_POST['id']), SQLITE3_INTEGER)) {
|
||||
throw new Exception('While binding id: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':gid', intval($gid), SQLITE3_INTEGER)) {
|
||||
throw new Exception('While binding gid: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
throw new Exception('While executing INSERT INTO statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
}
|
||||
$db->query('COMMIT;');
|
||||
|
||||
$reload = true;
|
||||
JSON_success();
|
||||
} catch (\Exception $ex) {
|
||||
JSON_error($ex->getMessage());
|
||||
}
|
||||
} elseif ($_POST['action'] == 'delete_client') {
|
||||
// Delete client identified by ID
|
||||
try {
|
||||
$stmt = $db->prepare('DELETE FROM client_by_group WHERE client_id=:id');
|
||||
if (!$stmt) {
|
||||
throw new Exception('While preparing client_by_group statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':id', intval($_POST['id']), SQLITE3_INTEGER)) {
|
||||
throw new Exception('While binding id to client_by_group statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
throw new Exception('While executing client_by_group statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
$stmt = $db->prepare('DELETE FROM client WHERE id=:id');
|
||||
if (!$stmt) {
|
||||
throw new Exception('While preparing client statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':id', intval($_POST['id']), SQLITE3_INTEGER)) {
|
||||
throw new Exception('While binding id to client statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
throw new Exception('While executing client statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
$reload = true;
|
||||
JSON_success();
|
||||
} catch (\Exception $ex) {
|
||||
JSON_error($ex->getMessage());
|
||||
}
|
||||
} elseif ($_POST['action'] == 'get_domains') {
|
||||
// List all available groups
|
||||
try {
|
||||
$limit = "";
|
||||
if (isset($_POST["showtype"]) && $_POST["showtype"] === "white"){
|
||||
$limit = " WHERE type = 0 OR type = 2";
|
||||
} elseif (isset($_POST["showtype"]) && $_POST["showtype"] === "black"){
|
||||
$limit = " WHERE type = 1 OR type = 3";
|
||||
}
|
||||
$query = $db->query('SELECT * FROM domainlist'.$limit);
|
||||
if (!$query) {
|
||||
throw new Exception('Error while querying gravity\'s domainlist table: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
$data = array();
|
||||
while (($res = $query->fetchArray(SQLITE3_ASSOC)) !== false) {
|
||||
$group_query = $db->query('SELECT group_id FROM domainlist_by_group WHERE domainlist_id = ' . $res['id'] . ';');
|
||||
if (!$group_query) {
|
||||
throw new Exception('Error while querying gravity\'s domainlist_by_group table: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
$groups = array();
|
||||
while ($gres = $group_query->fetchArray(SQLITE3_ASSOC)) {
|
||||
array_push($groups, $gres['group_id']);
|
||||
}
|
||||
$res['groups'] = $groups;
|
||||
if (extension_loaded("intl") &&
|
||||
($res['type'] === ListType::whitelist ||
|
||||
$res['type'] === ListType::blacklist) ) {
|
||||
|
||||
// Try to convert possible IDNA domain to Unicode, we try the UTS #46 standard first
|
||||
// as this is the new default, see https://sourceforge.net/p/icu/mailman/message/32980778/
|
||||
// We know that this fails for some Google domains violating the standard
|
||||
// see https://github.com/pi-hole/AdminLTE/issues/1223
|
||||
$utf8_domain = false;
|
||||
if (defined("INTL_IDNA_VARIANT_UTS46")) {
|
||||
// We have to use the option IDNA_NONTRANSITIONAL_TO_ASCII here
|
||||
// to ensure sparkasse-gießen.de is not converted into
|
||||
// sparkass-giessen.de but into xn--sparkasse-gieen-2ib.de
|
||||
// as mandated by the UTS #46 standard
|
||||
$utf8_domain = idn_to_utf8($res['domain'], IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46);
|
||||
}
|
||||
|
||||
// If conversion failed, try with the (deprecated!) IDNA 2003 variant
|
||||
// We have to check for its existance as support of this variant is
|
||||
// scheduled for removal with PHP 8.0
|
||||
// see https://wiki.php.net/rfc/deprecate-and-remove-intl_idna_variant_2003
|
||||
if ($utf8_domain === false && defined("INTL_IDNA_VARIANT_2003")) {
|
||||
$utf8_domain = idn_to_utf8($res['domain'], IDNA_DEFAULT, INTL_IDNA_VARIANT_2003);
|
||||
}
|
||||
|
||||
// Convert domain name to international form
|
||||
// if applicable and extension is available
|
||||
if ($utf8_domain !== false && $res['domain'] !== $utf8_domain) {
|
||||
$res['domain'] = $utf8_domain.' ('.$res['domain'].')';
|
||||
}
|
||||
}
|
||||
array_push($data, $res);
|
||||
}
|
||||
|
||||
|
||||
echo json_encode(array('data' => $data));
|
||||
} catch (\Exception $ex) {
|
||||
JSON_error($ex->getMessage());
|
||||
}
|
||||
} elseif ($_POST['action'] == 'add_domain') {
|
||||
// Add new domain
|
||||
try {
|
||||
$domains = explode(' ', trim($_POST['domain']));
|
||||
$total = count($domains);
|
||||
$added = 0;
|
||||
$stmt = $db->prepare('INSERT INTO domainlist (domain,type,comment) VALUES (:domain,:type,:comment)');
|
||||
if (!$stmt) {
|
||||
throw new Exception('While preparing statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
$type = intval($_POST['type']);
|
||||
|
||||
if (!$stmt->bindValue(':type', $type, SQLITE3_TEXT)) {
|
||||
throw new Exception('While binding type: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':comment', $_POST['comment'], SQLITE3_TEXT)) {
|
||||
throw new Exception('While binding comment: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
foreach ($domains as $domain) {
|
||||
$input = $domain;
|
||||
// Convert domain name to IDNA ASCII form for international domains
|
||||
if (extension_loaded("intl")) {
|
||||
// Be prepared that this may fail and see our comments above
|
||||
// (search for "idn_to_utf8)
|
||||
$idn_domain = false;
|
||||
if (defined("INTL_IDNA_VARIANT_UTS46")) {
|
||||
$idn_domain = idn_to_ascii($domain, IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46);
|
||||
}
|
||||
if ($idn_domain === false && defined("INTL_IDNA_VARIANT_2003")) {
|
||||
$idn_domain = idn_to_ascii($domain, IDNA_DEFAULT, INTL_IDNA_VARIANT_2003);
|
||||
}
|
||||
if($idn_domain !== false) {
|
||||
$domain = $idn_domain;
|
||||
}
|
||||
}
|
||||
|
||||
if(strlen($_POST['type']) === 2 && $_POST['type'][1] === 'W')
|
||||
{
|
||||
// Apply wildcard-style formatting
|
||||
$domain = "(\\.|^)".str_replace(".","\\.",$domain)."$";
|
||||
}
|
||||
|
||||
if($type === ListType::whitelist || $type === ListType::blacklist)
|
||||
{
|
||||
// If adding to the exact lists, we convert the domain lower case and check whether it is valid
|
||||
$domain = strtolower($domain);
|
||||
if(filter_var($domain, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME) === false)
|
||||
{
|
||||
// This is the case when idn_to_ascii() modified the string
|
||||
if($input !== $domain && strlen($domain) > 0)
|
||||
$errormsg = 'Domain ' . htmlentities($input) . ' (converted to "' . htmlentities(utf8_encode($domain)) . '") is not a valid domain.';
|
||||
elseif($input !== $domain)
|
||||
$errormsg = 'Domain ' . htmlentities($input) . ' is not a valid domain.';
|
||||
else
|
||||
$errormsg = 'Domain ' . htmlentities(utf8_encode($domain)) . ' is not a valid domain.';
|
||||
throw new Exception($errormsg . '<br>Added ' . $added . " out of ". $total . " domains");
|
||||
}
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':domain', $domain, SQLITE3_TEXT)) {
|
||||
throw new Exception('While binding domain: <strong>' . $db->lastErrorMsg() . '</strong><br>'.
|
||||
'Added ' . $added . " out of ". $total . " domains");
|
||||
}
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
throw new Exception('While executing: <strong>' . $db->lastErrorMsg() . '</strong><br>'.
|
||||
'Added ' . $added . " out of ". $total . " domains");
|
||||
}
|
||||
$added++;
|
||||
}
|
||||
|
||||
$reload = true;
|
||||
JSON_success();
|
||||
} catch (\Exception $ex) {
|
||||
JSON_error($ex->getMessage());
|
||||
}
|
||||
} elseif ($_POST['action'] == 'edit_domain') {
|
||||
// Edit domain identified by ID
|
||||
try {
|
||||
$stmt = $db->prepare('UPDATE domainlist SET enabled=:enabled, comment=:comment, type=:type WHERE id = :id');
|
||||
if (!$stmt) {
|
||||
throw new Exception('While preparing statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
$status = intval($_POST['status']);
|
||||
if ($status !== 0) {
|
||||
$status = 1;
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':enabled', $status, SQLITE3_INTEGER)) {
|
||||
throw new Exception('While binding enabled: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
$comment = $_POST['comment'];
|
||||
if (strlen($comment) == 0) {
|
||||
// Store NULL in database for empty comments
|
||||
$comment = null;
|
||||
}
|
||||
if (!$stmt->bindValue(':comment', $comment, SQLITE3_TEXT)) {
|
||||
throw new Exception('While binding comment: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':type', intval($_POST['type']), SQLITE3_INTEGER)) {
|
||||
throw new Exception('While binding type: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':id', intval($_POST['id']), SQLITE3_INTEGER)) {
|
||||
throw new Exception('While binding id: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
throw new Exception('While executing: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (isset($_POST['groups'])) {
|
||||
$stmt = $db->prepare('DELETE FROM domainlist_by_group WHERE domainlist_id = :id');
|
||||
if (!$stmt) {
|
||||
throw new Exception('While preparing DELETE statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':id', intval($_POST['id']), SQLITE3_INTEGER)) {
|
||||
throw new Exception('While binding id: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
throw new Exception('While executing DELETE statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
$db->query('BEGIN TRANSACTION;');
|
||||
foreach ($_POST['groups'] as $gid) {
|
||||
$stmt = $db->prepare('INSERT INTO domainlist_by_group (domainlist_id,group_id) VALUES(:id,:gid);');
|
||||
if (!$stmt) {
|
||||
throw new Exception('While preparing INSERT INTO statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':id', intval($_POST['id']), SQLITE3_INTEGER)) {
|
||||
throw new Exception('While binding id: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':gid', intval($gid), SQLITE3_INTEGER)) {
|
||||
throw new Exception('While binding gid: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
throw new Exception('While executing INSERT INTO statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
}
|
||||
$db->query('COMMIT;');
|
||||
}
|
||||
|
||||
$reload = true;
|
||||
JSON_success();
|
||||
} catch (\Exception $ex) {
|
||||
JSON_error($ex->getMessage());
|
||||
}
|
||||
} elseif ($_POST['action'] == 'delete_domain') {
|
||||
// Delete domain identified by ID
|
||||
try {
|
||||
$stmt = $db->prepare('DELETE FROM domainlist_by_group WHERE domainlist_id=:id');
|
||||
if (!$stmt) {
|
||||
throw new Exception('While preparing domainlist_by_group statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':id', intval($_POST['id']), SQLITE3_INTEGER)) {
|
||||
throw new Exception('While binding id to domainlist_by_group statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
throw new Exception('While executing domainlist_by_group statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
$stmt = $db->prepare('DELETE FROM domainlist WHERE id=:id');
|
||||
if (!$stmt) {
|
||||
throw new Exception('While preparing domainlist statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':id', intval($_POST['id']), SQLITE3_INTEGER)) {
|
||||
throw new Exception('While binding id to domainlist statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
throw new Exception('While executing domainlist statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
$reload = true;
|
||||
JSON_success();
|
||||
} catch (\Exception $ex) {
|
||||
JSON_error($ex->getMessage());
|
||||
}
|
||||
} elseif ($_POST['action'] == 'get_adlists') {
|
||||
// List all available groups
|
||||
try {
|
||||
$query = $db->query('SELECT * FROM adlist;');
|
||||
if (!$query) {
|
||||
throw new Exception('Error while querying gravity\'s adlist table: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
$data = array();
|
||||
while (($res = $query->fetchArray(SQLITE3_ASSOC)) !== false) {
|
||||
$group_query = $db->query('SELECT group_id FROM adlist_by_group WHERE adlist_id = ' . $res['id'] . ';');
|
||||
if (!$group_query) {
|
||||
throw new Exception('Error while querying gravity\'s adlist_by_group table: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
$groups = array();
|
||||
while ($gres = $group_query->fetchArray(SQLITE3_ASSOC)) {
|
||||
array_push($groups, $gres['group_id']);
|
||||
}
|
||||
$res['groups'] = $groups;
|
||||
array_push($data, $res);
|
||||
}
|
||||
|
||||
|
||||
echo json_encode(array('data' => $data));
|
||||
} catch (\Exception $ex) {
|
||||
JSON_error($ex->getMessage());
|
||||
}
|
||||
} elseif ($_POST['action'] == 'add_adlist') {
|
||||
// Add new adlist
|
||||
try {
|
||||
$addresses = explode(' ', trim($_POST['address']));
|
||||
$total = count($addresses);
|
||||
$added = 0;
|
||||
|
||||
$stmt = $db->prepare('INSERT INTO adlist (address,comment) VALUES (:address,:comment)');
|
||||
if (!$stmt) {
|
||||
throw new Exception('While preparing statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':comment', $_POST['comment'], SQLITE3_TEXT)) {
|
||||
throw new Exception('While binding comment: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
foreach ($addresses as $address) {
|
||||
if(preg_match("/[^a-zA-Z0-9:\/?&%=~._()-]/", $address) !== 0) {
|
||||
throw new Exception('<strong>Invalid adlist URL ' . htmlentities($address) . '</strong><br>'.
|
||||
'Added ' . $added . " out of ". $total . " adlists");
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':address', $address, SQLITE3_TEXT)) {
|
||||
throw new Exception('While binding address: <strong>' . $db->lastErrorMsg() . '</strong><br>'.
|
||||
'Added ' . $added . " out of ". $total . " adlists");
|
||||
}
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
throw new Exception('While executing: <strong>' . $db->lastErrorMsg() . '</strong><br>'.
|
||||
'Added ' . $added . " out of ". $total . " adlists");
|
||||
}
|
||||
$added++;
|
||||
}
|
||||
|
||||
$reload = true;
|
||||
JSON_success();
|
||||
} catch (\Exception $ex) {
|
||||
JSON_error($ex->getMessage());
|
||||
}
|
||||
} elseif ($_POST['action'] == 'edit_adlist') {
|
||||
// Edit adlist identified by ID
|
||||
try {
|
||||
$stmt = $db->prepare('UPDATE adlist SET enabled=:enabled, comment=:comment WHERE id = :id');
|
||||
if (!$stmt) {
|
||||
throw new Exception('While preparing statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
$status = intval($_POST['status']);
|
||||
if ($status !== 0) {
|
||||
$status = 1;
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':enabled', $status, SQLITE3_INTEGER)) {
|
||||
throw new Exception('While binding enabled: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
$comment = $_POST['comment'];
|
||||
if (strlen($comment) == 0) {
|
||||
// Store NULL in database for empty comments
|
||||
$comment = null;
|
||||
}
|
||||
if (!$stmt->bindValue(':comment', $comment, SQLITE3_TEXT)) {
|
||||
throw new Exception('While binding comment: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':id', intval($_POST['id']), SQLITE3_INTEGER)) {
|
||||
throw new Exception('While binding id: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
throw new Exception('While executing: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
$stmt = $db->prepare('DELETE FROM adlist_by_group WHERE adlist_id = :id');
|
||||
if (!$stmt) {
|
||||
throw new Exception('While preparing DELETE statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':id', intval($_POST['id']), SQLITE3_INTEGER)) {
|
||||
throw new Exception('While binding id: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
throw new Exception('While executing DELETE statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
$db->query('BEGIN TRANSACTION;');
|
||||
foreach ($_POST['groups'] as $gid) {
|
||||
$stmt = $db->prepare('INSERT INTO adlist_by_group (adlist_id,group_id) VALUES(:id,:gid);');
|
||||
if (!$stmt) {
|
||||
throw new Exception('While preparing INSERT INTO statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':id', intval($_POST['id']), SQLITE3_INTEGER)) {
|
||||
throw new Exception('While binding id: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':gid', intval($gid), SQLITE3_INTEGER)) {
|
||||
throw new Exception('While binding gid: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
throw new Exception('While executing INSERT INTO statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
}
|
||||
$db->query('COMMIT;');
|
||||
|
||||
$reload = true;
|
||||
JSON_success();
|
||||
} catch (\Exception $ex) {
|
||||
JSON_error($ex->getMessage());
|
||||
}
|
||||
} elseif ($_POST['action'] == 'delete_adlist') {
|
||||
// Delete adlist identified by ID
|
||||
try {
|
||||
$stmt = $db->prepare('DELETE FROM adlist_by_group WHERE adlist_id=:id');
|
||||
if (!$stmt) {
|
||||
throw new Exception('While preparing adlist_by_group statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':id', intval($_POST['id']), SQLITE3_INTEGER)) {
|
||||
throw new Exception('While binding id to adlist_by_group statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
throw new Exception('While executing adlist_by_group statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
$stmt = $db->prepare('DELETE FROM adlist WHERE id=:id');
|
||||
if (!$stmt) {
|
||||
throw new Exception('While preparing adlist statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->bindValue(':id', intval($_POST['id']), SQLITE3_INTEGER)) {
|
||||
throw new Exception('While binding id to adlist statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
throw new Exception('While executing adlist statement: ' . $db->lastErrorMsg());
|
||||
}
|
||||
|
||||
$reload = true;
|
||||
JSON_success();
|
||||
} catch (\Exception $ex) {
|
||||
JSON_error($ex->getMessage());
|
||||
}
|
||||
} else {
|
||||
log_and_die('Requested action not supported!');
|
||||
}
|
||||
// Reload lists in pihole-FTL after having added something
|
||||
if ($reload) {
|
||||
echo shell_exec('sudo pihole restartdns reload-lists');
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
require "scripts/pi-hole/php/auth.php";
|
||||
require "scripts/pi-hole/php/password.php";
|
||||
$scriptname = basename($_SERVER['SCRIPT_FILENAME']);
|
||||
|
||||
check_cors();
|
||||
|
||||
@@ -172,72 +173,83 @@
|
||||
}
|
||||
|
||||
?>
|
||||
<!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.
|
||||
* Please see LICENSE file for your rights under this license. -->
|
||||
<html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self' https://api.github.com; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'">
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self' https://api.github.com; script-src 'self' 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline'">
|
||||
<title>Pi-hole Admin Console</title>
|
||||
<!-- Usually browsers proactively perform domain name resolution on links that the user may choose to follow. We disable DNS prefetching here -->
|
||||
<meta http-equiv="x-dns-prefetch-control" content="off">
|
||||
<meta http-equiv="cache-control" content="max-age=60,private">
|
||||
<!-- Tell the browser to be responsive to screen width -->
|
||||
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
|
||||
<link rel="shortcut icon" href="img/favicon.png" type="image/x-icon" />
|
||||
<meta name="theme-color" content="#367fa9">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="img/favicon.png">
|
||||
<link rel="icon" type="image/png" sizes="192x192" href="img/logo.svg">
|
||||
<link rel="icon" type="image/png" sizes="96x96" href="img/logo.svg">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<link rel="apple-touch-icon" href="img/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" href="img/favicons/favicon-32x32.png" sizes="32x32" type="image/png">
|
||||
<link rel="icon" href="img/favicons/favicon-16x16.png" sizes="16x16" type="image/png">
|
||||
<link rel="manifest" href="img/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="img/favicons/safari-pinned-tab.svg" color="#367fa9">
|
||||
<link rel="shortcut icon" href="img/favicons/favicon.ico">
|
||||
<meta name="msapplication-TileColor" content="#367fa9">
|
||||
<meta name="msapplication-TileImage" content="img/logo.svg">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="msapplication-TileImage" content="img/favicons/mstile-150x150.png">
|
||||
<meta name="theme-color" content="#367fa9">
|
||||
|
||||
<link href="style/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
|
||||
<link href="style/vendor/font-awesome-5.6.3/css/all.min.css" rel="stylesheet" type="text/css" />
|
||||
<link href="style/vendor/ionicons-2.0.1/css/ionicons.min.css" rel="stylesheet" type="text/css" />
|
||||
<link href="style/vendor/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css" />
|
||||
<link href="style/vendor/daterangepicker.css" rel="stylesheet" type="text/css" />
|
||||
<link rel="stylesheet" href="style/vendor/SourceSansPro/SourceSansPro.css">
|
||||
<link rel="stylesheet" href="style/vendor/bootstrap/css/bootstrap.min.css">
|
||||
|
||||
<link href="style/vendor/AdminLTE.min.css" rel="stylesheet" type="text/css" />
|
||||
<link href="style/vendor/skin-blue.min.css" rel="stylesheet" type="text/css" />
|
||||
<link href="style/pi-hole.css" rel="stylesheet" type="text/css" />
|
||||
<link rel="icon" type="image/png" sizes="160x160" href="img/logo.svg" />
|
||||
<link rel="stylesheet" href="style/vendor/font-awesome-5.11.2/css/all.min.css">
|
||||
|
||||
<!--[if lt IE 9]>
|
||||
<script src="scripts/vendor/html5shiv.min.js"></script>
|
||||
<script src="scripts/vendor/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
<link rel="stylesheet" href="style/vendor/dataTables.bootstrap.min.css">
|
||||
<link rel="stylesheet" href="style/vendor/daterangepicker.css">
|
||||
|
||||
<link rel="stylesheet" href="style/vendor/AdminLTE.min.css">
|
||||
<link rel="stylesheet" href="style/vendor/skin-blue.min.css">
|
||||
<link rel="stylesheet" href="style/vendor/animate.css">
|
||||
|
||||
<link rel="stylesheet" href="style/pi-hole.css">
|
||||
<noscript><link rel="stylesheet" href="style/vendor/js-warn.css"></noscript>
|
||||
|
||||
<script src="scripts/vendor/jquery.min.js"></script>
|
||||
<script src="scripts/vendor/jquery-ui.min.js"></script>
|
||||
<script src="style/vendor/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script src="scripts/vendor/app.min.js"></script>
|
||||
<script src="scripts/vendor/bootstrap-notify.min.js"></script>
|
||||
|
||||
<?php if(in_array($scriptname, array("groups.php", "groups-clients.php", "groups-domains.php", "groups-adlists.php"))){ ?>
|
||||
<script src="style/vendor/bootstrap/js/bootstrap-select.min.js"></script>
|
||||
<link rel="stylesheet" href="style/vendor/bootstrap/css/bootstrap-select.min.css">
|
||||
<script src="style/vendor/bootstrap/js/bootstrap-toggle.min.js"></script>
|
||||
<link rel="stylesheet" href="style/vendor/bootstrap/css/bootstrap-toggle.min.css">
|
||||
<script src="scripts/vendor/moment.min.js"></script>
|
||||
<?php } ?>
|
||||
|
||||
<script src="scripts/vendor/jquery.dataTables.min.js"></script>
|
||||
<script src="scripts/vendor/dataTables.bootstrap.min.js"></script>
|
||||
<script src="scripts/vendor/Chart.bundle.min.js"></script>
|
||||
</head>
|
||||
<body class="skin-blue sidebar-mini <?php if($boxedlayout){ ?>layout-boxed<?php } ?>">
|
||||
<noscript>
|
||||
<!-- JS Warning -->
|
||||
<div>
|
||||
<link rel="stylesheet" type="text/css" href="style/vendor/js-warn.css">
|
||||
<input type="checkbox" id="js-hide" />
|
||||
<div class="js-warn" id="js-warn-exit"><h1>Javascript Is Disabled</h1><p>Javascript seems to be disabled. This will break some site features.</p>
|
||||
<p>To enable Javascript click <a href="http://www.enable-javascript.com/" target="_blank">here</a></p><label for="js-hide">Close</label></div>
|
||||
<input type="checkbox" id="js-hide">
|
||||
<div class="js-warn" id="js-warn-exit"><h1>JavaScript Is Disabled</h1><p>JavaScript is required for the site to function.</p>
|
||||
<p>To learn how to enable JavaScript click <a href="https://www.enable-javascript.com/" rel="noopener" target="_blank">here</a></p><label for="js-hide">Close</label>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /JS Warning -->
|
||||
</noscript>
|
||||
<?php
|
||||
if($auth) {
|
||||
echo "<div id='token' hidden>$token</div>";
|
||||
echo "<div id=\"token\" hidden>$token</div>";
|
||||
}
|
||||
?>
|
||||
<script src="scripts/pi-hole/js/header.js"></script>
|
||||
|
||||
<script src="scripts/vendor/jquery.min.js"></script>
|
||||
<script src="scripts/vendor/jquery-ui.min.js"></script>
|
||||
<script src="style/vendor/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script src="scripts/vendor/app.min.js"></script>
|
||||
|
||||
<script src="scripts/vendor/jquery.dataTables.min.js"></script>
|
||||
<script src="scripts/vendor/dataTables.bootstrap.min.js"></script>
|
||||
<script src="scripts/vendor/Chart.bundle.min.js"></script>
|
||||
|
||||
<!-- Send token to JS -->
|
||||
<div id="token" hidden><?php if($auth) echo $token; ?></div>
|
||||
@@ -245,30 +257,35 @@ if($auth) {
|
||||
<div class="wrapper">
|
||||
<header class="main-header">
|
||||
<!-- Logo -->
|
||||
<a href="http://pi-hole.net" class="logo" target="_blank">
|
||||
<a href="index.php" class="logo">
|
||||
<!-- mini logo for sidebar mini 50x50 pixels -->
|
||||
<span class="logo-mini">P<b>h</b></span>
|
||||
<!-- logo for regular state and mobile devices -->
|
||||
<span class="logo-lg">Pi-<b>hole</b></span>
|
||||
</a>
|
||||
<!-- Header Navbar: style can be found in header.less -->
|
||||
<nav class="navbar navbar-static-top" role="navigation">
|
||||
<nav class="navbar navbar-static-top">
|
||||
<!-- Sidebar toggle button-->
|
||||
<a href="#" class="sidebar-toggle" data-toggle="offcanvas" role="button">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
</a>
|
||||
<div class="navbar-custom-menu">
|
||||
<ul class="nav navbar-nav">
|
||||
<li><a style="pointer-events:none;"><samp><?php echo gethostname(); ?></samp></a></li>
|
||||
<li>
|
||||
<a style="pointer-events:none;">
|
||||
<span class="hidden-xs hidden-sm">hostname:</span>
|
||||
<code><?php echo gethostname(); ?></code>
|
||||
</a>
|
||||
</li>
|
||||
<li class="dropdown user user-menu">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="true">
|
||||
<img src="img/logo.svg" class="user-image" style="border-radius: initial" sizes="160x160" alt="Pi-hole logo" />
|
||||
<img src="img/logo.svg" class="user-image" style="border-radius: 0" alt="Pi-hole logo" width="25" height="25">
|
||||
<span class="hidden-xs">Pi-hole</span>
|
||||
</a>
|
||||
<ul class="dropdown-menu" style="right:0">
|
||||
<!-- User image -->
|
||||
<li class="user-header">
|
||||
<img src="img/logo.svg" sizes="160x160" alt="User Image" style="border-color:transparent" />
|
||||
<img src="img/logo.svg" alt="User Image" style="border-color:transparent" width="90" height="90">
|
||||
<p>
|
||||
Open Source Ad Blocker
|
||||
<small>Designed For Raspberry Pi</small>
|
||||
@@ -277,13 +294,13 @@ if($auth) {
|
||||
<!-- Menu Body -->
|
||||
<li class="user-body">
|
||||
<div class="col-xs-4 text-center">
|
||||
<a class="btn-link" href="https://github.com/pi-hole" target="_blank">GitHub</a>
|
||||
<a class="btn-link" href="https://github.com/pi-hole" rel="noopener" target="_blank">GitHub</a>
|
||||
</div>
|
||||
<div class="col-xs-4 text-center">
|
||||
<a class="btn-link" href="https://pi-hole.net" target="_blank">Website</a>
|
||||
<a class="btn-link" href="https://pi-hole.net/" rel="noopener" target="_blank">Website</a>
|
||||
</div>
|
||||
<div class="col-xs-4 text-center">
|
||||
<a class="btn-link" href="https://github.com/pi-hole/pi-hole/releases" target="_blank">Updates</a>
|
||||
<a class="btn-link" href="https://github.com/pi-hole/pi-hole/releases" rel="noopener" target="_blank">Updates</a>
|
||||
</div>
|
||||
<div class="col-xs-12 text-center" id="sessiontimer">
|
||||
<b>Session is valid for <span id="sessiontimercounter"><?php if($auth && strlen($pwhash) > 0){echo $maxlifetime;}else{echo "0";} ?></span></b>
|
||||
@@ -297,19 +314,19 @@ if($auth) {
|
||||
<b>Pi-hole Version </b> <?php
|
||||
echo $core_current;
|
||||
if(isset($core_commit)) { echo "<br>(".$core_branch.", ".$core_commit.")"; }
|
||||
if($core_update){ ?> <a class="alert-link lookatme btn-link" href="https://github.com/pi-hole/pi-hole/releases" target="_blank" style="background:none">(Update available!)</a><?php } ?><br>
|
||||
if($core_update){ ?> <a class="alert-link lookatme btn-link" href="https://github.com/pi-hole/pi-hole/releases" rel="noopener" target="_blank" style="background:none">(Update available!)</a><?php } ?><br>
|
||||
<b>Web Interface Version </b><?php
|
||||
echo $web_current;
|
||||
if(isset($web_commit)) { echo "<br>(".$web_branch.", ".$web_commit.")"; }
|
||||
if($web_update){ ?> <a class="alert-link lookatme btn-link" href="https://github.com/pi-hole/AdminLTE/releases" target="_blank" style="background:none">(Update available!)</a><?php } ?><br>
|
||||
if($web_update){ ?> <a class="alert-link lookatme btn-link" href="https://github.com/pi-hole/AdminLTE/releases" rel="noopener" target="_blank" style="background:none">(Update available!)</a><?php } ?><br>
|
||||
<b>FTL Version </b> <?php
|
||||
echo $FTL_current;
|
||||
if($FTL_update){ ?> <a class="alert-link lookatme btn-link" href="https://github.com/pi-hole/FTL/releases" target="_blank" style="background:none">(Update available!)</a><?php } ?><br><br>
|
||||
if($FTL_update){ ?> <a class="alert-link lookatme btn-link" href="https://github.com/pi-hole/FTL/releases" rel="noopener" target="_blank" style="background:none">(Update available!)</a><?php } ?><br><br>
|
||||
</div>
|
||||
*/ ?>
|
||||
<!-- PayPal -->
|
||||
<div class="text-center">
|
||||
<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3J2L3Z4DHW9UY" target="_blank" style="background:none">
|
||||
<a href="https://pi-hole.net/donate/" rel="noopener" target="_blank" style="background:none">
|
||||
<img src="img/donate.gif" alt="Donate">
|
||||
</a>
|
||||
</div>
|
||||
@@ -327,33 +344,33 @@ if($auth) {
|
||||
<!-- Sidebar user panel -->
|
||||
<div class="user-panel">
|
||||
<div class="pull-left image">
|
||||
<img src="img/logo.svg" class="img-responsive" alt="Pi-hole logo" style="display: table; table-layout: fixed; height: 67px;" />
|
||||
<img src="img/logo.svg" class="img-responsive" alt="Pi-hole logo" style="display: table; table-layout: fixed; height: 67px;">
|
||||
</div>
|
||||
<div class="pull-left info">
|
||||
<p>Status</p>
|
||||
<?php
|
||||
$pistatus = exec('sudo pihole status web');
|
||||
if ($pistatus == "1") {
|
||||
echo '<a id="status"><i class="fa fa-circle" style="color:#7FFF00"></i> Active</a>';
|
||||
echo '<a id="status"><i class="fa fa-circle text-green-light"></i> Active</a>';
|
||||
} elseif ($pistatus == "0") {
|
||||
echo '<a id="status"><i class="fa fa-circle" style="color:#FF0000"></i> Offline</a>';
|
||||
echo '<a id="status"><i class="fa fa-circle text-red"></i> Offline</a>';
|
||||
} elseif ($pistatus == "-1") {
|
||||
echo '<a id="status"><i class="fa fa-circle" style="color:#FF0000"></i> DNS service not running</a>';
|
||||
echo '<a id="status"><i class="fa fa-circle text-red"></i> DNS service not running</a>';
|
||||
} else {
|
||||
echo '<a id="status"><i class="fa fa-circle" style="color:#ff9900"></i> Unknown</a>';
|
||||
echo '<a id="status"><i class="fa fa-circle text-orange"></i> Unknown</a>';
|
||||
}
|
||||
|
||||
// CPU Temp
|
||||
if($FTL)
|
||||
{
|
||||
if ($celsius >= -273.15) {
|
||||
echo "<a id=\"temperature\"><i class=\"fa fa-fire\" style=\"color:";
|
||||
echo "<a id=\"temperature\"><i class=\"fa fa-fire ";
|
||||
if ($celsius > $temperaturelimit) {
|
||||
echo "#FF0000";
|
||||
echo "text-red";
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "#3366FF";
|
||||
echo "text-vivid-blue";
|
||||
}
|
||||
echo "\"></i> Temp: ";
|
||||
if($temperatureunit === "F")
|
||||
@@ -373,30 +390,30 @@ if($auth) {
|
||||
}
|
||||
else
|
||||
{
|
||||
echo '<a id=\"temperature\"><i class="fa fa-circle" style="color:#FF0000"></i> FTL offline</a>';
|
||||
echo '<a id=\"temperature\"><i class="fa fa-circle text-red"></i> FTL offline</a>';
|
||||
}
|
||||
?>
|
||||
<br/>
|
||||
<?php
|
||||
echo "<a title=\"Detected $nproc cores\"><i class=\"fa fa-circle\" style=\"color:";
|
||||
echo "<a title=\"Detected $nproc cores\"><i class=\"fa fa-circle ";
|
||||
if ($loaddata[0] > $nproc) {
|
||||
echo "#FF0000";
|
||||
echo "text-red";
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "#7FFF00";
|
||||
echo "text-green-light";
|
||||
}
|
||||
echo "\"></i> Load: " . $loaddata[0] . " " . $loaddata[1] . " ". $loaddata[2] . "</a>";
|
||||
?>
|
||||
<br/>
|
||||
<?php
|
||||
echo "<a><i class=\"fa fa-circle\" style=\"color:";
|
||||
echo "<a><i class=\"fa fa-circle ";
|
||||
if ($memory_usage > 0.75 || $memory_usage < 0.0) {
|
||||
echo "#FF0000";
|
||||
echo "text-red";
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "#7FFF00";
|
||||
echo "text-green-light";
|
||||
}
|
||||
if($memory_usage > 0.0)
|
||||
{
|
||||
@@ -411,14 +428,13 @@ if($auth) {
|
||||
</div>
|
||||
<!-- sidebar menu: : style can be found in sidebar.less -->
|
||||
<?php
|
||||
$scriptname = basename($_SERVER['SCRIPT_FILENAME']);
|
||||
if($scriptname === "list.php")
|
||||
if($scriptname === "groups-domains.php" && isset($_GET['type']))
|
||||
{
|
||||
if($_GET["l"] === "white")
|
||||
if($_GET["type"] === "white")
|
||||
{
|
||||
$scriptname = "whitelist";
|
||||
}
|
||||
elseif($_GET["l"] === "black")
|
||||
elseif($_GET["type"] === "black")
|
||||
{
|
||||
$scriptname = "blacklist";
|
||||
}
|
||||
@@ -470,18 +486,48 @@ if($auth) {
|
||||
</li>
|
||||
<!-- Whitelist -->
|
||||
<li<?php if($scriptname === "whitelist"){ ?> class="active"<?php } ?>>
|
||||
<a href="list.php?l=white">
|
||||
<a href="groups-domains.php?type=white">
|
||||
<i class="fa fa-check-circle "></i> <span>Whitelist</span>
|
||||
</a>
|
||||
</li>
|
||||
<!-- Blacklist -->
|
||||
<li<?php if($scriptname === "blacklist"){ ?> class="active"<?php } ?>>
|
||||
<a href="list.php?l=black">
|
||||
<a href="groups-domains.php?type=black">
|
||||
<i class="fa fa-ban"></i> <span>Blacklist</span>
|
||||
</a>
|
||||
</li>
|
||||
<!-- Group Management -->
|
||||
<li class="treeview <?php if(in_array($scriptname, array("groups.php", "groups-clients.php", "groups-domains.php", "groups-adlists.php"))){ ?>active<?php } ?>">
|
||||
<a href="#">
|
||||
<span class="pull-right-container">
|
||||
<i class="fa fa-angle-down pull-right" style="padding-right: 5px;"></i>
|
||||
</span>
|
||||
<i class="fa fa-users-cog"></i> <span>Group Management</span>
|
||||
</a>
|
||||
<ul class="treeview-menu">
|
||||
<li<?php if($scriptname === "groups.php"){ ?> class="active"<?php } ?>>
|
||||
<a href="groups.php">
|
||||
<i class="fa fa-user-friends"></i> <span>Groups</span>
|
||||
</a>
|
||||
</li>
|
||||
<li<?php if($scriptname === "groups-clients.php"){ ?> class="active"<?php } ?>>
|
||||
<a href="groups-clients.php">
|
||||
<i class="fa fa-laptop"></i> <span>Clients</span>
|
||||
</a>
|
||||
</li>
|
||||
<li<?php if($scriptname === "groups-domains.php"){ ?> class="active"<?php } ?>>
|
||||
<a href="groups-domains.php">
|
||||
<i class="fa fa-list"></i> <span>Domains</span>
|
||||
</a>
|
||||
</li>
|
||||
<li<?php if($scriptname === "groups-adlists.php"){ ?> class="active"<?php } ?>>
|
||||
<a href="groups-adlists.php">
|
||||
<i class="fa fa-shield-alt"></i> <span>Adlists</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<!-- Toggle -->
|
||||
|
||||
<li id="pihole-disable" class="treeview"<?php if ($pistatus == "0") { ?> hidden="true"<?php } ?>>
|
||||
<a href="#">
|
||||
<span class="pull-right-container">
|
||||
@@ -580,6 +626,12 @@ if($auth) {
|
||||
<i class="fa fa-cogs"></i> <span>Settings</span>
|
||||
</a>
|
||||
</li>
|
||||
<!-- Local DNS Records -->
|
||||
<li<?php if($scriptname === "dns_records.php"){ ?> class="active"<?php } ?>>
|
||||
<a href="dns_records.php">
|
||||
<i class="fa fa-address-book"></i> <span>Local DNS Records</span>
|
||||
</a>
|
||||
</li>
|
||||
<!-- Logout -->
|
||||
<?php
|
||||
// Show Logout button if $auth is set and authorization is required
|
||||
@@ -603,7 +655,7 @@ if($auth) {
|
||||
<?php } ?>
|
||||
<!-- Donate -->
|
||||
<li>
|
||||
<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3J2L3Z4DHW9UY" target="_blank">
|
||||
<a href="https://pi-hole.net/donate/" rel="noopener" target="_blank">
|
||||
<i class="fa-paypal-icon fab fa-paypal"></i> <span>Donate</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@@ -9,11 +9,14 @@
|
||||
<div class="mainbox col-md-6 col-md-offset-3 col-sm-8 col-sm-offset-2" style="float:none">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<div style="text-align: center;"><img src="img/logo.svg" width="<?php if ($boxedlayout) { ?>50%<?php } else { ?>30%<?php } ?>"></div><br>
|
||||
<div class="text-center">
|
||||
<img src="img/logo.svg" alt="" style="width: <?php if ($boxedlayout) { ?>50%<?php } else { ?>30%<?php } ?>;">
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<div class="panel-title text-center"><span class="logo-lg" style="font-size: 25px;">Pi-<b>hole</b></span></div>
|
||||
<div class="panel-title text-center"><span class="logo-lg" style="font-size: 25px;">Pi-<b>hole</b></span></div>
|
||||
<p class="login-box-msg">Sign in to start your session</p>
|
||||
<div id="cookieInfo" class="panel-title text-center" style="color:#F00; font-size: 150%" hidden>Verify that cookies are allowed for <samp><?php echo $_SERVER['HTTP_HOST']; ?></samp></div>
|
||||
<div id="cookieInfo" class="panel-title text-center text-red" style="font-size: 150%" hidden>Verify that cookies are allowed for <code><?php echo $_SERVER['HTTP_HOST']; ?></code></div>
|
||||
<?php if ($wrongpassword) { ?>
|
||||
<div class="form-group has-error login-box-msg">
|
||||
<label class="control-label"><i class="fa fa-times-circle"></i> Wrong password!</label>
|
||||
@@ -28,17 +31,17 @@
|
||||
<span class="fa fa-key form-control-feedback"></span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-8">
|
||||
<div class="col-xs-8 hidden-xs hidden-sm">
|
||||
<ul>
|
||||
<li><samp>Return</samp> → Log in and go to requested page (<?php echo $scriptname; ?>)</li>
|
||||
<li><samp>Ctrl+Return</samp> → Log in and go to Settings page</li>
|
||||
<li><kbd>Return</kbd> → Log in and go to requested page (<?php echo $scriptname; ?>)</li>
|
||||
<li><kbd>Ctrl</kbd>+<kbd>Return</kbd> → Log in and go to Settings page</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<div class="form-group">
|
||||
<div class="col-xs-12 col-md-4">
|
||||
<div class="form-group pull-left">
|
||||
<div class="checkbox pull-right"><label><input type="checkbox" id="logincookie" name="persistentlogin">Remember me for 7 days</label></div>
|
||||
</div>
|
||||
<button type="submit" href="#" class="btn btn-primary pull-right"><i class="glyphicon glyphicon-log-in"></i> Log in</button>
|
||||
<button type="submit" class="btn btn-primary pull-right"><i class="glyphicon glyphicon-log-in"></i> Log in</button>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
|
||||
if(basename($_SERVER['SCRIPT_FILENAME']) !== "settings.php")
|
||||
if(!in_array(basename($_SERVER['SCRIPT_FILENAME']), ["settings.php", "teleporter.php"], true))
|
||||
{
|
||||
die("Direct access to this script is forbidden!");
|
||||
}
|
||||
@@ -35,7 +35,7 @@ function istrue(&$argument) {
|
||||
// Credit: http://stackoverflow.com/a/4694816/2087442
|
||||
function validDomain($domain_name)
|
||||
{
|
||||
$validChars = preg_match("/^([_a-z\d](-*[_a-z\d])*)(\.([_a-z\d](-*[a-z\d])*))*(\.([a-z\d])*)*$/i", $domain_name);
|
||||
$validChars = preg_match("/^([_a-z\d](-*[_a-z\d])*)(\.([_a-z\d](-*[a-z\d])*))*(\.([_a-z\d])*)*$/i", $domain_name);
|
||||
$lengthCheck = preg_match("/^.{1,253}$/", $domain_name);
|
||||
$labelLengthCheck = preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name);
|
||||
return ( $validChars && $lengthCheck && $labelLengthCheck ); //length of each label
|
||||
@@ -44,7 +44,7 @@ function validDomain($domain_name)
|
||||
function validDomainWildcard($domain_name)
|
||||
{
|
||||
// There has to be either no or at most one "*" at the beginning of a line
|
||||
$validChars = preg_match("/^((\*.)?[_a-z\d](-*[_a-z\d])*)(\.([_a-z\d](-*[a-z\d])*))*(\.([a-z\d])*)*$/i", $domain_name);
|
||||
$validChars = preg_match("/^((\*.)?[_a-z\d](-*[_a-z\d])*)(\.([_a-z\d](-*[a-z\d])*))*(\.([_a-z\d])*)*$/i", $domain_name);
|
||||
$lengthCheck = preg_match("/^.{1,253}$/", $domain_name);
|
||||
$labelLengthCheck = preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name);
|
||||
return ( $validChars && $lengthCheck && $labelLengthCheck ); //length of each label
|
||||
@@ -75,20 +75,14 @@ function validEmail($email)
|
||||
}
|
||||
|
||||
$dhcp_static_leases = array();
|
||||
function readStaticLeasesFile()
|
||||
function readStaticLeasesFile($origin_file="/etc/dnsmasq.d/04-pihole-static-dhcp.conf")
|
||||
{
|
||||
global $dhcp_static_leases;
|
||||
$dhcp_static_leases = array();
|
||||
try
|
||||
{
|
||||
$dhcpstatic = @fopen('/etc/dnsmasq.d/04-pihole-static-dhcp.conf', 'r');
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
echo "Warning: Failed to read /etc/dnsmasq.d/04-pihole-static-dhcp.conf, this is not an error";
|
||||
if(!file_exists($origin_file) || !is_readable($origin_file))
|
||||
return false;
|
||||
}
|
||||
|
||||
$dhcpstatic = @fopen($origin_file, 'r');
|
||||
if(!is_resource($dhcpstatic))
|
||||
return false;
|
||||
|
||||
@@ -154,16 +148,16 @@ function readDNSserversList()
|
||||
$line = explode(';', $line);
|
||||
$name = $line[0];
|
||||
$values = [];
|
||||
if (!empty($line[1])) {
|
||||
if (!empty($line[1]) && validIP($line[1])) {
|
||||
$values["v4_1"] = $line[1];
|
||||
}
|
||||
if (!empty($line[2])) {
|
||||
if (!empty($line[2]) && validIP($line[2])) {
|
||||
$values["v4_2"] = $line[2];
|
||||
}
|
||||
if (!empty($line[3])) {
|
||||
if (!empty($line[3]) && validIP($line[3])) {
|
||||
$values["v6_1"] = $line[3];
|
||||
}
|
||||
if (!empty($line[4])) {
|
||||
if (!empty($line[4]) && validIP($line[4])) {
|
||||
$values["v6_2"] = $line[4];
|
||||
}
|
||||
$list[$name] = $values;
|
||||
@@ -173,43 +167,66 @@ function readDNSserversList()
|
||||
return $list;
|
||||
}
|
||||
|
||||
$adlist = [];
|
||||
function readAdlists()
|
||||
{
|
||||
// Reset list
|
||||
$list = [];
|
||||
$handle = @fopen("/etc/pihole/adlists.list", "r");
|
||||
if ($handle)
|
||||
{
|
||||
while (($line = fgets($handle)) !== false)
|
||||
require_once("database.php");
|
||||
|
||||
function addStaticDHCPLease($mac, $ip, $hostname) {
|
||||
global $error, $success, $dhcp_static_leases;
|
||||
|
||||
try {
|
||||
if(!validMAC($mac))
|
||||
{
|
||||
if(strlen($line) < 3)
|
||||
throw new Exception("MAC address (".htmlspecialchars($mac).") is invalid!<br>", 0);
|
||||
}
|
||||
$mac = strtoupper($mac);
|
||||
|
||||
if(!validIP($ip) && strlen($ip) > 0)
|
||||
{
|
||||
throw new Exception("IP address (".htmlspecialchars($ip).") is invalid!<br>", 1);
|
||||
}
|
||||
|
||||
if(!validDomain($hostname) && strlen($hostname) > 0)
|
||||
{
|
||||
throw new Exception("Host name (".htmlspecialchars($hostname).") is invalid!<br>", 2);
|
||||
}
|
||||
|
||||
if(strlen($hostname) == 0 && strlen($ip) == 0)
|
||||
{
|
||||
throw new Exception("You can not omit both the IP address and the host name!<br>", 3);
|
||||
}
|
||||
|
||||
if(strlen($hostname) == 0)
|
||||
$hostname = "nohost";
|
||||
|
||||
if(strlen($ip) == 0)
|
||||
$ip = "noip";
|
||||
|
||||
// Test if this lease is already included
|
||||
readStaticLeasesFile();
|
||||
|
||||
foreach($dhcp_static_leases as $lease) {
|
||||
if($lease["hwaddr"] === $mac)
|
||||
{
|
||||
continue;
|
||||
throw new Exception("Static release for MAC address (".htmlspecialchars($mac).") already defined!<br>", 4);
|
||||
}
|
||||
elseif($line[0] === "#")
|
||||
if($ip !== "noip" && $lease["IP"] === $ip)
|
||||
{
|
||||
// Comments start either with "##" or "# "
|
||||
if($line[1] !== "#" &&
|
||||
$line[1] !== " ")
|
||||
{
|
||||
// Commented list
|
||||
array_push($list, [false,rtrim(substr($line, 1))]);
|
||||
}
|
||||
throw new Exception("Static lease for IP address (".htmlspecialchars($ip).") already defined!<br>", 5);
|
||||
}
|
||||
else
|
||||
if($lease["host"] === $hostname)
|
||||
{
|
||||
// Active list
|
||||
array_push($list, [true,rtrim($line)]);
|
||||
throw new Exception("Static lease for hostname (".htmlspecialchars($hostname).") already defined!<br>", 6);
|
||||
}
|
||||
}
|
||||
fclose($handle);
|
||||
|
||||
exec("sudo pihole -a addstaticdhcp ".$mac." ".$ip." ".$hostname);
|
||||
$success .= "A new static address has been added";
|
||||
return true;
|
||||
} catch(Exception $exception) {
|
||||
$error .= $exception->getMessage();
|
||||
return false;
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
// Read available adlists
|
||||
$adlist = readAdlists();
|
||||
// Read available DNS server list
|
||||
$DNSserverslist = readDNSserversList();
|
||||
|
||||
@@ -512,9 +529,9 @@ function readAdlists()
|
||||
$adminemail = trim($_POST["adminemail"]);
|
||||
if(strlen($adminemail) == 0 || !isset($adminemail))
|
||||
{
|
||||
$adminemail = 'noadminemail';
|
||||
$adminemail = '';
|
||||
}
|
||||
elseif(!validEmail($adminemail))
|
||||
if(strlen($adminemail) > 0 && !validEmail($adminemail))
|
||||
{
|
||||
$error .= "Administrator email address (".htmlspecialchars($adminemail).") is invalid!<br>";
|
||||
}
|
||||
@@ -561,58 +578,7 @@ function readAdlists()
|
||||
$ip = $_POST["AddIP"];
|
||||
$hostname = $_POST["AddHostname"];
|
||||
|
||||
if(!validMAC($mac))
|
||||
{
|
||||
$error .= "MAC address (".htmlspecialchars($mac).") is invalid!<br>";
|
||||
}
|
||||
$mac = strtoupper($mac);
|
||||
|
||||
if(!validIP($ip) && strlen($ip) > 0)
|
||||
{
|
||||
$error .= "IP address (".htmlspecialchars($ip).") is invalid!<br>";
|
||||
}
|
||||
|
||||
if(!validDomain($hostname) && strlen($hostname) > 0)
|
||||
{
|
||||
$error .= "Host name (".htmlspecialchars($hostname).") is invalid!<br>";
|
||||
}
|
||||
|
||||
if(strlen($hostname) == 0 && strlen($ip) == 0)
|
||||
{
|
||||
$error .= "You can not omit both the IP address and the host name!<br>";
|
||||
}
|
||||
|
||||
if(strlen($hostname) == 0)
|
||||
$hostname = "nohost";
|
||||
|
||||
if(strlen($ip) == 0)
|
||||
$ip = "noip";
|
||||
|
||||
// Test if this lease is already included
|
||||
readStaticLeasesFile();
|
||||
foreach($dhcp_static_leases as $lease) {
|
||||
if($lease["hwaddr"] === $mac)
|
||||
{
|
||||
$error .= "Static release for MAC address (".htmlspecialchars($mac).") already defined!<br>";
|
||||
break;
|
||||
}
|
||||
if($ip !== "noip" && $lease["IP"] === $ip)
|
||||
{
|
||||
$error .= "Static lease for IP address (".htmlspecialchars($ip).") already defined!<br>";
|
||||
break;
|
||||
}
|
||||
if($lease["host"] === $hostname)
|
||||
{
|
||||
$error .= "Static lease for hostname (".htmlspecialchars($hostname).") already defined!<br>";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!strlen($error))
|
||||
{
|
||||
exec("sudo pihole -a addstaticdhcp ".$mac." ".$ip." ".$hostname);
|
||||
$success .= "A new static address has been added";
|
||||
}
|
||||
addStaticDHCPLease($mac, $ip, $hostname);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -706,40 +672,6 @@ function readAdlists()
|
||||
|
||||
break;
|
||||
|
||||
case "adlists":
|
||||
foreach ($adlist as $key => $value)
|
||||
{
|
||||
if(isset($_POST["adlist-del-".$key]))
|
||||
{
|
||||
// Delete list
|
||||
exec("sudo pihole -a adlist del ".escapeshellcmd($value[1]));
|
||||
}
|
||||
elseif(isset($_POST["adlist-enable-".$key]) && !$value[0])
|
||||
{
|
||||
// Is not enabled, but should be
|
||||
exec("sudo pihole -a adlist enable ".escapeshellcmd($value[1]));
|
||||
|
||||
}
|
||||
elseif(!isset($_POST["adlist-enable-".$key]) && $value[0])
|
||||
{
|
||||
// Is enabled, but shouldn't be
|
||||
exec("sudo pihole -a adlist disable ".escapeshellcmd($value[1]));
|
||||
}
|
||||
}
|
||||
|
||||
if(strlen($_POST["newuserlists"]) > 1)
|
||||
{
|
||||
$domains = array_filter(preg_split('/\r\n|[\r\n]/', $_POST["newuserlists"]));
|
||||
foreach($domains as $domain)
|
||||
{
|
||||
exec("sudo pihole -a adlist add ".escapeshellcmd($domain));
|
||||
}
|
||||
}
|
||||
|
||||
// Reread available adlists
|
||||
$adlist = readAdlists();
|
||||
break;
|
||||
|
||||
case "privacyLevel":
|
||||
$level = intval($_POST["privacylevel"]);
|
||||
if($level >= 0 && $level <= 4)
|
||||
@@ -773,6 +705,15 @@ function readAdlists()
|
||||
$error .= "Invalid privacy level (".$level.")!";
|
||||
}
|
||||
break;
|
||||
// Flush network table
|
||||
case "flusharp":
|
||||
exec("sudo pihole arpflush quiet", $output);
|
||||
$error = implode("<br>", $output);
|
||||
if(strlen($error) == 0)
|
||||
{
|
||||
$success .= "The network table has been flushed";
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// Option not found
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
<?php
|
||||
/* 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. */
|
||||
|
||||
require_once('auth.php');
|
||||
|
||||
$type = $_POST['list'];
|
||||
|
||||
// Perform all of the authentication for list editing
|
||||
// when NOT invoked and authenticated from API
|
||||
if (empty($api)) {
|
||||
list_verify($type);
|
||||
}
|
||||
|
||||
// Don't check if the added item is a valid domain for regex expressions. Regex
|
||||
// filters are validated by FTL on import and skipped if invalid
|
||||
if($type !== "regex") {
|
||||
check_domain();
|
||||
}
|
||||
|
||||
switch($type) {
|
||||
case "white":
|
||||
exec("sudo pihole -w -q -d ${_POST['domain']}");
|
||||
break;
|
||||
case "black":
|
||||
exec("sudo pihole -b -q -d ${_POST['domain']}");
|
||||
break;
|
||||
case "regex":
|
||||
if(($list = file_get_contents($regexfile)) === FALSE)
|
||||
{
|
||||
$err = error_get_last()["message"];
|
||||
echo "Unable to read ${regexfile}<br>Error message: $err";
|
||||
}
|
||||
|
||||
// Remove the regex and any empty lines from the list
|
||||
$list = explode("\n", $list);
|
||||
$list = array_diff($list, array($_POST['domain'], ""));
|
||||
$list = implode("\n", $list);
|
||||
|
||||
if(file_put_contents($regexfile, $list."\n") === FALSE)
|
||||
{
|
||||
$err = error_get_last()["message"];
|
||||
echo "Unable to remove regex \"".htmlspecialchars($_POST['domain'])."\" from ${regexfile}<br>Error message: $err";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Send SIGHUP to pihole-FTL using a frontend command
|
||||
// to force reloading of the regex domains
|
||||
// This will also wipe the resolver's cache
|
||||
echo exec("sudo pihole restartdns reload");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -8,12 +8,18 @@
|
||||
|
||||
require "password.php";
|
||||
require "auth.php"; // Also imports func.php
|
||||
require "database.php";
|
||||
require "savesettings.php";
|
||||
|
||||
if (php_sapi_name() !== "cli") {
|
||||
if(!$auth) die("Not authorized");
|
||||
check_csrf(isset($_POST["token"]) ? $_POST["token"] : "");
|
||||
}
|
||||
|
||||
$db = SQLite3_connect(getGravityDBFilename(), SQLITE3_OPEN_READWRITE);
|
||||
|
||||
$flushed_tables = array();
|
||||
|
||||
function archive_add_file($path,$name,$subdir="")
|
||||
{
|
||||
global $archive;
|
||||
@@ -21,6 +27,237 @@ function archive_add_file($path,$name,$subdir="")
|
||||
$archive[$subdir.$name] = file_get_contents($path.$name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the contents of a table to the archive
|
||||
*
|
||||
* @param $name string The name of the file in the archive to save the table to
|
||||
* @param $table string The table to export
|
||||
* @param $type integer Type of domains to store
|
||||
*/
|
||||
function archive_add_table($name, $table, $type=-1)
|
||||
{
|
||||
global $archive, $db;
|
||||
|
||||
if($type > -1)
|
||||
{
|
||||
$querystr = "SELECT * FROM $table WHERE type = $type;";
|
||||
}
|
||||
else
|
||||
{
|
||||
$querystr = "SELECT * FROM $table;";
|
||||
}
|
||||
$results = $db->query($querystr);
|
||||
|
||||
// Return early without creating a file if the
|
||||
// requested table cannot be accessed
|
||||
if(is_null($results))
|
||||
return;
|
||||
|
||||
$content = array();
|
||||
while ($row = $results->fetchArray(SQLITE3_ASSOC))
|
||||
{
|
||||
array_push($content, $row);
|
||||
}
|
||||
|
||||
$archive[$name] = json_encode($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the contents of a table from an uploaded archive
|
||||
*
|
||||
* @param $file object The file in the archive to restore the table from
|
||||
* @param $table string The table to import
|
||||
* @param $flush boolean Whether to flush the table before importing the archived data
|
||||
* @return integer Number of restored rows
|
||||
*/
|
||||
function archive_restore_table($file, $table, $flush=false)
|
||||
{
|
||||
global $db, $flushed_tables;
|
||||
|
||||
$json_string = file_get_contents($file);
|
||||
// Return early if we cannot extract the JSON string
|
||||
if(is_null($json_string))
|
||||
return 0;
|
||||
|
||||
$contents = json_decode($json_string, true);
|
||||
// Return early if we cannot decode the JSON string
|
||||
if(is_null($contents))
|
||||
return 0;
|
||||
|
||||
// Flush table if requested, only flush each table once
|
||||
if($flush && !in_array($table, $flushed_tables))
|
||||
{
|
||||
$db->exec("DELETE FROM ".$table);
|
||||
array_push($flushed_tables, $table);
|
||||
}
|
||||
|
||||
// Prepare field name for domain/address depending on the table we restore to
|
||||
if($table === "adlist")
|
||||
{
|
||||
$sql = "INSERT OR IGNORE INTO adlist";
|
||||
$sql .= " (id,address,enabled,date_added,comment)";
|
||||
$sql .= " VALUES (:id,:address,:enabled,:date_added,:comment);";
|
||||
$field = "address";
|
||||
}
|
||||
elseif($table === "domain_audit")
|
||||
{
|
||||
$sql = "INSERT OR IGNORE INTO domain_audit";
|
||||
$sql .= " (id,domain,date_added)";
|
||||
$sql .= " VALUES (:id,:domain,:date_added);";
|
||||
$field = "domain";
|
||||
}
|
||||
elseif($table === "domainlist")
|
||||
{
|
||||
$sql = "INSERT OR IGNORE INTO domainlist";
|
||||
$sql .= " (id,domain,enabled,date_added,comment,type)";
|
||||
$sql .= " VALUES (:id,:domain,:enabled,:date_added,:comment,:type);";
|
||||
$field = "domain";
|
||||
}
|
||||
else
|
||||
{
|
||||
if($table === "whitelist")
|
||||
$type = 0;
|
||||
elseif($table === "blacklist")
|
||||
$type = 1;
|
||||
elseif($table === "regex_whitelist")
|
||||
$type = 2;
|
||||
elseif($table === "regex_blacklist")
|
||||
$type = 3;
|
||||
|
||||
$sql = "INSERT OR IGNORE INTO domainlist";
|
||||
$sql .= " (id,domain,enabled,date_added,comment,type)";
|
||||
$sql .= " VALUES (:id,:domain,:enabled,:date_added,:comment,$type);";
|
||||
$field = "domain";
|
||||
}
|
||||
|
||||
// Prepare SQLite statememt
|
||||
$stmt = $db->prepare($sql);
|
||||
|
||||
// Return early if we fail to prepare the SQLite statement
|
||||
if(!$stmt)
|
||||
{
|
||||
echo "Failed to prepare statement for ".$table." table.";
|
||||
echo $sql;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Loop over rows and inject the entries into the database
|
||||
$num = 0;
|
||||
foreach($contents as $row)
|
||||
{
|
||||
// Limit max length for a domain entry to 253 chars
|
||||
if(strlen($row[$field]) > 253)
|
||||
continue;
|
||||
|
||||
$stmt->bindValue(":id", $row["id"], SQLITE3_INTEGER);
|
||||
$stmt->bindValue(":date_added", $row["date_added"], SQLITE3_INTEGER);
|
||||
$stmt->bindValue(":".$field, $row[$field], SQLITE3_TEXT);
|
||||
|
||||
if($table !== "domain_audit")
|
||||
{
|
||||
$stmt->bindValue(":enabled", $row["enabled"], SQLITE3_INTEGER);
|
||||
if(is_null($row["comment"]))
|
||||
$type = SQLITE3_NULL;
|
||||
else
|
||||
$type = SQLITE3_TEXT;
|
||||
$stmt->bindValue(":comment", $row["comment"], $type);
|
||||
}
|
||||
|
||||
if($table === "domainlist")
|
||||
{
|
||||
$stmt->bindValue(":type", $row["type"], SQLITE3_INTEGER);
|
||||
}
|
||||
|
||||
if($stmt->execute() && $stmt->reset() && $stmt->clear())
|
||||
$num++;
|
||||
else
|
||||
{
|
||||
$stmt->close();
|
||||
return $num;
|
||||
}
|
||||
}
|
||||
|
||||
// Close database connection and return number or processed rows
|
||||
$stmt->close();
|
||||
return $num;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create table rows from an uploaded archive file
|
||||
*
|
||||
* @param $file object The file in the archive to import
|
||||
* @param $table string The target table
|
||||
* @param $flush boolean Whether to flush the table before importing the archived data
|
||||
* @param $wildcardstyle boolean Whether to format the input domains in legacy wildcard notation
|
||||
* @return integer Number of processed rows from the imported file
|
||||
*/
|
||||
function archive_insert_into_table($file, $table, $flush=false, $wildcardstyle=false)
|
||||
{
|
||||
global $db;
|
||||
|
||||
$domains = array_filter(explode("\n",file_get_contents($file)));
|
||||
// Return early if we cannot extract the lines in the file
|
||||
if(is_null($domains))
|
||||
return 0;
|
||||
|
||||
// Generate comment
|
||||
$prefix = "phar:///tmp/";
|
||||
if (substr($file, 0, strlen($prefix)) == $prefix) {
|
||||
$file = substr($file, strlen($prefix));
|
||||
}
|
||||
$comment = "Imported from ".$file;
|
||||
|
||||
// Determine table and type to import to
|
||||
$type = null;
|
||||
if($table === "whitelist") {
|
||||
$table = "domainlist";
|
||||
$type = ListType::whitelist;
|
||||
} else if($table === "blacklist") {
|
||||
$table = "domainlist";
|
||||
$type = ListType::blacklist;
|
||||
} else if($table === "regex_blacklist") {
|
||||
$table = "domainlist";
|
||||
$type = ListType::regex_blacklist;
|
||||
} else if($table === "domain_audit") {
|
||||
$table = "domain_audit";
|
||||
$type = -1; // -1 -> not used inside add_to_table()
|
||||
} else if($table === "adlist") {
|
||||
$table = "adlist";
|
||||
$type = -1; // -1 -> not used inside add_to_table()
|
||||
}
|
||||
|
||||
// Flush table if requested
|
||||
if($flush) {
|
||||
flush_table($table, $type);
|
||||
}
|
||||
|
||||
// Add domains to requested table
|
||||
return add_to_table($db, $table, $domains, $comment, $wildcardstyle, true, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush table if requested. This subroutine flushes each table only once
|
||||
*
|
||||
* @param $table string The target table
|
||||
* @param $type integer Type of item to flush in table (applies only to domainlist table)
|
||||
*/
|
||||
function flush_table($table, $type=null)
|
||||
{
|
||||
global $db, $flushed_tables;
|
||||
|
||||
if(!in_array($table, $flushed_tables))
|
||||
{
|
||||
if($type !== null) {
|
||||
$sql = "DELETE FROM ".$table." WHERE type = ".$type;
|
||||
array_push($flushed_tables, $table.$type);
|
||||
} else {
|
||||
$sql = "DELETE FROM ".$table;
|
||||
array_push($flushed_tables, $table);
|
||||
}
|
||||
$db->exec($sql);
|
||||
}
|
||||
}
|
||||
|
||||
function archive_add_directory($path,$subdir="")
|
||||
{
|
||||
if($dir = opendir($path))
|
||||
@@ -43,33 +280,15 @@ function limit_length(&$item, $key)
|
||||
$item = substr($item, 0, 253);
|
||||
}
|
||||
|
||||
function process_file($contents,$check=True)
|
||||
function process_file($contents)
|
||||
{
|
||||
$domains = array_filter(explode("\n",$contents));
|
||||
|
||||
// Walk array and apply a max string length
|
||||
// function to every member of the array of domains
|
||||
array_walk($domains, "limit_length");
|
||||
|
||||
// Check validity of domains (don't do it for regex filters)
|
||||
if($check)
|
||||
{
|
||||
check_domains($domains);
|
||||
}
|
||||
|
||||
return $domains;
|
||||
}
|
||||
|
||||
function check_domains($domains)
|
||||
{
|
||||
foreach($domains as $domain)
|
||||
{
|
||||
if(!is_valid_domain_name($domain)){
|
||||
die(htmlspecialchars($domain).' is not a valid domain');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($_POST["action"]))
|
||||
{
|
||||
if($_FILES["zip_file"]["name"] && $_POST["action"] == "in")
|
||||
@@ -103,58 +322,124 @@ if(isset($_POST["action"]))
|
||||
|
||||
$importedsomething = false;
|
||||
|
||||
foreach($archive as $file)
|
||||
$flushtables = isset($_POST["flushtables"]);
|
||||
|
||||
foreach(new RecursiveIteratorIterator($archive) as $file)
|
||||
{
|
||||
if(isset($_POST["blacklist"]) && $file->getFilename() === "blacklist.txt")
|
||||
{
|
||||
$blacklist = process_file(file_get_contents($file));
|
||||
echo "Processing blacklist.txt (".count($blacklist)." entries)<br>\n";
|
||||
exec("sudo pihole -b -nr --nuke");
|
||||
exec("sudo pihole -b -q -nr ".implode(" ", $blacklist));
|
||||
$num = archive_insert_into_table($file, "blacklist", $flushtables);
|
||||
echo "Processed blacklist (exact) (".$num." entries)<br>\n";
|
||||
$importedsomething = true;
|
||||
}
|
||||
|
||||
if(isset($_POST["whitelist"]) && $file->getFilename() === "whitelist.txt")
|
||||
{
|
||||
$whitelist = process_file(file_get_contents($file));
|
||||
echo "Processing whitelist.txt (".count($whitelist)." entries)<br>\n";
|
||||
exec("sudo pihole -w -nr --nuke");
|
||||
exec("sudo pihole -w -q -nr ".implode(" ", $whitelist));
|
||||
$num = archive_insert_into_table($file, "whitelist", $flushtables);
|
||||
echo "Processed whitelist (exact) (".$num." entries)<br>\n";
|
||||
$importedsomething = true;
|
||||
}
|
||||
|
||||
if(isset($_POST["regexlist"]) && $file->getFilename() === "regex.list")
|
||||
{
|
||||
$regexraw = file_get_contents($file);
|
||||
$regexlist = process_file($regexraw,false);
|
||||
echo "Processing regex.list (".count($regexlist)." entries)<br>\n";
|
||||
// NULL = overwrite (or create) the regex filter file
|
||||
add_regex($regexraw, NULL,"");
|
||||
$num = archive_insert_into_table($file, "regex_blacklist", $flushtables);
|
||||
echo "Processed blacklist (regex) (".$num." entries)<br>\n";
|
||||
$importedsomething = true;
|
||||
}
|
||||
|
||||
// Also try to import legacy wildcard list if found
|
||||
if(isset($_POST["regexlist"]) && $file->getFilename() === "wildcardblocking.txt")
|
||||
{
|
||||
$wildlist = process_file(file_get_contents($file));
|
||||
echo "Processing wildcardblocking.txt (".count($wildlist)." entries)<br>\n";
|
||||
exec("sudo pihole --wild -nr --nuke");
|
||||
exec("sudo pihole --wild -q -nr ".implode(" ", $wildlist));
|
||||
$num = archive_insert_into_table($file, "regex_blacklist", $flushtables, true);
|
||||
echo "Processed blacklist (regex, wildcard style) (".$num." entries)<br>\n";
|
||||
$importedsomething = true;
|
||||
}
|
||||
|
||||
if(isset($_POST["auditlog"]) && $file->getFilename() === "auditlog.list")
|
||||
{
|
||||
$auditlog = process_file(file_get_contents($file));
|
||||
echo "Processing auditlog.list (".count($auditlog)." entries)<br>\n";
|
||||
exec("sudo pihole -a clearaudit");
|
||||
exec("sudo pihole -a audit ".implode(" ",$auditlog));
|
||||
$num = archive_insert_into_table($file, "domain_audit", $flushtables);
|
||||
echo "Processed audit log (".$num." entries)<br>\n";
|
||||
$importedsomething = true;
|
||||
}
|
||||
|
||||
if($importedsomething)
|
||||
if(isset($_POST["adlist"]) && $file->getFilename() === "adlists.list")
|
||||
{
|
||||
exec("sudo pihole restartdns");
|
||||
$num = archive_insert_into_table($file, "adlist", $flushtables);
|
||||
echo "Processed adlists (".$num." entries)<br>\n";
|
||||
$importedsomething = true;
|
||||
}
|
||||
|
||||
if(isset($_POST["blacklist"]) && $file->getFilename() === "blacklist.exact.json")
|
||||
{
|
||||
$num = archive_restore_table($file, "blacklist", $flushtables);
|
||||
echo "Processed blacklist (exact) (".$num." entries)<br>\n";
|
||||
$importedsomething = true;
|
||||
}
|
||||
|
||||
if(isset($_POST["regexlist"]) && $file->getFilename() === "blacklist.regex.json")
|
||||
{
|
||||
$num = archive_restore_table($file, "regex_blacklist", $flushtables);
|
||||
echo "Processed blacklist (regex) (".$num." entries)<br>\n";
|
||||
$importedsomething = true;
|
||||
}
|
||||
|
||||
if(isset($_POST["whitelist"]) && $file->getFilename() === "whitelist.exact.json")
|
||||
{
|
||||
$num = archive_restore_table($file, "whitelist", $flushtables);
|
||||
echo "Processed whitelist (exact) (".$num." entries)<br>\n";
|
||||
$importedsomething = true;
|
||||
}
|
||||
|
||||
if(isset($_POST["regex_whitelist"]) && $file->getFilename() === "whitelist.regex.json")
|
||||
{
|
||||
$num = archive_restore_table($file, "regex_whitelist", $flushtables);
|
||||
echo "Processed whitelist (regex) (".$num." entries)<br>\n";
|
||||
$importedsomething = true;
|
||||
}
|
||||
|
||||
if(isset($_POST["adlist"]) && $file->getFilename() === "adlist.json")
|
||||
{
|
||||
$num = archive_restore_table($file, "adlist", $flushtables);
|
||||
echo "Processed adlist (".$num." entries)<br>\n";
|
||||
$importedsomething = true;
|
||||
}
|
||||
|
||||
if(isset($_POST["auditlog"]) && $file->getFilename() === "domain_audit.json")
|
||||
{
|
||||
$num = archive_restore_table($file, "domain_audit", $flushtables);
|
||||
echo "Processed domain_audit (".$num." entries)<br>\n";
|
||||
$importedsomething = true;
|
||||
}
|
||||
|
||||
if(isset($_POST["staticdhcpleases"]) && $file->getFilename() === "04-pihole-static-dhcp.conf")
|
||||
{
|
||||
if($flushtables) {
|
||||
$local_file = @fopen("/etc/dnsmasq.d/04-pihole-static-dhcp.conf", "r+");
|
||||
if ($local_file !== false) {
|
||||
ftruncate($local_file, 0);
|
||||
fclose($local_file);
|
||||
}
|
||||
}
|
||||
$num = 0;
|
||||
$staticdhcpleases = process_file(file_get_contents($file));
|
||||
foreach($staticdhcpleases as $lease) {
|
||||
list($mac,$ip,$hostname) = explode(",",$lease);
|
||||
$mac = formatMAC($mac);
|
||||
if(addStaticDHCPLease($mac,$ip,$hostname))
|
||||
$num++;
|
||||
}
|
||||
|
||||
readStaticLeasesFile();
|
||||
echo "Processed static DHCP leases (".$num." entries)<br>\n";
|
||||
if($num > 0) {
|
||||
$importedsomething = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($importedsomething)
|
||||
{
|
||||
exec("sudo pihole restartdns reload");
|
||||
}
|
||||
|
||||
unlink($fullfilename);
|
||||
@@ -176,19 +461,22 @@ else
|
||||
exit("cannot open/create ".htmlentities($archive_file_name)."<br>\nPHP user: ".exec('whoami')."\n");
|
||||
}
|
||||
|
||||
archive_add_file("/etc/pihole/","whitelist.txt");
|
||||
archive_add_file("/etc/pihole/","blacklist.txt");
|
||||
archive_add_file("/etc/pihole/","adlists.list");
|
||||
archive_add_table("whitelist.exact.json", "domainlist", ListType::whitelist);
|
||||
archive_add_table("whitelist.regex.json", "domainlist", ListType::regex_whitelist);
|
||||
archive_add_table("blacklist.exact.json", "domainlist", ListType::blacklist);
|
||||
archive_add_table("blacklist.regex.json", "domainlist", ListType::regex_blacklist);
|
||||
archive_add_table("adlist.json", "adlist");
|
||||
archive_add_table("domain_audit.json", "domain_audit");
|
||||
archive_add_file("/etc/pihole/","setupVars.conf");
|
||||
archive_add_file("/etc/pihole/","auditlog.list");
|
||||
archive_add_file("/etc/pihole/","regex.list");
|
||||
archive_add_file("/etc/pihole/","dhcp.leases");
|
||||
archive_add_file("/etc/","hosts","etc/");
|
||||
archive_add_directory("/etc/dnsmasq.d/","dnsmasq.d/");
|
||||
|
||||
$archive->compress(Phar::GZ); // Creates a gziped copy
|
||||
unlink($archive_file_name); // Unlink original tar file as it is not needed anymore
|
||||
$archive_file_name .= ".gz"; // Append ".gz" extension to ".tar"
|
||||
|
||||
header("Content-type: application/zip");
|
||||
header("Content-type: application/gzip");
|
||||
header('Content-Transfer-Encoding: binary');
|
||||
header("Content-Disposition: attachment; filename=".$filename);
|
||||
header("Content-length: " . filesize($archive_file_name));
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
/**
|
||||
* @preserve HTML5 Shiv 3.7.2 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
|
||||
*/
|
||||
!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.2",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b)}(this,document);
|
||||
@@ -1,166 +1,180 @@
|
||||
/*!
|
||||
DataTables 1.10.12
|
||||
©2008-2015 SpryMedia Ltd - datatables.net/license
|
||||
Copyright 2008-2019 SpryMedia Ltd.
|
||||
|
||||
This source file is free software, available under the following license:
|
||||
MIT license - http://datatables.net/license
|
||||
|
||||
This source file is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
|
||||
|
||||
For details please refer to: http://www.datatables.net
|
||||
DataTables 1.10.20
|
||||
©2008-2019 SpryMedia Ltd - datatables.net/license
|
||||
*/
|
||||
(function(h){"function"===typeof define&&define.amd?define(["jquery"],function(D){return h(D,window,document)}):"object"===typeof exports?module.exports=function(D,I){D||(D=window);I||(I="undefined"!==typeof window?require("jquery"):require("jquery")(D));return h(I,D,D.document)}:h(jQuery,window,document)})(function(h,D,I,k){function X(a){var b,c,d={};h.each(a,function(e){if((b=e.match(/^([^A-Z]+?)([A-Z])/))&&-1!=="a aa ai ao as b fn i m o s ".indexOf(b[1]+" "))c=e.replace(b[0],b[2].toLowerCase()),
|
||||
d[c]=e,"o"===b[1]&&X(a[e])});a._hungarianMap=d}function K(a,b,c){a._hungarianMap||X(a);var d;h.each(b,function(e){d=a._hungarianMap[e];if(d!==k&&(c||b[d]===k))"o"===d.charAt(0)?(b[d]||(b[d]={}),h.extend(!0,b[d],b[e]),K(a[d],b[d],c)):b[d]=b[e]})}function Da(a){var b=m.defaults.oLanguage,c=a.sZeroRecords;!a.sEmptyTable&&(c&&"No data available in table"===b.sEmptyTable)&&E(a,a,"sZeroRecords","sEmptyTable");!a.sLoadingRecords&&(c&&"Loading..."===b.sLoadingRecords)&&E(a,a,"sZeroRecords","sLoadingRecords");
|
||||
a.sInfoThousands&&(a.sThousands=a.sInfoThousands);(a=a.sDecimal)&&db(a)}function eb(a){A(a,"ordering","bSort");A(a,"orderMulti","bSortMulti");A(a,"orderClasses","bSortClasses");A(a,"orderCellsTop","bSortCellsTop");A(a,"order","aaSorting");A(a,"orderFixed","aaSortingFixed");A(a,"paging","bPaginate");A(a,"pagingType","sPaginationType");A(a,"pageLength","iDisplayLength");A(a,"searching","bFilter");"boolean"===typeof a.sScrollX&&(a.sScrollX=a.sScrollX?"100%":"");"boolean"===typeof a.scrollX&&(a.scrollX=
|
||||
a.scrollX?"100%":"");if(a=a.aoSearchCols)for(var b=0,c=a.length;b<c;b++)a[b]&&K(m.models.oSearch,a[b])}function fb(a){A(a,"orderable","bSortable");A(a,"orderData","aDataSort");A(a,"orderSequence","asSorting");A(a,"orderDataType","sortDataType");var b=a.aDataSort;b&&!h.isArray(b)&&(a.aDataSort=[b])}function gb(a){if(!m.__browser){var b={};m.__browser=b;var c=h("<div/>").css({position:"fixed",top:0,left:0,height:1,width:1,overflow:"hidden"}).append(h("<div/>").css({position:"absolute",top:1,left:1,
|
||||
width:100,overflow:"scroll"}).append(h("<div/>").css({width:"100%",height:10}))).appendTo("body"),d=c.children(),e=d.children();b.barWidth=d[0].offsetWidth-d[0].clientWidth;b.bScrollOversize=100===e[0].offsetWidth&&100!==d[0].clientWidth;b.bScrollbarLeft=1!==Math.round(e.offset().left);b.bBounding=c[0].getBoundingClientRect().width?!0:!1;c.remove()}h.extend(a.oBrowser,m.__browser);a.oScroll.iBarWidth=m.__browser.barWidth}function hb(a,b,c,d,e,f){var g,j=!1;c!==k&&(g=c,j=!0);for(;d!==e;)a.hasOwnProperty(d)&&
|
||||
(g=j?b(g,a[d],d,a):a[d],j=!0,d+=f);return g}function Ea(a,b){var c=m.defaults.column,d=a.aoColumns.length,c=h.extend({},m.models.oColumn,c,{nTh:b?b:I.createElement("th"),sTitle:c.sTitle?c.sTitle:b?b.innerHTML:"",aDataSort:c.aDataSort?c.aDataSort:[d],mData:c.mData?c.mData:d,idx:d});a.aoColumns.push(c);c=a.aoPreSearchCols;c[d]=h.extend({},m.models.oSearch,c[d]);ja(a,d,h(b).data())}function ja(a,b,c){var b=a.aoColumns[b],d=a.oClasses,e=h(b.nTh);if(!b.sWidthOrig){b.sWidthOrig=e.attr("width")||null;var f=
|
||||
(e.attr("style")||"").match(/width:\s*(\d+[pxem%]+)/);f&&(b.sWidthOrig=f[1])}c!==k&&null!==c&&(fb(c),K(m.defaults.column,c),c.mDataProp!==k&&!c.mData&&(c.mData=c.mDataProp),c.sType&&(b._sManualType=c.sType),c.className&&!c.sClass&&(c.sClass=c.className),h.extend(b,c),E(b,c,"sWidth","sWidthOrig"),c.iDataSort!==k&&(b.aDataSort=[c.iDataSort]),E(b,c,"aDataSort"));var g=b.mData,j=Q(g),i=b.mRender?Q(b.mRender):null,c=function(a){return"string"===typeof a&&-1!==a.indexOf("@")};b._bAttrSrc=h.isPlainObject(g)&&
|
||||
(c(g.sort)||c(g.type)||c(g.filter));b._setter=null;b.fnGetData=function(a,b,c){var d=j(a,b,k,c);return i&&b?i(d,b,a,c):d};b.fnSetData=function(a,b,c){return R(g)(a,b,c)};"number"!==typeof g&&(a._rowReadObject=!0);a.oFeatures.bSort||(b.bSortable=!1,e.addClass(d.sSortableNone));a=-1!==h.inArray("asc",b.asSorting);c=-1!==h.inArray("desc",b.asSorting);!b.bSortable||!a&&!c?(b.sSortingClass=d.sSortableNone,b.sSortingClassJUI=""):a&&!c?(b.sSortingClass=d.sSortableAsc,b.sSortingClassJUI=d.sSortJUIAscAllowed):
|
||||
!a&&c?(b.sSortingClass=d.sSortableDesc,b.sSortingClassJUI=d.sSortJUIDescAllowed):(b.sSortingClass=d.sSortable,b.sSortingClassJUI=d.sSortJUI)}function Y(a){if(!1!==a.oFeatures.bAutoWidth){var b=a.aoColumns;Fa(a);for(var c=0,d=b.length;c<d;c++)b[c].nTh.style.width=b[c].sWidth}b=a.oScroll;(""!==b.sY||""!==b.sX)&&ka(a);u(a,null,"column-sizing",[a])}function Z(a,b){var c=la(a,"bVisible");return"number"===typeof c[b]?c[b]:null}function $(a,b){var c=la(a,"bVisible"),c=h.inArray(b,c);return-1!==c?c:null}
|
||||
function aa(a){var b=0;h.each(a.aoColumns,function(a,d){d.bVisible&&"none"!==h(d.nTh).css("display")&&b++});return b}function la(a,b){var c=[];h.map(a.aoColumns,function(a,e){a[b]&&c.push(e)});return c}function Ga(a){var b=a.aoColumns,c=a.aoData,d=m.ext.type.detect,e,f,g,j,i,h,l,q,t;e=0;for(f=b.length;e<f;e++)if(l=b[e],t=[],!l.sType&&l._sManualType)l.sType=l._sManualType;else if(!l.sType){g=0;for(j=d.length;g<j;g++){i=0;for(h=c.length;i<h;i++){t[i]===k&&(t[i]=B(a,i,e,"type"));q=d[g](t[i],a);if(!q&&
|
||||
g!==d.length-1)break;if("html"===q)break}if(q){l.sType=q;break}}l.sType||(l.sType="string")}}function ib(a,b,c,d){var e,f,g,j,i,n,l=a.aoColumns;if(b)for(e=b.length-1;0<=e;e--){n=b[e];var q=n.targets!==k?n.targets:n.aTargets;h.isArray(q)||(q=[q]);f=0;for(g=q.length;f<g;f++)if("number"===typeof q[f]&&0<=q[f]){for(;l.length<=q[f];)Ea(a);d(q[f],n)}else if("number"===typeof q[f]&&0>q[f])d(l.length+q[f],n);else if("string"===typeof q[f]){j=0;for(i=l.length;j<i;j++)("_all"==q[f]||h(l[j].nTh).hasClass(q[f]))&&
|
||||
d(j,n)}}if(c){e=0;for(a=c.length;e<a;e++)d(e,c[e])}}function N(a,b,c,d){var e=a.aoData.length,f=h.extend(!0,{},m.models.oRow,{src:c?"dom":"data",idx:e});f._aData=b;a.aoData.push(f);for(var g=a.aoColumns,j=0,i=g.length;j<i;j++)g[j].sType=null;a.aiDisplayMaster.push(e);b=a.rowIdFn(b);b!==k&&(a.aIds[b]=f);(c||!a.oFeatures.bDeferRender)&&Ha(a,e,c,d);return e}function ma(a,b){var c;b instanceof h||(b=h(b));return b.map(function(b,e){c=Ia(a,e);return N(a,c.data,e,c.cells)})}function B(a,b,c,d){var e=a.iDraw,
|
||||
f=a.aoColumns[c],g=a.aoData[b]._aData,j=f.sDefaultContent,i=f.fnGetData(g,d,{settings:a,row:b,col:c});if(i===k)return a.iDrawError!=e&&null===j&&(L(a,0,"Requested unknown parameter "+("function"==typeof f.mData?"{function}":"'"+f.mData+"'")+" for row "+b+", column "+c,4),a.iDrawError=e),j;if((i===g||null===i)&&null!==j&&d!==k)i=j;else if("function"===typeof i)return i.call(g);return null===i&&"display"==d?"":i}function jb(a,b,c,d){a.aoColumns[c].fnSetData(a.aoData[b]._aData,d,{settings:a,row:b,col:c})}
|
||||
function Ja(a){return h.map(a.match(/(\\.|[^\.])+/g)||[""],function(a){return a.replace(/\\./g,".")})}function Q(a){if(h.isPlainObject(a)){var b={};h.each(a,function(a,c){c&&(b[a]=Q(c))});return function(a,c,f,g){var j=b[c]||b._;return j!==k?j(a,c,f,g):a}}if(null===a)return function(a){return a};if("function"===typeof a)return function(b,c,f,g){return a(b,c,f,g)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("[")||-1!==a.indexOf("("))){var c=function(a,b,f){var g,j;if(""!==f){j=Ja(f);
|
||||
for(var i=0,n=j.length;i<n;i++){f=j[i].match(ba);g=j[i].match(U);if(f){j[i]=j[i].replace(ba,"");""!==j[i]&&(a=a[j[i]]);g=[];j.splice(0,i+1);j=j.join(".");if(h.isArray(a)){i=0;for(n=a.length;i<n;i++)g.push(c(a[i],b,j))}a=f[0].substring(1,f[0].length-1);a=""===a?g:g.join(a);break}else if(g){j[i]=j[i].replace(U,"");a=a[j[i]]();continue}if(null===a||a[j[i]]===k)return k;a=a[j[i]]}}return a};return function(b,e){return c(b,e,a)}}return function(b){return b[a]}}function R(a){if(h.isPlainObject(a))return R(a._);
|
||||
if(null===a)return function(){};if("function"===typeof a)return function(b,d,e){a(b,"set",d,e)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("[")||-1!==a.indexOf("("))){var b=function(a,d,e){var e=Ja(e),f;f=e[e.length-1];for(var g,j,i=0,n=e.length-1;i<n;i++){g=e[i].match(ba);j=e[i].match(U);if(g){e[i]=e[i].replace(ba,"");a[e[i]]=[];f=e.slice();f.splice(0,i+1);g=f.join(".");if(h.isArray(d)){j=0;for(n=d.length;j<n;j++)f={},b(f,d[j],g),a[e[i]].push(f)}else a[e[i]]=d;return}j&&(e[i]=e[i].replace(U,
|
||||
""),a=a[e[i]](d));if(null===a[e[i]]||a[e[i]]===k)a[e[i]]={};a=a[e[i]]}if(f.match(U))a[f.replace(U,"")](d);else a[f.replace(ba,"")]=d};return function(c,d){return b(c,d,a)}}return function(b,d){b[a]=d}}function Ka(a){return G(a.aoData,"_aData")}function na(a){a.aoData.length=0;a.aiDisplayMaster.length=0;a.aiDisplay.length=0;a.aIds={}}function oa(a,b,c){for(var d=-1,e=0,f=a.length;e<f;e++)a[e]==b?d=e:a[e]>b&&a[e]--; -1!=d&&c===k&&a.splice(d,1)}function ca(a,b,c,d){var e=a.aoData[b],f,g=function(c,d){for(;c.childNodes.length;)c.removeChild(c.firstChild);
|
||||
c.innerHTML=B(a,b,d,"display")};if("dom"===c||(!c||"auto"===c)&&"dom"===e.src)e._aData=Ia(a,e,d,d===k?k:e._aData).data;else{var j=e.anCells;if(j)if(d!==k)g(j[d],d);else{c=0;for(f=j.length;c<f;c++)g(j[c],c)}}e._aSortData=null;e._aFilterData=null;g=a.aoColumns;if(d!==k)g[d].sType=null;else{c=0;for(f=g.length;c<f;c++)g[c].sType=null;La(a,e)}}function Ia(a,b,c,d){var e=[],f=b.firstChild,g,j,i=0,n,l=a.aoColumns,q=a._rowReadObject,d=d!==k?d:q?{}:[],t=function(a,b){if("string"===typeof a){var c=a.indexOf("@");
|
||||
-1!==c&&(c=a.substring(c+1),R(a)(d,b.getAttribute(c)))}},S=function(a){if(c===k||c===i)j=l[i],n=h.trim(a.innerHTML),j&&j._bAttrSrc?(R(j.mData._)(d,n),t(j.mData.sort,a),t(j.mData.type,a),t(j.mData.filter,a)):q?(j._setter||(j._setter=R(j.mData)),j._setter(d,n)):d[i]=n;i++};if(f)for(;f;){g=f.nodeName.toUpperCase();if("TD"==g||"TH"==g)S(f),e.push(f);f=f.nextSibling}else{e=b.anCells;f=0;for(g=e.length;f<g;f++)S(e[f])}if(b=b.firstChild?b:b.nTr)(b=b.getAttribute("id"))&&R(a.rowId)(d,b);return{data:d,cells:e}}
|
||||
function Ha(a,b,c,d){var e=a.aoData[b],f=e._aData,g=[],j,i,n,l,q;if(null===e.nTr){j=c||I.createElement("tr");e.nTr=j;e.anCells=g;j._DT_RowIndex=b;La(a,e);l=0;for(q=a.aoColumns.length;l<q;l++){n=a.aoColumns[l];i=c?d[l]:I.createElement(n.sCellType);i._DT_CellIndex={row:b,column:l};g.push(i);if((!c||n.mRender||n.mData!==l)&&(!h.isPlainObject(n.mData)||n.mData._!==l+".display"))i.innerHTML=B(a,b,l,"display");n.sClass&&(i.className+=" "+n.sClass);n.bVisible&&!c?j.appendChild(i):!n.bVisible&&c&&i.parentNode.removeChild(i);
|
||||
n.fnCreatedCell&&n.fnCreatedCell.call(a.oInstance,i,B(a,b,l),f,b,l)}u(a,"aoRowCreatedCallback",null,[j,f,b])}e.nTr.setAttribute("role","row")}function La(a,b){var c=b.nTr,d=b._aData;if(c){var e=a.rowIdFn(d);e&&(c.id=e);d.DT_RowClass&&(e=d.DT_RowClass.split(" "),b.__rowc=b.__rowc?pa(b.__rowc.concat(e)):e,h(c).removeClass(b.__rowc.join(" ")).addClass(d.DT_RowClass));d.DT_RowAttr&&h(c).attr(d.DT_RowAttr);d.DT_RowData&&h(c).data(d.DT_RowData)}}function kb(a){var b,c,d,e,f,g=a.nTHead,j=a.nTFoot,i=0===
|
||||
h("th, td",g).length,n=a.oClasses,l=a.aoColumns;i&&(e=h("<tr/>").appendTo(g));b=0;for(c=l.length;b<c;b++)f=l[b],d=h(f.nTh).addClass(f.sClass),i&&d.appendTo(e),a.oFeatures.bSort&&(d.addClass(f.sSortingClass),!1!==f.bSortable&&(d.attr("tabindex",a.iTabIndex).attr("aria-controls",a.sTableId),Ma(a,f.nTh,b))),f.sTitle!=d[0].innerHTML&&d.html(f.sTitle),Na(a,"header")(a,d,f,n);i&&da(a.aoHeader,g);h(g).find(">tr").attr("role","row");h(g).find(">tr>th, >tr>td").addClass(n.sHeaderTH);h(j).find(">tr>th, >tr>td").addClass(n.sFooterTH);
|
||||
if(null!==j){a=a.aoFooter[0];b=0;for(c=a.length;b<c;b++)f=l[b],f.nTf=a[b].cell,f.sClass&&h(f.nTf).addClass(f.sClass)}}function ea(a,b,c){var d,e,f,g=[],j=[],i=a.aoColumns.length,n;if(b){c===k&&(c=!1);d=0;for(e=b.length;d<e;d++){g[d]=b[d].slice();g[d].nTr=b[d].nTr;for(f=i-1;0<=f;f--)!a.aoColumns[f].bVisible&&!c&&g[d].splice(f,1);j.push([])}d=0;for(e=g.length;d<e;d++){if(a=g[d].nTr)for(;f=a.firstChild;)a.removeChild(f);f=0;for(b=g[d].length;f<b;f++)if(n=i=1,j[d][f]===k){a.appendChild(g[d][f].cell);
|
||||
for(j[d][f]=1;g[d+i]!==k&&g[d][f].cell==g[d+i][f].cell;)j[d+i][f]=1,i++;for(;g[d][f+n]!==k&&g[d][f].cell==g[d][f+n].cell;){for(c=0;c<i;c++)j[d+c][f+n]=1;n++}h(g[d][f].cell).attr("rowspan",i).attr("colspan",n)}}}}function O(a){var b=u(a,"aoPreDrawCallback","preDraw",[a]);if(-1!==h.inArray(!1,b))C(a,!1);else{var b=[],c=0,d=a.asStripeClasses,e=d.length,f=a.oLanguage,g=a.iInitDisplayStart,j="ssp"==y(a),i=a.aiDisplay;a.bDrawing=!0;g!==k&&-1!==g&&(a._iDisplayStart=j?g:g>=a.fnRecordsDisplay()?0:g,a.iInitDisplayStart=
|
||||
-1);var g=a._iDisplayStart,n=a.fnDisplayEnd();if(a.bDeferLoading)a.bDeferLoading=!1,a.iDraw++,C(a,!1);else if(j){if(!a.bDestroying&&!lb(a))return}else a.iDraw++;if(0!==i.length){f=j?a.aoData.length:n;for(j=j?0:g;j<f;j++){var l=i[j],q=a.aoData[l];null===q.nTr&&Ha(a,l);l=q.nTr;if(0!==e){var t=d[c%e];q._sRowStripe!=t&&(h(l).removeClass(q._sRowStripe).addClass(t),q._sRowStripe=t)}u(a,"aoRowCallback",null,[l,q._aData,c,j]);b.push(l);c++}}else c=f.sZeroRecords,1==a.iDraw&&"ajax"==y(a)?c=f.sLoadingRecords:
|
||||
f.sEmptyTable&&0===a.fnRecordsTotal()&&(c=f.sEmptyTable),b[0]=h("<tr/>",{"class":e?d[0]:""}).append(h("<td />",{valign:"top",colSpan:aa(a),"class":a.oClasses.sRowEmpty}).html(c))[0];u(a,"aoHeaderCallback","header",[h(a.nTHead).children("tr")[0],Ka(a),g,n,i]);u(a,"aoFooterCallback","footer",[h(a.nTFoot).children("tr")[0],Ka(a),g,n,i]);d=h(a.nTBody);d.children().detach();d.append(h(b));u(a,"aoDrawCallback","draw",[a]);a.bSorted=!1;a.bFiltered=!1;a.bDrawing=!1}}function T(a,b){var c=a.oFeatures,d=c.bFilter;
|
||||
c.bSort&&mb(a);d?fa(a,a.oPreviousSearch):a.aiDisplay=a.aiDisplayMaster.slice();!0!==b&&(a._iDisplayStart=0);a._drawHold=b;O(a);a._drawHold=!1}function nb(a){var b=a.oClasses,c=h(a.nTable),c=h("<div/>").insertBefore(c),d=a.oFeatures,e=h("<div/>",{id:a.sTableId+"_wrapper","class":b.sWrapper+(a.nTFoot?"":" "+b.sNoFooter)});a.nHolding=c[0];a.nTableWrapper=e[0];a.nTableReinsertBefore=a.nTable.nextSibling;for(var f=a.sDom.split(""),g,j,i,n,l,q,t=0;t<f.length;t++){g=null;j=f[t];if("<"==j){i=h("<div/>")[0];
|
||||
n=f[t+1];if("'"==n||'"'==n){l="";for(q=2;f[t+q]!=n;)l+=f[t+q],q++;"H"==l?l=b.sJUIHeader:"F"==l&&(l=b.sJUIFooter);-1!=l.indexOf(".")?(n=l.split("."),i.id=n[0].substr(1,n[0].length-1),i.className=n[1]):"#"==l.charAt(0)?i.id=l.substr(1,l.length-1):i.className=l;t+=q}e.append(i);e=h(i)}else if(">"==j)e=e.parent();else if("l"==j&&d.bPaginate&&d.bLengthChange)g=ob(a);else if("f"==j&&d.bFilter)g=pb(a);else if("r"==j&&d.bProcessing)g=qb(a);else if("t"==j)g=rb(a);else if("i"==j&&d.bInfo)g=sb(a);else if("p"==
|
||||
j&&d.bPaginate)g=tb(a);else if(0!==m.ext.feature.length){i=m.ext.feature;q=0;for(n=i.length;q<n;q++)if(j==i[q].cFeature){g=i[q].fnInit(a);break}}g&&(i=a.aanFeatures,i[j]||(i[j]=[]),i[j].push(g),e.append(g))}c.replaceWith(e);a.nHolding=null}function da(a,b){var c=h(b).children("tr"),d,e,f,g,j,i,n,l,q,t;a.splice(0,a.length);f=0;for(i=c.length;f<i;f++)a.push([]);f=0;for(i=c.length;f<i;f++){d=c[f];for(e=d.firstChild;e;){if("TD"==e.nodeName.toUpperCase()||"TH"==e.nodeName.toUpperCase()){l=1*e.getAttribute("colspan");
|
||||
q=1*e.getAttribute("rowspan");l=!l||0===l||1===l?1:l;q=!q||0===q||1===q?1:q;g=0;for(j=a[f];j[g];)g++;n=g;t=1===l?!0:!1;for(j=0;j<l;j++)for(g=0;g<q;g++)a[f+g][n+j]={cell:e,unique:t},a[f+g].nTr=d}e=e.nextSibling}}}function qa(a,b,c){var d=[];c||(c=a.aoHeader,b&&(c=[],da(c,b)));for(var b=0,e=c.length;b<e;b++)for(var f=0,g=c[b].length;f<g;f++)if(c[b][f].unique&&(!d[f]||!a.bSortCellsTop))d[f]=c[b][f].cell;return d}function ra(a,b,c){u(a,"aoServerParams","serverParams",[b]);if(b&&h.isArray(b)){var d={},
|
||||
e=/(.*?)\[\]$/;h.each(b,function(a,b){var c=b.name.match(e);c?(c=c[0],d[c]||(d[c]=[]),d[c].push(b.value)):d[b.name]=b.value});b=d}var f,g=a.ajax,j=a.oInstance,i=function(b){u(a,null,"xhr",[a,b,a.jqXHR]);c(b)};if(h.isPlainObject(g)&&g.data){f=g.data;var n=h.isFunction(f)?f(b,a):f,b=h.isFunction(f)&&n?n:h.extend(!0,b,n);delete g.data}n={data:b,success:function(b){var c=b.error||b.sError;c&&L(a,0,c);a.json=b;i(b)},dataType:"json",cache:!1,type:a.sServerMethod,error:function(b,c){var d=u(a,null,"xhr",
|
||||
[a,null,a.jqXHR]);-1===h.inArray(!0,d)&&("parsererror"==c?L(a,0,"Invalid JSON response",1):4===b.readyState&&L(a,0,"Ajax error",7));C(a,!1)}};a.oAjaxData=b;u(a,null,"preXhr",[a,b]);a.fnServerData?a.fnServerData.call(j,a.sAjaxSource,h.map(b,function(a,b){return{name:b,value:a}}),i,a):a.sAjaxSource||"string"===typeof g?a.jqXHR=h.ajax(h.extend(n,{url:g||a.sAjaxSource})):h.isFunction(g)?a.jqXHR=g.call(j,b,i,a):(a.jqXHR=h.ajax(h.extend(n,g)),g.data=f)}function lb(a){return a.bAjaxDataGet?(a.iDraw++,C(a,
|
||||
!0),ra(a,ub(a),function(b){vb(a,b)}),!1):!0}function ub(a){var b=a.aoColumns,c=b.length,d=a.oFeatures,e=a.oPreviousSearch,f=a.aoPreSearchCols,g,j=[],i,n,l,q=V(a);g=a._iDisplayStart;i=!1!==d.bPaginate?a._iDisplayLength:-1;var k=function(a,b){j.push({name:a,value:b})};k("sEcho",a.iDraw);k("iColumns",c);k("sColumns",G(b,"sName").join(","));k("iDisplayStart",g);k("iDisplayLength",i);var S={draw:a.iDraw,columns:[],order:[],start:g,length:i,search:{value:e.sSearch,regex:e.bRegex}};for(g=0;g<c;g++)n=b[g],
|
||||
l=f[g],i="function"==typeof n.mData?"function":n.mData,S.columns.push({data:i,name:n.sName,searchable:n.bSearchable,orderable:n.bSortable,search:{value:l.sSearch,regex:l.bRegex}}),k("mDataProp_"+g,i),d.bFilter&&(k("sSearch_"+g,l.sSearch),k("bRegex_"+g,l.bRegex),k("bSearchable_"+g,n.bSearchable)),d.bSort&&k("bSortable_"+g,n.bSortable);d.bFilter&&(k("sSearch",e.sSearch),k("bRegex",e.bRegex));d.bSort&&(h.each(q,function(a,b){S.order.push({column:b.col,dir:b.dir});k("iSortCol_"+a,b.col);k("sSortDir_"+
|
||||
a,b.dir)}),k("iSortingCols",q.length));b=m.ext.legacy.ajax;return null===b?a.sAjaxSource?j:S:b?j:S}function vb(a,b){var c=sa(a,b),d=b.sEcho!==k?b.sEcho:b.draw,e=b.iTotalRecords!==k?b.iTotalRecords:b.recordsTotal,f=b.iTotalDisplayRecords!==k?b.iTotalDisplayRecords:b.recordsFiltered;if(d){if(1*d<a.iDraw)return;a.iDraw=1*d}na(a);a._iRecordsTotal=parseInt(e,10);a._iRecordsDisplay=parseInt(f,10);d=0;for(e=c.length;d<e;d++)N(a,c[d]);a.aiDisplay=a.aiDisplayMaster.slice();a.bAjaxDataGet=!1;O(a);a._bInitComplete||
|
||||
ta(a,b);a.bAjaxDataGet=!0;C(a,!1)}function sa(a,b){var c=h.isPlainObject(a.ajax)&&a.ajax.dataSrc!==k?a.ajax.dataSrc:a.sAjaxDataProp;return"data"===c?b.aaData||b[c]:""!==c?Q(c)(b):b}function pb(a){var b=a.oClasses,c=a.sTableId,d=a.oLanguage,e=a.oPreviousSearch,f=a.aanFeatures,g='<input type="search" class="'+b.sFilterInput+'"/>',j=d.sSearch,j=j.match(/_INPUT_/)?j.replace("_INPUT_",g):j+g,b=h("<div/>",{id:!f.f?c+"_filter":null,"class":b.sFilter}).append(h("<label/>").append(j)),f=function(){var b=!this.value?
|
||||
"":this.value;b!=e.sSearch&&(fa(a,{sSearch:b,bRegex:e.bRegex,bSmart:e.bSmart,bCaseInsensitive:e.bCaseInsensitive}),a._iDisplayStart=0,O(a))},g=null!==a.searchDelay?a.searchDelay:"ssp"===y(a)?400:0,i=h("input",b).val(e.sSearch).attr("placeholder",d.sSearchPlaceholder).bind("keyup.DT search.DT input.DT paste.DT cut.DT",g?Oa(f,g):f).bind("keypress.DT",function(a){if(13==a.keyCode)return!1}).attr("aria-controls",c);h(a.nTable).on("search.dt.DT",function(b,c){if(a===c)try{i[0]!==I.activeElement&&i.val(e.sSearch)}catch(d){}});
|
||||
return b[0]}function fa(a,b,c){var d=a.oPreviousSearch,e=a.aoPreSearchCols,f=function(a){d.sSearch=a.sSearch;d.bRegex=a.bRegex;d.bSmart=a.bSmart;d.bCaseInsensitive=a.bCaseInsensitive};Ga(a);if("ssp"!=y(a)){wb(a,b.sSearch,c,b.bEscapeRegex!==k?!b.bEscapeRegex:b.bRegex,b.bSmart,b.bCaseInsensitive);f(b);for(b=0;b<e.length;b++)xb(a,e[b].sSearch,b,e[b].bEscapeRegex!==k?!e[b].bEscapeRegex:e[b].bRegex,e[b].bSmart,e[b].bCaseInsensitive);yb(a)}else f(b);a.bFiltered=!0;u(a,null,"search",[a])}function yb(a){for(var b=
|
||||
m.ext.search,c=a.aiDisplay,d,e,f=0,g=b.length;f<g;f++){for(var j=[],i=0,n=c.length;i<n;i++)e=c[i],d=a.aoData[e],b[f](a,d._aFilterData,e,d._aData,i)&&j.push(e);c.length=0;h.merge(c,j)}}function xb(a,b,c,d,e,f){if(""!==b)for(var g=a.aiDisplay,d=Pa(b,d,e,f),e=g.length-1;0<=e;e--)b=a.aoData[g[e]]._aFilterData[c],d.test(b)||g.splice(e,1)}function wb(a,b,c,d,e,f){var d=Pa(b,d,e,f),e=a.oPreviousSearch.sSearch,f=a.aiDisplayMaster,g;0!==m.ext.search.length&&(c=!0);g=zb(a);if(0>=b.length)a.aiDisplay=f.slice();
|
||||
else{if(g||c||e.length>b.length||0!==b.indexOf(e)||a.bSorted)a.aiDisplay=f.slice();b=a.aiDisplay;for(c=b.length-1;0<=c;c--)d.test(a.aoData[b[c]]._sFilterRow)||b.splice(c,1)}}function Pa(a,b,c,d){a=b?a:Qa(a);c&&(a="^(?=.*?"+h.map(a.match(/"[^"]+"|[^ ]+/g)||[""],function(a){if('"'===a.charAt(0))var b=a.match(/^"(.*)"$/),a=b?b[1]:a;return a.replace('"',"")}).join(")(?=.*?")+").*$");return RegExp(a,d?"i":"")}function zb(a){var b=a.aoColumns,c,d,e,f,g,j,i,h,l=m.ext.type.search;c=!1;d=0;for(f=a.aoData.length;d<
|
||||
f;d++)if(h=a.aoData[d],!h._aFilterData){j=[];e=0;for(g=b.length;e<g;e++)c=b[e],c.bSearchable?(i=B(a,d,e,"filter"),l[c.sType]&&(i=l[c.sType](i)),null===i&&(i=""),"string"!==typeof i&&i.toString&&(i=i.toString())):i="",i.indexOf&&-1!==i.indexOf("&")&&(ua.innerHTML=i,i=Zb?ua.textContent:ua.innerText),i.replace&&(i=i.replace(/[\r\n]/g,"")),j.push(i);h._aFilterData=j;h._sFilterRow=j.join(" ");c=!0}return c}function Ab(a){return{search:a.sSearch,smart:a.bSmart,regex:a.bRegex,caseInsensitive:a.bCaseInsensitive}}
|
||||
function Bb(a){return{sSearch:a.search,bSmart:a.smart,bRegex:a.regex,bCaseInsensitive:a.caseInsensitive}}function sb(a){var b=a.sTableId,c=a.aanFeatures.i,d=h("<div/>",{"class":a.oClasses.sInfo,id:!c?b+"_info":null});c||(a.aoDrawCallback.push({fn:Cb,sName:"information"}),d.attr("role","status").attr("aria-live","polite"),h(a.nTable).attr("aria-describedby",b+"_info"));return d[0]}function Cb(a){var b=a.aanFeatures.i;if(0!==b.length){var c=a.oLanguage,d=a._iDisplayStart+1,e=a.fnDisplayEnd(),f=a.fnRecordsTotal(),
|
||||
g=a.fnRecordsDisplay(),j=g?c.sInfo:c.sInfoEmpty;g!==f&&(j+=" "+c.sInfoFiltered);j+=c.sInfoPostFix;j=Db(a,j);c=c.fnInfoCallback;null!==c&&(j=c.call(a.oInstance,a,d,e,f,g,j));h(b).html(j)}}function Db(a,b){var c=a.fnFormatNumber,d=a._iDisplayStart+1,e=a._iDisplayLength,f=a.fnRecordsDisplay(),g=-1===e;return b.replace(/_START_/g,c.call(a,d)).replace(/_END_/g,c.call(a,a.fnDisplayEnd())).replace(/_MAX_/g,c.call(a,a.fnRecordsTotal())).replace(/_TOTAL_/g,c.call(a,f)).replace(/_PAGE_/g,c.call(a,g?1:Math.ceil(d/
|
||||
e))).replace(/_PAGES_/g,c.call(a,g?1:Math.ceil(f/e)))}function ga(a){var b,c,d=a.iInitDisplayStart,e=a.aoColumns,f;c=a.oFeatures;var g=a.bDeferLoading;if(a.bInitialised){nb(a);kb(a);ea(a,a.aoHeader);ea(a,a.aoFooter);C(a,!0);c.bAutoWidth&&Fa(a);b=0;for(c=e.length;b<c;b++)f=e[b],f.sWidth&&(f.nTh.style.width=x(f.sWidth));u(a,null,"preInit",[a]);T(a);e=y(a);if("ssp"!=e||g)"ajax"==e?ra(a,[],function(c){var f=sa(a,c);for(b=0;b<f.length;b++)N(a,f[b]);a.iInitDisplayStart=d;T(a);C(a,!1);ta(a,c)},a):(C(a,!1),
|
||||
ta(a))}else setTimeout(function(){ga(a)},200)}function ta(a,b){a._bInitComplete=!0;(b||a.oInit.aaData)&&Y(a);u(a,null,"plugin-init",[a,b]);u(a,"aoInitComplete","init",[a,b])}function Ra(a,b){var c=parseInt(b,10);a._iDisplayLength=c;Sa(a);u(a,null,"length",[a,c])}function ob(a){for(var b=a.oClasses,c=a.sTableId,d=a.aLengthMenu,e=h.isArray(d[0]),f=e?d[0]:d,d=e?d[1]:d,e=h("<select/>",{name:c+"_length","aria-controls":c,"class":b.sLengthSelect}),g=0,j=f.length;g<j;g++)e[0][g]=new Option(d[g],f[g]);var i=
|
||||
h("<div><label/></div>").addClass(b.sLength);a.aanFeatures.l||(i[0].id=c+"_length");i.children().append(a.oLanguage.sLengthMenu.replace("_MENU_",e[0].outerHTML));h("select",i).val(a._iDisplayLength).bind("change.DT",function(){Ra(a,h(this).val());O(a)});h(a.nTable).bind("length.dt.DT",function(b,c,d){a===c&&h("select",i).val(d)});return i[0]}function tb(a){var b=a.sPaginationType,c=m.ext.pager[b],d="function"===typeof c,e=function(a){O(a)},b=h("<div/>").addClass(a.oClasses.sPaging+b)[0],f=a.aanFeatures;
|
||||
d||c.fnInit(a,b,e);f.p||(b.id=a.sTableId+"_paginate",a.aoDrawCallback.push({fn:function(a){if(d){var b=a._iDisplayStart,i=a._iDisplayLength,h=a.fnRecordsDisplay(),l=-1===i,b=l?0:Math.ceil(b/i),i=l?1:Math.ceil(h/i),h=c(b,i),k,l=0;for(k=f.p.length;l<k;l++)Na(a,"pageButton")(a,f.p[l],l,h,b,i)}else c.fnUpdate(a,e)},sName:"pagination"}));return b}function Ta(a,b,c){var d=a._iDisplayStart,e=a._iDisplayLength,f=a.fnRecordsDisplay();0===f||-1===e?d=0:"number"===typeof b?(d=b*e,d>f&&(d=0)):"first"==b?d=0:
|
||||
"previous"==b?(d=0<=e?d-e:0,0>d&&(d=0)):"next"==b?d+e<f&&(d+=e):"last"==b?d=Math.floor((f-1)/e)*e:L(a,0,"Unknown paging action: "+b,5);b=a._iDisplayStart!==d;a._iDisplayStart=d;b&&(u(a,null,"page",[a]),c&&O(a));return b}function qb(a){return h("<div/>",{id:!a.aanFeatures.r?a.sTableId+"_processing":null,"class":a.oClasses.sProcessing}).html(a.oLanguage.sProcessing).insertBefore(a.nTable)[0]}function C(a,b){a.oFeatures.bProcessing&&h(a.aanFeatures.r).css("display",b?"block":"none");u(a,null,"processing",
|
||||
[a,b])}function rb(a){var b=h(a.nTable);b.attr("role","grid");var c=a.oScroll;if(""===c.sX&&""===c.sY)return a.nTable;var d=c.sX,e=c.sY,f=a.oClasses,g=b.children("caption"),j=g.length?g[0]._captionSide:null,i=h(b[0].cloneNode(!1)),n=h(b[0].cloneNode(!1)),l=b.children("tfoot");l.length||(l=null);i=h("<div/>",{"class":f.sScrollWrapper}).append(h("<div/>",{"class":f.sScrollHead}).css({overflow:"hidden",position:"relative",border:0,width:d?!d?null:x(d):"100%"}).append(h("<div/>",{"class":f.sScrollHeadInner}).css({"box-sizing":"content-box",
|
||||
width:c.sXInner||"100%"}).append(i.removeAttr("id").css("margin-left",0).append("top"===j?g:null).append(b.children("thead"))))).append(h("<div/>",{"class":f.sScrollBody}).css({position:"relative",overflow:"auto",width:!d?null:x(d)}).append(b));l&&i.append(h("<div/>",{"class":f.sScrollFoot}).css({overflow:"hidden",border:0,width:d?!d?null:x(d):"100%"}).append(h("<div/>",{"class":f.sScrollFootInner}).append(n.removeAttr("id").css("margin-left",0).append("bottom"===j?g:null).append(b.children("tfoot")))));
|
||||
var b=i.children(),k=b[0],f=b[1],t=l?b[2]:null;if(d)h(f).on("scroll.DT",function(){var a=this.scrollLeft;k.scrollLeft=a;l&&(t.scrollLeft=a)});h(f).css(e&&c.bCollapse?"max-height":"height",e);a.nScrollHead=k;a.nScrollBody=f;a.nScrollFoot=t;a.aoDrawCallback.push({fn:ka,sName:"scrolling"});return i[0]}function ka(a){var b=a.oScroll,c=b.sX,d=b.sXInner,e=b.sY,b=b.iBarWidth,f=h(a.nScrollHead),g=f[0].style,j=f.children("div"),i=j[0].style,n=j.children("table"),j=a.nScrollBody,l=h(j),q=j.style,t=h(a.nScrollFoot).children("div"),
|
||||
m=t.children("table"),o=h(a.nTHead),F=h(a.nTable),p=F[0],r=p.style,u=a.nTFoot?h(a.nTFoot):null,Eb=a.oBrowser,Ua=Eb.bScrollOversize,s=G(a.aoColumns,"nTh"),P,v,w,y,z=[],A=[],B=[],C=[],D,E=function(a){a=a.style;a.paddingTop="0";a.paddingBottom="0";a.borderTopWidth="0";a.borderBottomWidth="0";a.height=0};v=j.scrollHeight>j.clientHeight;if(a.scrollBarVis!==v&&a.scrollBarVis!==k)a.scrollBarVis=v,Y(a);else{a.scrollBarVis=v;F.children("thead, tfoot").remove();u&&(w=u.clone().prependTo(F),P=u.find("tr"),w=
|
||||
w.find("tr"));y=o.clone().prependTo(F);o=o.find("tr");v=y.find("tr");y.find("th, td").removeAttr("tabindex");c||(q.width="100%",f[0].style.width="100%");h.each(qa(a,y),function(b,c){D=Z(a,b);c.style.width=a.aoColumns[D].sWidth});u&&J(function(a){a.style.width=""},w);f=F.outerWidth();if(""===c){r.width="100%";if(Ua&&(F.find("tbody").height()>j.offsetHeight||"scroll"==l.css("overflow-y")))r.width=x(F.outerWidth()-b);f=F.outerWidth()}else""!==d&&(r.width=x(d),f=F.outerWidth());J(E,v);J(function(a){B.push(a.innerHTML);
|
||||
z.push(x(h(a).css("width")))},v);J(function(a,b){if(h.inArray(a,s)!==-1)a.style.width=z[b]},o);h(v).height(0);u&&(J(E,w),J(function(a){C.push(a.innerHTML);A.push(x(h(a).css("width")))},w),J(function(a,b){a.style.width=A[b]},P),h(w).height(0));J(function(a,b){a.innerHTML='<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+B[b]+"</div>";a.style.width=z[b]},v);u&&J(function(a,b){a.innerHTML='<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+C[b]+"</div>";a.style.width=
|
||||
A[b]},w);if(F.outerWidth()<f){P=j.scrollHeight>j.offsetHeight||"scroll"==l.css("overflow-y")?f+b:f;if(Ua&&(j.scrollHeight>j.offsetHeight||"scroll"==l.css("overflow-y")))r.width=x(P-b);(""===c||""!==d)&&L(a,1,"Possible column misalignment",6)}else P="100%";q.width=x(P);g.width=x(P);u&&(a.nScrollFoot.style.width=x(P));!e&&Ua&&(q.height=x(p.offsetHeight+b));c=F.outerWidth();n[0].style.width=x(c);i.width=x(c);d=F.height()>j.clientHeight||"scroll"==l.css("overflow-y");e="padding"+(Eb.bScrollbarLeft?"Left":
|
||||
"Right");i[e]=d?b+"px":"0px";u&&(m[0].style.width=x(c),t[0].style.width=x(c),t[0].style[e]=d?b+"px":"0px");F.children("colgroup").insertBefore(F.children("thead"));l.scroll();if((a.bSorted||a.bFiltered)&&!a._drawHold)j.scrollTop=0}}function J(a,b,c){for(var d=0,e=0,f=b.length,g,j;e<f;){g=b[e].firstChild;for(j=c?c[e].firstChild:null;g;)1===g.nodeType&&(c?a(g,j,d):a(g,d),d++),g=g.nextSibling,j=c?j.nextSibling:null;e++}}function Fa(a){var b=a.nTable,c=a.aoColumns,d=a.oScroll,e=d.sY,f=d.sX,g=d.sXInner,
|
||||
j=c.length,i=la(a,"bVisible"),n=h("th",a.nTHead),l=b.getAttribute("width"),k=b.parentNode,t=!1,m,o,p=a.oBrowser,d=p.bScrollOversize;(m=b.style.width)&&-1!==m.indexOf("%")&&(l=m);for(m=0;m<i.length;m++)o=c[i[m]],null!==o.sWidth&&(o.sWidth=Fb(o.sWidthOrig,k),t=!0);if(d||!t&&!f&&!e&&j==aa(a)&&j==n.length)for(m=0;m<j;m++)i=Z(a,m),null!==i&&(c[i].sWidth=x(n.eq(m).width()));else{j=h(b).clone().css("visibility","hidden").removeAttr("id");j.find("tbody tr").remove();var r=h("<tr/>").appendTo(j.find("tbody"));
|
||||
j.find("thead, tfoot").remove();j.append(h(a.nTHead).clone()).append(h(a.nTFoot).clone());j.find("tfoot th, tfoot td").css("width","");n=qa(a,j.find("thead")[0]);for(m=0;m<i.length;m++)o=c[i[m]],n[m].style.width=null!==o.sWidthOrig&&""!==o.sWidthOrig?x(o.sWidthOrig):"",o.sWidthOrig&&f&&h(n[m]).append(h("<div/>").css({width:o.sWidthOrig,margin:0,padding:0,border:0,height:1}));if(a.aoData.length)for(m=0;m<i.length;m++)t=i[m],o=c[t],h(Gb(a,t)).clone(!1).append(o.sContentPadding).appendTo(r);h("[name]",
|
||||
j).removeAttr("name");o=h("<div/>").css(f||e?{position:"absolute",top:0,left:0,height:1,right:0,overflow:"hidden"}:{}).append(j).appendTo(k);f&&g?j.width(g):f?(j.css("width","auto"),j.removeAttr("width"),j.width()<k.clientWidth&&l&&j.width(k.clientWidth)):e?j.width(k.clientWidth):l&&j.width(l);for(m=e=0;m<i.length;m++)k=h(n[m]),g=k.outerWidth()-k.width(),k=p.bBounding?Math.ceil(n[m].getBoundingClientRect().width):k.outerWidth(),e+=k,c[i[m]].sWidth=x(k-g);b.style.width=x(e);o.remove()}l&&(b.style.width=
|
||||
x(l));if((l||f)&&!a._reszEvt)b=function(){h(D).bind("resize.DT-"+a.sInstance,Oa(function(){Y(a)}))},d?setTimeout(b,1E3):b(),a._reszEvt=!0}function Fb(a,b){if(!a)return 0;var c=h("<div/>").css("width",x(a)).appendTo(b||I.body),d=c[0].offsetWidth;c.remove();return d}function Gb(a,b){var c=Hb(a,b);if(0>c)return null;var d=a.aoData[c];return!d.nTr?h("<td/>").html(B(a,c,b,"display"))[0]:d.anCells[b]}function Hb(a,b){for(var c,d=-1,e=-1,f=0,g=a.aoData.length;f<g;f++)c=B(a,f,b,"display")+"",c=c.replace($b,
|
||||
""),c=c.replace(/ /g," "),c.length>d&&(d=c.length,e=f);return e}function x(a){return null===a?"0px":"number"==typeof a?0>a?"0px":a+"px":a.match(/\d$/)?a+"px":a}function V(a){var b,c,d=[],e=a.aoColumns,f,g,j,i;b=a.aaSortingFixed;c=h.isPlainObject(b);var n=[];f=function(a){a.length&&!h.isArray(a[0])?n.push(a):h.merge(n,a)};h.isArray(b)&&f(b);c&&b.pre&&f(b.pre);f(a.aaSorting);c&&b.post&&f(b.post);for(a=0;a<n.length;a++){i=n[a][0];f=e[i].aDataSort;b=0;for(c=f.length;b<c;b++)g=f[b],j=e[g].sType||
|
||||
"string",n[a]._idx===k&&(n[a]._idx=h.inArray(n[a][1],e[g].asSorting)),d.push({src:i,col:g,dir:n[a][1],index:n[a]._idx,type:j,formatter:m.ext.type.order[j+"-pre"]})}return d}function mb(a){var b,c,d=[],e=m.ext.type.order,f=a.aoData,g=0,j,i=a.aiDisplayMaster,h;Ga(a);h=V(a);b=0;for(c=h.length;b<c;b++)j=h[b],j.formatter&&g++,Ib(a,j.col);if("ssp"!=y(a)&&0!==h.length){b=0;for(c=i.length;b<c;b++)d[i[b]]=b;g===h.length?i.sort(function(a,b){var c,e,g,j,i=h.length,k=f[a]._aSortData,m=f[b]._aSortData;for(g=
|
||||
0;g<i;g++)if(j=h[g],c=k[j.col],e=m[j.col],c=c<e?-1:c>e?1:0,0!==c)return"asc"===j.dir?c:-c;c=d[a];e=d[b];return c<e?-1:c>e?1:0}):i.sort(function(a,b){var c,g,j,i,k=h.length,m=f[a]._aSortData,p=f[b]._aSortData;for(j=0;j<k;j++)if(i=h[j],c=m[i.col],g=p[i.col],i=e[i.type+"-"+i.dir]||e["string-"+i.dir],c=i(c,g),0!==c)return c;c=d[a];g=d[b];return c<g?-1:c>g?1:0})}a.bSorted=!0}function Jb(a){for(var b,c,d=a.aoColumns,e=V(a),a=a.oLanguage.oAria,f=0,g=d.length;f<g;f++){c=d[f];var j=c.asSorting;b=c.sTitle.replace(/<.*?>/g,
|
||||
"");var i=c.nTh;i.removeAttribute("aria-sort");c.bSortable&&(0<e.length&&e[0].col==f?(i.setAttribute("aria-sort","asc"==e[0].dir?"ascending":"descending"),c=j[e[0].index+1]||j[0]):c=j[0],b+="asc"===c?a.sSortAscending:a.sSortDescending);i.setAttribute("aria-label",b)}}function Va(a,b,c,d){var e=a.aaSorting,f=a.aoColumns[b].asSorting,g=function(a,b){var c=a._idx;c===k&&(c=h.inArray(a[1],f));return c+1<f.length?c+1:b?null:0};"number"===typeof e[0]&&(e=a.aaSorting=[e]);c&&a.oFeatures.bSortMulti?(c=h.inArray(b,
|
||||
G(e,"0")),-1!==c?(b=g(e[c],!0),null===b&&1===e.length&&(b=0),null===b?e.splice(c,1):(e[c][1]=f[b],e[c]._idx=b)):(e.push([b,f[0],0]),e[e.length-1]._idx=0)):e.length&&e[0][0]==b?(b=g(e[0]),e.length=1,e[0][1]=f[b],e[0]._idx=b):(e.length=0,e.push([b,f[0]]),e[0]._idx=0);T(a);"function"==typeof d&&d(a)}function Ma(a,b,c,d){var e=a.aoColumns[c];Wa(b,{},function(b){!1!==e.bSortable&&(a.oFeatures.bProcessing?(C(a,!0),setTimeout(function(){Va(a,c,b.shiftKey,d);"ssp"!==y(a)&&C(a,!1)},0)):Va(a,c,b.shiftKey,d))})}
|
||||
function va(a){var b=a.aLastSort,c=a.oClasses.sSortColumn,d=V(a),e=a.oFeatures,f,g;if(e.bSort&&e.bSortClasses){e=0;for(f=b.length;e<f;e++)g=b[e].src,h(G(a.aoData,"anCells",g)).removeClass(c+(2>e?e+1:3));e=0;for(f=d.length;e<f;e++)g=d[e].src,h(G(a.aoData,"anCells",g)).addClass(c+(2>e?e+1:3))}a.aLastSort=d}function Ib(a,b){var c=a.aoColumns[b],d=m.ext.order[c.sSortDataType],e;d&&(e=d.call(a.oInstance,a,b,$(a,b)));for(var f,g=m.ext.type.order[c.sType+"-pre"],j=0,i=a.aoData.length;j<i;j++)if(c=a.aoData[j],
|
||||
c._aSortData||(c._aSortData=[]),!c._aSortData[b]||d)f=d?e[j]:B(a,j,b,"sort"),c._aSortData[b]=g?g(f):f}function wa(a){if(a.oFeatures.bStateSave&&!a.bDestroying){var b={time:+new Date,start:a._iDisplayStart,length:a._iDisplayLength,order:h.extend(!0,[],a.aaSorting),search:Ab(a.oPreviousSearch),columns:h.map(a.aoColumns,function(b,d){return{visible:b.bVisible,search:Ab(a.aoPreSearchCols[d])}})};u(a,"aoStateSaveParams","stateSaveParams",[a,b]);a.oSavedState=b;a.fnStateSaveCallback.call(a.oInstance,a,
|
||||
b)}}function Kb(a){var b,c,d=a.aoColumns;if(a.oFeatures.bStateSave){var e=a.fnStateLoadCallback.call(a.oInstance,a);if(e&&e.time&&(b=u(a,"aoStateLoadParams","stateLoadParams",[a,e]),-1===h.inArray(!1,b)&&(b=a.iStateDuration,!(0<b&&e.time<+new Date-1E3*b)&&d.length===e.columns.length))){a.oLoadedState=h.extend(!0,{},e);e.start!==k&&(a._iDisplayStart=e.start,a.iInitDisplayStart=e.start);e.length!==k&&(a._iDisplayLength=e.length);e.order!==k&&(a.aaSorting=[],h.each(e.order,function(b,c){a.aaSorting.push(c[0]>=
|
||||
d.length?[0,c[1]]:c)}));e.search!==k&&h.extend(a.oPreviousSearch,Bb(e.search));b=0;for(c=e.columns.length;b<c;b++){var f=e.columns[b];f.visible!==k&&(d[b].bVisible=f.visible);f.search!==k&&h.extend(a.aoPreSearchCols[b],Bb(f.search))}u(a,"aoStateLoaded","stateLoaded",[a,e])}}}function xa(a){var b=m.settings,a=h.inArray(a,G(b,"nTable"));return-1!==a?b[a]:null}function L(a,b,c,d){c="DataTables warning: "+(a?"table id="+a.sTableId+" - ":"")+c;d&&(c+=". For more information about this error, please see http://datatables.net/tn/"+
|
||||
d);if(b)D.console&&console.log&&console.log(c);else if(b=m.ext,b=b.sErrMode||b.errMode,a&&u(a,null,"error",[a,d,c]),"alert"==b)alert(c);else{if("throw"==b)throw Error(c);"function"==typeof b&&b(a,d,c)}}function E(a,b,c,d){h.isArray(c)?h.each(c,function(c,d){h.isArray(d)?E(a,b,d[0],d[1]):E(a,b,d)}):(d===k&&(d=c),b[c]!==k&&(a[d]=b[c]))}function Lb(a,b,c){var d,e;for(e in b)b.hasOwnProperty(e)&&(d=b[e],h.isPlainObject(d)?(h.isPlainObject(a[e])||(a[e]={}),h.extend(!0,a[e],d)):a[e]=c&&"data"!==e&&"aaData"!==
|
||||
e&&h.isArray(d)?d.slice():d);return a}function Wa(a,b,c){h(a).bind("click.DT",b,function(b){a.blur();c(b)}).bind("keypress.DT",b,function(a){13===a.which&&(a.preventDefault(),c(a))}).bind("selectstart.DT",function(){return!1})}function z(a,b,c,d){c&&a[b].push({fn:c,sName:d})}function u(a,b,c,d){var e=[];b&&(e=h.map(a[b].slice().reverse(),function(b){return b.fn.apply(a.oInstance,d)}));null!==c&&(b=h.Event(c+".dt"),h(a.nTable).trigger(b,d),e.push(b.result));return e}function Sa(a){var b=a._iDisplayStart,
|
||||
c=a.fnDisplayEnd(),d=a._iDisplayLength;b>=c&&(b=c-d);b-=b%d;if(-1===d||0>b)b=0;a._iDisplayStart=b}function Na(a,b){var c=a.renderer,d=m.ext.renderer[b];return h.isPlainObject(c)&&c[b]?d[c[b]]||d._:"string"===typeof c?d[c]||d._:d._}function y(a){return a.oFeatures.bServerSide?"ssp":a.ajax||a.sAjaxSource?"ajax":"dom"}function ya(a,b){var c=[],c=Mb.numbers_length,d=Math.floor(c/2);b<=c?c=W(0,b):a<=d?(c=W(0,c-2),c.push("ellipsis"),c.push(b-1)):(a>=b-1-d?c=W(b-(c-2),b):(c=W(a-d+2,a+d-1),c.push("ellipsis"),
|
||||
c.push(b-1)),c.splice(0,0,"ellipsis"),c.splice(0,0,0));c.DT_el="span";return c}function db(a){h.each({num:function(b){return za(b,a)},"num-fmt":function(b){return za(b,a,Xa)},"html-num":function(b){return za(b,a,Aa)},"html-num-fmt":function(b){return za(b,a,Aa,Xa)}},function(b,c){v.type.order[b+a+"-pre"]=c;b.match(/^html\-/)&&(v.type.search[b+a]=v.type.search.html)})}function Nb(a){return function(){var b=[xa(this[m.ext.iApiIndex])].concat(Array.prototype.slice.call(arguments));return m.ext.internal[a].apply(this,
|
||||
b)}}var m=function(a){this.$=function(a,b){return this.api(!0).$(a,b)};this._=function(a,b){return this.api(!0).rows(a,b).data()};this.api=function(a){return a?new r(xa(this[v.iApiIndex])):new r(this)};this.fnAddData=function(a,b){var c=this.api(!0),d=h.isArray(a)&&(h.isArray(a[0])||h.isPlainObject(a[0]))?c.rows.add(a):c.row.add(a);(b===k||b)&&c.draw();return d.flatten().toArray()};this.fnAdjustColumnSizing=function(a){var b=this.api(!0).columns.adjust(),c=b.settings()[0],d=c.oScroll;a===k||a?b.draw(!1):
|
||||
(""!==d.sX||""!==d.sY)&&ka(c)};this.fnClearTable=function(a){var b=this.api(!0).clear();(a===k||a)&&b.draw()};this.fnClose=function(a){this.api(!0).row(a).child.hide()};this.fnDeleteRow=function(a,b,c){var d=this.api(!0),a=d.rows(a),e=a.settings()[0],h=e.aoData[a[0][0]];a.remove();b&&b.call(this,e,h);(c===k||c)&&d.draw();return h};this.fnDestroy=function(a){this.api(!0).destroy(a)};this.fnDraw=function(a){this.api(!0).draw(a)};this.fnFilter=function(a,b,c,d,e,h){e=this.api(!0);null===b||b===k?e.search(a,
|
||||
c,d,h):e.column(b).search(a,c,d,h);e.draw()};this.fnGetData=function(a,b){var c=this.api(!0);if(a!==k){var d=a.nodeName?a.nodeName.toLowerCase():"";return b!==k||"td"==d||"th"==d?c.cell(a,b).data():c.row(a).data()||null}return c.data().toArray()};this.fnGetNodes=function(a){var b=this.api(!0);return a!==k?b.row(a).node():b.rows().nodes().flatten().toArray()};this.fnGetPosition=function(a){var b=this.api(!0),c=a.nodeName.toUpperCase();return"TR"==c?b.row(a).index():"TD"==c||"TH"==c?(a=b.cell(a).index(),
|
||||
[a.row,a.columnVisible,a.column]):null};this.fnIsOpen=function(a){return this.api(!0).row(a).child.isShown()};this.fnOpen=function(a,b,c){return this.api(!0).row(a).child(b,c).show().child()[0]};this.fnPageChange=function(a,b){var c=this.api(!0).page(a);(b===k||b)&&c.draw(!1)};this.fnSetColumnVis=function(a,b,c){a=this.api(!0).column(a).visible(b);(c===k||c)&&a.columns.adjust().draw()};this.fnSettings=function(){return xa(this[v.iApiIndex])};this.fnSort=function(a){this.api(!0).order(a).draw()};this.fnSortListener=
|
||||
function(a,b,c){this.api(!0).order.listener(a,b,c)};this.fnUpdate=function(a,b,c,d,e){var h=this.api(!0);c===k||null===c?h.row(b).data(a):h.cell(b,c).data(a);(e===k||e)&&h.columns.adjust();(d===k||d)&&h.draw();return 0};this.fnVersionCheck=v.fnVersionCheck;var b=this,c=a===k,d=this.length;c&&(a={});this.oApi=this.internal=v.internal;for(var e in m.ext.internal)e&&(this[e]=Nb(e));this.each(function(){var e={},e=1<d?Lb(e,a,!0):a,g=0,j,i=this.getAttribute("id"),n=!1,l=m.defaults,q=h(this);if("table"!=
|
||||
this.nodeName.toLowerCase())L(null,0,"Non-table node initialisation ("+this.nodeName+")",2);else{eb(l);fb(l.column);K(l,l,!0);K(l.column,l.column,!0);K(l,h.extend(e,q.data()));var t=m.settings,g=0;for(j=t.length;g<j;g++){var p=t[g];if(p.nTable==this||p.nTHead.parentNode==this||p.nTFoot&&p.nTFoot.parentNode==this){g=e.bRetrieve!==k?e.bRetrieve:l.bRetrieve;if(c||g)return p.oInstance;if(e.bDestroy!==k?e.bDestroy:l.bDestroy){p.oInstance.fnDestroy();break}else{L(p,0,"Cannot reinitialise DataTable",3);
|
||||
return}}if(p.sTableId==this.id){t.splice(g,1);break}}if(null===i||""===i)this.id=i="DataTables_Table_"+m.ext._unique++;var o=h.extend(!0,{},m.models.oSettings,{sDestroyWidth:q[0].style.width,sInstance:i,sTableId:i});o.nTable=this;o.oApi=b.internal;o.oInit=e;t.push(o);o.oInstance=1===b.length?b:q.dataTable();eb(e);e.oLanguage&&Da(e.oLanguage);e.aLengthMenu&&!e.iDisplayLength&&(e.iDisplayLength=h.isArray(e.aLengthMenu[0])?e.aLengthMenu[0][0]:e.aLengthMenu[0]);e=Lb(h.extend(!0,{},l),e);E(o.oFeatures,
|
||||
e,"bPaginate bLengthChange bFilter bSort bSortMulti bInfo bProcessing bAutoWidth bSortClasses bServerSide bDeferRender".split(" "));E(o,e,["asStripeClasses","ajax","fnServerData","fnFormatNumber","sServerMethod","aaSorting","aaSortingFixed","aLengthMenu","sPaginationType","sAjaxSource","sAjaxDataProp","iStateDuration","sDom","bSortCellsTop","iTabIndex","fnStateLoadCallback","fnStateSaveCallback","renderer","searchDelay","rowId",["iCookieDuration","iStateDuration"],["oSearch","oPreviousSearch"],["aoSearchCols",
|
||||
"aoPreSearchCols"],["iDisplayLength","_iDisplayLength"],["bJQueryUI","bJUI"]]);E(o.oScroll,e,[["sScrollX","sX"],["sScrollXInner","sXInner"],["sScrollY","sY"],["bScrollCollapse","bCollapse"]]);E(o.oLanguage,e,"fnInfoCallback");z(o,"aoDrawCallback",e.fnDrawCallback,"user");z(o,"aoServerParams",e.fnServerParams,"user");z(o,"aoStateSaveParams",e.fnStateSaveParams,"user");z(o,"aoStateLoadParams",e.fnStateLoadParams,"user");z(o,"aoStateLoaded",e.fnStateLoaded,"user");z(o,"aoRowCallback",e.fnRowCallback,
|
||||
"user");z(o,"aoRowCreatedCallback",e.fnCreatedRow,"user");z(o,"aoHeaderCallback",e.fnHeaderCallback,"user");z(o,"aoFooterCallback",e.fnFooterCallback,"user");z(o,"aoInitComplete",e.fnInitComplete,"user");z(o,"aoPreDrawCallback",e.fnPreDrawCallback,"user");o.rowIdFn=Q(e.rowId);gb(o);i=o.oClasses;e.bJQueryUI?(h.extend(i,m.ext.oJUIClasses,e.oClasses),e.sDom===l.sDom&&"lfrtip"===l.sDom&&(o.sDom='<"H"lfr>t<"F"ip>'),o.renderer)?h.isPlainObject(o.renderer)&&!o.renderer.header&&(o.renderer.header="jqueryui"):
|
||||
o.renderer="jqueryui":h.extend(i,m.ext.classes,e.oClasses);q.addClass(i.sTable);o.iInitDisplayStart===k&&(o.iInitDisplayStart=e.iDisplayStart,o._iDisplayStart=e.iDisplayStart);null!==e.iDeferLoading&&(o.bDeferLoading=!0,g=h.isArray(e.iDeferLoading),o._iRecordsDisplay=g?e.iDeferLoading[0]:e.iDeferLoading,o._iRecordsTotal=g?e.iDeferLoading[1]:e.iDeferLoading);var r=o.oLanguage;h.extend(!0,r,e.oLanguage);""!==r.sUrl&&(h.ajax({dataType:"json",url:r.sUrl,success:function(a){Da(a);K(l.oLanguage,a);h.extend(true,
|
||||
r,a);ga(o)},error:function(){ga(o)}}),n=!0);null===e.asStripeClasses&&(o.asStripeClasses=[i.sStripeOdd,i.sStripeEven]);var g=o.asStripeClasses,v=q.children("tbody").find("tr").eq(0);-1!==h.inArray(!0,h.map(g,function(a){return v.hasClass(a)}))&&(h("tbody tr",this).removeClass(g.join(" ")),o.asDestroyStripes=g.slice());t=[];g=this.getElementsByTagName("thead");0!==g.length&&(da(o.aoHeader,g[0]),t=qa(o));if(null===e.aoColumns){p=[];g=0;for(j=t.length;g<j;g++)p.push(null)}else p=e.aoColumns;g=0;for(j=
|
||||
p.length;g<j;g++)Ea(o,t?t[g]:null);ib(o,e.aoColumnDefs,p,function(a,b){ja(o,a,b)});if(v.length){var s=function(a,b){return a.getAttribute("data-"+b)!==null?b:null};h(v[0]).children("th, td").each(function(a,b){var c=o.aoColumns[a];if(c.mData===a){var d=s(b,"sort")||s(b,"order"),e=s(b,"filter")||s(b,"search");if(d!==null||e!==null){c.mData={_:a+".display",sort:d!==null?a+".@data-"+d:k,type:d!==null?a+".@data-"+d:k,filter:e!==null?a+".@data-"+e:k};ja(o,a)}}})}var w=o.oFeatures;e.bStateSave&&(w.bStateSave=
|
||||
!0,Kb(o,e),z(o,"aoDrawCallback",wa,"state_save"));if(e.aaSorting===k){t=o.aaSorting;g=0;for(j=t.length;g<j;g++)t[g][1]=o.aoColumns[g].asSorting[0]}va(o);w.bSort&&z(o,"aoDrawCallback",function(){if(o.bSorted){var a=V(o),b={};h.each(a,function(a,c){b[c.src]=c.dir});u(o,null,"order",[o,a,b]);Jb(o)}});z(o,"aoDrawCallback",function(){(o.bSorted||y(o)==="ssp"||w.bDeferRender)&&va(o)},"sc");g=q.children("caption").each(function(){this._captionSide=q.css("caption-side")});j=q.children("thead");0===j.length&&
|
||||
(j=h("<thead/>").appendTo(this));o.nTHead=j[0];j=q.children("tbody");0===j.length&&(j=h("<tbody/>").appendTo(this));o.nTBody=j[0];j=q.children("tfoot");if(0===j.length&&0<g.length&&(""!==o.oScroll.sX||""!==o.oScroll.sY))j=h("<tfoot/>").appendTo(this);0===j.length||0===j.children().length?q.addClass(i.sNoFooter):0<j.length&&(o.nTFoot=j[0],da(o.aoFooter,o.nTFoot));if(e.aaData)for(g=0;g<e.aaData.length;g++)N(o,e.aaData[g]);else(o.bDeferLoading||"dom"==y(o))&&ma(o,h(o.nTBody).children("tr"));o.aiDisplay=
|
||||
o.aiDisplayMaster.slice();o.bInitialised=!0;!1===n&&ga(o)}});b=null;return this},v,r,p,s,Ya={},Ob=/[\r\n]/g,Aa=/<.*?>/g,ac=/^[\w\+\-]/,bc=/[\w\+\-]$/,cc=RegExp("(\\/|\\.|\\*|\\+|\\?|\\||\\(|\\)|\\[|\\]|\\{|\\}|\\\\|\\$|\\^|\\-)","g"),Xa=/[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi,M=function(a){return!a||!0===a||"-"===a?!0:!1},Pb=function(a){var b=parseInt(a,10);return!isNaN(b)&&isFinite(a)?b:null},Qb=function(a,b){Ya[b]||(Ya[b]=RegExp(Qa(b),"g"));return"string"===typeof a&&"."!==b?a.replace(/\./g,
|
||||
"").replace(Ya[b],"."):a},Za=function(a,b,c){var d="string"===typeof a;if(M(a))return!0;b&&d&&(a=Qb(a,b));c&&d&&(a=a.replace(Xa,""));return!isNaN(parseFloat(a))&&isFinite(a)},Rb=function(a,b,c){return M(a)?!0:!(M(a)||"string"===typeof a)?null:Za(a.replace(Aa,""),b,c)?!0:null},G=function(a,b,c){var d=[],e=0,f=a.length;if(c!==k)for(;e<f;e++)a[e]&&a[e][b]&&d.push(a[e][b][c]);else for(;e<f;e++)a[e]&&d.push(a[e][b]);return d},ha=function(a,b,c,d){var e=[],f=0,g=b.length;if(d!==k)for(;f<g;f++)a[b[f]][c]&&
|
||||
e.push(a[b[f]][c][d]);else for(;f<g;f++)e.push(a[b[f]][c]);return e},W=function(a,b){var c=[],d;b===k?(b=0,d=a):(d=b,b=a);for(var e=b;e<d;e++)c.push(e);return c},Sb=function(a){for(var b=[],c=0,d=a.length;c<d;c++)a[c]&&b.push(a[c]);return b},pa=function(a){var b=[],c,d,e=a.length,f,g=0;d=0;a:for(;d<e;d++){c=a[d];for(f=0;f<g;f++)if(b[f]===c)continue a;b.push(c);g++}return b};m.util={throttle:function(a,b){var c=b!==k?b:200,d,e;return function(){var b=this,g=+new Date,h=arguments;d&&g<d+c?(clearTimeout(e),
|
||||
e=setTimeout(function(){d=k;a.apply(b,h)},c)):(d=g,a.apply(b,h))}},escapeRegex:function(a){return a.replace(cc,"\\$1")}};var A=function(a,b,c){a[b]!==k&&(a[c]=a[b])},ba=/\[.*?\]$/,U=/\(\)$/,Qa=m.util.escapeRegex,ua=h("<div>")[0],Zb=ua.textContent!==k,$b=/<.*?>/g,Oa=m.util.throttle,Tb=[],w=Array.prototype,dc=function(a){var b,c,d=m.settings,e=h.map(d,function(a){return a.nTable});if(a){if(a.nTable&&a.oApi)return[a];if(a.nodeName&&"table"===a.nodeName.toLowerCase())return b=h.inArray(a,e),-1!==b?[d[b]]:
|
||||
null;if(a&&"function"===typeof a.settings)return a.settings().toArray();"string"===typeof a?c=h(a):a instanceof h&&(c=a)}else return[];if(c)return c.map(function(){b=h.inArray(this,e);return-1!==b?d[b]:null}).toArray()};r=function(a,b){if(!(this instanceof r))return new r(a,b);var c=[],d=function(a){(a=dc(a))&&(c=c.concat(a))};if(h.isArray(a))for(var e=0,f=a.length;e<f;e++)d(a[e]);else d(a);this.context=pa(c);b&&h.merge(this,b);this.selector={rows:null,cols:null,opts:null};r.extend(this,this,Tb)};
|
||||
m.Api=r;h.extend(r.prototype,{any:function(){return 0!==this.count()},concat:w.concat,context:[],count:function(){return this.flatten().length},each:function(a){for(var b=0,c=this.length;b<c;b++)a.call(this,this[b],b,this);return this},eq:function(a){var b=this.context;return b.length>a?new r(b[a],this[a]):null},filter:function(a){var b=[];if(w.filter)b=w.filter.call(this,a,this);else for(var c=0,d=this.length;c<d;c++)a.call(this,this[c],c,this)&&b.push(this[c]);return new r(this.context,b)},flatten:function(){var a=
|
||||
[];return new r(this.context,a.concat.apply(a,this.toArray()))},join:w.join,indexOf:w.indexOf||function(a,b){for(var c=b||0,d=this.length;c<d;c++)if(this[c]===a)return c;return-1},iterator:function(a,b,c,d){var e=[],f,g,h,i,n,l=this.context,m,t,p=this.selector;"string"===typeof a&&(d=c,c=b,b=a,a=!1);g=0;for(h=l.length;g<h;g++){var o=new r(l[g]);if("table"===b)f=c.call(o,l[g],g),f!==k&&e.push(f);else if("columns"===b||"rows"===b)f=c.call(o,l[g],this[g],g),f!==k&&e.push(f);else if("column"===b||"column-rows"===
|
||||
b||"row"===b||"cell"===b){t=this[g];"column-rows"===b&&(m=Ba(l[g],p.opts));i=0;for(n=t.length;i<n;i++)f=t[i],f="cell"===b?c.call(o,l[g],f.row,f.column,g,i):c.call(o,l[g],f,g,i,m),f!==k&&e.push(f)}}return e.length||d?(a=new r(l,a?e.concat.apply([],e):e),b=a.selector,b.rows=p.rows,b.cols=p.cols,b.opts=p.opts,a):this},lastIndexOf:w.lastIndexOf||function(a,b){return this.indexOf.apply(this.toArray.reverse(),arguments)},length:0,map:function(a){var b=[];if(w.map)b=w.map.call(this,a,this);else for(var c=
|
||||
0,d=this.length;c<d;c++)b.push(a.call(this,this[c],c));return new r(this.context,b)},pluck:function(a){return this.map(function(b){return b[a]})},pop:w.pop,push:w.push,reduce:w.reduce||function(a,b){return hb(this,a,b,0,this.length,1)},reduceRight:w.reduceRight||function(a,b){return hb(this,a,b,this.length-1,-1,-1)},reverse:w.reverse,selector:null,shift:w.shift,sort:w.sort,splice:w.splice,toArray:function(){return w.slice.call(this)},to$:function(){return h(this)},toJQuery:function(){return h(this)},
|
||||
unique:function(){return new r(this.context,pa(this))},unshift:w.unshift});r.extend=function(a,b,c){if(c.length&&b&&(b instanceof r||b.__dt_wrapper)){var d,e,f,g=function(a,b,c){return function(){var d=b.apply(a,arguments);r.extend(d,d,c.methodExt);return d}};d=0;for(e=c.length;d<e;d++)f=c[d],b[f.name]="function"===typeof f.val?g(a,f.val,f):h.isPlainObject(f.val)?{}:f.val,b[f.name].__dt_wrapper=!0,r.extend(a,b[f.name],f.propExt)}};r.register=p=function(a,b){if(h.isArray(a))for(var c=0,d=a.length;c<
|
||||
d;c++)r.register(a[c],b);else for(var e=a.split("."),f=Tb,g,j,c=0,d=e.length;c<d;c++){g=(j=-1!==e[c].indexOf("()"))?e[c].replace("()",""):e[c];var i;a:{i=0;for(var n=f.length;i<n;i++)if(f[i].name===g){i=f[i];break a}i=null}i||(i={name:g,val:{},methodExt:[],propExt:[]},f.push(i));c===d-1?i.val=b:f=j?i.methodExt:i.propExt}};r.registerPlural=s=function(a,b,c){r.register(a,c);r.register(b,function(){var a=c.apply(this,arguments);return a===this?this:a instanceof r?a.length?h.isArray(a[0])?new r(a.context,
|
||||
a[0]):a[0]:k:a})};p("tables()",function(a){var b;if(a){b=r;var c=this.context;if("number"===typeof a)a=[c[a]];else var d=h.map(c,function(a){return a.nTable}),a=h(d).filter(a).map(function(){var a=h.inArray(this,d);return c[a]}).toArray();b=new b(a)}else b=this;return b});p("table()",function(a){var a=this.tables(a),b=a.context;return b.length?new r(b[0]):a});s("tables().nodes()","table().node()",function(){return this.iterator("table",function(a){return a.nTable},1)});s("tables().body()","table().body()",
|
||||
function(){return this.iterator("table",function(a){return a.nTBody},1)});s("tables().header()","table().header()",function(){return this.iterator("table",function(a){return a.nTHead},1)});s("tables().footer()","table().footer()",function(){return this.iterator("table",function(a){return a.nTFoot},1)});s("tables().containers()","table().container()",function(){return this.iterator("table",function(a){return a.nTableWrapper},1)});p("draw()",function(a){return this.iterator("table",function(b){"page"===
|
||||
a?O(b):("string"===typeof a&&(a="full-hold"===a?!1:!0),T(b,!1===a))})});p("page()",function(a){return a===k?this.page.info().page:this.iterator("table",function(b){Ta(b,a)})});p("page.info()",function(){if(0===this.context.length)return k;var a=this.context[0],b=a._iDisplayStart,c=a.oFeatures.bPaginate?a._iDisplayLength:-1,d=a.fnRecordsDisplay(),e=-1===c;return{page:e?0:Math.floor(b/c),pages:e?1:Math.ceil(d/c),start:b,end:a.fnDisplayEnd(),length:c,recordsTotal:a.fnRecordsTotal(),recordsDisplay:d,
|
||||
serverSide:"ssp"===y(a)}});p("page.len()",function(a){return a===k?0!==this.context.length?this.context[0]._iDisplayLength:k:this.iterator("table",function(b){Ra(b,a)})});var Ub=function(a,b,c){if(c){var d=new r(a);d.one("draw",function(){c(d.ajax.json())})}if("ssp"==y(a))T(a,b);else{C(a,!0);var e=a.jqXHR;e&&4!==e.readyState&&e.abort();ra(a,[],function(c){na(a);for(var c=sa(a,c),d=0,e=c.length;d<e;d++)N(a,c[d]);T(a,b);C(a,!1)})}};p("ajax.json()",function(){var a=this.context;if(0<a.length)return a[0].json});
|
||||
p("ajax.params()",function(){var a=this.context;if(0<a.length)return a[0].oAjaxData});p("ajax.reload()",function(a,b){return this.iterator("table",function(c){Ub(c,!1===b,a)})});p("ajax.url()",function(a){var b=this.context;if(a===k){if(0===b.length)return k;b=b[0];return b.ajax?h.isPlainObject(b.ajax)?b.ajax.url:b.ajax:b.sAjaxSource}return this.iterator("table",function(b){h.isPlainObject(b.ajax)?b.ajax.url=a:b.ajax=a})});p("ajax.url().load()",function(a,b){return this.iterator("table",function(c){Ub(c,
|
||||
!1===b,a)})});var $a=function(a,b,c,d,e){var f=[],g,j,i,n,l,m;i=typeof b;if(!b||"string"===i||"function"===i||b.length===k)b=[b];i=0;for(n=b.length;i<n;i++){j=b[i]&&b[i].split?b[i].split(","):[b[i]];l=0;for(m=j.length;l<m;l++)(g=c("string"===typeof j[l]?h.trim(j[l]):j[l]))&&g.length&&(f=f.concat(g))}a=v.selector[a];if(a.length){i=0;for(n=a.length;i<n;i++)f=a[i](d,e,f)}return pa(f)},ab=function(a){a||(a={});a.filter&&a.search===k&&(a.search=a.filter);return h.extend({search:"none",order:"current",
|
||||
page:"all"},a)},bb=function(a){for(var b=0,c=a.length;b<c;b++)if(0<a[b].length)return a[0]=a[b],a[0].length=1,a.length=1,a.context=[a.context[b]],a;a.length=0;return a},Ba=function(a,b){var c,d,e,f=[],g=a.aiDisplay;c=a.aiDisplayMaster;var j=b.search;d=b.order;e=b.page;if("ssp"==y(a))return"removed"===j?[]:W(0,c.length);if("current"==e){c=a._iDisplayStart;for(d=a.fnDisplayEnd();c<d;c++)f.push(g[c])}else if("current"==d||"applied"==d)f="none"==j?c.slice():"applied"==j?g.slice():h.map(c,function(a){return-1===
|
||||
h.inArray(a,g)?a:null});else if("index"==d||"original"==d){c=0;for(d=a.aoData.length;c<d;c++)"none"==j?f.push(c):(e=h.inArray(c,g),(-1===e&&"removed"==j||0<=e&&"applied"==j)&&f.push(c))}return f};p("rows()",function(a,b){a===k?a="":h.isPlainObject(a)&&(b=a,a="");var b=ab(b),c=this.iterator("table",function(c){var e=b;return $a("row",a,function(a){var b=Pb(a);if(b!==null&&!e)return[b];var j=Ba(c,e);if(b!==null&&h.inArray(b,j)!==-1)return[b];if(!a)return j;if(typeof a==="function")return h.map(j,function(b){var e=
|
||||
c.aoData[b];return a(b,e._aData,e.nTr)?b:null});b=Sb(ha(c.aoData,j,"nTr"));if(a.nodeName){if(a._DT_RowIndex!==k)return[a._DT_RowIndex];if(a._DT_CellIndex)return[a._DT_CellIndex.row];b=h(a).closest("*[data-dt-row]");return b.length?[b.data("dt-row")]:[]}if(typeof a==="string"&&a.charAt(0)==="#"){j=c.aIds[a.replace(/^#/,"")];if(j!==k)return[j.idx]}return h(b).filter(a).map(function(){return this._DT_RowIndex}).toArray()},c,e)},1);c.selector.rows=a;c.selector.opts=b;return c});p("rows().nodes()",function(){return this.iterator("row",
|
||||
function(a,b){return a.aoData[b].nTr||k},1)});p("rows().data()",function(){return this.iterator(!0,"rows",function(a,b){return ha(a.aoData,b,"_aData")},1)});s("rows().cache()","row().cache()",function(a){return this.iterator("row",function(b,c){var d=b.aoData[c];return"search"===a?d._aFilterData:d._aSortData},1)});s("rows().invalidate()","row().invalidate()",function(a){return this.iterator("row",function(b,c){ca(b,c,a)})});s("rows().indexes()","row().index()",function(){return this.iterator("row",
|
||||
function(a,b){return b},1)});s("rows().ids()","row().id()",function(a){for(var b=[],c=this.context,d=0,e=c.length;d<e;d++)for(var f=0,g=this[d].length;f<g;f++){var h=c[d].rowIdFn(c[d].aoData[this[d][f]]._aData);b.push((!0===a?"#":"")+h)}return new r(c,b)});s("rows().remove()","row().remove()",function(){var a=this;this.iterator("row",function(b,c,d){var e=b.aoData,f=e[c],g,h,i,n,l;e.splice(c,1);g=0;for(h=e.length;g<h;g++)if(i=e[g],l=i.anCells,null!==i.nTr&&(i.nTr._DT_RowIndex=g),null!==l){i=0;for(n=
|
||||
l.length;i<n;i++)l[i]._DT_CellIndex.row=g}oa(b.aiDisplayMaster,c);oa(b.aiDisplay,c);oa(a[d],c,!1);Sa(b);c=b.rowIdFn(f._aData);c!==k&&delete b.aIds[c]});this.iterator("table",function(a){for(var c=0,d=a.aoData.length;c<d;c++)a.aoData[c].idx=c});return this});p("rows.add()",function(a){var b=this.iterator("table",function(b){var c,f,g,h=[];f=0;for(g=a.length;f<g;f++)c=a[f],c.nodeName&&"TR"===c.nodeName.toUpperCase()?h.push(ma(b,c)[0]):h.push(N(b,c));return h},1),c=this.rows(-1);c.pop();h.merge(c,b);
|
||||
return c});p("row()",function(a,b){return bb(this.rows(a,b))});p("row().data()",function(a){var b=this.context;if(a===k)return b.length&&this.length?b[0].aoData[this[0]]._aData:k;b[0].aoData[this[0]]._aData=a;ca(b[0],this[0],"data");return this});p("row().node()",function(){var a=this.context;return a.length&&this.length?a[0].aoData[this[0]].nTr||null:null});p("row.add()",function(a){a instanceof h&&a.length&&(a=a[0]);var b=this.iterator("table",function(b){return a.nodeName&&"TR"===a.nodeName.toUpperCase()?
|
||||
ma(b,a)[0]:N(b,a)});return this.row(b[0])});var cb=function(a,b){var c=a.context;if(c.length&&(c=c[0].aoData[b!==k?b:a[0]])&&c._details)c._details.remove(),c._detailsShow=k,c._details=k},Vb=function(a,b){var c=a.context;if(c.length&&a.length){var d=c[0].aoData[a[0]];if(d._details){(d._detailsShow=b)?d._details.insertAfter(d.nTr):d._details.detach();var e=c[0],f=new r(e),g=e.aoData;f.off("draw.dt.DT_details column-visibility.dt.DT_details destroy.dt.DT_details");0<G(g,"_details").length&&(f.on("draw.dt.DT_details",
|
||||
function(a,b){e===b&&f.rows({page:"current"}).eq(0).each(function(a){a=g[a];a._detailsShow&&a._details.insertAfter(a.nTr)})}),f.on("column-visibility.dt.DT_details",function(a,b){if(e===b)for(var c,d=aa(b),f=0,h=g.length;f<h;f++)c=g[f],c._details&&c._details.children("td[colspan]").attr("colspan",d)}),f.on("destroy.dt.DT_details",function(a,b){if(e===b)for(var c=0,d=g.length;c<d;c++)g[c]._details&&cb(f,c)}))}}};p("row().child()",function(a,b){var c=this.context;if(a===k)return c.length&&this.length?
|
||||
c[0].aoData[this[0]]._details:k;if(!0===a)this.child.show();else if(!1===a)cb(this);else if(c.length&&this.length){var d=c[0],c=c[0].aoData[this[0]],e=[],f=function(a,b){if(h.isArray(a)||a instanceof h)for(var c=0,k=a.length;c<k;c++)f(a[c],b);else a.nodeName&&"tr"===a.nodeName.toLowerCase()?e.push(a):(c=h("<tr><td/></tr>").addClass(b),h("td",c).addClass(b).html(a)[0].colSpan=aa(d),e.push(c[0]))};f(a,b);c._details&&c._details.remove();c._details=h(e);c._detailsShow&&c._details.insertAfter(c.nTr)}return this});
|
||||
p(["row().child.show()","row().child().show()"],function(){Vb(this,!0);return this});p(["row().child.hide()","row().child().hide()"],function(){Vb(this,!1);return this});p(["row().child.remove()","row().child().remove()"],function(){cb(this);return this});p("row().child.isShown()",function(){var a=this.context;return a.length&&this.length?a[0].aoData[this[0]]._detailsShow||!1:!1});var ec=/^(.+):(name|visIdx|visible)$/,Wb=function(a,b,c,d,e){for(var c=[],d=0,f=e.length;d<f;d++)c.push(B(a,e[d],b));
|
||||
return c};p("columns()",function(a,b){a===k?a="":h.isPlainObject(a)&&(b=a,a="");var b=ab(b),c=this.iterator("table",function(c){var e=a,f=b,g=c.aoColumns,j=G(g,"sName"),i=G(g,"nTh");return $a("column",e,function(a){var b=Pb(a);if(a==="")return W(g.length);if(b!==null)return[b>=0?b:g.length+b];if(typeof a==="function"){var e=Ba(c,f);return h.map(g,function(b,f){return a(f,Wb(c,f,0,0,e),i[f])?f:null})}var k=typeof a==="string"?a.match(ec):"";if(k)switch(k[2]){case "visIdx":case "visible":b=parseInt(k[1],
|
||||
10);if(b<0){var m=h.map(g,function(a,b){return a.bVisible?b:null});return[m[m.length+b]]}return[Z(c,b)];case "name":return h.map(j,function(a,b){return a===k[1]?b:null});default:return[]}if(a.nodeName&&a._DT_CellIndex)return[a._DT_CellIndex.column];b=h(i).filter(a).map(function(){return h.inArray(this,i)}).toArray();if(b.length||!a.nodeName)return b;b=h(a).closest("*[data-dt-column]");return b.length?[b.data("dt-column")]:[]},c,f)},1);c.selector.cols=a;c.selector.opts=b;return c});s("columns().header()",
|
||||
"column().header()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].nTh},1)});s("columns().footer()","column().footer()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].nTf},1)});s("columns().data()","column().data()",function(){return this.iterator("column-rows",Wb,1)});s("columns().dataSrc()","column().dataSrc()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].mData},1)});s("columns().cache()","column().cache()",
|
||||
function(a){return this.iterator("column-rows",function(b,c,d,e,f){return ha(b.aoData,f,"search"===a?"_aFilterData":"_aSortData",c)},1)});s("columns().nodes()","column().nodes()",function(){return this.iterator("column-rows",function(a,b,c,d,e){return ha(a.aoData,e,"anCells",b)},1)});s("columns().visible()","column().visible()",function(a,b){var c=this.iterator("column",function(b,c){if(a===k)return b.aoColumns[c].bVisible;var f=b.aoColumns,g=f[c],j=b.aoData,i,n,l;if(a!==k&&g.bVisible!==a){if(a){var m=
|
||||
h.inArray(!0,G(f,"bVisible"),c+1);i=0;for(n=j.length;i<n;i++)l=j[i].nTr,f=j[i].anCells,l&&l.insertBefore(f[c],f[m]||null)}else h(G(b.aoData,"anCells",c)).detach();g.bVisible=a;ea(b,b.aoHeader);ea(b,b.aoFooter);wa(b)}});a!==k&&(this.iterator("column",function(c,e){u(c,null,"column-visibility",[c,e,a,b])}),(b===k||b)&&this.columns.adjust());return c});s("columns().indexes()","column().index()",function(a){return this.iterator("column",function(b,c){return"visible"===a?$(b,c):c},1)});p("columns.adjust()",
|
||||
function(){return this.iterator("table",function(a){Y(a)},1)});p("column.index()",function(a,b){if(0!==this.context.length){var c=this.context[0];if("fromVisible"===a||"toData"===a)return Z(c,b);if("fromData"===a||"toVisible"===a)return $(c,b)}});p("column()",function(a,b){return bb(this.columns(a,b))});p("cells()",function(a,b,c){h.isPlainObject(a)&&(a.row===k?(c=a,a=null):(c=b,b=null));h.isPlainObject(b)&&(c=b,b=null);if(null===b||b===k)return this.iterator("table",function(b){var d=a,e=ab(c),f=
|
||||
b.aoData,g=Ba(b,e),j=Sb(ha(f,g,"anCells")),i=h([].concat.apply([],j)),l,n=b.aoColumns.length,m,p,r,u,v,s;return $a("cell",d,function(a){var c=typeof a==="function";if(a===null||a===k||c){m=[];p=0;for(r=g.length;p<r;p++){l=g[p];for(u=0;u<n;u++){v={row:l,column:u};if(c){s=f[l];a(v,B(b,l,u),s.anCells?s.anCells[u]:null)&&m.push(v)}else m.push(v)}}return m}if(h.isPlainObject(a))return[a];c=i.filter(a).map(function(a,b){return{row:b._DT_CellIndex.row,column:b._DT_CellIndex.column}}).toArray();if(c.length||
|
||||
!a.nodeName)return c;s=h(a).closest("*[data-dt-row]");return s.length?[{row:s.data("dt-row"),column:s.data("dt-column")}]:[]},b,e)});var d=this.columns(b,c),e=this.rows(a,c),f,g,j,i,n,l=this.iterator("table",function(a,b){f=[];g=0;for(j=e[b].length;g<j;g++){i=0;for(n=d[b].length;i<n;i++)f.push({row:e[b][g],column:d[b][i]})}return f},1);h.extend(l.selector,{cols:b,rows:a,opts:c});return l});s("cells().nodes()","cell().node()",function(){return this.iterator("cell",function(a,b,c){return(a=a.aoData[b])&&
|
||||
a.anCells?a.anCells[c]:k},1)});p("cells().data()",function(){return this.iterator("cell",function(a,b,c){return B(a,b,c)},1)});s("cells().cache()","cell().cache()",function(a){a="search"===a?"_aFilterData":"_aSortData";return this.iterator("cell",function(b,c,d){return b.aoData[c][a][d]},1)});s("cells().render()","cell().render()",function(a){return this.iterator("cell",function(b,c,d){return B(b,c,d,a)},1)});s("cells().indexes()","cell().index()",function(){return this.iterator("cell",function(a,
|
||||
b,c){return{row:b,column:c,columnVisible:$(a,c)}},1)});s("cells().invalidate()","cell().invalidate()",function(a){return this.iterator("cell",function(b,c,d){ca(b,c,a,d)})});p("cell()",function(a,b,c){return bb(this.cells(a,b,c))});p("cell().data()",function(a){var b=this.context,c=this[0];if(a===k)return b.length&&c.length?B(b[0],c[0].row,c[0].column):k;jb(b[0],c[0].row,c[0].column,a);ca(b[0],c[0].row,"data",c[0].column);return this});p("order()",function(a,b){var c=this.context;if(a===k)return 0!==
|
||||
c.length?c[0].aaSorting:k;"number"===typeof a?a=[[a,b]]:a.length&&!h.isArray(a[0])&&(a=Array.prototype.slice.call(arguments));return this.iterator("table",function(b){b.aaSorting=a.slice()})});p("order.listener()",function(a,b,c){return this.iterator("table",function(d){Ma(d,a,b,c)})});p("order.fixed()",function(a){if(!a){var b=this.context,b=b.length?b[0].aaSortingFixed:k;return h.isArray(b)?{pre:b}:b}return this.iterator("table",function(b){b.aaSortingFixed=h.extend(!0,{},a)})});p(["columns().order()",
|
||||
"column().order()"],function(a){var b=this;return this.iterator("table",function(c,d){var e=[];h.each(b[d],function(b,c){e.push([c,a])});c.aaSorting=e})});p("search()",function(a,b,c,d){var e=this.context;return a===k?0!==e.length?e[0].oPreviousSearch.sSearch:k:this.iterator("table",function(e){e.oFeatures.bFilter&&fa(e,h.extend({},e.oPreviousSearch,{sSearch:a+"",bRegex:null===b?!1:b,bSmart:null===c?!0:c,bCaseInsensitive:null===d?!0:d}),1)})});s("columns().search()","column().search()",function(a,
|
||||
b,c,d){return this.iterator("column",function(e,f){var g=e.aoPreSearchCols;if(a===k)return g[f].sSearch;e.oFeatures.bFilter&&(h.extend(g[f],{sSearch:a+"",bRegex:null===b?!1:b,bSmart:null===c?!0:c,bCaseInsensitive:null===d?!0:d}),fa(e,e.oPreviousSearch,1))})});p("state()",function(){return this.context.length?this.context[0].oSavedState:null});p("state.clear()",function(){return this.iterator("table",function(a){a.fnStateSaveCallback.call(a.oInstance,a,{})})});p("state.loaded()",function(){return this.context.length?
|
||||
this.context[0].oLoadedState:null});p("state.save()",function(){return this.iterator("table",function(a){wa(a)})});m.versionCheck=m.fnVersionCheck=function(a){for(var b=m.version.split("."),a=a.split("."),c,d,e=0,f=a.length;e<f;e++)if(c=parseInt(b[e],10)||0,d=parseInt(a[e],10)||0,c!==d)return c>d;return!0};m.isDataTable=m.fnIsDataTable=function(a){var b=h(a).get(0),c=!1;h.each(m.settings,function(a,e){var f=e.nScrollHead?h("table",e.nScrollHead)[0]:null,g=e.nScrollFoot?h("table",e.nScrollFoot)[0]:
|
||||
null;if(e.nTable===b||f===b||g===b)c=!0});return c};m.tables=m.fnTables=function(a){var b=!1;h.isPlainObject(a)&&(b=a.api,a=a.visible);var c=h.map(m.settings,function(b){if(!a||a&&h(b.nTable).is(":visible"))return b.nTable});return b?new r(c):c};m.camelToHungarian=K;p("$()",function(a,b){var c=this.rows(b).nodes(),c=h(c);return h([].concat(c.filter(a).toArray(),c.find(a).toArray()))});h.each(["on","one","off"],function(a,b){p(b+"()",function(){var a=Array.prototype.slice.call(arguments);a[0].match(/\.dt\b/)||
|
||||
(a[0]+=".dt");var d=h(this.tables().nodes());d[b].apply(d,a);return this})});p("clear()",function(){return this.iterator("table",function(a){na(a)})});p("settings()",function(){return new r(this.context,this.context)});p("init()",function(){var a=this.context;return a.length?a[0].oInit:null});p("data()",function(){return this.iterator("table",function(a){return G(a.aoData,"_aData")}).flatten()});p("destroy()",function(a){a=a||!1;return this.iterator("table",function(b){var c=b.nTableWrapper.parentNode,
|
||||
d=b.oClasses,e=b.nTable,f=b.nTBody,g=b.nTHead,j=b.nTFoot,i=h(e),f=h(f),k=h(b.nTableWrapper),l=h.map(b.aoData,function(a){return a.nTr}),p;b.bDestroying=!0;u(b,"aoDestroyCallback","destroy",[b]);a||(new r(b)).columns().visible(!0);k.unbind(".DT").find(":not(tbody *)").unbind(".DT");h(D).unbind(".DT-"+b.sInstance);e!=g.parentNode&&(i.children("thead").detach(),i.append(g));j&&e!=j.parentNode&&(i.children("tfoot").detach(),i.append(j));b.aaSorting=[];b.aaSortingFixed=[];va(b);h(l).removeClass(b.asStripeClasses.join(" "));
|
||||
h("th, td",g).removeClass(d.sSortable+" "+d.sSortableAsc+" "+d.sSortableDesc+" "+d.sSortableNone);b.bJUI&&(h("th span."+d.sSortIcon+", td span."+d.sSortIcon,g).detach(),h("th, td",g).each(function(){var a=h("div."+d.sSortJUIWrapper,this);h(this).append(a.contents());a.detach()}));f.children().detach();f.append(l);g=a?"remove":"detach";i[g]();k[g]();!a&&c&&(c.insertBefore(e,b.nTableReinsertBefore),i.css("width",b.sDestroyWidth).removeClass(d.sTable),(p=b.asDestroyStripes.length)&&f.children().each(function(a){h(this).addClass(b.asDestroyStripes[a%
|
||||
p])}));c=h.inArray(b,m.settings);-1!==c&&m.settings.splice(c,1)})});h.each(["column","row","cell"],function(a,b){p(b+"s().every()",function(a){var d=this.selector.opts,e=this;return this.iterator(b,function(f,g,h,i,n){a.call(e[b](g,"cell"===b?h:d,"cell"===b?d:k),g,h,i,n)})})});p("i18n()",function(a,b,c){var d=this.context[0],a=Q(a)(d.oLanguage);a===k&&(a=b);c!==k&&h.isPlainObject(a)&&(a=a[c]!==k?a[c]:a._);return a.replace("%d",c)});m.version="1.10.12";m.settings=[];m.models={};m.models.oSearch={bCaseInsensitive:!0,
|
||||
sSearch:"",bRegex:!1,bSmart:!0};m.models.oRow={nTr:null,anCells:null,_aData:[],_aSortData:null,_aFilterData:null,_sFilterRow:null,_sRowStripe:"",src:null,idx:-1};m.models.oColumn={idx:null,aDataSort:null,asSorting:null,bSearchable:null,bSortable:null,bVisible:null,_sManualType:null,_bAttrSrc:!1,fnCreatedCell:null,fnGetData:null,fnSetData:null,mData:null,mRender:null,nTh:null,nTf:null,sClass:null,sContentPadding:null,sDefaultContent:null,sName:null,sSortDataType:"std",sSortingClass:null,sSortingClassJUI:null,
|
||||
sTitle:null,sType:null,sWidth:null,sWidthOrig:null};m.defaults={aaData:null,aaSorting:[[0,"asc"]],aaSortingFixed:[],ajax:null,aLengthMenu:[10,25,50,100],aoColumns:null,aoColumnDefs:null,aoSearchCols:[],asStripeClasses:null,bAutoWidth:!0,bDeferRender:!1,bDestroy:!1,bFilter:!0,bInfo:!0,bJQueryUI:!1,bLengthChange:!0,bPaginate:!0,bProcessing:!1,bRetrieve:!1,bScrollCollapse:!1,bServerSide:!1,bSort:!0,bSortMulti:!0,bSortCellsTop:!1,bSortClasses:!0,bStateSave:!1,fnCreatedRow:null,fnDrawCallback:null,fnFooterCallback:null,
|
||||
fnFormatNumber:function(a){return a.toString().replace(/\B(?=(\d{3})+(?!\d))/g,this.oLanguage.sThousands)},fnHeaderCallback:null,fnInfoCallback:null,fnInitComplete:null,fnPreDrawCallback:null,fnRowCallback:null,fnServerData:null,fnServerParams:null,fnStateLoadCallback:function(a){try{return JSON.parse((-1===a.iStateDuration?sessionStorage:localStorage).getItem("DataTables_"+a.sInstance+"_"+location.pathname))}catch(b){}},fnStateLoadParams:null,fnStateLoaded:null,fnStateSaveCallback:function(a,b){try{(-1===
|
||||
a.iStateDuration?sessionStorage:localStorage).setItem("DataTables_"+a.sInstance+"_"+location.pathname,JSON.stringify(b))}catch(c){}},fnStateSaveParams:null,iStateDuration:7200,iDeferLoading:null,iDisplayLength:10,iDisplayStart:0,iTabIndex:0,oClasses:{},oLanguage:{oAria:{sSortAscending:": activate to sort column ascending",sSortDescending:": activate to sort column descending"},oPaginate:{sFirst:"First",sLast:"Last",sNext:"Next",sPrevious:"Previous"},sEmptyTable:"No data available in table",sInfo:"Showing _START_ to _END_ of _TOTAL_ entries",
|
||||
sInfoEmpty:"Showing 0 to 0 of 0 entries",sInfoFiltered:"(filtered from _MAX_ total entries)",sInfoPostFix:"",sDecimal:"",sThousands:",",sLengthMenu:"Show _MENU_ entries",sLoadingRecords:"Loading...",sProcessing:"Processing...",sSearch:"Search:",sSearchPlaceholder:"",sUrl:"",sZeroRecords:"No matching records found"},oSearch:h.extend({},m.models.oSearch),sAjaxDataProp:"data",sAjaxSource:null,sDom:"lfrtip",searchDelay:null,sPaginationType:"simple_numbers",sScrollX:"",sScrollXInner:"",sScrollY:"",sServerMethod:"GET",
|
||||
renderer:null,rowId:"DT_RowId"};X(m.defaults);m.defaults.column={aDataSort:null,iDataSort:-1,asSorting:["asc","desc"],bSearchable:!0,bSortable:!0,bVisible:!0,fnCreatedCell:null,mData:null,mRender:null,sCellType:"td",sClass:"",sContentPadding:"",sDefaultContent:null,sName:"",sSortDataType:"std",sTitle:null,sType:null,sWidth:null};X(m.defaults.column);m.models.oSettings={oFeatures:{bAutoWidth:null,bDeferRender:null,bFilter:null,bInfo:null,bLengthChange:null,bPaginate:null,bProcessing:null,bServerSide:null,
|
||||
bSort:null,bSortMulti:null,bSortClasses:null,bStateSave:null},oScroll:{bCollapse:null,iBarWidth:0,sX:null,sXInner:null,sY:null},oLanguage:{fnInfoCallback:null},oBrowser:{bScrollOversize:!1,bScrollbarLeft:!1,bBounding:!1,barWidth:0},ajax:null,aanFeatures:[],aoData:[],aiDisplay:[],aiDisplayMaster:[],aIds:{},aoColumns:[],aoHeader:[],aoFooter:[],oPreviousSearch:{},aoPreSearchCols:[],aaSorting:null,aaSortingFixed:[],asStripeClasses:null,asDestroyStripes:[],sDestroyWidth:0,aoRowCallback:[],aoHeaderCallback:[],
|
||||
aoFooterCallback:[],aoDrawCallback:[],aoRowCreatedCallback:[],aoPreDrawCallback:[],aoInitComplete:[],aoStateSaveParams:[],aoStateLoadParams:[],aoStateLoaded:[],sTableId:"",nTable:null,nTHead:null,nTFoot:null,nTBody:null,nTableWrapper:null,bDeferLoading:!1,bInitialised:!1,aoOpenRows:[],sDom:null,searchDelay:null,sPaginationType:"two_button",iStateDuration:0,aoStateSave:[],aoStateLoad:[],oSavedState:null,oLoadedState:null,sAjaxSource:null,sAjaxDataProp:null,bAjaxDataGet:!0,jqXHR:null,json:k,oAjaxData:k,
|
||||
fnServerData:null,aoServerParams:[],sServerMethod:null,fnFormatNumber:null,aLengthMenu:null,iDraw:0,bDrawing:!1,iDrawError:-1,_iDisplayLength:10,_iDisplayStart:0,_iRecordsTotal:0,_iRecordsDisplay:0,bJUI:null,oClasses:{},bFiltered:!1,bSorted:!1,bSortCellsTop:null,oInit:null,aoDestroyCallback:[],fnRecordsTotal:function(){return"ssp"==y(this)?1*this._iRecordsTotal:this.aiDisplayMaster.length},fnRecordsDisplay:function(){return"ssp"==y(this)?1*this._iRecordsDisplay:this.aiDisplay.length},fnDisplayEnd:function(){var a=
|
||||
this._iDisplayLength,b=this._iDisplayStart,c=b+a,d=this.aiDisplay.length,e=this.oFeatures,f=e.bPaginate;return e.bServerSide?!1===f||-1===a?b+d:Math.min(b+a,this._iRecordsDisplay):!f||c>d||-1===a?d:c},oInstance:null,sInstance:null,iTabIndex:0,nScrollHead:null,nScrollFoot:null,aLastSort:[],oPlugins:{},rowIdFn:null,rowId:null};m.ext=v={buttons:{},classes:{},builder:"-source-",errMode:"alert",feature:[],search:[],selector:{cell:[],column:[],row:[]},internal:{},legacy:{ajax:null},pager:{},renderer:{pageButton:{},
|
||||
header:{}},order:{},type:{detect:[],search:{},order:{}},_unique:0,fnVersionCheck:m.fnVersionCheck,iApiIndex:0,oJUIClasses:{},sVersion:m.version};h.extend(v,{afnFiltering:v.search,aTypes:v.type.detect,ofnSearch:v.type.search,oSort:v.type.order,afnSortData:v.order,aoFeatures:v.feature,oApi:v.internal,oStdClasses:v.classes,oPagination:v.pager});h.extend(m.ext.classes,{sTable:"dataTable",sNoFooter:"no-footer",sPageButton:"paginate_button",sPageButtonActive:"current",sPageButtonDisabled:"disabled",sStripeOdd:"odd",
|
||||
sStripeEven:"even",sRowEmpty:"dataTables_empty",sWrapper:"dataTables_wrapper",sFilter:"dataTables_filter",sInfo:"dataTables_info",sPaging:"dataTables_paginate paging_",sLength:"dataTables_length",sProcessing:"dataTables_processing",sSortAsc:"sorting_asc",sSortDesc:"sorting_desc",sSortable:"sorting",sSortableAsc:"sorting_asc_disabled",sSortableDesc:"sorting_desc_disabled",sSortableNone:"sorting_disabled",sSortColumn:"sorting_",sFilterInput:"",sLengthSelect:"",sScrollWrapper:"dataTables_scroll",sScrollHead:"dataTables_scrollHead",
|
||||
sScrollHeadInner:"dataTables_scrollHeadInner",sScrollBody:"dataTables_scrollBody",sScrollFoot:"dataTables_scrollFoot",sScrollFootInner:"dataTables_scrollFootInner",sHeaderTH:"",sFooterTH:"",sSortJUIAsc:"",sSortJUIDesc:"",sSortJUI:"",sSortJUIAscAllowed:"",sSortJUIDescAllowed:"",sSortJUIWrapper:"",sSortIcon:"",sJUIHeader:"",sJUIFooter:""});var Ca="",Ca="",H=Ca+"ui-state-default",ia=Ca+"css_right ui-icon ui-icon-",Xb=Ca+"fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix";h.extend(m.ext.oJUIClasses,
|
||||
m.ext.classes,{sPageButton:"fg-button ui-button "+H,sPageButtonActive:"ui-state-disabled",sPageButtonDisabled:"ui-state-disabled",sPaging:"dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi ui-buttonset-multi paging_",sSortAsc:H+" sorting_asc",sSortDesc:H+" sorting_desc",sSortable:H+" sorting",sSortableAsc:H+" sorting_asc_disabled",sSortableDesc:H+" sorting_desc_disabled",sSortableNone:H+" sorting_disabled",sSortJUIAsc:ia+"triangle-1-n",sSortJUIDesc:ia+"triangle-1-s",sSortJUI:ia+"carat-2-n-s",
|
||||
sSortJUIAscAllowed:ia+"carat-1-n",sSortJUIDescAllowed:ia+"carat-1-s",sSortJUIWrapper:"DataTables_sort_wrapper",sSortIcon:"DataTables_sort_icon",sScrollHead:"dataTables_scrollHead "+H,sScrollFoot:"dataTables_scrollFoot "+H,sHeaderTH:H,sFooterTH:H,sJUIHeader:Xb+" ui-corner-tl ui-corner-tr",sJUIFooter:Xb+" ui-corner-bl ui-corner-br"});var Mb=m.ext.pager;h.extend(Mb,{simple:function(){return["previous","next"]},full:function(){return["first","previous","next","last"]},numbers:function(a,b){return[ya(a,
|
||||
b)]},simple_numbers:function(a,b){return["previous",ya(a,b),"next"]},full_numbers:function(a,b){return["first","previous",ya(a,b),"next","last"]},_numbers:ya,numbers_length:7});h.extend(!0,m.ext.renderer,{pageButton:{_:function(a,b,c,d,e,f){var g=a.oClasses,j=a.oLanguage.oPaginate,i=a.oLanguage.oAria.paginate||{},k,l,m=0,p=function(b,d){var o,r,u,s,v=function(b){Ta(a,b.data.action,true)};o=0;for(r=d.length;o<r;o++){s=d[o];if(h.isArray(s)){u=h("<"+(s.DT_el||"div")+"/>").appendTo(b);p(u,s)}else{k=null;
|
||||
l="";switch(s){case "ellipsis":b.append('<span class="ellipsis">…</span>');break;case "first":k=j.sFirst;l=s+(e>0?"":" "+g.sPageButtonDisabled);break;case "previous":k=j.sPrevious;l=s+(e>0?"":" "+g.sPageButtonDisabled);break;case "next":k=j.sNext;l=s+(e<f-1?"":" "+g.sPageButtonDisabled);break;case "last":k=j.sLast;l=s+(e<f-1?"":" "+g.sPageButtonDisabled);break;default:k=s+1;l=e===s?g.sPageButtonActive:""}if(k!==null){u=h("<a>",{"class":g.sPageButton+" "+l,"aria-controls":a.sTableId,"aria-label":i[s],
|
||||
"data-dt-idx":m,tabindex:a.iTabIndex,id:c===0&&typeof s==="string"?a.sTableId+"_"+s:null}).html(k).appendTo(b);Wa(u,{action:s},v);m++}}}},r;try{r=h(b).find(I.activeElement).data("dt-idx")}catch(o){}p(h(b).empty(),d);r&&h(b).find("[data-dt-idx="+r+"]").focus()}}});h.extend(m.ext.type.detect,[function(a,b){var c=b.oLanguage.sDecimal;return Za(a,c)?"num"+c:null},function(a){if(a&&!(a instanceof Date)&&(!ac.test(a)||!bc.test(a)))return null;var b=Date.parse(a);return null!==b&&!isNaN(b)||M(a)?"date":
|
||||
null},function(a,b){var c=b.oLanguage.sDecimal;return Za(a,c,!0)?"num-fmt"+c:null},function(a,b){var c=b.oLanguage.sDecimal;return Rb(a,c)?"html-num"+c:null},function(a,b){var c=b.oLanguage.sDecimal;return Rb(a,c,!0)?"html-num-fmt"+c:null},function(a){return M(a)||"string"===typeof a&&-1!==a.indexOf("<")?"html":null}]);h.extend(m.ext.type.search,{html:function(a){return M(a)?a:"string"===typeof a?a.replace(Ob," ").replace(Aa,""):""},string:function(a){return M(a)?a:"string"===typeof a?a.replace(Ob,
|
||||
" "):a}});var za=function(a,b,c,d){if(0!==a&&(!a||"-"===a))return-Infinity;b&&(a=Qb(a,b));a.replace&&(c&&(a=a.replace(c,"")),d&&(a=a.replace(d,"")));return 1*a};h.extend(v.type.order,{"date-pre":function(a){return Date.parse(a)||0},"html-pre":function(a){return M(a)?"":a.replace?a.replace(/<.*?>/g,"").toLowerCase():a+""},"string-pre":function(a){return M(a)?"":"string"===typeof a?a.toLowerCase():!a.toString?"":a.toString()},"string-asc":function(a,b){return a<b?-1:a>b?1:0},"string-desc":function(a,
|
||||
b){return a<b?1:a>b?-1:0}});db("");h.extend(!0,m.ext.renderer,{header:{_:function(a,b,c,d){h(a.nTable).on("order.dt.DT",function(e,f,g,h){if(a===f){e=c.idx;b.removeClass(c.sSortingClass+" "+d.sSortAsc+" "+d.sSortDesc).addClass(h[e]=="asc"?d.sSortAsc:h[e]=="desc"?d.sSortDesc:c.sSortingClass)}})},jqueryui:function(a,b,c,d){h("<div/>").addClass(d.sSortJUIWrapper).append(b.contents()).append(h("<span/>").addClass(d.sSortIcon+" "+c.sSortingClassJUI)).appendTo(b);h(a.nTable).on("order.dt.DT",function(e,
|
||||
f,g,h){if(a===f){e=c.idx;b.removeClass(d.sSortAsc+" "+d.sSortDesc).addClass(h[e]=="asc"?d.sSortAsc:h[e]=="desc"?d.sSortDesc:c.sSortingClass);b.find("span."+d.sSortIcon).removeClass(d.sSortJUIAsc+" "+d.sSortJUIDesc+" "+d.sSortJUI+" "+d.sSortJUIAscAllowed+" "+d.sSortJUIDescAllowed).addClass(h[e]=="asc"?d.sSortJUIAsc:h[e]=="desc"?d.sSortJUIDesc:c.sSortingClassJUI)}})}}});var Yb=function(a){return"string"===typeof a?a.replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):a};m.render={number:function(a,
|
||||
b,c,d,e){return{display:function(f){if("number"!==typeof f&&"string"!==typeof f)return f;var g=0>f?"-":"",h=parseFloat(f);if(isNaN(h))return Yb(f);f=Math.abs(h);h=parseInt(f,10);f=c?b+(f-h).toFixed(c).substring(2):"";return g+(d||"")+h.toString().replace(/\B(?=(\d{3})+(?!\d))/g,a)+f+(e||"")}}},text:function(){return{display:Yb}}};h.extend(m.ext.internal,{_fnExternApiFunc:Nb,_fnBuildAjax:ra,_fnAjaxUpdate:lb,_fnAjaxParameters:ub,_fnAjaxUpdateDraw:vb,_fnAjaxDataSrc:sa,_fnAddColumn:Ea,_fnColumnOptions:ja,
|
||||
_fnAdjustColumnSizing:Y,_fnVisibleToColumnIndex:Z,_fnColumnIndexToVisible:$,_fnVisbleColumns:aa,_fnGetColumns:la,_fnColumnTypes:Ga,_fnApplyColumnDefs:ib,_fnHungarianMap:X,_fnCamelToHungarian:K,_fnLanguageCompat:Da,_fnBrowserDetect:gb,_fnAddData:N,_fnAddTr:ma,_fnNodeToDataIndex:function(a,b){return b._DT_RowIndex!==k?b._DT_RowIndex:null},_fnNodeToColumnIndex:function(a,b,c){return h.inArray(c,a.aoData[b].anCells)},_fnGetCellData:B,_fnSetCellData:jb,_fnSplitObjNotation:Ja,_fnGetObjectDataFn:Q,_fnSetObjectDataFn:R,
|
||||
_fnGetDataMaster:Ka,_fnClearTable:na,_fnDeleteIndex:oa,_fnInvalidate:ca,_fnGetRowElements:Ia,_fnCreateTr:Ha,_fnBuildHead:kb,_fnDrawHead:ea,_fnDraw:O,_fnReDraw:T,_fnAddOptionsHtml:nb,_fnDetectHeader:da,_fnGetUniqueThs:qa,_fnFeatureHtmlFilter:pb,_fnFilterComplete:fa,_fnFilterCustom:yb,_fnFilterColumn:xb,_fnFilter:wb,_fnFilterCreateSearch:Pa,_fnEscapeRegex:Qa,_fnFilterData:zb,_fnFeatureHtmlInfo:sb,_fnUpdateInfo:Cb,_fnInfoMacros:Db,_fnInitialise:ga,_fnInitComplete:ta,_fnLengthChange:Ra,_fnFeatureHtmlLength:ob,
|
||||
_fnFeatureHtmlPaginate:tb,_fnPageChange:Ta,_fnFeatureHtmlProcessing:qb,_fnProcessingDisplay:C,_fnFeatureHtmlTable:rb,_fnScrollDraw:ka,_fnApplyToChildren:J,_fnCalculateColumnWidths:Fa,_fnThrottle:Oa,_fnConvertToWidth:Fb,_fnGetWidestNode:Gb,_fnGetMaxLenString:Hb,_fnStringToCss:x,_fnSortFlatten:V,_fnSort:mb,_fnSortAria:Jb,_fnSortListener:Va,_fnSortAttachListener:Ma,_fnSortingClasses:va,_fnSortData:Ib,_fnSaveState:wa,_fnLoadState:Kb,_fnSettingsFromNode:xa,_fnLog:L,_fnMap:E,_fnBindAction:Wa,_fnCallbackReg:z,
|
||||
_fnCallbackFire:u,_fnLengthOverflow:Sa,_fnRenderer:Na,_fnDataSource:y,_fnRowAttributes:La,_fnCalculateEnd:function(){}});h.fn.dataTable=m;m.$=h;h.fn.dataTableSettings=m.settings;h.fn.dataTableExt=m.ext;h.fn.DataTable=function(a){return h(this).dataTable(a).api()};h.each(m,function(a,b){h.fn.DataTable[a]=b});return h.fn.dataTable});
|
||||
var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.findInternal=function(f,z,y){f instanceof String&&(f=String(f));for(var p=f.length,H=0;H<p;H++){var L=f[H];if(z.call(y,L,H,f))return{i:H,v:L}}return{i:-1,v:void 0}};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.SIMPLE_FROUND_POLYFILL=!1;
|
||||
$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(f,z,y){f!=Array.prototype&&f!=Object.prototype&&(f[z]=y.value)};$jscomp.getGlobal=function(f){return"undefined"!=typeof window&&window===f?f:"undefined"!=typeof global&&null!=global?global:f};$jscomp.global=$jscomp.getGlobal(this);
|
||||
$jscomp.polyfill=function(f,z,y,p){if(z){y=$jscomp.global;f=f.split(".");for(p=0;p<f.length-1;p++){var H=f[p];H in y||(y[H]={});y=y[H]}f=f[f.length-1];p=y[f];z=z(p);z!=p&&null!=z&&$jscomp.defineProperty(y,f,{configurable:!0,writable:!0,value:z})}};$jscomp.polyfill("Array.prototype.find",function(f){return f?f:function(f,y){return $jscomp.findInternal(this,f,y).v}},"es6","es3");
|
||||
(function(f){"function"===typeof define&&define.amd?define(["jquery"],function(z){return f(z,window,document)}):"object"===typeof exports?module.exports=function(z,y){z||(z=window);y||(y="undefined"!==typeof window?require("jquery"):require("jquery")(z));return f(y,z,z.document)}:f(jQuery,window,document)})(function(f,z,y,p){function H(a){var b,c,d={};f.each(a,function(e,h){(b=e.match(/^([^A-Z]+?)([A-Z])/))&&-1!=="a aa ai ao as b fn i m o s ".indexOf(b[1]+" ")&&(c=e.replace(b[0],b[2].toLowerCase()),
|
||||
d[c]=e,"o"===b[1]&&H(a[e]))});a._hungarianMap=d}function L(a,b,c){a._hungarianMap||H(a);var d;f.each(b,function(e,h){d=a._hungarianMap[e];d===p||!c&&b[d]!==p||("o"===d.charAt(0)?(b[d]||(b[d]={}),f.extend(!0,b[d],b[e]),L(a[d],b[d],c)):b[d]=b[e])})}function Ga(a){var b=q.defaults.oLanguage,c=b.sDecimal;c&&Ha(c);if(a){var d=a.sZeroRecords;!a.sEmptyTable&&d&&"No data available in table"===b.sEmptyTable&&M(a,a,"sZeroRecords","sEmptyTable");!a.sLoadingRecords&&d&&"Loading..."===b.sLoadingRecords&&M(a,a,
|
||||
"sZeroRecords","sLoadingRecords");a.sInfoThousands&&(a.sThousands=a.sInfoThousands);(a=a.sDecimal)&&c!==a&&Ha(a)}}function jb(a){F(a,"ordering","bSort");F(a,"orderMulti","bSortMulti");F(a,"orderClasses","bSortClasses");F(a,"orderCellsTop","bSortCellsTop");F(a,"order","aaSorting");F(a,"orderFixed","aaSortingFixed");F(a,"paging","bPaginate");F(a,"pagingType","sPaginationType");F(a,"pageLength","iDisplayLength");F(a,"searching","bFilter");"boolean"===typeof a.sScrollX&&(a.sScrollX=a.sScrollX?"100%":
|
||||
"");"boolean"===typeof a.scrollX&&(a.scrollX=a.scrollX?"100%":"");if(a=a.aoSearchCols)for(var b=0,c=a.length;b<c;b++)a[b]&&L(q.models.oSearch,a[b])}function kb(a){F(a,"orderable","bSortable");F(a,"orderData","aDataSort");F(a,"orderSequence","asSorting");F(a,"orderDataType","sortDataType");var b=a.aDataSort;"number"!==typeof b||f.isArray(b)||(a.aDataSort=[b])}function lb(a){if(!q.__browser){var b={};q.__browser=b;var c=f("<div/>").css({position:"fixed",top:0,left:-1*f(z).scrollLeft(),height:1,width:1,
|
||||
overflow:"hidden"}).append(f("<div/>").css({position:"absolute",top:1,left:1,width:100,overflow:"scroll"}).append(f("<div/>").css({width:"100%",height:10}))).appendTo("body"),d=c.children(),e=d.children();b.barWidth=d[0].offsetWidth-d[0].clientWidth;b.bScrollOversize=100===e[0].offsetWidth&&100!==d[0].clientWidth;b.bScrollbarLeft=1!==Math.round(e.offset().left);b.bBounding=c[0].getBoundingClientRect().width?!0:!1;c.remove()}f.extend(a.oBrowser,q.__browser);a.oScroll.iBarWidth=q.__browser.barWidth}
|
||||
function mb(a,b,c,d,e,h){var g=!1;if(c!==p){var k=c;g=!0}for(;d!==e;)a.hasOwnProperty(d)&&(k=g?b(k,a[d],d,a):a[d],g=!0,d+=h);return k}function Ia(a,b){var c=q.defaults.column,d=a.aoColumns.length;c=f.extend({},q.models.oColumn,c,{nTh:b?b:y.createElement("th"),sTitle:c.sTitle?c.sTitle:b?b.innerHTML:"",aDataSort:c.aDataSort?c.aDataSort:[d],mData:c.mData?c.mData:d,idx:d});a.aoColumns.push(c);c=a.aoPreSearchCols;c[d]=f.extend({},q.models.oSearch,c[d]);ma(a,d,f(b).data())}function ma(a,b,c){b=a.aoColumns[b];
|
||||
var d=a.oClasses,e=f(b.nTh);if(!b.sWidthOrig){b.sWidthOrig=e.attr("width")||null;var h=(e.attr("style")||"").match(/width:\s*(\d+[pxem%]+)/);h&&(b.sWidthOrig=h[1])}c!==p&&null!==c&&(kb(c),L(q.defaults.column,c,!0),c.mDataProp===p||c.mData||(c.mData=c.mDataProp),c.sType&&(b._sManualType=c.sType),c.className&&!c.sClass&&(c.sClass=c.className),c.sClass&&e.addClass(c.sClass),f.extend(b,c),M(b,c,"sWidth","sWidthOrig"),c.iDataSort!==p&&(b.aDataSort=[c.iDataSort]),M(b,c,"aDataSort"));var g=b.mData,k=U(g),
|
||||
l=b.mRender?U(b.mRender):null;c=function(a){return"string"===typeof a&&-1!==a.indexOf("@")};b._bAttrSrc=f.isPlainObject(g)&&(c(g.sort)||c(g.type)||c(g.filter));b._setter=null;b.fnGetData=function(a,b,c){var d=k(a,b,p,c);return l&&b?l(d,b,a,c):d};b.fnSetData=function(a,b,c){return Q(g)(a,b,c)};"number"!==typeof g&&(a._rowReadObject=!0);a.oFeatures.bSort||(b.bSortable=!1,e.addClass(d.sSortableNone));a=-1!==f.inArray("asc",b.asSorting);c=-1!==f.inArray("desc",b.asSorting);b.bSortable&&(a||c)?a&&!c?(b.sSortingClass=
|
||||
d.sSortableAsc,b.sSortingClassJUI=d.sSortJUIAscAllowed):!a&&c?(b.sSortingClass=d.sSortableDesc,b.sSortingClassJUI=d.sSortJUIDescAllowed):(b.sSortingClass=d.sSortable,b.sSortingClassJUI=d.sSortJUI):(b.sSortingClass=d.sSortableNone,b.sSortingClassJUI="")}function aa(a){if(!1!==a.oFeatures.bAutoWidth){var b=a.aoColumns;Ja(a);for(var c=0,d=b.length;c<d;c++)b[c].nTh.style.width=b[c].sWidth}b=a.oScroll;""===b.sY&&""===b.sX||na(a);A(a,null,"column-sizing",[a])}function ba(a,b){a=oa(a,"bVisible");return"number"===
|
||||
typeof a[b]?a[b]:null}function ca(a,b){a=oa(a,"bVisible");b=f.inArray(b,a);return-1!==b?b:null}function W(a){var b=0;f.each(a.aoColumns,function(a,d){d.bVisible&&"none"!==f(d.nTh).css("display")&&b++});return b}function oa(a,b){var c=[];f.map(a.aoColumns,function(a,e){a[b]&&c.push(e)});return c}function Ka(a){var b=a.aoColumns,c=a.aoData,d=q.ext.type.detect,e,h,g;var k=0;for(e=b.length;k<e;k++){var f=b[k];var n=[];if(!f.sType&&f._sManualType)f.sType=f._sManualType;else if(!f.sType){var m=0;for(h=
|
||||
d.length;m<h;m++){var w=0;for(g=c.length;w<g;w++){n[w]===p&&(n[w]=I(a,w,k,"type"));var u=d[m](n[w],a);if(!u&&m!==d.length-1)break;if("html"===u)break}if(u){f.sType=u;break}}f.sType||(f.sType="string")}}}function nb(a,b,c,d){var e,h,g,k=a.aoColumns;if(b)for(e=b.length-1;0<=e;e--){var l=b[e];var n=l.targets!==p?l.targets:l.aTargets;f.isArray(n)||(n=[n]);var m=0;for(h=n.length;m<h;m++)if("number"===typeof n[m]&&0<=n[m]){for(;k.length<=n[m];)Ia(a);d(n[m],l)}else if("number"===typeof n[m]&&0>n[m])d(k.length+
|
||||
n[m],l);else if("string"===typeof n[m]){var w=0;for(g=k.length;w<g;w++)("_all"==n[m]||f(k[w].nTh).hasClass(n[m]))&&d(w,l)}}if(c)for(e=0,a=c.length;e<a;e++)d(e,c[e])}function R(a,b,c,d){var e=a.aoData.length,h=f.extend(!0,{},q.models.oRow,{src:c?"dom":"data",idx:e});h._aData=b;a.aoData.push(h);for(var g=a.aoColumns,k=0,l=g.length;k<l;k++)g[k].sType=null;a.aiDisplayMaster.push(e);b=a.rowIdFn(b);b!==p&&(a.aIds[b]=h);!c&&a.oFeatures.bDeferRender||La(a,e,c,d);return e}function pa(a,b){var c;b instanceof
|
||||
f||(b=f(b));return b.map(function(b,e){c=Ma(a,e);return R(a,c.data,e,c.cells)})}function I(a,b,c,d){var e=a.iDraw,h=a.aoColumns[c],g=a.aoData[b]._aData,k=h.sDefaultContent,f=h.fnGetData(g,d,{settings:a,row:b,col:c});if(f===p)return a.iDrawError!=e&&null===k&&(O(a,0,"Requested unknown parameter "+("function"==typeof h.mData?"{function}":"'"+h.mData+"'")+" for row "+b+", column "+c,4),a.iDrawError=e),k;if((f===g||null===f)&&null!==k&&d!==p)f=k;else if("function"===typeof f)return f.call(g);return null===
|
||||
f&&"display"==d?"":f}function ob(a,b,c,d){a.aoColumns[c].fnSetData(a.aoData[b]._aData,d,{settings:a,row:b,col:c})}function Na(a){return f.map(a.match(/(\\.|[^\.])+/g)||[""],function(a){return a.replace(/\\\./g,".")})}function U(a){if(f.isPlainObject(a)){var b={};f.each(a,function(a,c){c&&(b[a]=U(c))});return function(a,c,h,g){var d=b[c]||b._;return d!==p?d(a,c,h,g):a}}if(null===a)return function(a){return a};if("function"===typeof a)return function(b,c,h,g){return a(b,c,h,g)};if("string"!==typeof a||
|
||||
-1===a.indexOf(".")&&-1===a.indexOf("[")&&-1===a.indexOf("("))return function(b,c){return b[a]};var c=function(a,b,h){if(""!==h){var d=Na(h);for(var e=0,l=d.length;e<l;e++){h=d[e].match(da);var n=d[e].match(X);if(h){d[e]=d[e].replace(da,"");""!==d[e]&&(a=a[d[e]]);n=[];d.splice(0,e+1);d=d.join(".");if(f.isArray(a))for(e=0,l=a.length;e<l;e++)n.push(c(a[e],b,d));a=h[0].substring(1,h[0].length-1);a=""===a?n:n.join(a);break}else if(n){d[e]=d[e].replace(X,"");a=a[d[e]]();continue}if(null===a||a[d[e]]===
|
||||
p)return p;a=a[d[e]]}}return a};return function(b,e){return c(b,e,a)}}function Q(a){if(f.isPlainObject(a))return Q(a._);if(null===a)return function(){};if("function"===typeof a)return function(b,d,e){a(b,"set",d,e)};if("string"!==typeof a||-1===a.indexOf(".")&&-1===a.indexOf("[")&&-1===a.indexOf("("))return function(b,d){b[a]=d};var b=function(a,d,e){e=Na(e);var c=e[e.length-1];for(var g,k,l=0,n=e.length-1;l<n;l++){g=e[l].match(da);k=e[l].match(X);if(g){e[l]=e[l].replace(da,"");a[e[l]]=[];c=e.slice();
|
||||
c.splice(0,l+1);g=c.join(".");if(f.isArray(d))for(k=0,n=d.length;k<n;k++)c={},b(c,d[k],g),a[e[l]].push(c);else a[e[l]]=d;return}k&&(e[l]=e[l].replace(X,""),a=a[e[l]](d));if(null===a[e[l]]||a[e[l]]===p)a[e[l]]={};a=a[e[l]]}if(c.match(X))a[c.replace(X,"")](d);else a[c.replace(da,"")]=d};return function(c,d){return b(c,d,a)}}function Oa(a){return J(a.aoData,"_aData")}function qa(a){a.aoData.length=0;a.aiDisplayMaster.length=0;a.aiDisplay.length=0;a.aIds={}}function ra(a,b,c){for(var d=-1,e=0,h=a.length;e<
|
||||
h;e++)a[e]==b?d=e:a[e]>b&&a[e]--; -1!=d&&c===p&&a.splice(d,1)}function ea(a,b,c,d){var e=a.aoData[b],h,g=function(c,d){for(;c.childNodes.length;)c.removeChild(c.firstChild);c.innerHTML=I(a,b,d,"display")};if("dom"!==c&&(c&&"auto"!==c||"dom"!==e.src)){var k=e.anCells;if(k)if(d!==p)g(k[d],d);else for(c=0,h=k.length;c<h;c++)g(k[c],c)}else e._aData=Ma(a,e,d,d===p?p:e._aData).data;e._aSortData=null;e._aFilterData=null;g=a.aoColumns;if(d!==p)g[d].sType=null;else{c=0;for(h=g.length;c<h;c++)g[c].sType=null;
|
||||
Pa(a,e)}}function Ma(a,b,c,d){var e=[],h=b.firstChild,g,k=0,l,n=a.aoColumns,m=a._rowReadObject;d=d!==p?d:m?{}:[];var w=function(a,b){if("string"===typeof a){var c=a.indexOf("@");-1!==c&&(c=a.substring(c+1),Q(a)(d,b.getAttribute(c)))}},u=function(a){if(c===p||c===k)g=n[k],l=f.trim(a.innerHTML),g&&g._bAttrSrc?(Q(g.mData._)(d,l),w(g.mData.sort,a),w(g.mData.type,a),w(g.mData.filter,a)):m?(g._setter||(g._setter=Q(g.mData)),g._setter(d,l)):d[k]=l;k++};if(h)for(;h;){var q=h.nodeName.toUpperCase();if("TD"==
|
||||
q||"TH"==q)u(h),e.push(h);h=h.nextSibling}else for(e=b.anCells,h=0,q=e.length;h<q;h++)u(e[h]);(b=b.firstChild?b:b.nTr)&&(b=b.getAttribute("id"))&&Q(a.rowId)(d,b);return{data:d,cells:e}}function La(a,b,c,d){var e=a.aoData[b],h=e._aData,g=[],k,l;if(null===e.nTr){var n=c||y.createElement("tr");e.nTr=n;e.anCells=g;n._DT_RowIndex=b;Pa(a,e);var m=0;for(k=a.aoColumns.length;m<k;m++){var w=a.aoColumns[m];var p=(l=c?!1:!0)?y.createElement(w.sCellType):d[m];p._DT_CellIndex={row:b,column:m};g.push(p);if(l||
|
||||
!(c&&!w.mRender&&w.mData===m||f.isPlainObject(w.mData)&&w.mData._===m+".display"))p.innerHTML=I(a,b,m,"display");w.sClass&&(p.className+=" "+w.sClass);w.bVisible&&!c?n.appendChild(p):!w.bVisible&&c&&p.parentNode.removeChild(p);w.fnCreatedCell&&w.fnCreatedCell.call(a.oInstance,p,I(a,b,m),h,b,m)}A(a,"aoRowCreatedCallback",null,[n,h,b,g])}e.nTr.setAttribute("role","row")}function Pa(a,b){var c=b.nTr,d=b._aData;if(c){if(a=a.rowIdFn(d))c.id=a;d.DT_RowClass&&(a=d.DT_RowClass.split(" "),b.__rowc=b.__rowc?
|
||||
ta(b.__rowc.concat(a)):a,f(c).removeClass(b.__rowc.join(" ")).addClass(d.DT_RowClass));d.DT_RowAttr&&f(c).attr(d.DT_RowAttr);d.DT_RowData&&f(c).data(d.DT_RowData)}}function pb(a){var b,c,d=a.nTHead,e=a.nTFoot,h=0===f("th, td",d).length,g=a.oClasses,k=a.aoColumns;h&&(c=f("<tr/>").appendTo(d));var l=0;for(b=k.length;l<b;l++){var n=k[l];var m=f(n.nTh).addClass(n.sClass);h&&m.appendTo(c);a.oFeatures.bSort&&(m.addClass(n.sSortingClass),!1!==n.bSortable&&(m.attr("tabindex",a.iTabIndex).attr("aria-controls",
|
||||
a.sTableId),Qa(a,n.nTh,l)));n.sTitle!=m[0].innerHTML&&m.html(n.sTitle);Ra(a,"header")(a,m,n,g)}h&&fa(a.aoHeader,d);f(d).find(">tr").attr("role","row");f(d).find(">tr>th, >tr>td").addClass(g.sHeaderTH);f(e).find(">tr>th, >tr>td").addClass(g.sFooterTH);if(null!==e)for(a=a.aoFooter[0],l=0,b=a.length;l<b;l++)n=k[l],n.nTf=a[l].cell,n.sClass&&f(n.nTf).addClass(n.sClass)}function ha(a,b,c){var d,e,h=[],g=[],k=a.aoColumns.length;if(b){c===p&&(c=!1);var l=0;for(d=b.length;l<d;l++){h[l]=b[l].slice();h[l].nTr=
|
||||
b[l].nTr;for(e=k-1;0<=e;e--)a.aoColumns[e].bVisible||c||h[l].splice(e,1);g.push([])}l=0;for(d=h.length;l<d;l++){if(a=h[l].nTr)for(;e=a.firstChild;)a.removeChild(e);e=0;for(b=h[l].length;e<b;e++){var n=k=1;if(g[l][e]===p){a.appendChild(h[l][e].cell);for(g[l][e]=1;h[l+k]!==p&&h[l][e].cell==h[l+k][e].cell;)g[l+k][e]=1,k++;for(;h[l][e+n]!==p&&h[l][e].cell==h[l][e+n].cell;){for(c=0;c<k;c++)g[l+c][e+n]=1;n++}f(h[l][e].cell).attr("rowspan",k).attr("colspan",n)}}}}}function S(a){var b=A(a,"aoPreDrawCallback",
|
||||
"preDraw",[a]);if(-1!==f.inArray(!1,b))K(a,!1);else{b=[];var c=0,d=a.asStripeClasses,e=d.length,h=a.oLanguage,g=a.iInitDisplayStart,k="ssp"==D(a),l=a.aiDisplay;a.bDrawing=!0;g!==p&&-1!==g&&(a._iDisplayStart=k?g:g>=a.fnRecordsDisplay()?0:g,a.iInitDisplayStart=-1);g=a._iDisplayStart;var n=a.fnDisplayEnd();if(a.bDeferLoading)a.bDeferLoading=!1,a.iDraw++,K(a,!1);else if(!k)a.iDraw++;else if(!a.bDestroying&&!qb(a))return;if(0!==l.length)for(h=k?a.aoData.length:n,k=k?0:g;k<h;k++){var m=l[k],w=a.aoData[m];
|
||||
null===w.nTr&&La(a,m);var u=w.nTr;if(0!==e){var q=d[c%e];w._sRowStripe!=q&&(f(u).removeClass(w._sRowStripe).addClass(q),w._sRowStripe=q)}A(a,"aoRowCallback",null,[u,w._aData,c,k,m]);b.push(u);c++}else c=h.sZeroRecords,1==a.iDraw&&"ajax"==D(a)?c=h.sLoadingRecords:h.sEmptyTable&&0===a.fnRecordsTotal()&&(c=h.sEmptyTable),b[0]=f("<tr/>",{"class":e?d[0]:""}).append(f("<td />",{valign:"top",colSpan:W(a),"class":a.oClasses.sRowEmpty}).html(c))[0];A(a,"aoHeaderCallback","header",[f(a.nTHead).children("tr")[0],
|
||||
Oa(a),g,n,l]);A(a,"aoFooterCallback","footer",[f(a.nTFoot).children("tr")[0],Oa(a),g,n,l]);d=f(a.nTBody);d.children().detach();d.append(f(b));A(a,"aoDrawCallback","draw",[a]);a.bSorted=!1;a.bFiltered=!1;a.bDrawing=!1}}function V(a,b){var c=a.oFeatures,d=c.bFilter;c.bSort&&rb(a);d?ia(a,a.oPreviousSearch):a.aiDisplay=a.aiDisplayMaster.slice();!0!==b&&(a._iDisplayStart=0);a._drawHold=b;S(a);a._drawHold=!1}function sb(a){var b=a.oClasses,c=f(a.nTable);c=f("<div/>").insertBefore(c);var d=a.oFeatures,e=
|
||||
f("<div/>",{id:a.sTableId+"_wrapper","class":b.sWrapper+(a.nTFoot?"":" "+b.sNoFooter)});a.nHolding=c[0];a.nTableWrapper=e[0];a.nTableReinsertBefore=a.nTable.nextSibling;for(var h=a.sDom.split(""),g,k,l,n,m,p,u=0;u<h.length;u++){g=null;k=h[u];if("<"==k){l=f("<div/>")[0];n=h[u+1];if("'"==n||'"'==n){m="";for(p=2;h[u+p]!=n;)m+=h[u+p],p++;"H"==m?m=b.sJUIHeader:"F"==m&&(m=b.sJUIFooter);-1!=m.indexOf(".")?(n=m.split("."),l.id=n[0].substr(1,n[0].length-1),l.className=n[1]):"#"==m.charAt(0)?l.id=m.substr(1,
|
||||
m.length-1):l.className=m;u+=p}e.append(l);e=f(l)}else if(">"==k)e=e.parent();else if("l"==k&&d.bPaginate&&d.bLengthChange)g=tb(a);else if("f"==k&&d.bFilter)g=ub(a);else if("r"==k&&d.bProcessing)g=vb(a);else if("t"==k)g=wb(a);else if("i"==k&&d.bInfo)g=xb(a);else if("p"==k&&d.bPaginate)g=yb(a);else if(0!==q.ext.feature.length)for(l=q.ext.feature,p=0,n=l.length;p<n;p++)if(k==l[p].cFeature){g=l[p].fnInit(a);break}g&&(l=a.aanFeatures,l[k]||(l[k]=[]),l[k].push(g),e.append(g))}c.replaceWith(e);a.nHolding=
|
||||
null}function fa(a,b){b=f(b).children("tr");var c,d,e;a.splice(0,a.length);var h=0;for(e=b.length;h<e;h++)a.push([]);h=0;for(e=b.length;h<e;h++){var g=b[h];for(c=g.firstChild;c;){if("TD"==c.nodeName.toUpperCase()||"TH"==c.nodeName.toUpperCase()){var k=1*c.getAttribute("colspan");var l=1*c.getAttribute("rowspan");k=k&&0!==k&&1!==k?k:1;l=l&&0!==l&&1!==l?l:1;var n=0;for(d=a[h];d[n];)n++;var m=n;var p=1===k?!0:!1;for(d=0;d<k;d++)for(n=0;n<l;n++)a[h+n][m+d]={cell:c,unique:p},a[h+n].nTr=g}c=c.nextSibling}}}
|
||||
function ua(a,b,c){var d=[];c||(c=a.aoHeader,b&&(c=[],fa(c,b)));b=0;for(var e=c.length;b<e;b++)for(var h=0,g=c[b].length;h<g;h++)!c[b][h].unique||d[h]&&a.bSortCellsTop||(d[h]=c[b][h].cell);return d}function va(a,b,c){A(a,"aoServerParams","serverParams",[b]);if(b&&f.isArray(b)){var d={},e=/(.*?)\[\]$/;f.each(b,function(a,b){(a=b.name.match(e))?(a=a[0],d[a]||(d[a]=[]),d[a].push(b.value)):d[b.name]=b.value});b=d}var h=a.ajax,g=a.oInstance,k=function(b){A(a,null,"xhr",[a,b,a.jqXHR]);c(b)};if(f.isPlainObject(h)&&
|
||||
h.data){var l=h.data;var n="function"===typeof l?l(b,a):l;b="function"===typeof l&&n?n:f.extend(!0,b,n);delete h.data}n={data:b,success:function(b){var c=b.error||b.sError;c&&O(a,0,c);a.json=b;k(b)},dataType:"json",cache:!1,type:a.sServerMethod,error:function(b,c,d){d=A(a,null,"xhr",[a,null,a.jqXHR]);-1===f.inArray(!0,d)&&("parsererror"==c?O(a,0,"Invalid JSON response",1):4===b.readyState&&O(a,0,"Ajax error",7));K(a,!1)}};a.oAjaxData=b;A(a,null,"preXhr",[a,b]);a.fnServerData?a.fnServerData.call(g,
|
||||
a.sAjaxSource,f.map(b,function(a,b){return{name:b,value:a}}),k,a):a.sAjaxSource||"string"===typeof h?a.jqXHR=f.ajax(f.extend(n,{url:h||a.sAjaxSource})):"function"===typeof h?a.jqXHR=h.call(g,b,k,a):(a.jqXHR=f.ajax(f.extend(n,h)),h.data=l)}function qb(a){return a.bAjaxDataGet?(a.iDraw++,K(a,!0),va(a,zb(a),function(b){Ab(a,b)}),!1):!0}function zb(a){var b=a.aoColumns,c=b.length,d=a.oFeatures,e=a.oPreviousSearch,h=a.aoPreSearchCols,g=[],k=Y(a);var l=a._iDisplayStart;var n=!1!==d.bPaginate?a._iDisplayLength:
|
||||
-1;var m=function(a,b){g.push({name:a,value:b})};m("sEcho",a.iDraw);m("iColumns",c);m("sColumns",J(b,"sName").join(","));m("iDisplayStart",l);m("iDisplayLength",n);var p={draw:a.iDraw,columns:[],order:[],start:l,length:n,search:{value:e.sSearch,regex:e.bRegex}};for(l=0;l<c;l++){var u=b[l];var sa=h[l];n="function"==typeof u.mData?"function":u.mData;p.columns.push({data:n,name:u.sName,searchable:u.bSearchable,orderable:u.bSortable,search:{value:sa.sSearch,regex:sa.bRegex}});m("mDataProp_"+l,n);d.bFilter&&
|
||||
(m("sSearch_"+l,sa.sSearch),m("bRegex_"+l,sa.bRegex),m("bSearchable_"+l,u.bSearchable));d.bSort&&m("bSortable_"+l,u.bSortable)}d.bFilter&&(m("sSearch",e.sSearch),m("bRegex",e.bRegex));d.bSort&&(f.each(k,function(a,b){p.order.push({column:b.col,dir:b.dir});m("iSortCol_"+a,b.col);m("sSortDir_"+a,b.dir)}),m("iSortingCols",k.length));b=q.ext.legacy.ajax;return null===b?a.sAjaxSource?g:p:b?g:p}function Ab(a,b){var c=function(a,c){return b[a]!==p?b[a]:b[c]},d=wa(a,b),e=c("sEcho","draw"),h=c("iTotalRecords",
|
||||
"recordsTotal");c=c("iTotalDisplayRecords","recordsFiltered");if(e){if(1*e<a.iDraw)return;a.iDraw=1*e}qa(a);a._iRecordsTotal=parseInt(h,10);a._iRecordsDisplay=parseInt(c,10);e=0;for(h=d.length;e<h;e++)R(a,d[e]);a.aiDisplay=a.aiDisplayMaster.slice();a.bAjaxDataGet=!1;S(a);a._bInitComplete||xa(a,b);a.bAjaxDataGet=!0;K(a,!1)}function wa(a,b){a=f.isPlainObject(a.ajax)&&a.ajax.dataSrc!==p?a.ajax.dataSrc:a.sAjaxDataProp;return"data"===a?b.aaData||b[a]:""!==a?U(a)(b):b}function ub(a){var b=a.oClasses,c=
|
||||
a.sTableId,d=a.oLanguage,e=a.oPreviousSearch,h=a.aanFeatures,g='<input type="search" class="'+b.sFilterInput+'"/>',k=d.sSearch;k=k.match(/_INPUT_/)?k.replace("_INPUT_",g):k+g;b=f("<div/>",{id:h.f?null:c+"_filter","class":b.sFilter}).append(f("<label/>").append(k));h=function(){var b=this.value?this.value:"";b!=e.sSearch&&(ia(a,{sSearch:b,bRegex:e.bRegex,bSmart:e.bSmart,bCaseInsensitive:e.bCaseInsensitive}),a._iDisplayStart=0,S(a))};g=null!==a.searchDelay?a.searchDelay:"ssp"===D(a)?400:0;var l=f("input",
|
||||
b).val(e.sSearch).attr("placeholder",d.sSearchPlaceholder).on("keyup.DT search.DT input.DT paste.DT cut.DT",g?Sa(h,g):h).on("keypress.DT",function(a){if(13==a.keyCode)return!1}).attr("aria-controls",c);f(a.nTable).on("search.dt.DT",function(b,c){if(a===c)try{l[0]!==y.activeElement&&l.val(e.sSearch)}catch(w){}});return b[0]}function ia(a,b,c){var d=a.oPreviousSearch,e=a.aoPreSearchCols,h=function(a){d.sSearch=a.sSearch;d.bRegex=a.bRegex;d.bSmart=a.bSmart;d.bCaseInsensitive=a.bCaseInsensitive},g=function(a){return a.bEscapeRegex!==
|
||||
p?!a.bEscapeRegex:a.bRegex};Ka(a);if("ssp"!=D(a)){Bb(a,b.sSearch,c,g(b),b.bSmart,b.bCaseInsensitive);h(b);for(b=0;b<e.length;b++)Cb(a,e[b].sSearch,b,g(e[b]),e[b].bSmart,e[b].bCaseInsensitive);Db(a)}else h(b);a.bFiltered=!0;A(a,null,"search",[a])}function Db(a){for(var b=q.ext.search,c=a.aiDisplay,d,e,h=0,g=b.length;h<g;h++){for(var k=[],l=0,n=c.length;l<n;l++)e=c[l],d=a.aoData[e],b[h](a,d._aFilterData,e,d._aData,l)&&k.push(e);c.length=0;f.merge(c,k)}}function Cb(a,b,c,d,e,h){if(""!==b){var g=[],k=
|
||||
a.aiDisplay;d=Ta(b,d,e,h);for(e=0;e<k.length;e++)b=a.aoData[k[e]]._aFilterData[c],d.test(b)&&g.push(k[e]);a.aiDisplay=g}}function Bb(a,b,c,d,e,h){e=Ta(b,d,e,h);var g=a.oPreviousSearch.sSearch,k=a.aiDisplayMaster;h=[];0!==q.ext.search.length&&(c=!0);var f=Eb(a);if(0>=b.length)a.aiDisplay=k.slice();else{if(f||c||d||g.length>b.length||0!==b.indexOf(g)||a.bSorted)a.aiDisplay=k.slice();b=a.aiDisplay;for(c=0;c<b.length;c++)e.test(a.aoData[b[c]]._sFilterRow)&&h.push(b[c]);a.aiDisplay=h}}function Ta(a,b,
|
||||
c,d){a=b?a:Ua(a);c&&(a="^(?=.*?"+f.map(a.match(/"[^"]+"|[^ ]+/g)||[""],function(a){if('"'===a.charAt(0)){var b=a.match(/^"(.*)"$/);a=b?b[1]:a}return a.replace('"',"")}).join(")(?=.*?")+").*$");return new RegExp(a,d?"i":"")}function Eb(a){var b=a.aoColumns,c,d,e=q.ext.type.search;var h=!1;var g=0;for(c=a.aoData.length;g<c;g++){var k=a.aoData[g];if(!k._aFilterData){var f=[];var n=0;for(d=b.length;n<d;n++){h=b[n];if(h.bSearchable){var m=I(a,g,n,"filter");e[h.sType]&&(m=e[h.sType](m));null===m&&(m="");
|
||||
"string"!==typeof m&&m.toString&&(m=m.toString())}else m="";m.indexOf&&-1!==m.indexOf("&")&&(ya.innerHTML=m,m=$b?ya.textContent:ya.innerText);m.replace&&(m=m.replace(/[\r\n\u2028]/g,""));f.push(m)}k._aFilterData=f;k._sFilterRow=f.join(" ");h=!0}}return h}function Fb(a){return{search:a.sSearch,smart:a.bSmart,regex:a.bRegex,caseInsensitive:a.bCaseInsensitive}}function Gb(a){return{sSearch:a.search,bSmart:a.smart,bRegex:a.regex,bCaseInsensitive:a.caseInsensitive}}function xb(a){var b=a.sTableId,c=a.aanFeatures.i,
|
||||
d=f("<div/>",{"class":a.oClasses.sInfo,id:c?null:b+"_info"});c||(a.aoDrawCallback.push({fn:Hb,sName:"information"}),d.attr("role","status").attr("aria-live","polite"),f(a.nTable).attr("aria-describedby",b+"_info"));return d[0]}function Hb(a){var b=a.aanFeatures.i;if(0!==b.length){var c=a.oLanguage,d=a._iDisplayStart+1,e=a.fnDisplayEnd(),h=a.fnRecordsTotal(),g=a.fnRecordsDisplay(),k=g?c.sInfo:c.sInfoEmpty;g!==h&&(k+=" "+c.sInfoFiltered);k+=c.sInfoPostFix;k=Ib(a,k);c=c.fnInfoCallback;null!==c&&(k=c.call(a.oInstance,
|
||||
a,d,e,h,g,k));f(b).html(k)}}function Ib(a,b){var c=a.fnFormatNumber,d=a._iDisplayStart+1,e=a._iDisplayLength,h=a.fnRecordsDisplay(),g=-1===e;return b.replace(/_START_/g,c.call(a,d)).replace(/_END_/g,c.call(a,a.fnDisplayEnd())).replace(/_MAX_/g,c.call(a,a.fnRecordsTotal())).replace(/_TOTAL_/g,c.call(a,h)).replace(/_PAGE_/g,c.call(a,g?1:Math.ceil(d/e))).replace(/_PAGES_/g,c.call(a,g?1:Math.ceil(h/e)))}function ja(a){var b=a.iInitDisplayStart,c=a.aoColumns;var d=a.oFeatures;var e=a.bDeferLoading;if(a.bInitialised){sb(a);
|
||||
pb(a);ha(a,a.aoHeader);ha(a,a.aoFooter);K(a,!0);d.bAutoWidth&&Ja(a);var h=0;for(d=c.length;h<d;h++){var g=c[h];g.sWidth&&(g.nTh.style.width=B(g.sWidth))}A(a,null,"preInit",[a]);V(a);c=D(a);if("ssp"!=c||e)"ajax"==c?va(a,[],function(c){var d=wa(a,c);for(h=0;h<d.length;h++)R(a,d[h]);a.iInitDisplayStart=b;V(a);K(a,!1);xa(a,c)},a):(K(a,!1),xa(a))}else setTimeout(function(){ja(a)},200)}function xa(a,b){a._bInitComplete=!0;(b||a.oInit.aaData)&&aa(a);A(a,null,"plugin-init",[a,b]);A(a,"aoInitComplete","init",
|
||||
[a,b])}function Va(a,b){b=parseInt(b,10);a._iDisplayLength=b;Wa(a);A(a,null,"length",[a,b])}function tb(a){var b=a.oClasses,c=a.sTableId,d=a.aLengthMenu,e=f.isArray(d[0]),h=e?d[0]:d;d=e?d[1]:d;e=f("<select/>",{name:c+"_length","aria-controls":c,"class":b.sLengthSelect});for(var g=0,k=h.length;g<k;g++)e[0][g]=new Option("number"===typeof d[g]?a.fnFormatNumber(d[g]):d[g],h[g]);var l=f("<div><label/></div>").addClass(b.sLength);a.aanFeatures.l||(l[0].id=c+"_length");l.children().append(a.oLanguage.sLengthMenu.replace("_MENU_",
|
||||
e[0].outerHTML));f("select",l).val(a._iDisplayLength).on("change.DT",function(b){Va(a,f(this).val());S(a)});f(a.nTable).on("length.dt.DT",function(b,c,d){a===c&&f("select",l).val(d)});return l[0]}function yb(a){var b=a.sPaginationType,c=q.ext.pager[b],d="function"===typeof c,e=function(a){S(a)};b=f("<div/>").addClass(a.oClasses.sPaging+b)[0];var h=a.aanFeatures;d||c.fnInit(a,b,e);h.p||(b.id=a.sTableId+"_paginate",a.aoDrawCallback.push({fn:function(a){if(d){var b=a._iDisplayStart,g=a._iDisplayLength,
|
||||
f=a.fnRecordsDisplay(),m=-1===g;b=m?0:Math.ceil(b/g);g=m?1:Math.ceil(f/g);f=c(b,g);var p;m=0;for(p=h.p.length;m<p;m++)Ra(a,"pageButton")(a,h.p[m],m,f,b,g)}else c.fnUpdate(a,e)},sName:"pagination"}));return b}function Xa(a,b,c){var d=a._iDisplayStart,e=a._iDisplayLength,h=a.fnRecordsDisplay();0===h||-1===e?d=0:"number"===typeof b?(d=b*e,d>h&&(d=0)):"first"==b?d=0:"previous"==b?(d=0<=e?d-e:0,0>d&&(d=0)):"next"==b?d+e<h&&(d+=e):"last"==b?d=Math.floor((h-1)/e)*e:O(a,0,"Unknown paging action: "+b,5);b=
|
||||
a._iDisplayStart!==d;a._iDisplayStart=d;b&&(A(a,null,"page",[a]),c&&S(a));return b}function vb(a){return f("<div/>",{id:a.aanFeatures.r?null:a.sTableId+"_processing","class":a.oClasses.sProcessing}).html(a.oLanguage.sProcessing).insertBefore(a.nTable)[0]}function K(a,b){a.oFeatures.bProcessing&&f(a.aanFeatures.r).css("display",b?"block":"none");A(a,null,"processing",[a,b])}function wb(a){var b=f(a.nTable);b.attr("role","grid");var c=a.oScroll;if(""===c.sX&&""===c.sY)return a.nTable;var d=c.sX,e=c.sY,
|
||||
h=a.oClasses,g=b.children("caption"),k=g.length?g[0]._captionSide:null,l=f(b[0].cloneNode(!1)),n=f(b[0].cloneNode(!1)),m=b.children("tfoot");m.length||(m=null);l=f("<div/>",{"class":h.sScrollWrapper}).append(f("<div/>",{"class":h.sScrollHead}).css({overflow:"hidden",position:"relative",border:0,width:d?d?B(d):null:"100%"}).append(f("<div/>",{"class":h.sScrollHeadInner}).css({"box-sizing":"content-box",width:c.sXInner||"100%"}).append(l.removeAttr("id").css("margin-left",0).append("top"===k?g:null).append(b.children("thead"))))).append(f("<div/>",
|
||||
{"class":h.sScrollBody}).css({position:"relative",overflow:"auto",width:d?B(d):null}).append(b));m&&l.append(f("<div/>",{"class":h.sScrollFoot}).css({overflow:"hidden",border:0,width:d?d?B(d):null:"100%"}).append(f("<div/>",{"class":h.sScrollFootInner}).append(n.removeAttr("id").css("margin-left",0).append("bottom"===k?g:null).append(b.children("tfoot")))));b=l.children();var p=b[0];h=b[1];var u=m?b[2]:null;if(d)f(h).on("scroll.DT",function(a){a=this.scrollLeft;p.scrollLeft=a;m&&(u.scrollLeft=a)});
|
||||
f(h).css(e&&c.bCollapse?"max-height":"height",e);a.nScrollHead=p;a.nScrollBody=h;a.nScrollFoot=u;a.aoDrawCallback.push({fn:na,sName:"scrolling"});return l[0]}function na(a){var b=a.oScroll,c=b.sX,d=b.sXInner,e=b.sY;b=b.iBarWidth;var h=f(a.nScrollHead),g=h[0].style,k=h.children("div"),l=k[0].style,n=k.children("table");k=a.nScrollBody;var m=f(k),w=k.style,u=f(a.nScrollFoot).children("div"),q=u.children("table"),t=f(a.nTHead),r=f(a.nTable),v=r[0],za=v.style,T=a.nTFoot?f(a.nTFoot):null,A=a.oBrowser,
|
||||
x=A.bScrollOversize,ac=J(a.aoColumns,"nTh"),Ya=[],y=[],z=[],C=[],G,H=function(a){a=a.style;a.paddingTop="0";a.paddingBottom="0";a.borderTopWidth="0";a.borderBottomWidth="0";a.height=0};var D=k.scrollHeight>k.clientHeight;if(a.scrollBarVis!==D&&a.scrollBarVis!==p)a.scrollBarVis=D,aa(a);else{a.scrollBarVis=D;r.children("thead, tfoot").remove();if(T){var E=T.clone().prependTo(r);var F=T.find("tr");E=E.find("tr")}var I=t.clone().prependTo(r);t=t.find("tr");D=I.find("tr");I.find("th, td").removeAttr("tabindex");
|
||||
c||(w.width="100%",h[0].style.width="100%");f.each(ua(a,I),function(b,c){G=ba(a,b);c.style.width=a.aoColumns[G].sWidth});T&&N(function(a){a.style.width=""},E);h=r.outerWidth();""===c?(za.width="100%",x&&(r.find("tbody").height()>k.offsetHeight||"scroll"==m.css("overflow-y"))&&(za.width=B(r.outerWidth()-b)),h=r.outerWidth()):""!==d&&(za.width=B(d),h=r.outerWidth());N(H,D);N(function(a){z.push(a.innerHTML);Ya.push(B(f(a).css("width")))},D);N(function(a,b){-1!==f.inArray(a,ac)&&(a.style.width=Ya[b])},
|
||||
t);f(D).height(0);T&&(N(H,E),N(function(a){C.push(a.innerHTML);y.push(B(f(a).css("width")))},E),N(function(a,b){a.style.width=y[b]},F),f(E).height(0));N(function(a,b){a.innerHTML='<div class="dataTables_sizing">'+z[b]+"</div>";a.childNodes[0].style.height="0";a.childNodes[0].style.overflow="hidden";a.style.width=Ya[b]},D);T&&N(function(a,b){a.innerHTML='<div class="dataTables_sizing">'+C[b]+"</div>";a.childNodes[0].style.height="0";a.childNodes[0].style.overflow="hidden";a.style.width=y[b]},E);r.outerWidth()<
|
||||
h?(F=k.scrollHeight>k.offsetHeight||"scroll"==m.css("overflow-y")?h+b:h,x&&(k.scrollHeight>k.offsetHeight||"scroll"==m.css("overflow-y"))&&(za.width=B(F-b)),""!==c&&""===d||O(a,1,"Possible column misalignment",6)):F="100%";w.width=B(F);g.width=B(F);T&&(a.nScrollFoot.style.width=B(F));!e&&x&&(w.height=B(v.offsetHeight+b));c=r.outerWidth();n[0].style.width=B(c);l.width=B(c);d=r.height()>k.clientHeight||"scroll"==m.css("overflow-y");e="padding"+(A.bScrollbarLeft?"Left":"Right");l[e]=d?b+"px":"0px";T&&
|
||||
(q[0].style.width=B(c),u[0].style.width=B(c),u[0].style[e]=d?b+"px":"0px");r.children("colgroup").insertBefore(r.children("thead"));m.trigger("scroll");!a.bSorted&&!a.bFiltered||a._drawHold||(k.scrollTop=0)}}function N(a,b,c){for(var d=0,e=0,h=b.length,g,k;e<h;){g=b[e].firstChild;for(k=c?c[e].firstChild:null;g;)1===g.nodeType&&(c?a(g,k,d):a(g,d),d++),g=g.nextSibling,k=c?k.nextSibling:null;e++}}function Ja(a){var b=a.nTable,c=a.aoColumns,d=a.oScroll,e=d.sY,h=d.sX,g=d.sXInner,k=c.length,l=oa(a,"bVisible"),
|
||||
n=f("th",a.nTHead),m=b.getAttribute("width"),p=b.parentNode,u=!1,q,t=a.oBrowser;d=t.bScrollOversize;(q=b.style.width)&&-1!==q.indexOf("%")&&(m=q);for(q=0;q<l.length;q++){var r=c[l[q]];null!==r.sWidth&&(r.sWidth=Jb(r.sWidthOrig,p),u=!0)}if(d||!u&&!h&&!e&&k==W(a)&&k==n.length)for(q=0;q<k;q++)l=ba(a,q),null!==l&&(c[l].sWidth=B(n.eq(q).width()));else{k=f(b).clone().css("visibility","hidden").removeAttr("id");k.find("tbody tr").remove();var v=f("<tr/>").appendTo(k.find("tbody"));k.find("thead, tfoot").remove();
|
||||
k.append(f(a.nTHead).clone()).append(f(a.nTFoot).clone());k.find("tfoot th, tfoot td").css("width","");n=ua(a,k.find("thead")[0]);for(q=0;q<l.length;q++)r=c[l[q]],n[q].style.width=null!==r.sWidthOrig&&""!==r.sWidthOrig?B(r.sWidthOrig):"",r.sWidthOrig&&h&&f(n[q]).append(f("<div/>").css({width:r.sWidthOrig,margin:0,padding:0,border:0,height:1}));if(a.aoData.length)for(q=0;q<l.length;q++)u=l[q],r=c[u],f(Kb(a,u)).clone(!1).append(r.sContentPadding).appendTo(v);f("[name]",k).removeAttr("name");r=f("<div/>").css(h||
|
||||
e?{position:"absolute",top:0,left:0,height:1,right:0,overflow:"hidden"}:{}).append(k).appendTo(p);h&&g?k.width(g):h?(k.css("width","auto"),k.removeAttr("width"),k.width()<p.clientWidth&&m&&k.width(p.clientWidth)):e?k.width(p.clientWidth):m&&k.width(m);for(q=e=0;q<l.length;q++)p=f(n[q]),g=p.outerWidth()-p.width(),p=t.bBounding?Math.ceil(n[q].getBoundingClientRect().width):p.outerWidth(),e+=p,c[l[q]].sWidth=B(p-g);b.style.width=B(e);r.remove()}m&&(b.style.width=B(m));!m&&!h||a._reszEvt||(b=function(){f(z).on("resize.DT-"+
|
||||
a.sInstance,Sa(function(){aa(a)}))},d?setTimeout(b,1E3):b(),a._reszEvt=!0)}function Jb(a,b){if(!a)return 0;a=f("<div/>").css("width",B(a)).appendTo(b||y.body);b=a[0].offsetWidth;a.remove();return b}function Kb(a,b){var c=Lb(a,b);if(0>c)return null;var d=a.aoData[c];return d.nTr?d.anCells[b]:f("<td/>").html(I(a,c,b,"display"))[0]}function Lb(a,b){for(var c,d=-1,e=-1,h=0,g=a.aoData.length;h<g;h++)c=I(a,h,b,"display")+"",c=c.replace(bc,""),c=c.replace(/ /g," "),c.length>d&&(d=c.length,e=h);return e}
|
||||
function B(a){return null===a?"0px":"number"==typeof a?0>a?"0px":a+"px":a.match(/\d$/)?a+"px":a}function Y(a){var b=[],c=a.aoColumns;var d=a.aaSortingFixed;var e=f.isPlainObject(d);var h=[];var g=function(a){a.length&&!f.isArray(a[0])?h.push(a):f.merge(h,a)};f.isArray(d)&&g(d);e&&d.pre&&g(d.pre);g(a.aaSorting);e&&d.post&&g(d.post);for(a=0;a<h.length;a++){var k=h[a][0];g=c[k].aDataSort;d=0;for(e=g.length;d<e;d++){var l=g[d];var n=c[l].sType||"string";h[a]._idx===p&&(h[a]._idx=f.inArray(h[a][1],c[l].asSorting));
|
||||
b.push({src:k,col:l,dir:h[a][1],index:h[a]._idx,type:n,formatter:q.ext.type.order[n+"-pre"]})}}return b}function rb(a){var b,c=[],d=q.ext.type.order,e=a.aoData,h=0,g=a.aiDisplayMaster;Ka(a);var k=Y(a);var f=0;for(b=k.length;f<b;f++){var n=k[f];n.formatter&&h++;Mb(a,n.col)}if("ssp"!=D(a)&&0!==k.length){f=0;for(b=g.length;f<b;f++)c[g[f]]=f;h===k.length?g.sort(function(a,b){var d,h=k.length,g=e[a]._aSortData,f=e[b]._aSortData;for(d=0;d<h;d++){var l=k[d];var m=g[l.col];var n=f[l.col];m=m<n?-1:m>n?1:0;
|
||||
if(0!==m)return"asc"===l.dir?m:-m}m=c[a];n=c[b];return m<n?-1:m>n?1:0}):g.sort(function(a,b){var h,g=k.length,f=e[a]._aSortData,l=e[b]._aSortData;for(h=0;h<g;h++){var m=k[h];var n=f[m.col];var p=l[m.col];m=d[m.type+"-"+m.dir]||d["string-"+m.dir];n=m(n,p);if(0!==n)return n}n=c[a];p=c[b];return n<p?-1:n>p?1:0})}a.bSorted=!0}function Nb(a){var b=a.aoColumns,c=Y(a);a=a.oLanguage.oAria;for(var d=0,e=b.length;d<e;d++){var h=b[d];var g=h.asSorting;var k=h.sTitle.replace(/<.*?>/g,"");var f=h.nTh;f.removeAttribute("aria-sort");
|
||||
h.bSortable&&(0<c.length&&c[0].col==d?(f.setAttribute("aria-sort","asc"==c[0].dir?"ascending":"descending"),h=g[c[0].index+1]||g[0]):h=g[0],k+="asc"===h?a.sSortAscending:a.sSortDescending);f.setAttribute("aria-label",k)}}function Za(a,b,c,d){var e=a.aaSorting,h=a.aoColumns[b].asSorting,g=function(a,b){var c=a._idx;c===p&&(c=f.inArray(a[1],h));return c+1<h.length?c+1:b?null:0};"number"===typeof e[0]&&(e=a.aaSorting=[e]);c&&a.oFeatures.bSortMulti?(c=f.inArray(b,J(e,"0")),-1!==c?(b=g(e[c],!0),null===
|
||||
b&&1===e.length&&(b=0),null===b?e.splice(c,1):(e[c][1]=h[b],e[c]._idx=b)):(e.push([b,h[0],0]),e[e.length-1]._idx=0)):e.length&&e[0][0]==b?(b=g(e[0]),e.length=1,e[0][1]=h[b],e[0]._idx=b):(e.length=0,e.push([b,h[0]]),e[0]._idx=0);V(a);"function"==typeof d&&d(a)}function Qa(a,b,c,d){var e=a.aoColumns[c];$a(b,{},function(b){!1!==e.bSortable&&(a.oFeatures.bProcessing?(K(a,!0),setTimeout(function(){Za(a,c,b.shiftKey,d);"ssp"!==D(a)&&K(a,!1)},0)):Za(a,c,b.shiftKey,d))})}function Aa(a){var b=a.aLastSort,
|
||||
c=a.oClasses.sSortColumn,d=Y(a),e=a.oFeatures,h;if(e.bSort&&e.bSortClasses){e=0;for(h=b.length;e<h;e++){var g=b[e].src;f(J(a.aoData,"anCells",g)).removeClass(c+(2>e?e+1:3))}e=0;for(h=d.length;e<h;e++)g=d[e].src,f(J(a.aoData,"anCells",g)).addClass(c+(2>e?e+1:3))}a.aLastSort=d}function Mb(a,b){var c=a.aoColumns[b],d=q.ext.order[c.sSortDataType],e;d&&(e=d.call(a.oInstance,a,b,ca(a,b)));for(var h,g=q.ext.type.order[c.sType+"-pre"],k=0,f=a.aoData.length;k<f;k++)if(c=a.aoData[k],c._aSortData||(c._aSortData=
|
||||
[]),!c._aSortData[b]||d)h=d?e[k]:I(a,k,b,"sort"),c._aSortData[b]=g?g(h):h}function Ba(a){if(a.oFeatures.bStateSave&&!a.bDestroying){var b={time:+new Date,start:a._iDisplayStart,length:a._iDisplayLength,order:f.extend(!0,[],a.aaSorting),search:Fb(a.oPreviousSearch),columns:f.map(a.aoColumns,function(b,d){return{visible:b.bVisible,search:Fb(a.aoPreSearchCols[d])}})};A(a,"aoStateSaveParams","stateSaveParams",[a,b]);a.oSavedState=b;a.fnStateSaveCallback.call(a.oInstance,a,b)}}function Ob(a,b,c){var d,
|
||||
e,h=a.aoColumns;b=function(b){if(b&&b.time){var g=A(a,"aoStateLoadParams","stateLoadParams",[a,b]);if(-1===f.inArray(!1,g)&&(g=a.iStateDuration,!(0<g&&b.time<+new Date-1E3*g||b.columns&&h.length!==b.columns.length))){a.oLoadedState=f.extend(!0,{},b);b.start!==p&&(a._iDisplayStart=b.start,a.iInitDisplayStart=b.start);b.length!==p&&(a._iDisplayLength=b.length);b.order!==p&&(a.aaSorting=[],f.each(b.order,function(b,c){a.aaSorting.push(c[0]>=h.length?[0,c[1]]:c)}));b.search!==p&&f.extend(a.oPreviousSearch,
|
||||
Gb(b.search));if(b.columns)for(d=0,e=b.columns.length;d<e;d++)g=b.columns[d],g.visible!==p&&(h[d].bVisible=g.visible),g.search!==p&&f.extend(a.aoPreSearchCols[d],Gb(g.search));A(a,"aoStateLoaded","stateLoaded",[a,b])}}c()};if(a.oFeatures.bStateSave){var g=a.fnStateLoadCallback.call(a.oInstance,a,b);g!==p&&b(g)}else c()}function Ca(a){var b=q.settings;a=f.inArray(a,J(b,"nTable"));return-1!==a?b[a]:null}function O(a,b,c,d){c="DataTables warning: "+(a?"table id="+a.sTableId+" - ":"")+c;d&&(c+=". For more information about this error, please see http://datatables.net/tn/"+
|
||||
d);if(b)z.console&&console.log&&console.log(c);else if(b=q.ext,b=b.sErrMode||b.errMode,a&&A(a,null,"error",[a,d,c]),"alert"==b)alert(c);else{if("throw"==b)throw Error(c);"function"==typeof b&&b(a,d,c)}}function M(a,b,c,d){f.isArray(c)?f.each(c,function(c,d){f.isArray(d)?M(a,b,d[0],d[1]):M(a,b,d)}):(d===p&&(d=c),b[c]!==p&&(a[d]=b[c]))}function ab(a,b,c){var d;for(d in b)if(b.hasOwnProperty(d)){var e=b[d];f.isPlainObject(e)?(f.isPlainObject(a[d])||(a[d]={}),f.extend(!0,a[d],e)):c&&"data"!==d&&"aaData"!==
|
||||
d&&f.isArray(e)?a[d]=e.slice():a[d]=e}return a}function $a(a,b,c){f(a).on("click.DT",b,function(b){f(a).blur();c(b)}).on("keypress.DT",b,function(a){13===a.which&&(a.preventDefault(),c(a))}).on("selectstart.DT",function(){return!1})}function E(a,b,c,d){c&&a[b].push({fn:c,sName:d})}function A(a,b,c,d){var e=[];b&&(e=f.map(a[b].slice().reverse(),function(b,c){return b.fn.apply(a.oInstance,d)}));null!==c&&(b=f.Event(c+".dt"),f(a.nTable).trigger(b,d),e.push(b.result));return e}function Wa(a){var b=a._iDisplayStart,
|
||||
c=a.fnDisplayEnd(),d=a._iDisplayLength;b>=c&&(b=c-d);b-=b%d;if(-1===d||0>b)b=0;a._iDisplayStart=b}function Ra(a,b){a=a.renderer;var c=q.ext.renderer[b];return f.isPlainObject(a)&&a[b]?c[a[b]]||c._:"string"===typeof a?c[a]||c._:c._}function D(a){return a.oFeatures.bServerSide?"ssp":a.ajax||a.sAjaxSource?"ajax":"dom"}function ka(a,b){var c=Pb.numbers_length,d=Math.floor(c/2);b<=c?a=Z(0,b):a<=d?(a=Z(0,c-2),a.push("ellipsis"),a.push(b-1)):(a>=b-1-d?a=Z(b-(c-2),b):(a=Z(a-d+2,a+d-1),a.push("ellipsis"),
|
||||
a.push(b-1)),a.splice(0,0,"ellipsis"),a.splice(0,0,0));a.DT_el="span";return a}function Ha(a){f.each({num:function(b){return Da(b,a)},"num-fmt":function(b){return Da(b,a,bb)},"html-num":function(b){return Da(b,a,Ea)},"html-num-fmt":function(b){return Da(b,a,Ea,bb)}},function(b,c){C.type.order[b+a+"-pre"]=c;b.match(/^html\-/)&&(C.type.search[b+a]=C.type.search.html)})}function Qb(a){return function(){var b=[Ca(this[q.ext.iApiIndex])].concat(Array.prototype.slice.call(arguments));return q.ext.internal[a].apply(this,
|
||||
b)}}var q=function(a){this.$=function(a,b){return this.api(!0).$(a,b)};this._=function(a,b){return this.api(!0).rows(a,b).data()};this.api=function(a){return a?new v(Ca(this[C.iApiIndex])):new v(this)};this.fnAddData=function(a,b){var c=this.api(!0);a=f.isArray(a)&&(f.isArray(a[0])||f.isPlainObject(a[0]))?c.rows.add(a):c.row.add(a);(b===p||b)&&c.draw();return a.flatten().toArray()};this.fnAdjustColumnSizing=function(a){var b=this.api(!0).columns.adjust(),c=b.settings()[0],d=c.oScroll;a===p||a?b.draw(!1):
|
||||
(""!==d.sX||""!==d.sY)&&na(c)};this.fnClearTable=function(a){var b=this.api(!0).clear();(a===p||a)&&b.draw()};this.fnClose=function(a){this.api(!0).row(a).child.hide()};this.fnDeleteRow=function(a,b,c){var d=this.api(!0);a=d.rows(a);var e=a.settings()[0],h=e.aoData[a[0][0]];a.remove();b&&b.call(this,e,h);(c===p||c)&&d.draw();return h};this.fnDestroy=function(a){this.api(!0).destroy(a)};this.fnDraw=function(a){this.api(!0).draw(a)};this.fnFilter=function(a,b,c,d,e,f){e=this.api(!0);null===b||b===p?
|
||||
e.search(a,c,d,f):e.column(b).search(a,c,d,f);e.draw()};this.fnGetData=function(a,b){var c=this.api(!0);if(a!==p){var d=a.nodeName?a.nodeName.toLowerCase():"";return b!==p||"td"==d||"th"==d?c.cell(a,b).data():c.row(a).data()||null}return c.data().toArray()};this.fnGetNodes=function(a){var b=this.api(!0);return a!==p?b.row(a).node():b.rows().nodes().flatten().toArray()};this.fnGetPosition=function(a){var b=this.api(!0),c=a.nodeName.toUpperCase();return"TR"==c?b.row(a).index():"TD"==c||"TH"==c?(a=b.cell(a).index(),
|
||||
[a.row,a.columnVisible,a.column]):null};this.fnIsOpen=function(a){return this.api(!0).row(a).child.isShown()};this.fnOpen=function(a,b,c){return this.api(!0).row(a).child(b,c).show().child()[0]};this.fnPageChange=function(a,b){a=this.api(!0).page(a);(b===p||b)&&a.draw(!1)};this.fnSetColumnVis=function(a,b,c){a=this.api(!0).column(a).visible(b);(c===p||c)&&a.columns.adjust().draw()};this.fnSettings=function(){return Ca(this[C.iApiIndex])};this.fnSort=function(a){this.api(!0).order(a).draw()};this.fnSortListener=
|
||||
function(a,b,c){this.api(!0).order.listener(a,b,c)};this.fnUpdate=function(a,b,c,d,e){var h=this.api(!0);c===p||null===c?h.row(b).data(a):h.cell(b,c).data(a);(e===p||e)&&h.columns.adjust();(d===p||d)&&h.draw();return 0};this.fnVersionCheck=C.fnVersionCheck;var b=this,c=a===p,d=this.length;c&&(a={});this.oApi=this.internal=C.internal;for(var e in q.ext.internal)e&&(this[e]=Qb(e));this.each(function(){var e={},g=1<d?ab(e,a,!0):a,k=0,l;e=this.getAttribute("id");var n=!1,m=q.defaults,w=f(this);if("table"!=
|
||||
this.nodeName.toLowerCase())O(null,0,"Non-table node initialisation ("+this.nodeName+")",2);else{jb(m);kb(m.column);L(m,m,!0);L(m.column,m.column,!0);L(m,f.extend(g,w.data()),!0);var u=q.settings;k=0;for(l=u.length;k<l;k++){var t=u[k];if(t.nTable==this||t.nTHead&&t.nTHead.parentNode==this||t.nTFoot&&t.nTFoot.parentNode==this){var v=g.bRetrieve!==p?g.bRetrieve:m.bRetrieve;if(c||v)return t.oInstance;if(g.bDestroy!==p?g.bDestroy:m.bDestroy){t.oInstance.fnDestroy();break}else{O(t,0,"Cannot reinitialise DataTable",
|
||||
3);return}}if(t.sTableId==this.id){u.splice(k,1);break}}if(null===e||""===e)this.id=e="DataTables_Table_"+q.ext._unique++;var r=f.extend(!0,{},q.models.oSettings,{sDestroyWidth:w[0].style.width,sInstance:e,sTableId:e});r.nTable=this;r.oApi=b.internal;r.oInit=g;u.push(r);r.oInstance=1===b.length?b:w.dataTable();jb(g);Ga(g.oLanguage);g.aLengthMenu&&!g.iDisplayLength&&(g.iDisplayLength=f.isArray(g.aLengthMenu[0])?g.aLengthMenu[0][0]:g.aLengthMenu[0]);g=ab(f.extend(!0,{},m),g);M(r.oFeatures,g,"bPaginate bLengthChange bFilter bSort bSortMulti bInfo bProcessing bAutoWidth bSortClasses bServerSide bDeferRender".split(" "));
|
||||
M(r,g,["asStripeClasses","ajax","fnServerData","fnFormatNumber","sServerMethod","aaSorting","aaSortingFixed","aLengthMenu","sPaginationType","sAjaxSource","sAjaxDataProp","iStateDuration","sDom","bSortCellsTop","iTabIndex","fnStateLoadCallback","fnStateSaveCallback","renderer","searchDelay","rowId",["iCookieDuration","iStateDuration"],["oSearch","oPreviousSearch"],["aoSearchCols","aoPreSearchCols"],["iDisplayLength","_iDisplayLength"]]);M(r.oScroll,g,[["sScrollX","sX"],["sScrollXInner","sXInner"],
|
||||
["sScrollY","sY"],["bScrollCollapse","bCollapse"]]);M(r.oLanguage,g,"fnInfoCallback");E(r,"aoDrawCallback",g.fnDrawCallback,"user");E(r,"aoServerParams",g.fnServerParams,"user");E(r,"aoStateSaveParams",g.fnStateSaveParams,"user");E(r,"aoStateLoadParams",g.fnStateLoadParams,"user");E(r,"aoStateLoaded",g.fnStateLoaded,"user");E(r,"aoRowCallback",g.fnRowCallback,"user");E(r,"aoRowCreatedCallback",g.fnCreatedRow,"user");E(r,"aoHeaderCallback",g.fnHeaderCallback,"user");E(r,"aoFooterCallback",g.fnFooterCallback,
|
||||
"user");E(r,"aoInitComplete",g.fnInitComplete,"user");E(r,"aoPreDrawCallback",g.fnPreDrawCallback,"user");r.rowIdFn=U(g.rowId);lb(r);var x=r.oClasses;f.extend(x,q.ext.classes,g.oClasses);w.addClass(x.sTable);r.iInitDisplayStart===p&&(r.iInitDisplayStart=g.iDisplayStart,r._iDisplayStart=g.iDisplayStart);null!==g.iDeferLoading&&(r.bDeferLoading=!0,e=f.isArray(g.iDeferLoading),r._iRecordsDisplay=e?g.iDeferLoading[0]:g.iDeferLoading,r._iRecordsTotal=e?g.iDeferLoading[1]:g.iDeferLoading);var y=r.oLanguage;
|
||||
f.extend(!0,y,g.oLanguage);y.sUrl&&(f.ajax({dataType:"json",url:y.sUrl,success:function(a){Ga(a);L(m.oLanguage,a);f.extend(!0,y,a);ja(r)},error:function(){ja(r)}}),n=!0);null===g.asStripeClasses&&(r.asStripeClasses=[x.sStripeOdd,x.sStripeEven]);e=r.asStripeClasses;var z=w.children("tbody").find("tr").eq(0);-1!==f.inArray(!0,f.map(e,function(a,b){return z.hasClass(a)}))&&(f("tbody tr",this).removeClass(e.join(" ")),r.asDestroyStripes=e.slice());e=[];u=this.getElementsByTagName("thead");0!==u.length&&
|
||||
(fa(r.aoHeader,u[0]),e=ua(r));if(null===g.aoColumns)for(u=[],k=0,l=e.length;k<l;k++)u.push(null);else u=g.aoColumns;k=0;for(l=u.length;k<l;k++)Ia(r,e?e[k]:null);nb(r,g.aoColumnDefs,u,function(a,b){ma(r,a,b)});if(z.length){var B=function(a,b){return null!==a.getAttribute("data-"+b)?b:null};f(z[0]).children("th, td").each(function(a,b){var c=r.aoColumns[a];if(c.mData===a){var d=B(b,"sort")||B(b,"order");b=B(b,"filter")||B(b,"search");if(null!==d||null!==b)c.mData={_:a+".display",sort:null!==d?a+".@data-"+
|
||||
d:p,type:null!==d?a+".@data-"+d:p,filter:null!==b?a+".@data-"+b:p},ma(r,a)}})}var C=r.oFeatures;e=function(){if(g.aaSorting===p){var a=r.aaSorting;k=0;for(l=a.length;k<l;k++)a[k][1]=r.aoColumns[k].asSorting[0]}Aa(r);C.bSort&&E(r,"aoDrawCallback",function(){if(r.bSorted){var a=Y(r),b={};f.each(a,function(a,c){b[c.src]=c.dir});A(r,null,"order",[r,a,b]);Nb(r)}});E(r,"aoDrawCallback",function(){(r.bSorted||"ssp"===D(r)||C.bDeferRender)&&Aa(r)},"sc");a=w.children("caption").each(function(){this._captionSide=
|
||||
f(this).css("caption-side")});var b=w.children("thead");0===b.length&&(b=f("<thead/>").appendTo(w));r.nTHead=b[0];b=w.children("tbody");0===b.length&&(b=f("<tbody/>").appendTo(w));r.nTBody=b[0];b=w.children("tfoot");0===b.length&&0<a.length&&(""!==r.oScroll.sX||""!==r.oScroll.sY)&&(b=f("<tfoot/>").appendTo(w));0===b.length||0===b.children().length?w.addClass(x.sNoFooter):0<b.length&&(r.nTFoot=b[0],fa(r.aoFooter,r.nTFoot));if(g.aaData)for(k=0;k<g.aaData.length;k++)R(r,g.aaData[k]);else(r.bDeferLoading||
|
||||
"dom"==D(r))&&pa(r,f(r.nTBody).children("tr"));r.aiDisplay=r.aiDisplayMaster.slice();r.bInitialised=!0;!1===n&&ja(r)};g.bStateSave?(C.bStateSave=!0,E(r,"aoDrawCallback",Ba,"state_save"),Ob(r,g,e)):e()}});b=null;return this},C,t,x,cb={},Rb=/[\r\n\u2028]/g,Ea=/<.*?>/g,cc=/^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/,dc=/(\/|\.|\*|\+|\?|\||\(|\)|\[|\]|\{|\}|\\|\$|\^|\-)/g,bb=/[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfkɃΞ]/gi,P=function(a){return a&&!0!==a&&"-"!==a?!1:
|
||||
!0},Sb=function(a){var b=parseInt(a,10);return!isNaN(b)&&isFinite(a)?b:null},Tb=function(a,b){cb[b]||(cb[b]=new RegExp(Ua(b),"g"));return"string"===typeof a&&"."!==b?a.replace(/\./g,"").replace(cb[b],"."):a},db=function(a,b,c){var d="string"===typeof a;if(P(a))return!0;b&&d&&(a=Tb(a,b));c&&d&&(a=a.replace(bb,""));return!isNaN(parseFloat(a))&&isFinite(a)},Ub=function(a,b,c){return P(a)?!0:P(a)||"string"===typeof a?db(a.replace(Ea,""),b,c)?!0:null:null},J=function(a,b,c){var d=[],e=0,h=a.length;if(c!==
|
||||
p)for(;e<h;e++)a[e]&&a[e][b]&&d.push(a[e][b][c]);else for(;e<h;e++)a[e]&&d.push(a[e][b]);return d},la=function(a,b,c,d){var e=[],h=0,g=b.length;if(d!==p)for(;h<g;h++)a[b[h]][c]&&e.push(a[b[h]][c][d]);else for(;h<g;h++)e.push(a[b[h]][c]);return e},Z=function(a,b){var c=[];if(b===p){b=0;var d=a}else d=b,b=a;for(a=b;a<d;a++)c.push(a);return c},Vb=function(a){for(var b=[],c=0,d=a.length;c<d;c++)a[c]&&b.push(a[c]);return b},ta=function(a){a:{if(!(2>a.length)){var b=a.slice().sort();for(var c=b[0],d=1,
|
||||
e=b.length;d<e;d++){if(b[d]===c){b=!1;break a}c=b[d]}}b=!0}if(b)return a.slice();b=[];e=a.length;var h,g=0;d=0;a:for(;d<e;d++){c=a[d];for(h=0;h<g;h++)if(b[h]===c)continue a;b.push(c);g++}return b};q.util={throttle:function(a,b){var c=b!==p?b:200,d,e;return function(){var b=this,g=+new Date,f=arguments;d&&g<d+c?(clearTimeout(e),e=setTimeout(function(){d=p;a.apply(b,f)},c)):(d=g,a.apply(b,f))}},escapeRegex:function(a){return a.replace(dc,"\\$1")}};var F=function(a,b,c){a[b]!==p&&(a[c]=a[b])},da=/\[.*?\]$/,
|
||||
X=/\(\)$/,Ua=q.util.escapeRegex,ya=f("<div>")[0],$b=ya.textContent!==p,bc=/<.*?>/g,Sa=q.util.throttle,Wb=[],G=Array.prototype,ec=function(a){var b,c=q.settings,d=f.map(c,function(a,b){return a.nTable});if(a){if(a.nTable&&a.oApi)return[a];if(a.nodeName&&"table"===a.nodeName.toLowerCase()){var e=f.inArray(a,d);return-1!==e?[c[e]]:null}if(a&&"function"===typeof a.settings)return a.settings().toArray();"string"===typeof a?b=f(a):a instanceof f&&(b=a)}else return[];if(b)return b.map(function(a){e=f.inArray(this,
|
||||
d);return-1!==e?c[e]:null}).toArray()};var v=function(a,b){if(!(this instanceof v))return new v(a,b);var c=[],d=function(a){(a=ec(a))&&c.push.apply(c,a)};if(f.isArray(a))for(var e=0,h=a.length;e<h;e++)d(a[e]);else d(a);this.context=ta(c);b&&f.merge(this,b);this.selector={rows:null,cols:null,opts:null};v.extend(this,this,Wb)};q.Api=v;f.extend(v.prototype,{any:function(){return 0!==this.count()},concat:G.concat,context:[],count:function(){return this.flatten().length},each:function(a){for(var b=0,c=
|
||||
this.length;b<c;b++)a.call(this,this[b],b,this);return this},eq:function(a){var b=this.context;return b.length>a?new v(b[a],this[a]):null},filter:function(a){var b=[];if(G.filter)b=G.filter.call(this,a,this);else for(var c=0,d=this.length;c<d;c++)a.call(this,this[c],c,this)&&b.push(this[c]);return new v(this.context,b)},flatten:function(){var a=[];return new v(this.context,a.concat.apply(a,this.toArray()))},join:G.join,indexOf:G.indexOf||function(a,b){b=b||0;for(var c=this.length;b<c;b++)if(this[b]===
|
||||
a)return b;return-1},iterator:function(a,b,c,d){var e=[],h,g,f=this.context,l,n=this.selector;"string"===typeof a&&(d=c,c=b,b=a,a=!1);var m=0;for(h=f.length;m<h;m++){var q=new v(f[m]);if("table"===b){var u=c.call(q,f[m],m);u!==p&&e.push(u)}else if("columns"===b||"rows"===b)u=c.call(q,f[m],this[m],m),u!==p&&e.push(u);else if("column"===b||"column-rows"===b||"row"===b||"cell"===b){var t=this[m];"column-rows"===b&&(l=Fa(f[m],n.opts));var x=0;for(g=t.length;x<g;x++)u=t[x],u="cell"===b?c.call(q,f[m],u.row,
|
||||
u.column,m,x):c.call(q,f[m],u,m,x,l),u!==p&&e.push(u)}}return e.length||d?(a=new v(f,a?e.concat.apply([],e):e),b=a.selector,b.rows=n.rows,b.cols=n.cols,b.opts=n.opts,a):this},lastIndexOf:G.lastIndexOf||function(a,b){return this.indexOf.apply(this.toArray.reverse(),arguments)},length:0,map:function(a){var b=[];if(G.map)b=G.map.call(this,a,this);else for(var c=0,d=this.length;c<d;c++)b.push(a.call(this,this[c],c));return new v(this.context,b)},pluck:function(a){return this.map(function(b){return b[a]})},
|
||||
pop:G.pop,push:G.push,reduce:G.reduce||function(a,b){return mb(this,a,b,0,this.length,1)},reduceRight:G.reduceRight||function(a,b){return mb(this,a,b,this.length-1,-1,-1)},reverse:G.reverse,selector:null,shift:G.shift,slice:function(){return new v(this.context,this)},sort:G.sort,splice:G.splice,toArray:function(){return G.slice.call(this)},to$:function(){return f(this)},toJQuery:function(){return f(this)},unique:function(){return new v(this.context,ta(this))},unshift:G.unshift});v.extend=function(a,
|
||||
b,c){if(c.length&&b&&(b instanceof v||b.__dt_wrapper)){var d,e=function(a,b,c){return function(){var d=b.apply(a,arguments);v.extend(d,d,c.methodExt);return d}};var h=0;for(d=c.length;h<d;h++){var g=c[h];b[g.name]="function"===g.type?e(a,g.val,g):"object"===g.type?{}:g.val;b[g.name].__dt_wrapper=!0;v.extend(a,b[g.name],g.propExt)}}};v.register=t=function(a,b){if(f.isArray(a))for(var c=0,d=a.length;c<d;c++)v.register(a[c],b);else{d=a.split(".");var e=Wb,h;a=0;for(c=d.length;a<c;a++){var g=(h=-1!==
|
||||
d[a].indexOf("()"))?d[a].replace("()",""):d[a];a:{var k=0;for(var l=e.length;k<l;k++)if(e[k].name===g){k=e[k];break a}k=null}k||(k={name:g,val:{},methodExt:[],propExt:[],type:"object"},e.push(k));a===c-1?(k.val=b,k.type="function"===typeof b?"function":f.isPlainObject(b)?"object":"other"):e=h?k.methodExt:k.propExt}}};v.registerPlural=x=function(a,b,c){v.register(a,c);v.register(b,function(){var a=c.apply(this,arguments);return a===this?this:a instanceof v?a.length?f.isArray(a[0])?new v(a.context,
|
||||
a[0]):a[0]:p:a})};var fc=function(a,b){if("number"===typeof a)return[b[a]];var c=f.map(b,function(a,b){return a.nTable});return f(c).filter(a).map(function(a){a=f.inArray(this,c);return b[a]}).toArray()};t("tables()",function(a){return a?new v(fc(a,this.context)):this});t("table()",function(a){a=this.tables(a);var b=a.context;return b.length?new v(b[0]):a});x("tables().nodes()","table().node()",function(){return this.iterator("table",function(a){return a.nTable},1)});x("tables().body()","table().body()",
|
||||
function(){return this.iterator("table",function(a){return a.nTBody},1)});x("tables().header()","table().header()",function(){return this.iterator("table",function(a){return a.nTHead},1)});x("tables().footer()","table().footer()",function(){return this.iterator("table",function(a){return a.nTFoot},1)});x("tables().containers()","table().container()",function(){return this.iterator("table",function(a){return a.nTableWrapper},1)});t("draw()",function(a){return this.iterator("table",function(b){"page"===
|
||||
a?S(b):("string"===typeof a&&(a="full-hold"===a?!1:!0),V(b,!1===a))})});t("page()",function(a){return a===p?this.page.info().page:this.iterator("table",function(b){Xa(b,a)})});t("page.info()",function(a){if(0===this.context.length)return p;a=this.context[0];var b=a._iDisplayStart,c=a.oFeatures.bPaginate?a._iDisplayLength:-1,d=a.fnRecordsDisplay(),e=-1===c;return{page:e?0:Math.floor(b/c),pages:e?1:Math.ceil(d/c),start:b,end:a.fnDisplayEnd(),length:c,recordsTotal:a.fnRecordsTotal(),recordsDisplay:d,
|
||||
serverSide:"ssp"===D(a)}});t("page.len()",function(a){return a===p?0!==this.context.length?this.context[0]._iDisplayLength:p:this.iterator("table",function(b){Va(b,a)})});var Xb=function(a,b,c){if(c){var d=new v(a);d.one("draw",function(){c(d.ajax.json())})}if("ssp"==D(a))V(a,b);else{K(a,!0);var e=a.jqXHR;e&&4!==e.readyState&&e.abort();va(a,[],function(c){qa(a);c=wa(a,c);for(var d=0,e=c.length;d<e;d++)R(a,c[d]);V(a,b);K(a,!1)})}};t("ajax.json()",function(){var a=this.context;if(0<a.length)return a[0].json});
|
||||
t("ajax.params()",function(){var a=this.context;if(0<a.length)return a[0].oAjaxData});t("ajax.reload()",function(a,b){return this.iterator("table",function(c){Xb(c,!1===b,a)})});t("ajax.url()",function(a){var b=this.context;if(a===p){if(0===b.length)return p;b=b[0];return b.ajax?f.isPlainObject(b.ajax)?b.ajax.url:b.ajax:b.sAjaxSource}return this.iterator("table",function(b){f.isPlainObject(b.ajax)?b.ajax.url=a:b.ajax=a})});t("ajax.url().load()",function(a,b){return this.iterator("table",function(c){Xb(c,
|
||||
!1===b,a)})});var eb=function(a,b,c,d,e){var h=[],g,k,l;var n=typeof b;b&&"string"!==n&&"function"!==n&&b.length!==p||(b=[b]);n=0;for(k=b.length;n<k;n++){var m=b[n]&&b[n].split&&!b[n].match(/[\[\(:]/)?b[n].split(","):[b[n]];var q=0;for(l=m.length;q<l;q++)(g=c("string"===typeof m[q]?f.trim(m[q]):m[q]))&&g.length&&(h=h.concat(g))}a=C.selector[a];if(a.length)for(n=0,k=a.length;n<k;n++)h=a[n](d,e,h);return ta(h)},fb=function(a){a||(a={});a.filter&&a.search===p&&(a.search=a.filter);return f.extend({search:"none",
|
||||
order:"current",page:"all"},a)},gb=function(a){for(var b=0,c=a.length;b<c;b++)if(0<a[b].length)return a[0]=a[b],a[0].length=1,a.length=1,a.context=[a.context[b]],a;a.length=0;return a},Fa=function(a,b){var c=[],d=a.aiDisplay;var e=a.aiDisplayMaster;var h=b.search;var g=b.order;b=b.page;if("ssp"==D(a))return"removed"===h?[]:Z(0,e.length);if("current"==b)for(g=a._iDisplayStart,a=a.fnDisplayEnd();g<a;g++)c.push(d[g]);else if("current"==g||"applied"==g)if("none"==h)c=e.slice();else if("applied"==h)c=
|
||||
d.slice();else{if("removed"==h){var k={};g=0;for(a=d.length;g<a;g++)k[d[g]]=null;c=f.map(e,function(a){return k.hasOwnProperty(a)?null:a})}}else if("index"==g||"original"==g)for(g=0,a=a.aoData.length;g<a;g++)"none"==h?c.push(g):(e=f.inArray(g,d),(-1===e&&"removed"==h||0<=e&&"applied"==h)&&c.push(g));return c},gc=function(a,b,c){var d;return eb("row",b,function(b){var e=Sb(b),g=a.aoData;if(null!==e&&!c)return[e];d||(d=Fa(a,c));if(null!==e&&-1!==f.inArray(e,d))return[e];if(null===b||b===p||""===b)return d;
|
||||
if("function"===typeof b)return f.map(d,function(a){var c=g[a];return b(a,c._aData,c.nTr)?a:null});if(b.nodeName){e=b._DT_RowIndex;var k=b._DT_CellIndex;if(e!==p)return g[e]&&g[e].nTr===b?[e]:[];if(k)return g[k.row]&&g[k.row].nTr===b.parentNode?[k.row]:[];e=f(b).closest("*[data-dt-row]");return e.length?[e.data("dt-row")]:[]}if("string"===typeof b&&"#"===b.charAt(0)&&(e=a.aIds[b.replace(/^#/,"")],e!==p))return[e.idx];e=Vb(la(a.aoData,d,"nTr"));return f(e).filter(b).map(function(){return this._DT_RowIndex}).toArray()},
|
||||
a,c)};t("rows()",function(a,b){a===p?a="":f.isPlainObject(a)&&(b=a,a="");b=fb(b);var c=this.iterator("table",function(c){return gc(c,a,b)},1);c.selector.rows=a;c.selector.opts=b;return c});t("rows().nodes()",function(){return this.iterator("row",function(a,b){return a.aoData[b].nTr||p},1)});t("rows().data()",function(){return this.iterator(!0,"rows",function(a,b){return la(a.aoData,b,"_aData")},1)});x("rows().cache()","row().cache()",function(a){return this.iterator("row",function(b,c){b=b.aoData[c];
|
||||
return"search"===a?b._aFilterData:b._aSortData},1)});x("rows().invalidate()","row().invalidate()",function(a){return this.iterator("row",function(b,c){ea(b,c,a)})});x("rows().indexes()","row().index()",function(){return this.iterator("row",function(a,b){return b},1)});x("rows().ids()","row().id()",function(a){for(var b=[],c=this.context,d=0,e=c.length;d<e;d++)for(var h=0,g=this[d].length;h<g;h++){var f=c[d].rowIdFn(c[d].aoData[this[d][h]]._aData);b.push((!0===a?"#":"")+f)}return new v(c,b)});x("rows().remove()",
|
||||
"row().remove()",function(){var a=this;this.iterator("row",function(b,c,d){var e=b.aoData,h=e[c],g,f;e.splice(c,1);var l=0;for(g=e.length;l<g;l++){var n=e[l];var m=n.anCells;null!==n.nTr&&(n.nTr._DT_RowIndex=l);if(null!==m)for(n=0,f=m.length;n<f;n++)m[n]._DT_CellIndex.row=l}ra(b.aiDisplayMaster,c);ra(b.aiDisplay,c);ra(a[d],c,!1);0<b._iRecordsDisplay&&b._iRecordsDisplay--;Wa(b);c=b.rowIdFn(h._aData);c!==p&&delete b.aIds[c]});this.iterator("table",function(a){for(var b=0,d=a.aoData.length;b<d;b++)a.aoData[b].idx=
|
||||
b});return this});t("rows.add()",function(a){var b=this.iterator("table",function(b){var c,d=[];var g=0;for(c=a.length;g<c;g++){var f=a[g];f.nodeName&&"TR"===f.nodeName.toUpperCase()?d.push(pa(b,f)[0]):d.push(R(b,f))}return d},1),c=this.rows(-1);c.pop();f.merge(c,b);return c});t("row()",function(a,b){return gb(this.rows(a,b))});t("row().data()",function(a){var b=this.context;if(a===p)return b.length&&this.length?b[0].aoData[this[0]]._aData:p;var c=b[0].aoData[this[0]];c._aData=a;f.isArray(a)&&c.nTr.id&&
|
||||
Q(b[0].rowId)(a,c.nTr.id);ea(b[0],this[0],"data");return this});t("row().node()",function(){var a=this.context;return a.length&&this.length?a[0].aoData[this[0]].nTr||null:null});t("row.add()",function(a){a instanceof f&&a.length&&(a=a[0]);var b=this.iterator("table",function(b){return a.nodeName&&"TR"===a.nodeName.toUpperCase()?pa(b,a)[0]:R(b,a)});return this.row(b[0])});var hc=function(a,b,c,d){var e=[],h=function(b,c){if(f.isArray(b)||b instanceof f)for(var d=0,g=b.length;d<g;d++)h(b[d],c);else b.nodeName&&
|
||||
"tr"===b.nodeName.toLowerCase()?e.push(b):(d=f("<tr><td/></tr>").addClass(c),f("td",d).addClass(c).html(b)[0].colSpan=W(a),e.push(d[0]))};h(c,d);b._details&&b._details.detach();b._details=f(e);b._detailsShow&&b._details.insertAfter(b.nTr)},hb=function(a,b){var c=a.context;c.length&&(a=c[0].aoData[b!==p?b:a[0]])&&a._details&&(a._details.remove(),a._detailsShow=p,a._details=p)},Yb=function(a,b){var c=a.context;c.length&&a.length&&(a=c[0].aoData[a[0]],a._details&&((a._detailsShow=b)?a._details.insertAfter(a.nTr):
|
||||
a._details.detach(),ic(c[0])))},ic=function(a){var b=new v(a),c=a.aoData;b.off("draw.dt.DT_details column-visibility.dt.DT_details destroy.dt.DT_details");0<J(c,"_details").length&&(b.on("draw.dt.DT_details",function(d,e){a===e&&b.rows({page:"current"}).eq(0).each(function(a){a=c[a];a._detailsShow&&a._details.insertAfter(a.nTr)})}),b.on("column-visibility.dt.DT_details",function(b,e,f,g){if(a===e)for(e=W(e),f=0,g=c.length;f<g;f++)b=c[f],b._details&&b._details.children("td[colspan]").attr("colspan",
|
||||
e)}),b.on("destroy.dt.DT_details",function(d,e){if(a===e)for(d=0,e=c.length;d<e;d++)c[d]._details&&hb(b,d)}))};t("row().child()",function(a,b){var c=this.context;if(a===p)return c.length&&this.length?c[0].aoData[this[0]]._details:p;!0===a?this.child.show():!1===a?hb(this):c.length&&this.length&&hc(c[0],c[0].aoData[this[0]],a,b);return this});t(["row().child.show()","row().child().show()"],function(a){Yb(this,!0);return this});t(["row().child.hide()","row().child().hide()"],function(){Yb(this,!1);
|
||||
return this});t(["row().child.remove()","row().child().remove()"],function(){hb(this);return this});t("row().child.isShown()",function(){var a=this.context;return a.length&&this.length?a[0].aoData[this[0]]._detailsShow||!1:!1});var jc=/^([^:]+):(name|visIdx|visible)$/,Zb=function(a,b,c,d,e){c=[];d=0;for(var f=e.length;d<f;d++)c.push(I(a,e[d],b));return c},kc=function(a,b,c){var d=a.aoColumns,e=J(d,"sName"),h=J(d,"nTh");return eb("column",b,function(b){var g=Sb(b);if(""===b)return Z(d.length);if(null!==
|
||||
g)return[0<=g?g:d.length+g];if("function"===typeof b){var l=Fa(a,c);return f.map(d,function(c,d){return b(d,Zb(a,d,0,0,l),h[d])?d:null})}var n="string"===typeof b?b.match(jc):"";if(n)switch(n[2]){case "visIdx":case "visible":g=parseInt(n[1],10);if(0>g){var m=f.map(d,function(a,b){return a.bVisible?b:null});return[m[m.length+g]]}return[ba(a,g)];case "name":return f.map(e,function(a,b){return a===n[1]?b:null});default:return[]}if(b.nodeName&&b._DT_CellIndex)return[b._DT_CellIndex.column];g=f(h).filter(b).map(function(){return f.inArray(this,
|
||||
h)}).toArray();if(g.length||!b.nodeName)return g;g=f(b).closest("*[data-dt-column]");return g.length?[g.data("dt-column")]:[]},a,c)};t("columns()",function(a,b){a===p?a="":f.isPlainObject(a)&&(b=a,a="");b=fb(b);var c=this.iterator("table",function(c){return kc(c,a,b)},1);c.selector.cols=a;c.selector.opts=b;return c});x("columns().header()","column().header()",function(a,b){return this.iterator("column",function(a,b){return a.aoColumns[b].nTh},1)});x("columns().footer()","column().footer()",function(a,
|
||||
b){return this.iterator("column",function(a,b){return a.aoColumns[b].nTf},1)});x("columns().data()","column().data()",function(){return this.iterator("column-rows",Zb,1)});x("columns().dataSrc()","column().dataSrc()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].mData},1)});x("columns().cache()","column().cache()",function(a){return this.iterator("column-rows",function(b,c,d,e,f){return la(b.aoData,f,"search"===a?"_aFilterData":"_aSortData",c)},1)});x("columns().nodes()",
|
||||
"column().nodes()",function(){return this.iterator("column-rows",function(a,b,c,d,e){return la(a.aoData,e,"anCells",b)},1)});x("columns().visible()","column().visible()",function(a,b){var c=this,d=this.iterator("column",function(b,c){if(a===p)return b.aoColumns[c].bVisible;var d=b.aoColumns,e=d[c],h=b.aoData,n;if(a!==p&&e.bVisible!==a){if(a){var m=f.inArray(!0,J(d,"bVisible"),c+1);d=0;for(n=h.length;d<n;d++){var q=h[d].nTr;b=h[d].anCells;q&&q.insertBefore(b[c],b[m]||null)}}else f(J(b.aoData,"anCells",
|
||||
c)).detach();e.bVisible=a}});a!==p&&this.iterator("table",function(d){ha(d,d.aoHeader);ha(d,d.aoFooter);d.aiDisplay.length||f(d.nTBody).find("td[colspan]").attr("colspan",W(d));Ba(d);c.iterator("column",function(c,d){A(c,null,"column-visibility",[c,d,a,b])});(b===p||b)&&c.columns.adjust()});return d});x("columns().indexes()","column().index()",function(a){return this.iterator("column",function(b,c){return"visible"===a?ca(b,c):c},1)});t("columns.adjust()",function(){return this.iterator("table",function(a){aa(a)},
|
||||
1)});t("column.index()",function(a,b){if(0!==this.context.length){var c=this.context[0];if("fromVisible"===a||"toData"===a)return ba(c,b);if("fromData"===a||"toVisible"===a)return ca(c,b)}});t("column()",function(a,b){return gb(this.columns(a,b))});var lc=function(a,b,c){var d=a.aoData,e=Fa(a,c),h=Vb(la(d,e,"anCells")),g=f([].concat.apply([],h)),k,l=a.aoColumns.length,n,m,q,u,t,v;return eb("cell",b,function(b){var c="function"===typeof b;if(null===b||b===p||c){n=[];m=0;for(q=e.length;m<q;m++)for(k=
|
||||
e[m],u=0;u<l;u++)t={row:k,column:u},c?(v=d[k],b(t,I(a,k,u),v.anCells?v.anCells[u]:null)&&n.push(t)):n.push(t);return n}if(f.isPlainObject(b))return b.column!==p&&b.row!==p&&-1!==f.inArray(b.row,e)?[b]:[];c=g.filter(b).map(function(a,b){return{row:b._DT_CellIndex.row,column:b._DT_CellIndex.column}}).toArray();if(c.length||!b.nodeName)return c;v=f(b).closest("*[data-dt-row]");return v.length?[{row:v.data("dt-row"),column:v.data("dt-column")}]:[]},a,c)};t("cells()",function(a,b,c){f.isPlainObject(a)&&
|
||||
(a.row===p?(c=a,a=null):(c=b,b=null));f.isPlainObject(b)&&(c=b,b=null);if(null===b||b===p)return this.iterator("table",function(b){return lc(b,a,fb(c))});var d=c?{page:c.page,order:c.order,search:c.search}:{},e=this.columns(b,d),h=this.rows(a,d),g,k,l,n;d=this.iterator("table",function(a,b){a=[];g=0;for(k=h[b].length;g<k;g++)for(l=0,n=e[b].length;l<n;l++)a.push({row:h[b][g],column:e[b][l]});return a},1);d=c&&c.selected?this.cells(d,c):d;f.extend(d.selector,{cols:b,rows:a,opts:c});return d});x("cells().nodes()",
|
||||
"cell().node()",function(){return this.iterator("cell",function(a,b,c){return(a=a.aoData[b])&&a.anCells?a.anCells[c]:p},1)});t("cells().data()",function(){return this.iterator("cell",function(a,b,c){return I(a,b,c)},1)});x("cells().cache()","cell().cache()",function(a){a="search"===a?"_aFilterData":"_aSortData";return this.iterator("cell",function(b,c,d){return b.aoData[c][a][d]},1)});x("cells().render()","cell().render()",function(a){return this.iterator("cell",function(b,c,d){return I(b,c,d,a)},
|
||||
1)});x("cells().indexes()","cell().index()",function(){return this.iterator("cell",function(a,b,c){return{row:b,column:c,columnVisible:ca(a,c)}},1)});x("cells().invalidate()","cell().invalidate()",function(a){return this.iterator("cell",function(b,c,d){ea(b,c,a,d)})});t("cell()",function(a,b,c){return gb(this.cells(a,b,c))});t("cell().data()",function(a){var b=this.context,c=this[0];if(a===p)return b.length&&c.length?I(b[0],c[0].row,c[0].column):p;ob(b[0],c[0].row,c[0].column,a);ea(b[0],c[0].row,
|
||||
"data",c[0].column);return this});t("order()",function(a,b){var c=this.context;if(a===p)return 0!==c.length?c[0].aaSorting:p;"number"===typeof a?a=[[a,b]]:a.length&&!f.isArray(a[0])&&(a=Array.prototype.slice.call(arguments));return this.iterator("table",function(b){b.aaSorting=a.slice()})});t("order.listener()",function(a,b,c){return this.iterator("table",function(d){Qa(d,a,b,c)})});t("order.fixed()",function(a){if(!a){var b=this.context;b=b.length?b[0].aaSortingFixed:p;return f.isArray(b)?{pre:b}:
|
||||
b}return this.iterator("table",function(b){b.aaSortingFixed=f.extend(!0,{},a)})});t(["columns().order()","column().order()"],function(a){var b=this;return this.iterator("table",function(c,d){var e=[];f.each(b[d],function(b,c){e.push([c,a])});c.aaSorting=e})});t("search()",function(a,b,c,d){var e=this.context;return a===p?0!==e.length?e[0].oPreviousSearch.sSearch:p:this.iterator("table",function(e){e.oFeatures.bFilter&&ia(e,f.extend({},e.oPreviousSearch,{sSearch:a+"",bRegex:null===b?!1:b,bSmart:null===
|
||||
c?!0:c,bCaseInsensitive:null===d?!0:d}),1)})});x("columns().search()","column().search()",function(a,b,c,d){return this.iterator("column",function(e,h){var g=e.aoPreSearchCols;if(a===p)return g[h].sSearch;e.oFeatures.bFilter&&(f.extend(g[h],{sSearch:a+"",bRegex:null===b?!1:b,bSmart:null===c?!0:c,bCaseInsensitive:null===d?!0:d}),ia(e,e.oPreviousSearch,1))})});t("state()",function(){return this.context.length?this.context[0].oSavedState:null});t("state.clear()",function(){return this.iterator("table",
|
||||
function(a){a.fnStateSaveCallback.call(a.oInstance,a,{})})});t("state.loaded()",function(){return this.context.length?this.context[0].oLoadedState:null});t("state.save()",function(){return this.iterator("table",function(a){Ba(a)})});q.versionCheck=q.fnVersionCheck=function(a){var b=q.version.split(".");a=a.split(".");for(var c,d,e=0,f=a.length;e<f;e++)if(c=parseInt(b[e],10)||0,d=parseInt(a[e],10)||0,c!==d)return c>d;return!0};q.isDataTable=q.fnIsDataTable=function(a){var b=f(a).get(0),c=!1;if(a instanceof
|
||||
q.Api)return!0;f.each(q.settings,function(a,e){a=e.nScrollHead?f("table",e.nScrollHead)[0]:null;var d=e.nScrollFoot?f("table",e.nScrollFoot)[0]:null;if(e.nTable===b||a===b||d===b)c=!0});return c};q.tables=q.fnTables=function(a){var b=!1;f.isPlainObject(a)&&(b=a.api,a=a.visible);var c=f.map(q.settings,function(b){if(!a||a&&f(b.nTable).is(":visible"))return b.nTable});return b?new v(c):c};q.camelToHungarian=L;t("$()",function(a,b){b=this.rows(b).nodes();b=f(b);return f([].concat(b.filter(a).toArray(),
|
||||
b.find(a).toArray()))});f.each(["on","one","off"],function(a,b){t(b+"()",function(){var a=Array.prototype.slice.call(arguments);a[0]=f.map(a[0].split(/\s/),function(a){return a.match(/\.dt\b/)?a:a+".dt"}).join(" ");var d=f(this.tables().nodes());d[b].apply(d,a);return this})});t("clear()",function(){return this.iterator("table",function(a){qa(a)})});t("settings()",function(){return new v(this.context,this.context)});t("init()",function(){var a=this.context;return a.length?a[0].oInit:null});t("data()",
|
||||
function(){return this.iterator("table",function(a){return J(a.aoData,"_aData")}).flatten()});t("destroy()",function(a){a=a||!1;return this.iterator("table",function(b){var c=b.nTableWrapper.parentNode,d=b.oClasses,e=b.nTable,h=b.nTBody,g=b.nTHead,k=b.nTFoot,l=f(e);h=f(h);var n=f(b.nTableWrapper),m=f.map(b.aoData,function(a){return a.nTr}),p;b.bDestroying=!0;A(b,"aoDestroyCallback","destroy",[b]);a||(new v(b)).columns().visible(!0);n.off(".DT").find(":not(tbody *)").off(".DT");f(z).off(".DT-"+b.sInstance);
|
||||
e!=g.parentNode&&(l.children("thead").detach(),l.append(g));k&&e!=k.parentNode&&(l.children("tfoot").detach(),l.append(k));b.aaSorting=[];b.aaSortingFixed=[];Aa(b);f(m).removeClass(b.asStripeClasses.join(" "));f("th, td",g).removeClass(d.sSortable+" "+d.sSortableAsc+" "+d.sSortableDesc+" "+d.sSortableNone);h.children().detach();h.append(m);g=a?"remove":"detach";l[g]();n[g]();!a&&c&&(c.insertBefore(e,b.nTableReinsertBefore),l.css("width",b.sDestroyWidth).removeClass(d.sTable),(p=b.asDestroyStripes.length)&&
|
||||
h.children().each(function(a){f(this).addClass(b.asDestroyStripes[a%p])}));c=f.inArray(b,q.settings);-1!==c&&q.settings.splice(c,1)})});f.each(["column","row","cell"],function(a,b){t(b+"s().every()",function(a){var c=this.selector.opts,e=this;return this.iterator(b,function(d,f,k,l,n){a.call(e[b](f,"cell"===b?k:c,"cell"===b?c:p),f,k,l,n)})})});t("i18n()",function(a,b,c){var d=this.context[0];a=U(a)(d.oLanguage);a===p&&(a=b);c!==p&&f.isPlainObject(a)&&(a=a[c]!==p?a[c]:a._);return a.replace("%d",c)});
|
||||
q.version="1.10.20";q.settings=[];q.models={};q.models.oSearch={bCaseInsensitive:!0,sSearch:"",bRegex:!1,bSmart:!0};q.models.oRow={nTr:null,anCells:null,_aData:[],_aSortData:null,_aFilterData:null,_sFilterRow:null,_sRowStripe:"",src:null,idx:-1};q.models.oColumn={idx:null,aDataSort:null,asSorting:null,bSearchable:null,bSortable:null,bVisible:null,_sManualType:null,_bAttrSrc:!1,fnCreatedCell:null,fnGetData:null,fnSetData:null,mData:null,mRender:null,nTh:null,nTf:null,sClass:null,sContentPadding:null,
|
||||
sDefaultContent:null,sName:null,sSortDataType:"std",sSortingClass:null,sSortingClassJUI:null,sTitle:null,sType:null,sWidth:null,sWidthOrig:null};q.defaults={aaData:null,aaSorting:[[0,"asc"]],aaSortingFixed:[],ajax:null,aLengthMenu:[10,25,50,100],aoColumns:null,aoColumnDefs:null,aoSearchCols:[],asStripeClasses:null,bAutoWidth:!0,bDeferRender:!1,bDestroy:!1,bFilter:!0,bInfo:!0,bLengthChange:!0,bPaginate:!0,bProcessing:!1,bRetrieve:!1,bScrollCollapse:!1,bServerSide:!1,bSort:!0,bSortMulti:!0,bSortCellsTop:!1,
|
||||
bSortClasses:!0,bStateSave:!1,fnCreatedRow:null,fnDrawCallback:null,fnFooterCallback:null,fnFormatNumber:function(a){return a.toString().replace(/\B(?=(\d{3})+(?!\d))/g,this.oLanguage.sThousands)},fnHeaderCallback:null,fnInfoCallback:null,fnInitComplete:null,fnPreDrawCallback:null,fnRowCallback:null,fnServerData:null,fnServerParams:null,fnStateLoadCallback:function(a){try{return JSON.parse((-1===a.iStateDuration?sessionStorage:localStorage).getItem("DataTables_"+a.sInstance+"_"+location.pathname))}catch(b){}},
|
||||
fnStateLoadParams:null,fnStateLoaded:null,fnStateSaveCallback:function(a,b){try{(-1===a.iStateDuration?sessionStorage:localStorage).setItem("DataTables_"+a.sInstance+"_"+location.pathname,JSON.stringify(b))}catch(c){}},fnStateSaveParams:null,iStateDuration:7200,iDeferLoading:null,iDisplayLength:10,iDisplayStart:0,iTabIndex:0,oClasses:{},oLanguage:{oAria:{sSortAscending:": activate to sort column ascending",sSortDescending:": activate to sort column descending"},oPaginate:{sFirst:"First",sLast:"Last",
|
||||
sNext:"Next",sPrevious:"Previous"},sEmptyTable:"No data available in table",sInfo:"Showing _START_ to _END_ of _TOTAL_ entries",sInfoEmpty:"Showing 0 to 0 of 0 entries",sInfoFiltered:"(filtered from _MAX_ total entries)",sInfoPostFix:"",sDecimal:"",sThousands:",",sLengthMenu:"Show _MENU_ entries",sLoadingRecords:"Loading...",sProcessing:"Processing...",sSearch:"Search:",sSearchPlaceholder:"",sUrl:"",sZeroRecords:"No matching records found"},oSearch:f.extend({},q.models.oSearch),sAjaxDataProp:"data",
|
||||
sAjaxSource:null,sDom:"lfrtip",searchDelay:null,sPaginationType:"simple_numbers",sScrollX:"",sScrollXInner:"",sScrollY:"",sServerMethod:"GET",renderer:null,rowId:"DT_RowId"};H(q.defaults);q.defaults.column={aDataSort:null,iDataSort:-1,asSorting:["asc","desc"],bSearchable:!0,bSortable:!0,bVisible:!0,fnCreatedCell:null,mData:null,mRender:null,sCellType:"td",sClass:"",sContentPadding:"",sDefaultContent:null,sName:"",sSortDataType:"std",sTitle:null,sType:null,sWidth:null};H(q.defaults.column);q.models.oSettings=
|
||||
{oFeatures:{bAutoWidth:null,bDeferRender:null,bFilter:null,bInfo:null,bLengthChange:null,bPaginate:null,bProcessing:null,bServerSide:null,bSort:null,bSortMulti:null,bSortClasses:null,bStateSave:null},oScroll:{bCollapse:null,iBarWidth:0,sX:null,sXInner:null,sY:null},oLanguage:{fnInfoCallback:null},oBrowser:{bScrollOversize:!1,bScrollbarLeft:!1,bBounding:!1,barWidth:0},ajax:null,aanFeatures:[],aoData:[],aiDisplay:[],aiDisplayMaster:[],aIds:{},aoColumns:[],aoHeader:[],aoFooter:[],oPreviousSearch:{},
|
||||
aoPreSearchCols:[],aaSorting:null,aaSortingFixed:[],asStripeClasses:null,asDestroyStripes:[],sDestroyWidth:0,aoRowCallback:[],aoHeaderCallback:[],aoFooterCallback:[],aoDrawCallback:[],aoRowCreatedCallback:[],aoPreDrawCallback:[],aoInitComplete:[],aoStateSaveParams:[],aoStateLoadParams:[],aoStateLoaded:[],sTableId:"",nTable:null,nTHead:null,nTFoot:null,nTBody:null,nTableWrapper:null,bDeferLoading:!1,bInitialised:!1,aoOpenRows:[],sDom:null,searchDelay:null,sPaginationType:"two_button",iStateDuration:0,
|
||||
aoStateSave:[],aoStateLoad:[],oSavedState:null,oLoadedState:null,sAjaxSource:null,sAjaxDataProp:null,bAjaxDataGet:!0,jqXHR:null,json:p,oAjaxData:p,fnServerData:null,aoServerParams:[],sServerMethod:null,fnFormatNumber:null,aLengthMenu:null,iDraw:0,bDrawing:!1,iDrawError:-1,_iDisplayLength:10,_iDisplayStart:0,_iRecordsTotal:0,_iRecordsDisplay:0,oClasses:{},bFiltered:!1,bSorted:!1,bSortCellsTop:null,oInit:null,aoDestroyCallback:[],fnRecordsTotal:function(){return"ssp"==D(this)?1*this._iRecordsTotal:
|
||||
this.aiDisplayMaster.length},fnRecordsDisplay:function(){return"ssp"==D(this)?1*this._iRecordsDisplay:this.aiDisplay.length},fnDisplayEnd:function(){var a=this._iDisplayLength,b=this._iDisplayStart,c=b+a,d=this.aiDisplay.length,e=this.oFeatures,f=e.bPaginate;return e.bServerSide?!1===f||-1===a?b+d:Math.min(b+a,this._iRecordsDisplay):!f||c>d||-1===a?d:c},oInstance:null,sInstance:null,iTabIndex:0,nScrollHead:null,nScrollFoot:null,aLastSort:[],oPlugins:{},rowIdFn:null,rowId:null};q.ext=C={buttons:{},
|
||||
classes:{},builder:"-source-",errMode:"alert",feature:[],search:[],selector:{cell:[],column:[],row:[]},internal:{},legacy:{ajax:null},pager:{},renderer:{pageButton:{},header:{}},order:{},type:{detect:[],search:{},order:{}},_unique:0,fnVersionCheck:q.fnVersionCheck,iApiIndex:0,oJUIClasses:{},sVersion:q.version};f.extend(C,{afnFiltering:C.search,aTypes:C.type.detect,ofnSearch:C.type.search,oSort:C.type.order,afnSortData:C.order,aoFeatures:C.feature,oApi:C.internal,oStdClasses:C.classes,oPagination:C.pager});
|
||||
f.extend(q.ext.classes,{sTable:"dataTable",sNoFooter:"no-footer",sPageButton:"paginate_button",sPageButtonActive:"current",sPageButtonDisabled:"disabled",sStripeOdd:"odd",sStripeEven:"even",sRowEmpty:"dataTables_empty",sWrapper:"dataTables_wrapper",sFilter:"dataTables_filter",sInfo:"dataTables_info",sPaging:"dataTables_paginate paging_",sLength:"dataTables_length",sProcessing:"dataTables_processing",sSortAsc:"sorting_asc",sSortDesc:"sorting_desc",sSortable:"sorting",sSortableAsc:"sorting_asc_disabled",
|
||||
sSortableDesc:"sorting_desc_disabled",sSortableNone:"sorting_disabled",sSortColumn:"sorting_",sFilterInput:"",sLengthSelect:"",sScrollWrapper:"dataTables_scroll",sScrollHead:"dataTables_scrollHead",sScrollHeadInner:"dataTables_scrollHeadInner",sScrollBody:"dataTables_scrollBody",sScrollFoot:"dataTables_scrollFoot",sScrollFootInner:"dataTables_scrollFootInner",sHeaderTH:"",sFooterTH:"",sSortJUIAsc:"",sSortJUIDesc:"",sSortJUI:"",sSortJUIAscAllowed:"",sSortJUIDescAllowed:"",sSortJUIWrapper:"",sSortIcon:"",
|
||||
sJUIHeader:"",sJUIFooter:""});var Pb=q.ext.pager;f.extend(Pb,{simple:function(a,b){return["previous","next"]},full:function(a,b){return["first","previous","next","last"]},numbers:function(a,b){return[ka(a,b)]},simple_numbers:function(a,b){return["previous",ka(a,b),"next"]},full_numbers:function(a,b){return["first","previous",ka(a,b),"next","last"]},first_last_numbers:function(a,b){return["first",ka(a,b),"last"]},_numbers:ka,numbers_length:7});f.extend(!0,q.ext.renderer,{pageButton:{_:function(a,b,
|
||||
c,d,e,h){var g=a.oClasses,k=a.oLanguage.oPaginate,l=a.oLanguage.oAria.paginate||{},n,m,q=0,t=function(b,d){var p,r=g.sPageButtonDisabled,u=function(b){Xa(a,b.data.action,!0)};var w=0;for(p=d.length;w<p;w++){var v=d[w];if(f.isArray(v)){var x=f("<"+(v.DT_el||"div")+"/>").appendTo(b);t(x,v)}else{n=null;m=v;x=a.iTabIndex;switch(v){case "ellipsis":b.append('<span class="ellipsis">…</span>');break;case "first":n=k.sFirst;0===e&&(x=-1,m+=" "+r);break;case "previous":n=k.sPrevious;0===e&&(x=-1,m+=
|
||||
" "+r);break;case "next":n=k.sNext;e===h-1&&(x=-1,m+=" "+r);break;case "last":n=k.sLast;e===h-1&&(x=-1,m+=" "+r);break;default:n=v+1,m=e===v?g.sPageButtonActive:""}null!==n&&(x=f("<a>",{"class":g.sPageButton+" "+m,"aria-controls":a.sTableId,"aria-label":l[v],"data-dt-idx":q,tabindex:x,id:0===c&&"string"===typeof v?a.sTableId+"_"+v:null}).html(n).appendTo(b),$a(x,{action:v},u),q++)}}};try{var v=f(b).find(y.activeElement).data("dt-idx")}catch(mc){}t(f(b).empty(),d);v!==p&&f(b).find("[data-dt-idx="+
|
||||
v+"]").focus()}}});f.extend(q.ext.type.detect,[function(a,b){b=b.oLanguage.sDecimal;return db(a,b)?"num"+b:null},function(a,b){if(a&&!(a instanceof Date)&&!cc.test(a))return null;b=Date.parse(a);return null!==b&&!isNaN(b)||P(a)?"date":null},function(a,b){b=b.oLanguage.sDecimal;return db(a,b,!0)?"num-fmt"+b:null},function(a,b){b=b.oLanguage.sDecimal;return Ub(a,b)?"html-num"+b:null},function(a,b){b=b.oLanguage.sDecimal;return Ub(a,b,!0)?"html-num-fmt"+b:null},function(a,b){return P(a)||"string"===
|
||||
typeof a&&-1!==a.indexOf("<")?"html":null}]);f.extend(q.ext.type.search,{html:function(a){return P(a)?a:"string"===typeof a?a.replace(Rb," ").replace(Ea,""):""},string:function(a){return P(a)?a:"string"===typeof a?a.replace(Rb," "):a}});var Da=function(a,b,c,d){if(0!==a&&(!a||"-"===a))return-Infinity;b&&(a=Tb(a,b));a.replace&&(c&&(a=a.replace(c,"")),d&&(a=a.replace(d,"")));return 1*a};f.extend(C.type.order,{"date-pre":function(a){a=Date.parse(a);return isNaN(a)?-Infinity:a},"html-pre":function(a){return P(a)?
|
||||
"":a.replace?a.replace(/<.*?>/g,"").toLowerCase():a+""},"string-pre":function(a){return P(a)?"":"string"===typeof a?a.toLowerCase():a.toString?a.toString():""},"string-asc":function(a,b){return a<b?-1:a>b?1:0},"string-desc":function(a,b){return a<b?1:a>b?-1:0}});Ha("");f.extend(!0,q.ext.renderer,{header:{_:function(a,b,c,d){f(a.nTable).on("order.dt.DT",function(e,f,g,k){a===f&&(e=c.idx,b.removeClass(c.sSortingClass+" "+d.sSortAsc+" "+d.sSortDesc).addClass("asc"==k[e]?d.sSortAsc:"desc"==k[e]?d.sSortDesc:
|
||||
c.sSortingClass))})},jqueryui:function(a,b,c,d){f("<div/>").addClass(d.sSortJUIWrapper).append(b.contents()).append(f("<span/>").addClass(d.sSortIcon+" "+c.sSortingClassJUI)).appendTo(b);f(a.nTable).on("order.dt.DT",function(e,f,g,k){a===f&&(e=c.idx,b.removeClass(d.sSortAsc+" "+d.sSortDesc).addClass("asc"==k[e]?d.sSortAsc:"desc"==k[e]?d.sSortDesc:c.sSortingClass),b.find("span."+d.sSortIcon).removeClass(d.sSortJUIAsc+" "+d.sSortJUIDesc+" "+d.sSortJUI+" "+d.sSortJUIAscAllowed+" "+d.sSortJUIDescAllowed).addClass("asc"==
|
||||
k[e]?d.sSortJUIAsc:"desc"==k[e]?d.sSortJUIDesc:c.sSortingClassJUI))})}}});var ib=function(a){return"string"===typeof a?a.replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):a};q.render={number:function(a,b,c,d,e){return{display:function(f){if("number"!==typeof f&&"string"!==typeof f)return f;var g=0>f?"-":"",h=parseFloat(f);if(isNaN(h))return ib(f);h=h.toFixed(c);f=Math.abs(h);h=parseInt(f,10);f=c?b+(f-h).toFixed(c).substring(2):"";return g+(d||"")+h.toString().replace(/\B(?=(\d{3})+(?!\d))/g,
|
||||
a)+f+(e||"")}}},text:function(){return{display:ib,filter:ib}}};f.extend(q.ext.internal,{_fnExternApiFunc:Qb,_fnBuildAjax:va,_fnAjaxUpdate:qb,_fnAjaxParameters:zb,_fnAjaxUpdateDraw:Ab,_fnAjaxDataSrc:wa,_fnAddColumn:Ia,_fnColumnOptions:ma,_fnAdjustColumnSizing:aa,_fnVisibleToColumnIndex:ba,_fnColumnIndexToVisible:ca,_fnVisbleColumns:W,_fnGetColumns:oa,_fnColumnTypes:Ka,_fnApplyColumnDefs:nb,_fnHungarianMap:H,_fnCamelToHungarian:L,_fnLanguageCompat:Ga,_fnBrowserDetect:lb,_fnAddData:R,_fnAddTr:pa,_fnNodeToDataIndex:function(a,
|
||||
b){return b._DT_RowIndex!==p?b._DT_RowIndex:null},_fnNodeToColumnIndex:function(a,b,c){return f.inArray(c,a.aoData[b].anCells)},_fnGetCellData:I,_fnSetCellData:ob,_fnSplitObjNotation:Na,_fnGetObjectDataFn:U,_fnSetObjectDataFn:Q,_fnGetDataMaster:Oa,_fnClearTable:qa,_fnDeleteIndex:ra,_fnInvalidate:ea,_fnGetRowElements:Ma,_fnCreateTr:La,_fnBuildHead:pb,_fnDrawHead:ha,_fnDraw:S,_fnReDraw:V,_fnAddOptionsHtml:sb,_fnDetectHeader:fa,_fnGetUniqueThs:ua,_fnFeatureHtmlFilter:ub,_fnFilterComplete:ia,_fnFilterCustom:Db,
|
||||
_fnFilterColumn:Cb,_fnFilter:Bb,_fnFilterCreateSearch:Ta,_fnEscapeRegex:Ua,_fnFilterData:Eb,_fnFeatureHtmlInfo:xb,_fnUpdateInfo:Hb,_fnInfoMacros:Ib,_fnInitialise:ja,_fnInitComplete:xa,_fnLengthChange:Va,_fnFeatureHtmlLength:tb,_fnFeatureHtmlPaginate:yb,_fnPageChange:Xa,_fnFeatureHtmlProcessing:vb,_fnProcessingDisplay:K,_fnFeatureHtmlTable:wb,_fnScrollDraw:na,_fnApplyToChildren:N,_fnCalculateColumnWidths:Ja,_fnThrottle:Sa,_fnConvertToWidth:Jb,_fnGetWidestNode:Kb,_fnGetMaxLenString:Lb,_fnStringToCss:B,
|
||||
_fnSortFlatten:Y,_fnSort:rb,_fnSortAria:Nb,_fnSortListener:Za,_fnSortAttachListener:Qa,_fnSortingClasses:Aa,_fnSortData:Mb,_fnSaveState:Ba,_fnLoadState:Ob,_fnSettingsFromNode:Ca,_fnLog:O,_fnMap:M,_fnBindAction:$a,_fnCallbackReg:E,_fnCallbackFire:A,_fnLengthOverflow:Wa,_fnRenderer:Ra,_fnDataSource:D,_fnRowAttributes:Pa,_fnExtend:ab,_fnCalculateEnd:function(){}});f.fn.dataTable=q;q.$=f;f.fn.dataTableSettings=q.settings;f.fn.dataTableExt=q.ext;f.fn.DataTable=function(a){return f(this).dataTable(a).api()};
|
||||
f.each(q,function(a,b){f.fn.DataTable[a]=b});return f.fn.dataTable});
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
/*! Respond.js v1.4.2: min/max-width media query polyfill * Copyright 2013 Scott Jehl
|
||||
* Licensed under https://github.com/scottjehl/Respond/blob/master/LICENSE-MIT
|
||||
* */
|
||||
|
||||
!function(a){"use strict";a.matchMedia=a.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement("body"),f=a.createElement("div");return f.id="mq-test-1",f.style.cssText="position:absolute;top:-100em",e.style.background="none",e.appendChild(f),function(a){return f.innerHTML='­<style media="'+a+'"> #mq-test-1 { width: 42px; }</style>',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";function b(){u(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))};if(c.ajax=f,c.queue=d,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/,maxw:/\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var g,h,i,j=a.document,k=j.documentElement,l=[],m=[],n=[],o={},p=30,q=j.getElementsByTagName("head")[0]||k,r=j.getElementsByTagName("base")[0],s=q.getElementsByTagName("link"),t=function(){var a,b=j.createElement("div"),c=j.body,d=k.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=j.createElement("body"),c.style.background="none"),k.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&k.insertBefore(c,k.firstChild),a=b.offsetWidth,f?k.removeChild(c):c.removeChild(b),k.style.fontSize=d,e&&(c.style.fontSize=e),a=i=parseFloat(a)},u=function(b){var c="clientWidth",d=k[c],e="CSS1Compat"===j.compatMode&&d||j.body[c]||d,f={},o=s[s.length-1],r=(new Date).getTime();if(b&&g&&p>r-g)return a.clearTimeout(h),h=a.setTimeout(u,p),void 0;g=r;for(var v in l)if(l.hasOwnProperty(v)){var w=l[v],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?i||t():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?i||t():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(m[w.rules]))}for(var C in n)n.hasOwnProperty(C)&&n[C]&&n[C].parentNode===q&&q.removeChild(n[C]);n.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=j.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,q.insertBefore(E,o.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(j.createTextNode(F)),n.push(E)}},v=function(a,b,d){var e=a.replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var g=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},h=!f&&d;b.length&&(b+="/"),h&&(f=1);for(var i=0;f>i;i++){var j,k,n,o;h?(j=d,m.push(g(a))):(j=e[i].match(c.regex.findStyles)&&RegExp.$1,m.push(RegExp.$2&&g(RegExp.$2))),n=j.split(","),o=n.length;for(var p=0;o>p;p++)k=n[p],l.push({media:k.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:m.length-1,hasquery:k.indexOf("(")>-1,minw:k.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:k.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}u()},w=function(){if(d.length){var b=d.shift();f(b.href,function(c){v(c,b.href,b.media),o[b.href]=!0,a.setTimeout(function(){w()},0)})}},x=function(){for(var b=0;b<s.length;b++){var c=s[b],e=c.href,f=c.media,g=c.rel&&"stylesheet"===c.rel.toLowerCase();e&&g&&!o[e]&&(c.styleSheet&&c.styleSheet.rawCssText?(v(c.styleSheet.rawCssText,e,f),o[e]=!0):(!/^([a-zA-Z:]*\/\/)/.test(e)&&!r||e.replace(RegExp.$1,"").split("/")[0]===a.location.host)&&("//"===e.substring(0,2)&&(e=a.location.protocol+e),d.push({href:e,media:f})))}w()};x(),c.update=x,c.getEmValue=t,a.addEventListener?a.addEventListener("resize",b,!1):a.attachEvent&&a.attachEvent("onresize",b)}}(this);
|
||||
@@ -26,7 +26,7 @@ if($last_error["type"] === E_WARNING || $last_error["type"] === E_ERROR)
|
||||
}
|
||||
|
||||
?>
|
||||
<style type="text/css">
|
||||
<style>
|
||||
.tooltip-inner {
|
||||
max-width: none;
|
||||
white-space: nowrap;
|
||||
@@ -250,48 +250,10 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "blocklists"
|
||||
<div class="col-md-12">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">Blocklists used to generate Pi-hole's Gravity: <?php echo count($adlist); ?></h3>
|
||||
<h3 class="box-title">Blocklists used to generate Pi-hole's Gravity</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-bordered dt-responsive nowrap">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Enabled</th>
|
||||
<th>List</th>
|
||||
<th style="width:1%">Delete</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($adlist as $key => $value) { ?>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="checkbox" name="adlist-enable-<?php echo $key; ?>" <?php if ($value[0]){ ?>checked<?php } ?>>
|
||||
</td>
|
||||
<td>
|
||||
<a href="<?php echo htmlentities($value[1]); ?>" target="_new" id="adlist-text-<?php echo $key; ?>"><?php echo htmlentities($value[1]); ?></a>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<button class="btn btn-danger btn-xs" id="adlist-btn-<?php echo $key; ?>">
|
||||
<span class="glyphicon glyphicon-trash"></span>
|
||||
</button>
|
||||
<input type="checkbox" name="adlist-del-<?php echo $key; ?>" hidden>
|
||||
</td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<textarea name="newuserlists" class="form-control" rows="1" placeholder="Enter one URL per line to add new blocklists"></textarea>
|
||||
</div>
|
||||
<input type="hidden" name="field" value="adlists">
|
||||
<input type="hidden" name="token" value="<?php echo $token ?>">
|
||||
</div>
|
||||
<div class="box-footer clearfix">
|
||||
<button type="submit" class="btn btn-primary" name="submit" value="save" id="blockinglistsave">Save</button>
|
||||
<span><strong>Important: </strong>Save and Update when you're done!</span>
|
||||
<button type="submit" class="btn btn-primary pull-right" name="submit" id="blockinglistsaveupdate" value="saveupdate">Save and Update</button>
|
||||
<p>Please use the <a href="groups-adlists.php">group management pages</a> to edit the blocklists used by Pi-hole.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -732,6 +694,8 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "blocklists"
|
||||
<input type="text" name="custom1val" class="form-control"
|
||||
<?php if (isset($custom1)){ ?>value="<?php echo $custom1; ?>"<?php } ?>>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Custom 2 (IPv4)</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">
|
||||
@@ -754,6 +718,8 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "blocklists"
|
||||
<input type="text" name="custom3val" class="form-control"
|
||||
<?php if (isset($custom3)){ ?>value="<?php echo $custom3; ?>"<?php } ?>>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Custom 4 (IPv6)</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">
|
||||
@@ -850,7 +816,7 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "blocklists"
|
||||
server which supports DNSSEC when activating DNSSEC. Note that
|
||||
the size of your log might increase significantly
|
||||
when enabling DNSSEC. A DNSSEC resolver test can be found
|
||||
<a href="http://dnssec.vs.uni-due.de/" target="_blank">here</a>.</p>
|
||||
<a href="https://dnssec.vs.uni-due.de/" rel="noopener" target="_blank">here</a>.</p>
|
||||
<label>Conditional Forwarding</label>
|
||||
<p>If not configured as your DHCP server, Pi-hole won't be able to
|
||||
determine the names of devices on your local network. As a
|
||||
@@ -1013,10 +979,8 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "blocklists"
|
||||
</div>
|
||||
<h4>Administrator Email Address</h4>
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" name="adminemail"
|
||||
value="<?php echo htmlspecialchars($adminemail); ?>">
|
||||
</div>
|
||||
<input type="text" class="form-control" name="adminemail"
|
||||
value="<?php echo htmlspecialchars($adminemail); ?>">
|
||||
</div>
|
||||
<input type="hidden" name="field" value="webUI">
|
||||
<input type="hidden" name="token" value="<?php echo $token ?>">
|
||||
@@ -1128,12 +1092,17 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "blocklists"
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-md-12">
|
||||
<label>Import ...</label>
|
||||
<label>Import...</label>
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" name="whitelist" value="true"
|
||||
checked>
|
||||
Whitelist</label>
|
||||
Whitelist (exact)</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" name="regex_whitelist" value="true"
|
||||
checked>
|
||||
Whitelist (regex/wildcard)</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" name="blacklist" value="true"
|
||||
@@ -1143,13 +1112,23 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "blocklists"
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" name="regexlist" value="true"
|
||||
checked>
|
||||
Regex filters</label>
|
||||
Blacklist (regex/wildcard)</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" name="adlist" value="true"
|
||||
checked>
|
||||
Blocklists</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" name="auditlog" value="true"
|
||||
checked>
|
||||
Audit log</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" name="staticdhcpleases" value="true"
|
||||
checked>
|
||||
Static DHCP Leases</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6 col-md-12">
|
||||
@@ -1160,6 +1139,11 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "blocklists"
|
||||
<button type="submit" class="btn btn-default" name="action"
|
||||
value="in">Import
|
||||
</button>
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" name="flushtables" value="true"
|
||||
checked>
|
||||
Clear existing data</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1287,7 +1271,7 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "blocklists"
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
See also our <a href="https://docs.pi-hole.net/ftldns/dns-cache/" target="_blank">DNS cache documentation</a>.
|
||||
See also our <a href="https://docs.pi-hole.net/ftldns/dns-cache/" rel="noopener" target="_blank">DNS cache documentation</a>.
|
||||
<?php } else { ?>
|
||||
<div>The FTL service is offline!</div>
|
||||
<?php } ?>
|
||||
@@ -1319,9 +1303,7 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "blocklists"
|
||||
</div>
|
||||
<p class="hidden-md hidden-lg"></p>
|
||||
<div class="col-md-4">
|
||||
<?php if ($piHoleLogging) { ?>
|
||||
<button type="button" class="btn btn-danger confirm-disablelogging form-control">Disable query logging and flush logs</button>
|
||||
<?php } ?>
|
||||
<button type="button" class="btn btn-warning confirm-flusharp form-control">Flush network table</button>
|
||||
</div>
|
||||
<p class="hidden-md hidden-lg"></p>
|
||||
<div class="col-md-4">
|
||||
@@ -1347,9 +1329,8 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "blocklists"
|
||||
<input type="hidden" name="field" value="flushlogs">
|
||||
<input type="hidden" name="token" value="<?php echo $token ?>">
|
||||
</form>
|
||||
<form role="form" method="post" id="disablelogsform">
|
||||
<input type="hidden" name="field" value="Logging">
|
||||
<input type="hidden" name="action" value="Disable">
|
||||
<form role="form" method="post" id="flusharpform">
|
||||
<input type="hidden" name="field" value="flusharp">
|
||||
<input type="hidden" name="token" value="<?php echo $token ?>">
|
||||
</form>
|
||||
<form role="form" method="post" id="disablelogsform-noflush">
|
||||
|
||||
@@ -16,19 +16,43 @@
|
||||
user-select: none;
|
||||
}
|
||||
.small-box span {
|
||||
-webkit-transition-duration: 500ms;
|
||||
-o-transition-duration: 500ms;
|
||||
transition-duration: 500ms;
|
||||
}
|
||||
.small-box span.glow {
|
||||
text-shadow: 0px 0px 5px #fff;
|
||||
text-shadow: 0 0 5px #fff;
|
||||
}
|
||||
.skin-blue .list-group-item:hover {
|
||||
background: #ddd;
|
||||
}
|
||||
|
||||
.skin-blue .not-used {
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
.skin-blue .not-used:hover {
|
||||
background: #c5c5c5;
|
||||
}
|
||||
|
||||
.skin-blue .used {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.skin-blue .used:hover {
|
||||
background: #ddd;
|
||||
}
|
||||
|
||||
@-webkit-keyframes Pulse{
|
||||
from {color:#630030;-webkit-text-shadow:0 0 2px transparent;}
|
||||
50% {color:#e33100;-webkit-text-shadow:0 0 5px #e33100;}
|
||||
to {color:#630030;-webkit-text-shadow:0 0 2px transparent;}
|
||||
}
|
||||
@-o-keyframes Pulse{
|
||||
from {color:#630030;text-shadow:0 0 2px transparent;}
|
||||
50% {color:#e33100;text-shadow:0 0 5px #e33100;}
|
||||
to {color:#630030;text-shadow:0 0 2px transparent;}
|
||||
}
|
||||
@keyframes Pulse{
|
||||
from {color:#630030;text-shadow:0 0 2px transparent;}
|
||||
50% {color:#e33100;text-shadow:0 0 5px #e33100;}
|
||||
@@ -36,10 +60,13 @@
|
||||
}
|
||||
.lookatme {
|
||||
-webkit-animation-name: Pulse;
|
||||
-o-animation-name: Pulse;
|
||||
animation-name: Pulse;
|
||||
-webkit-animation-duration: 2s;
|
||||
-o-animation-duration: 2s;
|
||||
animation-duration: 2s;
|
||||
-webkit-animation-iteration-count: infinite;
|
||||
-o-animation-iteration-count: infinite;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
|
||||
@@ -83,13 +110,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
.main-header>.navbar, .navbar>.sidebar-toggle {
|
||||
.main-header > .navbar,
|
||||
.navbar > .sidebar-toggle {
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
#resetButton {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
color: #f00;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.vertical-alignment-helper {
|
||||
@@ -116,9 +144,10 @@
|
||||
width: 0.8em;
|
||||
height: 0.8em;
|
||||
border-radius: 50%;
|
||||
border: 4px solid silver;
|
||||
border: 4px solid #c0c0c0;
|
||||
border-right-color: transparent;
|
||||
-webkit-animation: fa-spin 1s infinite linear;
|
||||
-o-animation: fa-spin 1s infinite linear;
|
||||
animation: fa-spin 1s infinite linear;
|
||||
}
|
||||
|
||||
@@ -126,31 +155,80 @@
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none
|
||||
}
|
||||
|
||||
#chartjs-tooltip {
|
||||
opacity: 1;
|
||||
.chartjs-tooltip {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
background: rgba(0, 0, 0, .7);
|
||||
color: white;
|
||||
border-radius: 3px;
|
||||
-webkit-transition: all .1s ease;
|
||||
transition: all .1s ease;
|
||||
pointer-events: none;
|
||||
-webkit-transform: translate(-50%, 0);
|
||||
transform: translate(-50%, 0);
|
||||
color: #fff;
|
||||
background-color: rgba(0,0,0,0.8);
|
||||
max-width: 95%;
|
||||
z-index: 900;
|
||||
}
|
||||
|
||||
.chartjs-tooltip th {
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
|
||||
.chartjs-tooltip,
|
||||
.chartjs-tooltip .arrow {
|
||||
-webkit-transition: all .2s cubic-bezier(0.165, 0.84, 0.44, 1);
|
||||
transition: all .2s cubic-bezier(0.165, 0.84, 0.44, 1);
|
||||
}
|
||||
|
||||
.chartjs-tooltip .arrow {
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-color: transparent;
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
.chartjs-tooltip.bottom .arrow {
|
||||
top: 100%;
|
||||
left: 50%;
|
||||
margin: 0 -5px -5px;
|
||||
border-width: 5px 5px 0;
|
||||
border-top-color: rgba(0, 0, 0, .8);
|
||||
}
|
||||
|
||||
.chartjs-tooltip.top .arrow {
|
||||
top: 0;
|
||||
left: 50%;
|
||||
border-width: 0 5px 5px;
|
||||
margin: -5px -5px 0;
|
||||
border-bottom-color: rgba(0, 0, 0, .8);
|
||||
}
|
||||
|
||||
.chartjs-tooltip.right.center .arrow {
|
||||
top: 50%;
|
||||
left: 100%;
|
||||
margin: -5px -5px -5px 0;
|
||||
border-width: 5px 0 5px 5px;
|
||||
border-left-color: rgba(0, 0, 0, .8);
|
||||
}
|
||||
|
||||
.chartjs-tooltip.left.center .arrow {
|
||||
top: 50%;
|
||||
left: 0;
|
||||
margin: -5px 0 -5px -5px;
|
||||
border-width: 5px 5px 5px 0;
|
||||
border-right-color: rgba(0, 0, 0, .8);
|
||||
}
|
||||
|
||||
.chartjs-tooltip-key {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 10px;
|
||||
margin-right: 10px;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin-right: 3px;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
|
||||
.chart-legend {
|
||||
height:250px;
|
||||
overflow:auto;
|
||||
height: 250px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.chart-legend ul {
|
||||
@@ -158,7 +236,8 @@
|
||||
}
|
||||
|
||||
.chart-legend li {
|
||||
cursor:pointer;
|
||||
cursor: pointer;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.chart-legend li span {
|
||||
@@ -172,10 +251,6 @@
|
||||
text-decoration: line-through !important;
|
||||
}
|
||||
|
||||
.float-left{
|
||||
float:left;
|
||||
}
|
||||
|
||||
.fa-paypal-icon {
|
||||
width: 18px;
|
||||
margin-left: 2px;
|
||||
@@ -185,3 +260,55 @@
|
||||
font-weight: 900;
|
||||
font-family: "Font Awesome 5 Free";
|
||||
}
|
||||
|
||||
/* Utilities */
|
||||
.text-black {
|
||||
color: #000 !important;
|
||||
}
|
||||
|
||||
.text-green-light {
|
||||
color: #7fff00 !important;
|
||||
}
|
||||
|
||||
.text-green {
|
||||
color: #080 !important;
|
||||
}
|
||||
|
||||
.text-orange {
|
||||
color: #ffa500 !important;
|
||||
}
|
||||
|
||||
.text-red {
|
||||
color: #f00 !important;
|
||||
}
|
||||
|
||||
.text-vivid-blue {
|
||||
color: #36f !important;
|
||||
}
|
||||
|
||||
td.highlight {
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
code.breakall
|
||||
{
|
||||
white-space: -moz-pre-wrap;
|
||||
white-space: -pre-wrap;
|
||||
white-space: -o-pre-wrap;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
||||
}
|
||||
|
||||
.underline {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.bootstrap-select.bs-container.align-right {
|
||||
left: unset !important;
|
||||
right: 10px;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
@import url(SourceSansPro/SourceSansPro.css);/*!
|
||||
/*!
|
||||
* AdminLTE v2.1.2
|
||||
* Author: Almsaeed Studio
|
||||
* Website: Almsaeed Studio <http://almsaeedstudio.com>
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*! ========================================================================
|
||||
* Bootstrap Toggle: bootstrap-toggle.css v2.2.0
|
||||
* http://www.bootstraptoggle.com
|
||||
* ========================================================================
|
||||
* Copyright 2014 Min Hur, The New York Times Company
|
||||
* Licensed under MIT
|
||||
* ======================================================================== */
|
||||
.checkbox label .toggle,.checkbox-inline .toggle{margin-left:-20px;margin-right:5px}
|
||||
.toggle{position:relative;overflow:hidden}
|
||||
.toggle input[type=checkbox]{display:none}
|
||||
.toggle-group{position:absolute;width:200%;top:0;bottom:0;left:0;transition:left .35s;-webkit-transition:left .35s;-moz-user-select:none;-webkit-user-select:none}
|
||||
.toggle.off .toggle-group{left:-100%}
|
||||
.toggle-on{position:absolute;top:0;bottom:0;left:0;right:50%;margin:0;border:0;border-radius:0}
|
||||
.toggle-off{position:absolute;top:0;bottom:0;left:50%;right:0;margin:0;border:0;border-radius:0}
|
||||
.toggle-handle{position:relative;margin:0 auto;padding-top:0;padding-bottom:0;height:100%;width:0;border-width:0 1px}
|
||||
.toggle.btn{min-width:59px;min-height:34px}
|
||||
.toggle-on.btn{padding-right:24px}
|
||||
.toggle-off.btn{padding-left:24px}
|
||||
.toggle.btn-lg{min-width:79px;min-height:45px}
|
||||
.toggle-on.btn-lg{padding-right:31px}
|
||||
.toggle-off.btn-lg{padding-left:31px}
|
||||
.toggle-handle.btn-lg{width:40px}
|
||||
.toggle.btn-sm{min-width:50px;min-height:30px}
|
||||
.toggle-on.btn-sm{padding-right:20px}
|
||||
.toggle-off.btn-sm{padding-left:20px}
|
||||
.toggle.btn-xs{min-width:35px;min-height:22px}
|
||||
.toggle-on.btn-xs{padding-right:12px}
|
||||
.toggle-off.btn-xs{padding-left:12px}
|
||||
@@ -0,0 +1,9 @@
|
||||
/*! ========================================================================
|
||||
* Bootstrap Toggle: bootstrap-toggle.js v2.2.0
|
||||
* http://www.bootstraptoggle.com
|
||||
* ========================================================================
|
||||
* Copyright 2014 Min Hur, The New York Times Company
|
||||
* Licensed under MIT
|
||||
* ======================================================================== */
|
||||
+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.toggle"),f="object"==typeof b&&b;e||d.data("bs.toggle",e=new c(this,f)),"string"==typeof b&&e[b]&&e[b]()})}var c=function(b,c){this.$element=a(b),this.options=a.extend({},this.defaults(),c),this.render()};c.VERSION="2.2.0",c.DEFAULTS={on:"On",off:"Off",onstyle:"primary",offstyle:"default",size:"normal",style:"",width:null,height:null},c.prototype.defaults=function(){return{on:this.$element.attr("data-on")||c.DEFAULTS.on,off:this.$element.attr("data-off")||c.DEFAULTS.off,onstyle:this.$element.attr("data-onstyle")||c.DEFAULTS.onstyle,offstyle:this.$element.attr("data-offstyle")||c.DEFAULTS.offstyle,size:this.$element.attr("data-size")||c.DEFAULTS.size,style:this.$element.attr("data-style")||c.DEFAULTS.style,width:this.$element.attr("data-width")||c.DEFAULTS.width,height:this.$element.attr("data-height")||c.DEFAULTS.height}},c.prototype.render=function(){this._onstyle="btn-"+this.options.onstyle,this._offstyle="btn-"+this.options.offstyle;var b="large"===this.options.size?"btn-lg":"small"===this.options.size?"btn-sm":"mini"===this.options.size?"btn-xs":"",c=a('<label class="btn">').html(this.options.on).addClass(this._onstyle+" "+b),d=a('<label class="btn">').html(this.options.off).addClass(this._offstyle+" "+b+" active"),e=a('<span class="toggle-handle btn btn-default">').addClass(b),f=a('<div class="toggle-group">').append(c,d,e),g=a('<div class="toggle btn" data-toggle="toggle">').addClass(this.$element.prop("checked")?this._onstyle:this._offstyle+" off").addClass(b).addClass(this.options.style);this.$element.wrap(g),a.extend(this,{$toggle:this.$element.parent(),$toggleOn:c,$toggleOff:d,$toggleGroup:f}),this.$toggle.append(f);var h=this.options.width||Math.max(c.outerWidth(),d.outerWidth())+e.outerWidth()/2,i=this.options.height||Math.max(c.outerHeight(),d.outerHeight());c.addClass("toggle-on"),d.addClass("toggle-off"),this.$toggle.css({width:h,height:i}),this.options.height&&(c.css("line-height",c.height()+"px"),d.css("line-height",d.height()+"px")),this.update(!0),this.trigger(!0)},c.prototype.toggle=function(){this.$element.prop("checked")?this.off():this.on()},c.prototype.on=function(a){return this.$element.prop("disabled")?!1:(this.$toggle.removeClass(this._offstyle+" off").addClass(this._onstyle),this.$element.prop("checked",!0),void(a||this.trigger()))},c.prototype.off=function(a){return this.$element.prop("disabled")?!1:(this.$toggle.removeClass(this._onstyle).addClass(this._offstyle+" off"),this.$element.prop("checked",!1),void(a||this.trigger()))},c.prototype.enable=function(){this.$toggle.removeAttr("disabled"),this.$element.prop("disabled",!1)},c.prototype.disable=function(){this.$toggle.attr("disabled","disabled"),this.$element.prop("disabled",!0)},c.prototype.update=function(a){this.$element.prop("disabled")?this.disable():this.enable(),this.$element.prop("checked")?this.on(a):this.off(a)},c.prototype.trigger=function(b){this.$element.off("change.bs.toggle"),b||this.$element.change(),this.$element.on("change.bs.toggle",a.proxy(function(){this.update()},this))},c.prototype.destroy=function(){this.$element.off("change.bs.toggle"),this.$toggleGroup.remove(),this.$element.removeData("bs.toggle"),this.$element.unwrap()};var d=a.fn.bootstrapToggle;a.fn.bootstrapToggle=b,a.fn.bootstrapToggle.Constructor=c,a.fn.toggle.noConflict=function(){return a.fn.bootstrapToggle=d,this},a(function(){a("input[type=checkbox][data-toggle^=toggle]").bootstrapToggle()}),a(document).on("click.bs.toggle","div[data-toggle^=toggle]",function(b){var c=a(this).find("input[type=checkbox]");c.bootstrapToggle("toggle"),b.preventDefault()})}(jQuery);
|
||||
//# sourceMappingURL=bootstrap-toggle.min.js.map
|
||||
|
After Width: | Height: | Size: 684 KiB |
@@ -0,0 +1,803 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!--
|
||||
Font Awesome Free 5.11.2 by @fontawesome - https://fontawesome.com
|
||||
License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
-->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
|
||||
<metadata>
|
||||
Created by FontForge 20190801 at Mon Sep 23 12:52:52 2019
|
||||
By Robert Madole
|
||||
Copyright (c) Font Awesome
|
||||
</metadata>
|
||||
<defs>
|
||||
<font id="FontAwesome5Free-Regular" horiz-adv-x="512" >
|
||||
<font-face
|
||||
font-family="Font Awesome 5 Free Regular"
|
||||
font-weight="400"
|
||||
font-stretch="normal"
|
||||
units-per-em="512"
|
||||
panose-1="2 0 5 3 0 0 0 0 0 0"
|
||||
ascent="448"
|
||||
descent="-64"
|
||||
bbox="-0.0663408 -64.0662 640.01 448.1"
|
||||
underline-thickness="25"
|
||||
underline-position="-50"
|
||||
unicode-range="U+0020-F5C8"
|
||||
/>
|
||||
<missing-glyph />
|
||||
<glyph glyph-name="heart" unicode=""
|
||||
d="M458.4 383.7c75.2998 -63.4004 64.0996 -166.601 10.5996 -221.3l-175.4 -178.7c-10 -10.2002 -23.2998 -15.7998 -37.5996 -15.7998c-14.2002 0 -27.5996 5.69922 -37.5996 15.8994l-175.4 178.7c-53.5996 54.7002 -64.5996 157.9 10.5996 221.2
|
||||
c57.8008 48.7002 147.101 41.2998 202.4 -15c55.2998 56.2998 144.6 63.5996 202.4 15zM434.8 196.2c36.2002 36.8994 43.7998 107.7 -7.2998 150.8c-38.7002 32.5996 -98.7002 27.9004 -136.5 -10.5996l-35 -35.7002l-35 35.7002
|
||||
c-37.5996 38.2998 -97.5996 43.1992 -136.5 10.5c-51.2002 -43.1006 -43.7998 -113.5 -7.2998 -150.7l175.399 -178.7c2.40039 -2.40039 4.40039 -2.40039 6.80078 0z" />
|
||||
<glyph glyph-name="star" unicode="" horiz-adv-x="576"
|
||||
d="M528.1 276.5c26.2002 -3.7998 36.7002 -36.0996 17.7002 -54.5996l-105.7 -103l25 -145.5c4.5 -26.3008 -23.1992 -45.9004 -46.3994 -33.7002l-130.7 68.7002l-130.7 -68.7002c-23.2002 -12.2998 -50.8994 7.39941 -46.3994 33.7002l25 145.5l-105.7 103
|
||||
c-19 18.5 -8.5 50.7998 17.7002 54.5996l146.1 21.2998l65.2998 132.4c11.7998 23.8994 45.7002 23.5996 57.4004 0l65.2998 -132.4zM388.6 135.7l100.601 98l-139 20.2002l-62.2002 126l-62.2002 -126l-139 -20.2002l100.601 -98l-23.7002 -138.4l124.3 65.2998
|
||||
l124.3 -65.2998z" />
|
||||
<glyph glyph-name="user" unicode="" horiz-adv-x="448"
|
||||
d="M313.6 144c74.2002 0 134.4 -60.2002 134.4 -134.4v-25.5996c0 -26.5 -21.5 -48 -48 -48h-352c-26.5 0 -48 21.5 -48 48v25.5996c0 74.2002 60.2002 134.4 134.4 134.4c28.7998 0 42.5 -16 89.5996 -16s60.9004 16 89.5996 16zM400 -16v25.5996
|
||||
c0 47.6006 -38.7998 86.4004 -86.4004 86.4004c-14.6992 0 -37.8994 -16 -89.5996 -16c-51.2998 0 -75 16 -89.5996 16c-47.6006 0 -86.4004 -38.7998 -86.4004 -86.4004v-25.5996h352zM224 160c-79.5 0 -144 64.5 -144 144s64.5 144 144 144s144 -64.5 144 -144
|
||||
s-64.5 -144 -144 -144zM224 400c-52.9004 0 -96 -43.0996 -96 -96s43.0996 -96 96 -96s96 43.0996 96 96s-43.0996 96 -96 96z" />
|
||||
<glyph glyph-name="clock" unicode=""
|
||||
d="M256 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM256 -8c110.5 0 200 89.5 200 200s-89.5 200 -200 200s-200 -89.5 -200 -200s89.5 -200 200 -200zM317.8 96.4004l-84.8994 61.6992
|
||||
c-3.10059 2.30078 -4.90039 5.90039 -4.90039 9.7002v164.2c0 6.59961 5.40039 12 12 12h32c6.59961 0 12 -5.40039 12 -12v-141.7l66.7998 -48.5996c5.40039 -3.90039 6.5 -11.4004 2.60059 -16.7998l-18.8008 -25.9004c-3.89941 -5.2998 -11.3994 -6.5 -16.7998 -2.59961z
|
||||
" />
|
||||
<glyph glyph-name="list-alt" unicode=""
|
||||
d="M464 416c26.5098 0 48 -21.4902 48 -48v-352c0 -26.5098 -21.4902 -48 -48 -48h-416c-26.5098 0 -48 21.4902 -48 48v352c0 26.5098 21.4902 48 48 48h416zM458 16c3.31152 0 6 2.68848 6 6v340c0 3.31152 -2.68848 6 -6 6h-404c-3.31152 0 -6 -2.68848 -6 -6v-340
|
||||
c0 -3.31152 2.68848 -6 6 -6h404zM416 108v-24c0 -6.62695 -5.37305 -12 -12 -12h-200c-6.62695 0 -12 5.37305 -12 12v24c0 6.62695 5.37305 12 12 12h200c6.62695 0 12 -5.37305 12 -12zM416 204v-24c0 -6.62695 -5.37305 -12 -12 -12h-200c-6.62695 0 -12 5.37305 -12 12
|
||||
v24c0 6.62695 5.37305 12 12 12h200c6.62695 0 12 -5.37305 12 -12zM416 300v-24c0 -6.62695 -5.37305 -12 -12 -12h-200c-6.62695 0 -12 5.37305 -12 12v24c0 6.62695 5.37305 12 12 12h200c6.62695 0 12 -5.37305 12 -12zM164 288c0 -19.8818 -16.1182 -36 -36 -36
|
||||
s-36 16.1182 -36 36s16.1182 36 36 36s36 -16.1182 36 -36zM164 192c0 -19.8818 -16.1182 -36 -36 -36s-36 16.1182 -36 36s16.1182 36 36 36s36 -16.1182 36 -36zM164 96c0 -19.8818 -16.1182 -36 -36 -36s-36 16.1182 -36 36s16.1182 36 36 36s36 -16.1182 36 -36z" />
|
||||
<glyph glyph-name="flag" unicode=""
|
||||
d="M336.174 368c35.4668 0 73.0195 12.6914 108.922 28.1797c31.6406 13.6514 66.9043 -9.65723 66.9043 -44.1162v-239.919c0 -16.1953 -8.1543 -31.3057 -21.7129 -40.1631c-26.5762 -17.3643 -70.0693 -39.9814 -128.548 -39.9814c-68.6084 0 -112.781 32 -161.913 32
|
||||
c-56.5674 0 -89.957 -11.2803 -127.826 -28.5566v-83.4434c0 -8.83691 -7.16309 -16 -16 -16h-16c-8.83691 0 -16 7.16309 -16 16v406.438c-14.3428 8.2998 -24 23.7979 -24 41.5615c0 27.5693 23.2422 49.71 51.2012 47.8965
|
||||
c22.9658 -1.49023 41.8662 -19.4717 44.4805 -42.3379c0.177734 -1.52441 0.321289 -4.00781 0.321289 -5.54199c0 -4.30176 -1.10352 -11.1035 -2.46289 -15.1846c22.418 8.68555 49.4199 15.168 80.7207 15.168c68.6084 0 112.781 -32 161.913 -32zM464 112v240
|
||||
c-31.5059 -14.6338 -84.5547 -32 -127.826 -32c-59.9111 0 -101.968 32 -161.913 32c-41.4365 0 -80.4766 -16.5879 -102.261 -32v-232c31.4473 14.5967 84.4648 24 127.826 24c59.9111 0 101.968 -32 161.913 -32c41.4365 0 80.4775 16.5879 102.261 32z" />
|
||||
<glyph glyph-name="bookmark" unicode="" horiz-adv-x="384"
|
||||
d="M336 448c26.5098 0 48 -21.4902 48 -48v-464l-192 112l-192 -112v464c0 26.5098 21.4902 48 48 48h288zM336 19.5703v374.434c0 3.31348 -2.68555 5.99609 -6 5.99609h-276c-3.31152 0 -6 -2.68848 -6 -6v-374.43l144 84z" />
|
||||
<glyph glyph-name="image" unicode=""
|
||||
d="M464 384c26.5098 0 48 -21.4902 48 -48v-288c0 -26.5098 -21.4902 -48 -48 -48h-416c-26.5098 0 -48 21.4902 -48 48v288c0 26.5098 21.4902 48 48 48h416zM458 48c3.31152 0 6 2.68848 6 6v276c0 3.31152 -2.68848 6 -6 6h-404c-3.31152 0 -6 -2.68848 -6 -6v-276
|
||||
c0 -3.31152 2.68848 -6 6 -6h404zM128 296c22.0908 0 40 -17.9092 40 -40s-17.9092 -40 -40 -40s-40 17.9092 -40 40s17.9092 40 40 40zM96 96v48l39.5137 39.5146c4.6875 4.68652 12.2852 4.68652 16.9717 0l39.5146 -39.5146l119.514 119.515
|
||||
c4.6875 4.68652 12.2852 4.68652 16.9717 0l87.5146 -87.5146v-80h-320z" />
|
||||
<glyph glyph-name="edit" unicode="" horiz-adv-x="576"
|
||||
d="M402.3 103.1l32 32c5 5 13.7002 1.5 13.7002 -5.69922v-145.4c0 -26.5 -21.5 -48 -48 -48h-352c-26.5 0 -48 21.5 -48 48v352c0 26.5 21.5 48 48 48h273.5c7.09961 0 10.7002 -8.59961 5.7002 -13.7002l-32 -32c-1.5 -1.5 -3.5 -2.2998 -5.7002 -2.2998h-241.5v-352h352
|
||||
v113.5c0 2.09961 0.799805 4.09961 2.2998 5.59961zM558.9 304.9l-262.601 -262.601l-90.3994 -10c-26.2002 -2.89941 -48.5 19.2002 -45.6006 45.6006l10 90.3994l262.601 262.601c22.8994 22.8994 59.8994 22.8994 82.6992 0l43.2002 -43.2002
|
||||
c22.9004 -22.9004 22.9004 -60 0.100586 -82.7998zM460.1 274l-58.0996 58.0996l-185.8 -185.899l-7.2998 -65.2998l65.2998 7.2998zM524.9 353.7l-43.2002 43.2002c-4.10059 4.09961 -10.7998 4.09961 -14.7998 0l-30.9004 -30.9004l58.0996 -58.0996l30.9004 30.8994
|
||||
c4 4.2002 4 10.7998 -0.0996094 14.9004z" />
|
||||
<glyph glyph-name="times-circle" unicode=""
|
||||
d="M256 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM256 -8c110.5 0 200 89.5 200 200s-89.5 200 -200 200s-200 -89.5 -200 -200s89.5 -200 200 -200zM357.8 254.2l-62.2002 -62.2002l62.2002 -62.2002
|
||||
c4.7002 -4.7002 4.7002 -12.2998 0 -17l-22.5996 -22.5996c-4.7002 -4.7002 -12.2998 -4.7002 -17 0l-62.2002 62.2002l-62.2002 -62.2002c-4.7002 -4.7002 -12.2998 -4.7002 -17 0l-22.5996 22.5996c-4.7002 4.7002 -4.7002 12.2998 0 17l62.2002 62.2002l-62.2002 62.2002
|
||||
c-4.7002 4.7002 -4.7002 12.2998 0 17l22.5996 22.5996c4.7002 4.7002 12.2998 4.7002 17 0l62.2002 -62.2002l62.2002 62.2002c4.7002 4.7002 12.2998 4.7002 17 0l22.5996 -22.5996c4.7002 -4.7002 4.7002 -12.2998 0 -17z" />
|
||||
<glyph glyph-name="check-circle" unicode=""
|
||||
d="M256 440c136.967 0 248 -111.033 248 -248s-111.033 -248 -248 -248s-248 111.033 -248 248s111.033 248 248 248zM256 392c-110.549 0 -200 -89.4678 -200 -200c0 -110.549 89.4678 -200 200 -200c110.549 0 200 89.4678 200 200c0 110.549 -89.4678 200 -200 200z
|
||||
M396.204 261.733c4.66699 -4.70508 4.63672 -12.3037 -0.0673828 -16.9717l-172.589 -171.204c-4.70508 -4.66797 -12.3027 -4.63672 -16.9697 0.0683594l-90.7812 91.5156c-4.66797 4.70605 -4.63672 12.3047 0.0683594 16.9717l22.7188 22.5361
|
||||
c4.70508 4.66699 12.3027 4.63574 16.9697 -0.0693359l59.792 -60.2773l141.353 140.216c4.70508 4.66797 12.3027 4.6377 16.9697 -0.0673828z" />
|
||||
<glyph glyph-name="question-circle" unicode=""
|
||||
d="M256 440c136.957 0 248 -111.083 248 -248c0 -136.997 -111.043 -248 -248 -248s-248 111.003 -248 248c0 136.917 111.043 248 248 248zM256 -8c110.569 0 200 89.4697 200 200c0 110.529 -89.5088 200 -200 200c-110.528 0 -200 -89.5049 -200 -200
|
||||
c0 -110.569 89.4678 -200 200 -200zM363.244 247.2c0 -67.0518 -72.4209 -68.084 -72.4209 -92.8633v-6.33691c0 -6.62695 -5.37305 -12 -12 -12h-45.6475c-6.62695 0 -12 5.37305 -12 12v8.65918c0 35.7451 27.1006 50.0342 47.5791 61.5156
|
||||
c17.5615 9.84473 28.3242 16.541 28.3242 29.5791c0 17.2461 -21.999 28.6934 -39.7842 28.6934c-23.1885 0 -33.8936 -10.9775 -48.9424 -29.9697c-4.05664 -5.11914 -11.46 -6.07031 -16.666 -2.12402l-27.8232 21.0986
|
||||
c-5.10742 3.87207 -6.25098 11.0654 -2.64453 16.3633c23.627 34.6934 53.7217 54.1846 100.575 54.1846c49.0713 0 101.45 -38.3037 101.45 -88.7998zM298 80c0 -23.1592 -18.8408 -42 -42 -42s-42 18.8408 -42 42s18.8408 42 42 42s42 -18.8408 42 -42z" />
|
||||
<glyph glyph-name="eye" unicode="" horiz-adv-x="576"
|
||||
d="M288 304c0.0927734 0 0.244141 0.000976562 0.336914 0.000976562c61.6641 0 111.71 -50.0469 111.71 -111.711c0 -61.6631 -50.0459 -111.71 -111.71 -111.71s-111.71 50.0469 -111.71 111.71c0 8.71289 1.95898 22.5781 4.37305 30.9502
|
||||
c6.93066 -3.94141 19.0273 -7.18457 27 -7.24023c30.9121 0 56 25.0879 56 56c-0.0556641 7.97266 -3.29883 20.0693 -7.24023 27c8.42383 2.62207 22.4189 4.8623 31.2402 5zM572.52 206.6c1.9209 -3.79883 3.47949 -10.3379 3.47949 -14.5947
|
||||
s-1.55859 -10.7959 -3.47949 -14.5947c-54.1992 -105.771 -161.59 -177.41 -284.52 -177.41s-230.29 71.5898 -284.52 177.4c-1.9209 3.79883 -3.47949 10.3379 -3.47949 14.5947s1.55859 10.7959 3.47949 14.5947c54.1992 105.771 161.59 177.41 284.52 177.41
|
||||
s230.29 -71.5898 284.52 -177.4zM288 48c98.6602 0 189.1 55 237.93 144c-48.8398 89 -139.27 144 -237.93 144s-189.09 -55 -237.93 -144c48.8398 -89 139.279 -144 237.93 -144z" />
|
||||
<glyph glyph-name="eye-slash" unicode="" horiz-adv-x="640"
|
||||
d="M634 -23c3.31738 -2.65137 6.00977 -8.25098 6.00977 -12.498c0 -3.10449 -1.57715 -7.58984 -3.51953 -10.0117l-10 -12.4902c-2.65234 -3.31152 -8.24707 -6 -12.4902 -6c-3.09961 0 -7.58008 1.57227 -10 3.50977l-598 467.49
|
||||
c-3.31738 2.65137 -6.00977 8.25098 -6.00977 12.498c0 3.10449 1.57715 7.58984 3.51953 10.0117l10 12.4902c2.65234 3.31152 8.24707 6 12.4902 6c3.09961 0 7.58008 -1.57227 10 -3.50977zM296.79 301.53c6.33496 1.35059 16.7324 2.45801 23.21 2.46973
|
||||
c60.4805 0 109.36 -47.9102 111.58 -107.85zM343.21 82.46c-6.33496 -1.34375 -16.7334 -2.44629 -23.21 -2.45996c-60.4697 0 -109.35 47.9102 -111.58 107.84zM320 336c-19.8799 0 -39.2803 -2.7998 -58.2197 -7.09961l-46.4102 36.29
|
||||
c32.9199 11.8096 67.9297 18.8096 104.63 18.8096c122.93 0 230.29 -71.5898 284.57 -177.4c1.91992 -3.79883 3.47949 -10.3379 3.47949 -14.5947s-1.55957 -10.7959 -3.47949 -14.5947c-11.7197 -22.7598 -35.4189 -56.4092 -52.9004 -75.1104l-37.7402 29.5
|
||||
c14.333 15.0156 34.0449 41.9854 44 60.2002c-48.8398 89 -139.279 144 -237.93 144zM320 48c19.8896 0 39.2803 2.7998 58.2197 7.08984l46.4102 -36.2803c-32.9199 -11.7598 -67.9297 -18.8096 -104.63 -18.8096c-122.92 0 -230.28 71.5898 -284.51 177.4
|
||||
c-1.9209 3.79883 -3.47949 10.3379 -3.47949 14.5947s1.55859 10.7959 3.47949 14.5947c11.7168 22.7568 35.4111 56.4014 52.8896 75.1006l37.7402 -29.5c-14.3467 -15.0107 -34.0811 -41.9756 -44.0498 -60.1904c48.8496 -89 139.279 -144 237.93 -144z" />
|
||||
<glyph glyph-name="calendar-alt" unicode="" horiz-adv-x="448"
|
||||
d="M148 160h-40c-6.59961 0 -12 5.40039 -12 12v40c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-40c0 -6.59961 -5.40039 -12 -12 -12zM256 172c0 -6.59961 -5.40039 -12 -12 -12h-40c-6.59961 0 -12 5.40039 -12 12v40c0 6.59961 5.40039 12 12 12h40
|
||||
c6.59961 0 12 -5.40039 12 -12v-40zM352 172c0 -6.59961 -5.40039 -12 -12 -12h-40c-6.59961 0 -12 5.40039 -12 12v40c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-40zM256 76c0 -6.59961 -5.40039 -12 -12 -12h-40c-6.59961 0 -12 5.40039 -12 12v40
|
||||
c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-40zM160 76c0 -6.59961 -5.40039 -12 -12 -12h-40c-6.59961 0 -12 5.40039 -12 12v40c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-40zM352 76c0 -6.59961 -5.40039 -12 -12 -12h-40
|
||||
c-6.59961 0 -12 5.40039 -12 12v40c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-40zM448 336v-352c0 -26.5 -21.5 -48 -48 -48h-352c-26.5 0 -48 21.5 -48 48v352c0 26.5 21.5 48 48 48h48v52c0 6.59961 5.40039 12 12 12h40
|
||||
c6.59961 0 12 -5.40039 12 -12v-52h128v52c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-52h48c26.5 0 48 -21.5 48 -48zM400 -10v298h-352v-298c0 -3.2998 2.7002 -6 6 -6h340c3.2998 0 6 2.7002 6 6z" />
|
||||
<glyph glyph-name="comment" unicode=""
|
||||
d="M256 416c141.4 0 256 -93.0996 256 -208s-114.6 -208 -256 -208c-32.7998 0 -64 5.2002 -92.9004 14.2998c-29.0996 -20.5996 -77.5996 -46.2998 -139.1 -46.2998c-9.59961 0 -18.2998 5.7002 -22.0996 14.5c-3.80078 8.7998 -2 19 4.59961 26
|
||||
c0.5 0.400391 31.5 33.7998 46.4004 73.2002c-33 35.0996 -52.9004 78.7002 -52.9004 126.3c0 114.9 114.6 208 256 208zM256 48c114.7 0 208 71.7998 208 160s-93.2998 160 -208 160s-208 -71.7998 -208 -160c0 -42.2002 21.7002 -74.0996 39.7998 -93.4004
|
||||
l20.6006 -21.7998l-10.6006 -28.0996c-5.5 -14.5 -12.5996 -28.1006 -19.8994 -40.2002c23.5996 7.59961 43.1992 18.9004 57.5 29l19.5 13.7998l22.6992 -7.2002c25.3008 -8 51.7002 -12.0996 78.4004 -12.0996z" />
|
||||
<glyph glyph-name="folder" unicode=""
|
||||
d="M464 320c26.5098 0 48 -21.4902 48 -48v-224c0 -26.5098 -21.4902 -48 -48 -48h-416c-26.5098 0 -48 21.4902 -48 48v288c0 26.5098 21.4902 48 48 48h146.74c8.49023 0 16.6299 -3.37012 22.6299 -9.37012l54.6299 -54.6299h192zM464 48v224h-198.62
|
||||
c-8.49023 0 -16.6299 3.37012 -22.6299 9.37012l-54.6299 54.6299h-140.12v-288h416z" />
|
||||
<glyph glyph-name="folder-open" unicode="" horiz-adv-x="576"
|
||||
d="M527.9 224c37.6992 0 60.6992 -41.5 40.6992 -73.4004l-79.8994 -128c-8.7998 -14.0996 -24.2002 -22.5996 -40.7002 -22.5996h-400c-26.5 0 -48 21.5 -48 48v288c0 26.5 21.5 48 48 48h160l64 -64h160c26.5 0 48 -21.5 48 -48v-48h47.9004zM48 330v-233.4l62.9004 104.2
|
||||
c8.69922 14.4004 24.2998 23.2002 41.0996 23.2002h280v42c0 3.2998 -2.7002 6 -6 6h-173.9l-64 64h-134.1c-3.2998 0 -6 -2.7002 -6 -6zM448 48l80 128h-378.8l-77.2002 -128h376z" />
|
||||
<glyph glyph-name="chart-bar" unicode=""
|
||||
d="M396.8 96c-6.39941 0 -12.7998 6.40039 -12.7998 12.7998v230.4c0 6.39941 6.40039 12.7998 12.7998 12.7998h22.4004c6.39941 0 12.7998 -6.40039 12.7998 -12.7998v-230.4c0 -6.39941 -6.40039 -12.7998 -12.7998 -12.7998h-22.4004zM204.8 96
|
||||
c-6.39941 0 -12.7998 6.40039 -12.7998 12.7998v198.4c0 6.39941 6.40039 12.7998 12.7998 12.7998h22.4004c6.39941 0 12.7998 -6.40039 12.7998 -12.7998v-198.4c0 -6.39941 -6.40039 -12.7998 -12.7998 -12.7998h-22.4004zM300.8 96
|
||||
c-6.39941 0 -12.7998 6.40039 -12.7998 12.7998v134.4c0 6.39941 6.40039 12.7998 12.7998 12.7998h22.4004c6.39941 0 12.7998 -6.40039 12.7998 -12.7998v-134.4c0 -6.39941 -6.40039 -12.7998 -12.7998 -12.7998h-22.4004zM496 48c8.83984 0 16 -7.16016 16 -16v-16
|
||||
c0 -8.83984 -7.16016 -16 -16 -16h-464c-17.6699 0 -32 14.3301 -32 32v336c0 8.83984 7.16016 16 16 16h16c8.83984 0 16 -7.16016 16 -16v-320h448zM108.8 96c-6.39941 0 -12.7998 6.40039 -12.7998 12.7998v70.4004c0 6.39941 6.40039 12.7998 12.7998 12.7998h22.4004
|
||||
c6.39941 0 12.7998 -6.40039 12.7998 -12.7998v-70.4004c0 -6.39941 -6.40039 -12.7998 -12.7998 -12.7998h-22.4004z" />
|
||||
<glyph glyph-name="comments" unicode="" horiz-adv-x="576"
|
||||
d="M532 61.7998c15.2998 -30.7002 37.4004 -54.5 37.7998 -54.7998c6.2998 -6.7002 8 -16.5 4.40039 -25c-3.7002 -8.5 -12 -14 -21.2002 -14c-53.5996 0 -96.7002 20.2998 -125.2 38.7998c-19 -4.39941 -39 -6.7998 -59.7998 -6.7998
|
||||
c-86.2002 0 -159.9 40.4004 -191.3 97.7998c-9.7002 1.2002 -19.2002 2.7998 -28.4004 4.90039c-28.5 -18.6006 -71.7002 -38.7998 -125.2 -38.7998c-9.19922 0 -17.5996 5.5 -21.1992 14c-3.7002 8.5 -1.90039 18.2998 4.39941 25
|
||||
c0.400391 0.399414 22.4004 24.1992 37.7002 54.8994c-27.5 27.2002 -44 61.2002 -44 98.2002c0 88.4004 93.0996 160 208 160c86.2998 0 160.3 -40.5 191.8 -98.0996c99.7002 -11.8008 176.2 -77.9004 176.2 -157.9c0 -37.0996 -16.5 -71.0996 -44 -98.2002zM139.2 154.1
|
||||
l19.7998 -4.5c16 -3.69922 32.5 -5.59961 49 -5.59961c86.7002 0 160 51.2998 160 112s-73.2998 112 -160 112s-160 -51.2998 -160 -112c0 -28.7002 16.2002 -50.5996 29.7002 -64l24.7998 -24.5l-15.5 -31.0996c-2.59961 -5.10059 -5.2998 -10.1006 -8 -14.8008
|
||||
c14.5996 5.10059 29 12.3008 43.0996 21.4004zM498.3 96c13.5 13.4004 29.7002 35.2998 29.7002 64c0 49.2002 -48.2998 91.5 -112.7 106c0.299805 -3.2998 0.700195 -6.59961 0.700195 -10c0 -80.9004 -78 -147.5 -179.3 -158.3
|
||||
c29.0996 -29.6006 77.2998 -49.7002 131.3 -49.7002c16.5 0 33 1.90039 49 5.59961l19.9004 4.60059l17.0996 -11.1006c14.0996 -9.09961 28.5 -16.2998 43.0996 -21.3994c-2.69922 4.7002 -5.39941 9.7002 -8 14.7998l-15.5 31.0996z" />
|
||||
<glyph glyph-name="star-half" unicode="" horiz-adv-x="576"
|
||||
d="M288 62.7002v-54.2998l-130.7 -68.6006c-23.3994 -12.2998 -50.8994 7.60059 -46.3994 33.7002l25 145.5l-105.7 103c-19 18.5 -8.5 50.7998 17.7002 54.5996l146.1 21.2002l65.2998 132.4c5.90039 11.8994 17.2998 17.7998 28.7002 17.7998v-68.0996l-62.2002 -126
|
||||
l-139 -20.2002l100.601 -98l-23.7002 -138.4z" />
|
||||
<glyph glyph-name="lemon" unicode=""
|
||||
d="M484.112 420.111c28.1221 -28.123 35.9434 -68.0039 19.0215 -97.0547c-23.0576 -39.584 50.1436 -163.384 -82.3311 -295.86c-132.301 -132.298 -256.435 -59.3594 -295.857 -82.3291c-29.0459 -16.917 -68.9219 -9.11426 -97.0576 19.0205
|
||||
c-28.1221 28.1221 -35.9434 68.0029 -19.0215 97.0547c23.0566 39.5859 -50.1436 163.386 82.3301 295.86c132.308 132.309 256.407 59.3496 295.862 82.332c29.0498 16.9219 68.9307 9.09863 97.0537 -19.0234zM461.707 347.217
|
||||
c13.5166 23.2031 -27.7578 63.7314 -50.4883 50.4912c-66.6025 -38.7939 -165.646 45.5898 -286.081 -74.8457c-120.444 -120.445 -36.0449 -219.472 -74.8447 -286.08c-13.542 -23.2471 27.8145 -63.6953 50.4932 -50.4883
|
||||
c66.6006 38.7949 165.636 -45.5996 286.076 74.8428c120.444 120.445 36.0449 219.472 74.8447 286.08zM291.846 338.481c1.37012 -10.96 -6.40332 -20.957 -17.3643 -22.3271c-54.8467 -6.85547 -135.779 -87.7871 -142.636 -142.636
|
||||
c-1.37305 -10.9883 -11.3984 -18.7334 -22.3262 -17.3643c-10.9609 1.37012 -18.7344 11.3652 -17.3643 22.3262c9.16211 73.2852 104.167 168.215 177.364 177.364c10.9531 1.36816 20.9561 -6.40234 22.3262 -17.3633z" />
|
||||
<glyph glyph-name="credit-card" unicode="" horiz-adv-x="576"
|
||||
d="M527.9 416c26.5996 0 48.0996 -21.5 48.0996 -48v-352c0 -26.5 -21.5 -48 -48.0996 -48h-479.801c-26.5996 0 -48.0996 21.5 -48.0996 48v352c0 26.5 21.5 48 48.0996 48h479.801zM54.0996 368c-3.2998 0 -6 -2.7002 -6 -6v-42h479.801v42c0 3.2998 -2.7002 6 -6 6
|
||||
h-467.801zM521.9 16c3.2998 0 6 2.7002 6 6v170h-479.801v-170c0 -3.2998 2.7002 -6 6 -6h467.801zM192 116v-40c0 -6.59961 -5.40039 -12 -12 -12h-72c-6.59961 0 -12 5.40039 -12 12v40c0 6.59961 5.40039 12 12 12h72c6.59961 0 12 -5.40039 12 -12zM384 116v-40
|
||||
c0 -6.59961 -5.40039 -12 -12 -12h-136c-6.59961 0 -12 5.40039 -12 12v40c0 6.59961 5.40039 12 12 12h136c6.59961 0 12 -5.40039 12 -12z" />
|
||||
<glyph glyph-name="hdd" unicode="" horiz-adv-x="576"
|
||||
d="M567.403 212.358c5.59668 -8.04688 8.59668 -17.6113 8.59668 -27.4121v-136.946c0 -26.5098 -21.4902 -48 -48 -48h-480c-26.5098 0 -48 21.4902 -48 48v136.946c0 8.30957 3.85156 20.5898 8.59668 27.4121l105.08 151.053
|
||||
c7.90625 11.3652 25.5596 20.5889 39.4033 20.5889h0.000976562h269.838h0.000976562c13.8438 0 31.4971 -9.22363 39.4033 -20.5889zM153.081 336l-77.9131 -112h425.664l-77.9131 112h-269.838zM528 48v128h-480v-128h480zM496 112c0 -17.6729 -14.3271 -32 -32 -32
|
||||
s-32 14.3271 -32 32s14.3271 32 32 32s32 -14.3271 32 -32zM400 112c0 -17.6729 -14.3271 -32 -32 -32s-32 14.3271 -32 32s14.3271 32 32 32s32 -14.3271 32 -32z" />
|
||||
<glyph glyph-name="hand-point-right" unicode=""
|
||||
d="M428.8 310.4c45.0996 0 83.2002 -38.1016 83.2002 -83.2002c0 -45.6162 -37.7646 -83.2002 -83.2002 -83.2002h-35.6475c-1.41602 -6.36719 -4.96875 -16.252 -7.92969 -22.0645c2.50586 -22.0059 -3.50293 -44.9775 -15.9844 -62.791
|
||||
c-1.14062 -52.4863 -37.3984 -91.1445 -99.9404 -91.1445h-21.2988c-60.0635 0 -98.5117 40 -127.2 40h-2.67871c-5.74707 -4.95215 -13.5361 -8 -22.1201 -8h-64c-17.6729 0 -32 12.8936 -32 28.7998v230.4c0 15.9062 14.3271 28.7998 32 28.7998h64.001
|
||||
c8.58398 0 16.373 -3.04785 22.1201 -8h2.67871c6.96387 0 14.8623 6.19336 30.1816 23.6689l0.128906 0.148438l0.130859 0.145508c8.85645 9.93652 18.1162 20.8398 25.8506 33.2529c18.7051 30.2471 30.3936 78.7842 75.707 78.7842c56.9277 0 92 -35.2861 92 -83.2002
|
||||
v-0.0839844c0 -6.21777 -0.974609 -16.2148 -2.17578 -22.3154h86.1768zM428.8 192c18.9756 0 35.2002 16.2246 35.2002 35.2002c0 18.7002 -16.7754 35.2002 -35.2002 35.2002h-158.399c0 17.3242 26.3994 35.1992 26.3994 70.3994c0 26.4004 -20.625 35.2002 -44 35.2002
|
||||
c-8.79395 0 -20.4443 -32.7119 -34.9258 -56.0996c-9.07422 -14.5752 -19.5244 -27.2256 -30.7988 -39.875c-16.1094 -18.374 -33.8359 -36.6328 -59.0752 -39.5967v-176.753c42.79 -3.7627 74.5088 -39.6758 120 -39.6758h21.2988
|
||||
c40.5244 0 57.124 22.1973 50.6006 61.3252c14.6113 8.00098 24.1514 33.9785 12.9248 53.625c19.3652 18.2246 17.7871 46.3809 4.9502 61.0498h91.0254zM88 64c0 13.2549 -10.7451 24 -24 24s-24 -10.7451 -24 -24s10.7451 -24 24 -24s24 10.7451 24 24z" />
|
||||
<glyph glyph-name="hand-point-left" unicode=""
|
||||
d="M0 227.2c0 45.0986 38.1006 83.2002 83.2002 83.2002h86.1758c-1.3623 6.91016 -2.17578 14.374 -2.17578 22.3994c0 47.9141 35.0723 83.2002 92 83.2002c45.3135 0 57.002 -48.5371 75.7061 -78.7852c7.73438 -12.4121 16.9951 -23.3154 25.8506 -33.2529
|
||||
l0.130859 -0.145508l0.128906 -0.148438c15.3213 -17.4746 23.2197 -23.668 30.1836 -23.668h2.67871c5.74707 4.95215 13.5361 8 22.1201 8h64c17.6729 0 32 -12.8936 32 -28.7998v-230.4c0 -15.9062 -14.3271 -28.7998 -32 -28.7998h-64
|
||||
c-8.58398 0 -16.373 3.04785 -22.1201 8h-2.67871c-28.6885 0 -67.1367 -40 -127.2 -40h-21.2988c-62.542 0 -98.8008 38.6582 -99.9404 91.1445c-12.4814 17.8135 -18.4922 40.7852 -15.9844 62.791c-2.96094 5.8125 -6.51367 15.6973 -7.92969 22.0645h-35.6465
|
||||
c-45.4355 0 -83.2002 37.584 -83.2002 83.2002zM48 227.2c0 -18.9756 16.2246 -35.2002 35.2002 -35.2002h91.0244c-12.8369 -14.6689 -14.415 -42.8252 4.9502 -61.0498c-11.2256 -19.6465 -1.68652 -45.624 12.9248 -53.625
|
||||
c-6.52246 -39.1279 10.0771 -61.3252 50.6016 -61.3252h21.2988c45.4912 0 77.21 35.9131 120 39.6768v176.752c-25.2393 2.96289 -42.9658 21.2227 -59.0752 39.5967c-11.2744 12.6494 -21.7246 25.2998 -30.7988 39.875
|
||||
c-14.4814 23.3877 -26.1318 56.0996 -34.9258 56.0996c-23.375 0 -44 -8.7998 -44 -35.2002c0 -35.2002 26.3994 -53.0752 26.3994 -70.3994h-158.399c-18.4248 0 -35.2002 -16.5 -35.2002 -35.2002zM448 88c-13.2549 0 -24 -10.7451 -24 -24s10.7451 -24 24 -24
|
||||
s24 10.7451 24 24s-10.7451 24 -24 24z" />
|
||||
<glyph glyph-name="hand-point-up" unicode="" horiz-adv-x="448"
|
||||
d="M105.6 364.8c0 45.0996 38.1016 83.2002 83.2002 83.2002c45.6162 0 83.2002 -37.7646 83.2002 -83.2002v-35.6465c6.36719 -1.41602 16.252 -4.96875 22.0645 -7.92969c22.0059 2.50684 44.9775 -3.50293 62.791 -15.9844
|
||||
c52.4863 -1.14062 91.1445 -37.3984 91.1445 -99.9404v-21.2988c0 -60.0635 -40 -98.5117 -40 -127.2v-2.67871c4.95215 -5.74707 8 -13.5361 8 -22.1201v-64c0 -17.6729 -12.8936 -32 -28.7998 -32h-230.4c-15.9062 0 -28.7998 14.3271 -28.7998 32v64
|
||||
c0 8.58398 3.04785 16.373 8 22.1201v2.67871c0 6.96387 -6.19336 14.8623 -23.6689 30.1816l-0.148438 0.128906l-0.145508 0.130859c-9.93652 8.85645 -20.8398 18.1162 -33.2529 25.8506c-30.2471 18.7051 -78.7842 30.3936 -78.7842 75.707
|
||||
c0 56.9277 35.2861 92 83.2002 92h0.0839844c6.21777 0 16.2148 -0.974609 22.3154 -2.17578v86.1768zM224 364.8c0 18.9756 -16.2246 35.2002 -35.2002 35.2002c-18.7002 0 -35.2002 -16.7754 -35.2002 -35.2002v-158.399c-17.3242 0 -35.1992 26.3994 -70.3994 26.3994
|
||||
c-26.4004 0 -35.2002 -20.625 -35.2002 -44c0 -8.79395 32.7119 -20.4443 56.0996 -34.9258c14.5752 -9.07422 27.2256 -19.5244 39.875 -30.7988c18.374 -16.1094 36.6328 -33.8359 39.5967 -59.0752h176.753c3.7627 42.79 39.6758 74.5088 39.6758 120v21.2988
|
||||
c0 40.5244 -22.1973 57.124 -61.3252 50.6006c-8.00098 14.6113 -33.9785 24.1514 -53.625 12.9248c-18.2246 19.3652 -46.3809 17.7871 -61.0498 4.9502v91.0254zM352 24c-13.2549 0 -24 -10.7451 -24 -24s10.7451 -24 24 -24s24 10.7451 24 24s-10.7451 24 -24 24z" />
|
||||
<glyph glyph-name="hand-point-down" unicode="" horiz-adv-x="448"
|
||||
d="M188.8 -64c-45.0986 0 -83.2002 38.1006 -83.2002 83.2002v86.1758c-6.91016 -1.3623 -14.374 -2.17578 -22.3994 -2.17578c-47.9141 0 -83.2002 35.0723 -83.2002 92c0 45.3135 48.5371 57.002 78.7852 75.707c12.4121 7.73438 23.3154 16.9951 33.2529 25.8506
|
||||
l0.145508 0.130859l0.148438 0.128906c17.4746 15.3213 23.668 23.2197 23.668 30.1836v2.67871c-4.95215 5.74707 -8 13.5361 -8 22.1201v64c0 17.6729 12.8936 32 28.7998 32h230.4c15.9062 0 28.7998 -14.3271 28.7998 -32v-64.001
|
||||
c0 -8.58398 -3.04785 -16.373 -8 -22.1201v-2.67871c0 -28.6885 40 -67.1367 40 -127.2v-21.2988c0 -62.542 -38.6582 -98.8008 -91.1445 -99.9404c-17.8135 -12.4814 -40.7852 -18.4922 -62.791 -15.9844c-5.8125 -2.96094 -15.6973 -6.51367 -22.0645 -7.92969v-35.6465
|
||||
c0 -45.4355 -37.584 -83.2002 -83.2002 -83.2002zM188.8 -16c18.9756 0 35.2002 16.2246 35.2002 35.2002v91.0244c14.6689 -12.8369 42.8252 -14.415 61.0498 4.9502c19.6465 -11.2256 45.624 -1.68652 53.625 12.9248c39.1279 -6.52246 61.3252 10.0771 61.3252 50.6016
|
||||
v21.2988c0 45.4912 -35.9131 77.21 -39.6768 120h-176.752c-2.96289 -25.2393 -21.2227 -42.9658 -39.5967 -59.0752c-12.6494 -11.2744 -25.2998 -21.7246 -39.875 -30.7988c-23.3877 -14.4814 -56.0996 -26.1318 -56.0996 -34.9258c0 -23.375 8.7998 -44 35.2002 -44
|
||||
c35.2002 0 53.0752 26.3994 70.3994 26.3994v-158.399c0 -18.4248 16.5 -35.2002 35.2002 -35.2002zM328 384c0 -13.2549 10.7451 -24 24 -24s24 10.7451 24 24s-10.7451 24 -24 24s-24 -10.7451 -24 -24z" />
|
||||
<glyph glyph-name="copy" unicode="" horiz-adv-x="448"
|
||||
d="M433.941 382.059c7.75977 -7.75977 14.0586 -22.9658 14.0586 -33.9404v-268.118c0 -26.5098 -21.4902 -48 -48 -48h-80v-48c0 -26.5098 -21.4902 -48 -48 -48h-224c-26.5098 0 -48 21.4902 -48 48v320c0 26.5098 21.4902 48 48 48h80v48c0 26.5098 21.4902 48 48 48
|
||||
h172.118c10.9746 0 26.1807 -6.29883 33.9404 -14.0586zM266 -16c3.31152 0 6 2.68848 6 6v42h-96c-26.5098 0 -48 21.4902 -48 48v224h-74c-3.31152 0 -6 -2.68848 -6 -6v-308c0 -3.31152 2.68848 -6 6 -6h212zM394 80c3.31152 0 6 2.68848 6 6v202h-88
|
||||
c-13.2549 0 -24 10.7451 -24 24v88h-106c-3.31152 0 -6 -2.68848 -6 -6v-308c0 -3.31152 2.68848 -6 6 -6h212zM400 336v9.63184v0.000976562c0 1.37207 -0.787109 3.27246 -1.75684 4.24219l-48.3682 48.3682c-1.12598 1.125 -2.65234 1.75684 -4.24316 1.75684h-9.63184
|
||||
v-64h64z" />
|
||||
<glyph glyph-name="save" unicode="" horiz-adv-x="448"
|
||||
d="M433.941 318.059c7.75977 -7.75977 14.0586 -22.9658 14.0586 -33.9404v-268.118c0 -26.5098 -21.4902 -48 -48 -48h-352c-26.5098 0 -48 21.4902 -48 48v352c0 26.5098 21.4902 48 48 48h268.118c10.9746 0 26.1807 -6.29883 33.9404 -14.0586zM272 368h-128v-80h128v80
|
||||
zM394 16c3.31152 0 6 2.68848 6 6v259.632v0.000976562c0 1.37207 -0.787109 3.27246 -1.75684 4.24219l-78.2432 78.2432v-100.118c0 -13.2549 -10.7451 -24 -24 -24h-176c-13.2549 0 -24 10.7451 -24 24v104h-42c-3.31152 0 -6 -2.68848 -6 -6v-340
|
||||
c0 -3.31152 2.68848 -6 6 -6h340zM224 216c48.5234 0 88 -39.4766 88 -88s-39.4766 -88 -88 -88s-88 39.4766 -88 88s39.4766 88 88 88zM224 88c22.0557 0 40 17.9443 40 40s-17.9443 40 -40 40s-40 -17.9443 -40 -40s17.9443 -40 40 -40z" />
|
||||
<glyph glyph-name="square" unicode="" horiz-adv-x="448"
|
||||
d="M400 416c26.5 0 48 -21.5 48 -48v-352c0 -26.5 -21.5 -48 -48 -48h-352c-26.5 0 -48 21.5 -48 48v352c0 26.5 21.5 48 48 48h352zM394 16c3.2998 0 6 2.7002 6 6v340c0 3.2998 -2.7002 6 -6 6h-340c-3.2998 0 -6 -2.7002 -6 -6v-340c0 -3.2998 2.7002 -6 6 -6h340z" />
|
||||
<glyph glyph-name="envelope" unicode=""
|
||||
d="M464 384c26.5098 0 48 -21.4902 48 -48v-288c0 -26.5098 -21.4902 -48 -48 -48h-416c-26.5098 0 -48 21.4902 -48 48v288c0 26.5098 21.4902 48 48 48h416zM464 336h-416v-40.8047c22.4248 -18.2627 58.1797 -46.6602 134.587 -106.49
|
||||
c16.834 -13.2422 50.2051 -45.0762 73.4131 -44.7012c23.2119 -0.371094 56.5723 31.4541 73.4131 44.7012c76.4189 59.8389 112.165 88.2305 134.587 106.49v40.8047zM48 48h416v185.601c-22.915 -18.252 -55.4189 -43.8691 -104.947 -82.6523
|
||||
c-22.5439 -17.748 -60.3359 -55.1787 -103.053 -54.9473c-42.9277 -0.231445 -81.2051 37.75 -103.062 54.9551c-49.5293 38.7842 -82.0244 64.3945 -104.938 82.6455v-185.602z" />
|
||||
<glyph glyph-name="lightbulb" unicode="" horiz-adv-x="352"
|
||||
d="M176 368c8.83984 0 16 -7.16016 16 -16s-7.16016 -16 -16 -16c-35.2803 0 -64 -28.7002 -64 -64c0 -8.83984 -7.16016 -16 -16 -16s-16 7.16016 -16 16c0 52.9404 43.0596 96 96 96zM96.0596 -11.1699l-0.0400391 43.1797h159.961l-0.0507812 -43.1797
|
||||
c-0.00976562 -3.13965 -0.939453 -6.21973 -2.67969 -8.83984l-24.5098 -36.8398c-2.95996 -4.45996 -7.95996 -7.14062 -13.3203 -7.14062h-78.8496c-5.35059 0 -10.3506 2.68066 -13.3203 7.14062l-24.5098 36.8398c-1.75 2.62012 -2.68066 5.68945 -2.68066 8.83984z
|
||||
M176 448c97.2002 0 176 -78.7998 176 -176c0 -44.3701 -16.4502 -84.8496 -43.5498 -115.79c-16.6406 -18.9795 -42.7402 -58.79 -52.4199 -92.1602v-0.0498047h-48v0.0996094c0.00390625 4.04199 0.999023 10.4482 2.21973 14.3008
|
||||
c5.67969 17.9893 22.9902 64.8496 62.0996 109.46c20.4102 23.29 31.6504 53.1699 31.6504 84.1396c0 70.5801 -57.4199 128 -128 128c-68.2803 0 -128.15 -54.3604 -127.95 -128c0.0898438 -30.9902 11.0703 -60.71 31.6104 -84.1396
|
||||
c39.3496 -44.9004 56.5801 -91.8604 62.1699 -109.67c1.42969 -4.56055 2.13965 -9.30078 2.15039 -14.0703v-0.120117h-48v0.0595703c-9.68066 33.3604 -35.7803 73.1709 -52.4209 92.1602c-27.1094 30.9307 -43.5596 71.4102 -43.5596 115.78
|
||||
c0 93.0303 73.7197 176 176 176z" />
|
||||
<glyph glyph-name="bell" unicode="" horiz-adv-x="448"
|
||||
d="M439.39 85.71c6 -6.44043 8.66016 -14.1602 8.61035 -21.71c-0.0996094 -16.4004 -12.9805 -32 -32.0996 -32h-383.801c-19.1191 0 -31.9893 15.5996 -32.0996 32c-0.0498047 7.5498 2.61035 15.2598 8.61035 21.71c19.3193 20.7598 55.4697 51.9902 55.4697 154.29
|
||||
c0 77.7002 54.4795 139.9 127.939 155.16v20.8398c0 17.6699 14.3203 32 31.9805 32s31.9805 -14.3301 31.9805 -32v-20.8398c73.46 -15.2598 127.939 -77.46 127.939 -155.16c0 -102.3 36.1504 -133.53 55.4697 -154.29zM67.5303 80h312.939
|
||||
c-21.2197 27.96 -44.4199 74.3203 -44.5293 159.42c0 0.200195 0.0595703 0.379883 0.0595703 0.580078c0 61.8604 -50.1396 112 -112 112s-112 -50.1396 -112 -112c0 -0.200195 0.0595703 -0.379883 0.0595703 -0.580078
|
||||
c-0.109375 -85.0898 -23.3096 -131.45 -44.5293 -159.42zM224 -64c-35.3203 0 -63.9697 28.6504 -63.9697 64h127.939c0 -35.3496 -28.6494 -64 -63.9697 -64z" />
|
||||
<glyph glyph-name="hospital" unicode="" horiz-adv-x="448"
|
||||
d="M128 204v40c0 6.62695 5.37305 12 12 12h40c6.62695 0 12 -5.37305 12 -12v-40c0 -6.62695 -5.37305 -12 -12 -12h-40c-6.62695 0 -12 5.37305 -12 12zM268 192c-6.62695 0 -12 5.37305 -12 12v40c0 6.62695 5.37305 12 12 12h40c6.62695 0 12 -5.37305 12 -12v-40
|
||||
c0 -6.62695 -5.37305 -12 -12 -12h-40zM192 108c0 -6.62695 -5.37305 -12 -12 -12h-40c-6.62695 0 -12 5.37305 -12 12v40c0 6.62695 5.37305 12 12 12h40c6.62695 0 12 -5.37305 12 -12v-40zM268 96c-6.62695 0 -12 5.37305 -12 12v40c0 6.62695 5.37305 12 12 12h40
|
||||
c6.62695 0 12 -5.37305 12 -12v-40c0 -6.62695 -5.37305 -12 -12 -12h-40zM448 -28v-36h-448v36c0 6.62695 5.37305 12 12 12h19.5v378.965c0 11.6172 10.7451 21.0352 24 21.0352h88.5v40c0 13.2549 10.7451 24 24 24h112c13.2549 0 24 -10.7451 24 -24v-40h88.5
|
||||
c13.2549 0 24 -9.41797 24 -21.0352v-378.965h19.5c6.62695 0 12 -5.37305 12 -12zM79.5 -15h112.5v67c0 6.62695 5.37305 12 12 12h40c6.62695 0 12 -5.37305 12 -12v-67h112.5v351h-64.5v-24c0 -13.2549 -10.7451 -24 -24 -24h-112c-13.2549 0 -24 10.7451 -24 24v24
|
||||
h-64.5v-351zM266 384h-26v26c0 3.31152 -2.68848 6 -6 6h-20c-3.31152 0 -6 -2.68848 -6 -6v-26h-26c-3.31152 0 -6 -2.68848 -6 -6v-20c0 -3.31152 2.68848 -6 6 -6h26v-26c0 -3.31152 2.68848 -6 6 -6h20c3.31152 0 6 2.68848 6 6v26h26c3.31152 0 6 2.68848 6 6v20
|
||||
c0 3.31152 -2.68848 6 -6 6z" />
|
||||
<glyph glyph-name="plus-square" unicode="" horiz-adv-x="448"
|
||||
d="M352 208v-32c0 -6.59961 -5.40039 -12 -12 -12h-88v-88c0 -6.59961 -5.40039 -12 -12 -12h-32c-6.59961 0 -12 5.40039 -12 12v88h-88c-6.59961 0 -12 5.40039 -12 12v32c0 6.59961 5.40039 12 12 12h88v88c0 6.59961 5.40039 12 12 12h32c6.59961 0 12 -5.40039 12 -12
|
||||
v-88h88c6.59961 0 12 -5.40039 12 -12zM448 368v-352c0 -26.5 -21.5 -48 -48 -48h-352c-26.5 0 -48 21.5 -48 48v352c0 26.5 21.5 48 48 48h352c26.5 0 48 -21.5 48 -48zM400 22v340c0 3.2998 -2.7002 6 -6 6h-340c-3.2998 0 -6 -2.7002 -6 -6v-340
|
||||
c0 -3.2998 2.7002 -6 6 -6h340c3.2998 0 6 2.7002 6 6z" />
|
||||
<glyph glyph-name="circle" unicode=""
|
||||
d="M256 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM256 -8c110.5 0 200 89.5 200 200s-89.5 200 -200 200s-200 -89.5 -200 -200s89.5 -200 200 -200z" />
|
||||
<glyph glyph-name="smile" unicode="" horiz-adv-x="496"
|
||||
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM168 208c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32
|
||||
s32 -14.2998 32 -32s-14.2998 -32 -32 -32zM328 208c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32s32 -14.2998 32 -32s-14.2998 -32 -32 -32zM332 135.4c8.5 10.1992 23.7002 11.5 33.7998 3.09961c10.2002 -8.5 11.6006 -23.5996 3.10059 -33.7998
|
||||
c-30 -36 -74.1006 -56.6006 -120.9 -56.6006s-90.9004 20.6006 -120.9 56.6006c-8.39941 10.2002 -7.09961 25.2998 3.10059 33.7998c10.0996 8.40039 25.2998 7.09961 33.7998 -3.09961c20.7998 -25.1006 51.5 -39.4004 84 -39.4004s63.2002 14.4004 84 39.4004z" />
|
||||
<glyph glyph-name="frown" unicode="" horiz-adv-x="496"
|
||||
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM168 208c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32
|
||||
s32 -14.2998 32 -32s-14.2998 -32 -32 -32zM328 272c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32s-32 14.2998 -32 32s14.2998 32 32 32zM248 144c40.2002 0 78 -17.7002 103.8 -48.5996c8.40039 -10.2002 7.10059 -25.3008 -3.09961 -33.8008
|
||||
c-10.7002 -8.7998 -25.7002 -6.59961 -33.7998 3.10059c-16.6006 20 -41 31.3994 -66.9004 31.3994s-50.2998 -11.5 -66.9004 -31.3994c-8.5 -10.2002 -23.5996 -11.5 -33.7998 -3.10059c-10.2002 8.5 -11.5996 23.6006 -3.09961 33.8008
|
||||
c25.7998 30.8994 63.5996 48.5996 103.8 48.5996z" />
|
||||
<glyph glyph-name="meh" unicode="" horiz-adv-x="496"
|
||||
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM168 208c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32
|
||||
s32 -14.2998 32 -32s-14.2998 -32 -32 -32zM328 272c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32s-32 14.2998 -32 32s14.2998 32 32 32zM336 128c13.2002 0 24 -10.7998 24 -24s-10.7998 -24 -24 -24h-176c-13.2002 0 -24 10.7998 -24 24s10.7998 24 24 24h176z
|
||||
" />
|
||||
<glyph glyph-name="keyboard" unicode="" horiz-adv-x="576"
|
||||
d="M528 384c26.5098 0 48 -21.4902 48 -48v-288c0 -26.5098 -21.4902 -48 -48 -48h-480c-26.5098 0 -48 21.4902 -48 48v288c0 26.5098 21.4902 48 48 48h480zM536 48v288c0 4.41113 -3.58887 8 -8 8h-480c-4.41113 0 -8 -3.58887 -8 -8v-288c0 -4.41113 3.58887 -8 8 -8
|
||||
h480c4.41113 0 8 3.58887 8 8zM170 178c0 -6.62695 -5.37305 -12 -12 -12h-28c-6.62695 0 -12 5.37305 -12 12v28c0 6.62695 5.37305 12 12 12h28c6.62695 0 12 -5.37305 12 -12v-28zM266 178c0 -6.62695 -5.37305 -12 -12 -12h-28c-6.62695 0 -12 5.37305 -12 12v28
|
||||
c0 6.62695 5.37305 12 12 12h28c6.62695 0 12 -5.37305 12 -12v-28zM362 178c0 -6.62695 -5.37305 -12 -12 -12h-28c-6.62695 0 -12 5.37305 -12 12v28c0 6.62695 5.37305 12 12 12h28c6.62695 0 12 -5.37305 12 -12v-28zM458 178c0 -6.62695 -5.37305 -12 -12 -12h-28
|
||||
c-6.62695 0 -12 5.37305 -12 12v28c0 6.62695 5.37305 12 12 12h28c6.62695 0 12 -5.37305 12 -12v-28zM122 96c0 -6.62695 -5.37305 -12 -12 -12h-28c-6.62695 0 -12 5.37305 -12 12v28c0 6.62695 5.37305 12 12 12h28c6.62695 0 12 -5.37305 12 -12v-28zM506 96
|
||||
c0 -6.62695 -5.37305 -12 -12 -12h-28c-6.62695 0 -12 5.37305 -12 12v28c0 6.62695 5.37305 12 12 12h28c6.62695 0 12 -5.37305 12 -12v-28zM122 260c0 -6.62695 -5.37305 -12 -12 -12h-28c-6.62695 0 -12 5.37305 -12 12v28c0 6.62695 5.37305 12 12 12h28
|
||||
c6.62695 0 12 -5.37305 12 -12v-28zM218 260c0 -6.62695 -5.37305 -12 -12 -12h-28c-6.62695 0 -12 5.37305 -12 12v28c0 6.62695 5.37305 12 12 12h28c6.62695 0 12 -5.37305 12 -12v-28zM314 260c0 -6.62695 -5.37305 -12 -12 -12h-28c-6.62695 0 -12 5.37305 -12 12v28
|
||||
c0 6.62695 5.37305 12 12 12h28c6.62695 0 12 -5.37305 12 -12v-28zM410 260c0 -6.62695 -5.37305 -12 -12 -12h-28c-6.62695 0 -12 5.37305 -12 12v28c0 6.62695 5.37305 12 12 12h28c6.62695 0 12 -5.37305 12 -12v-28zM506 260c0 -6.62695 -5.37305 -12 -12 -12h-28
|
||||
c-6.62695 0 -12 5.37305 -12 12v28c0 6.62695 5.37305 12 12 12h28c6.62695 0 12 -5.37305 12 -12v-28zM408 102c0 -6.62695 -5.37305 -12 -12 -12h-216c-6.62695 0 -12 5.37305 -12 12v16c0 6.62695 5.37305 12 12 12h216c6.62695 0 12 -5.37305 12 -12v-16z" />
|
||||
<glyph glyph-name="calendar" unicode="" horiz-adv-x="448"
|
||||
d="M400 384c26.5 0 48 -21.5 48 -48v-352c0 -26.5 -21.5 -48 -48 -48h-352c-26.5 0 -48 21.5 -48 48v352c0 26.5 21.5 48 48 48h48v52c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-52h128v52c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12
|
||||
v-52h48zM394 -16c3.2998 0 6 2.7002 6 6v298h-352v-298c0 -3.2998 2.7002 -6 6 -6h340z" />
|
||||
<glyph glyph-name="play-circle" unicode=""
|
||||
d="M371.7 210c16.3994 -9.2002 16.3994 -32.9004 0 -42l-176 -101c-15.9004 -8.7998 -35.7002 2.59961 -35.7002 21v208c0 18.5 19.9004 29.7998 35.7002 21zM504 192c0 -137 -111 -248 -248 -248s-248 111 -248 248s111 248 248 248s248 -111 248 -248zM56 192
|
||||
c0 -110.5 89.5 -200 200 -200s200 89.5 200 200s-89.5 200 -200 200s-200 -89.5 -200 -200z" />
|
||||
<glyph glyph-name="minus-square" unicode="" horiz-adv-x="448"
|
||||
d="M108 164c-6.59961 0 -12 5.40039 -12 12v32c0 6.59961 5.40039 12 12 12h232c6.59961 0 12 -5.40039 12 -12v-32c0 -6.59961 -5.40039 -12 -12 -12h-232zM448 368v-352c0 -26.5 -21.5 -48 -48 -48h-352c-26.5 0 -48 21.5 -48 48v352c0 26.5 21.5 48 48 48h352
|
||||
c26.5 0 48 -21.5 48 -48zM400 22v340c0 3.2998 -2.7002 6 -6 6h-340c-3.2998 0 -6 -2.7002 -6 -6v-340c0 -3.2998 2.7002 -6 6 -6h340c3.2998 0 6 2.7002 6 6z" />
|
||||
<glyph glyph-name="check-square" unicode="" horiz-adv-x="448"
|
||||
d="M400 416c26.5098 0 48 -21.4902 48 -48v-352c0 -26.5098 -21.4902 -48 -48 -48h-352c-26.5098 0 -48 21.4902 -48 48v352c0 26.5098 21.4902 48 48 48h352zM400 16v352h-352v-352h352zM364.136 257.724l-172.589 -171.204
|
||||
c-4.70508 -4.66699 -12.3027 -4.63672 -16.9697 0.0683594l-90.7812 91.5156c-4.66699 4.70508 -4.63672 12.3037 0.0693359 16.9717l22.7188 22.5361c4.70508 4.66699 12.3027 4.63672 16.9697 -0.0693359l59.792 -60.2773l141.353 140.217
|
||||
c4.70508 4.66699 12.3027 4.63672 16.9697 -0.0683594l22.5361 -22.7178c4.66699 -4.70605 4.63672 -12.3047 -0.0683594 -16.9717z" />
|
||||
<glyph glyph-name="share-square" unicode="" horiz-adv-x="576"
|
||||
d="M561.938 289.94c18.75 -18.7402 18.75 -49.1406 0 -67.8809l-143.998 -144c-29.9727 -29.9727 -81.9404 -9.05273 -81.9404 33.9404v53.7998c-101.266 -7.83691 -99.625 -31.6406 -84.1104 -78.7598c14.2285 -43.0889 -33.4736 -79.248 -71.0195 -55.7402
|
||||
c-51.6924 32.3057 -84.8701 83.0635 -84.8701 144.76c0 39.3408 12.2197 72.7402 36.3301 99.3008c19.8398 21.8398 47.7402 38.4697 82.9102 49.4199c36.7295 11.4395 78.3096 16.1094 120.76 17.9893v57.1982c0 42.9355 51.9258 63.9541 81.9404 33.9404zM384 112l144 144
|
||||
l-144 144v-104.09c-110.86 -0.90332 -240 -10.5166 -240 -119.851c0 -52.1396 32.79 -85.6094 62.3096 -104.06c-39.8174 120.65 48.999 141.918 177.69 143.84v-103.84zM408.74 27.5068c6.14844 1.75684 15.5449 5.92383 20.9736 9.30273
|
||||
c7.97656 4.95215 18.2861 -0.825195 18.2861 -10.2139v-42.5957c0 -26.5098 -21.4902 -48 -48 -48h-352c-26.5098 0 -48 21.4902 -48 48v352c0 26.5098 21.4902 48 48 48h132c6.62695 0 12 -5.37305 12 -12v-4.48633c0 -4.91699 -2.9873 -9.36914 -7.56934 -11.1514
|
||||
c-13.7021 -5.33105 -26.3955 -11.5371 -38.0498 -18.585c-1.59668 -0.974609 -4.41016 -1.77051 -6.28027 -1.77734h-86.1006c-3.31152 0 -6 -2.68848 -6 -6v-340c0 -3.31152 2.68848 -6 6 -6h340c3.31152 0 6 2.68848 6 6v25.9658c0 5.37012 3.5791 10.0596 8.74023 11.541
|
||||
z" />
|
||||
<glyph glyph-name="compass" unicode="" horiz-adv-x="496"
|
||||
d="M347.94 318.14c16.6592 7.61035 33.8096 -9.54004 26.1992 -26.1992l-65.9697 -144.341c-2.73047 -5.97363 -9.7959 -13.0391 -15.7695 -15.7695l-144.341 -65.9697c-16.6592 -7.61035 -33.8096 9.5498 -26.1992 26.1992l65.9697 144.341
|
||||
c2.73047 5.97363 9.7959 13.0391 15.7695 15.7695zM270.58 169.42c12.4697 12.4697 12.4697 32.6904 0 45.1602s-32.6904 12.4697 -45.1602 0s-12.4697 -32.6904 0 -45.1602s32.6904 -12.4697 45.1602 0zM248 440c136.97 0 248 -111.03 248 -248s-111.03 -248 -248 -248
|
||||
s-248 111.03 -248 248s111.03 248 248 248zM248 -8c110.28 0 200 89.7197 200 200s-89.7197 200 -200 200s-200 -89.7197 -200 -200s89.7197 -200 200 -200z" />
|
||||
<glyph glyph-name="caret-square-down" unicode="" horiz-adv-x="448"
|
||||
d="M125.1 240h197.801c10.6992 0 16.0996 -13 8.5 -20.5l-98.9004 -98.2998c-4.7002 -4.7002 -12.2002 -4.7002 -16.9004 0l-98.8994 98.2998c-7.7002 7.5 -2.2998 20.5 8.39941 20.5zM448 368v-352c0 -26.5 -21.5 -48 -48 -48h-352c-26.5 0 -48 21.5 -48 48v352
|
||||
c0 26.5 21.5 48 48 48h352c26.5 0 48 -21.5 48 -48zM400 22v340c0 3.2998 -2.7002 6 -6 6h-340c-3.2998 0 -6 -2.7002 -6 -6v-340c0 -3.2998 2.7002 -6 6 -6h340c3.2998 0 6 2.7002 6 6z" />
|
||||
<glyph glyph-name="caret-square-up" unicode="" horiz-adv-x="448"
|
||||
d="M322.9 144h-197.801c-10.6992 0 -16.0996 13 -8.5 20.5l98.9004 98.2998c4.7002 4.7002 12.2002 4.7002 16.9004 0l98.8994 -98.2998c7.7002 -7.5 2.2998 -20.5 -8.39941 -20.5zM448 368v-352c0 -26.5 -21.5 -48 -48 -48h-352c-26.5 0 -48 21.5 -48 48v352
|
||||
c0 26.5 21.5 48 48 48h352c26.5 0 48 -21.5 48 -48zM400 22v340c0 3.2998 -2.7002 6 -6 6h-340c-3.2998 0 -6 -2.7002 -6 -6v-340c0 -3.2998 2.7002 -6 6 -6h340c3.2998 0 6 2.7002 6 6z" />
|
||||
<glyph glyph-name="caret-square-right" unicode="" horiz-adv-x="448"
|
||||
d="M176 93.0996v197.801c0 10.6992 13 16.0996 20.5 8.5l98.2998 -98.9004c4.7002 -4.7002 4.7002 -12.2002 0 -16.9004l-98.2998 -98.8994c-7.5 -7.7002 -20.5 -2.2998 -20.5 8.39941zM448 368v-352c0 -26.5 -21.5 -48 -48 -48h-352c-26.5 0 -48 21.5 -48 48v352
|
||||
c0 26.5 21.5 48 48 48h352c26.5 0 48 -21.5 48 -48zM400 22v340c0 3.2998 -2.7002 6 -6 6h-340c-3.2998 0 -6 -2.7002 -6 -6v-340c0 -3.2998 2.7002 -6 6 -6h340c3.2998 0 6 2.7002 6 6z" />
|
||||
<glyph glyph-name="file" unicode="" horiz-adv-x="384"
|
||||
d="M369.9 350.1c9 -9 14.0996 -21.2998 14.0996 -34v-332.1c0 -26.5 -21.5 -48 -48 -48h-288c-26.5 0 -48 21.5 -48 48v416c0 26.5 21.5 48 48 48.0996h204.1c12.7002 0 24.9004 -5.09961 33.9004 -14.0996zM332.1 320l-76.0996 76.0996v-76.0996h76.0996zM48 -16h288v288
|
||||
h-104c-13.2998 0 -24 10.7002 -24 24v104h-160v-416z" />
|
||||
<glyph glyph-name="file-alt" unicode="" horiz-adv-x="384"
|
||||
d="M288 200v-28c0 -6.59961 -5.40039 -12 -12 -12h-168c-6.59961 0 -12 5.40039 -12 12v28c0 6.59961 5.40039 12 12 12h168c6.59961 0 12 -5.40039 12 -12zM276 128c6.59961 0 12 -5.40039 12 -12v-28c0 -6.59961 -5.40039 -12 -12 -12h-168c-6.59961 0 -12 5.40039 -12 12
|
||||
v28c0 6.59961 5.40039 12 12 12h168zM384 316.1v-332.1c0 -26.5 -21.5 -48 -48 -48h-288c-26.5 0 -48 21.5 -48 48v416c0 26.5 21.5 48 48 48h204.1c12.7002 0 24.9004 -5.09961 33.9004 -14.0996l83.9004 -83.9004c9 -8.90039 14.0996 -21.2002 14.0996 -33.9004z
|
||||
M256 396.1v-76.0996h76.0996zM336 -16v288h-104c-13.2998 0 -24 10.7002 -24 24v104h-160v-416h288z" />
|
||||
<glyph glyph-name="thumbs-up" unicode=""
|
||||
d="M466.27 161.31c4.6748 -22.6465 0.864258 -44.5371 -8.98926 -62.9893c2.95898 -23.8682 -4.02148 -48.5654 -17.3398 -66.9902c-0.954102 -55.9072 -35.8232 -95.3301 -112.94 -95.3301c-7 0 -15 0.00976562 -22.2197 0.00976562
|
||||
c-102.742 0 -133.293 38.9395 -177.803 39.9404c-3.56934 -13.7764 -16.085 -23.9502 -30.9775 -23.9502h-64c-17.6729 0 -32 14.3271 -32 32v240c0 17.6729 14.3271 32 32 32h98.7598c19.1455 16.9531 46.0137 60.6533 68.7598 83.4004
|
||||
c13.667 13.667 10.1533 108.6 71.7607 108.6c57.5801 0 95.2695 -31.9355 95.2695 -104.73c0 -18.4092 -3.92969 -33.7295 -8.84961 -46.5391h36.4795c48.6025 0 85.8203 -41.5654 85.8203 -85.5801c0 -19.1504 -4.95996 -34.9902 -13.7305 -49.8408zM404.52 107.48
|
||||
c21.5811 20.3838 18.6992 51.0645 5.21094 65.6191c9.44922 0 22.3594 18.9102 22.2695 37.8105c-0.0898438 18.9102 -16.71 37.8203 -37.8203 37.8203h-103.989c0 37.8193 28.3594 55.3691 28.3594 94.5391c0 23.75 0 56.7305 -47.2695 56.7305
|
||||
c-18.9102 -18.9102 -9.45996 -66.1797 -37.8203 -94.54c-26.5596 -26.5703 -66.1797 -97.46 -94.54 -97.46h-10.9199v-186.17c53.6113 0 100.001 -37.8203 171.64 -37.8203h37.8203c35.5117 0 60.8203 17.1201 53.1201 65.9004
|
||||
c15.2002 8.16016 26.5 36.4395 13.9395 57.5703zM88 16c0 13.2549 -10.7451 24 -24 24s-24 -10.7451 -24 -24s10.7451 -24 24 -24s24 10.7451 24 24z" />
|
||||
<glyph glyph-name="thumbs-down" unicode=""
|
||||
d="M466.27 222.69c8.77051 -14.8506 13.7305 -30.6904 13.7305 -49.8408c0 -44.0146 -37.2178 -85.5801 -85.8203 -85.5801h-36.4795c4.91992 -12.8096 8.84961 -28.1299 8.84961 -46.5391c0 -72.7949 -37.6895 -104.73 -95.2695 -104.73
|
||||
c-61.6074 0 -58.0938 94.9326 -71.7607 108.6c-22.7461 22.7471 -49.6133 66.4473 -68.7598 83.4004h-7.05176c-5.5332 -9.56152 -15.8662 -16 -27.708 -16h-64c-17.6729 0 -32 14.3271 -32 32v240c0 17.6729 14.3271 32 32 32h64c8.11328 0 15.5146 -3.02539 21.1553 -8
|
||||
h10.8447c40.9971 0 73.1953 39.9902 176.78 39.9902c7.21973 0 15.2197 0.00976562 22.2197 0.00976562c77.1172 0 111.986 -39.4229 112.94 -95.3301c13.3184 -18.4248 20.2979 -43.1221 17.3398 -66.9902c9.85352 -18.4521 13.6641 -40.3428 8.98926 -62.9893zM64 152
|
||||
c13.2549 0 24 10.7451 24 24s-10.7451 24 -24 24s-24 -10.7451 -24 -24s10.7451 -24 24 -24zM394.18 135.27c21.1104 0 37.7305 18.9102 37.8203 37.8203c0.0898438 18.9004 -12.8203 37.8105 -22.2695 37.8105c13.4883 14.5547 16.3701 45.2354 -5.21094 65.6191
|
||||
c12.5605 21.1309 1.26074 49.4102 -13.9395 57.5703c7.7002 48.7803 -17.6084 65.9004 -53.1201 65.9004h-37.8203c-71.6387 0 -118.028 -37.8203 -171.64 -37.8203v-186.17h10.9199c28.3604 0 67.9805 -70.8896 94.54 -97.46
|
||||
c28.3604 -28.3604 18.9102 -75.6299 37.8203 -94.54c47.2695 0 47.2695 32.9805 47.2695 56.7305c0 39.1699 -28.3594 56.7197 -28.3594 94.5391h103.989z" />
|
||||
<glyph glyph-name="sun" unicode=""
|
||||
d="M494.2 226.1c11.2002 -7.59961 17.7998 -20.0996 17.8994 -33.6992c0 -13.4004 -6.69922 -26 -17.7998 -33.5l-59.7998 -40.5l13.7002 -71c2.5 -13.2002 -1.60059 -26.8008 -11.1006 -36.3008s-22.8994 -13.7998 -36.2998 -11.0996l-70.8994 13.7002l-40.4004 -59.9004
|
||||
c-7.5 -11.0996 -20.0996 -17.7998 -33.5 -17.7998s-26 6.7002 -33.5 17.9004l-40.4004 59.8994l-70.7998 -13.7002c-13.3994 -2.59961 -26.7998 1.60059 -36.2998 11.1006s-13.7002 23.0996 -11.0996 36.2998l13.6992 71l-59.7998 40.5
|
||||
c-11.0996 7.5 -17.7998 20 -17.7998 33.5s6.59961 26 17.7998 33.5996l59.7998 40.5l-13.6992 71c-2.60059 13.2002 1.59961 26.7002 11.0996 36.3008c9.5 9.59961 23 13.6992 36.2998 11.1992l70.7998 -13.6992l40.4004 59.8994c15.0996 22.2998 51.9004 22.2998 67 0
|
||||
l40.4004 -59.8994l70.8994 13.6992c13 2.60059 26.6006 -1.59961 36.2002 -11.0996c9.5 -9.59961 13.7002 -23.2002 11.0996 -36.4004l-13.6992 -71zM381.3 140.5l76.7998 52.0996l-76.7998 52l17.6006 91.1006l-91 -17.6006l-51.9004 76.9004l-51.7998 -76.7998
|
||||
l-91 17.5996l17.5996 -91.2002l-76.7998 -52l76.7998 -52l-17.5996 -91.1992l90.8994 17.5996l51.9004 -77l51.9004 76.9004l91 -17.6006zM256 296c57.2998 0 104 -46.7002 104 -104s-46.7002 -104 -104 -104s-104 46.7002 -104 104s46.7002 104 104 104zM256 136
|
||||
c30.9004 0 56 25.0996 56 56s-25.0996 56 -56 56s-56 -25.0996 -56 -56s25.0996 -56 56 -56z" />
|
||||
<glyph glyph-name="moon" unicode=""
|
||||
d="M279.135 -64c-141.424 0 -256 114.64 -256 256c0 141.425 114.641 256 256 256c13.0068 -0.00195312 33.9443 -1.91797 46.7354 -4.27734c44.0205 -8.13086 53.7666 -66.8691 15.0215 -88.9189c-41.374 -23.5439 -67.4336 -67.4121 -67.4336 -115.836
|
||||
c0 -83.5234 75.9238 -146.475 158.272 -130.792c43.6904 8.32129 74.5186 -42.5693 46.248 -77.4004c-47.8613 -58.9717 -120.088 -94.7754 -198.844 -94.7754zM279.135 400c-114.875 0 -208 -93.125 -208 -208s93.125 -208 208 -208
|
||||
c65.2314 0 123.439 30.0361 161.575 77.0244c-111.611 -21.2568 -215.252 64.0957 -215.252 177.943c0 67.5127 36.9326 126.392 91.6934 157.555c-12.3271 2.27637 -25.0312 3.47754 -38.0166 3.47754z" />
|
||||
<glyph glyph-name="caret-square-left" unicode="" horiz-adv-x="448"
|
||||
d="M272 290.9v-197.801c0 -10.6992 -13 -16.0996 -20.5 -8.5l-98.2998 98.9004c-4.7002 4.7002 -4.7002 12.2002 0 16.9004l98.2998 98.8994c7.5 7.7002 20.5 2.2998 20.5 -8.39941zM448 368v-352c0 -26.5 -21.5 -48 -48 -48h-352c-26.5 0 -48 21.5 -48 48v352
|
||||
c0 26.5 21.5 48 48 48h352c26.5 0 48 -21.5 48 -48zM400 22v340c0 3.2998 -2.7002 6 -6 6h-340c-3.2998 0 -6 -2.7002 -6 -6v-340c0 -3.2998 2.7002 -6 6 -6h340c3.2998 0 6 2.7002 6 6z" />
|
||||
<glyph glyph-name="dot-circle" unicode=""
|
||||
d="M256 392c-110.549 0 -200 -89.4678 -200 -200c0 -110.549 89.4678 -200 200 -200c110.549 0 200 89.4678 200 200c0 110.549 -89.4678 200 -200 200zM256 440c136.967 0 248 -111.033 248 -248s-111.033 -248 -248 -248s-248 111.033 -248 248s111.033 248 248 248z
|
||||
M256 272c44.1826 0 80 -35.8174 80 -80s-35.8174 -80 -80 -80s-80 35.8174 -80 80s35.8174 80 80 80z" />
|
||||
<glyph glyph-name="building" unicode="" horiz-adv-x="448"
|
||||
d="M128 300v40c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-40c0 -6.59961 -5.40039 -12 -12 -12h-40c-6.59961 0 -12 5.40039 -12 12zM268 288c-6.59961 0 -12 5.40039 -12 12v40c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-40
|
||||
c0 -6.59961 -5.40039 -12 -12 -12h-40zM140 192c-6.59961 0 -12 5.40039 -12 12v40c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-40c0 -6.59961 -5.40039 -12 -12 -12h-40zM268 192c-6.59961 0 -12 5.40039 -12 12v40c0 6.59961 5.40039 12 12 12h40
|
||||
c6.59961 0 12 -5.40039 12 -12v-40c0 -6.59961 -5.40039 -12 -12 -12h-40zM192 108c0 -6.59961 -5.40039 -12 -12 -12h-40c-6.59961 0 -12 5.40039 -12 12v40c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-40zM268 96c-6.59961 0 -12 5.40039 -12 12v40
|
||||
c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-40c0 -6.59961 -5.40039 -12 -12 -12h-40zM448 -28v-36h-448v36c0 6.59961 5.40039 12 12 12h19.5v440c0 13.2998 10.7002 24 24 24h337c13.2998 0 24 -10.7002 24 -24v-440h19.5
|
||||
c6.59961 0 12 -5.40039 12 -12zM79.5 -15h112.5v67c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-67h112.5v414l-288.5 1z" />
|
||||
<glyph glyph-name="file-pdf" unicode="" horiz-adv-x="384"
|
||||
d="M369.9 350.1c9 -9 14.0996 -21.2998 14.0996 -34v-332.1c0 -26.5 -21.5 -48 -48 -48h-288c-26.5 0 -48 21.5 -48 48v416c0 26.5 21.5 48 48 48.0996h204.1c12.7002 0 24.9004 -5.09961 33.9004 -14.0996zM332.1 320l-76.0996 76.0996v-76.0996h76.0996zM48 -16h288v288
|
||||
h-104c-13.2998 0 -24 10.7002 -24 24v104h-160v-416zM298.2 127.7c10.5 -10.5 8 -38.7002 -17.5 -38.7002c-14.7998 0 -36.9004 6.7998 -55.7998 17c-21.6006 -3.59961 -46 -12.7002 -68.4004 -20.0996c-50.0996 -86.4004 -79.4004 -47 -76.0996 -31.2002
|
||||
c4 20 31 35.8994 51 46.2002c10.5 18.3994 25.3994 50.5 35.3994 74.3994c-7.39941 28.6006 -11.3994 51 -7 67.1006c4.7998 17.6992 38.4004 20.2998 42.6006 -5.90039c4.69922 -15.4004 -1.5 -39.9004 -5.40039 -56c8.09961 -21.2998 19.5996 -35.7998 36.7998 -46.2998
|
||||
c17.4004 2.2002 52.2002 5.5 64.4004 -6.5zM100.1 49.9004c0 -0.700195 11.4004 4.69922 30.4004 35c-5.90039 -5.5 -25.2998 -21.3008 -30.4004 -35zM181.7 240.5c-2.5 0 -2.60059 -26.9004 1.7998 -40.7998c4.90039 8.7002 5.59961 40.7998 -1.7998 40.7998zM157.3 103.9
|
||||
c15.9004 6.09961 34 14.8994 54.7998 19.1992c-11.1992 8.30078 -21.7998 20.4004 -30.0996 35.5c-6.7002 -17.6992 -15 -37.7998 -24.7002 -54.6992zM288.9 108.9c3.59961 2.39941 -2.2002 10.3994 -37.3008 7.7998c32.3008 -13.7998 37.3008 -7.7998 37.3008 -7.7998z" />
|
||||
<glyph glyph-name="file-word" unicode="" horiz-adv-x="384"
|
||||
d="M369.9 350.1c9 -9 14.0996 -21.2998 14.0996 -34v-332.1c0 -26.5 -21.5 -48 -48 -48h-288c-26.5 0 -48 21.5 -48 48v416c0 26.5 21.5 48 48 48.0996h204.1c12.7002 0 24.9004 -5.09961 33.9004 -14.0996zM332.1 320l-76.0996 76.0996v-76.0996h76.0996zM48 -16h288v288
|
||||
h-104c-13.2998 0 -24 10.7002 -24 24v104h-160v-416zM268.1 192v0.200195h15.8008c7.7998 0 13.5 -7.2998 11.5996 -14.9004c-4.2998 -17 -13.7002 -54.0996 -34.5 -136c-1.2998 -5.39941 -6.09961 -9.09961 -11.5996 -9.09961h-24.7002
|
||||
c-5.5 0 -10.2998 3.7998 -11.6006 9.09961c-5.2998 20.9004 -17.7998 71 -17.8994 71.4004l-2.90039 17.2998c-0.5 -5.2998 -1.5 -11.0996 -3 -17.2998l-17.8994 -71.4004c-1.30078 -5.39941 -6.10059 -9.09961 -11.6006 -9.09961h-25.2002
|
||||
c-5.59961 0 -10.3994 3.7002 -11.6992 9.09961c-6.5 26.5 -25.2002 103.4 -33.2002 136c-1.7998 7.5 3.89941 14.7998 11.7002 14.7998h16.7998c5.7998 0 10.7002 -4.09961 11.7998 -9.69922c5 -25.7002 18.4004 -93.8008 19.0996 -99
|
||||
c0.300781 -1.7002 0.400391 -3.10059 0.5 -4.2002c0.800781 7.5 0.400391 4.7002 24.8008 103.7c1.39941 5.2998 6.19922 9.09961 11.6992 9.09961h13.3008c5.59961 0 10.3994 -3.7998 11.6992 -9.2002c23.9004 -99.7002 22.8008 -94.3994 23.6006 -99.5
|
||||
c0.299805 -1.7002 0.5 -3.09961 0.700195 -4.2998c0.599609 8.09961 0.399414 5.7998 21 103.5c1.09961 5.5 6 9.5 11.6992 9.5z" />
|
||||
<glyph glyph-name="file-excel" unicode="" horiz-adv-x="384"
|
||||
d="M369.9 350.1c9 -9 14.0996 -21.2998 14.0996 -34v-332.1c0 -26.5 -21.5 -48 -48 -48h-288c-26.5 0 -48 21.5 -48 48v416c0 26.5 21.5 48 48 48.0996h204.1c12.7002 0 24.9004 -5.09961 33.9004 -14.0996zM332.1 320l-76.0996 76.0996v-76.0996h76.0996zM48 -16h288v288
|
||||
h-104c-13.2998 0 -24 10.7002 -24 24v104h-160v-416zM260 224c9.2002 0 15 -10 10.2998 -18c-16 -27.5 -45.5996 -76.9004 -46.2998 -78l46.4004 -78c4.59961 -8 -1.10059 -18 -10.4004 -18h-28.7998c-4.40039 0 -8.5 2.40039 -10.6006 6.2998
|
||||
c-22.6992 41.7998 -13.6992 27.5 -28.5996 57.7002c-5.59961 -12.7002 -6.90039 -17.7002 -28.5996 -57.7002c-2.10059 -3.89941 -6.10059 -6.2998 -10.5 -6.2998h-28.9004c-9.2998 0 -15.0996 10 -10.4004 18l46.3008 78l-46.3008 78c-4.59961 8 1.10059 18 10.4004 18
|
||||
h28.9004c4.39941 0 8.5 -2.40039 10.5996 -6.2998c21.7002 -40.4004 14.7002 -28.6006 28.5996 -57.7002c6.40039 15.2998 10.6006 24.5996 28.6006 57.7002c2.09961 3.89941 6.09961 6.2998 10.5 6.2998h28.7998z" />
|
||||
<glyph glyph-name="file-powerpoint" unicode="" horiz-adv-x="384"
|
||||
d="M369.9 350.1c9 -9 14.0996 -21.2998 14.0996 -34v-332.1c0 -26.5 -21.5 -48 -48 -48h-288c-26.5 0 -48 21.5 -48 48v416c0 26.5 21.5 48 48 48.0996h204.1c12.7002 0 24.9004 -5.09961 33.9004 -14.0996zM332.1 320l-76.0996 76.0996v-76.0996h76.0996zM48 -16h288v288
|
||||
h-104c-13.2998 0 -24 10.7002 -24 24v104h-160v-416zM120 44v168c0 6.59961 5.40039 12 12 12h69.2002c36.7002 0 62.7998 -27 62.7998 -66.2998c0 -74.2998 -68.7002 -66.5 -95.5 -66.5v-47.2002c0 -6.59961 -5.40039 -12 -12 -12h-24.5c-6.59961 0 -12 5.40039 -12 12z
|
||||
M168.5 131.4h23c7.90039 0 13.9004 2.39941 18.0996 7.19922c8.5 9.80078 8.40039 28.5 0.100586 37.8008c-4.10059 4.59961 -9.90039 7 -17.4004 7h-23.8994v-52h0.0996094z" />
|
||||
<glyph glyph-name="file-image" unicode="" horiz-adv-x="384"
|
||||
d="M369.9 350.1c9 -9 14.0996 -21.2998 14.0996 -34v-332.1c0 -26.5 -21.5 -48 -48 -48h-288c-26.5 0 -48 21.5 -48 48v416c0 26.5 21.5 48 48 48.0996h204.1c12.7002 0 24.9004 -5.09961 33.9004 -14.0996zM332.1 320l-76.0996 76.0996v-76.0996h76.0996zM48 -16h288v288
|
||||
h-104c-13.2998 0 -24 10.7002 -24 24v104h-160v-416zM80 32v64l39.5 39.5c4.7002 4.7002 12.2998 4.7002 17 0l39.5 -39.5l87.5 87.5c4.7002 4.7002 12.2998 4.7002 17 0l23.5 -23.5v-128h-224zM128 272c26.5 0 48 -21.5 48 -48s-21.5 -48 -48 -48s-48 21.5 -48 48
|
||||
s21.5 48 48 48z" />
|
||||
<glyph glyph-name="file-archive" unicode="" horiz-adv-x="384"
|
||||
d="M128.3 288h32v-32h-32v32zM192.3 384v-32h-32v32h32zM128.3 352h32v-32h-32v32zM192.3 320v-32h-32v32h32zM369.9 350.1c9 -9 14.0996 -21.2998 14.0996 -34v-332.1c0 -26.5 -21.5 -48 -48 -48h-288c-26.5 0 -48 21.5 -48 48v416c0 26.5 21.5 48 48 48.0996h204.1
|
||||
c12.7002 0 24.9004 -5.09961 33.9004 -14.0996zM256 396.1v-76.0996h76.0996zM336 -16v288h-104c-13.2998 0 -24 10.7002 -24 24v104h-48.2998v-16h-32v16h-79.7002v-416h288zM194.2 182.3l17.2998 -87.7002c6.40039 -32.3994 -18.4004 -62.5996 -51.5 -62.5996
|
||||
c-33.2002 0 -58 30.4004 -51.4004 62.9004l19.7002 97.0996v32h32v-32h22.1006c5.7998 0 10.6992 -4.09961 11.7998 -9.7002zM160.3 57.9004c17.9004 0 32.4004 12.0996 32.4004 27c0 14.8994 -14.5 27 -32.4004 27c-17.8994 0 -32.3994 -12.1006 -32.3994 -27
|
||||
c0 -14.9004 14.5 -27 32.3994 -27zM192.3 256v-32h-32v32h32z" />
|
||||
<glyph glyph-name="file-audio" unicode="" horiz-adv-x="384"
|
||||
d="M369.941 350.059c7.75977 -7.75977 14.0586 -22.9658 14.0586 -33.9404v-332.118c0 -26.5098 -21.4902 -48 -48 -48h-288c-26.5098 0 -48 21.4902 -48 48v416c0 26.5098 21.4902 48 48 48h204.118c10.9746 0 26.1807 -6.29883 33.9404 -14.0586zM332.118 320
|
||||
l-76.1182 76.1182v-76.1182h76.1182zM48 -16h288v288h-104c-13.2549 0 -24 10.7451 -24 24v104h-160v-416zM192 60.0244c0 -10.6914 -12.9258 -16.0459 -20.4854 -8.48535l-35.5146 35.9746h-28c-6.62695 0 -12 5.37305 -12 12v56c0 6.62695 5.37305 12 12 12h28
|
||||
l35.5146 36.9473c7.56055 7.56055 20.4854 2.20605 20.4854 -8.48535v-135.951zM233.201 107.154c9.05078 9.29688 9.05957 24.1328 0.000976562 33.4385c-22.1494 22.752 12.2344 56.2461 34.3945 33.4814c27.1982 -27.9404 27.2119 -72.4443 0.000976562 -100.401
|
||||
c-21.793 -22.3857 -56.9463 10.3154 -34.3965 33.4814z" />
|
||||
<glyph glyph-name="file-video" unicode="" horiz-adv-x="384"
|
||||
d="M369.941 350.059c7.75977 -7.75977 14.0586 -22.9658 14.0586 -33.9404v-332.118c0 -26.5098 -21.4902 -48 -48 -48h-288c-26.5098 0 -48 21.4902 -48 48v416c0 26.5098 21.4902 48 48 48h204.118c10.9746 0 26.1807 -6.29883 33.9404 -14.0586zM332.118 320
|
||||
l-76.1182 76.1182v-76.1182h76.1182zM48 -16h288v288h-104c-13.2549 0 -24 10.7451 -24 24v104h-160v-416zM276.687 195.303c10.0049 10.0049 27.3135 2.99707 27.3135 -11.3135v-111.976c0 -14.2939 -17.2959 -21.332 -27.3135 -11.3135l-52.6865 52.6738v-37.374
|
||||
c0 -11.0459 -8.9541 -20 -20 -20h-104c-11.0459 0 -20 8.9541 -20 20v104c0 11.0459 8.9541 20 20 20h104c11.0459 0 20 -8.9541 20 -20v-37.374z" />
|
||||
<glyph glyph-name="file-code" unicode="" horiz-adv-x="384"
|
||||
d="M149.9 98.9004c3.5 -3.30078 3.69922 -8.90039 0.399414 -12.4004l-17.3994 -18.5996c-1.60059 -1.80078 -4 -2.80078 -6.40039 -2.80078c-2.2002 0 -4.40039 0.900391 -6 2.40039l-57.7002 54.0996c-3.7002 3.40039 -3.7002 9.30078 0 12.8008l57.7002 54.0996
|
||||
c3.40039 3.2998 9 3.2002 12.4004 -0.400391l17.3994 -18.5996l0.200195 -0.200195c3.2002 -3.59961 2.7998 -9.2002 -0.799805 -12.3994l-32.7998 -28.9004l32.7998 -28.9004zM369.9 350.1c9 -9 14.0996 -21.2998 14.0996 -34v-332.1c0 -26.5 -21.5 -48 -48 -48h-288
|
||||
c-26.5 0 -48 21.5 -48 48v416c0 26.5 21.5 48 48 48.0996h204.1c12.7002 0 24.9004 -5.09961 33.9004 -14.0996zM256 396.1v-76.0996h76.0996zM336 -16v288h-104c-13.2998 0 -24 10.7002 -24 24v104h-160v-416h288zM209.6 234l24.4004 -7
|
||||
c4.7002 -1.2998 7.40039 -6.2002 6 -10.9004l-54.7002 -188.199c-1.2998 -4.60059 -6.2002 -7.40039 -10.8994 -6l-24.4004 7.09961c-4.7002 1.2998 -7.40039 6.2002 -6 10.9004l54.7002 188.1c1.39941 4.7002 6.2002 7.40039 10.8994 6zM234.1 157.1
|
||||
c-3.5 3.30078 -3.69922 8.90039 -0.399414 12.4004l17.3994 18.5996c3.30078 3.60059 8.90039 3.7002 12.4004 0.400391l57.7002 -54.0996c3.7002 -3.40039 3.7002 -9.30078 0 -12.8008l-57.7002 -54.0996c-3.5 -3.2998 -9.09961 -3.09961 -12.4004 0.400391
|
||||
l-17.3994 18.5996l-0.200195 0.200195c-3.2002 3.59961 -2.7998 9.2002 0.799805 12.3994l32.7998 28.9004l-32.7998 28.9004z" />
|
||||
<glyph glyph-name="life-ring" unicode=""
|
||||
d="M256 -56c-136.967 0 -248 111.033 -248 248s111.033 248 248 248s248 -111.033 248 -248s-111.033 -248 -248 -248zM152.602 20.7197c63.2178 -38.3184 143.579 -38.3184 206.797 0l-53.4111 53.4111c-31.8467 -13.5215 -68.168 -13.5059 -99.9746 0zM336 192
|
||||
c0 44.1123 -35.8877 80 -80 80s-80 -35.8877 -80 -80s35.8877 -80 80 -80s80 35.8877 80 80zM427.28 88.6016c38.3184 63.2178 38.3184 143.579 0 206.797l-53.4111 -53.4111c13.5215 -31.8467 13.5049 -68.168 0 -99.9746zM359.397 363.28
|
||||
c-63.2168 38.3184 -143.578 38.3184 -206.796 0l53.4111 -53.4111c31.8457 13.5215 68.167 13.5049 99.9736 0zM84.7197 295.398c-38.3184 -63.2178 -38.3184 -143.579 0 -206.797l53.4111 53.4111c-13.5215 31.8467 -13.5059 68.168 0 99.9746z" />
|
||||
<glyph glyph-name="paper-plane" unicode=""
|
||||
d="M440 441.5c34.5996 19.9004 77.5996 -8.7998 71.5 -48.9004l-59.4004 -387.199c-2.2998 -14.5 -11.0996 -27.3008 -23.8994 -34.5c-7.2998 -4.10059 -15.4004 -6.2002 -23.6006 -6.2002c-6.19922 0 -12.3994 1.2002 -18.2998 3.59961l-111.899 46.2002l-43.8008 -59.0996
|
||||
c-27.3994 -36.9004 -86.5996 -17.8008 -86.5996 28.5996v84.4004l-114.3 47.2998c-36.7998 15.0996 -40.1006 66 -5.7002 85.8994zM192 -16l36.5996 49.5l-36.5996 15.0996v-64.5996zM404.6 12.7002l59.4004 387.3l-416 -240l107.8 -44.5996l211.5 184.3
|
||||
c14.2002 12.2998 34.4004 -5.7002 23.7002 -21.2002l-140.2 -202.3z" />
|
||||
<glyph glyph-name="futbol" unicode="" horiz-adv-x="496"
|
||||
d="M483.8 268.6c42.2998 -130.199 -29 -270.1 -159.2 -312.399c-25.5 -8.2998 -51.2998 -12.2002 -76.6992 -12.2002c-104.5 0 -201.7 66.5996 -235.7 171.4c-42.2998 130.199 29 270.1 159.2 312.399c25.5 8.2998 51.2998 12.2002 76.6992 12.2002
|
||||
c104.5 0 201.7 -66.5996 235.7 -171.4zM409.3 74.9004c6.10059 8.39941 12.1006 16.8994 16.7998 26.1992c14.3008 28.1006 21.5 58.5 21.7002 89.2002l-38.8994 36.4004l-71.1006 -22.1006l-24.3994 -75.1992l43.6992 -60.9004zM409.3 310.3
|
||||
c-24.5 33.4004 -58.7002 58.4004 -97.8994 71.4004l-47.4004 -26.2002v-73.7998l64.2002 -46.5l70.7002 22zM184.9 381.6c-39.9004 -13.2998 -73.5 -38.5 -97.8008 -71.8994l10.1006 -52.5l70.5996 -22l64.2002 46.5v73.7998zM139 68.5l43.5 61.7002l-24.2998 74.2998
|
||||
l-71.1006 22.2002l-39 -36.4004c0.5 -55.7002 23.4004 -95.2002 37.8008 -115.3zM187.2 1.5c64.0996 -20.4004 115.5 -1.7998 121.7 0l22.3994 48.0996l-44.2998 61.7002h-78.5996l-43.6006 -61.7002z" />
|
||||
<glyph glyph-name="newspaper" unicode="" horiz-adv-x="576"
|
||||
d="M552 384c13.2549 0 24 -10.7451 24 -24v-336c0 -13.2549 -10.7451 -24 -24 -24h-496c-30.9277 0 -56 25.0723 -56 56v272c0 13.2549 10.7451 24 24 24h42.752c6.60547 18.623 24.3896 32 45.248 32h440zM48 56c0 -4.41113 3.58887 -8 8 -8s8 3.58887 8 8v248h-16v-248z
|
||||
M528 48v288h-416v-280c0 -2.7168 -0.204102 -5.38574 -0.578125 -8h416.578zM172 168c-6.62695 0 -12 5.37305 -12 12v96c0 6.62695 5.37305 12 12 12h136c6.62695 0 12 -5.37305 12 -12v-96c0 -6.62695 -5.37305 -12 -12 -12h-136zM200 248v-40h80v40h-80zM160 108v24
|
||||
c0 6.62695 5.37305 12 12 12h136c6.62695 0 12 -5.37305 12 -12v-24c0 -6.62695 -5.37305 -12 -12 -12h-136c-6.62695 0 -12 5.37305 -12 12zM352 108v24c0 6.62695 5.37305 12 12 12h104c6.62695 0 12 -5.37305 12 -12v-24c0 -6.62695 -5.37305 -12 -12 -12h-104
|
||||
c-6.62695 0 -12 5.37305 -12 12zM352 252v24c0 6.62695 5.37305 12 12 12h104c6.62695 0 12 -5.37305 12 -12v-24c0 -6.62695 -5.37305 -12 -12 -12h-104c-6.62695 0 -12 5.37305 -12 12zM352 180v24c0 6.62695 5.37305 12 12 12h104c6.62695 0 12 -5.37305 12 -12v-24
|
||||
c0 -6.62695 -5.37305 -12 -12 -12h-104c-6.62695 0 -12 5.37305 -12 12z" />
|
||||
<glyph glyph-name="bell-slash" unicode="" horiz-adv-x="640"
|
||||
d="M633.99 -23.0195c6.91016 -5.52051 8.01953 -15.5908 2.5 -22.4902l-10 -12.4902c-5.53027 -6.88965 -15.5898 -8.00977 -22.4902 -2.49023l-598 467.51c-6.90039 5.52051 -8.01953 15.5908 -2.49023 22.4902l10 12.4902
|
||||
c5.52051 6.90039 15.5898 8.00977 22.4902 2.49023zM163.53 80h182.84l61.3994 -48h-279.659c-19.1201 0 -31.9902 15.5996 -32.1006 32c-0.0498047 7.5498 2.61035 15.2598 8.61035 21.71c18.3701 19.7402 51.5703 49.6904 54.8398 140.42l45.4697 -35.5498
|
||||
c-6.91992 -54.7803 -24.6895 -88.5498 -41.3994 -110.58zM320 352c-23.3496 0 -45 -7.17969 -62.9404 -19.4004l-38.1699 29.8408c19.6807 15.7793 43.1104 27.3096 69.1299 32.7197v20.8398c0 17.6699 14.3203 32 31.9805 32s31.9805 -14.3301 31.9805 -32v-20.8398
|
||||
c73.46 -15.2598 127.939 -77.46 127.939 -155.16c0 -41.3604 6.03027 -70.7197 14.3398 -92.8496l-59.5293 46.54c-1.63086 13.96 -2.77051 28.8896 -2.79004 45.7295c0 0.200195 0.0595703 0.379883 0.0595703 0.580078c0 61.8604 -50.1396 112 -112 112zM320 -64
|
||||
c-35.3203 0 -63.9697 28.6504 -63.9697 64h127.939c0 -35.3496 -28.6494 -64 -63.9697 -64z" />
|
||||
<glyph glyph-name="copyright" unicode=""
|
||||
d="M256 440c136.967 0 248 -111.033 248 -248s-111.033 -248 -248 -248s-248 111.033 -248 248s111.033 248 248 248zM256 -8c110.549 0 200 89.4678 200 200c0 110.549 -89.4678 200 -200 200c-110.549 0 -200 -89.4688 -200 -200c0 -110.549 89.4678 -200 200 -200z
|
||||
M363.351 93.0645c-9.61328 -9.71289 -45.5293 -41.3965 -104.064 -41.3965c-82.4297 0 -140.484 61.4248 -140.484 141.567c0 79.1514 60.2754 139.4 139.763 139.4c55.5303 0 88.7373 -26.6201 97.5928 -34.7783c2.13379 -1.96289 3.86523 -5.9082 3.86523 -8.80762
|
||||
c0 -1.95508 -0.864258 -4.87402 -1.92969 -6.51465l-18.1543 -28.1133c-3.8418 -5.9502 -11.9668 -7.28223 -17.499 -2.9209c-8.5957 6.77637 -31.8145 22.5381 -61.708 22.5381c-48.3037 0 -77.916 -35.3301 -77.916 -80.082c0 -41.5889 26.8877 -83.6924 78.2764 -83.6924
|
||||
c32.6572 0 56.8428 19.0391 65.7266 27.2256c5.26953 4.85645 13.5957 4.03906 17.8193 -1.73828l19.8652 -27.1699c1.28613 -1.74512 2.33008 -4.91992 2.33008 -7.08789c0 -2.72363 -1.56055 -6.5 -3.48242 -8.42969z" />
|
||||
<glyph glyph-name="closed-captioning" unicode=""
|
||||
d="M464 384c26.5 0 48 -21.5 48 -48v-288c0 -26.5 -21.5 -48 -48 -48h-416c-26.5 0 -48 21.5 -48 48v288c0 26.5 21.5 48 48 48h416zM458 48c3.2998 0 6 2.7002 6 6v276c0 3.2998 -2.7002 6 -6 6h-404c-3.2998 0 -6 -2.7002 -6 -6v-276c0 -3.2998 2.7002 -6 6 -6h404z
|
||||
M246.9 133.7c1.69922 -2.40039 1.5 -5.60059 -0.5 -7.7002c-53.6006 -56.7998 -172.801 -32.0996 -172.801 67.9004c0 97.2998 121.7 119.5 172.5 70.0996c2.10059 -2 2.5 -3.2002 1 -5.7002l-17.5 -30.5c-1.89941 -3.09961 -6.19922 -4 -9.09961 -1.7002
|
||||
c-40.7998 32 -94.5996 14.9004 -94.5996 -31.1992c0 -48 51 -70.5 92.1992 -32.6006c2.80078 2.5 7.10059 2.10059 9.2002 -0.899414zM437.3 133.7c1.7002 -2.40039 1.5 -5.60059 -0.5 -7.7002c-53.5996 -56.9004 -172.8 -32.0996 -172.8 67.9004
|
||||
c0 97.2998 121.7 119.5 172.5 70.0996c2.09961 -2 2.5 -3.2002 1 -5.7002l-17.5 -30.5c-1.90039 -3.09961 -6.2002 -4 -9.09961 -1.7002c-40.8008 32 -94.6006 14.9004 -94.6006 -31.1992c0 -48 51 -70.5 92.2002 -32.6006c2.7998 2.5 7.09961 2.10059 9.2002 -0.899414z
|
||||
" />
|
||||
<glyph glyph-name="object-group" unicode=""
|
||||
d="M500 320h-12v-256h12c6.62695 0 12 -5.37305 12 -12v-72c0 -6.62695 -5.37305 -12 -12 -12h-72c-6.62695 0 -12 5.37305 -12 12v12h-320v-12c0 -6.62695 -5.37305 -12 -12 -12h-72c-6.62695 0 -12 5.37305 -12 12v72c0 6.62695 5.37305 12 12 12h12v256h-12
|
||||
c-6.62695 0 -12 5.37305 -12 12v72c0 6.62695 5.37305 12 12 12h72c6.62695 0 12 -5.37305 12 -12v-12h320v12c0 6.62695 5.37305 12 12 12h72c6.62695 0 12 -5.37305 12 -12v-72c0 -6.62695 -5.37305 -12 -12 -12zM448 384v-32h32v32h-32zM32 384v-32h32v32h-32zM64 0v32
|
||||
h-32v-32h32zM480 0v32h-32v-32h32zM440 64v256h-12c-6.62695 0 -12 5.37305 -12 12v12h-320v-12c0 -6.62695 -5.37305 -12 -12 -12h-12v-256h12c6.62695 0 12 -5.37305 12 -12v-12h320v12c0 6.62695 5.37305 12 12 12h12zM404 256c6.62695 0 12 -5.37207 12 -12v-168
|
||||
c0 -6.62793 -5.37305 -12 -12 -12h-200c-6.62695 0 -12 5.37207 -12 12v52h-84c-6.62695 0 -12 5.37207 -12 12v168c0 6.62793 5.37305 12 12 12h200c6.62695 0 12 -5.37207 12 -12v-52h84zM136 280v-112h144v112h-144zM376 104v112h-56v-76
|
||||
c0 -6.62793 -5.37305 -12 -12 -12h-76v-24h144z" />
|
||||
<glyph glyph-name="object-ungroup" unicode="" horiz-adv-x="576"
|
||||
d="M564 224h-12v-160h12c6.62695 0 12 -5.37305 12 -12v-72c0 -6.62695 -5.37305 -12 -12 -12h-72c-6.62695 0 -12 5.37305 -12 12v12h-224v-12c0 -6.62695 -5.37305 -12 -12 -12h-72c-6.62695 0 -12 5.37305 -12 12v72c0 6.62695 5.37305 12 12 12h12v24h-88v-12
|
||||
c0 -6.62695 -5.37305 -12 -12 -12h-72c-6.62695 0 -12 5.37305 -12 12v72c0 6.62695 5.37305 12 12 12h12v160h-12c-6.62695 0 -12 5.37305 -12 12v72c0 6.62695 5.37305 12 12 12h72c6.62695 0 12 -5.37305 12 -12v-12h224v12c0 6.62695 5.37305 12 12 12h72
|
||||
c6.62695 0 12 -5.37305 12 -12v-72c0 -6.62695 -5.37305 -12 -12 -12h-12v-24h88v12c0 6.62695 5.37305 12 12 12h72c6.62695 0 12 -5.37305 12 -12v-72c0 -6.62695 -5.37305 -12 -12 -12zM352 384v-32h32v32h-32zM352 128v-32h32v32h-32zM64 96v32h-32v-32h32zM64 352v32
|
||||
h-32v-32h32zM96 136h224v12c0 6.62695 5.37305 12 12 12h12v160h-12c-6.62695 0 -12 5.37305 -12 12v12h-224v-12c0 -6.62695 -5.37305 -12 -12 -12h-12v-160h12c6.62695 0 12 -5.37305 12 -12v-12zM224 0v32h-32v-32h32zM504 64v160h-12c-6.62695 0 -12 5.37305 -12 12v12
|
||||
h-88v-88h12c6.62695 0 12 -5.37305 12 -12v-72c0 -6.62695 -5.37305 -12 -12 -12h-72c-6.62695 0 -12 5.37305 -12 12v12h-88v-24h12c6.62695 0 12 -5.37305 12 -12v-12h224v12c0 6.62695 5.37305 12 12 12h12zM544 0v32h-32v-32h32zM544 256v32h-32v-32h32z" />
|
||||
<glyph glyph-name="sticky-note" unicode="" horiz-adv-x="448"
|
||||
d="M448 99.8936c0 -10.9746 -6.29883 -26.1797 -14.0586 -33.9404l-83.8828 -83.8818c-7.75977 -7.76074 -22.9658 -14.0596 -33.9404 -14.0596h-268.118c-26.5098 0 -48 21.4902 -48 48v351.988c0 26.5098 21.4902 48 48 48h352c26.5098 0 48 -21.4902 48 -48v-268.106z
|
||||
M320 19.8936l76.1182 76.1182h-76.1182v-76.1182zM400 368h-352v-351.988h224v104c0 13.2549 10.7451 24 24 24h104v223.988z" />
|
||||
<glyph glyph-name="clone" unicode=""
|
||||
d="M464 448c26.5098 0 48 -21.4902 48 -48v-320c0 -26.5098 -21.4902 -48 -48 -48h-48v-48c0 -26.5098 -21.4902 -48 -48 -48h-320c-26.5098 0 -48 21.4902 -48 48v320c0 26.5098 21.4902 48 48 48h48v48c0 26.5098 21.4902 48 48 48h320zM362 -16c3.31152 0 6 2.68848 6 6
|
||||
v42h-224c-26.5098 0 -48 21.4902 -48 48v224h-42c-3.31152 0 -6 -2.68848 -6 -6v-308c0 -3.31152 2.68848 -6 6 -6h308zM458 80c3.31152 0 6 2.68848 6 6v308c0 3.31152 -2.68848 6 -6 6h-308c-3.31152 0 -6 -2.68848 -6 -6v-308c0 -3.31152 2.68848 -6 6 -6h308z" />
|
||||
<glyph glyph-name="hourglass" unicode="" horiz-adv-x="384"
|
||||
d="M368 400c0 -80.0996 -31.8984 -165.619 -97.1797 -208c64.9912 -42.1934 97.1797 -127.436 97.1797 -208h4c6.62695 0 12 -5.37305 12 -12v-24c0 -6.62695 -5.37305 -12 -12 -12h-360c-6.62695 0 -12 5.37305 -12 12v24c0 6.62695 5.37305 12 12 12h4
|
||||
c0 80.0996 31.8994 165.619 97.1797 208c-64.9912 42.1934 -97.1797 127.436 -97.1797 208h-4c-6.62695 0 -12 5.37305 -12 12v24c0 6.62695 5.37305 12 12 12h360c6.62695 0 12 -5.37305 12 -12v-24c0 -6.62695 -5.37305 -12 -12 -12h-4zM64 400
|
||||
c0 -101.621 57.3066 -184 128 -184s128 82.3799 128 184h-256zM320 -16c0 101.62 -57.3076 184 -128 184s-128 -82.3799 -128 -184h256z" />
|
||||
<glyph glyph-name="hand-rock" unicode=""
|
||||
d="M408.864 368.948c48.8213 20.751 103.136 -15.0723 103.136 -67.9111v-114.443c0 -15.3955 -3.08887 -30.3906 -9.18262 -44.5674l-42.835 -99.6562c-4.99707 -11.625 -3.98242 -18.8574 -3.98242 -42.3701c0 -17.6729 -14.3271 -32 -32 -32h-252
|
||||
c-17.6729 0 -32 14.3271 -32 32c0 27.3301 1.1416 29.2012 -3.11035 32.9033l-97.71 85.0811c-24.8994 21.6797 -39.1797 52.8926 -39.1797 85.6338v56.9531c0 47.4277 44.8457 82.0215 91.0459 71.1807c1.96094 55.751 63.5107 87.8262 110.671 60.8057
|
||||
c29.1895 31.0713 78.8604 31.4473 108.334 -0.0214844c32.7051 18.6846 76.4121 10.3096 98.8135 -23.5879zM464 186.594v114.445c0 34.29 -52 33.8232 -52 0.676758c0 -8.83594 -7.16309 -16 -16 -16h-7c-8.83691 0 -16 7.16406 -16 16v26.751
|
||||
c0 34.457 -52 33.707 -52 0.676758v-27.4287c0 -8.83594 -7.16309 -16 -16 -16h-7c-8.83691 0 -16 7.16406 -16 16v40.4658c0 34.3525 -52 33.8115 -52 0.677734v-41.1436c0 -8.83594 -7.16406 -16 -16 -16h-7c-8.83594 0 -16 7.16406 -16 16v26.751
|
||||
c0 34.4023 -52 33.7744 -52 0.676758v-116.571c0 -8.83203 -7.16797 -16 -16 -16c-3.30664 0 -8.01367 1.7627 -10.5068 3.93359l-7 6.09473c-3.03223 2.64062 -5.49316 8.04688 -5.49316 12.0674v0v41.2275c0 34.2148 -52 33.8857 -52 0.677734v-56.9531
|
||||
c0 -18.8555 8.27441 -36.874 22.7002 -49.4365l97.71 -85.0801c12.4502 -10.8398 19.5898 -26.4463 19.5898 -42.8164v-10.2861h220v7.07617c0 13.21 2.65332 26.0791 7.88281 38.25l42.835 99.6553c2.91602 6.75391 5.28223 18.207 5.28223 25.5635v0.0488281z" />
|
||||
<glyph glyph-name="hand-paper" unicode="" horiz-adv-x="448"
|
||||
d="M372.57 335.359c39.9062 5.63281 75.4297 -25.7393 75.4297 -66.3594v-131.564c-0.00195312 -12.7666 -2.33008 -33.2246 -5.19531 -45.666l-30.1836 -130.958c-3.34668 -14.5234 -16.2783 -24.8125 -31.1816 -24.8125h-222.897
|
||||
c-9.10352 0 -20.7793 6.01758 -26.0615 13.4316l-119.97 168.415c-21.2441 29.8203 -14.8047 71.3574 14.5498 93.1533c18.7754 13.9395 42.1309 16.2979 62.083 8.87109v126.13c0 44.0547 41.125 75.5439 82.4053 64.9834c23.8926 48.1963 92.3535 50.2471 117.982 0.74707
|
||||
c42.5186 11.1445 83.0391 -21.9346 83.0391 -65.5469v-10.8242zM399.997 137.437l-0.00195312 131.563c0 24.9492 -36.5703 25.5508 -36.5703 -0.691406v-76.3086c0 -8.83691 -7.16309 -16 -16 -16h-6.85645c-8.83691 0 -16 7.16309 -16 16v154.184
|
||||
c0 25.501 -36.5703 26.3633 -36.5703 0.691406v-154.875c0 -8.83691 -7.16309 -16 -16 -16h-6.85645c-8.83691 0 -16 7.16309 -16 16v188.309c0 25.501 -36.5703 26.3545 -36.5703 0.691406v-189c0 -8.83691 -7.16309 -16 -16 -16h-6.85645c-8.83691 0 -16 7.16309 -16 16
|
||||
v153.309c0 25.501 -36.5713 26.3359 -36.5713 0.691406v-206.494c0 -15.5703 -20.0352 -21.9092 -29.0303 -9.2832l-27.1279 38.0791c-14.3711 20.1709 -43.833 -2.33496 -29.3945 -22.6045l115.196 -161.697h201.92l27.3252 118.551
|
||||
c2.63086 11.417 3.96484 23.1553 3.96484 34.8857z" />
|
||||
<glyph glyph-name="hand-scissors" unicode=""
|
||||
d="M256 -32c-44.9561 0 -77.3428 43.2627 -64.0244 85.8535c-21.6484 13.71 -34.0156 38.7617 -30.3408 65.0068h-87.6348c-40.8037 0 -74 32.8105 -74 73.1406c0 40.3291 33.1963 73.1396 74 73.1396l94 -9.14062l-78.8496 18.6787
|
||||
c-38.3076 14.7422 -57.04 57.4707 -41.9424 95.1123c15.0303 37.4736 57.7549 55.7803 95.6416 41.2012l144.929 -55.7568c24.9551 30.5566 57.8086 43.9932 92.2178 24.7324l97.999 -54.8525c20.9746 -11.7393 34.0049 -33.8457 34.0049 -57.6904v-205.702
|
||||
c0 -30.7422 -21.4404 -57.5576 -51.7979 -64.5537l-118.999 -27.4268c-4.97168 -1.14648 -10.0889 -1.72949 -15.2031 -1.72949zM256 16.0127l70 -0.000976562c1.23633 0 3.21777 0.225586 4.42285 0.501953l119.001 27.4277
|
||||
c8.58203 1.97754 14.5762 9.29102 14.5762 17.7812v205.701c0 6.4873 -3.62109 12.542 -9.44922 15.8047l-98 54.8545c-8.13965 4.55566 -18.668 2.61914 -24.4873 -4.50781l-21.7646 -26.6475c-2.65039 -3.24512 -8.20215 -5.87891 -12.3926 -5.87891
|
||||
c-1.64062 0 -4.21484 0.477539 -5.74609 1.06738l-166.549 64.0908c-32.6543 12.5664 -50.7744 -34.5771 -19.2227 -46.7168l155.357 -59.7852c5.66016 -2.17773 10.2539 -8.86816 10.2539 -14.9326v0v-11.6328c0 -8.83691 -7.16309 -16 -16 -16h-182
|
||||
c-34.375 0 -34.4297 -50.2803 0 -50.2803h182c8.83691 0 16 -7.16309 16 -16v-6.85645c0 -8.83691 -7.16309 -16 -16 -16h-28c-25.1221 0 -25.1592 -36.5674 0 -36.5674h28c8.83691 0 16 -7.16211 16 -16v-6.85547c0 -8.83691 -7.16309 -16 -16 -16
|
||||
c-25.1201 0 -25.1602 -36.5674 0 -36.5674z" />
|
||||
<glyph glyph-name="hand-lizard" unicode="" horiz-adv-x="576"
|
||||
d="M556.686 157.458c12.6357 -19.4863 19.3145 -42.0615 19.3145 -65.2871v-124.171h-224v71.582l-99.751 38.7871c-2.7832 1.08203 -5.70996 1.63086 -8.69727 1.63086h-131.552c-30.8789 0 -56 25.1211 -56 56c0 48.5234 39.4766 88 88 88h113.709l18.333 48h-196.042
|
||||
c-44.1123 0 -80 35.8877 -80 80v8c0 30.8779 25.1211 56 56 56h293.917c24.5 0 47.084 -12.2725 60.4111 -32.8291zM528 16v76.1709v0.0478516c0 11.7461 -5.19141 29.2734 -11.5879 39.124l-146.358 225.715c-4.44336 6.85254 -11.9707 10.9424 -20.1367 10.9424h-293.917
|
||||
c-4.41113 0 -8 -3.58887 -8 -8v-8c0 -17.6445 14.3555 -32 32 -32h213.471c25.2021 0 42.626 -25.293 33.6299 -48.8457l-24.5518 -64.2812c-7.05371 -18.4658 -25.0732 -30.873 -44.8398 -30.873h-113.709c-22.0557 0 -40 -17.9443 -40 -40c0 -4.41113 3.58887 -8 8 -8
|
||||
h131.552h0.0517578c7.44141 0 19.1074 -2.19238 26.041 -4.89355l99.752 -38.7881c18.5898 -7.22852 30.6035 -24.7881 30.6035 -44.7363v-23.582h128z" />
|
||||
<glyph glyph-name="hand-spock" unicode=""
|
||||
d="M21.0957 66.21c-26.9688 25.3818 -28.2471 67.7461 -2.87109 94.707c24.1982 25.7139 64.2881 28.2373 91.4824 5.72168l-31.04 136.509c-9.38379 41.2803 21.4336 81.0127 64.0713 81.8438c1.74414 28.9062 22.2656 54.4912 51.8818 61.2949
|
||||
c36.001 8.27539 72.0176 -14.2266 80.3037 -50.2959l21.6748 -131.99l16.9014 105.25c9.02344 36.0947 45.4473 57.7021 81.25 48.75c27.3066 -6.82715 45.7061 -29.1357 49.8496 -53.9922c43.2285 0.212891 75.6436 -40.1133 65.5439 -82.5244l-31.7295 -133.41
|
||||
c-0.938477 -3.94141 -1.41406 -7.99414 -1.41406 -12.0449v-36.8389v-0.00683594c0 -9.29102 -2.14355 -24.0596 -4.78516 -32.9668l-31.8145 -107.312c-4.02734 -13.585 -16.5107 -22.9043 -30.6807 -22.9043h-237.6c-7.00586 0 -16.8311 3.89648 -21.9316 8.69824z
|
||||
M53.1641 128.021c-7.17969 -7.62891 -6.81543 -19.6777 0.813477 -26.8574l124.487 -117.164h219.311l28.4199 95.8613c1.86133 6.27637 2.80469 12.7793 2.80469 19.3281v36.8389c0.000976562 6.48047 1.21973 16.8574 2.71973 23.1621l31.7549 133.407
|
||||
c5.83105 24.4893 -31.1445 33.25 -36.9658 8.80273l-26.9229 -113.105c-1.61523 -6.78711 -8.58887 -12.2949 -15.5645 -12.2949h-9.69434c-10.4072 0 -18.043 9.79199 -15.5225 19.8799l38.127 152.512c6.09766 24.376 -30.7607 33.6396 -36.8643 9.21777l-42.3721 -169.49
|
||||
c-1.67285 -6.68945 -8.62695 -12.1191 -15.5225 -12.1191h-13.2168v0c-7.0332 0 -14.0195 5.5625 -15.5938 12.417l-45.2207 196.828c-5.64453 24.5684 -42.6572 15.9609 -37.0342 -8.50781l41.6191 -181.153c2.30078 -10.0156 -5.31738 -19.583 -15.5938 -19.583h-8.60352
|
||||
h-0.000976562c-7.0498 0 -14.04 5.5791 -15.6025 12.4541l-30.3984 133.757c-5.55273 24.4395 -42.6504 16.1963 -37.0547 -8.4209l34.1299 -150.172c0.263672 -1.16309 0.397461 -2.35352 0.397461 -3.5459v-69.4795c0 -13.9941 -16.7754 -21.2432 -26.9658 -11.6523
|
||||
l-53.0117 49.8936c-7.61523 7.16699 -19.6377 6.85938 -26.8564 -0.8125z" />
|
||||
<glyph glyph-name="hand-pointer" unicode="" horiz-adv-x="448"
|
||||
d="M358.182 268.639c43.1934 16.6348 89.8184 -15.7949 89.8184 -62.6387v-84c-0.000976562 -4.25 -0.775391 -11.0615 -1.72754 -15.2041l-27.4297 -118.999c-6.98242 -30.2969 -33.7549 -51.7969 -64.5566 -51.7969h-178.286c-21.2588 0 -41.3682 10.4102 -53.791 27.8457
|
||||
l-109.699 154.001c-21.2432 29.8193 -14.8047 71.3574 14.5498 93.1523c18.8115 13.9658 42.1748 16.2822 62.083 8.87207v161.129c0 36.9443 29.7363 67 66.2861 67s66.2861 -30.0557 66.2861 -67v-73.6338c20.4131 2.85742 41.4678 -3.94238 56.5947 -19.6289
|
||||
c27.1934 12.8467 60.3799 5.66992 79.8721 -19.0986zM80.9854 168.303c-14.4004 20.2119 -43.8008 -2.38281 -29.3945 -22.6055l109.712 -154c3.43457 -4.81934 8.92871 -7.69727 14.6973 -7.69727h178.285c8.49219 0 15.8037 5.99414 17.7822 14.5762l27.4297 119.001
|
||||
c0.333008 1.44629 0.501953 2.93457 0.501953 4.42285v84c0 25.1602 -36.5713 25.1211 -36.5713 0c0 -8.83594 -7.16309 -16 -16 -16h-6.85645c-8.83691 0 -16 7.16406 -16 16v21c0 25.1602 -36.5713 25.1201 -36.5713 0v-21c0 -8.83594 -7.16309 -16 -16 -16h-6.85938
|
||||
c-8.83691 0 -16 7.16406 -16 16v35c0 25.1602 -36.5703 25.1201 -36.5703 0v-35c0 -8.83594 -7.16309 -16 -16 -16h-6.85742c-8.83691 0 -16 7.16406 -16 16v175c0 25.1602 -36.5713 25.1201 -36.5713 0v-241.493c0 -15.5703 -20.0352 -21.9092 -29.0303 -9.2832z
|
||||
M176.143 48v96c0 8.83691 6.26855 16 14 16h6c7.73242 0 14 -7.16309 14 -16v-96c0 -8.83691 -6.26758 -16 -14 -16h-6c-7.73242 0 -14 7.16309 -14 16zM251.571 48v96c0 8.83691 6.26758 16 14 16h6c7.73145 0 14 -7.16309 14 -16v-96c0 -8.83691 -6.26855 -16 -14 -16h-6
|
||||
c-7.73242 0 -14 7.16309 -14 16zM327 48v96c0 8.83691 6.26758 16 14 16h6c7.73242 0 14 -7.16309 14 -16v-96c0 -8.83691 -6.26758 -16 -14 -16h-6c-7.73242 0 -14 7.16309 -14 16z" />
|
||||
<glyph glyph-name="hand-peace" unicode="" horiz-adv-x="448"
|
||||
d="M362.146 256.024c42.5908 13.3184 85.8535 -19.0684 85.8535 -64.0244l-0.0117188 -70.001c-0.000976562 -4.25 -0.775391 -11.0615 -1.72949 -15.2031l-27.4268 -118.999c-6.99707 -30.3564 -33.8105 -51.7969 -64.5547 -51.7969h-205.702
|
||||
c-23.8447 0 -45.9502 13.0303 -57.6904 34.0059l-54.8525 97.999c-19.2607 34.4092 -5.82422 67.2617 24.7324 92.2178l-55.7568 144.928c-14.5791 37.8867 3.72754 80.6113 41.2012 95.6416c37.6406 15.0977 80.3691 -3.63477 95.1123 -41.9424l18.6787 -78.8496
|
||||
l-9.14062 94c0 40.8037 32.8096 74 73.1396 74s73.1406 -33.1963 73.1406 -74v-87.6348c26.2451 3.6748 51.2959 -8.69238 65.0068 -30.3408zM399.987 122l-0.000976562 70c0 25.1602 -36.5674 25.1201 -36.5674 0c0 -8.83691 -7.16309 -16 -16 -16h-6.85547
|
||||
c-8.83789 0 -16 7.16309 -16 16v28c0 25.1592 -36.5674 25.1221 -36.5674 0v-28c0 -8.83691 -7.16309 -16 -16 -16h-6.85645c-8.83691 0 -16 7.16309 -16 16v182c0 34.4297 -50.2803 34.375 -50.2803 0v-182c0 -8.83691 -7.16309 -16 -16 -16h-11.6328v0
|
||||
c-6.06445 0 -12.7549 4.59375 -14.9326 10.2539l-59.7842 155.357c-12.1396 31.5518 -59.2842 13.4326 -46.7168 -19.2227l64.0898 -166.549c0.589844 -1.53125 1.06738 -4.10547 1.06738 -5.74609c0 -4.19043 -2.63379 -9.74219 -5.87891 -12.3926l-26.6475 -21.7646
|
||||
c-7.12695 -5.81934 -9.06445 -16.3467 -4.50781 -24.4873l54.8535 -98c3.26367 -5.82812 9.31934 -9.44922 15.8057 -9.44922h205.701c8.49121 0 15.8037 5.99414 17.7812 14.5762l27.4277 119.001c0.333008 1.44629 0.501953 2.93457 0.501953 4.42285z" />
|
||||
<glyph glyph-name="registered" unicode=""
|
||||
d="M256 440c136.967 0 248 -111.033 248 -248s-111.033 -248 -248 -248s-248 111.033 -248 248s111.033 248 248 248zM256 -8c110.549 0 200 89.4678 200 200c0 110.549 -89.4678 200 -200 200c-110.549 0 -200 -89.4688 -200 -200c0 -110.549 89.4678 -200 200 -200z
|
||||
M366.442 73.791c4.40332 -7.99219 -1.37012 -17.791 -10.5107 -17.791h-42.8096h-0.0126953c-3.97559 0 -8.71582 2.84961 -10.5801 6.36035l-47.5156 89.3027h-31.958v-83.6631c0 -6.61719 -5.38281 -12 -12 -12h-38.5674c-6.61719 0 -12 5.38281 -12 12v248.304
|
||||
c0 6.61719 5.38281 12 12 12h78.667c71.251 0 101.498 -32.749 101.498 -85.252c0 -31.6123 -15.2148 -59.2969 -39.4824 -73.1758c3.02148 -4.61719 0.225586 0.199219 53.2715 -96.085zM256.933 208.094c20.9131 0 32.4307 11.5186 32.4316 32.4316
|
||||
c0 19.5752 -6.5127 31.709 -38.9297 31.709h-27.377v-64.1406h33.875z" />
|
||||
<glyph glyph-name="calendar-plus" unicode="" horiz-adv-x="448"
|
||||
d="M336 156v-24c0 -6.59961 -5.40039 -12 -12 -12h-76v-76c0 -6.59961 -5.40039 -12 -12 -12h-24c-6.59961 0 -12 5.40039 -12 12v76h-76c-6.59961 0 -12 5.40039 -12 12v24c0 6.59961 5.40039 12 12 12h76v76c0 6.59961 5.40039 12 12 12h24c6.59961 0 12 -5.40039 12 -12
|
||||
v-76h76c6.59961 0 12 -5.40039 12 -12zM448 336v-352c0 -26.5 -21.5 -48 -48 -48h-352c-26.5 0 -48 21.5 -48 48v352c0 26.5 21.5 48 48 48h48v52c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-52h128v52c0 6.59961 5.40039 12 12 12h40
|
||||
c6.59961 0 12 -5.40039 12 -12v-52h48c26.5 0 48 -21.5 48 -48zM400 -10v298h-352v-298c0 -3.2998 2.7002 -6 6 -6h340c3.2998 0 6 2.7002 6 6z" />
|
||||
<glyph glyph-name="calendar-minus" unicode="" horiz-adv-x="448"
|
||||
d="M124 120c-6.59961 0 -12 5.40039 -12 12v24c0 6.59961 5.40039 12 12 12h200c6.59961 0 12 -5.40039 12 -12v-24c0 -6.59961 -5.40039 -12 -12 -12h-200zM448 336v-352c0 -26.5 -21.5 -48 -48 -48h-352c-26.5 0 -48 21.5 -48 48v352c0 26.5 21.5 48 48 48h48v52
|
||||
c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-52h128v52c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-52h48c26.5 0 48 -21.5 48 -48zM400 -10v298h-352v-298c0 -3.2998 2.7002 -6 6 -6h340c3.2998 0 6 2.7002 6 6z" />
|
||||
<glyph glyph-name="calendar-times" unicode="" horiz-adv-x="448"
|
||||
d="M311.7 73.2998l-17 -17c-4.7002 -4.7002 -12.2998 -4.7002 -17 0l-53.7002 53.7998l-53.7002 -53.6992c-4.7002 -4.7002 -12.2998 -4.7002 -17 0l-17 17c-4.7002 4.69922 -4.7002 12.2998 0 17l53.7002 53.6992l-53.7002 53.7002c-4.7002 4.7002 -4.7002 12.2998 0 17
|
||||
l17 17c4.7002 4.7002 12.2998 4.7002 17 0l53.7002 -53.7002l53.7002 53.7002c4.7002 4.7002 12.2998 4.7002 17 0l17 -17c4.7002 -4.7002 4.7002 -12.2998 0 -17l-53.7998 -53.7998l53.6992 -53.7002c4.80078 -4.7002 4.80078 -12.2998 0.100586 -17zM448 336v-352
|
||||
c0 -26.5 -21.5 -48 -48 -48h-352c-26.5 0 -48 21.5 -48 48v352c0 26.5 21.5 48 48 48h48v52c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-52h128v52c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-52h48c26.5 0 48 -21.5 48 -48zM400 -10
|
||||
v298h-352v-298c0 -3.2998 2.7002 -6 6 -6h340c3.2998 0 6 2.7002 6 6z" />
|
||||
<glyph glyph-name="calendar-check" unicode="" horiz-adv-x="448"
|
||||
d="M400 384c26.5098 0 48 -21.4902 48 -48v-352c0 -26.5098 -21.4902 -48 -48 -48h-352c-26.5098 0 -48 21.4902 -48 48v352c0 26.5098 21.4902 48 48 48h48v52c0 6.62695 5.37305 12 12 12h40c6.62695 0 12 -5.37305 12 -12v-52h128v52c0 6.62695 5.37305 12 12 12h40
|
||||
c6.62695 0 12 -5.37305 12 -12v-52h48zM394 -16c3.31152 0 6 2.68848 6 6v298h-352v-298c0 -3.31152 2.68848 -6 6 -6h340zM341.151 184.65l-142.31 -141.169c-4.70508 -4.66699 -12.3027 -4.6377 -16.9707 0.0673828l-75.0908 75.6992
|
||||
c-4.66699 4.70508 -4.6377 12.3027 0.0673828 16.9707l22.7197 22.5361c4.70508 4.66699 12.3027 4.63672 16.9697 -0.0693359l44.1035 -44.4609l111.072 110.182c4.70508 4.66699 12.3027 4.63672 16.9707 -0.0683594l22.5361 -22.7178
|
||||
c4.66699 -4.70508 4.63672 -12.3027 -0.0683594 -16.9697z" />
|
||||
<glyph glyph-name="map" unicode="" horiz-adv-x="576"
|
||||
d="M560.02 416c8.4502 0 15.9805 -6.83008 15.9805 -16.0195v-346.32c0 -11.9609 -9.01367 -25.2705 -20.1201 -29.71l-151.83 -52.8105c-5.32617 -1.7334 -14.1953 -3.13965 -19.7969 -3.13965c-5.7373 0 -14.8105 1.47363 -20.2529 3.29004l-172 60.71l-170.05 -62.8398
|
||||
c-1.99023 -0.790039 -4 -1.16016 -5.95996 -1.16016c-8.45996 0 -15.9902 6.83008 -15.9902 16.0195v346.32c0.00292969 11.959 9.0166 25.2686 20.1201 29.71l151.83 52.8105c6.43945 2.08984 13.1201 3.13965 19.8096 3.13965
|
||||
c5.73242 -0.00195312 14.8008 -1.47168 20.2402 -3.28027l172 -60.7197h0.00976562l170.05 62.8398c1.98047 0.790039 4 1.16016 5.95996 1.16016zM224 357.58v-285.97l128 -45.1904v285.97zM48 29.9502l127.36 47.0801l0.639648 0.229492v286.2l-128 -44.5303v-288.979z
|
||||
M528 65.0801v288.97l-127.36 -47.0693l-0.639648 -0.240234v-286.19z" />
|
||||
<glyph glyph-name="comment-alt" unicode=""
|
||||
d="M448 448c35.2998 0 64 -28.7002 64 -64v-288c0 -35.2998 -28.7002 -64 -64 -64h-144l-124.9 -93.5996c-2.19922 -1.7002 -4.69922 -2.40039 -7.09961 -2.40039c-6.2002 0 -12 4.90039 -12 12v84h-96c-35.2998 0 -64 28.7002 -64 64v288c0 35.2998 28.7002 64 64 64h384z
|
||||
M464 96v288c0 8.7998 -7.2002 16 -16 16h-384c-8.7998 0 -16 -7.2002 -16 -16v-288c0 -8.7998 7.2002 -16 16 -16h144v-60l67.2002 50.4004l12.7998 9.59961h160c8.7998 0 16 7.2002 16 16z" />
|
||||
<glyph glyph-name="pause-circle" unicode=""
|
||||
d="M256 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM256 -8c110.5 0 200 89.5 200 200s-89.5 200 -200 200s-200 -89.5 -200 -200s89.5 -200 200 -200zM352 272v-160c0 -8.7998 -7.2002 -16 -16 -16h-48
|
||||
c-8.7998 0 -16 7.2002 -16 16v160c0 8.7998 7.2002 16 16 16h48c8.7998 0 16 -7.2002 16 -16zM240 272v-160c0 -8.7998 -7.2002 -16 -16 -16h-48c-8.7998 0 -16 7.2002 -16 16v160c0 8.7998 7.2002 16 16 16h48c8.7998 0 16 -7.2002 16 -16z" />
|
||||
<glyph glyph-name="stop-circle" unicode=""
|
||||
d="M504 192c0 -137 -111 -248 -248 -248s-248 111 -248 248s111 248 248 248s248 -111 248 -248zM56 192c0 -110.5 89.5 -200 200 -200s200 89.5 200 200s-89.5 200 -200 200s-200 -89.5 -200 -200zM352 272v-160c0 -8.7998 -7.2002 -16 -16 -16h-160
|
||||
c-8.7998 0 -16 7.2002 -16 16v160c0 8.7998 7.2002 16 16 16h160c8.7998 0 16 -7.2002 16 -16z" />
|
||||
<glyph glyph-name="handshake" unicode="" horiz-adv-x="640"
|
||||
d="M519.2 320.1h120.8v-255.699h-64c-17.5 0 -31.7998 14.1992 -31.9004 31.6992h-57.8994c-1.7998 -8.19922 -5.2998 -16.0996 -10.9004 -23l-26.2002 -32.2998c-15.7998 -19.3994 -41.8994 -25.5 -64 -16.7998c-13.5 -16.5996 -30.5996 -24 -48.7998 -24
|
||||
c-15.0996 0 -28.5996 5.09961 -41.0996 15.9004c-31.7998 -21.9004 -74.7002 -21.3008 -105.601 3.7998l-84.5996 76.3994h-9.09961c-0.100586 -17.5 -14.3008 -31.6992 -31.9004 -31.6992h-64v255.699h118l47.5996 47.6006c10.5 10.3994 24.8008 16.2998 39.6006 16.2998
|
||||
h226.8v0c12.7812 0 30.5225 -7.30273 39.5996 -16.2998zM48 96.4004c8.7998 0 16 7.09961 16 16c0 8.7998 -7.2002 16 -16 16s-16 -7.2002 -16 -16c0 -8.80078 7.2002 -16 16 -16zM438 103.3c2.7002 3.40039 2.2002 8.5 -1.2002 11.2998l-108.2 87.8008l-8.19922 -7.5
|
||||
c-40.3008 -36.8008 -86.7002 -11.8008 -101.5 4.39941c-26.7002 29 -25 74.4004 4.39941 101.3l38.7002 35.5h-56.7002c-2 -0.799805 -3.7002 -1.5 -5.7002 -2.2998l-61.6992 -61.5996h-41.9004v-128.101h27.7002l97.2998 -88
|
||||
c16.0996 -13.0996 41.4004 -10.5 55.2998 6.60059l15.6006 19.2002l36.7998 -31.5c3 -2.40039 12 -4.90039 18 2.39941l30 36.5l23.8994 -19.3994c3.5 -2.80078 8.5 -2.2002 11.3008 1.19922zM544 144.1v128h-44.7002l-61.7002 61.6006
|
||||
c-1.39941 1.5 -3.39941 2.2998 -5.5 2.2998l-83.6992 -0.200195c-10 0 -19.6006 -3.7002 -27 -10.5l-65.6006 -60.0996c-9.7002 -8.7998 -10.5 -24 -1.2002 -33.9004c8.90039 -9.39941 25.1006 -8.7002 34.6006 0l55.2002 50.6006c6.5 5.89941 16.5996 5.5 22.5996 -1
|
||||
l10.9004 -11.7002c6 -6.5 5.5 -16.6006 -1 -22.6006l-12.5 -11.3994l102.699 -83.4004c2.80078 -2.2998 5.40039 -4.89941 7.7002 -7.7002h69.2002zM592 96.4004c8.7998 0 16 7.09961 16 16c0 8.7998 -7.2002 16 -16 16s-16 -7.2002 -16 -16c0 -8.80078 7.2002 -16 16 -16z
|
||||
" />
|
||||
<glyph glyph-name="envelope-open" unicode=""
|
||||
d="M494.586 283.484c9.6123 -7.94824 17.4141 -24.5205 17.4141 -36.9932v-262.491c0 -26.5098 -21.4902 -48 -48 -48h-416c-26.5098 0 -48 21.4902 -48 48v262.515c0 12.5166 7.84668 29.1279 17.5146 37.0771c4.08008 3.35449 110.688 89.0996 135.15 108.549
|
||||
c22.6992 18.1426 60.1299 55.8594 103.335 55.8594c43.4365 0 81.2314 -38.1914 103.335 -55.8594c23.5283 -18.707 130.554 -104.773 135.251 -108.656zM464 -10v253.632v0.00488281c0 1.5791 -0.996094 3.66602 -2.22363 4.6582
|
||||
c-15.8633 12.8232 -108.793 87.5752 -132.366 106.316c-17.5527 14.0195 -49.7168 45.3887 -73.4102 45.3887c-23.6016 0 -55.2451 -30.8799 -73.4102 -45.3887c-23.5713 -18.7393 -116.494 -93.4795 -132.364 -106.293
|
||||
c-1.40918 -1.13965 -2.22559 -2.85254 -2.22559 -4.66504v-253.653c0 -3.31152 2.68848 -6 6 -6h404c3.31152 0 6 2.68848 6 6zM432.009 177.704c4.24902 -5.15918 3.46484 -12.7949 -1.74512 -16.9814c-28.9746 -23.2822 -59.2734 -47.5967 -70.9287 -56.8623
|
||||
c-22.6992 -18.1436 -60.1299 -55.8604 -103.335 -55.8604c-43.4521 0 -81.2871 38.2373 -103.335 55.8604c-11.2793 8.9668 -41.7441 33.4131 -70.9268 56.8643c-5.20996 4.1875 -5.99316 11.8223 -1.74512 16.9814l15.2578 18.5283
|
||||
c4.17773 5.07227 11.6572 5.84277 16.7793 1.72559c28.6182 -23.001 58.5654 -47.0352 70.5596 -56.5713c17.5527 -14.0195 49.7168 -45.3887 73.4102 -45.3887c23.6016 0 55.2461 30.8799 73.4102 45.3887c11.9941 9.53516 41.9434 33.5703 70.5625 56.5684
|
||||
c5.12207 4.11621 12.6016 3.3457 16.7783 -1.72656z" />
|
||||
<glyph glyph-name="address-book" unicode="" horiz-adv-x="448"
|
||||
d="M436 288h-20v-64h20c6.59961 0 12 -5.40039 12 -12v-40c0 -6.59961 -5.40039 -12 -12 -12h-20v-64h20c6.59961 0 12 -5.40039 12 -12v-40c0 -6.59961 -5.40039 -12 -12 -12h-20v-48c0 -26.5 -21.5 -48 -48 -48h-320c-26.5 0 -48 21.5 -48 48v416c0 26.5 21.5 48 48 48
|
||||
h320c26.5 0 48 -21.5 48 -48v-48h20c6.59961 0 12 -5.40039 12 -12v-40c0 -6.59961 -5.40039 -12 -12 -12zM368 -16v416h-320v-416h320zM208 192c-35.2998 0 -64 28.7002 -64 64s28.7002 64 64 64s64 -28.7002 64 -64s-28.7002 -64 -64 -64zM118.4 64
|
||||
c-12.4004 0 -22.4004 8.59961 -22.4004 19.2002v19.2002c0 31.7998 30.0996 57.5996 67.2002 57.5996c11.3994 0 17.8994 -8 44.7998 -8c26.0996 0 34 8 44.7998 8c37.1006 0 67.2002 -25.7998 67.2002 -57.5996v-19.2002c0 -10.6006 -10 -19.2002 -22.4004 -19.2002
|
||||
h-179.199z" />
|
||||
<glyph glyph-name="address-card" unicode="" horiz-adv-x="576"
|
||||
d="M528 416c26.5 0 48 -21.5 48 -48v-352c0 -26.5 -21.5 -48 -48 -48h-480c-26.5 0 -48 21.5 -48 48v352c0 26.5 21.5 48 48 48h480zM528 16v352h-480v-352h480zM208 192c-35.2998 0 -64 28.7002 -64 64s28.7002 64 64 64s64 -28.7002 64 -64s-28.7002 -64 -64 -64z
|
||||
M118.4 64c-12.4004 0 -22.4004 8.59961 -22.4004 19.2002v19.2002c0 31.7998 30.0996 57.5996 67.2002 57.5996c11.3994 0 17.8994 -8 44.7998 -8c26.0996 0 34 8 44.7998 8c37.1006 0 67.2002 -25.7998 67.2002 -57.5996v-19.2002
|
||||
c0 -10.6006 -10 -19.2002 -22.4004 -19.2002h-179.199zM360 128c-4.40039 0 -8 3.59961 -8 8v16c0 4.40039 3.59961 8 8 8h112c4.40039 0 8 -3.59961 8 -8v-16c0 -4.40039 -3.59961 -8 -8 -8h-112zM360 192c-4.40039 0 -8 3.59961 -8 8v16c0 4.40039 3.59961 8 8 8h112
|
||||
c4.40039 0 8 -3.59961 8 -8v-16c0 -4.40039 -3.59961 -8 -8 -8h-112zM360 256c-4.40039 0 -8 3.59961 -8 8v16c0 4.40039 3.59961 8 8 8h112c4.40039 0 8 -3.59961 8 -8v-16c0 -4.40039 -3.59961 -8 -8 -8h-112z" />
|
||||
<glyph glyph-name="user-circle" unicode="" horiz-adv-x="496"
|
||||
d="M248 344c53 0 96 -43 96 -96s-43 -96 -96 -96s-96 43 -96 96s43 96 96 96zM248 200c26.5 0 48 21.5 48 48s-21.5 48 -48 48s-48 -21.5 -48 -48s21.5 -48 48 -48zM248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8
|
||||
c49.7002 0 95.0996 18.2998 130.1 48.4004c-14.8994 23 -40.3994 38.5 -69.5996 39.5c-20.7998 -6.5 -40.5996 -9.60059 -60.5 -9.60059s-39.7002 3.2002 -60.5 9.60059c-29.2002 -0.900391 -54.7002 -16.5 -69.5996 -39.5c35 -30.1006 80.3994 -48.4004 130.1 -48.4004z
|
||||
M410.7 76.0996c23.3994 32.7002 37.2998 72.7002 37.2998 115.9c0 110.3 -89.7002 200 -200 200s-200 -89.7002 -200 -200c0 -43.2002 13.9004 -83.2002 37.2998 -115.9c24.5 31.4004 62.2002 51.9004 105.101 51.9004c10.1992 0 26.0996 -9.59961 57.5996 -9.59961
|
||||
c31.5996 0 47.4004 9.59961 57.5996 9.59961c43 0 80.7002 -20.5 105.101 -51.9004z" />
|
||||
<glyph glyph-name="id-badge" unicode="" horiz-adv-x="384"
|
||||
d="M336 448c26.5 0 48 -21.5 48 -48v-416c0 -26.5 -21.5 -48 -48 -48h-288c-26.5 0 -48 21.5 -48 48v416c0 26.5 21.5 48 48 48h288zM336 -16v416h-288v-416h288zM144 336c-8.7998 0 -16 7.2002 -16 16s7.2002 16 16 16h96c8.7998 0 16 -7.2002 16 -16s-7.2002 -16 -16 -16
|
||||
h-96zM192 160c-35.2998 0 -64 28.7002 -64 64s28.7002 64 64 64s64 -28.7002 64 -64s-28.7002 -64 -64 -64zM102.4 32c-12.4004 0 -22.4004 8.59961 -22.4004 19.2002v19.2002c0 31.7998 30.0996 57.5996 67.2002 57.5996c11.3994 0 17.8994 -8 44.7998 -8
|
||||
c26.0996 0 34 8 44.7998 8c37.1006 0 67.2002 -25.7998 67.2002 -57.5996v-19.2002c0 -10.6006 -10 -19.2002 -22.4004 -19.2002h-179.199z" />
|
||||
<glyph glyph-name="id-card" unicode="" horiz-adv-x="576"
|
||||
d="M528 416c26.5 0 48 -21.5 48 -48v-352c0 -26.5 -21.5 -48 -48 -48h-480c-26.5 0 -48 21.5 -48 48v352c0 26.5 21.5 48 48 48h480zM528 16v288h-480v-288h32.7998c-1 4.5 -0.799805 -3.59961 -0.799805 22.4004c0 31.7998 30.0996 57.5996 67.2002 57.5996
|
||||
c11.3994 0 17.8994 -8 44.7998 -8c26.0996 0 34 8 44.7998 8c37.1006 0 67.2002 -25.7998 67.2002 -57.5996c0 -26 0.0996094 -17.9004 -0.799805 -22.4004h224.8zM360 96c-4.40039 0 -8 3.59961 -8 8v16c0 4.40039 3.59961 8 8 8h112c4.40039 0 8 -3.59961 8 -8v-16
|
||||
c0 -4.40039 -3.59961 -8 -8 -8h-112zM360 160c-4.40039 0 -8 3.59961 -8 8v16c0 4.40039 3.59961 8 8 8h112c4.40039 0 8 -3.59961 8 -8v-16c0 -4.40039 -3.59961 -8 -8 -8h-112zM360 224c-4.40039 0 -8 3.59961 -8 8v16c0 4.40039 3.59961 8 8 8h112
|
||||
c4.40039 0 8 -3.59961 8 -8v-16c0 -4.40039 -3.59961 -8 -8 -8h-112zM192 128c-35.2998 0 -64 28.7002 -64 64s28.7002 64 64 64s64 -28.7002 64 -64s-28.7002 -64 -64 -64z" />
|
||||
<glyph glyph-name="window-maximize" unicode=""
|
||||
d="M464 416c26.5 0 48 -21.5 48 -48v-352c0 -26.5 -21.5 -48 -48 -48h-416c-26.5 0 -48 21.5 -48 48v352c0 26.5 21.5 48 48 48h416zM464 22v234h-416v-234c0 -3.2998 2.7002 -6 6 -6h404c3.2998 0 6 2.7002 6 6z" />
|
||||
<glyph glyph-name="window-minimize" unicode=""
|
||||
d="M480 -32h-448c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32h448c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32z" />
|
||||
<glyph glyph-name="window-restore" unicode=""
|
||||
d="M464 448c26.5 0 48 -21.5 48 -48v-320c0 -26.5 -21.5 -48 -48 -48h-48v-48c0 -26.5 -21.5 -48 -48 -48h-320c-26.5 0 -48 21.5 -48 48v320c0 26.5 21.5 48 48 48h48v48c0 26.5 21.5 48 48 48h320zM368 -16v208h-320v-208h320zM464 80v320h-320v-48h224
|
||||
c26.5 0 48 -21.5 48 -48v-224h48z" />
|
||||
<glyph glyph-name="snowflake" unicode="" horiz-adv-x="448"
|
||||
d="M440.1 92.7998c7.60059 -4.39941 10.1006 -14.2002 5.5 -21.7002l-7.89941 -13.8994c-4.40039 -7.7002 -14 -10.2998 -21.5 -5.90039l-39.2002 23l9.09961 -34.7002c2.30078 -8.5 -2.69922 -17.2998 -11.0996 -19.5996l-15.2002 -4.09961
|
||||
c-8.39941 -2.30078 -17.0996 2.7998 -19.2998 11.2998l-21.2998 81l-71.9004 42.2002v-84.5l58.2998 -59.3008c6.10059 -6.19922 6.10059 -16.3994 0 -22.5996l-11.0996 -11.2998c-6.09961 -6.2002 -16.0996 -6.2002 -22.2002 0l-24.8994 25.3994v-46.0996
|
||||
c0 -8.7998 -7 -16 -15.7002 -16h-15.7002c-8.7002 0 -15.7002 7.2002 -15.7002 16v45.9004l-24.8994 -25.4004c-6.10059 -6.2002 -16.1006 -6.2002 -22.2002 0l-11.1006 11.2998c-6.09961 6.2002 -6.09961 16.4004 0 22.6006l58.3008 59.2998v84.5l-71.9004 -42.2002
|
||||
l-21.2998 -81c-2.2998 -8.5 -10.9004 -13.5996 -19.2998 -11.2998l-15.2002 4.09961c-8.40039 2.2998 -13.2998 11.1006 -11.1006 19.6006l9.10059 34.6992l-39.2002 -23c-7.5 -4.39941 -17.2002 -1.7998 -21.5 5.90039l-7.90039 13.9004
|
||||
c-4.2998 7.69922 -1.69922 17.5 5.80078 21.8994l39.1992 23l-34.0996 9.2998c-8.40039 2.30078 -13.2998 11.1006 -11.0996 19.6006l4.09961 15.5c2.2998 8.5 10.9004 13.5996 19.2998 11.2998l79.7002 -21.7002l71.9004 42.2002l-71.9004 42.2002l-79.7002 -21.7002
|
||||
c-8.39941 -2.2998 -17.0996 2.7998 -19.2998 11.2998l-4.09961 15.5c-2.30078 8.5 2.69922 17.2998 11.0996 19.6006l34.0996 9.09961l-39.1992 23c-7.60059 4.5 -10.1006 14.2002 -5.80078 21.9004l7.90039 13.8994c4.40039 7.7002 14 10.2998 21.5 5.90039l39.2002 -23
|
||||
l-9.10059 34.7002c-2.2998 8.5 2.7002 17.2998 11.1006 19.5996l15.2002 4.09961c8.39941 2.30078 17.0996 -2.7998 19.2998 -11.2998l21.2998 -81l71.9004 -42.2002v84.5l-58.3008 59.3008c-6.09961 6.19922 -6.09961 16.3994 0 22.5996l11.5 11.2998
|
||||
c6.10059 6.2002 16.1006 6.2002 22.2002 0l24.9004 -25.3994v46.0996c0 8.7998 7 16 15.7002 16h15.6992c8.7002 0 15.7002 -7.2002 15.7002 -16v-45.9004l24.9004 25.4004c6.09961 6.2002 16.0996 6.2002 22.2002 0l11.0996 -11.2998
|
||||
c6.09961 -6.2002 6.09961 -16.4004 0 -22.6006l-58.2998 -59.2998v-84.5l71.8994 42.2002l21.3008 81c2.2998 8.5 10.8994 13.5996 19.2998 11.2998l15.2002 -4.09961c8.39941 -2.2998 13.2998 -11.1006 11.0996 -19.6006l-9.09961 -34.6992l39.1992 23
|
||||
c7.5 4.39941 17.2002 1.7998 21.5 -5.90039l7.90039 -13.9004c4.2998 -7.69922 1.7002 -17.5 -5.7998 -21.8994l-39.2002 -23l34.0996 -9.2998c8.40039 -2.30078 13.3008 -11.1006 11.1006 -19.6006l-4.10059 -15.5c-2.2998 -8.5 -10.8994 -13.5996 -19.2998 -11.2998
|
||||
l-79.7002 21.7002l-71.8994 -42.2002l71.7998 -42.2002l79.7002 21.7002c8.39941 2.2998 17.0996 -2.7998 19.2998 -11.2998l4.09961 -15.5c2.30078 -8.5 -2.69922 -17.2998 -11.0996 -19.6006l-34.0996 -9.2998z" />
|
||||
<glyph glyph-name="trash-alt" unicode="" horiz-adv-x="448"
|
||||
d="M268 32c-6.62402 0 -12 5.37598 -12 12v216c0 6.62402 5.37598 12 12 12h24c6.62402 0 12 -5.37598 12 -12v-216c0 -6.62402 -5.37598 -12 -12 -12h-24zM432 368c8.83203 0 16 -7.16797 16 -16v-16c0 -8.83203 -7.16797 -16 -16 -16h-16v-336
|
||||
c0 -26.4961 -21.5039 -48 -48 -48h-288c-26.4961 0 -48 21.5039 -48 48v336h-16c-8.83203 0 -16 7.16797 -16 16v16c0 8.83203 7.16797 16 16 16h82.4102l34.0195 56.7002c7.71875 12.8613 26.1572 23.2998 41.1572 23.2998h0.00292969h100.82h0.0224609
|
||||
c15 0 33.4385 -10.4385 41.1572 -23.2998l34 -56.7002h82.4102zM171.84 397.09l-17.4502 -29.0898h139.221l-17.46 29.0898c-0.96582 1.60645 -3.26953 2.91016 -5.14355 2.91016h-0.00683594h-94h-0.0166016c-1.87402 0 -4.17871 -1.30371 -5.14355 -2.91016zM368 -16v336
|
||||
h-288v-336h288zM156 32c-6.62402 0 -12 5.37598 -12 12v216c0 6.62402 5.37598 12 12 12h24c6.62402 0 12 -5.37598 12 -12v-216c0 -6.62402 -5.37598 -12 -12 -12h-24z" />
|
||||
<glyph glyph-name="images" unicode="" horiz-adv-x="576"
|
||||
d="M480 32v-16c0 -26.5098 -21.4902 -48 -48 -48h-384c-26.5098 0 -48 21.4902 -48 48v256c0 26.5098 21.4902 48 48 48h16v-48h-10c-3.31152 0 -6 -2.68848 -6 -6v-244c0 -3.31152 2.68848 -6 6 -6h372c3.31152 0 6 2.68848 6 6v10h48zM522 368h-372
|
||||
c-3.31152 0 -6 -2.68848 -6 -6v-244c0 -3.31152 2.68848 -6 6 -6h372c3.31152 0 6 2.68848 6 6v244c0 3.31152 -2.68848 6 -6 6zM528 416c26.5098 0 48 -21.4902 48 -48v-256c0 -26.5098 -21.4902 -48 -48 -48h-384c-26.5098 0 -48 21.4902 -48 48v256
|
||||
c0 26.5098 21.4902 48 48 48h384zM264 304c0 -22.0908 -17.9092 -40 -40 -40s-40 17.9092 -40 40s17.9092 40 40 40s40 -17.9092 40 -40zM192 208l39.5146 39.5146c4.68652 4.68652 12.2842 4.68652 16.9717 0l39.5137 -39.5146l103.515 103.515
|
||||
c4.68652 4.68652 12.2842 4.68652 16.9717 0l71.5137 -71.5146v-80h-288v48z" />
|
||||
<glyph glyph-name="clipboard" unicode="" horiz-adv-x="384"
|
||||
d="M336 384c26.5 0 48 -21.5 48 -48v-352c0 -26.5 -21.5 -48 -48 -48h-288c-26.5 0 -48 21.5 -48 48v352c0 26.5 21.5 48 48 48h80c0 35.2998 28.7002 64 64 64s64 -28.7002 64 -64h80zM192 408c-13.2998 0 -24 -10.7002 -24 -24s10.7002 -24 24 -24s24 10.7002 24 24
|
||||
s-10.7002 24 -24 24zM336 -10v340c0 3.2998 -2.7002 6 -6 6h-42v-36c0 -6.59961 -5.40039 -12 -12 -12h-168c-6.59961 0 -12 5.40039 -12 12v36h-42c-3.2998 0 -6 -2.7002 -6 -6v-340c0 -3.2998 2.7002 -6 6 -6h276c3.2998 0 6 2.7002 6 6z" />
|
||||
<glyph glyph-name="arrow-alt-circle-down" unicode=""
|
||||
d="M256 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM256 -8c110.5 0 200 89.5 200 200s-89.5 200 -200 200s-200 -89.5 -200 -200s89.5 -200 200 -200zM224 308c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-116
|
||||
h67c10.7002 0 16.0996 -12.9004 8.5 -20.5l-99 -99c-4.7002 -4.7002 -12.2998 -4.7002 -17 0l-99 99c-7.5 7.59961 -2.2002 20.5 8.5 20.5h67v116z" />
|
||||
<glyph glyph-name="arrow-alt-circle-left" unicode=""
|
||||
d="M8 192c0 137 111 248 248 248s248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248zM456 192c0 110.5 -89.5 200 -200 200s-200 -89.5 -200 -200s89.5 -200 200 -200s200 89.5 200 200zM384 212v-40c0 -6.59961 -5.40039 -12 -12 -12h-116v-67
|
||||
c0 -10.7002 -12.9004 -16 -20.5 -8.5l-99 99c-4.7002 4.7002 -4.7002 12.2998 0 17l99 99c7.59961 7.59961 20.5 2.2002 20.5 -8.5v-67h116c6.59961 0 12 -5.40039 12 -12z" />
|
||||
<glyph glyph-name="arrow-alt-circle-right" unicode=""
|
||||
d="M504 192c0 -137 -111 -248 -248 -248s-248 111 -248 248s111 248 248 248s248 -111 248 -248zM56 192c0 -110.5 89.5 -200 200 -200s200 89.5 200 200s-89.5 200 -200 200s-200 -89.5 -200 -200zM128 172v40c0 6.59961 5.40039 12 12 12h116v67
|
||||
c0 10.7002 12.9004 16 20.5 8.5l99 -99c4.7002 -4.7002 4.7002 -12.2998 0 -17l-99 -99c-7.59961 -7.59961 -20.5 -2.2002 -20.5 8.5v67h-116c-6.59961 0 -12 5.40039 -12 12z" />
|
||||
<glyph glyph-name="arrow-alt-circle-up" unicode=""
|
||||
d="M256 -56c-137 0 -248 111 -248 248s111 248 248 248s248 -111 248 -248s-111 -248 -248 -248zM256 392c-110.5 0 -200 -89.5 -200 -200s89.5 -200 200 -200s200 89.5 200 200s-89.5 200 -200 200zM276 64h-40c-6.59961 0 -12 5.40039 -12 12v116h-67
|
||||
c-10.7002 0 -16 12.9004 -8.5 20.5l99 99c4.7002 4.7002 12.2998 4.7002 17 0l99 -99c7.59961 -7.59961 2.2002 -20.5 -8.5 -20.5h-67v-116c0 -6.59961 -5.40039 -12 -12 -12z" />
|
||||
<glyph glyph-name="gem" unicode="" horiz-adv-x="576"
|
||||
d="M464 448c4.09961 0 7.7998 -2 10.0996 -5.40039l99.9004 -147.199c2.90039 -4.40039 2.59961 -10.1006 -0.700195 -14.2002l-276 -340.8c-4.7998 -5.90039 -13.7998 -5.90039 -18.5996 0l-276 340.8c-3.2998 4 -3.60059 9.7998 -0.700195 14.2002l100 147.199
|
||||
c2.2002 3.40039 6 5.40039 10 5.40039h352zM444.7 400h-56.7998l51.6992 -96h68.4004zM242.6 400l-51.5996 -96h194l-51.7002 96h-90.7002zM131.3 400l-63.2998 -96h68.4004l51.6992 96h-56.7998zM88.2998 256l119.7 -160l-68.2998 160h-51.4004zM191.2 256l96.7998 -243.3
|
||||
l96.7998 243.3h-193.6zM368 96l119.6 160h-51.3994z" />
|
||||
<glyph glyph-name="money-bill-alt" unicode="" horiz-adv-x="640"
|
||||
d="M320 304c53.0195 0 96 -50.1396 96 -112c0 -61.8701 -43 -112 -96 -112c-53.0195 0 -96 50.1504 -96 112c0 61.8604 42.9805 112 96 112zM360 136v16c0 4.41992 -3.58008 8 -8 8h-16v88c0 4.41992 -3.58008 8 -8 8h-13.5801h-0.000976562
|
||||
c-4.01074 0 -9.97266 -1.80566 -13.3086 -4.03027l-15.3301 -10.2197c-1.96777 -1.30957 -3.56445 -4.29004 -3.56445 -6.65332c0 -1.33691 0.601562 -3.32422 1.34375 -4.43652l8.88086 -13.3105c1.30859 -1.9668 4.29004 -3.56445 6.65332 -3.56445
|
||||
c1.33691 0 3.32422 0.602539 4.43652 1.34473l0.469727 0.310547v-55.4404h-16c-4.41992 0 -8 -3.58008 -8 -8v-16c0 -4.41992 3.58008 -8 8 -8h64c4.41992 0 8 3.58008 8 8zM608 384c17.6699 0 32 -14.3301 32 -32v-320c0 -17.6699 -14.3301 -32 -32 -32h-576
|
||||
c-17.6699 0 -32 14.3301 -32 32v320c0 17.6699 14.3301 32 32 32h576zM592 112v160c-35.3496 0 -64 28.6504 -64 64h-416c0 -35.3496 -28.6504 -64 -64 -64v-160c35.3496 0 64 -28.6504 64 -64h416c0 35.3496 28.6504 64 64 64z" />
|
||||
<glyph glyph-name="window-close" unicode=""
|
||||
d="M464 416c26.5 0 48 -21.5 48 -48v-352c0 -26.5 -21.5 -48 -48 -48h-416c-26.5 0 -48 21.5 -48 48v352c0 26.5 21.5 48 48 48h416zM464 22v340c0 3.2998 -2.7002 6 -6 6h-404c-3.2998 0 -6 -2.7002 -6 -6v-340c0 -3.2998 2.7002 -6 6 -6h404c3.2998 0 6 2.7002 6 6z
|
||||
M356.5 253.4l-61.4004 -61.4004l61.4004 -61.4004c4.59961 -4.59961 4.59961 -12.0996 0 -16.7998l-22.2998 -22.2998c-4.60059 -4.59961 -12.1006 -4.59961 -16.7998 0l-61.4004 61.4004l-61.4004 -61.4004c-4.59961 -4.59961 -12.0996 -4.59961 -16.7998 0
|
||||
l-22.2998 22.2998c-4.59961 4.60059 -4.59961 12.1006 0 16.7998l61.4004 61.4004l-61.4004 61.4004c-4.59961 4.59961 -4.59961 12.0996 0 16.7998l22.2998 22.2998c4.60059 4.59961 12.1006 4.59961 16.7998 0l61.4004 -61.4004l61.4004 61.4004
|
||||
c4.59961 4.59961 12.0996 4.59961 16.7998 0l22.2998 -22.2998c4.7002 -4.60059 4.7002 -12.1006 0 -16.7998z" />
|
||||
<glyph glyph-name="comment-dots" unicode=""
|
||||
d="M144 240c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32s-32 14.2998 -32 32s14.2998 32 32 32zM256 240c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32s-32 14.2998 -32 32s14.2998 32 32 32zM368 240c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32
|
||||
s-32 14.2998 -32 32s14.2998 32 32 32zM256 416c141.4 0 256 -93.0996 256 -208s-114.6 -208 -256 -208c-32.7998 0 -64 5.2002 -92.9004 14.2998c-29.0996 -20.5996 -77.5996 -46.2998 -139.1 -46.2998c-9.59961 0 -18.2998 5.7002 -22.0996 14.5
|
||||
c-3.80078 8.7998 -2 19 4.59961 26c0.5 0.400391 31.5 33.7998 46.4004 73.2002c-33 35.0996 -52.9004 78.7002 -52.9004 126.3c0 114.9 114.6 208 256 208zM256 48c114.7 0 208 71.7998 208 160s-93.2998 160 -208 160s-208 -71.7998 -208 -160
|
||||
c0 -42.2002 21.7002 -74.0996 39.7998 -93.4004l20.6006 -21.7998l-10.6006 -28.0996c-5.5 -14.5 -12.5996 -28.1006 -19.8994 -40.2002c23.5996 7.59961 43.1992 18.9004 57.5 29l19.5 13.7998l22.6992 -7.2002c25.3008 -8 51.7002 -12.0996 78.4004 -12.0996z" />
|
||||
<glyph glyph-name="smile-wink" unicode="" horiz-adv-x="496"
|
||||
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM365.8 138.4c10.2002 -8.5 11.6006 -23.6006 3.10059 -33.8008
|
||||
c-30 -36 -74.1006 -56.5996 -120.9 -56.5996s-90.9004 20.5996 -120.9 56.5996c-8.39941 10.2002 -7.09961 25.3008 3.10059 33.8008c10.0996 8.39941 25.2998 7.09961 33.7998 -3.10059c20.7998 -25.0996 51.5 -39.3994 84 -39.3994s63.2002 14.3994 84 39.3994
|
||||
c8.5 10.2002 23.5996 11.6006 33.7998 3.10059zM168 208c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32s32 -14.2998 32 -32s-14.2998 -32 -32 -32zM328 268c25.7002 0 55.9004 -16.9004 59.7002 -42.0996c1.7998 -11.1006 -11.2998 -18.2002 -19.7998 -10.8008l-9.5 8.5
|
||||
c-14.8008 13.2002 -46.2002 13.2002 -61 0l-9.5 -8.5c-8.30078 -7.39941 -21.5 -0.399414 -19.8008 10.8008c4 25.1992 34.2002 42.0996 59.9004 42.0996z" />
|
||||
<glyph glyph-name="angry" unicode="" horiz-adv-x="496"
|
||||
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM248 136c33.5996 0 65.2002 -14.7998 86.7998 -40.5996
|
||||
c8.40039 -10.2002 7.10059 -25.3008 -3.09961 -33.8008c-10.6006 -8.89941 -25.7002 -6.69922 -33.7998 3c-24.8008 29.7002 -75 29.7002 -99.8008 0c-8.5 -10.1992 -23.5996 -11.5 -33.7998 -3s-11.5996 23.6006 -3.09961 33.8008
|
||||
c21.5996 25.7998 53.2002 40.5996 86.7998 40.5996zM200 208c0 -17.7002 -14.2998 -32.0996 -32 -32.0996s-32 14.2998 -32 32c0 6.19922 2.2002 11.6992 5.2998 16.5996l-28.2002 8.5c-12.6992 3.7998 -19.8994 17.2002 -16.0996 29.9004
|
||||
c3.7998 12.6992 17.0996 20 29.9004 16.0996l80 -24c12.6992 -3.7998 19.8994 -17.2002 16.0996 -29.9004c-3.09961 -10.3994 -12.7002 -17.0996 -23 -17.0996zM399 262.9c3.7998 -12.7002 -3.40039 -26.1006 -16.0996 -29.8008l-28.2002 -8.5
|
||||
c3.09961 -4.89941 5.2998 -10.3994 5.2998 -16.5996c0 -17.7002 -14.2998 -32 -32 -32s-32 14.2998 -32 32c-10.2998 0 -19.9004 6.7002 -23 17.0996c-3.7998 12.7002 3.40039 26.1006 16.0996 29.9004l80 24c12.8008 3.7998 26.1006 -3.40039 29.9004 -16.0996z" />
|
||||
<glyph glyph-name="dizzy" unicode="" horiz-adv-x="496"
|
||||
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM214.2 209.9
|
||||
c-7.90039 -7.90039 -20.5 -7.90039 -28.4004 -0.200195l-17.7998 17.7998l-17.7998 -17.7998c-7.7998 -7.7998 -20.5 -7.7998 -28.2998 0c-7.80078 7.7998 -7.80078 20.5 0 28.2998l17.8994 17.9004l-17.8994 17.8994c-7.80078 7.7998 -7.80078 20.5 0 28.2998
|
||||
c7.7998 7.80078 20.5 7.80078 28.2998 0l17.7998 -17.7998l17.9004 17.9004c7.7998 7.7998 20.5 7.7998 28.2998 0s7.7998 -20.5 0 -28.2998l-17.9004 -17.9004l17.9004 -17.7998c7.7998 -7.7998 7.7998 -20.5 0 -28.2998zM374.2 302.1
|
||||
c7.7002 -7.7998 7.7002 -20.3994 0 -28.1992l-17.9004 -17.9004l17.7998 -18c7.80078 -7.7998 7.80078 -20.5 0 -28.2998c-7.7998 -7.7998 -20.5 -7.7998 -28.2998 0l-17.7998 17.7998l-17.7998 -17.7998c-7.7998 -7.7998 -20.5 -7.7998 -28.2998 0
|
||||
c-7.80078 7.7998 -7.80078 20.5 0 28.2998l17.8994 17.9004l-17.8994 17.8994c-7.80078 7.7998 -7.80078 20.5 0 28.2998c7.7998 7.80078 20.5 7.80078 28.2998 0l17.7998 -17.7998l17.9004 17.7998c7.7998 7.80078 20.5 7.80078 28.2998 0zM248 176
|
||||
c35.2998 0 64 -28.7002 64 -64s-28.7002 -64 -64 -64s-64 28.7002 -64 64s28.7002 64 64 64z" />
|
||||
<glyph glyph-name="flushed" unicode="" horiz-adv-x="496"
|
||||
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM344 304c44.2002 0 80 -35.7998 80 -80s-35.7998 -80 -80 -80
|
||||
s-80 35.7998 -80 80s35.7998 80 80 80zM344 176c26.5 0 48 21.5 48 48s-21.5 48 -48 48s-48 -21.5 -48 -48s21.5 -48 48 -48zM344 248c13.2998 0 24 -10.7002 24 -24s-10.7002 -24 -24 -24s-24 10.7002 -24 24s10.7002 24 24 24zM232 224c0 -44.2002 -35.7998 -80 -80 -80
|
||||
s-80 35.7998 -80 80s35.7998 80 80 80s80 -35.7998 80 -80zM152 176c26.5 0 48 21.5 48 48s-21.5 48 -48 48s-48 -21.5 -48 -48s21.5 -48 48 -48zM152 248c13.2998 0 24 -10.7002 24 -24s-10.7002 -24 -24 -24s-24 10.7002 -24 24s10.7002 24 24 24zM312 104
|
||||
c13.2002 0 24 -10.7998 24 -24s-10.7998 -24 -24 -24h-128c-13.2002 0 -24 10.7998 -24 24s10.7998 24 24 24h128z" />
|
||||
<glyph glyph-name="frown-open" unicode="" horiz-adv-x="496"
|
||||
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM200 240c0 -17.7002 -14.2998 -32 -32 -32s-32 14.2998 -32 32
|
||||
s14.2998 32 32 32s32 -14.2998 32 -32zM328 272c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32s-32 14.2998 -32 32s14.2998 32 32 32zM248 160c35.5996 0 88.7998 -21.2998 95.7998 -61.2002c2 -11.7998 -9.09961 -21.5996 -20.5 -18.0996
|
||||
c-31.2002 9.59961 -59.3994 15.2998 -75.2998 15.2998s-44.0996 -5.7002 -75.2998 -15.2998c-11.5 -3.40039 -22.5 6.2998 -20.5 18.0996c7 39.9004 60.2002 61.2002 95.7998 61.2002z" />
|
||||
<glyph glyph-name="grimace" unicode="" horiz-adv-x="496"
|
||||
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM168 208c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32
|
||||
s32 -14.2998 32 -32s-14.2998 -32 -32 -32zM328 208c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32s32 -14.2998 32 -32s-14.2998 -32 -32 -32zM344 192c26.5 0 48 -21.5 48 -48v-32c0 -26.5 -21.5 -48 -48 -48h-192c-26.5 0 -48 21.5 -48 48v32c0 26.5 21.5 48 48 48
|
||||
h192zM176 96v24h-40v-8c0 -8.7998 7.2002 -16 16 -16h24zM176 136v24h-24c-8.7998 0 -16 -7.2002 -16 -16v-8h40zM240 96v24h-48v-24h48zM240 136v24h-48v-24h48zM304 96v24h-48v-24h48zM304 136v24h-48v-24h48zM360 112v8h-40v-24h24c8.7998 0 16 7.2002 16 16zM360 136v8
|
||||
c0 8.7998 -7.2002 16 -16 16h-24v-24h40z" />
|
||||
<glyph glyph-name="grin" unicode="" horiz-adv-x="496"
|
||||
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM353.6 143.4c10 3.09961 19.3008 -5.5 17.7002 -15.3008
|
||||
c-8 -47.0996 -71.2998 -80 -123.3 -80s-115.4 32.9004 -123.3 80c-1.7002 9.90039 7.7998 18.4004 17.7002 15.3008c26 -8.30078 64.3994 -13.1006 105.6 -13.1006s79.7002 4.7998 105.6 13.1006zM168 208c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32
|
||||
s32 -14.2998 32 -32s-14.2998 -32 -32 -32zM328 208c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32s32 -14.2998 32 -32s-14.2998 -32 -32 -32z" />
|
||||
<glyph glyph-name="grin-alt" unicode="" horiz-adv-x="496"
|
||||
d="M200.3 200c-7.5 -11.4004 -24.5996 -12 -32.7002 0c-12.3994 18.7002 -15.1992 37.2998 -15.6992 56c0.599609 18.7002 3.2998 37.2998 15.6992 56c7.60059 11.4004 24.7002 12 32.7002 0c12.4004 -18.7002 15.2002 -37.2998 15.7002 -56
|
||||
c-0.599609 -18.7002 -3.2998 -37.2998 -15.7002 -56zM328.3 200c-7.5 -11.4004 -24.5996 -12 -32.7002 0c-12.3994 18.7002 -15.1992 37.2998 -15.6992 56c0.599609 18.7002 3.2998 37.2998 15.6992 56c7.60059 11.4004 24.7002 12 32.7002 0
|
||||
c12.4004 -18.7002 15.2002 -37.2998 15.7002 -56c-0.599609 -18.7002 -3.2998 -37.2998 -15.7002 -56zM248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200
|
||||
s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM353.6 143.4c10 3.09961 19.3008 -5.5 17.7002 -15.3008c-8 -47.0996 -71.2998 -80 -123.3 -80s-115.4 32.8008 -123.3 80c-1.7002 10 7.7998 18.4004 17.7002 15.3008c26 -8.30078 64.3994 -13.1006 105.6 -13.1006
|
||||
s79.7002 4.7998 105.6 13.1006z" />
|
||||
<glyph glyph-name="grin-beam" unicode="" horiz-adv-x="496"
|
||||
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM353.6 143.4c10 3.09961 19.3008 -5.5 17.7002 -15.3008
|
||||
c-8 -47.0996 -71.2998 -80 -123.3 -80s-115.4 32.9004 -123.3 80c-1.7002 10 7.89941 18.4004 17.7002 15.3008c26 -8.30078 64.3994 -13.1006 105.6 -13.1006s79.7002 4.7998 105.6 13.1006zM117.7 216.3c-3.60059 1.10059 -6 4.60059 -5.7002 8.2998
|
||||
c3.2998 42.1006 32.2002 71.4004 56 71.4004s52.7002 -29.2998 56 -71.4004c0.299805 -3.7998 -2.09961 -7.19922 -5.7002 -8.2998c-3.09961 -1 -7.2002 0 -9.2998 3.7002l-9.5 17c-7.7002 13.7002 -19.2002 21.5996 -31.5 21.5996s-23.7998 -7.89941 -31.5 -21.5996
|
||||
l-9.5 -17c-1.90039 -3.2002 -5.7998 -4.7998 -9.2998 -3.7002zM277.7 216.3c-3.60059 1.10059 -6 4.60059 -5.7002 8.2998c3.2998 42.1006 32.2002 71.4004 56 71.4004s52.7002 -29.2998 56 -71.4004c0.299805 -3.7998 -2.09961 -7.19922 -5.7002 -8.2998
|
||||
c-3.09961 -1 -7.2002 0 -9.2998 3.7002l-9.5 17c-7.7002 13.7002 -19.2002 21.5996 -31.5 21.5996s-23.7998 -7.89941 -31.5 -21.5996l-9.5 -17c-1.90039 -3.2002 -5.7998 -4.7998 -9.2998 -3.7002z" />
|
||||
<glyph glyph-name="grin-beam-sweat" unicode="" horiz-adv-x="496"
|
||||
d="M440 288c-29.5 0 -53.2998 26.2998 -53.2998 58.7002c0 25 31.7002 75.5 46.2002 97.2998c3.5 5.2998 10.5996 5.2998 14.1992 0c14.5 -21.7998 46.2002 -72.2998 46.2002 -97.2998c0 -32.4004 -23.7998 -58.7002 -53.2998 -58.7002zM248 48
|
||||
c-51.9004 0 -115.3 32.9004 -123.3 80c-1.7002 10 7.89941 18.4004 17.7002 15.2998c26 -8.2998 64.3994 -13.0996 105.6 -13.0996s79.7002 4.7998 105.6 13.0996c10 3.2002 19.4004 -5.39941 17.7002 -15.2998c-8 -47.0996 -71.3994 -80 -123.3 -80zM378.3 216.3
|
||||
c-3.09961 -0.899414 -7.2002 0.100586 -9.2998 3.7002l-9.5 17c-7.7002 13.7002 -19.2002 21.5996 -31.5 21.5996s-23.7998 -7.89941 -31.5 -21.5996l-9.5 -17c-1.90039 -3.2002 -5.7998 -4.7998 -9.2998 -3.7002c-3.60059 1.10059 -6 4.60059 -5.7002 8.2998
|
||||
c3.2998 42.1006 32.2002 71.4004 56 71.4004s52.7002 -29.2998 56 -71.4004c0.299805 -3.7998 -2.09961 -7.19922 -5.7002 -8.2998zM483.6 269.2c8 -24.2998 12.4004 -50.2002 12.4004 -77.2002c0 -137 -111 -248 -248 -248s-248 111 -248 248s111 248 248 248
|
||||
c45.7002 0 88.4004 -12.5996 125.2 -34.2002c-10.9004 -21.5996 -15.5 -36.2002 -17.2002 -45.7002c-31.2002 20.1006 -68.2002 31.9004 -108 31.9004c-110.3 0 -200 -89.7002 -200 -200s89.7002 -200 200 -200s200 89.7002 200 200
|
||||
c0 22.5 -3.90039 44.0996 -10.7998 64.2998c0.399414 0 21.7998 -2.7998 46.3994 12.9004zM168 258.6c-12.2998 0 -23.7998 -7.7998 -31.5 -21.5996l-9.5 -17c-1.90039 -3.2002 -5.7998 -4.7998 -9.2998 -3.7002c-3.60059 1.10059 -6 4.60059 -5.7002 8.2998
|
||||
c3.2998 42.1006 32.2002 71.4004 56 71.4004s52.7002 -29.2998 56 -71.4004c0.299805 -3.7998 -2.09961 -7.19922 -5.7002 -8.2998c-3.09961 -1 -7.2002 0 -9.2998 3.7002l-9.5 17c-7.7002 13.7002 -19.2002 21.5996 -31.5 21.5996z" />
|
||||
<glyph glyph-name="grin-hearts" unicode="" horiz-adv-x="496"
|
||||
d="M353.6 143.4c10 3.09961 19.3008 -5.5 17.7002 -15.3008c-8 -47.0996 -71.2998 -80 -123.3 -80s-115.4 32.8008 -123.3 80c-1.7002 10 7.89941 18.4004 17.7002 15.3008c26 -8.30078 64.3994 -13.1006 105.6 -13.1006s79.7002 4.7998 105.6 13.1006zM200.8 192.3
|
||||
l-70.2002 18.1006c-20.3994 5.2998 -31.8994 27 -24.1992 47.1992c6.69922 17.7002 26.6992 26.7002 44.8994 22l7.10059 -1.89941l2 7.09961c5.09961 18.1006 22.8994 30.9004 41.5 27.9004c21.3994 -3.40039 34.3994 -24.2002 28.7998 -44.5l-19.4004 -69.9004
|
||||
c-1.2998 -4.5 -6 -7.2002 -10.5 -6zM389.6 257.6c7.7002 -20.1992 -3.7998 -41.7998 -24.1992 -47.0996l-70.2002 -18.2002c-4.60059 -1.2002 -9.2998 1.5 -10.5 6l-19.4004 69.9004c-5.59961 20.2998 7.40039 41.0996 28.7998 44.5c18.7002 3 36.5 -9.7998 41.5 -27.9004
|
||||
l2 -7.09961l7.10059 1.89941c18.2002 4.7002 38.2002 -4.39941 44.8994 -22zM248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200
|
||||
s89.7002 -200 200 -200z" />
|
||||
<glyph glyph-name="grin-squint" unicode="" horiz-adv-x="496"
|
||||
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM353.6 143.4c10 3.09961 19.3008 -5.5 17.7002 -15.3008
|
||||
c-8 -47.0996 -71.2998 -80 -123.3 -80s-115.4 32.9004 -123.3 80c-1.7002 9.90039 7.7998 18.4004 17.7002 15.3008c26 -8.30078 64.3994 -13.1006 105.6 -13.1006s79.7002 4.7998 105.6 13.1006zM118.9 184.2c-3.80078 4.39941 -3.90039 11 -0.100586 15.5l33.6006 40.2998
|
||||
l-33.6006 40.2998c-3.7002 4.5 -3.7002 11 0.100586 15.5c3.89941 4.40039 10.1992 5.5 15.2998 2.5l80 -48c3.59961 -2.2002 5.7998 -6.09961 5.7998 -10.2998s-2.2002 -8.09961 -5.7998 -10.2998l-80 -48c-5.40039 -3.2002 -11.7002 -1.7002 -15.2998 2.5zM361.8 181.7
|
||||
l-80 48c-3.59961 2.2002 -5.7998 6.09961 -5.7998 10.2998s2.2002 8.09961 5.7998 10.2998l80 48c5.10059 2.90039 11.5 1.90039 15.2998 -2.5c3.80078 -4.5 3.90039 -11 0.100586 -15.5l-33.6006 -40.2998l33.6006 -40.2998c3.7002 -4.5 3.7002 -11 -0.100586 -15.5
|
||||
c-3.59961 -4.2002 -9.89941 -5.7002 -15.2998 -2.5z" />
|
||||
<glyph glyph-name="grin-squint-tears" unicode=""
|
||||
d="M117.1 63.9004c6.30078 0.899414 11.7002 -4.5 10.9004 -10.9004c-3.7002 -25.7998 -13.7002 -84 -30.5996 -100.9c-22 -21.8994 -57.9004 -21.5 -80.3008 0.900391c-22.3994 22.4004 -22.7998 58.4004 -0.899414 80.2998
|
||||
c16.8994 16.9004 75.0996 26.9004 100.899 30.6006zM75.9004 105.6c-19.6006 -3.89941 -35.1006 -8.09961 -47.3008 -12.1992c-39.2998 90.5996 -22.0996 199.899 52 274c48.5 48.3994 111.9 72.5996 175.4 72.5996c38.9004 0 77.7998 -9.2002 113.2 -27.4004
|
||||
c-4 -12.1992 -8.2002 -28 -12 -48.2998c-30.4004 17.9004 -65 27.7002 -101.2 27.7002c-53.4004 0 -103.6 -20.7998 -141.4 -58.5996c-61.5996 -61.5 -74.2998 -153.4 -38.6992 -227.801zM428.2 293.2c20.2998 3.89941 36.2002 8 48.5 12
|
||||
c47.8994 -93.2002 32.8994 -210.5 -45.2002 -288.601c-48.5 -48.3994 -111.9 -72.5996 -175.4 -72.5996c-33.6992 0 -67.2998 7 -98.6992 20.5996c4.19922 12.2002 8.2998 27.7002 12.1992 47.2002c26.6006 -12.7998 55.9004 -19.7998 86.4004 -19.7998
|
||||
c53.4004 0 103.6 20.7998 141.4 58.5996c65.6992 65.7002 75.7998 166 30.7998 242.601zM394.9 320.1c-6.30078 -0.899414 -11.7002 4.5 -10.9004 10.9004c3.7002 25.7998 13.7002 84 30.5996 100.9c22 21.8994 57.9004 21.5 80.3008 -0.900391
|
||||
c22.3994 -22.4004 22.7998 -58.4004 0.899414 -80.2998c-16.8994 -16.9004 -75.0996 -26.9004 -100.899 -30.6006zM207.9 211.8c3 -3 4.19922 -7.2998 3.19922 -11.5l-22.5996 -90.5c-1.40039 -5.39941 -6.2002 -9.09961 -11.7002 -9.09961h-0.899414
|
||||
c-5.80078 0.5 -10.5 5.09961 -11 10.8994l-4.80078 52.3008l-52.2998 4.7998c-5.7998 0.5 -10.3994 5.2002 -10.8994 11c-0.400391 5.89941 3.39941 11.2002 9.09961 12.5996l90.5 22.7002c4.2002 1 8.40039 -0.200195 11.4004 -3.2002zM247.6 236.9
|
||||
c-0.0996094 0 -6.39941 -1.80078 -11.3994 3.19922c-3 3 -4.2002 7.30078 -3.2002 11.4004l22.5996 90.5c1.40039 5.7002 7 9.2002 12.6006 9.09961c5.7998 -0.5 10.5 -5.09961 11 -10.8994l4.7998 -52.2998l52.2998 -4.80078c5.7998 -0.5 10.4004 -5.19922 10.9004 -11
|
||||
c0.399414 -5.89941 -3.40039 -11.1992 -9.10059 -12.5996zM299.6 148.4c29.1006 29.0996 53 59.5996 65.3008 83.7998c4.89941 9.2998 17.5996 9.89941 23.3994 1.7002c27.7002 -38.9004 6.10059 -106.9 -30.5996 -143.7s-104.8 -58.2998 -143.7 -30.6006
|
||||
c-8.2998 5.90039 -7.5 18.6006 1.7002 23.4004c24.2002 12.5 54.7998 36.2998 83.8994 65.4004z" />
|
||||
<glyph glyph-name="grin-stars" unicode="" horiz-adv-x="496"
|
||||
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM353.6 143.4c10 3.09961 19.3008 -5.5 17.7002 -15.3008
|
||||
c-8 -47.0996 -71.2998 -80 -123.3 -80s-115.4 32.8008 -123.3 80c-1.7002 10 7.89941 18.4004 17.7002 15.3008c26 -8.30078 64.3994 -13.1006 105.6 -13.1006s79.7002 4.7998 105.6 13.1006zM125.7 200.9l6.09961 34.8994l-25.3994 24.6006
|
||||
c-4.60059 4.59961 -1.90039 12.2998 4.2998 13.1992l34.8994 5l15.5 31.6006c2.90039 5.7998 11 5.7998 13.9004 0l15.5 -31.6006l34.9004 -5c6.19922 -1 8.7998 -8.69922 4.2998 -13.1992l-25.4004 -24.6006l6 -34.8994c1 -6.2002 -5.39941 -11 -11 -7.90039
|
||||
l-31.2998 16.2998l-31.2998 -16.2998c-5.60059 -3.09961 -12 1.7002 -11 7.90039zM385.4 273.6c6.19922 -1 8.89941 -8.59961 4.39941 -13.1992l-25.3994 -24.6006l6 -34.8994c1 -6.2002 -5.40039 -11 -11 -7.90039l-31.3008 16.2998l-31.2998 -16.2998
|
||||
c-5.59961 -3.09961 -12 1.7002 -11 7.90039l6 34.8994l-25.3994 24.6006c-4.60059 4.59961 -1.90039 12.2998 4.2998 13.1992l34.8994 5l15.5 31.6006c2.90039 5.7998 11 5.7998 13.9004 0l15.5 -31.6006z" />
|
||||
<glyph glyph-name="grin-tears" unicode="" horiz-adv-x="640"
|
||||
d="M117.1 191.9c6.30078 0.899414 11.7002 -4.5 10.9004 -10.9004c-3.7002 -25.7998 -13.7002 -84 -30.5996 -100.9c-22 -21.8994 -57.9004 -21.5 -80.3008 0.900391c-22.3994 22.4004 -22.7998 58.4004 -0.899414 80.2998c16.8994 16.9004 75.0996 26.9004 100.899 30.6006
|
||||
zM623.8 161.3c21.9004 -21.8994 21.5 -57.8994 -0.799805 -80.2002c-22.4004 -22.3994 -58.4004 -22.7998 -80.2998 -0.899414c-16.9004 16.8994 -26.9004 75.0996 -30.6006 100.899c-0.899414 6.30078 4.5 11.7002 10.8008 10.8008
|
||||
c25.7998 -3.7002 84 -13.7002 100.899 -30.6006zM497.2 99.5996c12.3994 -37.2998 25.0996 -43.7998 28.2998 -46.5c-44.5996 -65.7998 -120 -109.1 -205.5 -109.1s-160.9 43.2998 -205.5 109.1c3.09961 2.60059 15.7998 9.10059 28.2998 46.5
|
||||
c33.4004 -63.8994 100.3 -107.6 177.2 -107.6s143.8 43.7002 177.2 107.6zM122.7 223.5c-2.40039 0.299805 -5 2.5 -49.5 -6.90039c12.3994 125.4 118.1 223.4 246.8 223.4s234.4 -98 246.8 -223.5c-44.2998 9.40039 -47.3994 7.2002 -49.5 7
|
||||
c-15.2002 95.2998 -97.7998 168.5 -197.3 168.5s-182.1 -73.2002 -197.3 -168.5zM320 48c-51.9004 0 -115.3 32.9004 -123.3 80c-1.7002 10 7.89941 18.4004 17.7002 15.2998c26 -8.2998 64.3994 -13.0996 105.6 -13.0996s79.7002 4.7998 105.6 13.0996
|
||||
c10 3.2002 19.4004 -5.39941 17.7002 -15.2998c-8 -47.0996 -71.3994 -80 -123.3 -80zM450.3 216.3c-3.09961 -0.899414 -7.2002 0.100586 -9.2998 3.7002l-9.5 17c-7.7002 13.7002 -19.2002 21.5996 -31.5 21.5996s-23.7998 -7.89941 -31.5 -21.5996l-9.5 -17
|
||||
c-1.90039 -3.2002 -5.7998 -4.7998 -9.2998 -3.7002c-3.60059 1.10059 -6 4.60059 -5.7002 8.2998c3.2998 42.1006 32.2002 71.4004 56 71.4004s52.7002 -29.2998 56 -71.4004c0.299805 -3.7998 -2.09961 -7.19922 -5.7002 -8.2998zM240 258.6
|
||||
c-12.2998 0 -23.7998 -7.7998 -31.5 -21.5996l-9.5 -17c-1.90039 -3.2002 -5.7998 -4.7998 -9.2998 -3.7002c-3.60059 1.10059 -6 4.60059 -5.7002 8.2998c3.2998 42.1006 32.2002 71.4004 56 71.4004s52.7002 -29.2998 56 -71.4004
|
||||
c0.299805 -3.7998 -2.09961 -7.19922 -5.7002 -8.2998c-3.09961 -1 -7.2002 0 -9.2998 3.7002l-9.5 17c-7.7002 13.7002 -19.2002 21.5996 -31.5 21.5996z" />
|
||||
<glyph glyph-name="grin-tongue" unicode="" horiz-adv-x="496"
|
||||
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM312 40h0.0996094v43.7998l-17.6992 8.7998c-15.1006 7.60059 -31.5 -1.69922 -34.9004 -16.5l-2.7998 -12.0996c-2.10059 -9.2002 -15.2002 -9.2002 -17.2998 0
|
||||
l-2.80078 12.0996c-3.39941 14.8008 -19.8994 24 -34.8994 16.5l-17.7002 -8.7998v-42.7998c0 -35.2002 28 -64.5 63.0996 -65c35.8008 -0.5 64.9004 28.4004 64.9004 64zM340.2 14.7002c64 33.3994 107.8 100.3 107.8 177.3c0 110.3 -89.7002 200 -200 200
|
||||
s-200 -89.7002 -200 -200c0 -77 43.7998 -143.9 107.8 -177.3c-2.2002 8.09961 -3.7998 16.5 -3.7998 25.2998v43.5c-14.2002 12.4004 -24.4004 27.5 -27.2998 44.5c-1.7002 10 7.7998 18.4004 17.7002 15.2998c26 -8.2998 64.3994 -13.0996 105.6 -13.0996
|
||||
s79.7002 4.7998 105.6 13.0996c10 3.2002 19.4004 -5.39941 17.7002 -15.2998c-2.89941 -17 -13.0996 -32.0996 -27.2998 -44.5v-43.5c0 -8.7998 -1.59961 -17.2002 -3.7998 -25.2998zM168 272c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32s-32 14.2998 -32 32
|
||||
s14.2998 32 32 32zM328 272c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32s-32 14.2998 -32 32s14.2998 32 32 32z" />
|
||||
<glyph glyph-name="grin-tongue-squint" unicode="" horiz-adv-x="496"
|
||||
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM312 40h0.0996094v43.7998l-17.6992 8.7998c-15.1006 7.60059 -31.5 -1.69922 -34.9004 -16.5l-2.7998 -12.0996c-2.10059 -9.2002 -15.2002 -9.2002 -17.2998 0
|
||||
l-2.80078 12.0996c-3.39941 14.8008 -19.8994 24 -34.8994 16.5l-17.7002 -8.7998v-42.7998c0 -35.2002 28 -64.5 63.0996 -65c35.8008 -0.5 64.9004 28.4004 64.9004 64zM340.2 14.7002c64 33.3994 107.8 100.3 107.8 177.3c0 110.3 -89.7002 200 -200 200
|
||||
s-200 -89.7002 -200 -200c0 -77 43.7998 -143.9 107.8 -177.3c-2.2002 8.09961 -3.7998 16.5 -3.7998 25.2998v43.5c-14.2002 12.4004 -24.4004 27.5 -27.2998 44.5c-1.7002 10 7.7998 18.4004 17.7002 15.2998c26 -8.2998 64.3994 -13.0996 105.6 -13.0996
|
||||
s79.7002 4.7998 105.6 13.0996c10 3.2002 19.4004 -5.39941 17.7002 -15.2998c-2.89941 -17 -13.0996 -32.0996 -27.2998 -44.5v-43.5c0 -8.7998 -1.59961 -17.2002 -3.7998 -25.2998zM377.1 295.8c3.80078 -4.39941 3.90039 -11 0.100586 -15.5l-33.6006 -40.2998
|
||||
l33.6006 -40.2998c3.7002 -4.5 3.7002 -11 -0.100586 -15.5c-3.59961 -4.2002 -9.89941 -5.7002 -15.2998 -2.5l-80 48c-3.59961 2.2002 -5.7998 6.09961 -5.7998 10.2998s2.2002 8.09961 5.7998 10.2998l80 48c5 3 11.5 1.90039 15.2998 -2.5zM214.2 250.3
|
||||
c3.59961 -2.2002 5.7998 -6.09961 5.7998 -10.2998s-2.2002 -8.09961 -5.7998 -10.2998l-80 -48c-5.40039 -3.2002 -11.7002 -1.7002 -15.2998 2.5c-3.80078 4.5 -3.90039 11 -0.100586 15.5l33.6006 40.2998l-33.6006 40.2998c-3.7002 4.5 -3.7002 11 0.100586 15.5
|
||||
c3.89941 4.5 10.2998 5.5 15.2998 2.5z" />
|
||||
<glyph glyph-name="grin-tongue-wink" unicode="" horiz-adv-x="496"
|
||||
d="M152 268c25.7002 0 55.9004 -16.9004 59.7998 -42.0996c0.799805 -5 -1.7002 -10 -6.09961 -12.4004c-5.7002 -3.09961 -11.2002 -0.599609 -13.7002 1.59961l-9.5 8.5c-14.7998 13.2002 -46.2002 13.2002 -61 0l-9.5 -8.5
|
||||
c-3.7998 -3.39941 -9.2998 -4 -13.7002 -1.59961c-4.39941 2.40039 -6.89941 7.40039 -6.09961 12.4004c3.89941 25.1992 34.0996 42.0996 59.7998 42.0996zM328 320c44.2002 0 80 -35.7998 80 -80s-35.7998 -80 -80 -80s-80 35.7998 -80 80s35.7998 80 80 80zM328 192
|
||||
c26.5 0 48 21.5 48 48s-21.5 48 -48 48s-48 -21.5 -48 -48s21.5 -48 48 -48zM328 264c13.2998 0 24 -10.7002 24 -24s-10.7002 -24 -24 -24s-24 10.7002 -24 24s10.7002 24 24 24zM248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248z
|
||||
M312 40h0.0996094v43.7998l-17.6992 8.7998c-15.1006 7.60059 -31.5 -1.69922 -34.9004 -16.5l-2.7998 -12.0996c-2.10059 -9.2002 -15.2002 -9.2002 -17.2998 0l-2.80078 12.0996c-3.39941 14.8008 -19.8994 24 -34.8994 16.5l-17.7002 -8.7998v-42.7998
|
||||
c0 -35.2002 28 -64.5 63.0996 -65c35.8008 -0.5 64.9004 28.4004 64.9004 64zM340.2 14.7002c64 33.3994 107.8 100.3 107.8 177.3c0 110.3 -89.7002 200 -200 200s-200 -89.7002 -200 -200c0 -77 43.7998 -143.9 107.8 -177.3
|
||||
c-2.2002 8.09961 -3.7998 16.5 -3.7998 25.2998v43.5c-14.2002 12.4004 -24.4004 27.5 -27.2998 44.5c-1.7002 10 7.7998 18.4004 17.7002 15.2998c26 -8.2998 64.3994 -13.0996 105.6 -13.0996s79.7002 4.7998 105.6 13.0996c10 3.2002 19.4004 -5.39941 17.7002 -15.2998
|
||||
c-2.89941 -17 -13.0996 -32.0996 -27.2998 -44.5v-43.5c0 -8.7998 -1.59961 -17.2002 -3.7998 -25.2998z" />
|
||||
<glyph glyph-name="grin-wink" unicode="" horiz-adv-x="496"
|
||||
d="M328 268c25.6904 0 55.8799 -16.9199 59.8701 -42.1201c1.72949 -11.0898 -11.3506 -18.2695 -19.8301 -10.8398l-9.5498 8.47949c-14.8105 13.1904 -46.1602 13.1904 -60.9707 0l-9.5498 -8.47949c-8.33008 -7.40039 -21.5801 -0.379883 -19.8301 10.8398
|
||||
c3.98047 25.2002 34.1699 42.1201 59.8604 42.1201zM168 208c-17.6699 0 -32 14.3301 -32 32s14.3301 32 32 32s32 -14.3301 32 -32s-14.3301 -32 -32 -32zM353.55 143.36c10.04 3.13965 19.3906 -5.4502 17.71 -15.3408
|
||||
c-7.92969 -47.1494 -71.3193 -80.0195 -123.26 -80.0195s-115.33 32.8701 -123.26 80.0195c-1.69043 9.9707 7.76953 18.4707 17.71 15.3408c25.9297 -8.31055 64.3994 -13.0605 105.55 -13.0605s79.6201 4.75977 105.55 13.0605zM248 440c136.97 0 248 -111.03 248 -248
|
||||
s-111.03 -248 -248 -248s-248 111.03 -248 248s111.03 248 248 248zM248 -8c110.28 0 200 89.7197 200 200s-89.7197 200 -200 200s-200 -89.7197 -200 -200s89.7197 -200 200 -200z" />
|
||||
<glyph glyph-name="kiss" unicode="" horiz-adv-x="496"
|
||||
d="M168 272c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32s-32 14.2998 -32 32s14.2998 32 32 32zM304 140c0 -13 -13.4004 -27.2998 -35.0996 -36.4004c21.7998 -8.69922 35.1992 -23 35.1992 -36c0 -19.1992 -28.6992 -41.5 -71.5 -44h-0.5
|
||||
c-3.69922 0 -7 2.60059 -7.7998 6.2002c-0.899414 3.7998 1.10059 7.7002 4.7002 9.2002l17 7.2002c12.9004 5.5 20.7002 13.5 20.7002 21.5s-7.7998 16 -20.7998 21.5l-16.9004 7.2002c-6 2.59961 -5.7002 12.3994 0 14.7998l17 7.2002
|
||||
c12.9004 5.5 20.7002 13.5 20.7002 21.5s-7.7998 16 -20.7998 21.5l-16.9004 7.19922c-3.59961 1.5 -5.59961 5.40039 -4.7002 9.2002c0.799805 3.7998 4.40039 6.60059 8.2002 6.2002c42.7002 -2.5 71.5 -24.7998 71.5 -44zM248 440c137 0 248 -111 248 -248
|
||||
s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM328 272c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32s-32 14.2998 -32 32s14.2998 32 32 32z
|
||||
" />
|
||||
<glyph glyph-name="kiss-beam" unicode="" horiz-adv-x="496"
|
||||
d="M168 296c23.7998 0 52.7002 -29.2998 55.7998 -71.4004c0.299805 -3.7998 -2 -7.19922 -5.59961 -8.2998c-3.10059 -1 -7.2002 0 -9.2998 3.7002l-9.5 17c-7.7002 13.7002 -19.2002 21.5996 -31.5 21.5996c-12.3008 0 -23.8008 -7.89941 -31.5 -21.5996l-9.5 -17
|
||||
c-1.80078 -3.2002 -5.80078 -4.7002 -9.30078 -3.7002c-3.59961 1.10059 -5.89941 4.60059 -5.59961 8.2998c3.2998 42.1006 32.2002 71.4004 56 71.4004zM248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8
|
||||
c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM304 140c0 -13 -13.4004 -27.2998 -35.0996 -36.4004c21.7998 -8.69922 35.1992 -23 35.1992 -36c0 -19.1992 -28.6992 -41.5 -71.5 -44h-0.5
|
||||
c-3.69922 0 -7 2.60059 -7.7998 6.2002c-0.899414 3.7998 1.10059 7.7002 4.7002 9.2002l17 7.2002c12.9004 5.5 20.7002 13.5 20.7002 21.5s-7.7998 16 -20.7998 21.5l-16.9004 7.2002c-6 2.59961 -5.7002 12.3994 0 14.7998l17 7.2002
|
||||
c12.9004 5.5 20.7002 13.5 20.7002 21.5s-7.7998 16 -20.7998 21.5l-16.9004 7.19922c-3.59961 1.5 -5.59961 5.40039 -4.7002 9.2002c0.799805 3.7998 4.40039 6.60059 8.2002 6.2002c42.7002 -2.5 71.5 -24.7998 71.5 -44zM328 296
|
||||
c23.7998 0 52.7002 -29.2998 55.7998 -71.4004c0.299805 -3.7998 -2 -7.19922 -5.59961 -8.2998c-3.10059 -1 -7.2002 0 -9.2998 3.7002l-9.5 17c-7.7002 13.7002 -19.2002 21.5996 -31.5 21.5996c-12.3008 0 -23.8008 -7.89941 -31.5 -21.5996l-9.5 -17
|
||||
c-1.80078 -3.2002 -5.80078 -4.7002 -9.30078 -3.7002c-3.59961 1.10059 -5.89941 4.60059 -5.59961 8.2998c3.2998 42.1006 32.2002 71.4004 56 71.4004z" />
|
||||
<glyph glyph-name="kiss-wink-heart" unicode="" horiz-adv-x="504"
|
||||
d="M304 139.5c0 -13 -13.4004 -27.2998 -35.0996 -36.4004c21.7998 -8.69922 35.1992 -23 35.1992 -36c0 -19.1992 -28.6992 -41.5 -71.5 -44h-0.5c-3.69922 0 -7 2.60059 -7.7998 6.2002c-0.899414 3.7998 1.10059 7.7002 4.7002 9.2002l17 7.2002
|
||||
c12.9004 5.5 20.7002 13.5 20.7002 21.5s-7.7998 16 -20.7998 21.5l-16.9004 7.2002c-6 2.59961 -5.7002 12.3994 0 14.7998l17 7.2002c12.9004 5.5 20.7002 13.5 20.7002 21.5s-7.7998 16 -20.7998 21.5l-16.9004 7.19922c-3.59961 1.5 -5.59961 5.40039 -4.7002 9.2002
|
||||
c0.799805 3.7998 4.40039 6.60059 8.2002 6.2002c42.7002 -2.5 71.5 -24.7998 71.5 -44zM374.5 223c-14.7998 13.2002 -46.2002 13.2002 -61 0l-9.5 -8.5c-2.5 -2.2998 -7.90039 -4.7002 -13.7002 -1.59961c-4.39941 2.39941 -6.89941 7.39941 -6.09961 12.3994
|
||||
c3.89941 25.2002 34.2002 42.1006 59.7998 42.1006s55.7998 -16.9004 59.7998 -42.1006c0.799805 -5 -1.7002 -10 -6.09961 -12.3994c-4.40039 -2.40039 -9.90039 -1.7002 -13.7002 1.59961zM136 239.5c0 17.7002 14.2998 32 32 32s32 -14.2998 32 -32s-14.2998 -32 -32 -32
|
||||
s-32 14.2998 -32 32zM501.1 45.5c9.2002 -23.9004 -4.39941 -49.4004 -28.5 -55.7002l-83 -21.5c-5.39941 -1.39941 -10.8994 1.7998 -12.3994 7.10059l-22.9004 82.5996c-6.59961 24 8.7998 48.5996 34 52.5996c22 3.5 43.1006 -11.5996 49 -33l2.2998 -8.39941
|
||||
l8.40039 2.2002c21.5996 5.59961 45.0996 -5.10059 53.0996 -25.9004zM334 11.7002c17.7002 -64 10.9004 -39.5 13.4004 -46.7998c-30.5 -13.4004 -64 -20.9004 -99.4004 -20.9004c-137 0 -248 111 -248 248s111 248 248 248s248 -111 247.9 -248
|
||||
c0 -31.7998 -6.2002 -62.0996 -17.1006 -90c-6 1.5 -12.2002 2.7998 -18.5996 2.90039c-5.60059 9.69922 -13.6006 17.5 -22.6006 23.8994c6.7002 19.9004 10.4004 41.1006 10.4004 63.2002c0 110.3 -89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200
|
||||
c30.7998 0 59.9004 7.2002 86 19.7002z" />
|
||||
<glyph glyph-name="laugh" unicode="" horiz-adv-x="496"
|
||||
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM389.4 50.5996c37.7998 37.8008 58.5996 88 58.5996 141.4s-20.7998 103.6 -58.5996 141.4c-37.8008 37.7998 -88 58.5996 -141.4 58.5996s-103.6 -20.7998 -141.4 -58.5996
|
||||
c-37.7998 -37.8008 -58.5996 -88 -58.5996 -141.4s20.7998 -103.6 58.5996 -141.4c37.8008 -37.7998 88 -58.5996 141.4 -58.5996s103.6 20.7998 141.4 58.5996zM328 224c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32s32 -14.2998 32 -32s-14.2998 -32 -32 -32zM168 224
|
||||
c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32s32 -14.2998 32 -32s-14.2998 -32 -32 -32zM362.4 160c8.19922 0 14.5 -7 13.5 -15c-7.5 -59.2002 -58.9004 -105 -121.101 -105h-13.5996c-62.2002 0 -113.601 45.7998 -121.101 105c-1 8 5.30078 15 13.5 15h228.801z" />
|
||||
<glyph glyph-name="laugh-beam" unicode="" horiz-adv-x="496"
|
||||
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM389.4 50.5996c37.7998 37.8008 58.5996 88 58.5996 141.4s-20.7998 103.6 -58.5996 141.4c-37.8008 37.7998 -88 58.5996 -141.4 58.5996s-103.6 -20.7998 -141.4 -58.5996
|
||||
c-37.7998 -37.8008 -58.5996 -88 -58.5996 -141.4s20.7998 -103.6 58.5996 -141.4c37.8008 -37.7998 88 -58.5996 141.4 -58.5996s103.6 20.7998 141.4 58.5996zM328 296c23.7998 0 52.7002 -29.2998 55.7998 -71.4004c0.700195 -8.5 -10.7998 -11.8994 -14.8994 -4.5
|
||||
l-9.5 17c-7.7002 13.7002 -19.2002 21.6006 -31.5 21.6006c-12.3008 0 -23.8008 -7.90039 -31.5 -21.6006l-9.5 -17c-4.10059 -7.39941 -15.6006 -4.09961 -14.9004 4.5c3.2998 42.1006 32.2002 71.4004 56 71.4004zM127 220.1c-4.2002 -7.39941 -15.7002 -4 -15.0996 4.5
|
||||
c3.2998 42.1006 32.1992 71.4004 56 71.4004c23.7998 0 52.6992 -29.2998 56 -71.4004c0.699219 -8.5 -10.8008 -11.8994 -14.9004 -4.5l-9.5 17c-7.7002 13.7002 -19.2002 21.6006 -31.5 21.6006s-23.7998 -7.90039 -31.5 -21.6006zM362.4 160c8.19922 0 14.5 -7 13.5 -15
|
||||
c-7.5 -59.2002 -58.9004 -105 -121.101 -105h-13.5996c-62.2002 0 -113.601 45.7998 -121.101 105c-1 8 5.30078 15 13.5 15h228.801z" />
|
||||
<glyph glyph-name="laugh-squint" unicode="" horiz-adv-x="496"
|
||||
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM389.4 50.5996c37.7998 37.8008 58.5996 88 58.5996 141.4s-20.7998 103.6 -58.5996 141.4c-37.8008 37.7998 -88 58.5996 -141.4 58.5996s-103.6 -20.7998 -141.4 -58.5996
|
||||
c-37.7998 -37.8008 -58.5996 -88 -58.5996 -141.4s20.7998 -103.6 58.5996 -141.4c37.8008 -37.7998 88 -58.5996 141.4 -58.5996s103.6 20.7998 141.4 58.5996zM343.6 252l33.6006 -40.2998c8.59961 -10.4004 -3.90039 -24.7998 -15.4004 -18l-80 48
|
||||
c-7.7998 4.7002 -7.7998 15.8994 0 20.5996l80 48c11.6006 6.7998 24 -7.7002 15.4004 -18zM134.2 193.7c-11.6006 -6.7998 -24.1006 7.59961 -15.4004 18l33.6006 40.2998l-33.6006 40.2998c-8.59961 10.2998 3.7998 24.9004 15.4004 18l80 -48
|
||||
c7.7998 -4.7002 7.7998 -15.8994 0 -20.5996zM362.4 160c8.19922 0 14.5 -7 13.5 -15c-7.5 -59.2002 -58.9004 -105 -121.101 -105h-13.5996c-62.2002 0 -113.601 45.7998 -121.101 105c-1 8 5.30078 15 13.5 15h228.801z" />
|
||||
<glyph glyph-name="laugh-wink" unicode="" horiz-adv-x="496"
|
||||
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM389.4 50.5996c37.7998 37.8008 58.5996 88 58.5996 141.4s-20.7998 103.6 -58.5996 141.4c-37.8008 37.7998 -88 58.5996 -141.4 58.5996s-103.6 -20.7998 -141.4 -58.5996
|
||||
c-37.7998 -37.8008 -58.5996 -88 -58.5996 -141.4s20.7998 -103.6 58.5996 -141.4c37.8008 -37.7998 88 -58.5996 141.4 -58.5996s103.6 20.7998 141.4 58.5996zM328 284c25.7002 0 55.9004 -16.9004 59.7002 -42.0996c1.7998 -11.1006 -11.2998 -18.2002 -19.7998 -10.8008
|
||||
l-9.5 8.5c-14.8008 13.2002 -46.2002 13.2002 -61 0l-9.5 -8.5c-8.30078 -7.39941 -21.5 -0.399414 -19.8008 10.8008c4 25.1992 34.2002 42.0996 59.9004 42.0996zM168 224c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32s32 -14.2998 32 -32s-14.2998 -32 -32 -32z
|
||||
M362.4 160c8.19922 0 14.5 -7 13.5 -15c-7.5 -59.2002 -58.9004 -105 -121.101 -105h-13.5996c-62.2002 0 -113.601 45.7998 -121.101 105c-1 8 5.30078 15 13.5 15h228.801z" />
|
||||
<glyph glyph-name="meh-blank" unicode="" horiz-adv-x="496"
|
||||
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM168 272c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32
|
||||
s-32 14.2998 -32 32s14.2998 32 32 32zM328 272c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32s-32 14.2998 -32 32s14.2998 32 32 32z" />
|
||||
<glyph glyph-name="meh-rolling-eyes" unicode="" horiz-adv-x="496"
|
||||
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM336 296c39.7998 0 72 -32.2002 72 -72s-32.2002 -72 -72 -72
|
||||
s-72 32.2002 -72 72s32.2002 72 72 72zM336 184c22.0996 0 40 17.9004 40 40c0 13.5996 -7.2998 25.0996 -17.7002 32.2998c1 -2.59961 1.7002 -5.39941 1.7002 -8.2998c0 -13.2998 -10.7002 -24 -24 -24s-24 10.7002 -24 24c0 3 0.700195 5.7002 1.7002 8.2998
|
||||
c-10.4004 -7.2002 -17.7002 -18.7002 -17.7002 -32.2998c0 -22.0996 17.9004 -40 40 -40zM232 224c0 -39.7998 -32.2002 -72 -72 -72s-72 32.2002 -72 72s32.2002 72 72 72s72 -32.2002 72 -72zM120 224c0 -22.0996 17.9004 -40 40 -40s40 17.9004 40 40
|
||||
c0 13.5996 -7.2998 25.0996 -17.7002 32.2998c1 -2.59961 1.7002 -5.39941 1.7002 -8.2998c0 -13.2998 -10.7002 -24 -24 -24s-24 10.7002 -24 24c0 3 0.700195 5.7002 1.7002 8.2998c-10.4004 -7.2002 -17.7002 -18.7002 -17.7002 -32.2998zM312 96
|
||||
c13.2002 0 24 -10.7998 24 -24s-10.7998 -24 -24 -24h-128c-13.2002 0 -24 10.7998 -24 24s10.7998 24 24 24h128z" />
|
||||
<glyph glyph-name="sad-cry" unicode="" horiz-adv-x="496"
|
||||
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM392 53.5996c34.5996 35.9004 56 84.7002 56 138.4c0 110.3 -89.7002 200 -200 200s-200 -89.7002 -200 -200c0 -53.7002 21.4004 -102.4 56 -138.4v114.4
|
||||
c0 13.2002 10.7998 24 24 24s24 -10.7998 24 -24v-151.4c28.5 -15.5996 61.2002 -24.5996 96 -24.5996s67.5 9 96 24.5996v151.4c0 13.2002 10.7998 24 24 24s24 -10.7998 24 -24v-114.4zM205.8 213.5c-5.7998 -3.2002 -11.2002 -0.700195 -13.7002 1.59961l-9.5 8.5
|
||||
c-14.7998 13.2002 -46.1992 13.2002 -61 0l-9.5 -8.5c-3.7998 -3.39941 -9.2998 -4 -13.6992 -1.59961c-4.40039 2.40039 -6.90039 7.40039 -6.10059 12.4004c3.90039 25.1992 34.2002 42.0996 59.7998 42.0996c25.6006 0 55.8008 -16.9004 59.8008 -42.0996
|
||||
c0.799805 -5 -1.7002 -10 -6.10059 -12.4004zM344 268c25.7002 0 55.9004 -16.9004 59.7998 -42.0996c0.799805 -5 -1.7002 -10 -6.09961 -12.4004c-5.7002 -3.09961 -11.2002 -0.599609 -13.7002 1.59961l-9.5 8.5c-14.7998 13.2002 -46.2002 13.2002 -61 0l-9.5 -8.5
|
||||
c-3.7998 -3.39941 -9.2002 -4 -13.7002 -1.59961c-4.39941 2.40039 -6.89941 7.40039 -6.09961 12.4004c3.89941 25.1992 34.0996 42.0996 59.7998 42.0996zM248 176c30.9004 0 56 -28.7002 56 -64s-25.0996 -64 -56 -64s-56 28.7002 -56 64s25.0996 64 56 64z" />
|
||||
<glyph glyph-name="sad-tear" unicode="" horiz-adv-x="496"
|
||||
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM256 144c38.0996 0 74 -16.7998 98.5 -46.0996
|
||||
c8.5 -10.2002 7.09961 -25.3008 -3.09961 -33.8008c-10.6006 -8.7998 -25.7002 -6.69922 -33.8008 3.10059c-15.2998 18.2998 -37.7998 28.7998 -61.5996 28.7998c-13.2002 0 -24 10.7998 -24 24s10.7998 24 24 24zM168 208c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32
|
||||
s32 -14.2998 32 -32s-14.2998 -32 -32 -32zM328 272c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32s-32 14.2998 -32 32s14.2998 32 32 32zM162.4 173.2c2.7998 3.7002 8.39941 3.7002 11.1992 0c11.4004 -15.2998 36.4004 -50.6006 36.4004 -68.1006
|
||||
c0 -22.6992 -18.7998 -41.0996 -42 -41.0996s-42 18.4004 -42 41.0996c0 17.5 25 52.8008 36.4004 68.1006z" />
|
||||
<glyph glyph-name="smile-beam" unicode="" horiz-adv-x="496"
|
||||
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM332 135.4c8.5 10.1992 23.5996 11.5 33.7998 3.09961
|
||||
c10.2002 -8.5 11.6006 -23.5996 3.10059 -33.7998c-30 -36 -74.1006 -56.6006 -120.9 -56.6006s-90.9004 20.6006 -120.9 56.6006c-8.39941 10.2002 -7.09961 25.2998 3.10059 33.7998c10.2002 8.40039 25.2998 7.09961 33.7998 -3.09961
|
||||
c20.7998 -25.1006 51.5 -39.4004 84 -39.4004s63.2002 14.4004 84 39.4004zM136.5 237l-9.5 -17c-1.90039 -3.2002 -5.90039 -4.7998 -9.2998 -3.7002c-3.60059 1.10059 -6 4.60059 -5.7002 8.2998c3.2998 42.1006 32.2002 71.4004 56 71.4004s52.7002 -29.2998 56 -71.4004
|
||||
c0.299805 -3.7998 -2.09961 -7.19922 -5.7002 -8.2998c-3.09961 -1 -7.2002 0 -9.2998 3.7002l-9.5 17c-7.7002 13.7002 -19.2002 21.5996 -31.5 21.5996s-23.7998 -7.89941 -31.5 -21.5996zM328 296c23.7998 0 52.7002 -29.2998 56 -71.4004
|
||||
c0.299805 -3.7998 -2.09961 -7.19922 -5.7002 -8.2998c-3.09961 -1 -7.2002 0 -9.2998 3.7002l-9.5 17c-7.7002 13.7002 -19.2002 21.5996 -31.5 21.5996s-23.7998 -7.89941 -31.5 -21.5996l-9.5 -17c-1.90039 -3.2002 -5.7998 -4.7998 -9.2998 -3.7002
|
||||
c-3.60059 1.10059 -6 4.60059 -5.7002 8.2998c3.2998 42.1006 32.2002 71.4004 56 71.4004z" />
|
||||
<glyph glyph-name="surprise" unicode="" horiz-adv-x="496"
|
||||
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM248 168c35.2998 0 64 -28.7002 64 -64s-28.7002 -64 -64 -64
|
||||
s-64 28.7002 -64 64s28.7002 64 64 64zM200 240c0 -17.7002 -14.2998 -32 -32 -32s-32 14.2998 -32 32s14.2998 32 32 32s32 -14.2998 32 -32zM328 272c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32s-32 14.2998 -32 32s14.2998 32 32 32z" />
|
||||
<glyph glyph-name="tired" unicode="" horiz-adv-x="496"
|
||||
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM377.1 295.8c3.80078 -4.39941 3.90039 -11 0.100586 -15.5
|
||||
l-33.6006 -40.2998l33.6006 -40.2998c3.7998 -4.5 3.7002 -11 -0.100586 -15.5c-3.5 -4.10059 -9.89941 -5.7002 -15.2998 -2.5l-80 48c-3.59961 2.2002 -5.7998 6.09961 -5.7998 10.2998s2.2002 8.09961 5.7998 10.2998l80 48c5 2.90039 11.5 1.90039 15.2998 -2.5z
|
||||
M220 240c0 -4.2002 -2.2002 -8.09961 -5.7998 -10.2998l-80 -48c-5.40039 -3.2002 -11.7998 -1.60059 -15.2998 2.5c-3.80078 4.5 -3.90039 11 -0.100586 15.5l33.6006 40.2998l-33.6006 40.2998c-3.7998 4.5 -3.7002 11 0.100586 15.5
|
||||
c3.7998 4.40039 10.2998 5.5 15.2998 2.5l80 -48c3.59961 -2.2002 5.7998 -6.09961 5.7998 -10.2998zM248 176c45.4004 0 100.9 -38.2998 107.8 -93.2998c1.5 -11.9004 -7 -21.6006 -15.5 -17.9004c-22.7002 9.7002 -56.2998 15.2002 -92.2998 15.2002
|
||||
s-69.5996 -5.5 -92.2998 -15.2002c-8.60059 -3.7002 -17 6.10059 -15.5 17.9004c6.89941 55 62.3994 93.2998 107.8 93.2998z" />
|
||||
</font>
|
||||
</defs></svg>
|
||||
|
After Width: | Height: | Size: 141 KiB |