Files
cmsPRO/_backup.php
2026-02-22 21:59:33 +01:00

220 lines
6.2 KiB
PHP

<?php
define('TMP_FILE', __DIR__ . '/backup_tmp.json');
define('FILES_PER_STEP', 50);
// Sprawdzenie czy możemy użyć shell_exec + zip/tar
function canUseShell() {
return function_exists('shell_exec') && !in_array('shell_exec', explode(',', ini_get('disable_functions')));
}
function commandAvailable($cmd) {
$check = shell_exec("command -v $cmd 2>/dev/null");
return !empty($check);
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
header('Content-Type: application/json');
$action = $_POST['action'] ?? '';
if ($action === 'init') {
$filename = 'backup_' . date("Ymd_His");
$response = ['success' => false];
if (canUseShell()) {
if (commandAvailable('tar')) {
$tarName = "$filename.tar";
shell_exec("tar -cf $tarName .");
if (file_exists($tarName)) {
$response = [
'success' => true,
'method' => 'shell_tar',
'file' => $tarName
];
echo json_encode($response);
exit;
}
} elseif (commandAvailable('zip')) {
$zipName = "$filename.zip";
shell_exec("zip -r $zipName . -x '*backup_*.zip' '*.git*' 'node_modules/*' 'vendor/*'");
if (file_exists($zipName)) {
$response = [
'success' => true,
'method' => 'shell_zip',
'file' => $zipName
];
echo json_encode($response);
exit;
}
}
}
// Jeśli nie ma shell_exec lub zip/tar — fallback na ZipArchive krok po kroku
$zipName = "$filename.zip";
$zipPath = __DIR__ . '/' . $zipName;
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator(__DIR__, RecursiveDirectoryIterator::SKIP_DOTS)
);
$files = [];
foreach ($iterator as $file) {
$path = $file->getPathname();
if (strpos($path, $zipName) !== false) continue;
$files[] = $path;
}
$zip = new ZipArchive();
if ($zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
echo json_encode(['success' => false, 'message' => 'Nie można utworzyć ZIP']);
exit;
}
$zip->addEmptyDir('__INIT__');
$zip->close();
file_put_contents(TMP_FILE, json_encode([
'method' => 'php_zip',
'files' => $files,
'index' => 0,
'zipfile' => $zipPath,
'zipname' => $zipName
]));
echo json_encode([
'success' => true,
'method' => 'php_zip'
]);
exit;
}
if ($action === 'step') {
if (!file_exists(TMP_FILE)) {
echo json_encode(['success' => false, 'message' => 'Brak danych tymczasowych']);
exit;
}
$data = json_decode(file_get_contents(TMP_FILE), true);
$files = $data['files'];
$index = $data['index'];
$zipfile = $data['zipfile'];
$zipname = $data['zipname'];
$zip = new ZipArchive();
if ($zip->open($zipfile) !== true) {
echo json_encode(['success' => false, 'message' => 'Nie można otworzyć ZIP']);
exit;
}
$end = min($index + FILES_PER_STEP, count($files));
for ($i = $index; $i < $end; $i++) {
$filePath = $files[$i];
if (is_file($filePath)) {
$localname = substr($filePath, strlen(__DIR__) + 1);
$zip->addFile($filePath, $localname);
}
}
$zip->close();
$data['index'] = $end;
file_put_contents(TMP_FILE, json_encode($data));
$progress = $end / count($files);
echo json_encode([
'success' => true,
'method' => 'php_zip',
'progress' => round($progress * 100, 2),
'done' => $end >= count($files),
'zipfile' => $zipname
]);
exit;
}
}
?>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Backup dynamiczny</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<style>
#progress-bar {
width: 100%;
background-color: #eee;
border: 1px solid #ccc;
margin-top: 10px;
}
#progress-bar-inner {
height: 20px;
width: 0;
background-color: #4caf50;
text-align: center;
color: white;
line-height: 20px;
transition: width 0.3s ease;
}
</style>
</head>
<body>
<h2>Automatyczny backup plików</h2>
<button id="start-backup">Rozpocznij</button>
<div id="progress-bar" style="display:none;">
<div id="progress-bar-inner">0.00%</div>
</div>
<div id="status"></div>
<script>
$(document).ready(function(){
let method = '';
let zipFile = '';
$("#start-backup").click(function(){
$("#status").text("Inicjalizowanie...");
$("#progress-bar").show();
$("#progress-bar-inner").css("width", "0%").text("0.00%");
$.post("", { action: "init" }, function(res){
if (!res.success) {
$("#status").text("Błąd: " + res.message);
return;
}
method = res.method;
if (method === 'shell_tar' || method === 'shell_zip') {
$("#progress-bar-inner").css("width", "100%").text("100%");
$("#status").html("✅ Gotowe! <a href='" + res.file + "' download>Pobierz</a>");
} else if (method === 'php_zip') {
doStep();
}
}, "json");
});
function doStep() {
$.post("", { action: "step" }, function(res){
if (res.success && res.method === 'php_zip') {
let percent = parseFloat(res.progress).toFixed(2);
$("#progress-bar-inner").css("width", percent + "%").text(percent + "%");
if (res.done) {
$("#status").html("✅ Backup gotowy! <a href='" + res.zipfile + "' download>Pobierz ZIP</a>");
} else {
setTimeout(doStep, 300);
}
} else {
$("#status").text("Błąd: " + res.message);
}
}, "json");
}
});
</script>
</body>
</html>