
­­­­­­­­­­­­­­­­­­
<!DOCTYPE html>
<html>
<?php
declare(strict_types=1);

session_start();

error_reporting(E_ALL);
ini_set('display_errors', '0');

/*
 * 403 Private File Manager
 * Clean replacement for the corrupted/obfuscated version.
 *
 * IMPORTANT:
 * - Put this file in the directory you want to manage.
 * - All filesystem operations are restricted to that directory.
 * - Change the default password below before deployment.
 */

const APP_NAME = '403 Private File Manager';
const DEFAULT_PASSWORD = '12345';

/*
 * Files with these extensions are allowed to be edited.
 */
const EDITABLE_EXTENSIONS = [
    'txt', 'php', 'html', 'htm', 'css', 'js', 'json', 'xml',
    'md', 'log', 'ini', 'conf', 'cfg', 'yml', 'yaml',
    'sh', 'bash', 'py', 'java', 'c', 'cpp', 'h', 'sql',
    'htaccess', 'env', 'gitignore', 'lock', 'csv', 'tsv',
    'svg', 'vue', 'ts', 'jsx', 'tsx', 'rb', 'go', 'rs',
    'pl', 'lua', 'r', 'swift', 'kt', 'scala', 'dart'
];

/*
 * The managed root is the directory containing this PHP file.
 */
$ROOT = realpath(__DIR__);

if ($ROOT === false) {
    http_response_code(500);
    exit('Unable to determine application directory.');
}

/* ---------------------------------------------------------
 * Helper functions
 * --------------------------------------------------------- */

function h(mixed $value): string
{
    return htmlspecialchars(
        (string)$value,
        ENT_QUOTES | ENT_SUBSTITUTE,
        'UTF-8'
    );
}

function redirect(string $url = '?'): never
{
    header('Location: ' . $url);
    exit;
}

function isLoggedIn(): bool
{
    return isset($_SESSION['mrx_logged']) &&
           $_SESSION['mrx_logged'] === true;
}

function passwordEnabled(): bool
{
    return !empty($_SESSION['mrx_password_enabled']);
}

function setFlash(string $message, string $type = 'success'): void
{
    $_SESSION['mrx_flash'] = [
        'message' => $message,
        'type' => $type
    ];
}

function getFlash(): ?array
{
    $flash = $_SESSION['mrx_flash'] ?? null;
    unset($_SESSION['mrx_flash']);

    return is_array($flash) ? $flash : null;
}

/*
 * Convert a user-supplied path into a path relative to ROOT.
 * Returns null if the path attempts to escape ROOT.
 */
function safePath(string $input, string $root): ?string
{
    $input = trim(str_replace('\\', '/', $input));

    if ($input === '') {
        return $root;
    }

    /*
     * Remove accidental leading slash because paths are relative
     * to the file-manager root.
     */
    $input = ltrim($input, '/');

    /*
     * Reject NUL bytes.
     */
    if (strpos($input, "\0") !== false) {
        return null;
    }

    /*
     * Resolve the existing parent portion.
     */
    $candidate = $root . DIRECTORY_SEPARATOR . $input;

    /*
     * For existing files/directories, realpath gives us a canonical path.
     */
    if (file_exists($candidate) || is_link($candidate)) {
        $real = realpath($candidate);

        if ($real === false) {
            return null;
        }

        if ($real !== $root &&
            !str_starts_with($real, $root . DIRECTORY_SEPARATOR)) {
            return null;
        }

        return $real;
    }

    /*
     * For new files/folders, validate the parent directory.
     */
    $parent = realpath(dirname($candidate));

    if ($parent === false) {
        return null;
    }

    if ($parent !== $root &&
        !str_starts_with($parent, $root . DIRECTORY_SEPARATOR)) {
        return null;
    }

    return $parent . DIRECTORY_SEPARATOR . basename($candidate);
}

function relativePath(string $path, string $root): string
{
    if ($path === $root) {
        return '';
    }

    $relative = substr($path, strlen($root));

    return ltrim(str_replace(DIRECTORY_SEPARATOR, '/', $relative), '/');
}

function formatSize(int $size): string
{
    if ($size >= 1073741824) {
        return number_format($size / 1073741824, 2) . ' GB';
    }

    if ($size >= 1048576) {
        return number_format($size / 1048576, 2) . ' MB';
    }

    if ($size >= 1024) {
        return number_format($size / 1024, 2) . ' KB';
    }

    return $size . ' B';
}

