955 lines
32 KiB
PHP
955 lines
32 KiB
PHP
<?php
|
|
|
|
$config = require '../config.php';
|
|
|
|
function get_mysqli(): MySQLi
|
|
{
|
|
global $config;
|
|
static $handle;
|
|
if (!isset($handle)) {
|
|
$handle = new MySQLi(
|
|
hostname: $config['db_host'],
|
|
username: $config['db_user'],
|
|
password: $config['db_pass'],
|
|
database: $config['db_database'],
|
|
);
|
|
// make sure that the timezone is set to UTC!!!
|
|
$handle->query("SET time_zone = '+00:00'");
|
|
}
|
|
return $handle;
|
|
}
|
|
|
|
function flash_message(string $msg, string $type = 'info', bool $unsafe = false): void
|
|
{
|
|
if (session_status() === PHP_SESSION_NONE)
|
|
session_start();
|
|
|
|
$types = [
|
|
"info",
|
|
"success",
|
|
"danger",
|
|
"warning"
|
|
];
|
|
if (!in_array($type, $types)) {
|
|
throw new InvalidArgumentException("Flash type: \"$type\" does not exist");
|
|
}
|
|
$key = 'flash_messages';
|
|
if (!isset($_SESSION[$key]))
|
|
{
|
|
$_SESSION[$key] = [];
|
|
}
|
|
if (count($_SESSION[$key]) >= 100)
|
|
{
|
|
$_SESSION[$key] = [];
|
|
throw new Exception('Too many flashed messages!');
|
|
}
|
|
$_SESSION[$key][] = [
|
|
"message" => ($unsafe) ? $msg : htmlspecialchars($msg),
|
|
"type" => $type
|
|
];
|
|
}
|
|
|
|
function get_flash_messages(): ?array
|
|
{
|
|
if (session_status() === PHP_SESSION_NONE)
|
|
session_start();
|
|
|
|
$key = 'flash_messages';
|
|
if (empty($_SESSION[$key])) {
|
|
return null;
|
|
}
|
|
$msgs = $_SESSION[$key];
|
|
$_SESSION[$key] = [];
|
|
return $msgs;
|
|
}
|
|
|
|
function page_header(string $title, array $toolbar_links = [])
|
|
{
|
|
$ref_uuid = filter_input(INPUT_GET, 'ref_uuid');
|
|
$prefer_ref_uuid = !empty($ref_uuid);
|
|
if ($prefer_ref_uuid) $ref_uuid = htmlspecialchars($ref_uuid);
|
|
|
|
$host = strtolower(filter_input(INPUT_GET, 'host'));
|
|
if (!empty($host) && !is_valid_host($host)) {
|
|
$host = NULL;
|
|
}
|
|
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title><?=$title?></title>
|
|
<link rel="stylesheet" href="static/css/style.css">
|
|
<link rel="icon" type="image/svg+xml" href="static/img/logo.svg">
|
|
</head>
|
|
<body>
|
|
<header>
|
|
<nav>
|
|
<a href="?p=default<?=($prefer_ref_uuid ? '&ref_uuid=' . $ref_uuid : '') . (!empty($host) ? '&host=' . $host : '')?>">Pinglerr</a>
|
|
</nav>
|
|
</header>
|
|
|
|
<?php if (!empty($toolbar_links)): ?>
|
|
<div class="toolbar">
|
|
<nav>
|
|
Handling:
|
|
<?php foreach ($toolbar_links as $link): ?>
|
|
<span>[ <a
|
|
<?php if(isset($link['type']) && $link['type'] === 'danger'): ?>
|
|
class="link-btn-danger"
|
|
<?php else: ?>
|
|
class="link-btn-normal"
|
|
<?php endif; ?>
|
|
href="<?=$link['href']?>"><?=$link['name']?></a> ]</span>
|
|
<?php endforeach; ?>
|
|
</nav>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<main>
|
|
|
|
<?php
|
|
$flash_messages = get_flash_messages();
|
|
?>
|
|
<?php if(!empty($flash_messages)): ?>
|
|
<?php foreach ($flash_messages as $message): ?>
|
|
<?php if($message['type'] === 'info'): ?>
|
|
<div class="alert alert-info"><?=$message['message']?></div>
|
|
<?php endif; ?>
|
|
<?php if($message['type'] === 'success'): ?>
|
|
<div class="alert alert-success"><?=$message['message']?></div>
|
|
<?php endif; ?>
|
|
<?php if($message['type'] === 'danger'): ?>
|
|
<div class="alert alert-danger"><?=$message['message']?></div>
|
|
<?php endif; ?>
|
|
<?php if($message['type'] === 'warning'): ?>
|
|
<div class="alert alert-warning"><?=$message['message']?></div>
|
|
<?php endif; ?>
|
|
<?php endforeach ?>
|
|
<hr>
|
|
<?php endif; ?>
|
|
<?php
|
|
}
|
|
|
|
function page_footer()
|
|
{
|
|
?>
|
|
</main>
|
|
<script src="static/js/apexcharts.min.js"></script>
|
|
<script src="static/js/global.js"></script>
|
|
<footer>
|
|
<small>Laget av William for Altidata AS</small>
|
|
</footer>
|
|
</body>
|
|
</html>
|
|
<?php
|
|
}
|
|
|
|
function get_referer(): string
|
|
{
|
|
if (isset($_SERVER['HTTP_REFERER'])) {
|
|
return htmlspecialchars($_SERVER['HTTP_REFERER']);
|
|
}
|
|
return '?p=default';
|
|
}
|
|
|
|
function is_valid_host(string $host): bool
|
|
{
|
|
if (empty($host)) {
|
|
return false;
|
|
}
|
|
if (!filter_var(
|
|
$host, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)
|
|
) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function suicide_user_bad_request(string $errormsg)
|
|
{
|
|
http_response_code(400);
|
|
page_header('Oops, dette var en feil');
|
|
?>
|
|
<h1>Kunne ikke fortsette</h1>
|
|
<p>Feilmelding: <?=htmlspecialchars($errormsg)?></p>
|
|
<a href="<?=get_referer()?>">Klikk her for å gå tilbake</a>
|
|
<?php
|
|
page_footer();
|
|
die();
|
|
}
|
|
|
|
function pinglerr_get_scan(?string $host = null, ?string $ref_uuid = null, ?string $scan_id = null, bool $must_be_active_or_waiting = true): ?array
|
|
{
|
|
if ($host !== null) {
|
|
$sql = "SELECT * FROM pinglerr_scans WHERE host = ? AND ref_uuid IS NULL";
|
|
$param = $host;
|
|
}
|
|
if ($ref_uuid !== null) {
|
|
$sql = "SELECT * FROM pinglerr_scans WHERE ref_uuid = ?";
|
|
$param = $ref_uuid;
|
|
}
|
|
if ($scan_id !== null) {
|
|
$sql = "SELECT * FROM pinglerr_scans WHERE id = ?";
|
|
$param = $scan_id;
|
|
}
|
|
if ($must_be_active_or_waiting) {
|
|
$sql = $sql . " AND status_code IN ('ACTIVE', 'WAITING')";
|
|
}
|
|
$stmt = get_mysqli()->prepare($sql);
|
|
$stmt->bind_param("s", $param);
|
|
$stmt->execute();
|
|
$result = $stmt->get_result();
|
|
$assoc = $result->fetch_assoc();
|
|
return $assoc;
|
|
}
|
|
|
|
function pinglerr_get_scan_history(?string $host = null, ?string $ref_uuid = null, ?int $max_rows = null): ?array
|
|
{
|
|
if ($host !== null) {
|
|
$sql = "SELECT * FROM pinglerr_scans WHERE host = ? AND ref_uuid IS NULL ORDER BY start_date DESC";
|
|
$param = $host;
|
|
}
|
|
if ($ref_uuid !== null) {
|
|
$sql = "SELECT * FROM pinglerr_scans WHERE ref_uuid= ? ORDER BY start_date DESC";
|
|
$param = $ref_uuid;
|
|
}
|
|
if ($max_rows !== null) {
|
|
$sql = $sql . ' LIMIT ' . $max_rows;
|
|
}
|
|
$scans = (function() use ($sql, $param): ?array
|
|
{
|
|
$stmt = get_mysqli()->prepare($sql);
|
|
$stmt->bind_param("s", $param);
|
|
$stmt->execute();
|
|
$result = $stmt->get_result();
|
|
$assoc_array = [];
|
|
while ($row = $result->fetch_assoc()) {
|
|
$assoc_array[] = $row;
|
|
}
|
|
if (empty($assoc_array)) {
|
|
return null;
|
|
}
|
|
return $assoc_array;
|
|
})();
|
|
return $scans;
|
|
}
|
|
|
|
$route['default'] = function()
|
|
{
|
|
$ref_uuid = filter_input(INPUT_GET, 'ref_uuid');
|
|
$prefer_ref_uuid = !empty($ref_uuid);
|
|
if ($prefer_ref_uuid) $ref_uuid = htmlspecialchars($ref_uuid);
|
|
|
|
$host = strtolower(filter_input(INPUT_GET, 'host'));
|
|
|
|
|
|
if (!empty($host) && !is_valid_host($host)) {
|
|
suicide_user_bad_request('Ugyldig vert adresse');
|
|
}
|
|
|
|
if ($prefer_ref_uuid) {
|
|
$scan = pinglerr_get_scan(ref_uuid: $ref_uuid);
|
|
} else {
|
|
$scan = pinglerr_get_scan(host: $host);
|
|
}
|
|
|
|
$function['show_form'] = function() use($ref_uuid, $prefer_ref_uuid, $host) {
|
|
?>
|
|
<h1>Pinglerr</h1>
|
|
<p>Sjekk tilkobling status til IP-adresse eller annen tjeneste</p>
|
|
<form method="POST" action="?p=start_scan">
|
|
<input style="width: 100%; box-sizing: border-box; padding: .5rem;" value="<?=$host?>" autocomplete="off" placeholder="Vertsnavn eller adresse som f.eks nrk.no, 192.168.1.1" type="text" name="host">
|
|
|
|
<?php if($prefer_ref_uuid): ?>
|
|
<br>
|
|
<br>
|
|
<label for="ref_uuid">Referanse</label>
|
|
<input style="width: 100%; box-sizing: border-box; padding: .5rem;" value="<?=$ref_uuid?>" autocomplete="off" placeholder="Referanse" type="text" name="ref_uuid">
|
|
<?php endif; ?>
|
|
|
|
<br>
|
|
<br>
|
|
<label for="time_limit">Hvor lenge skal denne kjøre?</label>
|
|
<select name="time_limit" id="time_limit">
|
|
<option value="600">10 minutter</option>
|
|
<option value="3600">1 time</option>
|
|
<option value="14400">4 timer</option>
|
|
<option value="28800">8 timer</option>
|
|
<option value="43200">12 timer</option>
|
|
<option value="86400">24 timer</option>
|
|
<option value="172800">2 døgn</option>
|
|
<option value="345600">4 døgn</option>
|
|
<option value="604800">1 uke</option>
|
|
</select>
|
|
<br>
|
|
<br>
|
|
<input style="width: 5rem; padding: .5rem;" type="submit" value="Sjekk" class="btn btn-primary btn-lg">
|
|
</form>
|
|
<?php
|
|
};
|
|
|
|
$function['show_scan_history'] = function() use($prefer_ref_uuid, $ref_uuid, $host) {
|
|
$show_full_history = boolval(filter_input(INPUT_GET, 'show_full_history'));
|
|
$max_rows = 10;
|
|
if ($show_full_history) {
|
|
$max_rows = 10000;
|
|
}
|
|
|
|
if ($prefer_ref_uuid) {
|
|
$scans = pinglerr_get_scan_history(ref_uuid: $ref_uuid, max_rows: $max_rows);
|
|
$current_scan = pinglerr_get_scan(ref_uuid: $ref_uuid);
|
|
} else {
|
|
$scans = pinglerr_get_scan_history($host, max_rows: $max_rows);
|
|
$current_scan = pinglerr_get_scan($host);
|
|
}
|
|
if (empty($scans)) {
|
|
return;
|
|
}
|
|
?>
|
|
<h1>Historikk</h1>
|
|
<p>Tidligere skanninger som er gjort på denne verten eller referanse.</p>
|
|
|
|
<table>
|
|
<tr>
|
|
<th>Start Dato</th>
|
|
<th>Handling</th>
|
|
</tr>
|
|
<?php foreach($scans as $scan): ?>
|
|
<tr>
|
|
<td class="dateConverter"><?=$scan['start_date']?></td>
|
|
|
|
<td>[ <a class="link-btn-normal" href="?p=scan_details&scan_id=<?=$scan['id']?><?=($prefer_ref_uuid ? '&ref_uuid=' . $ref_uuid : '&host=' . $host)?>">Detaljer</a> ]</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</table>
|
|
<?php
|
|
};
|
|
|
|
$function['show_live_stats'] = function() use($scan, $ref_uuid, $prefer_ref_uuid)
|
|
{
|
|
?>
|
|
<form>
|
|
<label for="timeRangeSelector">Hent statistikk fra siste:</label>
|
|
<select name="timeRangeSelector" id="timeRangeSelector">
|
|
<option value="900">15 minutter</option>
|
|
<option value="1800">30 minutter</option>
|
|
<option value="3600">1 time</option>
|
|
<option value="14400">4 timer</option>
|
|
<option value="28800">8 timer</option>
|
|
<option value="43200">12 timer</option>
|
|
<option value="86400">24 timer</option>
|
|
<option value="Details">Fullstendig</option>
|
|
</select>
|
|
</form>
|
|
<hr>
|
|
<h1>Sanntid statistikk</h1>
|
|
<div class="sign-container">
|
|
<div class="sign">
|
|
<span class="sign-label" style="">Tilkobling</span><span class="sign-text" id="connection_status">Ukjent</span>
|
|
</div>
|
|
<div class="sign">
|
|
<span class="sign-label">Vert</span><span class="sign-text"><?=$scan['host']?></span>
|
|
</div>
|
|
<?php if($prefer_ref_uuid): ?>
|
|
<div class="sign">
|
|
<span class="sign-label">Referanse</span><span class="sign-text"><?=$scan['ref_uuid']?></span>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<br>
|
|
|
|
<div style="
|
|
display: grid;
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
gap: .5rem;
|
|
">
|
|
<div style="padding: 0.5rem; background: #eee; border: 1px solid #ccc; text-align: center; border-radius: 0.25rem;">
|
|
<div>Ping (siste)</div>
|
|
<div style="font-size: 2rem;"><span id="ping">Vent</span></div>
|
|
</div>
|
|
<div style="padding: 0.5rem; background: #eee; border: 1px solid #ccc; text-align: center; border-radius: 0.25rem;">
|
|
<div style="">Pakke tap</div>
|
|
<div style="font-size: 2rem;"><span id="packet_loss">Vent</span></div>
|
|
</div>
|
|
<div style="padding: 0.5rem; background: #eee; border: 1px solid #ccc; text-align: center; border-radius: 0.25rem;">
|
|
<div style="">Suksess-rate</div>
|
|
<div style="font-size: 2rem;"><span id="uptime">Vent</span></div>
|
|
</div>
|
|
</div>
|
|
|
|
<br>
|
|
|
|
<div style="height: 15rem">
|
|
<div id="liveChart"></div>
|
|
</div>
|
|
|
|
<script src="static/js/live_stats.js"></script>
|
|
<?php
|
|
};
|
|
|
|
if (!empty($scan)) {
|
|
page_header('Pinglerr', toolbar_links: [
|
|
[
|
|
'href' => '?p=stop_scanning&scan_id=' . $scan['id'] . ($prefer_ref_uuid ? '&ref_uuid=' . $ref_uuid : '') . (!empty($host) ? '&host=' . $host : ''),
|
|
'name' => 'Stop skanning',
|
|
'type' => 'danger'
|
|
]
|
|
]);
|
|
} else {
|
|
page_header('Pinglerr');
|
|
}
|
|
?>
|
|
<?php if(!empty($scan)): ?>
|
|
<?=$function['show_live_stats']()?>
|
|
<?php endif;?>
|
|
|
|
<?php if(empty($scan)): ?>
|
|
<?=$function['show_form']()?>
|
|
<?php endif;?>
|
|
|
|
<?php if(!empty($host) || $prefer_ref_uuid): ?>
|
|
<?=$function['show_scan_history']();?>
|
|
<?php endif; ?>
|
|
<?php
|
|
page_footer();
|
|
};
|
|
|
|
$route['scan_details'] = function()
|
|
{
|
|
$ref_uuid = filter_input(INPUT_GET, 'ref_uuid');
|
|
$prefer_ref_uuid = !empty($ref_uuid);
|
|
if ($prefer_ref_uuid) $ref_uuid = htmlspecialchars($ref_uuid);
|
|
|
|
$scan_id = filter_input(INPUT_GET, 'scan_id');
|
|
if (empty($scan_id)) {
|
|
suicide_user_bad_request('scan_id kan ikke være tom!');
|
|
}
|
|
|
|
$scan = pinglerr_get_scan(
|
|
scan_id: $scan_id,
|
|
must_be_active_or_waiting: false
|
|
);
|
|
if (!$scan) {
|
|
suicide_user_bad_request('Fant ikke scan i databasen!');
|
|
}
|
|
if ($scan['status_code'] === 'WAITING') {
|
|
suicide_user_bad_request('Venter på at denne skanningen skal starte');
|
|
}
|
|
page_header('Detaljer - Pinglerr', toolbar_links: [
|
|
[
|
|
'href' => get_referer(),
|
|
'name' => 'Gå tilbake'
|
|
]
|
|
]);
|
|
?>
|
|
<h1>Fullstendig statistikk</h1>
|
|
<div class="sign-container">
|
|
<?php if($scan['status_code'] === 'ACTIVE'): ?>
|
|
<span class="sign"><span class="sign-label">Status</span><span class="sign-text alert-success">Aktiv</span></span>
|
|
<?php elseif($scan['status_code'] === 'DONE'): ?>
|
|
<span class="sign"><span class="sign-label">Status</span><span class="sign-text alert-info">Ferdig</span></span>
|
|
<?php endif; ?>
|
|
<span class="sign"><span class="sign-label">Vert</span><span class="sign-text"><?=$scan['host']?></span></span>
|
|
<span class="sign"><span class="sign-label">ID</span><span class="sign-text"><?=$scan_id?></span></span>
|
|
</div>
|
|
|
|
<div id="chartElement"></div>
|
|
<div id="brushChartElement"></div>
|
|
|
|
<script src="static/js/scan_history_details.js"></script>
|
|
<?php
|
|
page_footer();
|
|
};
|
|
|
|
$route['start_scan'] = function()
|
|
{
|
|
$ref_uuid = filter_input(INPUT_POST, 'ref_uuid');
|
|
$prefer_ref_uuid = !empty($ref_uuid);
|
|
if ($prefer_ref_uuid) $ref_uuid = htmlspecialchars($ref_uuid);
|
|
|
|
$host = strtolower(filter_input(INPUT_POST, 'host'));
|
|
if (!is_valid_host($host)) {
|
|
if ($prefer_ref_uuid) {
|
|
header('Location: ?p=default&host=' . $host . '&ref_uuid=' . $ref_uuid);
|
|
} else {
|
|
header('Location: ?p=default&host=' . $host);
|
|
}
|
|
flash_message('Kunne ikke starte ny skanning: ugyldig vert adresse!', 'danger');
|
|
die();
|
|
}
|
|
|
|
if ($prefer_ref_uuid) {
|
|
$scan = pinglerr_get_scan(ref_uuid: $ref_uuid);
|
|
} else {
|
|
$scan = pinglerr_get_scan($host);
|
|
}
|
|
|
|
// if scan is not active or waiting
|
|
if ($scan === null) {
|
|
$stmt = get_mysqli()->prepare(
|
|
"INSERT INTO pinglerr_scans (host, ref_uuid, status_code, end_date) VALUES (?, ?, ?, NOW() + INTERVAL ? SECOND)"
|
|
);
|
|
$status_code = 'WAITING';
|
|
|
|
$time_limit_in_seconds = filter_input(INPUT_POST, 'time_limit');
|
|
if (!is_numeric($time_limit_in_seconds))
|
|
suicide_user_bad_request('time_limit is not numeric');
|
|
if ($time_limit_in_seconds > 31536000)
|
|
suicide_user_bad_request('time_limit should not be above 1 year');
|
|
if ($time_limit_in_seconds < 0)
|
|
suicide_user_bad_request('time_limit should not be a negative value');
|
|
|
|
// run forever
|
|
if ($time_limit_in_seconds == 0)
|
|
$time_limit_in_seconds = 315569260;
|
|
|
|
$stmt->bind_param("sssi", $host, $ref_uuid, $status_code, $time_limit_in_seconds);
|
|
$stmt->execute();
|
|
} else {
|
|
flash_message('Det eksisterer allerede en aktiv skanning på denne verten eller referansen');
|
|
if ($prefer_ref_uuid) {
|
|
header('Location: ?p=default&ref_uuid=' . $ref_uuid);
|
|
} else {
|
|
header('Location: ?p=default&host=' . $host);
|
|
}
|
|
die();
|
|
}
|
|
if ($prefer_ref_uuid) {
|
|
header('Location: ?p=default&ref_uuid=' . $ref_uuid);
|
|
} else {
|
|
header('Location: ?p=default&host=' . $host);
|
|
}
|
|
};
|
|
|
|
$route['stop_scanning'] = function()
|
|
{
|
|
$confirm = filter_input(INPUT_GET, 'confirm');
|
|
$scan_id = filter_input(INPUT_GET, 'scan_id');
|
|
|
|
$ref_uuid = filter_input(INPUT_GET, 'ref_uuid');
|
|
$prefer_ref_uuid = !empty($ref_uuid);
|
|
if ($prefer_ref_uuid) $ref_uuid = htmlspecialchars($ref_uuid);
|
|
|
|
$host = strtolower(filter_input(INPUT_GET, 'host'));
|
|
if (!$prefer_ref_uuid && !empty($host) && !is_valid_host($host)) {
|
|
suicide_user_bad_request('Ugyldig vertsnavn');
|
|
}
|
|
|
|
if (boolval($confirm)) {
|
|
$scan = pinglerr_get_scan(scan_id: $scan_id);
|
|
if (empty($scan)) {
|
|
suicide_user_bad_request('Fant ikke noen aktiv skanning');
|
|
}
|
|
$stmt = get_mysqli()->prepare(
|
|
"UPDATE pinglerr_scans SET status_code = ?, end_date = NOW(), error_message = ? WHERE status_code IN ('ACTIVE', 'WAITING') AND id = ?"
|
|
);
|
|
$status_code = 'DONE';
|
|
$error_message = 'Manually stopped by user';
|
|
$stmt->bind_param("sss",
|
|
$status_code,
|
|
$error_message,
|
|
$scan['id']
|
|
);
|
|
$stmt->execute();
|
|
|
|
if ($prefer_ref_uuid) {
|
|
header('Location: ?p=default&host=' . $host . '&ref_uuid=' . $ref_uuid);
|
|
} else {
|
|
header('Location: ?p=default&host=' . $host);
|
|
}
|
|
flash_message('Du har nå stanset skanningen', 'success');
|
|
die();
|
|
|
|
} else {
|
|
page_header('Er du sikker? - Pingler');
|
|
?>
|
|
<h1>Er du sikker?</h1>
|
|
<p>Vil du virkelig stanse denne skanningen?</p>
|
|
<span>[ <a class="link-btn-success" href="?p=stop_scanning&confirm=true&scan_id=<?=htmlspecialchars($scan_id)?><?=($prefer_ref_uuid ? '&ref_uuid=' . $ref_uuid : '') . (!empty($host) ? '&host=' . $host : '')?>">Ja det vil jeg!</a> ]</span>
|
|
<span>[ <a class="link-btn-danger" href="<?=get_referer()?>">Nei ta meg tilbake igjen</a> ]</span>
|
|
<?php
|
|
page_footer();
|
|
}
|
|
};
|
|
|
|
$route['daemon_poll'] = function()
|
|
{
|
|
$scans = (function(): ?array {
|
|
$stmt = get_mysqli()->prepare(
|
|
"SELECT * FROM pinglerr_scans WHERE status_code IN ('ACTIVE', 'WAITING')"
|
|
);
|
|
$stmt->execute();
|
|
$result = $stmt->get_result();
|
|
$assoc_array = [];
|
|
while ($row = $result->fetch_assoc()) {
|
|
$assoc_array[] = $row;
|
|
}
|
|
return $assoc_array;
|
|
})();
|
|
header('Content-type: application/json');
|
|
echo json_encode($scans);
|
|
};
|
|
|
|
// not in use anymore, replaced with daemon_bulk_update
|
|
$route['daemon_update'] = function()
|
|
{
|
|
$scan_id = filter_input(INPUT_GET, 'scan_id');
|
|
if (empty($scan_id)) {
|
|
suicide_user_bad_request('Mangler scan_id query parameter');
|
|
}
|
|
|
|
$scan = pinglerr_get_scan(scan_id: $scan_id);
|
|
if ($scan === null) {
|
|
suicide_user_bad_request('Kunne ikke finne scan fra scan_id');
|
|
}
|
|
|
|
// if time is up change the status to DONE and also exit the script
|
|
// TODO: this would probably be more suitable in the route daemon_jobs or some other
|
|
// endpoint that the daemon would periodically call
|
|
(function() use($scan)
|
|
{
|
|
$current_epoch = time();
|
|
$end_epoch = strtotime($scan['end_date']);
|
|
if ($current_epoch > $end_epoch) {
|
|
$stmt = get_mysqli()->prepare(
|
|
"UPDATE pinglerr_scans SET status_code = ?, error_message = ? WHERE status_code IN ('ACTIVE', 'WAITING') AND id = ?"
|
|
);
|
|
$status_code = 'DONE';
|
|
$error_message = 'Stopped because end_date was reached';
|
|
$stmt->bind_param("sss",
|
|
$status_code,
|
|
$error_message,
|
|
$scan['id']
|
|
);
|
|
$stmt->execute();
|
|
die();
|
|
}
|
|
})();
|
|
|
|
// set scan status from WAITING to ACTIVE
|
|
(function() use($scan)
|
|
{
|
|
$stmt = get_mysqli()->prepare(
|
|
"UPDATE pinglerr_scans SET status_code = ? WHERE id = ?"
|
|
);
|
|
$status_code = 'ACTIVE';
|
|
$stmt->bind_param("si",
|
|
$status_code,
|
|
$scan['id'],
|
|
);
|
|
$stmt->execute();
|
|
})();
|
|
|
|
(function() use($scan)
|
|
{
|
|
$pkt_transmitted = filter_input(INPUT_GET, 'pkt_transmitted');
|
|
$pkt_received = filter_input(INPUT_GET, 'pkt_received');
|
|
$ping_avg = filter_input(INPUT_GET, 'ping_avg');
|
|
|
|
$stmt = get_mysqli()->prepare(
|
|
"INSERT INTO pinglerr_pings (scan_id, ping_avg, pkt_transmitted, pkt_received) VALUES (?,?,?,?)"
|
|
);
|
|
$stmt->bind_param("idii",
|
|
$scan['id'],
|
|
$ping_avg,
|
|
$pkt_transmitted,
|
|
$pkt_received,
|
|
);
|
|
$stmt->execute();
|
|
})();
|
|
};
|
|
|
|
$route['daemon_bulk_update'] = function()
|
|
{
|
|
$bulk_pings = json_decode(file_get_contents('php://input'), true);
|
|
|
|
foreach ($bulk_pings as $ping) {
|
|
$scan_id = $ping['scan_id'];
|
|
$pkt_transmitted = $ping['pkt_transmitted'];
|
|
$pkt_received = $ping['pkt_received'];
|
|
if (!isset($ping['ping_avg'])) {
|
|
$ping_avg = null;
|
|
} else {
|
|
$ping_avg = $ping['ping_avg'];
|
|
}
|
|
|
|
$scan = pinglerr_get_scan(scan_id: $scan_id);
|
|
if ($scan === null) {
|
|
suicide_user_bad_request('Kunne ikke finne scan for scan_id');
|
|
}
|
|
|
|
$time_is_up = (function() use($scan)
|
|
{
|
|
$current_epoch = time();
|
|
$end_epoch = strtotime($scan['end_date']);
|
|
if ($current_epoch > $end_epoch) {
|
|
$stmt = get_mysqli()->prepare(
|
|
"UPDATE pinglerr_scans SET status_code = ?, error_message = ? WHERE status_code IN ('ACTIVE', 'WAITING') AND id = ?"
|
|
);
|
|
$status_code = 'DONE';
|
|
$error_message = 'Stopped because end_date was reached';
|
|
$stmt->bind_param("sss",
|
|
$status_code,
|
|
$error_message,
|
|
$scan['id']
|
|
);
|
|
$stmt->execute();
|
|
return true;
|
|
}
|
|
return false;
|
|
})();
|
|
if ($time_is_up) {
|
|
continue;
|
|
}
|
|
|
|
// set scan status from WAITING to ACTIVE
|
|
(function() use($scan)
|
|
{
|
|
$stmt = get_mysqli()->prepare(
|
|
"UPDATE pinglerr_scans SET status_code = ? WHERE id = ?"
|
|
);
|
|
$status_code = 'ACTIVE';
|
|
$stmt->bind_param("si",
|
|
$status_code,
|
|
$scan['id'],
|
|
);
|
|
$stmt->execute();
|
|
})();
|
|
|
|
(function() use($scan, $pkt_transmitted, $pkt_received, $ping_avg)
|
|
{
|
|
$stmt = get_mysqli()->prepare(
|
|
"INSERT INTO pinglerr_pings (scan_id, ping_avg, pkt_transmitted, pkt_received) VALUES (?,?,?,?)"
|
|
);
|
|
$stmt->bind_param("idii",
|
|
$scan['id'],
|
|
$ping_avg,
|
|
$pkt_transmitted,
|
|
$pkt_received,
|
|
);
|
|
$stmt->execute();
|
|
})();
|
|
|
|
}
|
|
};
|
|
|
|
$route['api_chart'] = function()
|
|
{
|
|
$scan_id = filter_input(INPUT_GET, 'scan_id');
|
|
$since = intval(filter_input(INPUT_GET, 'since'));
|
|
$limit_length = intval(filter_input(INPUT_GET, 'limit_length'));
|
|
|
|
$pings = (function() use($scan_id, $since): array
|
|
{
|
|
$stmt = get_mysqli()->prepare(
|
|
"SELECT ping_avg, pkt_transmitted, pkt_received, date_added FROM pinglerr_pings WHERE scan_id = ? AND date_added > FROM_UNIXTIME(?) ORDER BY date_added ASC"
|
|
);
|
|
$stmt->bind_param("ii", $scan_id, $since);
|
|
$stmt->execute();
|
|
$result = $stmt->get_result();
|
|
$assoc_array = [];
|
|
while ($row = $result->fetch_assoc()) {
|
|
$assoc_array[] = $row;
|
|
}
|
|
return $assoc_array;
|
|
})();
|
|
if (empty($pings)) {
|
|
http_response_code(204);
|
|
die();
|
|
}
|
|
|
|
if ($limit_length > 0 && $limit_length < count($pings)) {
|
|
$merged_pings = [];
|
|
|
|
$merge_gap = count($pings) / $limit_length;
|
|
$merge_iteration = 0;
|
|
$merge_remainder = 0;
|
|
|
|
$ping_avg_sum_storage = [];
|
|
$ping_pkt_transmitted_storage = [];
|
|
$ping_pkt_received_storage = [];
|
|
foreach ($pings as $ping) {
|
|
if ($merge_iteration >= $merge_gap - $merge_remainder) {
|
|
$merge_remainder+= $merge_iteration - $merge_gap;
|
|
|
|
$how_many_nulls = 0;
|
|
for ($i=0; $i < count($ping_avg_sum_storage); $i++) {
|
|
if ($ping_avg_sum_storage[$i] === null) {
|
|
$how_many_nulls++;
|
|
}
|
|
}
|
|
if ($how_many_nulls > count($ping_avg_sum_storage) / 2) {
|
|
$ping_avg = null;
|
|
} else {
|
|
for ($i=0; $i < count($ping_avg_sum_storage); $i++) {
|
|
if ($ping_avg_sum_storage[$i] === null) {
|
|
unset($ping_avg_sum_storage[$i]);
|
|
}
|
|
}
|
|
$ping_avg = round(array_sum($ping_avg_sum_storage) / count($ping_avg_sum_storage), 3);
|
|
}
|
|
|
|
$merged_pings[] = [
|
|
'ping_avg' => $ping_avg,
|
|
'date_added' => $ping['date_added'],
|
|
'pkt_transmitted' => round(array_sum($ping_pkt_transmitted_storage) / count($ping_pkt_transmitted_storage), 3),
|
|
'pkt_received' => round(array_sum($ping_pkt_received_storage) / count($ping_pkt_received_storage), 3),
|
|
];
|
|
$ping_pkt_transmitted_storage = [];
|
|
$ping_pkt_received_storage = [];
|
|
$ping_avg_sum_storage = [];
|
|
$merge_iteration = 0;
|
|
}
|
|
$ping_pkt_transmitted_storage[] = $ping['pkt_transmitted'];
|
|
$ping_pkt_received_storage[] = $ping['pkt_received'];
|
|
$ping_avg_sum_storage[] = $ping['ping_avg'];
|
|
$merge_iteration++;
|
|
}
|
|
|
|
$pings = $merged_pings;
|
|
}
|
|
|
|
|
|
//echo 'Gap: ' . htmlspecialchars($merge_gap) . ' Antall: ' . count($pings) . ' Remains: ' . $merge_remainder;
|
|
//die();
|
|
|
|
header('Content-type: application/json');
|
|
echo json_encode([
|
|
'latest' => strtotime($pings[count($pings) - 1]['date_added']),
|
|
'pings' => $pings,
|
|
]);
|
|
};
|
|
|
|
$route['api_stats'] = function()
|
|
{
|
|
$ref_uuid = filter_input(INPUT_GET, 'ref_uuid');
|
|
$prefer_ref_uuid = !empty($ref_uuid);
|
|
if ($prefer_ref_uuid) $ref_uuid = htmlspecialchars($ref_uuid);
|
|
|
|
$host = strtolower(filter_input(INPUT_GET, 'host'));
|
|
if (!$prefer_ref_uuid && !empty($host) && !is_valid_host($host)) {
|
|
suicide_user_bad_request('Ugyldig vertsnavn');
|
|
}
|
|
|
|
$scan_id = filter_input(INPUT_GET, 'scan_id');
|
|
|
|
if ($prefer_ref_uuid) {
|
|
$scan = pinglerr_get_scan(ref_uuid: $ref_uuid);
|
|
} elseif(!empty($host)) {
|
|
$scan = pinglerr_get_scan($host);
|
|
} elseif(!empty($scan_id)) {
|
|
$scan = pinglerr_get_scan(
|
|
scan_id: $scan_id,
|
|
must_be_active_or_waiting: false
|
|
);
|
|
} else {
|
|
suicide_user_bad_request('Mangler ref_uuid, host eller scan_id parameter');
|
|
}
|
|
if ($scan === null) {
|
|
suicide_user_bad_request('Kunne ikke finne noen aktive skanninger for denne verten eller referanse');
|
|
}
|
|
|
|
$since = intval(filter_input(INPUT_GET, 'since'));
|
|
|
|
$pings = (function() use($scan, $since): array
|
|
{
|
|
$stmt = get_mysqli()->prepare(
|
|
"SELECT * FROM pinglerr_pings WHERE scan_id = ? AND date_added > FROM_UNIXTIME(?) ORDER BY date_added DESC"
|
|
);
|
|
$stmt->bind_param("is", $scan['id'], $since);
|
|
$stmt->execute();
|
|
$result = $stmt->get_result();
|
|
$assoc_array = [];
|
|
while ($row = $result->fetch_assoc()) {
|
|
$assoc_array[] = $row;
|
|
}
|
|
return $assoc_array;
|
|
})();
|
|
if (empty($pings)) {
|
|
http_response_code(204);
|
|
die();
|
|
}
|
|
|
|
$pkt_transmitted = (function() use($pings): int {
|
|
$pkts = 0;
|
|
foreach ($pings as $ping_row) {
|
|
if ($ping_row['pkt_transmitted'] === null) {
|
|
continue;
|
|
}
|
|
$pkts = $pkts + $ping_row['pkt_transmitted'];
|
|
}
|
|
return $pkts;
|
|
})();
|
|
$pkt_received = (function() use($pings): int {
|
|
$pkts = 0;
|
|
foreach ($pings as $ping_row) {
|
|
if ($ping_row['pkt_received'] === null) {
|
|
continue;
|
|
}
|
|
$pkts = $pkts + $ping_row['pkt_received'];
|
|
}
|
|
return $pkts;
|
|
})();
|
|
$packet_loss_percentage = (function() use($pkt_transmitted, $pkt_received): float {
|
|
try {
|
|
$packet_loss_percentage = $pkt_received / $pkt_transmitted * 100;
|
|
} catch (\DivisionByZeroError $th) {
|
|
return 100;
|
|
}
|
|
if ($packet_loss_percentage > 100) {
|
|
$packet_loss_percentage = 100;
|
|
} else {
|
|
$packet_loss_percentage = 100 - $packet_loss_percentage;
|
|
}
|
|
return $packet_loss_percentage;
|
|
})();
|
|
// TODO: this is just packet_loss_percentage reversed! make a more proper uptime calculation
|
|
$uptime_percentage = (function() use($packet_loss_percentage): float {
|
|
return 100 - $packet_loss_percentage;
|
|
})();
|
|
// TODO: this is too simple, but it works for now. make a more proper calculation using jitter
|
|
$connection_status = (function() use($pings, $packet_loss_percentage) {
|
|
if ($pings[0]['ping_avg'] === null) {
|
|
return 'OFFLINE';
|
|
}
|
|
if ($packet_loss_percentage >= 2) {
|
|
return 'UNSTABLE';
|
|
}
|
|
return 'ONLINE';
|
|
})();
|
|
|
|
header('Content-type: application/json');
|
|
return json_encode([
|
|
'latest' => strtotime($pings[0]['date_added']),
|
|
'scan_id' => $scan['id'],
|
|
'host' => $scan['host'],
|
|
'ref_uuid' => $scan['ref_uuid'],
|
|
'status_code' => $scan['status_code'],
|
|
'connection_status' => $connection_status,
|
|
'pkt_transmitted' => $pkt_transmitted,
|
|
'pkt_received' => $pkt_received,
|
|
'ping_latest' => round($pings[0]['ping_avg'], 0, PHP_ROUND_HALF_EVEN),
|
|
'packet_loss_percentage' => round($packet_loss_percentage, 0, PHP_ROUND_HALF_UP),
|
|
'uptime_percentage' => round($uptime_percentage, 0, PHP_ROUND_HALF_DOWN),
|
|
]);
|
|
};
|
|
|
|
$page = filter_input(INPUT_GET, 'p');
|
|
if (empty($page)) {
|
|
$page = 'default';
|
|
}
|
|
if (isset($route[$page])) {
|
|
die($route[$page]());
|
|
}
|
|
http_response_code(404);
|
|
page_header('Kunne ikke finne siden')
|
|
?>
|
|
<h1>Siden ble ikke funnet</h1>
|
|
<a href="<?=get_referer()?>">Klikk her for å gå tilbake</a>
|
|
<?php
|
|
page_footer()
|
|
?>
|