__DIR__ . DIRECTORY_SEPARATOR,
'base_dir' => DIRECTORY_SEPARATOR,
'allowed_types' => ['zip', 'php', 'txt', 'jpg', 'png', 'pdf', 'html', 'css', 'js'],
'max_size' => 10 * 1024 * 1024,
'text_extensions' => ['txt', 'php', 'html', 'css', 'js', 'log', 'ini', 'md', 'csv', 'xml', 'json', 'htaccess'],
'max_view_size' => 5 * 1024 * 1024,
];
$AUTH = [
'user_hash' => '$2y$11$vloemvW2RzZ4QvgBc0eaEOcVGfyFeqkqgR23avtYsVcc6jlIprYsu',
'pass_hash' => '$2y$11$lL6ABKLcizNyk66UsEFPBOFtB93mW0P/9zmvl8dKAp2iXktfj9BF.',
'session_name' => 'fm_session',
'timeout' => 30 * 60,
'max_attempts' => 5,
'lockout' => 5 * 60,
];
$CONFIG['base_dir'] = rtrim(str_replace(['\\', '/'], DIRECTORY_SEPARATOR, realpath($CONFIG['base_dir']) ?: $CONFIG['base_dir']), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
$CONFIG['script_dir'] = realpath($CONFIG['script_dir']) . DIRECTORY_SEPARATOR;
$CONFIG['temp_dir'] = $CONFIG['script_dir'] . 'temp' . DIRECTORY_SEPARATOR;
if (!is_dir($CONFIG['temp_dir'])) {
@mkdir($CONFIG['temp_dir'], 0755, true);
}
if (is_dir($CONFIG['temp_dir']) && !is_file($CONFIG['temp_dir'] . '.htaccess')) {
@file_put_contents(
$CONFIG['temp_dir'] . '.htaccess',
"Require all denied\n\nOrder allow,deny\nDeny from all\n\n"
);
}
function e($value) {
return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
}
function formatSize($bytes) {
$bytes = (int) $bytes;
if ($bytes <= 0) return '0 B';
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
$i = (int) floor(log($bytes, 1024));
$i = min($i, count($units) - 1);
return round($bytes / pow(1024, $i), 1) . ' ' . $units[$i];
}
function fileExt($name) {
return strtolower(pathinfo($name, PATHINFO_EXTENSION));
}
function normalizeSeparators($path) {
return str_replace(['\\', '/'], DIRECTORY_SEPARATOR, $path);
}
function relativeTo($absolute, $base_dir) {
$rel = strpos($absolute, $base_dir) === 0
? substr($absolute, strlen($base_dir))
: $absolute;
return trim(str_replace(DIRECTORY_SEPARATOR, '/', $rel), '/');
}
function securePath($user_path, $base_dir) {
$user_path = normalizeSeparators($user_path);
$user_path = preg_replace('/\.\.+/', '', $user_path);
$full_path = $base_dir . ltrim($user_path, DIRECTORY_SEPARATOR);
$real_path = realpath($full_path);
if ($real_path === false) {
return realpath(dirname($full_path)) === false ? false : $full_path;
}
if (strpos($real_path . DIRECTORY_SEPARATOR, $base_dir) !== 0) {
return false;
}
return $real_path . (is_dir($real_path) ? DIRECTORY_SEPARATOR : '');
}
function insideBase($path, $base_dir) {
$real = realpath($path);
return $real !== false && strpos($real . DIRECTORY_SEPARATOR, $base_dir) === 0;
}
function postedItems() {
$raw = $_POST['items'] ?? [];
if (!is_array($raw)) {
$raw = array_filter(array_map('trim', explode(',', (string) $raw)), 'strlen');
}
$items = [];
foreach ($raw as $item) {
$name = basename(trim((string) $item));
if ($name !== '' && $name !== '.' && $name !== '..') {
$items[] = $name;
}
}
return array_values(array_unique($items));
}
function itemIcon($name, $is_dir = false) {
if ($is_dir) {
return ['fi-rr-folder', 'ico-folder'];
}
$map = [
'zip' => ['fi-rr-file-zipper', 'ico-archive'],
'rar' => ['fi-rr-file-zipper', 'ico-archive'],
'7z' => ['fi-rr-file-zipper', 'ico-archive'],
'tar' => ['fi-rr-file-zipper', 'ico-archive'],
'gz' => ['fi-rr-file-zipper', 'ico-archive'],
'jpg' => ['fi-rr-picture', 'ico-image'],
'jpeg' => ['fi-rr-picture', 'ico-image'],
'png' => ['fi-rr-picture', 'ico-image'],
'gif' => ['fi-rr-picture', 'ico-image'],
'webp' => ['fi-rr-picture', 'ico-image'],
'svg' => ['fi-rr-picture', 'ico-image'],
'bmp' => ['fi-rr-picture', 'ico-image'],
'ico' => ['fi-rr-picture', 'ico-image'],
'pdf' => ['fi-rr-file-pdf', 'ico-pdf'],
'doc' => ['fi-rr-file-word', 'ico-doc'],
'docx' => ['fi-rr-file-word', 'ico-doc'],
'xls' => ['fi-rr-file-excel', 'ico-sheet'],
'xlsx' => ['fi-rr-file-excel', 'ico-sheet'],
'csv' => ['fi-rr-file-excel', 'ico-sheet'],
'php' => ['fi-rr-file-code', 'ico-code'],
'js' => ['fi-rr-file-code', 'ico-code'],
'ts' => ['fi-rr-file-code', 'ico-code'],
'json' => ['fi-rr-file-code', 'ico-code'],
'xml' => ['fi-rr-file-code', 'ico-code'],
'css' => ['fi-rr-file-code', 'ico-code'],
'py' => ['fi-rr-file-code', 'ico-code'],
'html' => ['fi-rr-browser', 'ico-code'],
'sql' => ['fi-rr-database', 'ico-code'],
'sh' => ['fi-rr-terminal', 'ico-code'],
'bat' => ['fi-rr-terminal', 'ico-code'],
'mp3' => ['fi-rr-music-alt', 'ico-media'],
'wav' => ['fi-rr-music-alt', 'ico-media'],
'ogg' => ['fi-rr-music-alt', 'ico-media'],
'mp4' => ['fi-rr-video-camera', 'ico-media'],
'avi' => ['fi-rr-video-camera', 'ico-media'],
'mkv' => ['fi-rr-video-camera', 'ico-media'],
'mov' => ['fi-rr-video-camera', 'ico-media'],
'txt' => ['fi-rr-document', 'ico-text'],
'md' => ['fi-rr-document', 'ico-text'],
'log' => ['fi-rr-time-past', 'ico-text'],
'ini' => ['fi-rr-settings-sliders', 'ico-text'],
];
return $map[fileExt($name)] ?? ['fi-rr-file', 'ico-file'];
}
function result($errors = [], $success = '') {
return ['errors' => (array) $errors, 'success' => $success];
}
function generateHashesCli(array $argv) {
$user = $argv[2] ?? '';
$pass = $argv[3] ?? '';
if ($user === '' || $pass === '') {
echo "Uso: php " . basename(__FILE__) . " --hash \"usuario\" \"senha\"\n";
exit(1);
}
echo "\nCole as duas linhas abaixo no array \$AUTH, no topo deste arquivo:\n\n";
echo " 'user_hash' => '" . password_hash($user, PASSWORD_BCRYPT, ['cost' => 11]) . "',\n";
echo " 'pass_hash' => '" . password_hash($pass, PASSWORD_BCRYPT, ['cost' => 11]) . "',\n\n";
exit(0);
}
if (PHP_SAPI === 'cli') {
if (($argv[1] ?? '') === '--hash') {
generateHashesCli($argv);
}
exit("Abra este arquivo pelo navegador.\n"
. "Para gerar novas credenciais: php " . basename(__FILE__) . " --hash \"usuario\" \"senha\"\n");
}
function startSecureSession(array $auth) {
if (session_status() === PHP_SESSION_ACTIVE) {
return;
}
$https = (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off')
|| (int) ($_SERVER['SERVER_PORT'] ?? 0) === 443
|| strtolower($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '') === 'https';
session_name($auth['session_name']);
session_set_cookie_params([
'lifetime' => 0,
'path' => '/',
'httponly' => true,
'secure' => $https,
'samesite' => 'Strict',
]);
session_start();
}
function agentFingerprint() {
return sha1($_SERVER['HTTP_USER_AGENT'] ?? '');
}
function csrfToken() {
if (empty($_SESSION['fm_csrf'])) {
$_SESSION['fm_csrf'] = bin2hex(random_bytes(32));
}
return $_SESSION['fm_csrf'];
}
function csrfValid() {
return !empty($_SESSION['fm_csrf'])
&& is_string($_POST['csrf'] ?? null)
&& hash_equals($_SESSION['fm_csrf'], $_POST['csrf']);
}
function csrfField() {
return '';
}
function lockoutFile(array $auth, $temp_dir) {
$ip = $_SERVER['REMOTE_ADDR'] ?? 'local';
return $temp_dir . '.login_' . substr(sha1($ip . '|' . $auth['session_name']), 0, 16) . '.json';
}
function loginState(array $auth, $temp_dir) {
$file = lockoutFile($auth, $temp_dir);
$state = is_file($file) ? json_decode((string) @file_get_contents($file), true) : null;
if (!is_array($state)) {
$state = ['count' => 0, 'until' => 0];
}
if (($state['until'] ?? 0) > 0 && $state['until'] <= time()) {
$state = ['count' => 0, 'until' => 0];
@unlink($file);
}
return $state;
}
function registerLoginFailure(array $auth, $temp_dir) {
$state = loginState($auth, $temp_dir);
$state['count'] = ($state['count'] ?? 0) + 1;
if ($state['count'] >= $auth['max_attempts']) {
$state['until'] = time() + $auth['lockout'];
}
@file_put_contents(lockoutFile($auth, $temp_dir), json_encode($state));
return $state;
}
function clearLoginFailures(array $auth, $temp_dir) {
@unlink(lockoutFile($auth, $temp_dir));
}
function lockoutRemaining(array $state) {
return max(0, (int) ($state['until'] ?? 0) - time());
}
function isLoggedIn(array $auth) {
if (empty($_SESSION['fm_auth'])) {
return false;
}
if (($_SESSION['fm_agent'] ?? '') !== agentFingerprint()) {
return false;
}
if ($auth['timeout'] > 0 && (time() - (int) ($_SESSION['fm_seen'] ?? 0)) > $auth['timeout']) {
return false;
}
$_SESSION['fm_seen'] = time();
return true;
}
function doLogout() {
$_SESSION = [];
if (ini_get('session.use_cookies')) {
$p = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000, $p['path'], $p['domain'], $p['secure'], $p['httponly']);
}
session_destroy();
}
function renderLoginPage($error = '', $locked_for = 0) {
$csrf = csrfToken();
?>
Acesso restrito
Acesso restrito
Entre com suas credenciais para abrir o gerenciador
0) {
$login_error = 'Acesso bloqueado temporariamente.';
} elseif (!csrfValid()) {
$login_error = 'Sessão expirada. Tente novamente.';
} else {
$user_ok = password_verify((string) $_POST['login_user'], $AUTH['user_hash']);
$pass_ok = password_verify((string) ($_POST['login_pass'] ?? ''), $AUTH['pass_hash']);
if ($user_ok && $pass_ok) {
clearLoginFailures($AUTH, $CONFIG['temp_dir']);
session_regenerate_id(true);
$_SESSION['fm_auth'] = true;
$_SESSION['fm_user'] = substr(trim((string) $_POST['login_user']), 0, 64);
$_SESSION['fm_seen'] = time();
$_SESSION['fm_agent'] = agentFingerprint();
$_SESSION['fm_csrf'] = bin2hex(random_bytes(32));
header('Location: ' . $_SERVER['REQUEST_URI']);
exit;
}
$state = registerLoginFailure($AUTH, $CONFIG['temp_dir']);
$left = max(0, $AUTH['max_attempts'] - $state['count']);
$login_error = 'Usuário ou senha inválidos.'
. ($left > 0 ? ' Tentativas restantes: ' . $left . '.' : '');
}
}
renderLoginPage($login_error, lockoutRemaining($state));
}
function sendDownloadHeaders($filename, $length, $mime = 'application/octet-stream') {
$safe = str_replace(['"', "\r", "\n"], '', $filename);
header('Content-Description: File Transfer');
header('Content-Type: ' . $mime);
header('Content-Disposition: attachment; filename="' . $safe . '"; filename*=UTF-8\'\'' . rawurlencode($filename));
header('Content-Length: ' . $length);
header('Cache-Control: no-cache, must-revalidate');
header('Pragma: public');
}
function streamFile($path, $filename, $mime = 'application/octet-stream', $delete_after = false) {
while (ob_get_level()) {
ob_end_clean();
}
sendDownloadHeaders($filename, filesize($path), $mime);
readfile($path);
if ($delete_after) {
@unlink($path);
}
exit;
}
function zipAddPath(ZipArchive $zip, $real_path, $entry_name) {
if (is_file($real_path)) {
return $zip->addFile($real_path, $entry_name) ? 1 : 0;
}
$count = $zip->addEmptyDir($entry_name) ? 1 : 0;
$prefix = strlen($real_path) + 1;
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($real_path, RecursiveDirectoryIterator::SKIP_DOTS),
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($iterator as $file) {
$sub = str_replace(DIRECTORY_SEPARATOR, '/', substr($file->getPathname(), $prefix));
$entry = $entry_name . '/' . $sub;
$ok = $file->isDir() ? $zip->addEmptyDir($entry) : $zip->addFile($file->getPathname(), $entry);
if ($ok) $count++;
}
return $count;
}
function buildZip(array $items, $zip_path, $current_dir, $base_dir) {
if (empty($items)) {
return ['error' => 'Nenhum item selecionado.'];
}
if (!class_exists('ZipArchive')) {
return ['error' => 'Extensão ZIP não disponível no servidor.'];
}
$zip = new ZipArchive();
if ($zip->open($zip_path, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
return ['error' => 'Não foi possível criar o arquivo ZIP.'];
}
$count = 0;
$warnings = [];
foreach ($items as $item) {
$item_path = $current_dir . $item;
if (!file_exists($item_path)) {
$warnings[] = 'Item não encontrado: ' . $item;
continue;
}
if (!insideBase($item_path, $base_dir)) {
$warnings[] = 'Acesso negado: ' . $item;
continue;
}
$count += zipAddPath($zip, realpath($item_path), $item);
}
$zip->close();
if ($count === 0) {
@unlink($zip_path);
return ['error' => 'Nenhum item pôde ser adicionado ao ZIP.'];
}
return ['count' => $count, 'warnings' => $warnings];
}
function actionCompress(array $items, array $ctx) {
$zip_name = 'backup_' . date('Y-m-d_H-i-s') . '_' . substr(md5(uniqid('', true)), 0, 8) . '.zip';
$zip_path = $ctx['temp_dir'] . $zip_name;
$zip = buildZip($items, $zip_path, $ctx['current_dir'], $ctx['base_dir']);
if (isset($zip['error'])) {
return result([$zip['error']]);
}
$final_path = $ctx['current_dir'] . $zip_name;
if (!@rename($zip_path, $final_path)) {
@unlink($zip_path);
return result(['Erro ao mover o arquivo ZIP para o diretório atual. Verifique as permissões.']);
}
@chmod($final_path, 0644);
$msg = 'Compactação concluída: ' . e($zip_name) . '
'
. 'Itens adicionados: ' . (int) $zip['count'] . ' · Tamanho: ' . formatSize(filesize($final_path));
if (!empty($zip['warnings'])) {
$msg .= '
Avisos: ' . e(implode('; ', $zip['warnings'])) . '';
}
return result([], $msg);
}
function actionDownloadSelected(array $items, array $ctx) {
if (empty($items)) {
return result(['Nenhum item selecionado.']);
}
if (count($items) === 1) {
$path = securePath(($ctx['rel_dir'] ? $ctx['rel_dir'] . '/' : '') . $items[0], $ctx['base_dir']);
if ($path !== false && is_file($path)) {
streamFile($path, $items[0]);
}
}
$zip_name = count($items) === 1
? $items[0] . '.zip'
: 'arquivos_selecionados_' . date('Y-m-d_H-i-s') . '.zip';
$zip_path = $ctx['temp_dir'] . 'download_' . uniqid('', true) . '.zip';
$zip = buildZip($items, $zip_path, $ctx['current_dir'], $ctx['base_dir']);
if (isset($zip['error'])) {
return result([$zip['error']]);
}
streamFile($zip_path, $zip_name, 'application/zip', true);
}
function actionDownload($name, array $ctx) {
$filename = basename($name);
$filepath = securePath(($ctx['rel_dir'] ? $ctx['rel_dir'] . '/' : '') . $filename, $ctx['base_dir']);
if ($filepath === false || !is_file($filepath)) {
return result(['Arquivo não encontrado ou acesso negado.']);
}
streamFile($filepath, $filename);
}
function actionView($name, array $ctx) {
$filename = basename($name);
$filepath = securePath(($ctx['rel_dir'] ? $ctx['rel_dir'] . '/' : '') . $filename, $ctx['base_dir']);
if ($filepath === false || !is_file($filepath) || !in_array(fileExt($filename), $ctx['text_extensions'], true)) {
return result(['Arquivo não encontrado, acesso negado ou não é um arquivo de texto.']);
}
while (ob_get_level()) {
ob_end_clean();
}
header('Content-Type: text/plain; charset=utf-8');
header('Content-Disposition: inline; filename="' . str_replace('"', '', $filename) . '"');
if (filesize($filepath) > $ctx['max_view_size']) {
echo 'Arquivo muito grande para visualização. Faça o download.';
exit;
}
readfile($filepath);
exit;
}
function actionCopy(array $post, array $ctx) {
$source_name = basename($post['source'] ?? '');
$target_name = basename($post['target'] ?? '');
$target_dir = trim($post['target_dir'] ?? '', '/\\');
if ($source_name === '' || $target_name === '') {
return result(['Nome de arquivo inválido.']);
}
$source_path = securePath(($ctx['rel_dir'] ? $ctx['rel_dir'] . '/' : '') . $source_name, $ctx['base_dir']);
$dest_dir_path = securePath($target_dir !== '' ? $target_dir : $ctx['rel_dir'], $ctx['base_dir']);
if ($source_path === false || !is_file($source_path) || $dest_dir_path === false || !is_dir($dest_dir_path)) {
return result(['Origem ou destino inválido.']);
}
$target_path = rtrim($dest_dir_path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $target_name;
if (file_exists($target_path)) {
return result(['O arquivo de destino já existe: ' . $target_name]);
}
if (!@copy($source_path, $target_path)) {
return result(['Erro ao copiar o arquivo. Verifique as permissões.']);
}
@chmod($target_path, 0644);
return result([], 'Arquivo copiado: ' . e($source_name) . ' → ' . e($target_name) . '');
}
function actionMkdir($name, array $ctx) {
$folder_name = basename(trim((string) $name));
if ($folder_name === '' || $folder_name === '.' || $folder_name === '..') {
return result(['Nome de pasta inválido.']);
}
$new_folder = $ctx['current_dir'] . $folder_name;
if (file_exists($new_folder)) {
return result(['Esta pasta já existe.']);
}
if (!@mkdir($new_folder, 0755, true)) {
return result(['Erro ao criar a pasta. Verifique as permissões.']);
}
return result([], 'Pasta criada: ' . e($folder_name) . '');
}
function actionDelete($name, array $ctx) {
$item_name = basename((string) $name);
$item_path = securePath(($ctx['rel_dir'] ? $ctx['rel_dir'] . '/' : '') . $item_name, $ctx['base_dir']);
if ($item_path === false || rtrim($item_path, DIRECTORY_SEPARATOR) === rtrim($ctx['base_dir'], DIRECTORY_SEPARATOR)) {
return result(['Operação não permitida.']);
}
if (is_dir($item_path)) {
if (count(scandir($item_path)) > 2) {
return result(['A pasta não está vazia. Remova os arquivos primeiro.']);
}
return @rmdir($item_path)
? result([], 'Pasta removida: ' . e($item_name) . '')
: result(['Erro ao remover a pasta.']);
}
if (is_file($item_path)) {
return @unlink($item_path)
? result([], 'Arquivo removido: ' . e($item_name) . '')
: result(['Erro ao remover o arquivo.']);
}
return result(['Item não encontrado.']);
}
function uploadTarget($upload_dir, array $ctx) {
$dest = securePath(trim((string) $upload_dir, '/\\'), $ctx['base_dir']);
return ($dest === false || !is_dir($dest)) ? $ctx['base_dir'] : $dest;
}
function actionUrlUpload(array $post, array $ctx) {
$url = trim($post['url'] ?? '');
$dest = uploadTarget($post['upload_dir'] ?? '', $ctx);
if ($url === '') {
return result(['A URL não pode estar vazia.']);
}
if (!filter_var($url, FILTER_VALIDATE_URL)) {
return result(['URL inválida.']);
}
if (!function_exists('curl_init')) {
return result(['cURL não está disponível no servidor.']);
}
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 5,
CURLOPT_TIMEOUT => 30,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_USERAGENT => 'Mozilla/5.0 (compatible; FileManager/1.0)',
]);
$content = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$content_type = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
$curl_error = curl_error($ch);
curl_close($ch);
if ($curl_error !== '') return result(['Erro cURL: ' . $curl_error]);
if ($http_code !== 200) return result(['Erro HTTP: ' . $http_code]);
if ($content === '' || $content === false) return result(['Arquivo vazio ou não pôde ser baixado.']);
if (strlen($content) > $ctx['max_size']) {
return result(['Arquivo muito grande. Máximo: ' . formatSize($ctx['max_size'])]);
}
$path_parts = pathinfo(parse_url($url, PHP_URL_PATH) ?? '');
$original_name = $path_parts['filename'] ?? 'arquivo';
$file_ext = strtolower($path_parts['extension'] ?? '');
if ($file_ext === '' && $content_type) {
$mime_map = [
'application/zip' => 'zip',
'application/pdf' => 'pdf',
'image/jpeg' => 'jpg',
'image/png' => 'png',
'text/plain' => 'txt',
'text/html' => 'html',
'text/css' => 'css',
'application/json' => 'txt',
];
foreach ($mime_map as $mime => $ext) {
if (strpos($content_type, $mime) !== false) {
$file_ext = $ext;
break;
}
}
}
if ($file_ext === '') {
$file_ext = 'bin';
}
if (!in_array($file_ext, $ctx['allowed_types'], true)) {
return result(['Tipo de arquivo não permitido: ' . $file_ext]);
}
$filename = preg_replace('/[^A-Za-z0-9._-]/', '_', $original_name) . '_' . time() . '.' . $file_ext;
$target_path = $dest . $filename;
if (@file_put_contents($target_path, $content) === false) {
return result(['Erro ao salvar o arquivo.']);
}
@chmod($target_path, 0644);
return result([], 'Arquivo baixado: ' . e($filename) . '
'
. 'Tamanho: ' . formatSize(strlen($content))
. ' · Destino: /' . e(relativeTo($dest, $ctx['base_dir'])));
}
function actionLocalUpload(array $file, array $post, array $ctx) {
$dest = uploadTarget($post['upload_dir'] ?? '', $ctx);
$file_name = basename($file['name'] ?? '');
$target_file = $dest . $file_name;
$file_type = fileExt($target_file);
if (!is_uploaded_file($file['tmp_name'] ?? '')) {
return result(['Arquivo inválido ou upload interrompido.']);
}
if ($file['size'] > $ctx['max_size']) {
return result(['Arquivo muito grande. Máximo: ' . formatSize($ctx['max_size'])]);
}
if (!in_array($file_type, $ctx['allowed_types'], true)) {
return result(['Tipo de arquivo não permitido: ' . ($file_type ?: 'desconhecido')]);
}
if (file_exists($target_file)) {
return result(['Já existe um arquivo com este nome no destino.']);
}
if (!move_uploaded_file($file['tmp_name'], $target_file)) {
return result(['Erro ao mover o arquivo enviado.']);
}
@chmod($target_file, 0644);
return result([], 'Upload concluído: ' . e($file_name) . '
'
. 'Tamanho: ' . formatSize($file['size'])
. ' · Destino: /' . e(relativeTo($dest, $ctx['base_dir'])));
}
$errors = [];
$success = '';
$rel_dir = isset($_GET['dir']) ? trim($_GET['dir'], '/\\') : '';
$current_dir = $CONFIG['base_dir'];
if ($rel_dir !== '') {
$test_dir = securePath($rel_dir, $CONFIG['base_dir']);
if ($test_dir !== false && is_dir($test_dir)) {
$current_dir = $test_dir;
} else {
$errors[] = 'Diretório inválido ou acesso negado.';
$rel_dir = '';
}
}
$display_rel = relativeTo($current_dir, $CONFIG['base_dir']);
$ctx = $CONFIG + ['current_dir' => $current_dir, 'rel_dir' => $rel_dir];
$outcome = null;
if ($_SERVER['REQUEST_METHOD'] === 'POST' && !csrfValid()) {
$errors[] = 'Sessão expirada ou requisição inválida. Recarregue a página e tente novamente.';
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
$action = $_POST['action'] ?? '';
if (isset($_POST['delete_item'])) {
$outcome = actionDelete($_POST['delete_item'], $ctx);
} else {
switch ($action) {
case 'compress':
$outcome = actionCompress(postedItems(), $ctx);
break;
case 'download_selected':
$outcome = actionDownloadSelected(postedItems(), $ctx);
break;
case 'copy':
$outcome = actionCopy($_POST, $ctx);
break;
case 'mkdir':
$outcome = actionMkdir($_POST['folder_name'] ?? '', $ctx);
break;
case 'delete':
$outcome = actionDelete($_POST['item'] ?? '', $ctx);
break;
case 'upload_url':
$outcome = actionUrlUpload($_POST, $ctx);
break;
default:
if (!empty($_FILES['fileToUpload']['name'])) {
$outcome = actionLocalUpload($_FILES['fileToUpload'], $_POST, $ctx);
}
}
}
} elseif (!empty($_GET['download'])) {
$outcome = actionDownload($_GET['download'], $ctx);
} elseif (!empty($_GET['view'])) {
$outcome = actionView($_GET['view'], $ctx);
}
if (is_array($outcome)) {
$errors = array_merge($errors, $outcome['errors']);
$success = $outcome['success'];
}
function listDirectory($current_dir, $temp_dir) {
$entries = @scandir($current_dir);
if ($entries === false) {
return false;
}
$dirs = [];
$files = [];
foreach ($entries as $entry) {
if ($entry === '.' || $entry === '..') continue;
if ($entry === 'temp' && realpath($current_dir . $entry) === realpath($temp_dir)) continue;
$full = $current_dir . $entry;
$row = [
'name' => $entry,
'is_dir' => is_dir($full),
'size' => is_dir($full) ? 0 : (int) @filesize($full),
'modified' => (int) @filemtime($full),
];
if ($row['is_dir']) {
$dirs[] = $row;
} else {
$files[] = $row;
}
}
$by_name = function ($a, $b) {
return strnatcasecmp($a['name'], $b['name']);
};
usort($dirs, $by_name);
usort($files, $by_name);
return ['dirs' => $dirs, 'files' => $files, 'all' => array_merge($dirs, $files)];
}
function breadcrumbSegments($display_rel) {
$segments = [];
$acc = '';
foreach (explode('/', trim($display_rel, '/')) as $part) {
if ($part === '') continue;
$acc .= ($acc === '' ? '' : '/') . $part;
$segments[] = ['label' => $part, 'path' => $acc];
}
return $segments;
}
$listing = listDirectory($current_dir, $CONFIG['temp_dir']);
$crumbs = breadcrumbSegments($display_rel);
$parent_rel = count($crumbs) > 1 ? $crumbs[count($crumbs) - 2]['path'] : '';
$total_dirs = $listing ? count($listing['dirs']) : 0;
$total_files = $listing ? count($listing['files']) : 0;
$total_size = 0;
if ($listing) {
foreach ($listing['files'] as $file) {
$total_size += $file['size'];
}
}
?>
Gerenciador de Arquivos
Gerenciador de Arquivos
Navegue, envie, compacte e baixe seus arquivos
= e($CONFIG['base_dir']) ?>
= e($_SESSION['fm_user'] ?? 'sessão ativa') ?>
Não foi possível concluir
Enviar arquivo do computador
Informações do ambiente
Upload máximo
= formatSize($CONFIG['max_size']) ?>
Tipos permitidos
= e(implode(', ', $CONFIG['allowed_types'])) ?>
cURL
= function_exists('curl_version') ? 'Disponível' : 'Indisponível' ?>
ZipArchive
= class_exists('ZipArchive') ? 'Disponível' : 'Indisponível' ?>
Diretório base
= e($CONFIG['base_dir']) ?>
Local do script
= e($CONFIG['script_dir']) ?>
Este script dá acesso total ao sistema de arquivos. Mantenha-o protegido por autenticação e nunca o exponha publicamente.
0 selecionado(s)