文件管理已关闭~~'; header("refresh:3;url=" . $config['domain'] . '?manag-closed'); exit(require_once APP_ROOT . '/app/footer.php'); } /**结束 - 自定义修改 */ // 目录绝对路径,结尾不加 `/` // RexHelper::$root = $_SERVER['DOCUMENT_ROOT']; RexHelper::$root = $_SERVER['DOCUMENT_ROOT']; // 系统用户列表,密码类型 MD5 RexHelper::$users[$config['user']] = array( 'password' => $config['password'] ); // 可编辑文件后缀,开头不加 `.` // RexHelper::$text_suff[] = "jsx"; // RexHelper::$text_suff[] = "php5"; // 文件排除规则,仅正则表达式 RexHelper::$ignore_list = array( '/^\.git|.php|.htaccess|robots.txt|favicon.ico|README.md/', '/^admin|api|app|config|docs|install|public/' ); session_start(); ?> 文件管理 - <?php echo $config['title']; ?> '; RExplorer::body_breadcrumb($path); RExplorer::index($path, $view); echo ''; } } // 未登录 else { if ($action == 'login') { RexAction::action($path, $action); } else { RExplorer::view_login($path); } } ?> 路径不存在或无权限访问!'; } /** * 用户登录视图 * @param string $path 路径 */ static function view_login($path) { echo '
文件管理 v' . RexHelper::$version . '
'; } /** * 目录内容视图 * @param string $path 路径 */ static function view_list($path) { $sapath = RexHelper::path_rtoa($path); $fslist = iterator_to_array(new FilesystemIterator($sapath, 256)); ksort($fslist, SORT_NATURAL); usort($fslist, function ($a, $b) { if ($a->isDir() && !$b->isDir()) { return -1; } if (!$a->isDir() && $b->isDir()) { return 1; } return 0; }); echo '
'; foreach ($fslist as $item) { $suffix = $item->isDir() ? '/' : ''; $srpath = RexHelper::path_ator($item->getRealPath()); if (RexHelper::is_ignore($item->getFileName())) { continue; } echo ''; if (RexHelper::file_catetory($srpath) == 'image') { echo ' '; } else { echo ' '; } echo ' '; } echo '
名称 大小 权限 所有者 创建时间 操作
查看原图 ' . $item->getFileName() . $suffix . ' ' . ($item->isFile() ? RexHelper::format_bytes($item->getSize()) : '-') . ' ' . substr(sprintf('%o', $item->getPerms()), -4) . ' ' . $item->getOwner() . ':' . $item->getGroup() . '' . date('Y-m-d H:i', $item->getCTime()) . ' 查看|改名|权限|删除
'; } /** * 新增目录视图 * @param string $path 路径 */ static function view_newdir($path) { echo '
'; } /** * 新增文件视图 * @param string $path 路径 */ static function view_newfile($path) { echo '
'; } /** * 编辑文件内容视图 * @param string $path 路径 */ static function view_edit($path) { $sapath = RexHelper::path_rtoa($path); $category = RexHelper::file_catetory($sapath); switch ($category) { case 'text': $c = htmlspecialchars(file_get_contents($sapath)); echo '
'; if (is_writable($sapath)) { echo ''; } else { echo ''; } echo '
'; return; case 'image': echo '
'; return; default: echo '
'; return; } } /** * 上传文件视图 * @param string $path 路径 */ static function view_upload($path) { echo '
'; } /** * 重命名文件视图 * @param string $path 路径 */ static function view_rename($path) { echo '
'; } /** * 编辑权限视图 * @param string $path 路径 */ static function view_chmod($path) { $sapath = RexHelper::path_rtoa($path); $perms = substr(sprintf("%o", fileperms($sapath)), -4); echo '
'; } /** * 压缩文件视图 * @param string $path 路径 */ static function view_zip($path) { echo '
'; } /** * 解压缩文件视图 * @param string $path 路径 */ static function view_unzip($path) { echo '
'; } /** * 全局操作菜单 * @param string $path 路径 * @param string $view 视图 */ static function body_navbar($path, $view) { $pdir = $path; if (!is_dir(RexHelper::path_rtoa($path))) { $pdir = dirname($path); } $member = RexAction::user_info(); echo ' '; } /** * 路径转为导航 * @param string $path 路径 */ static function body_breadcrumb($path) { echo ' '; } /** * URL重定向 * @param string $url 重定向的URL地址 * @param integer $sec 重定向的等待时间(秒) * @param string $msg 重定向前的提示信息 * @return void */ static function url_redirect($url, $sec, $msg = '') { $url = str_replace(array("\n", "\r"), '', $url); $msg = $sec == 1 ? '操作成功!' : '操作失败!'; $cat = $sec == 1 ? 'success' : 'danger'; echo '
'; exit(''); } } /** * 回调方法类 */ class RexAction { static function action($path, $action) { $method = 'act_' . $action; if (!method_exists('RexAction', $method)) { RExplorer::url_redirect('?r=fail', 2, '接口不存在!'); } self::$method($path); } /** * 用户信息 * @return array | null */ static function user_info() { if (isset($_SESSION[RexHelper::$ssid])) { return $_SESSION[RexHelper::$ssid]; } } /** * 用户登录操作 */ static function act_login() { $uname = G('username'); if (empty(RexHelper::$users[$uname])) { RExplorer::url_redirect('?r=fail', 2, '用户不存在!'); } if (RexHelper::$users[$uname]['password'] != hash('sha256', (G('password')))) { RExplorer::url_redirect('?r=fail', 2, '密码错误!'); } $_SESSION[RexHelper::$ssid] = array( 'username' => $uname, ); RExplorer::url_redirect('?r=ok', 1); } /** * 用户登出操作 */ static function act_logout() { unset($_SESSION[RexHelper::$ssid]); RExplorer::url_redirect('?r=ok', 1); } /** * 保存新目录 * @param string $path 路径 */ static function act_newdir($path) { $filename = G('filename'); if (!$filename) { RExplorer::url_redirect('?path=' . $path, 2, '目录名称无效!'); } $mode = intval(G('mode'), 8); $sapath = RexHelper::path_rtoa($path); $target = $sapath . DIRECTORY_SEPARATOR . $filename; if (file_exists($target)) { RExplorer::url_redirect('?path=' . $path, 2, ' 目标已存在!'); } if (@mkdir($target, $mode)) { RExplorer::url_redirect('?path=' . $path, 1); } RExplorer::url_redirect('?path=' . $path, 2); } /** * 新建文件 * @param string $path 路径 */ static function act_newfile($path) { $filename = G('filename'); if (!$filename || strpos($filename, '.') === false) { RExplorer::url_redirect('?path=' . $path, 2, '文件名或扩展名无效!'); } $content = G('content'); $sapath = RexHelper::path_rtoa($path); is_dir($sapath) || $sapath = dirname($sapath); // 降级 $target = $sapath . DIRECTORY_SEPARATOR . $filename; if (file_put_contents($target, $content) !== false) { RExplorer::url_redirect('?path=' . $path, 1); } RExplorer::url_redirect('?path=' . $path, 2); } /** * 修改文件 * @param string $path 路径 */ static function act_edit($path) { $content = G('content'); $sapath = RexHelper::path_rtoa($path); if (file_put_contents($sapath, $content) !== false) { RExplorer::url_redirect('?path=' . $path, 1); } RExplorer::url_redirect('?path=' . $path, 2); } /** * 删除路径(文件或目录) * @param string $path 路径 */ static function act_delete($path) { $sapath = RexHelper::path_rtoa($path); if (is_file($sapath)) { if (@unlink($sapath)) { RExplorer::url_redirect('?path=' . dirname($path), 1); } RExplorer::url_redirect('?path=' . dirname($path), 2); } if (is_dir($sapath)) { if (@rmdir($sapath)) { RExplorer::url_redirect('?path=' . dirname($path), 1); } RExplorer::url_redirect('?path=' . $path, 2, '非空或权限不足!'); } RExplorer::url_redirect('?path=' . $path, 2, '不是有效文件或目录!'); } /** * 上传文件 * @param string $path 路径 */ static function act_upload($path) { $sapath = RexHelper::path_rtoa($path); // 从远程获取 if ($fileurl = G('url')) { if ($data = file_get_contents($fileurl)) { $target = $sapath . DIRECTORY_SEPARATOR . basename($fileurl); if (file_put_contents($target, $data)) { RExplorer::url_redirect('?path=' . $path, 1); } RExplorer::url_redirect('?path=' . $path, 2, '保存文件失败'); } RExplorer::url_redirect('?path=' . $path, 2, '获取源文件失败'); } // 从本地上传 if (!empty($_FILES['file'])) { if ($_FILES['file']['error']) { $msg = '错误代码 ' . $_FILES['file']['error']; RExplorer::url_redirect('?path=' . $path, 2, $msg); } $target = $sapath . DIRECTORY_SEPARATOR . $_FILES['file']['name']; if (file_exists($target)) { $msg = $_FILES['file']['name'] . ' 文件已存在!'; RExplorer::url_redirect('?path=' . $path, 2, $msg); } if (@move_uploaded_file($_FILES['file']['tmp_name'], $target)) { RExplorer::url_redirect('?path=' . $path, 1); } RExplorer::url_redirect('?path=' . $path, 2); } // 参数错误 RExplorer::url_redirect('?path=' . $path, 2, '参数错误'); } /** * 重命名路径 * @param string $path 路径 */ static function act_rename($path) { $filename = G('filename'); if (!$filename) { RExplorer::url_redirect('?view=rename&path=' . $path, 2, '名称不能为空!'); } $sapath = RexHelper::path_rtoa($path); if (is_file($sapath) && strpos($filename, '.') === false) { RExplorer::url_redirect('?view=rename&path=' . $path, 2, '文件扩展名无效!'); } $target = dirname($sapath) . DIRECTORY_SEPARATOR . $filename; if (@rename($sapath, $target)) { RExplorer::url_redirect('?path=' . dirname($path), 1); } RExplorer::url_redirect('?path=' . dirname($path), 2); } /** * 编辑权限 * @param string $path 路径 */ static function act_chmod($path) { $mode = intval(G('mode'), 8); if (!$mode) { RExplorer::url_redirect('?view=chmod&path=' . $path, 2, '权限模式无效!'); } $sapath = RexHelper::path_rtoa($path); if (@chmod($sapath, $mode)) { RExplorer::url_redirect('?path=' . dirname($path), 1); } RExplorer::url_redirect('?path=' . dirname($path), 2); } /** * 压缩操作 * @param string $path 路径 */ static function act_zip($path) { $filename = G('filename'); if (!$filename || !strpos($filename, '.')) { RExplorer::url_redirect('?path=' . $path, 2, '压缩文件名无效!'); } $filename = RexHelper::path_rtoa($filename); if (file_exists($filename)) { RExplorer::url_redirect('?path=' . $path, 2, '压缩文件已存在!'); } $content = G('content'); if (!$content) { RExplorer::url_redirect('?path=' . $path, 2, '压缩内容无效!'); } $include = array(); $exclude = array(); $items = explode(PHP_EOL, $content); foreach ($items as $item) { if (strpos($item, 'exclude ') === 0) { $exclude[] = RexHelper::path_rtoa(trim(substr($item, 8))); } else { $include[] = RexHelper::path_rtoa($item); } } if (empty($include)) { RExplorer::url_redirect('?path=' . $path, 2, '压缩内容无效!'); } $zip = new ZipHelper(); $trimpath = RexHelper::path_rtoa(G('trimpath')); if ($zip->zip($filename, $msg, $include, $exclude, $trimpath)) { RExplorer::url_redirect('?path=' . $path, 1, $msg); } RExplorer::url_redirect('?path=' . $path, 2, $msg); } /** * 解压缩文件 * @param string $path 路径 */ static function act_unzip($path) { $root = RexHelper::path_rtoa(G('root')); $filename = RexHelper::path_rtoa(G('filename')); if (!$filename) { $msg = '压缩文件路径无效!'; RExplorer::url_redirect('?path=' . $path, 2, $msg); } if (!$root) { $msg = '解压缩路径无效!'; RExplorer::url_redirect('?path=' . $path, 2, $msg); } $zip = new ZipHelper(); if ($zip->unzip($filename, $root, $msg)) { RExplorer::url_redirect('?path=' . $path, 1, $msg); } RExplorer::url_redirect('?path=' . $path, 2, $msg); } /** * 清空OPCache * @param string $path 路径 */ static function act_opreset($path) { if (opcache_reset()) { RExplorer::url_redirect('?path=' . $path, 1); } RExplorer::url_redirect('?path=' . $path, 2); } } class RexHelper { static $root = __DIR__; static $version = '1.4'; static $ssid = 'rexplorer_sid'; static $users = array(); static $text_suff = array( 'sql', 'tpl', 'php', 'htm', 'html', 'ts', 'js', 'css', 'bat', 'sh', 'md', 'log', 'txt', 'json', 'env', 'ini', ); static $img_suff = array( 'jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'ico', 'jfif', 'tif', 'tga', 'svg' ); static $ignore_list = array(); /** * 优化容量显示 * @param string $path 路径 */ static function format_bytes($size) { $units = array(' B', ' KB', ' MB', ' GB', ' TB'); for ($i = 0; $size >= 1024 && $i < 4; $i++) $size /= 1024; return round($size, 2) . $units[$i]; } /** * 绝对路径转相对路径 * @param string $path 路径 * @return string */ static function path_ator($path) { $path = substr($path, strlen(self::$root)); if (DIRECTORY_SEPARATOR != '/') { $path = str_replace(DIRECTORY_SEPARATOR, '/', $path); } return $path; } /** * 相对路径转绝对路径 * @param string $path 路径 * @return string */ static function path_rtoa($path) { $path = self::$root . DIRECTORY_SEPARATOR . trim($path, '/\\'); if (DIRECTORY_SEPARATOR != '/') { return str_replace('/', DIRECTORY_SEPARATOR, $path); } return $path; } /** * 获取文件扩展名类型 * @param string $path 文件路径 * @return string */ static function file_catetory($path) { if ($ext = pathinfo($path, PATHINFO_EXTENSION)) { if (in_array($ext, self::$text_suff)) { return 'text'; } if (in_array($ext, self::$img_suff)) { return 'image'; } } return ''; } /** * 检测是否需要排除 * @param string $name 文件名称 * @return string */ static function is_ignore($name) { if (!empty(self::$ignore_list)) { foreach (self::$ignore_list as $expr) { if (preg_match($expr, $name)) { return true; } } } return false; } } /** * 压缩类 */ class ZipHelper { /** * 解压缩之 * @param string $filename 文件名 * @param string $path 解压路径 * @param string $msg 错误消息 * @return boolean */ function unzip($filename, $path, &$msg = '') { if (!$filename) { $msg = '压缩文件名无效!'; return false; } $zip = new ZipArchive(); $msg = $zip->open($filename); if (true !== $msg) { $msg = var_export($msg, true); return false; } $zip->extractTo($path); $zip->close(); return true; } /** * 压缩之 * @param string $filename 文件名 * @param string $msg 错误消息 * @param array $include 包含文件列表 * @param array $exclude 排除文件列表 * @param string $trimpath 删除根路径 * @param string $comment 注释内容 * @return boolean */ function zip($filename, &$msg = '', $include = array(), $exclude = array(), $trimpath = '', $comment = 'default') { if (!$filename) { $msg = '压缩文件名无效!'; return false; } if (empty($include)) { $msg = '压缩内容无效!'; return false; } if ('default' == $comment) { $comment = basename($filename) . PHP_EOL . 'Generate at ' . date('Y-m-d H:i:s') . PHP_EOL . 'Powerd by RExplorer.'; } try { $zip = new ZipArchive(); $res = $zip->open($filename, ZipArchive::CREATE); if ($res !== true) { $msg = var_export($res, true); return false; } if ($comment) { $zip->setArchiveComment($comment); } if ($trimpath) { $trimpath = rtrim($trimpath, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; } $substart = strlen($trimpath); foreach ($include as $source) { $this->zip_dir($zip, $source, $exclude, $substart); } $zip->close(); return true; } catch (Exception $ex) { $msg = $ex->getMessage(); return false; } } /** * 递归压缩整个目录 * @param ZipArchive $zip Zip 实例 * @param string $source 包含的路径 * @param array $exclude 排除的路径 * @param int $substart 开始截取的路径字符串(用于去除路径中的根目录路径) */ function zip_dir(&$zip, $source, $exclude, $substart = 0) { if (is_dir($source)) { $source = rtrim($source, DIRECTORY_SEPARATOR); if ($handle = opendir($source)) { while (false !== ($f = readdir($handle))) { if ('.' == $f || '..' == $f) { continue; } $filename = $source . DIRECTORY_SEPARATOR . $f; if (is_dir($filename)) { if ($exclude && in_array($filename, $exclude)) { continue; } $this->zip_dir($zip, $filename, $exclude, $substart); } else { if ($exclude && in_array($filename, $exclude)) { continue; } $zip->addFile($filename, substr($filename, $substart)); } } closedir($handle); } } else { if ($exclude && in_array($source, $exclude)) { return; } $zip->addFile($source); } } } /** 环境检测 */ require_once APP_ROOT . '/app/check.php'; /** 底部广告 */ if ($config['ad_bot']) echo $config['ad_bot_info']; /** 引入底部 */ require_once APP_ROOT . '/app/footer.php';