prepare("SELECT * FROM software_versions WHERE rowID = ?"); $stmt->execute([$tokenData['version_id']]); $version = $stmt->fetch(PDO::FETCH_ASSOC); if (!$version) { http_response_code(404); exit('File not found'); } // Invalidate token after use (one-time use) invalidateToken($pdo, $token); // Stream the file $filePath = $version['file_path']; // e.g., '/var/www/secure_files/update_v2.0.zip' if (!file_exists($filePath)) { http_response_code(404); exit('File not found on server'); } // Set headers for file download header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="' . basename($version['filename']) . '"'); header('Content-Length: ' . filesize($filePath)); header('Cache-Control: no-cache, must-revalidate'); header('Pragma: no-cache'); header('Expires: 0'); // Stream file in chunks to handle large files $handle = fopen($filePath, 'rb'); while (!feof($handle)) { echo fread($handle, 8192); flush(); } fclose($handle); exit; // Helper functions for token management function validateDownloadToken($pdo, $token) { $stmt = $pdo->prepare( "SELECT user_id, version_id, expires_at, used FROM download_tokens WHERE token = ?" ); $stmt->execute([$token]); $tokenData = $stmt->fetch(PDO::FETCH_ASSOC); if (!$tokenData) { return false; } // Check if expired if (strtotime($tokenData['expires_at']) < time()) { return false; } // Check if already used if ($tokenData['used']) { return false; } return $tokenData; } function invalidateToken($pdo, $token) { $stmt = $pdo->prepare("UPDATE download_tokens SET used = 1 WHERE token = ?"); $stmt->execute([$token]); } ?>