function permissions(string $path): string
{
    $mode = @fileperms($path);

    if ($mode === false) {
        return '---------';
    }

    $result = '';

    $result .= ($mode & 0400) ? 'r' : '-';
    $result .= ($mode & 0200) ? 'w' : '-';
    $result .= ($mode & 0100) ? 'x' : '-';

    $result .= ($mode & 0040) ? 'r' : '-';
    $result .= ($mode & 0020) ? 'w' : '-';
    $result .= ($mode & 0010) ? 'x' : '-';

    $result .= ($mode & 0004) ? 'r' : '-';
    $result .= ($mode & 0002) ? 'w' : '-';
    $result .= ($mode & 0001) ? 'x' : '-';

    return $result;
}

function octalPermissions(string $path): string
{
    $mode = @fileperms($path);

    if ($mode === false) {
        return '0000';
    }

    return substr(sprintf('%o', $mode), -4);
}

function isEditable(string $path): bool
{
    if (!is_file($path) || !is_readable($path)) {
        return false;
    }

    $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));

    if (in_array($extension, EDITABLE_EXTENSIONS, true)) {
        return true;
    }

    $mime = @mime_content_type($path);

    return $mime === 'text/plain';
}

function deleteRecursive(string $path): bool
{
    if (is_link($path) || is_file($path)) {
        return @unlink($path);
    }

    if (!is_dir($path)) {
        return false;
    }

    $items = @scandir($path);

    if ($items === false) {
        return false;
    }

    foreach ($items as $item) {
        if ($item === '.' || $item === '..') {
            continue;
        }

        if (!deleteRecursive($path . DIRECTORY_SEPARATOR . $item)) {
            return false;
        }
    }

    return @rmdir($path);
}

function safeName(string $name): string
{
    $name = trim($name);

    /*
     * Do not allow path separators.
     */
    $name = str_replace(['/', '\\'], '', $name);

    /*
     * Remove NUL bytes.
     */
    $name = str_replace("\0", '', $name);

    return $name;
}

function breadcrumb(string $relative): array
{
    $parts = $relative === ''
        ? []
        : explode('/', trim($relative, '/'));

    $result = [
        [
            'name' => 'root',
            'path' => ''
        ]
    ];

    $current = '';

    foreach ($parts as $part) {
        if ($part === '') {
            continue;
        }

        $current .= ($current === '' ? '' : '/') . $part;

        $result[] = [
            'name' => $part,
            'path' => $current
        ];
    }

    return $result;
}

/* ---------------------------------------------------------
 * Password setup
 * --------------------------------------------------------- */

/*
 * This session flag lets the user disable/enable the login
 * without storing a password in a separate writable config.
 *
 * For a production installation, change DEFAULT_PASSWORD.
 */
if (!isset($_SESSION['mrx_password_enabled'])) {
    $_SESSION['mrx_password_enabled'] = true;
}

/* ---------------------------------------------------------
 * Authentication
 * --------------------------------------------------------- */

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $action = $_POST['action'] ?? '';

    if ($action === 'login') {
        $password = (string)($_POST['password'] ?? '');

        if (hash_equals(DEFAULT_PASSWORD, $password)) {
            session_regenerate_id(true);
            $_SESSION['mrx_logged'] = true;

            setFlash('Login successful.', 'success');
        } else {
            setFlash('Access denied — wrong password.', 'error');
        }

        redirect();
    }

    if ($action === 'logout') {
        $_SESSION = [];

        if (ini_get('session.use_cookies')) {
            $params = session_get_cookie_params();

            setcookie(
                session_name(),
                '',
                time() - 42000,
                $params['path'],
                $params['domain'],
                $params['secure'],
                $params['httponly']
            );
        }

        session_destroy();
        redirect();
    }
}

/*
 * Authentication is enabled by default.
 */
