'YOUR_ACCESS_KEY_ID', // 阿里云 AccessKeyId
'access_key_secret' => 'YOUR_ACCESS_KEY_SECRET', // 阿里云 AccessKeySecret
'endpoint' => 'oss-cn-hangzhou.aliyuncs.com', // OSS endpoint,如: oss-cn-hangzhou.aliyuncs.com
'bucket' => 'your-bucket-name', // OSS bucket 名称
'use_internal' => false, // 设置为 true 会自动转换为内网 endpoint
'use_ssl' => true, // 是否使用 HTTPS
'prefix' => '', // OSS 文件路径前缀,如: 'files/' (可选)
'custom_domain' => '', // 自定义域名,如: 'cdn.yourdomain.com' (可选)
);
// OSS SDK 自动加载路径 (使用 Composer 安装: composer require aliyuncs/oss-sdk-php)
$oss_sdk_path = __DIR__ . '/vendor/autoload.php';
// ========== OSS 配置结束 ==========
// Auth with login/password
// set true/false to enable/disable it
// Is independent from IP white- and blacklisting
$use_auth = true;
// Login user name and password
// Users: array('Username' => 'Password', 'Username2' => 'Password2', ...)
// Generate secure password hash - https://tinyfilemanager.github.io/docs/pwd.html
$auth_users = array(
'admin' => '$2y$10$8qIYdh84LSOVzngfLEXWse6wJdJtdzxOyn2I3xRCiUtaLx9ccLCHe', //admin@123
'user' => '$2y$10$8qIYdh84LSOVzngfLEXWse6wJdJtdzxOyn2I3xRCiUtaLx9ccLCHe' //12345
);
// Readonly users
// e.g. array('users', 'guest', ...)
$readonly_users = array(
'user'
);
// Global readonly, including when auth is not being used
$global_readonly = false;
// user specific directories
// array('Username' => 'Directory path', 'Username2' => 'Directory path', ...)
$directories_users = array();
// Enable highlight.js (https://highlightjs.org/) on view's page
$use_highlightjs = true;
// highlight.js style
// for dark theme use 'ir-black'
$highlightjs_style = 'vs';
// Enable ace.js (https://ace.c9.io/) on view's page
$edit_files = true;
// Default timezone for date() and time()
// Doc - http://php.net/manual/en/timezones.php
$default_timezone = 'Etc/UTC'; // UTC
// Root path for file manager
// use absolute path of directory i.e: '/var/www/folder' or $_SERVER['DOCUMENT_ROOT'].'/folder'
//make sure update $root_url in next section
$root_path = $_SERVER['DOCUMENT_ROOT'];
// Root url for links in file manager.Relative to $http_host. Variants: '', 'path/to/subfolder'
// Will not working if $root_path will be outside of server document root
$root_url = '';
// Server hostname. Can set manually if wrong
// $_SERVER['HTTP_HOST'].'/folder'
$http_host = $_SERVER['HTTP_HOST'];
// input encoding for iconv
$iconv_input_encoding = 'UTF-8';
// date() format for file modification date
// Doc - https://www.php.net/manual/en/function.date.php
$datetime_format = 'm/d/Y g:i A';
// Path display mode when viewing file information
// 'full' => show full path
// 'relative' => show path relative to root_path
// 'host' => show path on the host
$path_display_mode = 'full';
// Allowed file extensions for create and rename files
// e.g. 'txt,html,css,js'
$allowed_file_extensions = '';
// Allowed file extensions for upload files
// e.g. 'gif,png,jpg,html,txt'
$allowed_upload_extensions = '';
// Favicon path. This can be either a full url to an .PNG image, or a path based on the document root.
// full path, e.g http://example.com/favicon.png
// local path, e.g images/icons/favicon.png
$favicon_path = '';
// Files and folders to excluded from listing
// e.g. array('myfile.html', 'personal-folder', '*.php', ...)
$exclude_items = array();
// Online office Docs Viewer
// Available rules are 'google', 'microsoft' or false
// Google => View documents using Google Docs Viewer
// Microsoft => View documents using Microsoft Web Apps Viewer
// false => disable online doc viewer
$online_viewer = 'google';
// Sticky Nav bar
// true => enable sticky header
// false => disable sticky header
$sticky_navbar = true;
// Maximum file upload size
// Increase the following values in php.ini to work properly
// memory_limit, upload_max_filesize, post_max_size
$max_upload_size_bytes = 5000000000; // size 5,000,000,000 bytes (~5GB)
// chunk size used for upload
// eg. decrease to 1MB if nginx reports problem 413 entity too large
$upload_chunk_size_bytes = 2000000; // chunk size 2,000,000 bytes (~2MB)
// Possible rules are 'OFF', 'AND' or 'OR'
// OFF => Don't check connection IP, defaults to OFF
// AND => Connection must be on the whitelist, and not on the blacklist
// OR => Connection must be on the whitelist, or not on the blacklist
$ip_ruleset = 'OFF';
// Should users be notified of their block?
$ip_silent = true;
// IP-addresses, both ipv4 and ipv6
$ip_whitelist = array(
'127.0.0.1', // local ipv4
'::1' // local ipv6
);
// IP-addresses, both ipv4 and ipv6
$ip_blacklist = array(
'0.0.0.0', // non-routable meta ipv4
'::' // non-routable meta ipv6
);
// if User has the external config file, try to use it to override the default config above [config.php]
// sample config - https://tinyfilemanager.github.io/config-sample.txt
$config_file = __DIR__ . '/config.php';
if (is_readable($config_file)) {
@include($config_file);
}
// External CDN resources that can be used in the HTML (replace for GDPR compliance)
$external = array(
'css-bootstrap' => '',
'css-dropzone' => '',
'css-font-awesome' => '',
'css-highlightjs' => '',
'js-ace' => '',
'js-bootstrap' => '',
'js-dropzone' => '',
'js-jquery' => '',
'js-jquery-datatables' => '',
'js-highlightjs' => '',
'pre-jsdelivr' => '',
'pre-cloudflare' => ''
);
// --- EDIT BELOW CAREFULLY OR DO NOT EDIT AT ALL ---
// 定义 OSS 相关常量
define('USE_ALIYUN_OSS', $use_aliyun_oss);
define('OSS_CONFIG', $oss_config);
define('OSS_SDK_PATH', $oss_sdk_path);
// max upload file size
define('MAX_UPLOAD_SIZE', $max_upload_size_bytes);
// upload chunk size
define('UPLOAD_CHUNK_SIZE', $upload_chunk_size_bytes);
// private key and session name to store to the session
if (!defined('FM_SESSION_ID')) {
define('FM_SESSION_ID', 'filemanager');
}
// Configuration
$cfg = new FM_Config();
// 初始化 OSS 适配器 (插件式集成)
$fm_oss = new FM_OSS_Adapter();
// 添加 OSS 辅助函数
if (!function_exists('fm_scandir')) {
function fm_scandir($path) {
global $fm_oss;
if (USE_ALIYUN_OSS && $fm_oss) {
return $fm_oss->scandir($path);
}
return scandir($path);
}
}
if (!function_exists('fm_file_exists')) {
function fm_file_exists($path) {
global $fm_oss;
if (USE_ALIYUN_OSS && $fm_oss) {
return $fm_oss->fileExists($path);
}
return file_exists($path);
}
}
if (!function_exists('fm_is_dir')) {
function fm_is_dir($path) {
global $fm_oss;
if (USE_ALIYUN_OSS && $fm_oss) {
return $fm_oss->isDir($path);
}
return is_dir($path);
}
}
if (!function_exists('fm_is_file')) {
function fm_is_file($path) {
global $fm_oss;
if (USE_ALIYUN_OSS && $fm_oss) {
return $fm_oss->isFile($path);
}
return is_file($path);
}
}
if (!function_exists('fm_filesize')) {
function fm_filesize($path) {
global $fm_oss;
if (USE_ALIYUN_OSS && $fm_oss) {
return $fm_oss->filesize($path);
}
return filesize($path);
}
}
if (!function_exists('fm_filemtime')) {
function fm_filemtime($path) {
global $fm_oss;
if (USE_ALIYUN_OSS && $fm_oss) {
return $fm_oss->filemtime($path);
}
return filemtime($path);
}
}
if (!function_exists('fm_file_get_contents')) {
function fm_file_get_contents($path) {
global $fm_oss;
if (USE_ALIYUN_OSS && $fm_oss) {
return $fm_oss->fileGetContents($path);
}
return file_get_contents($path);
}
}
if (!function_exists('fm_file_put_contents')) {
function fm_file_put_contents($path, $data) {
global $fm_oss;
if (USE_ALIYUN_OSS && $fm_oss) {
return $fm_oss->filePutContents($path, $data);
}
return file_put_contents($path, $data);
}
}
if (!function_exists('fm_unlink')) {
function fm_unlink($path) {
global $fm_oss;
if (USE_ALIYUN_OSS && $fm_oss) {
return $fm_oss->unlink($path);
}
return unlink($path);
}
}
if (!function_exists('fm_rmdir')) {
function fm_rmdir($path) {
global $fm_oss;
if (USE_ALIYUN_OSS && $fm_oss) {
return $fm_oss->rmdir($path);
}
return rmdir($path);
}
}
if (!function_exists('fm_rename')) {
function fm_rename($old, $new) {
global $fm_oss;
if (USE_ALIYUN_OSS && $fm_oss) {
return $fm_oss->rename($old, $new);
}
return rename($old, $new);
}
}
// Default language
$lang = isset($cfg->data['lang']) ? $cfg->data['lang'] : 'en';
// Show or hide files and folders that starts with a dot
$show_hidden_files = isset($cfg->data['show_hidden']) ? $cfg->data['show_hidden'] : true;
// PHP error reporting - false = Turns off Errors, true = Turns on Errors
$report_errors = isset($cfg->data['error_reporting']) ? $cfg->data['error_reporting'] : true;
// Hide Permissions and Owner cols in file-listing
$hide_Cols = isset($cfg->data['hide_Cols']) ? $cfg->data['hide_Cols'] : true;
// Theme
$theme = isset($cfg->data['theme']) ? $cfg->data['theme'] : 'light';
define('FM_THEME', $theme);
//available languages
$lang_list = array(
'en' => 'English'
);
if ($report_errors == true) {
@ini_set('error_reporting', E_ALL);
@ini_set('display_errors', 1);
} else {
@ini_set('error_reporting', E_ALL);
@ini_set('display_errors', 0);
}
// if fm included
if (defined('FM_EMBED')) {
$use_auth = false;
$sticky_navbar = false;
} else {
@set_time_limit(600);
date_default_timezone_set($default_timezone);
ini_set('default_charset', 'UTF-8');
if (version_compare(PHP_VERSION, '5.6.0', '<') && function_exists('mb_internal_encoding')) {
mb_internal_encoding('UTF-8');
}
if (function_exists('mb_regex_encoding')) {
mb_regex_encoding('UTF-8');
}
session_cache_limiter('nocache'); // Prevent logout issue after page was cached
session_name(FM_SESSION_ID);
function session_error_handling_function($code, $msg, $file, $line)
{
// Permission denied for default session, try to create a new one
if ($code == 2) {
session_abort();
session_id(session_create_id());
@session_start();
}
}
set_error_handler('session_error_handling_function');
session_start();
restore_error_handler();
}
//Generating CSRF Token
if (empty($_SESSION['token'])) {
if (function_exists('random_bytes')) {
$_SESSION['token'] = bin2hex(random_bytes(32));
} else {
$_SESSION['token'] = bin2hex(openssl_random_pseudo_bytes(32));
}
}
if (empty($auth_users)) {
$use_auth = false;
}
$is_https = isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1)
|| isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https';
// update $root_url based on user specific directories
if (isset($_SESSION[FM_SESSION_ID]['logged']) && !empty($directories_users[$_SESSION[FM_SESSION_ID]['logged']])) {
$wd = fm_clean_path(dirname($_SERVER['PHP_SELF']));
$root_url = $root_url . $wd . DIRECTORY_SEPARATOR . $directories_users[$_SESSION[FM_SESSION_ID]['logged']];
}
// clean $root_url
$root_url = fm_clean_path($root_url);
// abs path for site
defined('FM_ROOT_URL') || define('FM_ROOT_URL', ($is_https ? 'https' : 'http') . '://' . $http_host . (!empty($root_url) ? '/' . $root_url : ''));
defined('FM_SELF_URL') || define('FM_SELF_URL', ($is_https ? 'https' : 'http') . '://' . $http_host . $_SERVER['PHP_SELF']);
// logout
if (isset($_GET['logout'])) {
unset($_SESSION[FM_SESSION_ID]['logged']);
unset($_SESSION['token']);
fm_redirect(FM_SELF_URL);
}
// Validate connection IP
if ($ip_ruleset != 'OFF') {
function getClientIP()
{
if (array_key_exists('HTTP_CF_CONNECTING_IP', $_SERVER)) {
return $_SERVER["HTTP_CF_CONNECTING_IP"];
} else if (array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER)) {
return $_SERVER["HTTP_X_FORWARDED_FOR"];
} else if (array_key_exists('REMOTE_ADDR', $_SERVER)) {
return $_SERVER['REMOTE_ADDR'];
} else if (array_key_exists('HTTP_CLIENT_IP', $_SERVER)) {
return $_SERVER['HTTP_CLIENT_IP'];
}
return '';
}
$clientIp = getClientIP();
$proceed = false;
$whitelisted = in_array($clientIp, $ip_whitelist);
$blacklisted = in_array($clientIp, $ip_blacklist);
if ($ip_ruleset == 'AND') {
if ($whitelisted == true && $blacklisted == false) {
$proceed = true;
}
} else
if ($ip_ruleset == 'OR') {
if ($whitelisted == true || $blacklisted == false) {
$proceed = true;
}
}
if ($proceed == false) {
trigger_error('User connection denied from: ' . $clientIp, E_USER_WARNING);
if ($ip_silent == false) {
fm_set_msg(lng('Access denied. IP restriction applicable'), 'error');
fm_show_header_login();
fm_show_message();
}
exit();
}
}
// Checking if the user is logged in or not. If not, it will show the login form.
if ($use_auth) {
if (isset($_SESSION[FM_SESSION_ID]['logged'], $auth_users[$_SESSION[FM_SESSION_ID]['logged']])) {
// Logged
} elseif (isset($_POST['fm_usr'], $_POST['fm_pwd'], $_POST['token'])) {
// Logging In
sleep(1);
if (function_exists('password_verify')) {
if (isset($auth_users[$_POST['fm_usr']]) && isset($_POST['fm_pwd']) && password_verify($_POST['fm_pwd'], $auth_users[$_POST['fm_usr']]) && verifyToken($_POST['token'])) {
$_SESSION[FM_SESSION_ID]['logged'] = $_POST['fm_usr'];
fm_set_msg(lng('You are logged in'));
fm_redirect(FM_SELF_URL);
} else {
unset($_SESSION[FM_SESSION_ID]['logged']);
fm_set_msg(lng('Login failed. Invalid username or password'), 'error');
fm_redirect(FM_SELF_URL);
}
} else {
fm_set_msg(lng('password_hash not supported, Upgrade PHP version'), 'error');;
}
} else {
// Form
unset($_SESSION[FM_SESSION_ID]['logged']);
fm_show_header_login();
?>
" . lng('Root path') . " \"{$root_path}\" " . lng('not found!') . " ";
exit;
}
defined('FM_SHOW_HIDDEN') || define('FM_SHOW_HIDDEN', $show_hidden_files);
defined('FM_ROOT_PATH') || define('FM_ROOT_PATH', $root_path);
defined('FM_LANG') || define('FM_LANG', $lang);
defined('FM_FILE_EXTENSION') || define('FM_FILE_EXTENSION', $allowed_file_extensions);
defined('FM_UPLOAD_EXTENSION') || define('FM_UPLOAD_EXTENSION', $allowed_upload_extensions);
defined('FM_EXCLUDE_ITEMS') || define('FM_EXCLUDE_ITEMS', (version_compare(PHP_VERSION, '7.0.0', '<') ? serialize($exclude_items) : $exclude_items));
defined('FM_DOC_VIEWER') || define('FM_DOC_VIEWER', $online_viewer);
define('FM_READONLY', $global_readonly || ($use_auth && !empty($readonly_users) && isset($_SESSION[FM_SESSION_ID]['logged']) && in_array($_SESSION[FM_SESSION_ID]['logged'], $readonly_users)));
define('FM_IS_WIN', DIRECTORY_SEPARATOR == '\\');
// always use ?p=
if (!isset($_GET['p']) && empty($_FILES)) {
fm_redirect(FM_SELF_URL . '?p=');
}
// get path
$p = isset($_GET['p']) ? $_GET['p'] : (isset($_POST['p']) ? $_POST['p'] : '');
// clean path
$p = fm_clean_path($p);
// for ajax request - save
$input = file_get_contents('php://input');
$_POST = (strpos($input, 'ajax') != FALSE && strpos($input, 'save') != FALSE) ? json_decode($input, true) : $_POST;
// instead globals vars
define('FM_PATH', $p);
define('FM_USE_AUTH', $use_auth);
define('FM_EDIT_FILE', $edit_files);
defined('FM_ICONV_INPUT_ENC') || define('FM_ICONV_INPUT_ENC', $iconv_input_encoding);
defined('FM_USE_HIGHLIGHTJS') || define('FM_USE_HIGHLIGHTJS', $use_highlightjs);
defined('FM_HIGHLIGHTJS_STYLE') || define('FM_HIGHLIGHTJS_STYLE', $highlightjs_style);
defined('FM_DATETIME_FORMAT') || define('FM_DATETIME_FORMAT', $datetime_format);
unset($p, $use_auth, $iconv_input_encoding, $use_highlightjs, $highlightjs_style);
/*************************** ACTIONS ***************************/
// Handle all AJAX Request
if ((isset($_SESSION[FM_SESSION_ID]['logged'], $auth_users[$_SESSION[FM_SESSION_ID]['logged']]) || !FM_USE_AUTH) && isset($_POST['ajax'], $_POST['token']) && !FM_READONLY) {
if (!verifyToken($_POST['token'])) {
header('HTTP/1.0 401 Unauthorized');
die("Invalid Token.");
}
//search : get list of files from the current folder
if (isset($_POST['type']) && $_POST['type'] == "search") {
$dir = $_POST['path'] == "." ? '' : $_POST['path'];
$response = scan(fm_clean_path($dir), $_POST['content']);
echo json_encode($response);
exit();
}
// save editor file
if (isset($_POST['type']) && $_POST['type'] == "save") {
// get current path
$path = FM_ROOT_PATH;
if (FM_PATH != '') {
$path .= '/' . FM_PATH;
}
// check path
if (!fm_is_dir($path)) {
fm_redirect(FM_SELF_URL . '?p=');
}
$file = $_GET['edit'];
$file = fm_clean_path($file);
$file = str_replace('/', '', $file);
if ($file == '' || !fm_is_file($path . '/' . $file)) {
fm_set_msg(lng('File not found'), 'error');
$FM_PATH = FM_PATH;
fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
}
header('X-XSS-Protection:0');
$file_path = $path . '/' . $file;
$writedata = $_POST['content'];
// OSS 模式下使用 fm_file_put_contents
$write_results = fm_file_put_contents($file_path, $writedata);
if ($write_results === false) {
header("HTTP/1.1 500 Internal Server Error");
die("Could Not Write File! - Check Permissions / Ownership");
}
die(true);
}
// backup files
if (isset($_POST['type']) && $_POST['type'] == "backup" && !empty($_POST['file'])) {
$fileName = fm_clean_path($_POST['file']);
$fullPath = FM_ROOT_PATH . '/';
if (!empty($_POST['path'])) {
$relativeDirPath = fm_clean_path($_POST['path']);
$fullPath .= "{$relativeDirPath}/";
}
$date = date("dMy-His");
$newFileName = "{$fileName}-{$date}.bak";
$fullyQualifiedFileName = $fullPath . $fileName;
try {
if (!fm_file_exists($fullyQualifiedFileName)) {
throw new Exception("File {$fileName} not found");
}
if (fm_copy($fullyQualifiedFileName, $fullPath . $newFileName, false)) {
echo "Backup {$newFileName} created";
} else {
throw new Exception("Could not copy file {$fileName}");
}
} catch (Exception $e) {
echo $e->getMessage();
}
}
// Save Config
if (isset($_POST['type']) && $_POST['type'] == "settings") {
global $cfg, $lang, $report_errors, $show_hidden_files, $lang_list, $hide_Cols, $theme;
$newLng = $_POST['js-language'];
fm_get_translations([]);
if (!array_key_exists($newLng, $lang_list)) {
$newLng = 'en';
}
$erp = isset($_POST['js-error-report']) && $_POST['js-error-report'] == "true" ? true : false;
$shf = isset($_POST['js-show-hidden']) && $_POST['js-show-hidden'] == "true" ? true : false;
$hco = isset($_POST['js-hide-cols']) && $_POST['js-hide-cols'] == "true" ? true : false;
$te3 = $_POST['js-theme-3'];
if ($cfg->data['lang'] != $newLng) {
$cfg->data['lang'] = $newLng;
$lang = $newLng;
}
if ($cfg->data['error_reporting'] != $erp) {
$cfg->data['error_reporting'] = $erp;
$report_errors = $erp;
}
if ($cfg->data['show_hidden'] != $shf) {
$cfg->data['show_hidden'] = $shf;
$show_hidden_files = $shf;
}
if ($cfg->data['show_hidden'] != $shf) {
$cfg->data['show_hidden'] = $shf;
$show_hidden_files = $shf;
}
if ($cfg->data['hide_Cols'] != $hco) {
$cfg->data['hide_Cols'] = $hco;
$hide_Cols = $hco;
}
if ($cfg->data['theme'] != $te3) {
$cfg->data['theme'] = $te3;
$theme = $te3;
}
$cfg->save();
echo true;
}
// new password hash
if (isset($_POST['type']) && $_POST['type'] == "pwdhash") {
$res = isset($_POST['inputPassword2']) && !empty($_POST['inputPassword2']) ? password_hash($_POST['inputPassword2'], PASSWORD_DEFAULT) : '';
echo $res;
}
//upload using url
if (isset($_POST['type']) && $_POST['type'] == "upload" && !empty($_REQUEST["uploadurl"])) {
$path = FM_ROOT_PATH;
if (FM_PATH != '') {
$path .= '/' . FM_PATH;
}
function event_callback($message)
{
global $callback;
echo json_encode($message);
}
function get_file_path()
{
global $path, $fileinfo, $temp_file;
return $path . "/" . basename($fileinfo->name);
}
$url = !empty($_REQUEST["uploadurl"]) && preg_match("|^http(s)?://.+$|", stripslashes($_REQUEST["uploadurl"])) ? stripslashes($_REQUEST["uploadurl"]) : null;
//prevent 127.* domain and known ports
$domain = parse_url($url, PHP_URL_HOST);
$port = parse_url($url, PHP_URL_PORT);
$knownPorts = [22, 23, 25, 3306];
if (preg_match("/^localhost$|^127(?:\.[0-9]+){0,2}\.[0-9]+$|^(?:0*\:)*?:?0*1$/i", $domain) || in_array($port, $knownPorts)) {
$err = array("message" => "URL is not allowed");
event_callback(array("fail" => $err));
exit();
}
$use_curl = false;
$temp_file = tempnam(sys_get_temp_dir(), "upload-");
$fileinfo = new stdClass();
$fileinfo->name = trim(urldecode(basename($url)), ".\x00..\x20");
$allowed = (FM_UPLOAD_EXTENSION) ? explode(',', FM_UPLOAD_EXTENSION) : false;
$ext = strtolower(pathinfo($fileinfo->name, PATHINFO_EXTENSION));
$isFileAllowed = ($allowed) ? in_array($ext, $allowed) : true;
$err = false;
if (!$isFileAllowed) {
$err = array("message" => "File extension is not allowed");
event_callback(array("fail" => $err));
exit();
}
if (!$url) {
$success = false;
} else if ($use_curl) {
@$fp = fopen($temp_file, "w");
@$ch = curl_init($url);
curl_setopt($ch, CURLOPT_NOPROGRESS, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_FILE, $fp);
@$success = curl_exec($ch);
$curl_info = curl_getinfo($ch);
if (!$success) {
$err = array("message" => curl_error($ch));
}
@curl_close($ch);
fclose($fp);
$fileinfo->size = $curl_info["size_download"];
$fileinfo->type = $curl_info["content_type"];
} else {
$ctx = stream_context_create();
@$success = copy($url, $temp_file, $ctx);
if (!$success) {
$err = error_get_last();
}
}
if ($success) {
$success = rename($temp_file, strtok(get_file_path(), '?'));
}
if ($success) {
event_callback(array("done" => $fileinfo));
} else {
unlink($temp_file);
if (!$err) {
$err = array("message" => "Invalid url parameter");
}
event_callback(array("fail" => $err));
}
}
exit();
}
// Delete file / folder
if (isset($_GET['del'], $_POST['token']) && !FM_READONLY) {
$del = str_replace('/', '', fm_clean_path($_GET['del']));
if ($del != '' && $del != '..' && $del != '.' && verifyToken($_POST['token'])) {
$path = FM_ROOT_PATH;
if (FM_PATH != '') {
$path .= '/' . FM_PATH;
}
$delPath = $path . '/' . $del;
// 先检查是否已经删除(防止重复提交)
if (!fm_file_exists($delPath)) {
$msg = lng('File') . ' %s ' . lng('Deleted');
fm_set_msg(sprintf($msg, fm_enc($del)));
} else {
$is_dir = fm_is_dir($delPath);
if (fm_rdelete($delPath)) {
$msg = $is_dir ? lng('Folder') . ' %s ' . lng('Deleted') : lng('File') . ' %s ' . lng('Deleted');
fm_set_msg(sprintf($msg, fm_enc($del)));
} else {
$msg = $is_dir ? lng('Folder') . ' %s ' . lng('not deleted') : lng('File') . ' %s ' . lng('not deleted');
fm_set_msg(sprintf($msg, fm_enc($del)), 'error');
}
}
} else {
fm_set_msg(lng('Invalid file or folder name'), 'error');
}
$FM_PATH = FM_PATH;
fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
}
// Create a new file/folder
if (isset($_POST['newfilename'], $_POST['newfile'], $_POST['token']) && !FM_READONLY) {
$type = urldecode($_POST['newfile']);
$new = str_replace('/', '', fm_clean_path(strip_tags($_POST['newfilename'])));
if (fm_isvalid_filename($new) && $new != '' && $new != '..' && $new != '.' && verifyToken($_POST['token'])) {
$path = FM_ROOT_PATH;
if (FM_PATH != '') {
$path .= '/' . FM_PATH;
}
if ($type == "file") {
if (!fm_file_exists($path . '/' . $new)) {
if (fm_is_valid_ext($new)) {
// 创建空文件
$result = fm_file_put_contents($path . '/' . $new, '');
if ($result !== false) {
fm_set_msg(sprintf(lng('File') . ' %s ' . lng('Created'), fm_enc($new)));
} else {
die('Cannot open file: ' . $new);
}
} else {
fm_set_msg(lng('File extension is not allowed'), 'error');
}
} else {
fm_set_msg(sprintf(lng('File') . ' %s ' . lng('already exists'), fm_enc($new)), 'alert');
}
} else {
if (fm_mkdir($path . '/' . $new, false) === true) {
fm_set_msg(sprintf(lng('Folder') . ' %s ' . lng('Created'), $new));
} elseif (fm_mkdir($path . '/' . $new, false) === $path . '/' . $new) {
fm_set_msg(sprintf(lng('Folder') . ' %s ' . lng('already exists'), fm_enc($new)), 'alert');
} else {
fm_set_msg(sprintf(lng('Folder') . ' %s ' . lng('not created'), fm_enc($new)), 'error');
}
}
} else {
fm_set_msg(lng('Invalid characters in file or folder name'), 'error');
}
$FM_PATH = FM_PATH;
fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
}
// Copy folder / file
if (isset($_GET['copy'], $_GET['finish']) && !FM_READONLY) {
// from
$copy = urldecode($_GET['copy']);
$copy = fm_clean_path($copy);
// empty path
if ($copy == '') {
fm_set_msg(lng('Source path not defined'), 'error');
$FM_PATH = FM_PATH;
fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
}
// abs path from
$from = FM_ROOT_PATH . '/' . $copy;
// abs path to
$dest = FM_ROOT_PATH;
if (FM_PATH != '') {
$dest .= '/' . FM_PATH;
}
$dest .= '/' . basename($from);
// move?
$move = isset($_GET['move']);
$move = fm_clean_path(urldecode($move));
// copy/move/duplicate
if ($from != $dest) {
$msg_from = trim(FM_PATH . '/' . basename($from), '/');
if ($move) { // Move and to != from so just perform move
$rename = fm_rename_check($from, $dest);
if ($rename) {
fm_set_msg(sprintf(lng('Moved from') . ' %s ' . lng('to') . ' %s', fm_enc($copy), fm_enc($msg_from)));
} elseif ($rename === null) {
fm_set_msg(lng('File or folder with this path already exists'), 'alert');
} else {
fm_set_msg(sprintf(lng('Error while moving from') . ' %s ' . lng('to') . ' %s', fm_enc($copy), fm_enc($msg_from)), 'error');
}
} else { // Not move and to != from so copy with original name
if (fm_rcopy($from, $dest)) {
fm_set_msg(sprintf(lng('Copied from') . ' %s ' . lng('to') . ' %s', fm_enc($copy), fm_enc($msg_from)));
} else {
fm_set_msg(sprintf(lng('Error while copying from') . ' %s ' . lng('to') . ' %s', fm_enc($copy), fm_enc($msg_from)), 'error');
}
}
} else {
if (!$move) { //Not move and to = from so duplicate
$msg_from = trim(FM_PATH . '/' . basename($from), '/');
$fn_parts = pathinfo($from);
$extension_suffix = '';
if (!fm_is_dir($from)) {
$extension_suffix = '.' . $fn_parts['extension'];
}
//Create new name for duplicate
$fn_duplicate = $fn_parts['dirname'] . '/' . $fn_parts['filename'] . '-' . date('YmdHis') . $extension_suffix;
$loop_count = 0;
$max_loop = 1000;
// Check if a file with the duplicate name already exists, if so, make new name (edge case...)
while (fm_file_exists($fn_duplicate) & $loop_count < $max_loop) {
$fn_parts = pathinfo($fn_duplicate);
$fn_duplicate = $fn_parts['dirname'] . '/' . $fn_parts['filename'] . '-copy' . $extension_suffix;
$loop_count++;
}
if (fm_rcopy($from, $fn_duplicate, False)) {
fm_set_msg(sprintf('Copied from %s to %s', fm_enc($copy), fm_enc($fn_duplicate)));
} else {
fm_set_msg(sprintf('Error while copying from %s to %s', fm_enc($copy), fm_enc($fn_duplicate)), 'error');
}
} else {
fm_set_msg(lng('Paths must be not equal'), 'alert');
}
}
$FM_PATH = FM_PATH;
fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
}
// Mass copy files/ folders
if (isset($_POST['file'], $_POST['copy_to'], $_POST['finish'], $_POST['token']) && !FM_READONLY) {
if (!verifyToken($_POST['token'])) {
fm_set_msg(lng('Invalid Token.'), 'error');
}
// from
$path = FM_ROOT_PATH;
if (FM_PATH != '') {
$path .= '/' . FM_PATH;
}
// to
$copy_to_path = FM_ROOT_PATH;
$copy_to = fm_clean_path($_POST['copy_to']);
if ($copy_to != '') {
$copy_to_path .= '/' . $copy_to;
}
if ($path == $copy_to_path) {
fm_set_msg(lng('Paths must be not equal'), 'alert');
$FM_PATH = FM_PATH;
fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
}
if (!fm_is_dir($copy_to_path)) {
if (!fm_mkdir($copy_to_path, true)) {
fm_set_msg('Unable to create destination folder', 'error');
$FM_PATH = FM_PATH;
fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
}
}
// move?
$move = isset($_POST['move']);
// copy/move
$errors = 0;
$files = $_POST['file'];
if (is_array($files) && count($files)) {
foreach ($files as $f) {
if ($f != '') {
$f = fm_clean_path($f);
// abs path from
$from = $path . '/' . $f;
// abs path to
$dest = $copy_to_path . '/' . $f;
// do
if ($move) {
$rename = fm_rename_check($from, $dest);
if ($rename === false) {
$errors++;
}
} else {
if (!fm_rcopy($from, $dest)) {
$errors++;
}
}
}
}
if ($errors == 0) {
$msg = $move ? 'Selected files and folders moved' : 'Selected files and folders copied';
fm_set_msg($msg);
} else {
$msg = $move ? 'Error while moving items' : 'Error while copying items';
fm_set_msg($msg, 'error');
}
} else {
fm_set_msg(lng('Nothing selected'), 'alert');
}
$FM_PATH = FM_PATH;
fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
}
// Rename
if (isset($_POST['rename_from'], $_POST['rename_to'], $_POST['token']) && !FM_READONLY) {
if (!verifyToken($_POST['token'])) {
fm_set_msg("Invalid Token.", 'error');
}
// old name
$old = urldecode($_POST['rename_from']);
$old = fm_clean_path($old);
$old = str_replace('/', '', $old);
// new name
$new = urldecode($_POST['rename_to']);
$new = fm_clean_path(strip_tags($new));
$new = str_replace('/', '', $new);
// path
$path = FM_ROOT_PATH;
if (FM_PATH != '') {
$path .= '/' . FM_PATH;
}
$oldPath = $path . '/' . $old;
$newPath = $path . '/' . $new;
// rename
if (fm_isvalid_filename($new) && $old != '' && $new != '') {
// 先检查是否已经重命名成功(防止重复提交)
if (!fm_file_exists($oldPath) && fm_file_exists($newPath)) {
fm_set_msg(sprintf(lng('Renamed from') . ' %s ' . lng('to') . ' %s', fm_enc($old), fm_enc($new)));
} elseif (fm_rename_check($oldPath, $newPath)) {
fm_set_msg(sprintf(lng('Renamed from') . ' %s ' . lng('to') . ' %s', fm_enc($old), fm_enc($new)));
} else {
fm_set_msg(sprintf(lng('Error while renaming from') . ' %s ' . lng('to') . ' %s', fm_enc($old), fm_enc($new)), 'error');
}
} else {
fm_set_msg(lng('Invalid characters in file name'), 'error');
}
$FM_PATH = FM_PATH;
fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
}
// Download
if (isset($_GET['dl'], $_POST['token'])) {
// Verify the token to ensure it's valid
if (!verifyToken($_POST['token'])) {
fm_set_msg("Invalid Token.", 'error');
exit;
}
// Clean the download file path
$dl = urldecode($_GET['dl']);
$dl = fm_clean_path($dl);
$dl = str_replace('/', '', $dl); // Prevent directory traversal attacks
// Define the file path
$path = FM_ROOT_PATH;
if (FM_PATH != '') {
$path .= '/' . FM_PATH;
}
// Check if the file exists and is valid
if ($dl != '' && fm_is_file($path . '/' . $dl)) {
// Close the session to prevent session locking
if (session_status() === PHP_SESSION_ACTIVE) {
session_write_close();
}
// Call the download function
fm_download_file($path . '/' . $dl, $dl, 1024); // Download with a buffer size of 1024 bytes
exit;
} else {
// Handle the case where the file is not found
fm_set_msg(lng('File not found'), 'error');
$FM_PATH = FM_PATH;
fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
}
}
// Upload
if (!empty($_FILES) && !FM_READONLY) {
if (isset($_POST['token'])) {
if (!verifyToken($_POST['token'])) {
$response = array('status' => 'error', 'info' => "Invalid Token.");
echo json_encode($response);
exit();
}
} else {
$response = array('status' => 'error', 'info' => "Token Missing.");
echo json_encode($response);
exit();
}
$chunkIndex = $_POST['dzchunkindex'];
$chunkTotal = $_POST['dztotalchunkcount'];
$fullPathInput = fm_clean_path($_REQUEST['fullpath']);
$f = $_FILES;
$path = FM_ROOT_PATH;
$ds = DIRECTORY_SEPARATOR;
if (FM_PATH != '') {
$path .= '/' . FM_PATH;
}
$errors = 0;
$uploads = 0;
$allowed = (FM_UPLOAD_EXTENSION) ? explode(',', FM_UPLOAD_EXTENSION) : false;
$response = array(
'status' => 'error',
'info' => 'Oops! Try again'
);
$filename = $f['file']['name'];
$tmp_name = $f['file']['tmp_name'];
$ext = pathinfo($filename, PATHINFO_FILENAME) != '' ? strtolower(pathinfo($filename, PATHINFO_EXTENSION)) : '';
$isFileAllowed = ($allowed) ? in_array($ext, $allowed) : true;
if (!fm_isvalid_filename($filename) && !fm_isvalid_filename($fullPathInput)) {
$response = array(
'status' => 'error',
'info' => "Invalid File name!",
);
echo json_encode($response);
exit();
}
$targetPath = $path . $ds;
// OSS 模式下总是可写,本地模式检查可写性
$is_writable = USE_ALIYUN_OSS ? true : is_writable($targetPath);
if ($is_writable) {
$fullPath = $path . '/' . $fullPathInput;
$folder = substr($fullPath, 0, strrpos($fullPath, "/"));
if (!fm_is_dir($folder)) {
$old = umask(0);
mkdir($folder, 0777, true);
umask($old);
}
if (empty($f['file']['error']) && !empty($tmp_name) && $tmp_name != 'none' && $isFileAllowed) {
if ($chunkTotal) {
// OSS 模式下使用临时文件
global $fm_oss;
$tempFile = sys_get_temp_dir() . '/' . md5($fullPath) . '.part';
$out = @fopen($tempFile, $chunkIndex == 0 ? "wb" : "ab");
if ($out) {
$in = @fopen($tmp_name, "rb");
if ($in) {
if (PHP_VERSION_ID < 80009) {
// workaround https://bugs.php.net/bug.php?id=81145
do {
for (;;) {
$buff = fread($in, 4096);
if ($buff === false || $buff === '') {
break;
}
fwrite($out, $buff);
}
} while (!feof($in));
} else {
stream_copy_to_stream($in, $out);
}
$response = array(
'status' => 'success',
'info' => "file upload successful"
);
} else {
$response = array(
'status' => 'error',
'info' => "failed to open input stream",
'errorDetails' => error_get_last()
);
}
@fclose($in);
@fclose($out);
@unlink($tmp_name);
$response = array(
'status' => 'success',
'info' => "file upload successful"
);
} else {
$response = array(
'status' => 'error',
'info' => "failed to open output stream"
);
}
if ($chunkIndex == $chunkTotal - 1) {
if (fm_file_exists($fullPath)) {
$ext_1 = $ext ? '.' . $ext : '';
$fullPathTarget = $path . '/' . basename($fullPathInput, $ext_1) . '_' . date('ymdHis') . $ext_1;
} else {
$fullPathTarget = $fullPath;
}
// OSS 模式下上传临时文件
if (USE_ALIYUN_OSS && $fm_oss) {
$fm_oss->uploadFile($tempFile, $fullPathTarget);
@unlink($tempFile);
} else {
rename($tempFile, $fullPathTarget);
}
}
} else {
// OSS 模式下使用 uploadFile,本地模式使用 move_uploaded_file
global $fm_oss;
$upload_success = false;
if (USE_ALIYUN_OSS && $fm_oss) {
$upload_success = $fm_oss->uploadFile($tmp_name, $fullPath);
} else {
$upload_success = move_uploaded_file($tmp_name, $fullPath);
}
if ($upload_success) {
// Be sure that the file has been uploaded
if (fm_file_exists($fullPath)) {
$response = array(
'status' => 'success',
'info' => "file upload successful"
);
} else {
$response = array(
'status' => 'error',
'info' => 'Couldn\'t upload the requested file.'
);
}
} else {
$response = array(
'status' => 'error',
'info' => "Error while uploading files. Uploaded files $uploads",
);
}
}
}
} else {
$response = array(
'status' => 'error',
'info' => 'The specified folder for upload isn\'t writeable.'
);
}
// Return the response
echo json_encode($response);
exit();
}
// Mass deleting
if (isset($_POST['group'], $_POST['delete'], $_POST['token']) && !FM_READONLY) {
if (!verifyToken($_POST['token'])) {
fm_set_msg(lng("Invalid Token."), 'error');
}
$path = FM_ROOT_PATH;
if (FM_PATH != '') {
$path .= '/' . FM_PATH;
}
$errors = 0;
$files = $_POST['file'];
if (is_array($files) && count($files)) {
foreach ($files as $f) {
if ($f != '') {
$new_path = $path . '/' . $f;
if (!fm_rdelete($new_path)) {
$errors++;
}
}
}
if ($errors == 0) {
fm_set_msg(lng('Selected files and folder deleted'));
} else {
fm_set_msg(lng('Error while deleting items'), 'error');
}
} else {
fm_set_msg(lng('Nothing selected'), 'alert');
}
$FM_PATH = FM_PATH;
fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
}
// Pack files zip, tar
if (isset($_POST['group'], $_POST['token']) && (isset($_POST['zip']) || isset($_POST['tar'])) && !FM_READONLY) {
if (!verifyToken($_POST['token'])) {
fm_set_msg(lng("Invalid Token."), 'error');
}
$path = FM_ROOT_PATH;
$ext = 'zip';
if (FM_PATH != '') {
$path .= '/' . FM_PATH;
}
//set pack type
$ext = isset($_POST['tar']) ? 'tar' : 'zip';
if (($ext == "zip" && !class_exists('ZipArchive')) || ($ext == "tar" && !class_exists('PharData'))) {
fm_set_msg(lng('Operations with archives are not available'), 'error');
$FM_PATH = FM_PATH;
fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
}
$files = $_POST['file'];
$sanitized_files = array();
// clean path
foreach ($files as $file) {
array_push($sanitized_files, fm_clean_path($file));
}
$files = $sanitized_files;
if (!empty($files)) {
chdir($path);
if (count($files) == 1) {
$one_file = reset($files);
$one_file = basename($one_file);
$zipname = $one_file . '_' . date('ymd_His') . '.' . $ext;
} else {
$zipname = 'archive_' . date('ymd_His') . '.' . $ext;
}
if ($ext == 'zip') {
$zipper = new FM_Zipper();
$res = $zipper->create($zipname, $files);
} elseif ($ext == 'tar') {
$tar = new FM_Zipper_Tar();
$res = $tar->create($zipname, $files);
}
if ($res) {
fm_set_msg(sprintf(lng('Archive') . ' %s ' . lng('Created'), fm_enc($zipname)));
} else {
fm_set_msg(lng('Archive not created'), 'error');
}
} else {
fm_set_msg(lng('Nothing selected'), 'alert');
}
$FM_PATH = FM_PATH;
fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
}
// Unpack zip, tar
if (isset($_POST['unzip'], $_POST['token']) && !FM_READONLY) {
if (!verifyToken($_POST['token'])) {
fm_set_msg(lng("Invalid Token."), 'error');
}
$unzip = urldecode($_POST['unzip']);
$unzip = fm_clean_path($unzip);
$unzip = str_replace('/', '', $unzip);
$isValid = false;
$path = FM_ROOT_PATH;
if (FM_PATH != '') {
$path .= '/' . FM_PATH;
}
if ($unzip != '' && fm_is_file($path . '/' . $unzip)) {
$zip_path = $path . '/' . $unzip;
$ext = pathinfo($zip_path, PATHINFO_EXTENSION);
$isValid = true;
} else {
fm_set_msg(lng('File not found'), 'error');
}
if (($ext == "zip" && !class_exists('ZipArchive')) || ($ext == "tar" && !class_exists('PharData'))) {
fm_set_msg(lng('Operations with archives are not available'), 'error');
$FM_PATH = FM_PATH;
fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
}
if ($isValid) {
//to folder
$tofolder = '';
if (isset($_POST['tofolder'])) {
$tofolder = pathinfo($zip_path, PATHINFO_FILENAME);
if (fm_mkdir($path . '/' . $tofolder, true)) {
$path .= '/' . $tofolder;
}
}
if ($ext == "zip") {
$zipper = new FM_Zipper();
$res = $zipper->unzip($zip_path, $path);
} elseif ($ext == "tar") {
try {
$gzipper = new PharData($zip_path);
if (@$gzipper->extractTo($path, null, true)) {
$res = true;
} else {
$res = false;
}
} catch (Exception $e) {
//TODO:: need to handle the error
$res = true;
}
}
if ($res) {
fm_set_msg(lng('Archive unpacked'));
} else {
fm_set_msg(lng('Archive not unpacked'), 'error');
}
} else {
fm_set_msg(lng('File not found'), 'error');
}
$FM_PATH = FM_PATH;
fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
}
// Change Perms (not for Windows)
if (isset($_POST['chmod'], $_POST['token']) && !FM_READONLY && !FM_IS_WIN) {
if (!verifyToken($_POST['token'])) {
fm_set_msg(lng("Invalid Token."), 'error');
}
$path = FM_ROOT_PATH;
if (FM_PATH != '') {
$path .= '/' . FM_PATH;
}
$file = $_POST['chmod'];
$file = fm_clean_path($file);
$file = str_replace('/', '', $file);
if ($file == '' || (!fm_is_file($path . '/' . $file) && !fm_is_dir($path . '/' . $file))) {
fm_set_msg(lng('File not found'), 'error');
$FM_PATH = FM_PATH;
fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
}
$mode = 0;
if (!empty($_POST['ur'])) {
$mode |= 0400;
}
if (!empty($_POST['uw'])) {
$mode |= 0200;
}
if (!empty($_POST['ux'])) {
$mode |= 0100;
}
if (!empty($_POST['gr'])) {
$mode |= 0040;
}
if (!empty($_POST['gw'])) {
$mode |= 0020;
}
if (!empty($_POST['gx'])) {
$mode |= 0010;
}
if (!empty($_POST['or'])) {
$mode |= 0004;
}
if (!empty($_POST['ow'])) {
$mode |= 0002;
}
if (!empty($_POST['ox'])) {
$mode |= 0001;
}
if (@chmod($path . '/' . $file, $mode)) {
fm_set_msg(lng('Permissions changed'));
} else {
fm_set_msg(lng('Permissions not changed'), 'error');
}
$FM_PATH = FM_PATH;
fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
}
/*************************** ACTIONS ***************************/
// get current path
$path = FM_ROOT_PATH;
if (FM_PATH != '') {
$path .= '/' . FM_PATH;
}
// check path
if (!fm_is_dir($path)) {
fm_redirect(FM_SELF_URL . '?p=');
}
// get parent folder
$parent = fm_get_parent_path(FM_PATH);
// OSS 模式下直接扫描,本地模式检查可读性
if (USE_ALIYUN_OSS) {
$objects = fm_scandir($path);
} else {
$objects = is_readable($path) ? fm_scandir($path) : array();
}
$folders = array();
$files = array();
$current_path = array_slice(explode("/", $path), -1)[0];
if (is_array($objects) && fm_is_exclude_items($current_path)) {
foreach ($objects as $file) {
if ($file == '.' || $file == '..') {
continue;
}
if (!FM_SHOW_HIDDEN && substr($file, 0, 1) === '.') {
continue;
}
$new_path = $path . '/' . $file;
if (@fm_is_file($new_path) && fm_is_exclude_items($file)) {
$files[] = $file;
} elseif (@fm_is_dir($new_path) && $file != '.' && $file != '..' && fm_is_exclude_items($file)) {
$folders[] = $file;
}
}
}
if (!empty($files)) {
natcasesort($files);
}
if (!empty($folders)) {
natcasesort($folders);
}
// upload form
if (isset($_GET['upload']) && !FM_READONLY) {
fm_show_header(); // HEADER
fm_show_nav_path(FM_PATH); // current path
//get the allowed file extensions
function getUploadExt()
{
$extArr = explode(',', FM_UPLOAD_EXTENSION);
if (FM_UPLOAD_EXTENSION && $extArr) {
array_walk($extArr, function (&$x) {
$x = ".$x";
});
return implode(',', $extArr);
}
return '';
}
?>
getPublicUrl($file_path);
} else {
$file_url = FM_ROOT_URL . fm_convert_win((FM_PATH != '' ? '/' . FM_PATH : '') . '/' . $file);
}
$ext = strtolower(pathinfo($file_path, PATHINFO_EXTENSION));
$mime_type = fm_get_mime_type($file_path);
$filesize_raw = fm_get_size($file_path);
$filesize = fm_get_filesize($filesize_raw);
$is_zip = false;
$is_gzip = false;
$is_image = false;
$is_audio = false;
$is_video = false;
$is_text = false;
$is_onlineViewer = false;
$view_title = 'File';
$filenames = false; // for zip
$content = ''; // for text
$online_viewer = strtolower(FM_DOC_VIEWER);
if ($online_viewer && $online_viewer !== 'false' && in_array($ext, fm_get_onlineViewer_exts())) {
$is_onlineViewer = true;
} elseif ($ext == 'zip' || $ext == 'tar') {
$is_zip = true;
$view_title = 'Archive';
$filenames = fm_get_zif_info($file_path, $ext);
} elseif (in_array($ext, fm_get_image_exts())) {
$is_image = true;
$view_title = 'Image';
} elseif (in_array($ext, fm_get_audio_exts())) {
$is_audio = true;
$view_title = 'Audio';
} elseif (in_array($ext, fm_get_video_exts())) {
$is_video = true;
$view_title = 'Video';
} elseif (in_array($ext, fm_get_text_exts()) || substr($mime_type, 0, 4) == 'text' || in_array($mime_type, fm_get_text_mimes())) {
$is_text = true;
$content = fm_file_get_contents($file_path);
}
?>
- :
- :
- File size:
- MIME-type:
- :
- :
- :
- : %
' . lng('Image size') . ': N/A (OSS mode)';
} else {
$image_size = getimagesize($file_path);
echo '- ' . lng('Image size') . ': ' . (isset($image_size[0]) ? $image_size[0] : '0') . ' x ' . (isset($image_size[1]) ? $image_size[1] : '0') . '
';
}
}
// Text info
if ($is_text) {
$is_utf8 = fm_is_utf8($content);
if (function_exists('iconv')) {
if (!$is_utf8) {
$content = iconv(FM_ICONV_INPUT_ENC, 'UTF-8//IGNORE', $content);
}
}
echo '- ' . lng('Charset') . ': ' . ($is_utf8 ? 'utf-8' : '8 bit') . '
';
}
?>
';
} else if ($online_viewer == 'microsoft') {
echo '
';
}
} elseif ($is_zip) {
// ZIP content
if ($filenames !== false) {
echo '
';
foreach ($filenames as $fn) {
if ($fn['folder']) {
echo '' . fm_enc($fn['name']) . '
';
} else {
echo $fn['name'] . ' (' . fm_get_filesize($fn['filesize']) . ')
';
}
}
echo '';
} else {
echo '
' . lng('Error while fetching archive info') . '
';
}
} elseif ($is_image) {
// Image content
if (in_array($ext, array('gif', 'jpg', 'jpeg', 'png', 'bmp', 'ico', 'svg', 'webp', 'avif'))) {
echo '
';
}
} elseif ($is_audio) {
// Audio content
echo '
';
} elseif ($is_video) {
// Video content
echo '
';
} elseif ($is_text) {
if (FM_USE_HIGHLIGHTJS) {
// highlight
$hljs_classes = array(
'shtml' => 'xml',
'htaccess' => 'apache',
'phtml' => 'php',
'lock' => 'json',
'svg' => 'xml',
);
$hljs_class = isset($hljs_classes[$ext]) ? 'lang-' . $hljs_classes[$ext] : 'lang-' . $ext;
if (empty($ext) || in_array(strtolower($file), fm_get_text_names()) || preg_match('#\.min\.(css|js)$#i', $file)) {
$hljs_class = 'nohighlight';
}
$content = '
' . fm_enc($content) . '
';
} elseif (in_array($ext, array('php', 'php4', 'php5', 'phtml', 'phps'))) {
// php highlight
$content = highlight_string($content, true);
} else {
$content = '
' . fm_enc($content) . '
';
}
echo $content;
}
?>
' . $file . '';
header('X-XSS-Protection:0');
fm_show_header(); // HEADER
fm_show_nav_path(FM_PATH); // current path
$file_url = FM_ROOT_URL . fm_convert_win((FM_PATH != '' ? '/' . FM_PATH : '') . '/' . $file);
$file_path = $path . '/' . $file;
// normal editer
$isNormalEditor = true;
if (isset($_GET['env'])) {
if ($_GET['env'] == "ace") {
$isNormalEditor = false;
}
}
// Save File
if (isset($_POST['savedata'])) {
$writedata = $_POST['savedata'];
$write_result = fm_file_put_contents($file_path, $writedata);
if ($write_result !== false) {
fm_set_msg(lng('File Saved Successfully'));
} else {
fm_set_msg(lng('Error saving file'), 'error');
}
}
$ext = strtolower(pathinfo($file_path, PATHINFO_EXTENSION));
$mime_type = fm_get_mime_type($file_path);
$filesize = fm_filesize($file_path);
$is_text = false;
$content = ''; // for text
if (in_array($ext, fm_get_text_exts()) || substr($mime_type, 0, 4) == 'text' || in_array($mime_type, fm_get_text_mimes())) {
$is_text = true;
$content = fm_file_get_contents($file_path);
}
?>
' . htmlspecialchars($content) . '';
echo '';
} elseif ($is_text) {
echo '
' . htmlspecialchars($content) . '
';
} else {
fm_set_msg(lng('FILE EXTENSION HAS NOT SUPPORTED'), 'error');
}
?>
";
return;
}
echo "$external[$key]";
}
/**
* Verify CSRF TOKEN and remove after certified
* @param string $token
* @return bool
*/
function verifyToken($token)
{
if (hash_equals($_SESSION['token'], $token)) {
return true;
}
return false;
}
/**
* Delete file or folder (recursively)
* @param string $path
* @return bool
*/
function fm_rdelete($path)
{
if (is_link($path)) {
return fm_unlink($path);
} elseif (fm_is_dir($path)) {
$objects = fm_scandir($path);
$ok = true;
if (is_array($objects)) {
foreach ($objects as $file) {
if ($file != '.' && $file != '..') {
if (!fm_rdelete($path . '/' . $file)) {
$ok = false;
}
}
}
}
return ($ok) ? fm_rmdir($path) : false;
} elseif (fm_is_file($path)) {
return fm_unlink($path);
}
return false;
}
/**
* Recursive chmod
* @param string $path
* @param int $filemode
* @param int $dirmode
* @return bool
* @todo Will use in mass chmod
*/
function fm_rchmod($path, $filemode, $dirmode)
{
if (is_dir($path)) {
if (!chmod($path, $dirmode)) {
return false;
}
$objects = scandir($path);
if (is_array($objects)) {
foreach ($objects as $file) {
if ($file != '.' && $file != '..') {
if (!fm_rchmod($path . '/' . $file, $filemode, $dirmode)) {
return false;
}
}
}
}
return true;
} elseif (is_link($path)) {
return true;
} elseif (is_file($path)) {
return chmod($path, $filemode);
}
return false;
}
/**
* Check the file extension which is allowed or not
* @param string $filename
* @return bool
*/
function fm_is_valid_ext($filename)
{
$allowed = (FM_FILE_EXTENSION) ? explode(',', FM_FILE_EXTENSION) : false;
$ext = pathinfo($filename, PATHINFO_EXTENSION);
$isFileAllowed = ($allowed) ? in_array($ext, $allowed) : true;
return ($isFileAllowed) ? true : false;
}
/**
* Safely rename
* @param string $old
* @param string $new
* @return bool|null
*/
function fm_rename_check($old, $new)
{
$isFileAllowed = fm_is_valid_ext($new);
if (!fm_is_dir($old)) {
if (!$isFileAllowed) {
error_log('fm_rename_check: 文件类型不允许 - ' . $new);
return false;
}
}
$old_exists = fm_file_exists($old);
$new_exists = fm_file_exists($new);
if (!$old_exists) {
error_log('fm_rename_check: 源文件不存在 - ' . $old);
return null;
}
if ($new_exists) {
error_log('fm_rename_check: 目标文件已存在 - ' . $new);
return null;
}
$result = fm_rename($old, $new);
if (!$result) {
error_log('fm_rename_check: 重命名失败 - From: ' . $old . ', To: ' . $new);
}
return $result;
}
/**
* Copy file or folder (recursively).
* @param string $path
* @param string $dest
* @param bool $upd Update files
* @param bool $force Create folder with same names instead file
* @return bool
*/
function fm_rcopy($path, $dest, $upd = true, $force = true)
{
if (!fm_is_dir($path) && !fm_is_file($path)) {
return false;
}
if (fm_is_dir($path)) {
if (!fm_mkdir($dest, $force)) {
return false;
}
$objects = array_diff(fm_scandir($path), ['.', '..']);
foreach ($objects as $file) {
if (!fm_rcopy("$path/$file", "$dest/$file", $upd, $force)) {
return false;
}
}
return true;
}
// Handle file copying
return fm_copy($path, $dest, $upd);
}
/**
* Safely create folder
* @param string $dir
* @param bool $force
* @return bool
*/
function fm_mkdir($dir, $force)
{
global $fm_oss;
if (USE_ALIYUN_OSS && $fm_oss) {
if ($fm_oss->fileExists($dir)) {
if ($fm_oss->isDir($dir)) {
return $dir;
} elseif (!$force) {
return false;
}
$fm_oss->unlink($dir);
}
return $fm_oss->mkdir($dir, 0777, true);
} else {
if (file_exists($dir)) {
if (is_dir($dir)) {
return $dir;
} elseif (!$force) {
return false;
}
unlink($dir);
}
return mkdir($dir, 0777, true);
}
}
/**
* Safely copy file
* @param string $f1
* @param string $f2
* @param bool $upd Indicates if file should be updated with new content
* @return bool
*/
function fm_copy($f1, $f2, $upd)
{
global $fm_oss;
if (USE_ALIYUN_OSS && $fm_oss) {
$time1 = $fm_oss->filemtime($f1);
if ($fm_oss->fileExists($f2)) {
$time2 = $fm_oss->filemtime($f2);
if ($time2 >= $time1 && $upd) {
return false;
}
}
return $fm_oss->copy($f1, $f2);
} else {
$time1 = filemtime($f1);
if (file_exists($f2)) {
$time2 = filemtime($f2);
if ($time2 >= $time1 && $upd) {
return false;
}
}
$ok = copy($f1, $f2);
if ($ok) {
touch($f2, $time1);
}
return $ok;
}
}
/**
* Get mime type
* @param string $file_path
* @return mixed|string
*/
function fm_get_mime_type($file_path)
{
if (function_exists('finfo_open')) {
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $file_path);
finfo_close($finfo);
return $mime;
} elseif (function_exists('mime_content_type')) {
return mime_content_type($file_path);
} elseif (!stristr(ini_get('disable_functions'), 'shell_exec')) {
$file = escapeshellarg($file_path);
$mime = shell_exec('file -bi ' . $file);
return $mime;
} else {
return '--';
}
}
/**
* HTTP Redirect
* @param string $url
* @param int $code
*/
function fm_redirect($url, $code = 302)
{
header('Location: ' . $url, true, $code);
exit;
}
/**
* Path traversal prevention and clean the url
* It replaces (consecutive) occurrences of / and \\ with whatever is in DIRECTORY_SEPARATOR, and processes /. and /.. fine.
* @param $path
* @return string
*/
function get_absolute_path($path)
{
$path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path);
$parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen');
$absolutes = array();
foreach ($parts as $part) {
if ('.' == $part) continue;
if ('..' == $part) {
array_pop($absolutes);
} else {
$absolutes[] = $part;
}
}
return implode(DIRECTORY_SEPARATOR, $absolutes);
}
/**
* Clean path
* @param string $path
* @return string
*/
function fm_clean_path($path, $trim = true)
{
$path = $trim ? trim($path) : $path;
$path = trim($path, '\\/');
$path = str_replace(array('../', '..\\'), '', $path);
$path = get_absolute_path($path);
if ($path == '..') {
$path = '';
}
return str_replace('\\', '/', $path);
}
/**
* Get parent path
* @param string $path
* @return bool|string
*/
function fm_get_parent_path($path)
{
$path = fm_clean_path($path);
if ($path != '') {
$array = explode('/', $path);
if (count($array) > 1) {
$array = array_slice($array, 0, -1);
return implode('/', $array);
}
return '';
}
return false;
}
function fm_get_display_path($file_path)
{
global $path_display_mode, $root_path, $root_url;
switch ($path_display_mode) {
case 'relative':
return array(
'label' => 'Path',
'path' => fm_enc(fm_convert_win(str_replace($root_path, '', $file_path)))
);
case 'host':
$relative_path = str_replace($root_path, '', $file_path);
return array(
'label' => 'Host Path',
'path' => fm_enc(fm_convert_win('/' . $root_url . '/' . ltrim(str_replace('\\', '/', $relative_path), '/')))
);
case 'full':
default:
return array(
'label' => 'Full Path',
'path' => fm_enc(fm_convert_win($file_path))
);
}
}
/**
* Check file is in exclude list
* @param string $file
* @return bool
*/
function fm_is_exclude_items($file)
{
$ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
if (isset($exclude_items) and sizeof($exclude_items)) {
unset($exclude_items);
}
$exclude_items = FM_EXCLUDE_ITEMS;
if (version_compare(PHP_VERSION, '7.0.0', '<')) {
$exclude_items = unserialize($exclude_items);
}
if (!in_array($file, $exclude_items) && !in_array("*.$ext", $exclude_items)) {
return true;
}
return false;
}
/**
* get language translations from json file
* @param int $tr
* @return array
*/
function fm_get_translations($tr)
{
try {
$content = @file_get_contents('translation.json');
if ($content !== FALSE) {
$lng = json_decode($content, TRUE);
global $lang_list;
foreach ($lng["language"] as $key => $value) {
$code = $value["code"];
$lang_list[$code] = $value["name"];
if ($tr)
$tr[$code] = $value["translation"];
}
return $tr;
}
} catch (Exception $e) {
echo $e;
}
}
/**
* @param string $file
* Recover all file sizes larger than > 2GB.
* Works on php 32bits and 64bits and supports linux
* @return int|string
*/
function fm_get_size($file)
{
global $fm_oss;
// 如果使用 OSS,直接调用 OSS 的 filesize 方法
if (USE_ALIYUN_OSS && $fm_oss) {
return $fm_oss->filesize($file);
}
static $iswin = null;
static $isdarwin = null;
static $exec_works = null;
// Set static variables once
if ($iswin === null) {
$iswin = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
$isdarwin = strtoupper(PHP_OS) === 'DARWIN';
$exec_works = function_exists('exec') && !ini_get('safe_mode') && @exec('echo EXEC') === 'EXEC';
}
// Attempt shell command if exec is available
if ($exec_works) {
$arg = escapeshellarg($file);
$cmd = $iswin ? "for %F in (\"$file\") do @echo %~zF" : ($isdarwin ? "stat -f%z $arg" : "stat -c%s $arg");
@exec($cmd, $output);
if (!empty($output) && ctype_digit($size = trim(implode("\n", $output)))) {
return $size;
}
}
// Attempt Windows COM interface for Windows systems
if ($iswin && class_exists('COM')) {
try {
$fsobj = new COM('Scripting.FileSystemObject');
$f = $fsobj->GetFile(realpath($file));
if (ctype_digit($size = $f->Size)) {
return $size;
}
} catch (Exception $e) {
// COM failed, fallback to filesize
}
}
// Default to PHP's filesize function
return filesize($file);
}
/**
* Get nice filesize
* @param int $size
* @return string
*/
function fm_get_filesize($size)
{
$size = (float) $size;
$units = array('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
$power = ($size > 0) ? floor(log($size, 1024)) : 0;
$power = ($power > (count($units) - 1)) ? (count($units) - 1) : $power;
return sprintf('%s %s', round($size / pow(1024, $power), 2), $units[$power]);
}
/**
* Get info about zip archive
* @param string $path
* @return array|bool
*/
function fm_get_zif_info($path, $ext)
{
if ($ext == 'zip' && function_exists('zip_open')) {
$arch = @zip_open($path);
if ($arch) {
$filenames = array();
while ($zip_entry = @zip_read($arch)) {
$zip_name = @zip_entry_name($zip_entry);
$zip_folder = substr($zip_name, -1) == '/';
$filenames[] = array(
'name' => $zip_name,
'filesize' => @zip_entry_filesize($zip_entry),
'compressed_size' => @zip_entry_compressedsize($zip_entry),
'folder' => $zip_folder
//'compression_method' => zip_entry_compressionmethod($zip_entry),
);
}
@zip_close($arch);
return $filenames;
}
} elseif ($ext == 'tar' && class_exists('PharData')) {
$archive = new PharData($path);
$filenames = array();
foreach (new RecursiveIteratorIterator($archive) as $file) {
$parent_info = $file->getPathInfo();
$zip_name = str_replace("phar://" . $path, '', $file->getPathName());
$zip_name = substr($zip_name, ($pos = strpos($zip_name, '/')) !== false ? $pos + 1 : 0);
$zip_folder = $parent_info->getFileName();
$zip_info = new SplFileInfo($file);
$filenames[] = array(
'name' => $zip_name,
'filesize' => $zip_info->getSize(),
'compressed_size' => $file->getCompressedSize(),
'folder' => $zip_folder
);
}
return $filenames;
}
return false;
}
/**
* Encode html entities
* @param string $text
* @return string
*/
function fm_enc($text)
{
return htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
}
/**
* Prevent XSS attacks
* @param string $text
* @return string
*/
function fm_isvalid_filename($text)
{
return (strpbrk($text, '/?%*:|"<>') === FALSE) ? true : false;
}
/**
* Save message in session
* @param string $msg
* @param string $status
*/
function fm_set_msg($msg, $status = 'ok')
{
$_SESSION[FM_SESSION_ID]['message'] = $msg;
$_SESSION[FM_SESSION_ID]['status'] = $status;
}
/**
* Check if string is in UTF-8
* @param string $string
* @return int
*/
function fm_is_utf8($string)
{
return preg_match('//u', $string);
}
/**
* Convert file name to UTF-8 in Windows
* @param string $filename
* @return string
*/
function fm_convert_win($filename)
{
if (FM_IS_WIN && function_exists('iconv')) {
$filename = iconv(FM_ICONV_INPUT_ENC, 'UTF-8//IGNORE', $filename);
}
return $filename;
}
/**
* @param $obj
* @return array
*/
function fm_object_to_array($obj)
{
if (!is_object($obj) && !is_array($obj)) {
return $obj;
}
if (is_object($obj)) {
$obj = get_object_vars($obj);
}
return array_map('fm_object_to_array', $obj);
}
/**
* Get CSS classname for file
* @param string $path
* @return string
*/
function fm_get_file_icon_class($path)
{
// get extension
$ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));
switch ($ext) {
case 'ico':
case 'gif':
case 'jpg':
case 'jpeg':
case 'jpc':
case 'jp2':
case 'jpx':
case 'xbm':
case 'wbmp':
case 'png':
case 'bmp':
case 'tif':
case 'tiff':
case 'webp':
case 'avif':
case 'svg':
$img = 'fa fa-picture-o';
break;
case 'passwd':
case 'ftpquota':
case 'sql':
case 'js':
case 'ts':
case 'jsx':
case 'tsx':
case 'hbs':
case 'json':
case 'sh':
case 'config':
case 'twig':
case 'tpl':
case 'md':
case 'gitignore':
case 'c':
case 'cpp':
case 'cs':
case 'py':
case 'rs':
case 'map':
case 'lock':
case 'dtd':
case 'ps1':
$img = 'fa fa-file-code-o';
break;
case 'txt':
case 'ini':
case 'conf':
case 'log':
case 'htaccess':
case 'yaml':
case 'yml':
case 'toml':
case 'tmp':
case 'top':
case 'bot':
case 'dat':
case 'bak':
case 'htpasswd':
case 'pl':
$img = 'fa fa-file-text-o';
break;
case 'css':
case 'less':
case 'sass':
case 'scss':
$img = 'fa fa-css3';
break;
case 'bz2':
case 'tbz2':
case 'tbz':
case 'zip':
case 'rar':
case 'gz':
case 'tgz':
case 'tar':
case '7z':
case 'xz':
case 'txz':
case 'zst':
case 'tzst':
$img = 'fa fa-file-archive-o';
break;
case 'php':
case 'php4':
case 'php5':
case 'phps':
case 'phtml':
$img = 'fa fa-code';
break;
case 'htm':
case 'html':
case 'shtml':
case 'xhtml':
$img = 'fa fa-html5';
break;
case 'xml':
case 'xsl':
$img = 'fa fa-file-excel-o';
break;
case 'wav':
case 'mp3':
case 'mp2':
case 'm4a':
case 'aac':
case 'ogg':
case 'oga':
case 'wma':
case 'mka':
case 'flac':
case 'ac3':
case 'tds':
$img = 'fa fa-music';
break;
case 'm3u':
case 'm3u8':
case 'pls':
case 'cue':
case 'xspf':
$img = 'fa fa-headphones';
break;
case 'avi':
case 'mpg':
case 'mpeg':
case 'mp4':
case 'm4v':
case 'flv':
case 'f4v':
case 'ogm':
case 'ogv':
case 'mov':
case 'mkv':
case '3gp':
case 'asf':
case 'wmv':
case 'webm':
$img = 'fa fa-file-video-o';
break;
case 'eml':
case 'msg':
$img = 'fa fa-envelope-o';
break;
case 'xls':
case 'xlsx':
case 'ods':
$img = 'fa fa-file-excel-o';
break;
case 'csv':
$img = 'fa fa-file-text-o';
break;
case 'bak':
case 'swp':
$img = 'fa fa-clipboard';
break;
case 'doc':
case 'docx':
case 'odt':
$img = 'fa fa-file-word-o';
break;
case 'ppt':
case 'pptx':
$img = 'fa fa-file-powerpoint-o';
break;
case 'ttf':
case 'ttc':
case 'otf':
case 'woff':
case 'woff2':
case 'eot':
case 'fon':
$img = 'fa fa-font';
break;
case 'pdf':
$img = 'fa fa-file-pdf-o';
break;
case 'psd':
case 'ai':
case 'eps':
case 'fla':
case 'swf':
$img = 'fa fa-file-image-o';
break;
case 'exe':
case 'msi':
$img = 'fa fa-file-o';
break;
case 'bat':
$img = 'fa fa-terminal';
break;
default:
$img = 'fa fa-info-circle';
}
return $img;
}
/**
* Get image files extensions
* @return array
*/
function fm_get_image_exts()
{
return array('ico', 'gif', 'jpg', 'jpeg', 'jpc', 'jp2', 'jpx', 'xbm', 'wbmp', 'png', 'bmp', 'tif', 'tiff', 'psd', 'svg', 'webp', 'avif');
}
/**
* Get video files extensions
* @return array
*/
function fm_get_video_exts()
{
return array('avi', 'webm', 'wmv', 'mp4', 'm4v', 'ogm', 'ogv', 'mov', 'mkv');
}
/**
* Get audio files extensions
* @return array
*/
function fm_get_audio_exts()
{
return array('wav', 'mp3', 'ogg', 'm4a');
}
/**
* Get text file extensions
* @return array
*/
function fm_get_text_exts()
{
return array(
'txt',
'css',
'ini',
'conf',
'log',
'htaccess',
'passwd',
'ftpquota',
'sql',
'js',
'ts',
'jsx',
'tsx',
'mjs',
'json',
'sh',
'config',
'php',
'php4',
'php5',
'phps',
'phtml',
'htm',
'html',
'shtml',
'xhtml',
'xml',
'xsl',
'm3u',
'm3u8',
'pls',
'cue',
'bash',
'vue',
'eml',
'msg',
'csv',
'bat',
'twig',
'tpl',
'md',
'gitignore',
'less',
'sass',
'scss',
'c',
'cpp',
'cs',
'py',
'go',
'zsh',
'swift',
'map',
'lock',
'dtd',
'svg',
'asp',
'aspx',
'asx',
'asmx',
'ashx',
'jsp',
'jspx',
'cgi',
'dockerfile',
'ruby',
'yml',
'yaml',
'toml',
'vhost',
'scpt',
'applescript',
'csx',
'cshtml',
'c++',
'coffee',
'cfm',
'rb',
'graphql',
'mustache',
'jinja',
'http',
'handlebars',
'java',
'es',
'es6',
'markdown',
'wiki',
'tmp',
'top',
'bot',
'dat',
'bak',
'htpasswd',
'pl',
'ps1'
);
}
/**
* Get mime types of text files
* @return array
*/
function fm_get_text_mimes()
{
return array(
'application/xml',
'application/javascript',
'application/x-javascript',
'image/svg+xml',
'message/rfc822',
'application/json',
);
}
/**
* Get file names of text files w/o extensions
* @return array
*/
function fm_get_text_names()
{
return array(
'license',
'readme',
'authors',
'contributors',
'changelog',
);
}
/**
* Get online docs viewer supported files extensions
* @return array
*/
function fm_get_onlineViewer_exts()
{
return array('doc', 'docx', 'xls', 'xlsx', 'pdf', 'ppt', 'pptx', 'ai', 'psd', 'dxf', 'xps', 'rar', 'odt', 'ods');
}
/**
* It returns the mime type of a file based on its extension.
* @param extension The file extension of the file you want to get the mime type for.
* @return string|string[] The mime type of the file.
*/
function fm_get_file_mimes($extension)
{
$fileTypes['swf'] = 'application/x-shockwave-flash';
$fileTypes['pdf'] = 'application/pdf';
$fileTypes['exe'] = 'application/octet-stream';
$fileTypes['zip'] = 'application/zip';
$fileTypes['doc'] = 'application/msword';
$fileTypes['xls'] = 'application/vnd.ms-excel';
$fileTypes['ppt'] = 'application/vnd.ms-powerpoint';
$fileTypes['gif'] = 'image/gif';
$fileTypes['png'] = 'image/png';
$fileTypes['jpeg'] = 'image/jpg';
$fileTypes['jpg'] = 'image/jpg';
$fileTypes['webp'] = 'image/webp';
$fileTypes['avif'] = 'image/avif';
$fileTypes['rar'] = 'application/rar';
$fileTypes['ra'] = 'audio/x-pn-realaudio';
$fileTypes['ram'] = 'audio/x-pn-realaudio';
$fileTypes['ogg'] = 'audio/x-pn-realaudio';
$fileTypes['wav'] = 'video/x-msvideo';
$fileTypes['wmv'] = 'video/x-msvideo';
$fileTypes['avi'] = 'video/x-msvideo';
$fileTypes['asf'] = 'video/x-msvideo';
$fileTypes['divx'] = 'video/x-msvideo';
$fileTypes['mp3'] = 'audio/mpeg';
$fileTypes['mp4'] = 'audio/mpeg';
$fileTypes['mpeg'] = 'video/mpeg';
$fileTypes['mpg'] = 'video/mpeg';
$fileTypes['mpe'] = 'video/mpeg';
$fileTypes['mov'] = 'video/quicktime';
$fileTypes['swf'] = 'video/quicktime';
$fileTypes['3gp'] = 'video/quicktime';
$fileTypes['m4a'] = 'video/quicktime';
$fileTypes['aac'] = 'video/quicktime';
$fileTypes['m3u'] = 'video/quicktime';
$fileTypes['php'] = ['application/x-php'];
$fileTypes['html'] = ['text/html'];
$fileTypes['txt'] = ['text/plain'];
//Unknown mime-types should be 'application/octet-stream'
if (empty($fileTypes[$extension])) {
$fileTypes[$extension] = ['application/octet-stream'];
}
return $fileTypes[$extension];
}
/**
* This function scans the files and folder recursively, and return matching files
* @param string $dir
* @param string $filter
* @return array|null
*/
function scan($dir = '', $filter = '')
{
$path = FM_ROOT_PATH . '/' . $dir;
if ($path) {
$ite = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path));
$rii = new RegexIterator($ite, "/(" . $filter . ")/i");
$files = array();
foreach ($rii as $file) {
if (!$file->isDir()) {
$fileName = $file->getFilename();
$location = str_replace(FM_ROOT_PATH, '', $file->getPath());
$files[] = array(
"name" => $fileName,
"type" => "file",
"path" => $location,
);
}
}
return $files;
}
}
/**
* Parameters: downloadFile(File Location, File Name,
* max speed, is streaming
* If streaming - videos will show as videos, images as images
* instead of download prompt
* https://stackoverflow.com/a/13821992/1164642
*/
function fm_download_file($fileLocation, $fileName, $chunkSize = 1024)
{
global $fm_oss;
// OSS 模式下直接重定向到公共 URL
if (USE_ALIYUN_OSS && $fm_oss) {
$url = $fm_oss->getPublicUrl($fileLocation);
header('Location: ' . $url);
exit;
}
if (connection_status() != 0)
return (false);
$extension = pathinfo($fileName, PATHINFO_EXTENSION);
$contentType = fm_get_file_mimes($extension);
if (is_array($contentType)) {
$contentType = implode(' ', $contentType);
}
// OSS 模式下获取文件大小
$size = fm_filesize($fileLocation);
if ($size == 0) {
fm_set_msg(lng('Zero byte file! Aborting download'), 'error');
$FM_PATH = FM_PATH;
fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
return (false);
}
@ini_set('magic_quotes_runtime', 0);
// OSS 模式下不需要打开文件句柄
global $fm_oss;
if (!USE_ALIYUN_OSS || !$fm_oss) {
$fp = fopen("$fileLocation", "rb");
if ($fp === false) {
fm_set_msg(lng('Cannot open file! Aborting download'), 'error');
$FM_PATH = FM_PATH;
fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
return (false);
}
}
// headers
header('Content-Description: File Transfer');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header("Content-Transfer-Encoding: binary");
header("Content-Type: $contentType");
$contentDisposition = 'attachment';
if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE")) {
$fileName = preg_replace('/\./', '%2e', $fileName, substr_count($fileName, '.') - 1);
header("Content-Disposition: $contentDisposition;filename=\"$fileName\"");
} else {
header("Content-Disposition: $contentDisposition;filename=\"$fileName\"");
}
header("Accept-Ranges: bytes");
$range = 0;
if (isset($_SERVER['HTTP_RANGE'])) {
list($a, $range) = explode("=", $_SERVER['HTTP_RANGE']);
str_replace($range, "-", $range);
$size2 = $size - 1;
$new_length = $size - $range;
header("HTTP/1.1 206 Partial Content");
header("Content-Length: $new_length");
header("Content-Range: bytes $range$size2/$size");
} else {
$size2 = $size - 1;
header("Content-Range: bytes 0-$size2/$size");
header("Content-Length: " . $size);
}
// OSS 模式下直接读取内容,本地模式使用 readfile
global $fm_oss;
if (USE_ALIYUN_OSS && $fm_oss) {
$content = fm_file_get_contents($fileLocation);
echo $content;
} else {
$fileLocation = realpath($fileLocation);
while (ob_get_level()) ob_end_clean();
readfile($fileLocation);
fclose($fp);
}
return ((connection_status() == 0) and !connection_aborted());
}
/**
* Class to work with zip files (using ZipArchive)
*/
class FM_Zipper
{
private $zip;
public function __construct()
{
$this->zip = new ZipArchive();
}
/**
* Create archive with name $filename and files $files (RELATIVE PATHS!)
* @param string $filename
* @param array|string $files
* @return bool
*/
public function create($filename, $files)
{
$res = $this->zip->open($filename, ZipArchive::CREATE);
if ($res !== true) {
return false;
}
if (is_array($files)) {
foreach ($files as $f) {
$f = fm_clean_path($f);
if (!$this->addFileOrDir($f)) {
$this->zip->close();
return false;
}
}
$this->zip->close();
return true;
} else {
if ($this->addFileOrDir($files)) {
$this->zip->close();
return true;
}
return false;
}
}
/**
* Extract archive $filename to folder $path (RELATIVE OR ABSOLUTE PATHS)
* @param string $filename
* @param string $path
* @return bool
*/
public function unzip($filename, $path)
{
$res = $this->zip->open($filename);
if ($res !== true) {
return false;
}
if ($this->zip->extractTo($path)) {
$this->zip->close();
return true;
}
return false;
}
/**
* Add file/folder to archive
* @param string $filename
* @return bool
*/
private function addFileOrDir($filename)
{
if (is_file($filename)) {
return $this->zip->addFile($filename);
} elseif (is_dir($filename)) {
return $this->addDir($filename);
}
return false;
}
/**
* Add folder recursively
* @param string $path
* @return bool
*/
private function addDir($path)
{
if (!$this->zip->addEmptyDir($path)) {
return false;
}
$objects = scandir($path);
if (is_array($objects)) {
foreach ($objects as $file) {
if ($file != '.' && $file != '..') {
if (is_dir($path . '/' . $file)) {
if (!$this->addDir($path . '/' . $file)) {
return false;
}
} elseif (is_file($path . '/' . $file)) {
if (!$this->zip->addFile($path . '/' . $file)) {
return false;
}
}
}
}
return true;
}
return false;
}
}
/**
* Class to work with Tar files (using PharData)
*/
class FM_Zipper_Tar
{
private $tar;
public function __construct()
{
$this->tar = null;
}
/**
* Create archive with name $filename and files $files (RELATIVE PATHS!)
* @param string $filename
* @param array|string $files
* @return bool
*/
public function create($filename, $files)
{
$this->tar = new PharData($filename);
if (is_array($files)) {
foreach ($files as $f) {
$f = fm_clean_path($f);
if (!$this->addFileOrDir($f)) {
return false;
}
}
return true;
} else {
if ($this->addFileOrDir($files)) {
return true;
}
return false;
}
}
/**
* Extract archive $filename to folder $path (RELATIVE OR ABSOLUTE PATHS)
* @param string $filename
* @param string $path
* @return bool
*/
public function unzip($filename, $path)
{
$res = $this->tar->open($filename);
if ($res !== true) {
return false;
}
if ($this->tar->extractTo($path)) {
return true;
}
return false;
}
/**
* Add file/folder to archive
* @param string $filename
* @return bool
*/
private function addFileOrDir($filename)
{
if (is_file($filename)) {
try {
$this->tar->addFile($filename);
return true;
} catch (Exception $e) {
return false;
}
} elseif (is_dir($filename)) {
return $this->addDir($filename);
}
return false;
}
/**
* Add folder recursively
* @param string $path
* @return bool
*/
private function addDir($path)
{
$objects = scandir($path);
if (is_array($objects)) {
foreach ($objects as $file) {
if ($file != '.' && $file != '..') {
if (is_dir($path . '/' . $file)) {
if (!$this->addDir($path . '/' . $file)) {
return false;
}
} elseif (is_file($path . '/' . $file)) {
try {
$this->tar->addFile($path . '/' . $file);
} catch (Exception $e) {
return false;
}
}
}
}
return true;
}
return false;
}
}
/**
* 阿里云 OSS 适配器类 (插件式集成)
* 将文件系统操作透明地路由到 OSS 或本地文件系统
*/
class FM_OSS_Adapter
{
private $ossClient = null;
private $config = null;
private $useOSS = false;
function __construct()
{
$this->useOSS = USE_ALIYUN_OSS;
$this->config = OSS_CONFIG;
// 如果启用 OSS,尝试初始化 OSS 客户端
if ($this->useOSS) {
$this->initOSSClient();
}
}
/**
* 初始化 OSS 客户端
*/
private function initOSSClient()
{
try {
// 加载 OSS SDK
if (file_exists(OSS_SDK_PATH)) {
require_once OSS_SDK_PATH;
// 处理 endpoint:如果使用内网,自动添加 -internal
$endpoint = $this->config['endpoint'];
$useSSL = isset($this->config['use_ssl']) ? $this->config['use_ssl'] : true;
if (isset($this->config['use_internal']) && $this->config['use_internal']) {
// 如果还没有 -internal 后缀,则添加
if (strpos($endpoint, '-internal.') === false) {
$endpoint = str_replace('.aliyuncs.com', '-internal.aliyuncs.com', $endpoint);
}
// 内网必须使用 HTTPS
$useSSL = true;
}
// 添加协议头
if ($useSSL) {
$endpoint = 'https://' . $endpoint;
} else {
$endpoint = 'http://' . $endpoint;
}
// 创建 OSS 客户端
$this->ossClient = new \OSS\OssClient(
$this->config['access_key_id'],
$this->config['access_key_secret'],
$endpoint,
false // isCName
);
} else {
$this->useOSS = false;
error_log('OSS SDK 未找到,请使用 Composer 安装: composer require aliyuncs/oss-sdk-php');
}
} catch (Exception $e) {
$this->useOSS = false;
error_log('OSS 初始化失败: ' . $e->getMessage());
}
}
/**
* 获取完整的 OSS 对象名称(加上前缀)
*/
private function getOSSKey($path)
{
// 去掉 FM_ROOT_PATH 前缀(如果存在)
if (defined('FM_ROOT_PATH') && FM_ROOT_PATH && strpos($path, FM_ROOT_PATH) === 0) {
$path = substr($path, strlen(FM_ROOT_PATH));
}
// 去除左侧的 /
$path = ltrim($path, '/');
// 如果配置了 prefix,添加到路径前面
$prefix = isset($this->config['prefix']) ? trim($this->config['prefix'], '/') : '';
// 组合最终的 OSS key
if ($prefix && $path) {
$result = $prefix . '/' . $path;
} elseif ($prefix) {
$result = $prefix;
} else {
$result = $path;
}
return $result;
}
/**
* 判断文件是否存在(包括目录)
*/
public function fileExists($path)
{
if (!$this->useOSS || !$this->ossClient) {
return file_exists($path);
}
try {
// 先检查是否为目录
if ($this->isDir($path)) {
return true;
}
// 再检查是否为文件
return $this->ossClient->doesObjectExist($this->config['bucket'], $this->getOSSKey($path));
} catch (Exception $e) {
error_log('OSS fileExists 错误: ' . $e->getMessage());
return false;
}
}
/**
* 判断是否为目录
*/
public function isDir($path)
{
if (!$this->useOSS || !$this->ossClient) {
return is_dir($path);
}
// OSS 不区分目录和文件,但可以通过列举判断
try {
$prefix = $this->getOSSKey($path);
// 空路径或根目录视为目录
if (empty($prefix) || $prefix == '/' || $prefix == FM_ROOT_PATH) {
return true;
}
$options = array(
'prefix' => rtrim($prefix, '/') . '/',
'max-keys' => 1
);
$listObjectInfo = $this->ossClient->listObjects($this->config['bucket'], $options);
$isDir = count($listObjectInfo->getObjectList()) > 0 || count($listObjectInfo->getPrefixList()) > 0;
return $isDir;
} catch (Exception $e) {
error_log('OSS isDir 错误: ' . $e->getMessage() . ' Path: ' . $path);
// 错误时返回 true 避免无限重定向
return true;
}
}
/**
* 判断是否为文件
*/
public function isFile($path)
{
if (!$this->useOSS || !$this->ossClient) {
return is_file($path);
}
return $this->fileExists($path) && !$this->isDir($path);
}
/**
* 读取文件内容
*/
public function fileGetContents($path)
{
if (!$this->useOSS || !$this->ossClient) {
return file_get_contents($path);
}
try {
return $this->ossClient->getObject($this->config['bucket'], $this->getOSSKey($path));
} catch (Exception $e) {
error_log('OSS fileGetContents 错误: ' . $e->getMessage());
return false;
}
}
/**
* 写入文件内容
*/
public function filePutContents($path, $content)
{
if (!$this->useOSS || !$this->ossClient) {
return file_put_contents($path, $content);
}
try {
$this->ossClient->putObject($this->config['bucket'], $this->getOSSKey($path), $content);
return strlen($content);
} catch (Exception $e) {
error_log('OSS filePutContents 错误: ' . $e->getMessage());
return false;
}
}
/**
* 删除文件
*/
public function unlink($path)
{
if (!$this->useOSS || !$this->ossClient) {
return unlink($path);
}
try {
$this->ossClient->deleteObject($this->config['bucket'], $this->getOSSKey($path));
return true;
} catch (Exception $e) {
error_log('OSS unlink 错误: ' . $e->getMessage());
return false;
}
}
/**
* 创建目录
*/
public function mkdir($path, $mode = 0755, $recursive = false)
{
if (!$this->useOSS || !$this->ossClient) {
return mkdir($path, $mode, $recursive);
}
// OSS 不需要显式创建目录,但可以创建一个空对象模拟目录
try {
$dirKey = rtrim($this->getOSSKey($path), '/') . '/';
$this->ossClient->putObject($this->config['bucket'], $dirKey, '');
return true;
} catch (Exception $e) {
error_log('OSS mkdir 错误: ' . $e->getMessage());
return false;
}
}
/**
* 删除目录(优化版,批量删除)
*/
public function rmdir($path)
{
if (!$this->useOSS || !$this->ossClient) {
return rmdir($path);
}
// 删除 OSS 目录下的所有文件
try {
$prefix = rtrim($this->getOSSKey($path), '/') . '/';
$options = array(
'prefix' => $prefix,
'max-keys' => 1000 // 每次最多处理 1000 个对象
);
$totalDeleted = 0;
do {
$listObjectInfo = $this->ossClient->listObjects($this->config['bucket'], $options);
$objectList = $listObjectInfo->getObjectList();
if (!empty($objectList)) {
$keys = array();
foreach ($objectList as $objectInfo) {
$keys[] = $objectInfo->getKey();
}
$this->ossClient->deleteObjects($this->config['bucket'], $keys);
$totalDeleted += count($keys);
}
$options['marker'] = $listObjectInfo->getNextMarker();
} while ($listObjectInfo->getIsTruncated());
error_log('OSS rmdir 成功: 删除了 ' . $totalDeleted . ' 个对象 - Path: ' . $path);
return true;
} catch (Exception $e) {
error_log('OSS rmdir 错误: ' . $e->getMessage() . ' - Path: ' . $path);
return false;
}
}
/**
* 获取文件大小
*/
public function filesize($path)
{
if (!$this->useOSS || !$this->ossClient) {
return filesize($path);
}
try {
// 如果是目录,返回 0
if ($this->isDir($path)) {
return 0;
}
$meta = $this->ossClient->getObjectMeta($this->config['bucket'], $this->getOSSKey($path));
return isset($meta['content-length']) ? intval($meta['content-length']) : 0;
} catch (Exception $e) {
error_log('OSS filesize 错误: ' . $e->getMessage() . ' - Path: ' . $path);
return 0;
}
}
/**
* 获取文件修改时间
*/
public function filemtime($path)
{
if (!$this->useOSS || !$this->ossClient) {
return filemtime($path);
}
try {
// 如果是目录,返回当前时间
if ($this->isDir($path)) {
return time();
}
$meta = $this->ossClient->getObjectMeta($this->config['bucket'], $this->getOSSKey($path));
return isset($meta['last-modified']) ? strtotime($meta['last-modified']) : time();
} catch (Exception $e) {
error_log('OSS filemtime 错误: ' . $e->getMessage() . ' - Path: ' . $path);
return time();
}
}
/**
* 列出目录内容
*/
public function scandir($path)
{
if (!$this->useOSS || !$this->ossClient) {
return scandir($path);
}
try {
$prefix = $this->getOSSKey($path);
$prefix = $prefix ? rtrim($prefix, '/') . '/' : '';
$options = array(
'prefix' => $prefix,
'delimiter' => '/'
);
$listObjectInfo = $this->ossClient->listObjects($this->config['bucket'], $options);
$items = array();
// 添加目录
foreach ($listObjectInfo->getPrefixList() as $prefixInfo) {
$dir = rtrim(substr($prefixInfo->getPrefix(), strlen($prefix)), '/');
if ($dir) {
$items[] = $dir;
}
}
// 添加文件(包含 0 字节文件)
foreach ($listObjectInfo->getObjectList() as $objectInfo) {
$key = $objectInfo->getKey();
$file = substr($key, strlen($prefix));
// 跳过空文件名、包含 / 的、以及目录占位符(仅跳过以 / 结尾的)
if ($file && strpos($file, '/') === false && substr($file, -1) !== '/') {
$items[] = $file;
}
}
return $items;
} catch (Exception $e) {
error_log('OSS scandir 错误: ' . $e->getMessage());
return array();
}
}
/**
* 重命名/移动文件或目录(优化版,使用批量删除)
*/
public function rename($oldPath, $newPath)
{
if (!$this->useOSS || !$this->ossClient) {
return rename($oldPath, $newPath);
}
try {
$oldKey = $this->getOSSKey($oldPath);
$newKey = $this->getOSSKey($newPath);
// 判断是文件还是目录
if ($this->isDir($oldPath)) {
// 目录重命名:递归重命名所有子对象
$prefix = rtrim($oldKey, '/') . '/';
$newPrefix = rtrim($newKey, '/') . '/';
$options = array(
'prefix' => $prefix,
'max-keys' => 1000 // 每次最多处理 1000 个对象
);
$deleteKeys = array();
do {
$listObjectInfo = $this->ossClient->listObjects($this->config['bucket'], $options);
$objectList = $listObjectInfo->getObjectList();
foreach ($objectList as $objectInfo) {
$key = $objectInfo->getKey();
$newObjKey = $newPrefix . substr($key, strlen($prefix));
// 复制到新位置
$this->ossClient->copyObject(
$this->config['bucket'],
$key,
$this->config['bucket'],
$newObjKey
);
// 收集需要删除的旧对象
$deleteKeys[] = $key;
}
// 批量删除旧对象(每 1000 个一批)
if (count($deleteKeys) >= 1000) {
$this->ossClient->deleteObjects($this->config['bucket'], $deleteKeys);
$deleteKeys = array();
}
$options['marker'] = $listObjectInfo->getNextMarker();
} while ($listObjectInfo->getIsTruncated());
// 删除剩余的旧对象
if (!empty($deleteKeys)) {
$this->ossClient->deleteObjects($this->config['bucket'], $deleteKeys);
}
return true;
} else {
// 文件重命名
$this->ossClient->copyObject(
$this->config['bucket'],
$oldKey,
$this->config['bucket'],
$newKey
);
$this->ossClient->deleteObject($this->config['bucket'], $oldKey);
return true;
}
} catch (Exception $e) {
error_log('OSS rename 错误: ' . $e->getMessage() . ' - Old: ' . $oldPath . ', New: ' . $newPath);
return false;
}
}
/**
* 复制文件
*/
public function copy($source, $dest)
{
if (!$this->useOSS || !$this->ossClient) {
return copy($source, $dest);
}
try {
$sourceKey = $this->getOSSKey($source);
$destKey = $this->getOSSKey($dest);
$this->ossClient->copyObject(
$this->config['bucket'],
$sourceKey,
$this->config['bucket'],
$destKey
);
return true;
} catch (Exception $e) {
error_log('OSS copy 错误: ' . $e->getMessage());
return false;
}
}
/**
* 上传文件
*/
public function uploadFile($localPath, $remotePath)
{
if (!$this->useOSS || !$this->ossClient) {
return copy($localPath, $remotePath);
}
try {
$this->ossClient->uploadFile(
$this->config['bucket'],
$this->getOSSKey($remotePath),
$localPath
);
return true;
} catch (Exception $e) {
error_log('OSS uploadFile 错误: ' . $e->getMessage());
return false;
}
}
/**
* 获取文件下载 URL
*/
public function getSignedUrl($path, $timeout = 3600)
{
if (!$this->useOSS || !$this->ossClient) {
return $path;
}
try {
return $this->ossClient->signUrl(
$this->config['bucket'],
$this->getOSSKey($path),
$timeout
);
} catch (Exception $e) {
error_log('OSS getSignedUrl 错误: ' . $e->getMessage());
return '';
}
}
/**
* 获取公共访问 URL(支持自定义域名)
*/
public function getPublicUrl($path)
{
if (!$this->useOSS || !$this->ossClient) {
return $path;
}
$key = $this->getOSSKey($path);
// 如果配置了自定义域名,使用自定义域名
if (isset($this->config['custom_domain']) && !empty($this->config['custom_domain'])) {
$protocol = $this->config['use_ssl'] ? 'https' : 'http';
$domain = rtrim($this->config['custom_domain'], '/');
return sprintf('%s://%s/%s', $protocol, $domain, $key);
}
// 否则使用默认的 OSS 域名
$protocol = $this->config['use_ssl'] ? 'https' : 'http';
$endpoint = $this->config['endpoint'];
$bucket = $this->config['bucket'];
return sprintf('%s://%s.%s/%s', $protocol, $bucket, $endpoint, $key);
}
}
/**
* Save Configuration
*/
class FM_Config
{
var $data;
function __construct()
{
global $root_path, $root_url, $CONFIG;
$fm_url = $root_url . $_SERVER["PHP_SELF"];
$this->data = array(
'lang' => 'en',
'error_reporting' => true,
'show_hidden' => true
);
$data = false;
if (strlen($CONFIG)) {
$data = fm_object_to_array(json_decode($CONFIG));
} else {
$msg = 'Tiny File Manager
Error: Cannot load configuration';
if (substr($fm_url, -1) == '/') {
$fm_url = rtrim($fm_url, '/');
$msg .= '
';
$msg .= '
Seems like you have a trailing slash on the URL.';
$msg .= '
Try this link: ' . $fm_url . '';
}
die($msg);
}
if (is_array($data) && count($data)) $this->data = $data;
else $this->save();
}
function save()
{
global $config_file;
$fm_file = is_readable($config_file) ? $config_file : __FILE__;
$var_name = '$CONFIG';
$var_value = var_export(json_encode($this->data), true);
$config_string = "
' . $_SESSION[FM_SESSION_ID]['message'] . '';
unset($_SESSION[FM_SESSION_ID]['message']);
unset($_SESSION[FM_SESSION_ID]['status']);
}
}
/**
* Show page header in Login Form
*/
function fm_show_header_login()
{
header("Content-Type: text/html; charset=utf-8");
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
header("Pragma: no-cache");
global $favicon_path;
?>
">
';
} ?>
">
';
} ?>
|
">