Siteβ―Builder
Editing:
import.php
writable 0666
<?php /* MelanieΒ AI β Site Importer 1.2 Robust tempβdir handling (avoids 500 on shared hosts) -------------------------------------------------------------------- */ /* ββ security gate βββββββββββββββββββββββββββββββββββββββββββββββ */ require_once $_SERVER['DOCUMENT_ROOT'].'/members/lib/auth.php'; require_login(); if (current_user()['role'] !== 'admin') forbidden_page(); if (session_status() === PHP_SESSION_NONE) session_start(); /* ββ show errors on screen (remove on production) βββββββββββββββ */ ini_set('display_errors', 1); error_reporting(E_ALL); /* ββ temp directory logic βββββββββββββββββββββββββββββββββββββββ */ $systemTmp = sys_get_temp_dir(); $localTmp = __DIR__ . '/tmp'; if (is_writable($systemTmp)) { define('IMP_TMP', $systemTmp); $tmpMsg = "Using system tmp: $systemTmp"; } else { if (!is_dir($localTmp)) mkdir($localTmp, 0755, true); if (!is_writable($localTmp)) { die('<h2 style="color:#ff8383">Neither /tmp nor ./tmp is writable. Please make one writable.</h2>'); } define('IMP_TMP', $localTmp); $tmpMsg = "Using local tmp: $localTmp"; } /* ββ other config βββββββββββββββββββββββββββββββββββββββββββββββ */ define('MAX_ZIP_SIZE', 50 * 1024 * 1024); // 50Β MB define('WEB_ROOT', realpath($_SERVER['DOCUMENT_ROOT'])); /* ββ helpers ββββββββββββββββββββββββββββββββββββββββββββββββββββ */ function clean($p) { return ltrim(str_replace(['\\', '..'], ['/', ''], $p), '/'); } function nice($b) { return $b > 1048576 ? round($b / 1048576, 1) . ' MB' : round($b / 1024) . ' KB'; } /* ββ session state βββββββββββββββββββββββββββββββββββββββββββββ */ $state =& $_SESSION['imp']; if (!$state) $state = ['step' => 'upload']; //////////////////////////////////////////////////////////////////////// // STEP 1 β scan archive //////////////////////////////////////////////////////////////////////// if (isset($_POST['step']) && $_POST['step'] === 'scan') { if (($_FILES['zip']['error'] ?? 1) !== 0) die('Upload failed.'); if ($_FILES['zip']['size'] > MAX_ZIP_SIZE) die('File too large.'); $zipTmp = IMP_TMP . '/imp_' . bin2hex(random_bytes(4)) . '.zip'; if (!move_uploaded_file($_FILES['zip']['tmp_name'], $zipTmp)) die('Cannot move uploaded file.'); $folder = clean($_POST['folder'] ?? ''); if (!$folder) die('No target folder specified.'); $extract = WEB_ROOT . '/' . $folder; $zip = new ZipArchive; if ($zip->open($zipTmp) !== true) die('Bad ZIP file.'); $list = []; for ($i = 0; $i < $zip->numFiles; $i++) { $name = clean($zip->getNameIndex($i)); if (!$name || substr($name, -1) === '/') continue; $list[] = [ 'name' => $name, 'size' => $zip->statIndex($i)['size'], 'exists' => file_exists($extract . '/' . $name) ]; } $zip->close(); // save manifest to a tmp json file $meta = IMP_TMP . '/imp_' . bin2hex(random_bytes(4)) . '.json'; file_put_contents($meta, json_encode($list)); $state = [ 'step' => 'review', 'zip' => $zipTmp, 'meta' => $meta, 'extract' => $extract ]; } //////////////////////////////////////////////////////////////////////// // STEP 2 β extract selected //////////////////////////////////////////////////////////////////////// if (isset($_POST['step']) && $_POST['step'] === 'import' && $state['step'] === 'review') { $pick = array_map('intval', $_POST['pick'] ?? []); $manifest = json_decode(file_get_contents($state['meta']), true) ?? []; $zip = new ZipArchive; $zip->open($state['zip']); foreach ($pick as $idx) { if (!isset($manifest[$idx])) continue; $entry = $manifest[$idx]; $src = $zip->getStream($entry['name']); if (!$src) continue; $destPath = $state['extract'] . '/' . $entry['name']; $dir = dirname($destPath); if (!is_dir($dir)) mkdir($dir, 0755, true); $dest = fopen($destPath, 'w'); stream_copy_to_stream($src, $dest); fclose($src); fclose($dest); chmod($destPath, 0644); } $zip->close(); unlink($state['zip']); unlink($state['meta']); $state = ['step' => 'done', 'extract' => $state['extract']]; } //////////////////////////////////////////////////////////////////////// // HTML //////////////////////////////////////////////////////////////////////// ?><!DOCTYPE html><html><head><meta charset="utf-8"> <title>Site Importer</title><meta name="viewport" content="width=device-width,initial-scale=1"> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap" rel="stylesheet"> <style> :root{--bg:#101119;--panel:#1c1d27;--accent:#ff4ecd;--fg:#e9e9f2;--radius:12px;font-family:Inter,system-ui,sans-serif} body{margin:0;min-height:100vh;background:var(--bg);color:var(--fg);display:flex;flex-direction:column} h1{margin:0;background:var(--panel);padding:1rem 2rem;font-size:1.4rem} main{flex:1;display:flex;justify-content:center;align-items:flex-start;padding:2rem} section{background:var(--panel);padding:1.6rem 2rem;border-radius:var(--radius);min-width:340px;max-width:680px} input[type=file],input[type=text]{width:100%;padding:.5rem;margin:.4rem 0;border:none;border-radius:8px;background:#2b2c3b;color:var(--fg)} button{background:var(--accent);border:none;color:#fff;padding:.6rem 1.4rem;border-radius:40px;font-weight:600;cursor:pointer} table{width:100%;border-collapse:collapse;font-size:.9rem;margin-top:1rem} td,th{padding:.35rem .5rem} th{text-align:left;font-weight:600} tr:nth-child(even){background:#23242f} .exists{color:#ffb063} .banner{padding:.4rem .8rem;border-radius:6px;margin-bottom:.8rem;font-size:.85rem} .ok{background:#2c4332;color:#c8f8c8} .err{background:#5b2626;color:#ffd0d0} </style></head><body> <h1>Site Importer</h1><main><section> <div class="banner ok"><?=htmlspecialchars($tmpMsg)?></div> <?php if ($state['step'] === 'upload'): ?> <h2>1 Β· Upload ZIP</h2> <form method="post" enctype="multipart/form-data"> <input type="file" name="zip" accept=".zip" required> <input type="text" name="folder" placeholder="target folder (e.g. mai-myshop)" required> <p style="font-size:.8rem;opacity:.7;margin-top:0">Folder is created if it doesnβt exist.</p> <button name="step" value="scan">Scan Archive</button> </form> <?php elseif ($state['step'] === 'review'): $manifest = json_decode(file_get_contents($state['meta']), true) ?? []; ?> <h2>2 Β· Review files</h2> <form method="post"> <table><thead><tr><th></th><th>file</th><th>size</th><th></th></tr></thead><tbody> <?php foreach ($manifest as $idx => $f): ?> <tr> <td><input type="checkbox" name="pick[]" value="<?=$idx?>" <?= $f['exists'] ? '' : 'checked' ?>></td> <td><?=htmlspecialchars($f['name'])?></td> <td><?=nice($f['size'])?></td> <td><?=$f['exists']?'<span class="exists">β overwrite</span>':'β new'?></td> </tr> <?php endforeach; ?></tbody></table> <p style="font-size:.85rem;opacity:.7">Tick the files you want to extract (overwrites unchecked by default).</p> <button name="step" value="import">Import Selected</button> </form> <?php elseif ($state['step'] === 'done'): ?> <h2>Import complete β</h2> <p>Files were extracted to:<br><code><?=htmlspecialchars($state['extract'])?></code></p> <p><a href="/">Go to site</a></p> <?php endif; ?> </section></main></body></html>
Save changes
Create folder
writable 0777
Create
Cancel