if (!isLoggedIn()) {
    $flash = getFlash();

    ?>
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title><?= h(APP_NAME) ?></title>

        <style>
            :root {
                --bg: #05050a;
                --bg2: #0c0c14;
                --bg3: #12121e;
                --green: #00ff9f;
                --cyan: #00e5ff;
                --pink: #ff2e88;
                --purple: #b44aff;
                --text: #e0e0ff;
                --muted: #8888aa;
                --danger: #ff3366;
                --border: rgba(0, 229, 255, .20);
            }

            * {
                box-sizing: border-box;
            }

            body {
                margin: 0;
                min-height: 100vh;
                display: flex;
                align-items: center;
                justify-content: center;
                padding: 20px;
                color: var(--text);
                background:
                    radial-gradient(
                        ellipse at 20% 0%,
                        rgba(0,229,255,.08),
                        transparent 40%
                    ),
                    radial-gradient(
                        ellipse at 80% 100%,
                        rgba(180,74,255,.08),
                        transparent 40%
                    ),
                    #05050a;
                font-family:
                    Inter,
                    "Segoe UI",
                    system-ui,
                    sans-serif;
            }

            .login {
                width: 100%;
                max-width: 430px;
                padding: 36px;
                background: var(--bg2);
                border: 1px solid var(--border);
                border-radius: 16px;
                box-shadow:
                    0 0 30px rgba(0,229,255,.10),
                    0 0 60px rgba(180,74,255,.08);
            }

            h1 {
                margin: 0 0 8px;
                text-align: center;
                font-size: 25px;
                background:
                    linear-gradient(
                        90deg,
                        var(--green),
                        var(--cyan),
                        var(--pink)
                    );
                -webkit-background-clip: text;
                background-clip: text;
                color: transparent;
            }

            .subtitle {
                text-align: center;
                color: var(--muted);
                margin-bottom: 28px;
            }

            input {
                width: 100%;
                padding: 13px 14px;
                margin-bottom: 14px;
                border: 1px solid var(--border);
                border-radius: 8px;
                background: var(--bg3);
                color: var(--text);
                outline: none;
                font-size: 15px;
            }

            input:focus {
                border-color: var(--green);
            }

            button {
                width: 100%;
                padding: 13px;
                border: 0;
                border-radius: 8px;
                background:
                    linear-gradient(
                        90deg,
                        var(--green),
                        var(--cyan)
                    );
                color: #000;
                font-weight: 700;
                cursor: pointer;
            }

            .flash {
                padding: 11px 13px;
                margin-bottom: 16px;
                border-radius: 8px;
                background: rgba(255,51,102,.12);
                border: 1px solid var(--danger);
                color: var(--danger);
            }
        </style>
    </head>

    <body>
        <div class="login">
            <h1><?= h(APP_NAME) ?></h1>
            <div class="subtitle">Protected Edition</div>

            <?php if ($flash): ?>
                <div class="flash"><?= h($flash['message']) ?></div>
            <?php endif; ?>

            <form method="post">
                <input type="hidden" name="action" value="login">

                <input
                    type="password"
                    name="password"
                    placeholder="Enter password"
                    autocomplete="current-password"
                    autofocus
                    required
                >

                <button type="submit">
                    UNLOCK SYSTEM
                </button>
            </form>
        </div>
    </body>
    </html>
    <?php
    exit;
}

/* ---------------------------------------------------------
 * Current directory
 * --------------------------------------------------------- */

$relativeDir = (string)($_GET['dir'] ?? '');
$currentDir = safePath($relativeDir, $ROOT);

if ($currentDir === null || !is_dir($currentDir)) {
    setFlash('Invalid directory.', 'error');
    redirect();
}

