53 lines
1.7 KiB
PHP
53 lines
1.7 KiB
PHP
<?php
|
|
// presence endpoint for den.js
|
|
// counts client ids (js-running visitors), capped per ip to prevent inflation
|
|
// stores hmac'd fingerprints only, never raw ips or ids. entries expire after 5 min
|
|
// one line per active visitor: latest_timestamp|fingerprint|iphash
|
|
// change this secret, keep it private
|
|
define('DEN_SECRET', 'NowmIO4VXYYF6cmg6hJRw3P4ZEd4PIpylnmpKhj8QeW9fe7wfJ94lwTGw8PfwRgRB2MlZEqaIBftH9L3twsccucwq6gFKnmqLpXsTS0PqN1Glwi6tRYtH3hPKm0VD3U');
|
|
|
|
$f = __DIR__ . '/../owo_presence.txt';
|
|
$now = time();
|
|
$iph = substr(hash_hmac('sha1', $_SERVER['REMOTE_ADDR'], DEN_SECRET), 0, 12);
|
|
|
|
$id = isset($_GET['id']) ? $_GET['id'] : '';
|
|
if (preg_match('/^[a-f0-9]{16}$/', $id)) {
|
|
$me = substr(hash_hmac('sha1', 'id:' . $id, DEN_SECRET), 0, 12);
|
|
} else {
|
|
$me = $iph;
|
|
}
|
|
|
|
$roster = [];
|
|
if (file_exists($f)) {
|
|
foreach (file($f, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $l) {
|
|
$p = explode('|', $l, 3);
|
|
if (count($p) < 2) continue;
|
|
$ts = (int)$p[0];
|
|
if ($ts < $now - 300) continue;
|
|
$fp = $p[1];
|
|
$rih = isset($p[2]) ? $p[2] : '';
|
|
if (!isset($roster[$fp]) || $ts > $roster[$fp][0]) {
|
|
$roster[$fp] = [$ts, $rih];
|
|
}
|
|
}
|
|
}
|
|
|
|
$from_my_ip = 0;
|
|
foreach ($roster as $fp => $e) {
|
|
if ($e[1] === $iph && $fp !== $me) $from_my_ip++;
|
|
}
|
|
if (isset($roster[$me]) || $from_my_ip < 3) {
|
|
$roster[$me] = [$now, $iph];
|
|
}
|
|
$others = count($roster) - (isset($roster[$me]) ? 1 : 0);
|
|
|
|
$out = '';
|
|
foreach ($roster as $fp => $e) {
|
|
$out .= $e[0] . '|' . $fp . '|' . $e[1] . "\n";
|
|
}
|
|
@file_put_contents($f, $out, LOCK_EX);
|
|
|
|
header('Content-Type: application/json');
|
|
header('Cache-Control: no-store');
|
|
echo json_encode(['others' => $others]);
|