track.php 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. <?php
  2. /**
  3. * Click tracking capture endpoint.
  4. * Logs request details to data/tracks.jsonl and redirects to the main page.
  5. * Usage: track.php (no parameters required)
  6. */
  7. $dataDir = __DIR__ . '/data';
  8. $logFile = $dataDir . '/tracks.jsonl';
  9. $mainPageUrl = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http')
  10. . '://' . ($_SERVER['HTTP_HOST'] ?? 'localhost')
  11. . rtrim(dirname($_SERVER['SCRIPT_NAME'] ?? '/'), '/') . '/index.php';
  12. $ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '';
  13. $forwarded = isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : '';
  14. $realIp = isset($_SERVER['HTTP_X_REAL_IP']) ? $_SERVER['HTTP_X_REAL_IP'] : '';
  15. function lookupCountryCode($ip)
  16. {
  17. if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
  18. return null;
  19. }
  20. $context = stream_context_create(['http' => ['timeout' => 2]]);
  21. $response = @file_get_contents(
  22. 'http://ip-api.com/json/' . urlencode($ip) . '?fields=status,countryCode',
  23. false,
  24. $context
  25. );
  26. if ($response === false) {
  27. return null;
  28. }
  29. $data = json_decode($response, true);
  30. if (!is_array($data) || ($data['status'] ?? '') !== 'success') {
  31. return null;
  32. }
  33. return $data['countryCode'] ?? null;
  34. }
  35. $countryCode = lookupCountryCode($ip);
  36. $key = isset($_GET['key']) && $_GET['key'] !== '' ? trim($_GET['key']) : null;
  37. if ($key === 'KEY') {
  38. header('Location: ' . $mainPageUrl);
  39. exit;
  40. }
  41. $payload = [
  42. 'timestamp' => date('c'),
  43. 'key' => $key,
  44. 'target_url' => null,
  45. 'ip' => $ip,
  46. 'ip_forwarded' => $forwarded !== '' ? $forwarded : null,
  47. 'ip_real' => $realIp !== '' ? $realIp : null,
  48. 'country_code' => $countryCode,
  49. 'user_agent' => isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null,
  50. 'referrer' => isset($_SERVER['HTTP_REFERER']) && $_SERVER['HTTP_REFERER'] !== '' ? $_SERVER['HTTP_REFERER'] : null,
  51. 'request_uri' => isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : null,
  52. 'request_method' => isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : null,
  53. 'query_string' => isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : null,
  54. 'accept_language' => isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? $_SERVER['HTTP_ACCEPT_LANGUAGE'] : null,
  55. 'accept' => isset($_SERVER['HTTP_ACCEPT']) ? $_SERVER['HTTP_ACCEPT'] : null,
  56. ];
  57. if (!is_dir($dataDir)) {
  58. mkdir($dataDir, 0755, true);
  59. }
  60. $line = json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . "\n";
  61. file_put_contents($logFile, $line, FILE_APPEND | LOCK_EX);
  62. header('Location: ' . $mainPageUrl);
  63. exit;