/* ---------------------------------------------------------
 * POST actions
 * --------------------------------------------------------- */

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $action = (string)($_POST['action'] ?? '');

    /*
     * Logout
     */
    if ($action === 'logout') {
        $_SESSION = [];
        session_destroy();
        redirect();
    }

    /*
     * Create folder
     */
    if ($action === 'mkdir') {
        $name = safeName((string)($_POST['folder_name'] ?? ''));

        if ($name === '' || $name === '.' || $name === '..') {
            setFlash('Invalid folder name.', 'error');
            redirect('?dir=' . urlencode($relativeDir));
        }

        $target = safePath(
            relativePath($currentDir, $ROOT) . '/' . $name,
            $ROOT
        );

        if ($target === null) {
            setFlash('Invalid folder path.', 'error');
        } elseif (file_exists($target)) {
            setFlash('A file or folder with that name already exists.', 'error');
        } elseif (@mkdir($target, 0755)) {
            setFlash('Folder created: ' . $name, 'success');
        } else {
            setFlash('Failed to create folder.', 'error');
        }

        redirect('?dir=' . urlencode($relativeDir));
    }

    /*
     * Create file
     */
    if ($action === 'newfile') {
        $name = safeName((string)($_POST['file_name'] ?? ''));

        if ($name === '' || $name === '.' || $name === '..') {
            setFlash('Invalid file name.', 'error');
            redirect('?dir=' . urlencode($relativeDir));
        }

        $target = safePath(
            relativePath($currentDir, $ROOT) . '/' . $name,
            $ROOT
        );

        if ($target === null) {
            setFlash('Invalid file path.', 'error');
        } elseif (file_exists($target)) {
            setFlash('A file or folder with that name already exists.', 'error');
        } elseif (@file_put_contents($target, '') !== false) {
            @chmod($target, 0644);
            setFlash('File created: ' . $name, 'success');
        } else {
            setFlash('Failed to create file.', 'error');
        }

        redirect('?dir=' . urlencode($relativeDir));
    }

    /*
     * Rename
     */
    if ($action === 'rename') {
        $old = (string)($_POST['old'] ?? '');
        $newName = safeName((string)($_POST['new_name'] ?? ''));

        $oldPath = safePath($old, $ROOT);

        if (
            $oldPath === null ||
            !file_exists($oldPath) ||
            $newName === '' ||
            $newName === '.' ||
            $newName === '..'
        ) {
            setFlash('Invalid rename request.', 'error');
            redirect('?dir=' . urlencode($relativeDir));
        }

        $newPath = dirname($oldPath) . DIRECTORY_SEPARATOR . $newName;

        if (file_exists($newPath)) {
            setFlash('A file or folder with that name already exists.', 'error');
        } elseif (@rename($oldPath, $newPath)) {
            setFlash('Renamed successfully.', 'success');
        } else {
            setFlash('Rename failed.', 'error');
        }

        redirect('?dir=' . urlencode($relativeDir));
    }

    /*
     * Delete
     */
    if ($action === 'delete') {
        $targetInput = (string)($_POST['target'] ?? '');
        $target = safePath($targetInput, $ROOT);

        /*
         * Never allow deletion of the root directory.
         */
        if (
            $target === null ||
            !file_exists($target) ||
            $target === $ROOT
        ) {
            setFlash('Invalid delete request.', 'error');
            redirect('?dir=' . urlencode($relativeDir));
        }

        /*
         * Never allow deletion of this PHP application itself.
         */
        $self = realpath(__FILE__);

        if ($self !== false && realpath($target) === $self) {
            setFlash(
                'DELETE PROTECTION: Cannot delete the File Manager itself.',
                'error'
            );

            redirect('?dir=' . urlencode($relativeDir));
        }

        if (@deleteRecursive($target)) {
            setFlash(
                'Deleted successfully: ' . basename($target),
                'success'
            );
        } else {
            setFlash('Delete failed.', 'error');
        }

        redirect('?dir=' . urlencode($relativeDir));
    }

    /*
     * Chmod
     */
    if ($action === 'chmod') {
        $targetInput = (string)($_POST['target'] ?? '');
        $modeInput = trim((string)($_POST['mode'] ?? ''));

        $target = safePath($targetInput, $ROOT);

        if (
            $target === null ||
            !file_exists($target) ||
            !preg_match('/^[0-7]{3,4}$/', $modeInput)
        ) {
            setFlash('Invalid permission mode.', 'error');
            redirect('?dir=' . urlencode($relativeDir));
        }

        $mode = octdec($modeInput);

        if (@chmod($target, $mode)) {
            setFlash(
                'Permissions changed to ' . $modeInput,
                'success'
            );
        } else {
            setFlash(
                'Chmod failed (permission denied).',
                'error'
            );
        }

        redirect('?dir=' . urlencode($relativeDir));
    }

    /*
     * Save edited file
     */
    if ($action === 'save') {
        $fileInput = (string)($_POST['file'] ?? '');
        $content = (string)($_POST['content'] ?? '');

        $file = safePath($fileInput, $ROOT);

        if (
            $file === null ||
            !is_file($file) ||
            !is_writable($file) ||
            !isEditable($file)
        ) {
            setFlash(
                'Cannot save this file.',
                'error'
            );

            redirect('?dir=' . urlencode($relativeDir));
        }

        /*
         * Prevent this application from being overwritten.
         */
        if (realpath($file) === realpath(__FILE__)) {
            setFlash(
                'Cannot overwrite the File Manager itself.',
                'error'
            );

            redirect('?dir=' . urlencode($relativeDir));
        }

        if (@file_put_contents($file, $content, LOCK_EX) !== false) {
            setFlash('File saved successfully.', 'success');
        } else {
            setFlash('Save failed.', 'error');
        }

        redirect(
            '?dir=' . urlencode(dirname($fileInput))
        );
    }

    /*
     * Upload
     */
    if ($action === 'upload') {
        if (!isset($_FILES['files'])) {
            setFlash('No files received.', 'error');
            redirect('?dir=' . urlencode($relativeDir));
        }

        $files = $_FILES['files'];

        $count = is_array($files['name'])
            ? count($files['name'])
            : 1;

        $success = 0;
        $errors = [];

        for ($i = 0; $i < $count; $i++) {
            $name = is_array($files['name'])
                ? (string)$files['name'][$i]
                : (string)$files['name'];

            $tmp = is_array($files['tmp_name'])
                ? (string)$files['tmp_name'][$i]
                : (string)$files['tmp_name'];

            $error = is_array($files['error'])
                ? (int)$files['error'][$i]
                : (int)$files['error'];

            $name = safeName(basename($name));

            if ($name === '') {
                $errors[] = 'Invalid filename.';
                continue;
            }

            if ($error !== UPLOAD_ERR_OK) {
                $errors[] = $name . ': upload error ' . $error;
                continue;
            }

            if (!is_uploaded_file($tmp)) {
                $errors[] = $name . ': invalid upload.';
                continue;
            }

            $destination = $currentDir . DIRECTORY_SEPARATOR . $name;

            if (
                realpath($destination) !== false &&
                realpath($destination) === realpath(__FILE__)
            ) {
                $errors[] = $name . ': cannot overwrite File Manager.';
                continue;
            }

            if (@move_uploaded_file($tmp, $destination)) {
                @chmod($destination, 0644);
                $success++;
            } else {
                $errors[] = $name . ': upload failed.';
            }
        }

        if ($success > 0) {
            $message = $success . ' file(s) uploaded successfully.';

            if ($errors) {
                $message .= ' ' . implode(' ', $errors);
            }

            setFlash($message, 'success');
        } else {
            setFlash(
                $errors
                    ? implode(' ', $errors)
                    : 'No files were uploaded.',
                'error'
            );
        }

        redirect('?dir=' . urlencode($relativeDir));
    }
}

