' . htmlspecialchars((string)($translations['backup_access_denied'] ?? 'Accès refusé.'), ENT_QUOTES, 'UTF-8') . '
'; return; } if (!isset($pdo)) { $db=realpath(__DIR__.'/../../includes/db.php'); if($db) require_once $db; } if (!isset($pdo) || !($pdo instanceof PDO)) { echo '
' . htmlspecialchars((string)($translations['backup_db_unavailable'] ?? 'DB indisponible.'), ENT_QUOTES, 'UTF-8') . '
'; return; } try{$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);}catch(Throwable){} require_once __DIR__.'/_lib_audit.php'; // reauth (10 min) $mustReauth=function(int $ttl=600){$t=(int)($_SESSION['admin_reauth_at']??0);return ($t===0||(time()-$t)>$ttl);}; if ($mustReauth()){ $qs=http_build_query(['page'=>'reauth','redir'=>($_SERVER['REQUEST_URI']??'index.php?page=maintenance')]); header('Location:?'.$qs); exit; } $e=static fn($s)=>htmlspecialchars((string)$s,ENT_QUOTES,'UTF-8'); if (empty($_SESSION['csrf_token'])) $_SESSION['csrf_token']=bin2hex(random_bytes(32)); $CSRF=$_SESSION['csrf_token']; $siteRoot=realpath(__DIR__.'/../../'); $backupDir=$siteRoot.'/backups/db'; @is_dir($backupDir) || @mkdir($backupDir,0755,true); $msg=null; $ok=null; // Params $retentionDays = max(0,(int)($_POST['retention'] ?? ($_GET['retention'] ?? 30))); $useGzip = true; if ($_SERVER['REQUEST_METHOD']==='POST') { if (!hash_equals($CSRF, $_POST['csrf'] ?? '')) { $msg = (string)($translations['backup_csrf_invalid'] ?? 'CSRF invalide.'); } else { $act = $_POST['action'] ?? ''; if ($act==='create') { // Dump via PDO (fallback si mysqldump non dispo) $dbName = $pdo->query("SELECT DATABASE()")->fetchColumn(); $fname = 'db_'.$dbName.'_'.date('Ymd_His').'.sql'; $tmp = $backupDir.'/'.$fname; // --- export --- $fh = @fopen($tmp,'wb'); if(!$fh){ $tpl = (string)($translations['backup_cannot_write_dir'] ?? "Impossible d'écrire dans {DIR}"); $msg = str_replace('{DIR}', (string)$backupDir, $tpl); } else { fwrite($fh, "-- Backup of `$dbName` on ".date('c')."\nSET FOREIGN_KEY_CHECKS=0;\n"); // tables $tables = $pdo->query("SHOW FULL TABLES WHERE Table_Type='BASE TABLE'")->fetchAll(PDO::FETCH_COLUMN); foreach ($tables as $t) { // DDL $row = $pdo->query("SHOW CREATE TABLE `$t`")->fetch(PDO::FETCH_ASSOC); fwrite($fh, "\n-- Structure `$t`\nDROP TABLE IF EXISTS `$t`;\n".$row['Create Table'].";\n"); // DML $st = $pdo->query("SELECT * FROM `$t`", PDO::FETCH_ASSOC); $cols = array_map(fn($c)=>'`'.$c.'`', array_keys($st->fetch() ?: [])); if ($cols) { // Refaire la requête pour ne pas “perdre” la première ligne $st = $pdo->query("SELECT * FROM `$t`", PDO::FETCH_ASSOC); $colList = implode(',', $cols); $placeholders = '(' . implode(',', array_fill(0, count($cols), '?')) . ')'; $batch=[]; $n=0; foreach($st as $row){ $vals = array_values($row); $vals = array_map(function($v) use($pdo){ return isset($v)?$pdo->quote((string)$v):"NULL"; }, $vals); $batch[] = '('.implode(',', $vals).')'; if (++$n % 200 === 0) { fwrite($fh, "INSERT INTO `$t` ($colList) VALUES\n".implode(",\n",$batch).";\n"); $batch=[]; } } if ($batch){ fwrite($fh, "INSERT INTO `$t` ($colList) VALUES\n".implode(",\n",$batch).";\n"); } } } fwrite($fh, "SET FOREIGN_KEY_CHECKS=1;\n"); fclose($fh); // gzip if ($useGzip) { $gz = $tmp.'.gz'; $gzh = gzopen($gz,'wb9'); $src = fopen($tmp,'rb'); while(!feof($src)){ gzwrite($gzh, fread($src, 1<<20)); } fclose($src); gzclose($gzh); @unlink($tmp); $final=$gz; } else { $final=$tmp; } $tpl = (string)($translations['backup_created_ok'] ?? 'Sauvegarde créée : {FILE}'); $ok = str_replace('{FILE}', basename($final), $tpl); AdminAudit::log($pdo, [ 'admin_id'=>(int)($_SESSION['user_id']??0), 'action'=>'backup_create', 'scope'=>'maintenance', 'meta'=>['file'=>basename($final),'dir'=>'backups/db'] ]); } } elseif ($act==='prune') { $cut = time()-($retentionDays*86400); $n=0; foreach (glob($backupDir.'/db_*.sql*') as $f){ if(filemtime($f)<$cut){ @unlink($f); $n++; } } $tpl = (string)($translations['backup_retention_applied'] ?? 'Rétention appliquée : {N} fichier(s) supprimé(s) (> {D} j)'); $ok = str_replace(['{N}','{D}'], [(string)$n, (string)$retentionDays], $tpl); AdminAudit::log($pdo, [ 'admin_id'=>(int)($_SESSION['user_id']??0), 'action'=>'backup_prune', 'scope'=>'maintenance', 'meta'=>['retention_days'=>$retentionDays] ]); } } } // Liste $files = array_map('basename', glob($backupDir.'/db_*.sql*') ?: []); usort($files, fn($a,$b)=>strcmp($b,$a)); // plus récent d'abord ?>

KB