action(), $ctx->daUser->username(), Http::server('REMOTE_ADDR'), Http::method(), Http::server('REQUEST_URI'), $message ); @error_log($entry, 3, $pluginErrorLog); }; try { if (!$ctx->daUser->hasPluginAccess()) { throw new RuntimeException('Brak dostępu do pluginu.'); } $queue = new BackupQueueService($ctx->settings, $ctx->daUser); $jobId = trim($ctx->queryString('job')); $backupPath = trim($ctx->queryString('path')); $downloadPath = ''; $logLabel = ''; if ($jobId !== '') { $logLabel = 'job_id=' . $jobId; $downloadPath = $queue->resolveBackupTargetFileForCurrentUser($jobId); } elseif ($backupPath !== '') { $logLabel = 'path=' . $backupPath; $downloadPath = $queue->resolveUserBackupFileForCurrentUser($backupPath); } else { throw new RuntimeException('Brak parametru job lub path.'); } // Reuse streaming logic from index handler (simplified) $log('start ' . $logLabel); if (!is_file($downloadPath) || !is_readable($downloadPath)) { throw new RuntimeException('Plik backupu nie istnieje lub brak odczytu.'); } $downloadName = basename($downloadPath); $downloadName = preg_replace('/[^A-Za-z0-9._-]+/', '_', $downloadName) ?? 'backup.sql'; $contentType = 'application/octet-stream'; if (preg_match('/\\.sql$/i', $downloadName)) { $contentType = 'application/sql'; } elseif (preg_match('/\\.gz$/i', $downloadName)) { $contentType = 'application/gzip'; } clearstatcache(true, $downloadPath); $size = @filesize($downloadPath); while (ob_get_level() > 0) { @ob_end_clean(); } if (function_exists('apache_setenv')) { @apache_setenv('no-gzip', '1'); } @ini_set('zlib.output_compression', '0'); @ini_set('output_buffering', '0'); if ($rawMode) { $statusLine = 'HTTP/1.1 200 OK'; echo $statusLine . "\r\n"; echo 'Content-Type: ' . $contentType . "\r\n"; echo 'Content-Disposition: attachment; filename="' . str_replace('"', '', $downloadName) . "\"\r\n"; echo "X-Content-Type-Options: nosniff\r\n"; echo "Cache-Control: no-store, no-cache, must-revalidate\r\n"; echo "Pragma: no-cache\r\n"; if (is_int($size) && $size > 0) { echo 'Content-Length: ' . (string)$size . "\r\n"; } echo "\r\n"; } else { if (headers_sent($hsFile, $hsLine)) { $log('headers_sent ' . $logLabel . ' file=' . $hsFile . ' line=' . (string)$hsLine); throw new RuntimeException('Nagłówki zostały już wysłane.'); } header_remove('Content-Encoding'); header('Content-Type: ' . $contentType); header('Content-Disposition: attachment; filename="' . str_replace('"', '', $downloadName) . '"'); header('X-Content-Type-Options: nosniff'); header('Cache-Control: no-store, no-cache, must-revalidate'); header('Pragma: no-cache'); if (is_int($size) && $size > 0) { header('Content-Length: ' . (string)$size); } } $bytes = @readfile($downloadPath); $log('done ' . $logLabel . ' bytes=' . (string)$bytes); exit; } catch (Throwable $e) { $log('error message=' . $e->getMessage()); if ($rawMode) { echo "HTTP/1.1 404 Not Found\r\n"; echo "Content-Type: text/plain; charset=UTF-8\r\n\r\n"; echo 'Nie można pobrać backupu: ' . $e->getMessage(); } else { http_response_code(404); header('Content-Type: text/plain; charset=UTF-8'); echo 'Nie można pobrać backupu: ' . $e->getMessage(); } exit; } };