/* ---------------------------------------------------------
 * Download
 * --------------------------------------------------------- */

if (isset($_GET['download'])) {
    $downloadInput = (string)$_GET['download'];
    $file = safePath($downloadInput, $ROOT);

    if (
        $file === null ||
        !is_file($file) ||
        !is_readable($file)
    ) {
        http_response_code(404);
        exit('File not found.');
    }

    $filename = basename($file);

    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename="' .
        addcslashes($filename, "\"\\") . '"');
    header('Content-Length: ' . filesize($file));
    header('Cache-Control: no-cache, no-store, must-revalidate');
    header('Pragma: public');
    header('Expires: 0');

    readfile($file);
    exit;
}

/* ---------------------------------------------------------
 * Edit file
 * --------------------------------------------------------- */

$editPath = null;
$editContent = '';

if (isset($_GET['edit'])) {
    $editInput = (string)$_GET['edit'];
    $candidate = safePath($editInput, $ROOT);

    if (
        $candidate !== null &&
        is_file($candidate) &&
        is_readable($candidate) &&
        isEditable($candidate)
    ) {
        $editPath = $candidate;
        $editContent = (string)@file_get_contents($candidate);
    } else {
        setFlash(
            'Cannot edit this file. It is binary, unreadable, or unsupported.',
            'error'
        );
    }
}

/* ---------------------------------------------------------
 * Directory listing
 * --------------------------------------------------------- */

$items = @scandir($currentDir);

if ($items === false) {
    $items = [];
}

$directories = [];
$files = [];

foreach ($items as $name) {
    if ($name === '.' || $name === '..') {
        continue;
    }

    $path = $currentDir . DIRECTORY_SEPARATOR . $name;

    $item = [
        'name' => $name,
        'path' => relativePath($path, $ROOT),
        'is_dir' => is_dir($path),
        'size' => is_file($path)
            ? formatSize((int)(@filesize($path) ?: 0))
            : '—',
        'permissions' => permissions($path),
        'octal' => octalPermissions($path),
        'modified' => @filemtime($path)
            ? date('Y-m-d H:i', (int)filemtime($path))
            : '—',
        'writable' => is_writable($path),
        'editable' => isEditable($path)
    ];

    if ($item['is_dir']) {
        $directories[] = $item;
    } else {
        $files[] = $item;
    }
}

usort(
    $directories,
    fn(array $a, array $b): int =>
        strcasecmp($a['name'], $b['name'])
);

usort(
    $files,
    fn(array $a, array $b): int =>
        strcasecmp($a['name'], $b['name'])
);

$items = array_merge($directories, $files);

$flash = getFlash();
$crumbs = breadcrumb($relativeDir);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">

<title><?= h(APP_NAME) ?></title>

<style>
:root {
    --bg: #05050a;
    --bg2: #0c0c14;
    --bg3: #12121e;
    --green: #00ff9f;
    --cyan: #00e5ff;
    --pink: #ff2e88;
    --purple: #b44aff;
    --yellow: #ffe66d;
    --text: #e0e0ff;
    --muted: #8888aa;
    --danger: #ff3366;
    --border: rgba(0,229,255,.20);
}

* {
    box-sizing: border-box;
}

