|
Server : Apache System : Linux iZ6xhqomji47p1Z 5.10.134-15.al8.x86_64 #1 SMP Thu Jul 20 00:44:04 CST 2023 x86_64 User : www ( 1000) PHP Version : 8.1.30 Disable Function : passthru,exec,system,putenv,chroot,chgrp,chown,shell_exec,popen,proc_open,pcntl_exec,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,imap_open,apache_setenv Directory : /www/wwwroot/fsjlkj.cn/application/admin/logic/ |
<?php
/**
* 易优CMS
* ============================================================================
* 版权所有 2016-2028 海南赞赞网络科技有限公司,并保留所有权利。
* 网站地址: http://www.eyoucms.com
* ----------------------------------------------------------------------------
* 如果商业用途务必到官方购买正版授权, 以免引起不必要的法律纠纷.
* ============================================================================
* Author: 小虎哥 <1105415366@qq.com>
* Date: 2018-4-3
*/
namespace app\admin\logic;
use think\Model;
use think\Db;
/**
* 文件管理逻辑定义
* Class CatsLogic
* @package admin\Logic
*/
class FilemanagerLogic extends Model
{
public $globalTpCache = array();
public $baseDir = ''; // 服务器站点根目录绝对路径
public $maxDir = '';
public $replaceImgOpArr = array(); // 替换权限
public $editOpArr = array(); // 编辑权限
public $renameOpArr = array(); // 改名权限
public $delOpArr = array(); // 删除权限
public $moveOpArr = array(); // 移动权限
public $editExt = array(); // 允许新增/编辑扩展名文件
public $disableFuns = array(); // 允许新增/编辑扩展名文件
/**
* 析构函数
*/
function __construct() {
$this->globalTpCache = tpCache('global');
$this->baseDir = rtrim(ROOT_PATH, DS); // 服务器站点根目录绝对路径
$this->maxDir = $this->globalTpCache['web_templets_dir']; // 默认文件管理的最大级别目录
// 替换权限
$this->replaceImgOpArr = array('gif','jpg','svg');
// 编辑权限
$this->editOpArr = array('txt','htm','js','css');
// 改名权限
$this->renameOpArr = array('dir','gif','jpg','svg','flash','zip','exe','mp3','wmv','rm','txt','htm','js','css','other');
// 删除权限
$this->delOpArr = array('dir','gif','jpg','svg','flash','zip','exe','mp3','wmv','rm','txt','htm','php','js','css','other');
// 移动权限
$this->moveOpArr = array('gif','jpg','svg','flash','zip','exe','mp3','wmv','rm','txt','htm','js','css','other');
// 允许新增/编辑扩展名文件
$this->editExt = array('htm','js','css','txt');
// 过滤php危险函数
$this->disableFuns = ['phpinfo'];
}
/**
* 编辑文件
*
* @access public
* @param string $filename 文件名
* @param string $activepath 当前路径
* @param string $content 文件内容
* @return string
*/
public function editFile($filename, $activepath = '', $content = '')
{
$security = tpSetting('security');
if (empty($security['security_ask_open']) || empty($security['security_answer'])) {
return '需要开启二次验证密码';
} else {
$admin_id = session('?admin_id') ? (int)session('admin_id') : 0;
$admin_info = Db::name('admin')->field('admin_id,last_ip')->where(['admin_id'=>$admin_id])->find();
// 当前管理员二次安全验证过的IP地址
$security_answerverify_ip = !empty($security['security_answerverify_ip']) ? $security['security_answerverify_ip'] : '-1';
// 同IP不验证
if (empty($admin_info) || $admin_info['last_ip'] != $security_answerverify_ip) {
return '出于安全考虑,请勿非法越过二次安全验证';
}
}
if (!filename_preg_match()) {
return '文件名称含有非法入侵字符!';
}
$fileinfo = pathinfo($filename);
$ext = strtolower($fileinfo['extension']);
$filename = trim($fileinfo['filename'], '.').'.'.$fileinfo['extension'];
/*不允许越过指定最大级目录的文件编辑*/
$tmp_max_dir = preg_replace("#\/#i", "\/", $this->maxDir);
if (!preg_match("#^".$tmp_max_dir."#i", $activepath)) {
return '没有操作权限!';
}
/*--end*/
/*允许编辑的文件类型*/
if (!in_array($ext, $this->editExt)) {
return '只允许操作文件类型如下:'.implode('|', $this->editExt);
}
/*--end*/
$file = $this->baseDir."$activepath/$filename";
if (!is_writable(dirname($file))) {
return "请把模板文件目录设置为可写入权限!";
}
if ('htm' == $ext) {
$content = htmlspecialchars_decode($content, ENT_QUOTES);
if (preg_match('#<([^?]*)\?php#i', $content) || preg_match('#<\?(\s*)=#i', $content) || (preg_match('#<\?#i', $content) && preg_match('#\?>#i', $content)) || preg_match('#\{eyou\:php([^\}]*)\}#i', $content) || preg_match('#\{php([^\}]*)\}#i', $content) || preg_match('#(\s+)language(\s*)=(\s*)("|\')?php("|\')?#i', $content)) {
return "模板里不允许有php语法,为了安全考虑,请通过FTP工具进行编辑上传。";
}
foreach ($this->disableFuns as $key => $val) {
$val_new = msubstr($val, 0, 1).'-'.msubstr($val, 1);
$content = preg_replace("/(@)?".$val."(\s*)\(/i", "{$val_new}(", $content);
}
}
$fp = fopen($file, "w");
fputs($fp, $content);
fclose($fp);
return true;
}
/**
* 上传文件
*
* @param string $dirname 新目录
* @param string $activepath 当前路径
* @param boolean $replace 是否替换
* @param string $type 文件类型:图片image , 附件file , 视频media
*/
public function upload($fileElementId, $activepath = '', $replace = false, $type = 'image')
{
$retData = [];
$file = request()->file($fileElementId);
if (is_object($file) && !is_array($file)) {
$retData = $this->uploadfile($file, $activepath, $replace, $type);
}
else if (!is_object($file) && is_array($file)) {
$fileArr = $file;
$i = 0;
$j = 0;
foreach ($fileArr as $key => $fileObj) {
if (empty($fileObj)) {
continue;
}
$res = $this->uploadfile($fileObj, $activepath, $replace, $type);
if(!empty($res['code']) && $res['code'] == 1) {
$i++;
} else {
$j++;
}
}
if ($j == 0) {
$retData['code'] = 0;
$retData['msg'] = "上传失败 $i 个文件到: $activepath";
} else {
$retData['code'] = 1;
$retData['msg'] = "上传成功!";
}
}
return $retData;
}
/**
* 自定义上传
*
* @param object $file 文件对象
* @param string $activepath 当前路径
* @param boolean $replace 是否替换
* @param string $type 文件类型:图片image , 附件file , 视频media
*/
public function uploadfile($file, $activepath = '', $replace = false, $type = 'image')
{
$validate = array();
/*文件类型限制*/
switch ($type) {
case 'image':
$validate_ext = tpCache('basic.image_type');
break;
case 'file':
$validate_ext = tpCache('basic.file_type');
break;
case 'media':
$validate_ext = tpCache('basic.media_type');
break;
default:
$validate_ext = tpCache('basic.image_type');
break;
}
$validate['ext'] = explode('|', $validate_ext);
/*--end*/
/*文件大小限制*/
$validate_size = tpCache('basic.file_size');
if (!empty($validate_size)) {
$validate['size'] = $validate_size * 1024 * 1024; // 单位为b
}
/*--end*/
/*上传文件验证*/
if (!empty($validate)) {
$is_validate = $file->check($validate);
if ($is_validate === false) {
return ['code'=>0, 'msg'=>$file->getError()];
}
}
/*--end*/
$savePath = !empty($activepath) ? trim($activepath, '/') : UPLOAD_PATH.'temp';
if (!file_exists($savePath)) {
tp_mkdir($savePath);
}
if (false == $replace) {
$fileinfo = $file->getInfo();
$filename = pathinfo($fileinfo['name'], PATHINFO_BASENAME); //获取上传文件名
} else {
$filename = $replace;
}
$fileExt = pathinfo($filename, PATHINFO_EXTENSION); //获取上传文件扩展名
if (!in_array($fileExt, $validate['ext'])) {
return ['code'=>0, 'msg'=>'上传文件后缀不允许'];
}
// 使用自定义的文件保存规则
$info = $file->move($savePath, $filename, true);
if($info){
return ['code'=>1, 'msg'=>'上传成功'];
}else{
return ['code'=>0, 'msg'=>$file->getError()];
}
}
/**
* 当前目录下的文件列表
*/
public function getDirFile($directory, $activepath = '', &$arr_file = array()) {
if (!file_exists($directory)) {
return false;
}
$fileArr = $dirArr = $parentArr = array();
$mydir = dir($directory);
while(false !== $file = $mydir->read())
{
$filesize = $filetime = $intro = '';
$filemine = 'file';
if($file != "." && $file != ".." && !is_dir("$directory/$file"))
{
@$filesize = filesize("$directory/$file");
@$filesize = format_bytes($filesize);
@$filetime = filemtime("$directory/$file");
}
if ($file == '.')
{
continue;
}
else if($file == "..")
{
if($activepath == "" || $activepath == $this->maxDir) {
continue;
}
$parentArr = array(
array(
'filepath' => preg_replace("#[\/][^\/]*$#i", "", $activepath),
'filename' => '上级目录',
'filesize' => '',
'filetime' => '',
'filemine' => 'dir',
'filetype' => 'dir2',
'icon' => 'file_topdir.gif',
'intro' => '(当前目录:'.$activepath.')',
),
);
continue;
}
else if(is_dir("$directory/$file"))
{
if(preg_match("#^_(.*)$#i", $file)) continue; #屏蔽FrontPage扩展目录和linux隐蔽目录
if(preg_match("#^\.(.*)$#i", $file)) continue;
$file_info = array(
'filepath' => $activepath.'/'.$file,
'filename' => $file,
'filesize' => '',
'filetime' => '',
'filemine' => 'dir',
'filetype' => 'dir',
'icon' => 'dir.gif',
'intro' => '',
);
array_push($dirArr, $file_info);
continue;
}
else if(preg_match("#\.(gif|png)#i",$file))
{
$filemine = 'image';
$filetype = 'gif';
$icon = 'gif.gif';
}
else if(preg_match("#\.(jpg|jpeg|bmp|webp)#i",$file))
{
$filemine = 'image';
$filetype = 'jpg';
$icon = 'jpg.gif';
}
else if(preg_match("#\.(svg)#i",$file))
{
$filemine = 'image';
$filetype = 'svg';
$icon = 'jpg.gif';
}
else if(preg_match("#\.(swf|fla|fly)#i",$file))
{
$filetype = 'flash';
$icon = 'flash.gif';
}
else if(preg_match("#\.(zip|rar|tar.gz)#i",$file))
{
$filetype = 'zip';
$icon = 'zip.gif';
}
else if(preg_match("#\.(exe)#i",$file))
{
$filetype = 'exe';
$icon = 'exe.gif';
}
else if(preg_match("#\.(mp3|wma)#i",$file))
{
$filetype = 'mp3';
$icon = 'mp3.gif';
}
else if(preg_match("#\.(wmv|api)#i",$file))
{
$filetype = 'wmv';
$icon = 'wmv.gif';
}
else if(preg_match("#\.(rm|rmvb)#i",$file))
{
$filetype = 'rm';
$icon = 'rm.gif';
}
else if(preg_match("#\.(txt|inc|pl|cgi|asp|xml|xsl|aspx|cfm)#",$file))
{
$filetype = 'txt';
$icon = 'txt.gif';
}
else if(preg_match("#\.(htm|html)#i",$file))
{
$filetype = 'htm';
$icon = 'htm.gif';
}
else if(preg_match("#\.(php)#i",$file))
{
$filetype = 'php';
$icon = 'php.gif';
}
else if(preg_match("#\.(js)#i",$file))
{
$filetype = 'js';
$icon = 'js.gif';
}
else if(preg_match("#\.(css)#i",$file))
{
$filetype = 'css';
$icon = 'css.gif';
}
else
{
$filetype = 'other';
$icon = 'other.gif';
}
$file_info = array(
'filepath' => $activepath.'/'.$file,
'filename' => $file,
'filesize' => $filesize,
'filetime' => $filetime,
'filemine' => $filemine,
'filetype' => $filetype,
'icon' => $icon,
'intro' => $intro,
);
array_push($fileArr, $file_info);
}
$mydir->close();
$arr_file = array_merge($parentArr, $dirArr, $fileArr);
return $arr_file;
}
/**
* 将冒号符反替换为反斜杠,适用于IIS服务器在URL上的双重转义限制
* @param string $filepath 相对路径
* @param string $replacement 目标字符
* @param boolean $is_back false为替换,true为还原
*/
public function replace_path($activepath, $replacement = ':', $is_back = false)
{
$activepath = replace_path($activepath, $replacement, $is_back);
$activepath = preg_replace('/<(\w+)([^\>]*)>([^<]*)<\/(\w+)>/i', '', $activepath);
$activepath = preg_replace('/(<|>|;|\(|\)|\!)/i', '', $activepath);
return $activepath;
}
}