<?php
// Secure temporary backup download endpoint. Links are generated from admin panel/bot.
error_reporting(0);
$root = __DIR__;
$token = isset($_GET['token']) ? preg_replace('/[^a-f0-9]/i', '', (string)$_GET['token']) : '';
if($token === '' || strlen($token) < 32){ http_response_code(404); exit('Not found'); }
$mapFile = $root.'/cache/backup_downloads.json';
if(!is_file($mapFile)){ http_response_code(404); exit('Not found'); }
$map = json_decode((string)@file_get_contents($mapFile), true);
if(!is_array($map) || empty($map[$token]) || !is_array($map[$token])){ http_response_code(404); exit('Not found'); }
$row = $map[$token];
if((int)($row['expires'] ?? 0) < time()){
    unset($map[$token]);
    @file_put_contents($mapFile, json_encode($map, JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT), LOCK_EX);
    http_response_code(410); exit('Expired');
}
$file = (string)($row['file'] ?? '');
$real = realpath($file);
$allowedBases = array_filter([
    realpath($root.'/cache/backups'),
    realpath($root.'/cache/exports'),
]);
$allowed = false;
foreach($allowedBases as $base){
    if($real && $base && strpos($real, $base) === 0){ $allowed = true; break; }
}
if(!$real || !$allowed || !is_file($real)){
    http_response_code(404); exit('Not found');
}
$downloadName = basename($real);
$lower = strtolower($downloadName);
$contentType = 'application/octet-stream';
if(substr($lower, -5) === '.json') $contentType = 'application/json; charset=utf-8';
elseif(substr($lower, -7) === '.sql.gz') $contentType = 'application/gzip';
elseif(substr($lower, -4) === '.sql') $contentType = 'application/sql; charset=utf-8';
elseif(substr($lower, -4) === '.csv') $contentType = 'text/csv; charset=utf-8';
header('Content-Type: '.$contentType);
header('X-Content-Type-Options: nosniff');
header('Content-Disposition: attachment; filename="'.str_replace('"','', $downloadName).'"; filename*=UTF-8\'\''.rawurlencode($downloadName));
header('Content-Length: '.filesize($real));
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
readfile($real);
exit;
?>
