mirror of
git://f0xx.org/ac/ac-ms-devices
synced 2026-07-29 02:57:50 +03:00
initial
This commit is contained in:
65
public/api/heartbeat.php
Normal file
65
public/api/heartbeat.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
require_once __DIR__ . '/../../src/bootstrap.php';
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'POST') {
|
||||
http_response_code(405);
|
||||
echo json_encode(['error' => 'method_not_allowed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$raw = file_get_contents('php://input') ?: '';
|
||||
$req = json_decode($raw, true);
|
||||
if (!is_array($req)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'invalid_json']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$heartbeat = $req['heartbeat'] ?? [];
|
||||
if (!is_array($heartbeat)) {
|
||||
$heartbeat = [];
|
||||
}
|
||||
|
||||
$type = (string)($heartbeat['type'] ?? 'generic');
|
||||
$srvEpoch = time();
|
||||
$srvTz = date('O');
|
||||
$clientIp = (string)($_SERVER['HTTP_X_FORWARDED_FOR'] ?? ($_SERVER['REMOTE_ADDR'] ?? ''));
|
||||
|
||||
$resp = [
|
||||
'heartbeat' => [
|
||||
'type' => $type,
|
||||
'server_date' => $srvEpoch,
|
||||
'server_tz' => $srvTz,
|
||||
],
|
||||
];
|
||||
|
||||
if ($type === 'ntp') {
|
||||
$clientDate = (int)($heartbeat['date'] ?? 0);
|
||||
$clientTz = (string)($heartbeat['tz'] ?? '');
|
||||
$timeSource = trim((string)($heartbeat['time_source'] ?? 'device'));
|
||||
if ($timeSource === '') {
|
||||
$timeSource = 'device';
|
||||
}
|
||||
$correction = $clientDate > 0 ? ($srvEpoch - $clientDate) : null;
|
||||
$resp['heartbeat']['client_date'] = $clientDate;
|
||||
$resp['heartbeat']['client_tz'] = $clientTz;
|
||||
$resp['heartbeat']['time_source'] = $timeSource;
|
||||
$resp['heartbeat']['correction_seconds'] = $correction;
|
||||
$resp['heartbeat']['ntp_correction_s'] = $correction;
|
||||
$resp['heartbeat']['enabled'] = true;
|
||||
}
|
||||
|
||||
if ($type === 'ip') {
|
||||
$resp['heartbeat']['external_ip'] = $clientIp;
|
||||
}
|
||||
|
||||
if ($type === 'ra') {
|
||||
require_once __DIR__ . '/../../src/RemoteAccessRepository.php';
|
||||
$ra = RemoteAccessRepository::handleDeviceHeartbeat($heartbeat, $clientIp);
|
||||
$resp['heartbeat'] = array_merge($resp['heartbeat'], $ra);
|
||||
}
|
||||
|
||||
echo json_encode($resp, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||
53
public/api/upload.php
Normal file
53
public/api/upload.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/*
|
||||
* package examples/crash_reporter/backend/public/api/upload.php
|
||||
* upload.php
|
||||
* Created at: Wed 20 May 2026 14:31:55 +0200
|
||||
* Updated at: Wed 20 May 2026 15:17:13 +0200 by Anton Afanasyeu <a.afanasieff@gmail.com>
|
||||
* Commit: 5d8e82d2e60a21fff3138d2a394ee4e8b4c6dcb8
|
||||
* Contributors:
|
||||
* - Anton Afanasyeu <a.afanasieff@gmail.com> (2 commits, 25 lines)
|
||||
* - Cursor Agent (project assistant)
|
||||
* Digest: SHA256 edbab2563cb9d5ba1c9a6a6272071ac12efa782274c7d1626f088a951033d5a6
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
require_once __DIR__ . '/../../src/bootstrap.php';
|
||||
|
||||
$raw = read_crash_upload_body();
|
||||
if ($raw === null) {
|
||||
json_out(['ok' => false, 'error' => 'empty body'], 400);
|
||||
}
|
||||
if ($raw === false) {
|
||||
json_out(['ok' => false, 'error' => 'invalid gzip body'], 400);
|
||||
}
|
||||
$data = json_decode($raw, true);
|
||||
if (!is_array($data)) {
|
||||
json_out(['ok' => false, 'error' => 'invalid json'], 400);
|
||||
}
|
||||
if ((int) ($data['schema_version'] ?? 0) !== 1) {
|
||||
json_out(['ok' => false, 'error' => 'unsupported schema_version'], 400);
|
||||
}
|
||||
try {
|
||||
ReportRepository::insert($data);
|
||||
json_out(['ok' => true, 'report_id' => $data['report_id'] ?? null]);
|
||||
} catch (PDOException $e) {
|
||||
$msg = $e->getMessage();
|
||||
if ($e->getCode() === '23000' || stripos($msg, 'UNIQUE') !== false) {
|
||||
json_out(['ok' => false, 'error' => 'duplicate report_id'], 409);
|
||||
}
|
||||
error_log('crash upload PDO: ' . $msg);
|
||||
log_crash_event('upload', 'PDO: ' . $msg);
|
||||
$out = ['ok' => false, 'error' => 'store failed'];
|
||||
if (cfg('debug')) {
|
||||
$out['hint'] = $msg;
|
||||
}
|
||||
json_out($out, 500);
|
||||
} catch (Throwable $e) {
|
||||
error_log('crash upload: ' . $e->getMessage());
|
||||
log_crash_event('upload', $e->getMessage());
|
||||
$out = ['ok' => false, 'error' => 'store failed'];
|
||||
if (cfg('debug')) {
|
||||
$out['hint'] = $e->getMessage();
|
||||
}
|
||||
json_out($out, 500);
|
||||
}
|
||||
Reference in New Issue
Block a user