Repository navigation
Expand file tree
/
Copy pathping.php
More file actions
92 lines (82 loc) · 2.57 KB
/
Copy pathping.php
File metadata and controls
92 lines (82 loc) · 2.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
<?php
/**
* Anonymous PDF-download counter for /check-writer/
*
* Privacy contract:
* - Does NOT read check fields, query strings, or request body.
* - Does NOT set cookies or sessions.
* - Stores only an integer total (+ optional daily totals).
* - No IP logging in this file (rely on server access logs separately if needed).
*
* Read total: open count.json on the server, or GET this endpoint.
*/
declare(strict_types=1);
header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-store');
header('X-Content-Type-Options: nosniff');
// Explicit: no cookies
header_remove('Set-Cookie');
// Only allow GET (read) and POST (increment). No other methods.
$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
if ($method !== 'GET' && $method !== 'POST') {
http_response_code(405);
echo json_encode(['ok' => false, 'error' => 'method_not_allowed']);
exit;
}
$file = __DIR__ . '/count.json';
/**
* @return array{total:int, by_day:array<string,int>}
*/
function load_counts(string $file): array
{
$default = ['total' => 0, 'by_day' => []];
if (!is_file($file)) {
return $default;
}
$raw = file_get_contents($file);
if ($raw === false || $raw === '') {
return $default;
}
$data = json_decode($raw, true);
if (!is_array($data)) {
return $default;
}
return [
'total' => (int) ($data['total'] ?? 0),
'by_day' => is_array($data['by_day'] ?? null) ? $data['by_day'] : [],
];
}
/**
* @param array{total:int, by_day:array<string,int>} $data
*/
function save_counts(string $file, array $data): bool
{
$json = json_encode($data, JSON_PRETTY_PRINT);
if ($json === false) {
return false;
}
return file_put_contents($file, $json, LOCK_EX) !== false;
}
$counts = load_counts($file);
if ($method === 'POST') {
// Increment only — never accept or store payload fields
$counts['total']++;
$day = gmdate('Y-m-d');
$counts['by_day'][$day] = (int) ($counts['by_day'][$day] ?? 0) + 1;
// Keep by_day from growing forever (last 90 days)
if (count($counts['by_day']) > 90) {
ksort($counts['by_day']);
$counts['by_day'] = array_slice($counts['by_day'], -90, null, true);
}
if (!save_counts($file, $counts)) {
http_response_code(500);
echo json_encode(['ok' => false, 'error' => 'write_failed']);
exit;
}
}
echo json_encode([
'ok' => true,
'total' => $counts['total'],
// today only — enough for a dashboard peek without dumping history
'today' => (int) ($counts['by_day'][gmdate('Y-m-d')] ?? 0),
]);