body {
    margin: 0;
    min-height: 100vh;
    color: var(--text);
    background:
        radial-gradient(
            ellipse at 20% 0%,
            rgba(0,229,255,.08),
            transparent 40%
        ),
        radial-gradient(
            ellipse at 80% 100%,
            rgba(180,74,255,.08),
            transparent 40%
        ),
        linear-gradient(180deg,#05050a,#0a0a12);
    font-family:
        Inter,
        "Segoe UI",
        system-ui,
        sans-serif;
}

a {
    color: inherit;
}

.banner {
    padding: 20px;
    text-align: center;
    background: #090912;
    border-bottom: 1px solid var(--border);
}

.banner h1 {
    margin: 0 0 5px;
    font-size: 27px;
    letter-spacing: 1px;
    background:
        linear-gradient(
            90deg,
            var(--green),
            var(--cyan),
            var(--pink),
            var(--purple)
        );
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}

.banner p {
    margin: 0;
    color: var(--muted);
    font-size: 13px;
}

.container {
    width: min(1400px, 100%);
    margin: auto;
    padding: 18px;
}

.topbar {
    display: flex;
    gap: 12px;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    margin-bottom: 16px;
}

.path {
    display: flex;
    gap: 5px;
    align-items: center;
    flex-wrap: wrap;
    font-family: monospace;
}

.path a {
    padding: 4px 7px;
    border-radius: 5px;
    color: var(--cyan);
    text-decoration: none;
}

.path a:hover {
    background: rgba(0,229,255,.1);
}

.actions {
    display: flex;
    gap: 7px;
    flex-wrap: wrap;
}

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    padding: 8px 12px;
    border: 1px solid var(--border);
    border-radius: 7px;
    background: transparent;
    color: var(--cyan);
    text-decoration: none;
    cursor: pointer;
    font-size: 13px;
}

.btn:hover {
    border-color: var(--cyan);
    background: rgba(0,229,255,.08);
}

.btn-primary {
    border: 0;
    color: #000;
    background: linear-gradient(
        90deg,
        var(--green),
        var(--cyan)
    );
    font-weight: 700;
}

.btn-danger {
    border: 0;
    color: #fff;
    background: linear-gradient(
        90deg,
        #ff3366,
        #ff5577
    );
}

.btn-small {
    padding: 5px 8px;
    font-size: 12px;
}

.panel {
    padding: 16px;
    margin-bottom: 16px;
    background: var(--bg2);
    border: 1px solid var(--border);
    border-radius: 12px;
}

.panel h2,
.panel h3 {
    margin-top: 0;
    color: var(--green);
}

.tools {
    display: grid;
    grid-template-columns:
        repeat(auto-fit,minmax(280px,1fr));
    gap: 16px;
}

.form-row {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    margin-top: 10px;
}

input[type="text"],
input[type="password"],
textarea {
    border: 1px solid var(--border);
    border-radius: 7px;
    background: var(--bg3);
    color: var(--text);
    padding: 9px 11px;
    outline: none;
}

input[type="text"]:focus,
input[type="password"]:focus,
textarea:focus {
    border-color: var(--cyan);
}

input[type="text"] {
    min-width: 180px;
}

.upload {
    padding: 25px;
    text-align: center;
    border: 2px dashed rgba(0,229,255,.25);
    border-radius: 10px;
    cursor: pointer;
}

.upload:hover {
    border-color: var(--green);
    background: rgba(0,255,159,.04);
}

.upload input {
    display: none;
}

.flash {
    margin-bottom: 16px;
    padding: 12px 14px;
    border-radius: 8px;
}

.flash.success {
    color: var(--green);
    border: 1px solid var(--green);
    background: rgba(0,255,159,.08);
}

.flash.error {
    color: var(--danger);
    border: 1px solid var(--danger);
    background: rgba(255,51,102,.08);
}

.table-wrap {
    overflow-x: auto;
    background: var(--bg2);
    border: 1px solid var(--border);
    border-radius: 12px;
}

table {
    width: 100%;
    border-collapse: collapse;
    min-width: 850px;
}

th {
    padding: 11px 13px;
    text-align: left;
    color: var(--green);
    background: var(--bg3);
    border-bottom: 1px solid var(--border);
}

td {
    padding: 10px 13px;
    border-bottom: 1px solid rgba(255,255,255,.04);
}

tr:hover td {
    background: rgba(0,229,255,.025);
}

.name {
    color: var(--text);
    text-decoration: none;
    font-weight: 600;
}

.name:hover {
    color: var(--cyan);
}

.folder {
    color: var(--yellow);
}

.icon {
    display: inline-block;
    width: 24px;
}

.mono {
    font-family: monospace;
    color: var(--muted);
    font-size: 12px;
}

.inline-form {
    display: none;
    margin-top: 8px;
    padding: 8px;
    background: var(--bg3);
    border-radius: 7px;
}

.inline-form.show {
    display: block;
}

textarea {
    width: 100%;
    min-height: 500px;
    resize: vertical;
    font-family:
        "Cascadia Code",
        "Fira Code",
        Consolas,
        monospace;
    line-height: 1.5;
}

.editor-title {
    color: var(--cyan);
    margin-bottom: 10px;
}

.footer {
    padding: 30px 20px;
    text-align: center;
    color: var(--muted);
    font-size: 12px;
}

