1124 lines
38 KiB
PHP
1124 lines
38 KiB
PHP
<?php
|
||
|
||
/**
|
||
* Powered by https://github.com/rehiy/web-indexr
|
||
*/
|
||
|
||
/**开始 - 自定义修改 */
|
||
require_once __DIR__ . '/../app/function.php';
|
||
require_once __DIR__ . '/../config/config.php';
|
||
|
||
// 开启tinyfilemanager文件管理
|
||
if (!$config['file_manage']) {
|
||
require_once APP_ROOT . '/app/header.php';
|
||
echo '<h4 class="alert alert-danger">文件管理已关闭~~</h4>';
|
||
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();
|
||
?>
|
||
<!DOCTYPE html>
|
||
<html lang="zh-Hans-CN">
|
||
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||
<meta name="renderer" content="webkit" />
|
||
<meta name="force-rendering" content="webkit" />
|
||
<meta name="author" content="Icret EasyImage2.0">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>文件管理 - <?php echo $config['title']; ?></title>
|
||
<meta name="keywords" content="<?php echo $config['keywords']; ?>" />
|
||
<meta name="description" content="<?php echo $config['description']; ?>" />
|
||
<link rel="shortcut icon" href="<?php static_cdn(); ?>/favicon.ico" type="image/x-icon" />
|
||
<link rel="stylesheet" href="<?php static_cdn(); ?>/public/static/zui/css/zui.min.css">
|
||
<script type="application/javascript" src="<?php static_cdn(); ?>/public/static/zui/lib/jquery/jquery-3.6.0.min.js"></script>
|
||
<script type="application/javascript" src="<?php static_cdn(); ?>/public/static/zui/js/zui.min.js"></script>
|
||
<style type="text/css">
|
||
body {
|
||
font-size: 14px;
|
||
}
|
||
|
||
a {
|
||
text-decoration: none;
|
||
}
|
||
|
||
.login {
|
||
margin: 100px auto;
|
||
max-width: 95%;
|
||
width: 320px;
|
||
}
|
||
|
||
.view-image {
|
||
max-width: 95%;
|
||
width: 320px;
|
||
}
|
||
</style>
|
||
</head>
|
||
|
||
<body>
|
||
<?php
|
||
// 模块参数
|
||
$view = G('view');
|
||
$action = G('action');
|
||
$path = G('path', '/');
|
||
// 已登陆
|
||
if (RexAction::user_info()) {
|
||
if ($action) {
|
||
RexAction::action($path, $action);
|
||
} else {
|
||
RExplorer::body_navbar($path, $view);
|
||
echo '<div class="container">';
|
||
RExplorer::body_breadcrumb($path);
|
||
RExplorer::index($path, $view);
|
||
echo '</div>';
|
||
}
|
||
}
|
||
// 未登录
|
||
else {
|
||
if ($action == 'login') {
|
||
RexAction::action($path, $action);
|
||
} else {
|
||
RExplorer::view_login($path);
|
||
}
|
||
}
|
||
?>
|
||
<script type="text/javascript">
|
||
function do_cofirm(url, act) {
|
||
var i = 0;
|
||
while (i++ < 3) {
|
||
if (!confirm(i + '.重要的操作要重复问三遍,您确定要' + act + '吗?')) {
|
||
return false;
|
||
}
|
||
}
|
||
location.href = url;
|
||
}
|
||
</script>
|
||
</body>
|
||
|
||
</html>
|
||
|
||
<?php
|
||
/**
|
||
* 获取参数
|
||
* @param string $name
|
||
* @param mixed $defv
|
||
* @return mixed
|
||
*/
|
||
function G($name, $defv = '')
|
||
{
|
||
if (isset($_REQUEST[$name])) {
|
||
return $_REQUEST[$name];
|
||
}
|
||
return $defv;
|
||
}
|
||
|
||
/**
|
||
* 页面主类
|
||
*/
|
||
class RExplorer
|
||
{
|
||
/**
|
||
* 显示网站目录的项目内容
|
||
*/
|
||
static function index($path, $view)
|
||
{
|
||
$method = 'view_' . $view;
|
||
if (method_exists('RExplorer', $method)) {
|
||
return self::$method($path);
|
||
}
|
||
// 查看路径
|
||
$sapath = RexHelper::path_rtoa($path);
|
||
if (is_dir($sapath)) {
|
||
return self::view_list($path);
|
||
}
|
||
if (is_file($sapath)) {
|
||
return self::view_edit($path);
|
||
}
|
||
echo '<strong class="red">路径不存在或无权限访问!</strong>';
|
||
}
|
||
|
||
/**
|
||
* 用户登录视图
|
||
* @param string $path 路径
|
||
*/
|
||
static function view_login($path)
|
||
{
|
||
echo '
|
||
<div class="login"">
|
||
<form class="form-horizontal" method="post" action="?action=login">
|
||
<h5 class="card-title text-center mb-5">文件管理 <small>v' . RexHelper::$version . '</small></h5>
|
||
<div class="form-group">
|
||
<label for="exampleInputEmail3">账号</label>
|
||
<input type="text" class="form-control" name="username" id="exampleInputEmail3" placeholder="登录账号">
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="exampleInputInviteCode3">密码</label>
|
||
<input type="password" class="form-control" name="password" id="exampleInputInviteCode3" placeholder="登录密码">
|
||
</div>
|
||
<button type="submit" class="btn btn-primary">登录</button>
|
||
</form>
|
||
</div>';
|
||
}
|
||
|
||
/**
|
||
* 目录内容视图
|
||
* @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 '
|
||
<div class="table-responsive table-condensed">
|
||
<table class="table table-hover table-striped table-bordered text-nowrap">
|
||
<thead>
|
||
<tr>
|
||
<th scope="col">名称</th>
|
||
<th scope="col">大小</th>
|
||
<th scope="col" class="d-none d-sm-table-cell">权限</th>
|
||
<th scope="col" class="d-none d-md-table-cell">所有者</th>
|
||
<th scope="col">创建时间</th>
|
||
<th scope="col">操作</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
';
|
||
foreach ($fslist as $item) {
|
||
$suffix = $item->isDir() ? '/' : '';
|
||
$srpath = RexHelper::path_ator($item->getRealPath());
|
||
if (RexHelper::is_ignore($item->getFileName())) {
|
||
continue;
|
||
}
|
||
|
||
echo '<tr>';
|
||
if (RexHelper::file_catetory($srpath) == 'image') {
|
||
echo '
|
||
<td>
|
||
<img data-toggle="lightbox" src="../app/thumb.php?img=', $srpath, '" data-image="' . $srpath . '" data-caption="查看原图" class="img-thumbnail" alt="查看原图" width="80">
|
||
</td>';
|
||
} else {
|
||
echo '
|
||
<td>
|
||
<a href="?path=' . $srpath . '">' . $item->getFileName() . $suffix . '</a>
|
||
</td>';
|
||
}
|
||
echo '
|
||
<td>' . ($item->isFile() ? RexHelper::format_bytes($item->getSize()) : '-') . '</td>
|
||
<td class="d-none d-sm-table-cell">' . substr(sprintf('%o', $item->getPerms()), -4) . '</td>
|
||
<td class="d-none d-md-table-cell">' . $item->getOwner() . ':' . $item->getGroup() . '<td>' . date('Y-m-d H:i', $item->getCTime()) . '</td>
|
||
<td><a href="?path=' . $srpath . '">查看</a>|<a href="?view=rename&path=' . $srpath . '">改名</a>|<a href="?view=chmod&path=' . $srpath . '">权限</a>|<a href="javascript:;" onclick="do_cofirm(\'?action=delete&path=' . $srpath . '\', \'删除\')">删除</a></td>
|
||
</tr>
|
||
';
|
||
}
|
||
echo '
|
||
</tbody>
|
||
</table>
|
||
';
|
||
}
|
||
|
||
/**
|
||
* 新增目录视图
|
||
* @param string $path 路径
|
||
*/
|
||
static function view_newdir($path)
|
||
{
|
||
echo '
|
||
<div class="newdir">
|
||
<form method="post" action="?action=newdir&path=' . $path . '">
|
||
<div class="row mb-3">
|
||
<label class="col-sm-2 col-form-label">目录名</label>
|
||
<div class="col-sm-10">
|
||
<input type="text" class="form-control" name="filename">
|
||
</div>
|
||
</div>
|
||
<div class="row mb-4">
|
||
<label class="col-sm-2 col-form-label">权限模式</label>
|
||
<div class="col-sm-10">
|
||
<input type="text" class="form-control" name="mode" value="0777">
|
||
</div>
|
||
</div>
|
||
<div class="d-grid">
|
||
<button type="submit" class="btn btn-dark">创建目录</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
';
|
||
}
|
||
|
||
/**
|
||
* 新增文件视图
|
||
* @param string $path 路径
|
||
*/
|
||
static function view_newfile($path)
|
||
{
|
||
echo '
|
||
<div class="newfile">
|
||
<form method="post" action="?action=newfile&path=' . $path . '">
|
||
<div class="row mb-3">
|
||
<label class="col-sm-2 col-form-label">文件名</label>
|
||
<div class="col-sm-10">
|
||
<input type="text" class="form-control" name="filename" placeholder="如:newfile.txt">
|
||
</div>
|
||
</div>
|
||
<div class="row mb-4">
|
||
<label class="col-sm-2 col-form-label">内容</label>
|
||
<div class="col-sm-10">
|
||
<textarea class="form-control" name="content" rows="10"></textarea>
|
||
</div>
|
||
</div>
|
||
<div class="d-grid">
|
||
<button type="submit" class="btn btn-dark">创建文件</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
';
|
||
}
|
||
|
||
/**
|
||
* 编辑文件内容视图
|
||
* @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 '
|
||
<div class="edit">
|
||
<form method="post" action="?action=edit&path=' . $path . '">
|
||
<div class="mb-4">
|
||
<textarea class="form-control" name="content" rows="30">' . $c . '</textarea>
|
||
</div>
|
||
<div class="d-grid">
|
||
';
|
||
if (is_writable($sapath)) {
|
||
echo '<button type="submit" class="btn btn-dark">保存文件</button>';
|
||
} else {
|
||
echo '<button class="btn btn-dark" disabled>文件不可写</button>';
|
||
}
|
||
echo '
|
||
</div>
|
||
</form>
|
||
</div>
|
||
';
|
||
return;
|
||
case 'image':
|
||
echo '
|
||
<div class="card view-image">
|
||
<img src="', $path, '" class="card-img-top">
|
||
<div class="card-body">
|
||
<a href="', $path, '" class="card-link">查看原图</a>
|
||
</div>
|
||
</div>
|
||
';
|
||
return;
|
||
default:
|
||
echo '
|
||
<div class="card">
|
||
<div class="card-body">
|
||
<a href="', $path, '" class="card-link">下载文件</a>
|
||
</div>
|
||
</div>
|
||
';
|
||
return;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 上传文件视图
|
||
* @param string $path 路径
|
||
*/
|
||
static function view_upload($path)
|
||
{
|
||
echo '
|
||
<div class="upload">
|
||
<form method="post" enctype="multipart/form-data" action="?action=upload&path=' . $path . '">
|
||
<div class="row mb-4">
|
||
<label class="col-sm-2 col-form-label">远程 URL</label>
|
||
<div class="col-sm-10">
|
||
<input type="text" class="form-control" name="url">
|
||
</div>
|
||
</div>
|
||
<div class="row mb-4">
|
||
<label class="col-sm-2 col-form-label">本地文件</label>
|
||
<div class="col-sm-10">
|
||
<input type="file" class="form-control" name="file">
|
||
</div>
|
||
</div>
|
||
<div class="d-grid">
|
||
<button type="submit" class="btn btn-dark">立即上传</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
';
|
||
}
|
||
|
||
/**
|
||
* 重命名文件视图
|
||
* @param string $path 路径
|
||
*/
|
||
static function view_rename($path)
|
||
{
|
||
echo '
|
||
<div class="rename">
|
||
<form method="post" action="?action=rename&path=' . $path . '">
|
||
<div class="row mb-3">
|
||
<label class="col-sm-2 col-form-label">原名称</label>
|
||
<div class="col-sm-10">
|
||
<input type="text" class="form-control" value="' . basename($path) . '" readonly>
|
||
</div>
|
||
</div>
|
||
<div class="row mb-4">
|
||
<label class="col-sm-2 col-form-label">新名称</label>
|
||
<div class="col-sm-10">
|
||
<input type="text" class="form-control" name="filename">
|
||
</div>
|
||
</div>
|
||
<div class="d-grid">
|
||
<button type="submit" class="btn btn-dark">重命名</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
';
|
||
}
|
||
|
||
/**
|
||
* 编辑权限视图
|
||
* @param string $path 路径
|
||
*/
|
||
static function view_chmod($path)
|
||
{
|
||
$sapath = RexHelper::path_rtoa($path);
|
||
$perms = substr(sprintf("%o", fileperms($sapath)), -4);
|
||
echo '
|
||
<div class="chmod">
|
||
<form method="post" action="?action=chmod&path=' . $path . '">
|
||
<div class="row mb-3">
|
||
<label class="col-sm-2 col-form-label">名称</label>
|
||
<div class="col-sm-10">
|
||
<input type="text" class="form-control" value="' . basename($path) . '" disabled>
|
||
</div>
|
||
</div>
|
||
<div class="row mb-4">
|
||
<label class="col-sm-2 col-form-label">权限模式</label>
|
||
<div class="col-sm-10">
|
||
<input type="text" class="form-control" name="mode" value="' . $perms . '">
|
||
</div>
|
||
</div>
|
||
<div class="d-grid">
|
||
<button type="submit" class="btn btn-dark">设置</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
';
|
||
}
|
||
|
||
/**
|
||
* 压缩文件视图
|
||
* @param string $path 路径
|
||
*/
|
||
static function view_zip($path)
|
||
{
|
||
echo '
|
||
<div class="zip">
|
||
<form method="post" action="?action=zip&path=' . $path . '">
|
||
<div class="row mb-3">
|
||
<label class="col-sm-2 col-form-label">压缩文件名</label>
|
||
<div class="col-sm-10">
|
||
<input type="text" class="form-control" name="filename" value="/test.zip">
|
||
</div>
|
||
</div>
|
||
<div class="row mb-4">
|
||
<label class="col-sm-2 col-form-label">文件列表</label>
|
||
<div class="col-sm-10">
|
||
<textarea class="form-control" name="content" rows="10">' . $path . '</textarea>
|
||
</div>
|
||
</div>
|
||
<div class="row mb-3">
|
||
<label class="col-sm-2 col-form-label">去除根路径</label>
|
||
<div class="col-sm-10">
|
||
<input type="text" class="form-control" name="trimpath" placeholder="/www">
|
||
</div>
|
||
</div>
|
||
<div class="d-grid">
|
||
<button type="submit" class="btn btn-dark">压缩</button>
|
||
</div>
|
||
</form>
|
||
<div class="alert alert-secondary mt-2" role="alert">
|
||
注意,所有路径都相对于目录 ' . RexHelper::$root . '<br />
|
||
文件列表:每个路径一行,支持排除路径<br />
|
||
包含路径示例:/www/app<br />
|
||
排除路径示例:exclude /www/app/log<br />
|
||
</div>
|
||
</div>
|
||
';
|
||
}
|
||
|
||
/**
|
||
* 解压缩文件视图
|
||
* @param string $path 路径
|
||
*/
|
||
static function view_unzip($path)
|
||
{
|
||
echo '
|
||
<div class="unzip">
|
||
<form method="post" action="?action=unzip&path=' . $path . '">
|
||
<div class="row mb-3">
|
||
<label class="col-sm-2 col-form-label">压缩包路径</label>
|
||
<div class="col-sm-10">
|
||
<input type="text" class="form-control" name="filename" value="/test.zip">
|
||
</div>
|
||
</div>
|
||
<div class="row mb-3">
|
||
<label class="col-sm-2 col-form-label">解压缩路径</label>
|
||
<div class="col-sm-10">
|
||
<input type="text" class="form-control" name="root" value="' . $path . '">
|
||
</div>
|
||
</div>
|
||
<div class="d-grid">
|
||
<button type="submit" class="btn btn-dark">解压</button>
|
||
</div>
|
||
<div class="alert alert-secondary mt-2" role="alert">
|
||
注意,所有路径都相对于' . RexHelper::$root . '
|
||
</div>
|
||
</form>
|
||
</div>
|
||
';
|
||
}
|
||
|
||
/**
|
||
* 全局操作菜单
|
||
* @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 '
|
||
<nav class="navbar navbar-inverse" role="navigation">
|
||
<div class="container-fluid">
|
||
<!-- 导航头部 -->
|
||
<div class="navbar-header">
|
||
<!-- 移动设备上的导航切换按钮 -->
|
||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse-example">
|
||
<span class="sr-only">切换导航</span>
|
||
<span class="icon-bar"></span>
|
||
<span class="icon-bar"></span>
|
||
<span class="icon-bar"></span>
|
||
</button>
|
||
<!-- 品牌名称或logo -->
|
||
<a class="navbar-brand" href="?">文件管理</a>
|
||
</div>
|
||
<!-- 导航项目 -->
|
||
<div class="collapse navbar-collapse navbar-collapse-example">
|
||
<!-- 一般导航项目 -->
|
||
<ul class="nav navbar-nav">
|
||
<li class="' . ($view == 'newdir' ? 'active' : '') . '"><a href="?view=newdir&path=' . $pdir . '">新建目录</a></li>
|
||
<li class="' . ($view == 'newfile' ? 'active' : '') . '"><a href="?view=newfile&path=' . $pdir . '">新建文件</a></li>
|
||
<li class="' . ($view == 'upload' ? 'active' : '') . '"><a href="?view=upload&path=' . $pdir . '">上传文件</a></li>
|
||
<li class="' . ($view == 'zip' ? 'active' : '') . '"><a href="?view=zip&path=' . $pdir . '">打包目录</a></li>
|
||
<li class="' . ($view == 'unzip' ? 'active' : '') . '"><a href="?view=unzip&path=' . $pdir . '">解压文件</a></li>
|
||
<li class="' . ($view == 'opreset' ? 'active' : '') . '"><a href="?action=opreset&path=' . $path . '">清空OPCache</a></li>
|
||
</ul>
|
||
<!-- 右侧的导航项目 -->
|
||
<ul class="nav navbar-nav navbar-right">
|
||
<li><a href="your/nice/url">欢迎您, ' . $member['username'] . '</a></li>
|
||
<li><a href="?action=logout">注销</a></li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</nav>';
|
||
}
|
||
|
||
/**
|
||
* 路径转为导航
|
||
* @param string $path 路径
|
||
*/
|
||
static function body_breadcrumb($path)
|
||
{
|
||
echo '
|
||
<nav class="mb-3">
|
||
<ol class="breadcrumb">
|
||
<li class="breadcrumb-item"><a href="?path=/">HOME</a></li>
|
||
';
|
||
$full = '';
|
||
$items = explode('/', trim($path, '/'));
|
||
foreach ($items as $item) {
|
||
$full .= '/' . $item;
|
||
echo '<li class="breadcrumb-item"><a href="?path=', $full, '">', $item, '</a></li>';
|
||
}
|
||
echo '
|
||
</ol>
|
||
</nav>
|
||
';
|
||
}
|
||
|
||
/**
|
||
* 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 '
|
||
<div class="container pt-3">
|
||
<div class="alert alert-' . $cat . '" role="alert">
|
||
' . $msg . $sec . '秒后重定向到 ' . $url . '
|
||
</div>
|
||
</div>
|
||
<script type="text/javascript">
|
||
setTimeout(function() {
|
||
location.href = "' . $url . '";
|
||
}, ' . $sec * 1000 . ');
|
||
</script>
|
||
';
|
||
exit('</body></html>');
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 回调方法类
|
||
*/
|
||
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';
|