@media (max-width: 700px) {
    .container {
        padding: 10px;
    }

    .banner h1 {
        font-size: 21px;
    }

    .tools {
        grid-template-columns: 1fr;
    }
}
</style>
</head>

<body>

<div class="banner">
    <h1><?= h(APP_NAME) ?></h1>
    <p>Protected Edition</p>
</div>

<div class="container">

    <?php if ($flash): ?>
        <div class="flash <?= h($flash['type']) ?>">
            <?= h($flash['message']) ?>
        </div>
    <?php endif; ?>

    <div class="topbar">

        <div class="path">
            <span style="color:var(--muted)">PATH:</span>

            <?php foreach ($crumbs as $index => $crumb): ?>

                <?php if ($index > 0): ?>
                    <span style="color:var(--muted)">/</span>
                <?php endif; ?>

                <a href="?dir=<?= urlencode($crumb['path']) ?>">
                    <?= h($crumb['name']) ?>
                </a>

            <?php endforeach; ?>
        </div>

        <div class="actions">
            <?php if ($relativeDir !== ''): ?>
                <?php
                $parent = dirname($relativeDir);

                if ($parent === '.' || $parent === DIRECTORY_SEPARATOR) {
                    $parent = '';
                }
                ?>
                <a
                    class="btn"
                    href="?dir=<?= urlencode($parent) ?>"
                >
                    ← Parent
                </a>
            <?php endif; ?>

            <form method="post">
                <input
                    type="hidden"
                    name="action"
                    value="logout"
                >
                <button class="btn" type="submit">
                    Logout
                </button>
            </form>
        </div>

    </div>

    <div class="tools">

        <!-- Upload -->

        <div class="panel">

            <h3>📤 Upload Files</h3>

            <form
                method="post"
                enctype="multipart/form-data"
            >

                <input
                    type="hidden"
                    name="action"
                    value="upload"
                >

                <label class="upload">
                    <div style="font-size:28px">📁</div>
                    <div>
                        Click to select files
                    </div>

                    <small style="color:var(--muted)">
                        Multiple files supported
                    </small>

                    <input
                        type="file"
                        name="files[]"
                        multiple
                    >
                </label>

                <div class="form-row">
                    <button
                        class="btn btn-primary"
                        type="submit"
                    >
                        Upload
                    </button>
                </div>

            </form>

        </div>

        <!-- Create -->

        <div class="panel">

            <h3>📁 Create New</h3>

            <form method="post" class="form-row">

                <input
                    type="hidden"
                    name="action"
                    value="mkdir"
                >

                <input
                    type="text"
                    name="folder_name"
                    placeholder="Folder name"
                    required
                >

                <button
                    class="btn btn-primary"
                    type="submit"
                >
                    + Folder
                </button>

            </form>

            <form
                method="post"
                class="form-row"
            >

                <input
                    type="hidden"
                    name="action"
                    value="newfile"
                >

                <input
                    type="text"
                    name="file_name"
                    placeholder="File name"
                    required
                >

                <button
                    class="btn btn-primary"
                    type="submit"
                >
                    + File
                </button>

            </form>

        </div>

    </div>

    <?php if ($editPath !== null): ?>

        <div class="panel">

            <h3 class="editor-title">
                ✏️ Editing:
                <?= h(basename($editPath)) ?>
            </h3>

            <form method="post">

                <input
                    type="hidden"
                    name="action"
                    value="save"
                >

                <input
                    type="hidden"
                    name="file"
                    value="<?= h(relativePath($editPath, $ROOT)) ?>"
                >

                <textarea
                    name="content"
                    spellcheck="false"
                ><?= h($editContent) ?></textarea>

                <div class="form-row">

                    <button
                        class="btn btn-primary"
                        type="submit"
                    >
                        💾 Save Changes
                    </button>

                    <a
                        class="btn"
                        href="?dir=<?= urlencode($relativeDir) ?>"
                    >
                        Cancel
                    </a>

                </div>

            </form>

        </div>

    <?php endif; ?>

    <!-- File list -->

    <div class="table-wrap">

        <table>

            <thead>
                <tr>
                    <th>Name</th>
                    <th>Size</th>
                    <th>Permissions</th>
                    <th>Modified</th>
                    <th>Actions</th>
                </tr>
            </thead>

            <tbody>

            <?php if ($relativeDir !== ''): ?>

                <?php
                $parent = dirname($relativeDir);

                if ($parent === '.' || $parent === DIRECTORY_SEPARATOR) {
                    $parent = '';
                }
                ?>

                <tr>
                    <td colspan="5">
                        <a
                            class="name folder"
                            href="?dir=<?= urlencode($parent) ?>"
                        >
                            📁 ..
                        </a>
                    </td>
                </tr>

            <?php endif; ?>

            <?php if (!$items): ?>

                <tr>
                    <td
                        colspan="5"
                        style="
                            text-align:center;
                            color:var(--muted);
                            padding:30px;
                        "
                    >
                        Directory is empty.
                    </td>
                </tr>

            <?php endif; ?>

            <?php foreach ($items as $item): ?>

                <tr>

                    <td>

                        <?php if ($item['is_dir']): ?>

                            <span class="icon">📁</span>

                            <a
                                class="name folder"
                                href="?dir=<?= urlencode($item['path']) ?>"
                            >
                                <?= h($item['name']) ?>
                            </a>

                        <?php else: ?>

                            <span class="icon">📄</span>

                            <?php if ($item['editable']): ?>

                                <a
                                    class="name"
                                    href="?edit=<?= urlencode($item['path']) ?>"
                                >
                                    <?= h($item['name']) ?>
                                </a>

                            <?php else: ?>

                                <span>
                                    <?= h($item['name']) ?>
                                </span>

                            <?php endif; ?>

                        <?php endif; ?>

                    </td>

                    <td>
                        <?= h($item['size']) ?>
                    </td>

                    <td class="mono">

                        <?= h($item['permissions']) ?>

                        <br>

                        <small>
                            <?= h($item['octal']) ?>
                        </small>

                    </td>

                    <td class="mono">
                        <?= h($item['modified']) ?>
                    </td>

                    <td>

                        <div class="actions">

                            <?php if (!$item['is_dir']): ?>

                                <a
                                    class="btn btn-small"
                                    href="?download=<?= urlencode($item['path']) ?>"
                                >
                                    ⬇ Download
                                </a>

                                <?php if ($item['editable']): ?>

                                    <a
                                        class="btn btn-small"
                                        href="?edit=<?= urlencode($item['path']) ?>"
                                    >
                                        ✏️ Edit
                                    </a>

                                <?php endif; ?>

                            <?php endif; ?>

                            <!-- Rename -->

                            <button
                                type="button"
                                class="btn btn-small"
                                onclick="toggleForm('rename-<?= md5($item['path']) ?>')"
                            >
                                ✏️ Rename
                            </button>

                            <!-- Chmod -->

                            <button
                                type="button"
                                class="btn btn-small"
                                onclick="toggleForm('chmod-<?= md5($item['path']) ?>')"
                            >
                                🔐 Chmod
                            </button>

                            <!-- Delete -->

                            <form
                                method="post"
                                onsubmit="return confirm(
                                    'Are you sure you want to permanently delete <?= h(addslashes($item['name'])) ?>?'
                                );"
                            >

                                <input
                                    type="hidden"
                                    name="action"
                                    value="delete"
                                >

                                <input
                                    type="hidden"
                                    name="target"
                                    value="<?= h($item['path']) ?>"
                                >

                                <button
                                    class="btn btn-danger btn-small"
                                    type="submit"
                                >
                                    🗑 Delete
                                </button>

                            </form>

                        </div>

                        <!-- Rename form -->

                        <div
                            class="inline-form"
                            id="rename-<?= md5($item['path']) ?>"
                        >

                            <form method="post" class="form-row">

                                <input
                                    type="hidden"
                                    name="action"
                                    value="rename"
                                >

                                <input
                                    type="hidden"
                                    name="old"
                                    value="<?= h($item['path']) ?>"
                                >

                                <input
                                    type="text"
                                    name="new_name"
                                    value="<?= h($item['name']) ?>"
                                    required
                                >

                                <button
                                    class="btn btn-primary btn-small"
                                    type="submit"
                                >
                                    OK
                                </button>

                            </form>

                        </div>

                        <!-- Chmod form -->

                        <div
                            class="inline-form"
                            id="chmod-<?= md5($item['path']) ?>"
                        >

                            <form method="post" class="form-row">

                                <input
                                    type="hidden"
                                    name="action"
                                    value="chmod"
                                >

                                <input
                                    type="hidden"
                                    name="target"
                                    value="<?= h($item['path']) ?>"
                                >

                                <input
                                    type="text"
                                    name="mode"
                                    value="<?= h($item['octal']) ?>"
                                    pattern="[0-7]{3,4}"
                                    required
                                    style="width:90px"
                                >

                                <button
                                    class="btn btn-primary btn-small"
                                    type="submit"
                                >
                                    Set
                                </button>

                            </form>

                        </div>

                    </td>

                </tr>

            <?php endforeach; ?>

            </tbody>

        </table>

    </div>

</div>

<div class="footer">
    <?= h(APP_NAME) ?> · Protected Edition
</div>

<script>
function toggleForm(id) {
    const element = document.getElementById(id);

    if (element) {
        element.classList.toggle('show');
    }
}
</script>

</body>
</html>
