diff --git a/README.md b/README.md index ec53303..020ff24 100755 --- a/README.md +++ b/README.md @@ -231,6 +231,7 @@ $HTTP["url"] =~ "^/(i|public)/" {
点击查看2.0版更新日志 * 2023-02-01 v2.7.0 dev +- 增加限制游客上传 - 增加上传历史记录 - 增加粘贴上传状态 - 增加广场非图片图标 diff --git a/admin/admin.inc.php b/admin/admin.inc.php index d89d668..05d8863 100755 --- a/admin/admin.inc.php +++ b/admin/admin.inc.php @@ -487,9 +487,9 @@ if (isset($_GET['recycle_reimg'])) {
- +
- +
@@ -519,24 +519,6 @@ if (isset($_GET['recycle_reimg'])) { -
- - -
-
- - - -
-
- - - -
@@ -727,6 +709,45 @@ if (isset($_GET['recycle_reimg'])) {
+
+
+
+ + + +
+
+
+
+ + + +
+
+
+
+
+
+
+ 游客上传限制 + + +
+
+
+
+
+
+ 图片鉴黄 + +
+
+
+
" placeholder="隐藏的保存">
diff --git a/api/index.php b/api/index.php index 015555d..76b3f61 100755 --- a/api/index.php +++ b/api/index.php @@ -31,6 +31,25 @@ if ($config['check_ip']) { } } +// 根据IP限制游客每日上传数量 +if ($config['ip_upload_counts'] > 0 && !is_who_login(null)) { + $ipList = APP_ROOT . '/admin/logs/ipcounts/' . date('Ymd') . '.php'; + if (is_file($ipList)) { + $ipList = file_get_contents($ipList); + $ipList = explode(PHP_EOL, $ipList); + if (array_count_values($ipList)[real_ip()] >= $config['ip_upload_counts']) { + exit(json_encode( + array( + "result" => "failed", + "code" => 403, + "message" => "游客限制每日上传 " . $config['ip_upload_counts'] . ' 张', + ) + )); + } + clearstatcache(); + } +} + $token = preg_replace('/[\W]/', '', $_POST['token']); // 获取Token并过滤非字母数字,删除空格; // 检查api合法性 @@ -168,8 +187,6 @@ if ($handle->uploaded) { } /** 后续处理 */ - require APP_ROOT . '/application/process.php'; - // 使用fastcgi_finish_request操作 if (function_exists('fastcgi_finish_request')) { fastcgi_finish_request(); @@ -181,6 +198,8 @@ if ($handle->uploaded) { @water($handle->file_dst_pathname); // 压缩 @compress($handle->file_dst_pathname); + // 记录同IP上传次数 + @ip_upload_counts(); } else { // 鉴黄 @process_checkImg($processUrl); @@ -190,6 +209,8 @@ if ($handle->uploaded) { @water($handle->file_dst_pathname); // 压缩 @compress($handle->file_dst_pathname); + // 记录同IP上传次数 + @ip_upload_counts(); } unset($handle); diff --git a/application/function.php b/application/function.php index 0c762b0..42dadf6 100755 --- a/application/function.php +++ b/application/function.php @@ -38,7 +38,7 @@ define('IS_WIN', strstr(PHP_OS, 'WIN') ? 1 : 0); require_once APP_ROOT . '/config/config.php'; require_once APP_ROOT . '/config/config.guest.php'; - +require_once __DIR__ . '/WaterMask.php'; /** * 判断GIF图片是否为动态 * @param $filename string 文件 @@ -759,15 +759,21 @@ function getDel($url, $type) /** * 判断是否此用户登录 - * @param $user string 需要判断的用户名 + * @param string $user 判断登录者权限 当$user=null 时检查是否登录, 不区分身份 * @return bool 是|否 */ function is_who_login($user) { + if (empty($user)) { + if (checkLogin() == 205 || checkLogin() == 204) return true; + return false; + } + $status = json_decode(_login(), true); if ($user == 'admin') { if ($status['level'] == 1) return true; } + if ($user == 'guest') { if ($status['level'] == 2) return true; } @@ -1516,6 +1522,152 @@ function get_current_version($file = '/admin/version.php') return 'No Version File'; } +// 压缩图片与图片鉴黄 +function compress($absolutePath) +{ + global $config; + + // 压缩图片 后压缩模式,不影响前台输出速度 + if ($config['compress']) { + if (!is_Gif_Webp_Animated($absolutePath)) { + require_once __DIR__ . '/compress/Imagick/class.Imgcompress.php'; + $percent = $config['compress_ratio'] / 100; // 压缩率 + $img = new Imgcompress($absolutePath, $percent); + $img->compressImg($absolutePath); + // 释放 + ob_flush(); + flush(); + } + } +} + +// 设置水印 +function water($source) +{ + global $config; + + // 文字水印 + if ($config['watermark'] == 1) { + // 过滤gif + if (!is_Gif_Webp_Animated($source)) { + $arr = [ + # 水印图片路径(如果不存在将会被当成是字符串水印) + 'res' => $config['waterText'], + # 水印显示位置 + 'pos' => $config['waterPosition'], + # 不指定name(会覆盖原图,也就是保存成thumb.jpeg) + 'name' => $source, + 'font' => APP_ROOT . $config['textFont'], + 'fontSize' => $config['textSize'], + 'color' => str_replace(array('rgba', '(', ')'), '', $config['textColor']), + ]; + Imgs::setWater($source, $arr); + } + } + + // 图片水印 + if ($config['watermark'] == 2) { + // 过滤gif + if (!is_Gif_Webp_Animated($source)) { + $arr = [ + # 水印图片路径(如果不存在将会被当成是字符串水印) + 'res' => APP_ROOT . $config['waterImg'], + # 水印显示位置 + 'pos' => $config['waterPosition'], + # 不指定name(会覆盖原图,也就是保存成thumb.jpeg) + 'name' => $source, + ]; + Imgs::setWater($source, $arr); + } + } +} + +function process_checkImg($imgurl) +{ + global $config; + // 图片违规检查 + if ($config['checkImg'] == 1) { + checkImg($imgurl, 1); + } + + if ($config['checkImg'] == 2) { + checkImg($imgurl, 2); + } +} + +/** + * 写日志 + * + * 格式: + * { + * 上传图片名称{ + * source:源文件名称, + * date:上传日期(Asia/Shanghai), + * ip:上传者IP,port:IP端口, + * user_agent:上传者浏览器信息, + * path:文件相对路径, + * size:文件大小(格式化), + * md5:文件MD5, + * checkImg:鉴黄状态, + * form:上传方式web/API ID + * } + * } + * + * $filePath 文件相对路径 + * $sourceName 源文件名称 + * $absolutePath 图片的绝对路径 + * $fileSize 图片的大小 + * $form 来源如果是网页上传直接显示网页,如果是API上传则显示ID + */ +function write_log($filePath, $sourceName, $absolutePath, $fileSize, $from = "web") +{ + global $config; + + $checkImg = $config['checkImg'] == true ? "ON" : "OFF"; + + // $name = trim(basename($filePath), " \t\n\r\0\x0B"); // 当前图片名称 + $log = array(basename($filePath) => array( // 以上传图片名称为Array + 'source' => $sourceName, // 原始文件名称 + 'date' => date('Y-m-d H:i:s'), // 上传日期 + 'ip' => real_ip(), // 上传IP + 'port' => $_SERVER['REMOTE_PORT'], // IP端口 + 'user_agent' => $_SERVER['HTTP_USER_AGENT'], // 浏览器信息 + 'path' => $filePath, // 文件相对路径 + 'size' => getDistUsed($fileSize), // 文件大小(格式化) + 'md5' => md5_file($absolutePath), // 文件的md5 + 'checkImg' => $checkImg, // 鉴黄状态 + 'from' => $from, // 图片上传来源 + )); + + // 创建日志文件夹 + if (!is_dir(APP_ROOT . '/admin/logs/upload/')) { + mkdir(APP_ROOT . '/admin/logs/upload', 0755, true); + } + + // logs文件组成 + $logFileName = APP_ROOT . '/admin/logs/upload/' . date('Y-m') . '.php'; + + // 创建logs文件 + if (!is_file($logFileName)) { + file_put_contents($logFileName, ''); + } + + // 引入logs + include $logFileName; + + // // 写入禁止浏览器直接访问 + // if (filesize($logFileName) == 0) { + // $php_exit = ''; + // file_put_contents($logFileName, $php_exit); + // } + + // $log = json_encode($log, JSON_UNESCAPED_UNICODE); + // file_put_contents($logFileName, PHP_EOL . $log, FILE_APPEND | LOCK_EX); + + $log = array_replace($logs, $log); + cache_write($logFileName, $log, 'logs'); +} + /** * IP地址查询 */ @@ -1555,3 +1707,18 @@ function ip2region(String $IP) echo PHP_EOL; */ } + +/** + * 记录同IP每日上传次数 + */ +function ip_upload_counts() +{ + $dir = APP_ROOT . '/admin/logs/ipcounts/'; + + if (!is_dir($dir)) { + mkdir($dir, 0777); + } + + $file = $dir . date('Ymd') . '.php'; + file_put_contents($file, real_ip() . PHP_EOL, FILE_APPEND | LOCK_EX); +} diff --git a/application/history.php b/application/history.php index 167a93e..a664647 100644 --- a/application/history.php +++ b/application/history.php @@ -25,7 +25,7 @@ include_once __DIR__ . "/header.php"; console.log('url list: ' + value['url']) // 获取所有链接 if (value['url'] !== undefined) { let v_url = parseURL(value['url']); // 获取链接路径 console.log(parseURL(value['url']).path); - $('.listNum').append('') + $('.listNum').append('') } }) $('.history_clear').append('

'); diff --git a/application/info.php b/application/info.php index 2a2b3ca..5274477 100755 --- a/application/info.php +++ b/application/info.php @@ -8,12 +8,17 @@ if (isset($_GET['img'])) { // 过滤特殊符号 $getIMG = strip_tags($_GET['img']); $del_url = $config['domain'] . $getIMG; +} elseif (isset($_GET['history'])) { + // 过滤特殊符号 + $getIMG = $config['path'] . ltrim(strip_tags($_GET['history']), '/'); + $del_url = $config['domain'] . $getIMG; } else { // 未获取到图片地址 $getIMG = "/public/images/404.png"; $del_url = "#"; } + // 开启隐藏上传目录 if ($config['hide_path']) { $img_url = rand_imgurl() . str_replace($config['path'], '/', $getIMG); @@ -40,9 +45,8 @@ if (empty($logs[$logsName])) { } // 图片真实路径 $imgABPath = APP_ROOT . $getIMG; - // 图片是否存在 -if (!file_exists($imgABPath)) { +if (!is_file($imgABPath)) { $imgABPath = APP_ROOT . "/public/images/404.png"; $img_url = rand_imgurl() . "/public/images/404.png"; } diff --git a/application/process.php b/application/process.php deleted file mode 100755 index ede4920..0000000 --- a/application/process.php +++ /dev/null @@ -1,149 +0,0 @@ -compressImg($absolutePath); - // 释放 - ob_flush(); - flush(); - } - } -} - -// 设置水印 -function water($source) -{ - global $config; - - // 文字水印 - if ($config['watermark'] == 1) { - // 过滤gif - if (!is_Gif_Webp_Animated($source)) { - $arr = [ - # 水印图片路径(如果不存在将会被当成是字符串水印) - 'res' => $config['waterText'], - # 水印显示位置 - 'pos' => $config['waterPosition'], - # 不指定name(会覆盖原图,也就是保存成thumb.jpeg) - 'name' => $source, - 'font' => APP_ROOT . $config['textFont'], - 'fontSize' => $config['textSize'], - 'color' => str_replace(array('rgba', '(', ')'), '', $config['textColor']), - ]; - Imgs::setWater($source, $arr); - } - } - - // 图片水印 - if ($config['watermark'] == 2) { - // 过滤gif - if (!is_Gif_Webp_Animated($source)) { - $arr = [ - # 水印图片路径(如果不存在将会被当成是字符串水印) - 'res' => APP_ROOT . $config['waterImg'], - # 水印显示位置 - 'pos' => $config['waterPosition'], - # 不指定name(会覆盖原图,也就是保存成thumb.jpeg) - 'name' => $source, - ]; - Imgs::setWater($source, $arr); - } - } -} - -function process_checkImg($imgurl) -{ - global $config; - // 图片违规检查 - if ($config['checkImg'] == 1) { - checkImg($imgurl, 1); - } - - if ($config['checkImg'] == 2) { - checkImg($imgurl, 2); - } -} - -/** - * 写日志 - * - * 格式: - * { - * 上传图片名称{ - * source:源文件名称, - * date:上传日期(Asia/Shanghai), - * ip:上传者IP,port:IP端口, - * user_agent:上传者浏览器信息, - * path:文件相对路径, - * size:文件大小(格式化), - * md5:文件MD5, - * checkImg:鉴黄状态, - * form:上传方式web/API ID - * } - * } - * - * $filePath 文件相对路径 - * $sourceName 源文件名称 - * $absolutePath 图片的绝对路径 - * $fileSize 图片的大小 - * $form 来源如果是网页上传直接显示网页,如果是API上传则显示ID - */ -function write_log($filePath, $sourceName, $absolutePath, $fileSize, $from = "web") -{ - global $config; - - $checkImg = $config['checkImg'] == true ? "ON" : "OFF"; - - // $name = trim(basename($filePath), " \t\n\r\0\x0B"); // 当前图片名称 - $log = array(basename($filePath) => array( // 以上传图片名称为Array - 'source' => $sourceName, // 原始文件名称 - 'date' => date('Y-m-d H:i:s'), // 上传日期 - 'ip' => real_ip(), // 上传IP - 'port' => $_SERVER['REMOTE_PORT'], // IP端口 - 'user_agent' => $_SERVER['HTTP_USER_AGENT'], // 浏览器信息 - 'path' => $filePath, // 文件相对路径 - 'size' => getDistUsed($fileSize), // 文件大小(格式化) - 'md5' => md5_file($absolutePath), // 文件的md5 - 'checkImg' => $checkImg, // 鉴黄状态 - 'from' => $from, // 图片上传来源 - )); - - // 创建日志文件夹 - if (!is_dir(APP_ROOT . '/admin/logs/upload/')) { - mkdir(APP_ROOT . '/admin/logs/upload', 0755, true); - } - - // logs文件组成 - $logFileName = APP_ROOT . '/admin/logs/upload/' . date('Y-m') . '.php'; - - // 创建logs文件 - if (!is_file($logFileName)) { - file_put_contents($logFileName, ''); - } - - // 引入logs - include $logFileName; - - // // 写入禁止浏览器直接访问 - // if (filesize($logFileName) == 0) { - // $php_exit = ''; - // file_put_contents($logFileName, $php_exit); - // } - - // $log = json_encode($log, JSON_UNESCAPED_UNICODE); - // file_put_contents($logFileName, PHP_EOL . $log, FILE_APPEND | LOCK_EX); - - $log = array_replace($logs, $log); - cache_write($logFileName, $log, 'logs'); -} diff --git a/application/upload.php b/application/upload.php index 0a349b8..1b4336b 100755 --- a/application/upload.php +++ b/application/upload.php @@ -7,7 +7,7 @@ require __DIR__ . '/class.upload.php'; // 检查登录 if ($config['mustLogin']) { - if (checkLogin() !== 204 && checkLogin() !== 205) { + if (is_who_login(null)) { exit(json_encode(array( "result" => "failed", "code" => 401, @@ -16,6 +16,17 @@ if ($config['mustLogin']) { } } +// 无文件 +if (empty($_FILES['file'])) { + exit(json_encode( + array( + "result" => "failed", + "code" => 204, + "message" => "没有选择上传的文件", + ) + )); +} + // 黑/白IP名单上传 if ($config['check_ip']) { if (checkIP(null, $config['check_ip_list'], $config['check_ip_model'])) { @@ -28,15 +39,23 @@ if ($config['check_ip']) { } } -// 无文件 -if (empty($_FILES['file'])) { - exit(json_encode( - array( - "result" => "failed", - "code" => 204, - "message" => "没有选择上传的文件", - ) - )); +// 根据IP限制游客每日上传数量 +if ($config['ip_upload_counts'] > 0 && !is_who_login(null)) { + $ipList = APP_ROOT . '/admin/logs/ipcounts/' . date('Ymd') . '.php'; + if (is_file($ipList)) { + $ipList = file_get_contents($ipList); + $ipList = explode(PHP_EOL, $ipList); + if (array_count_values($ipList)[real_ip()] >= $config['ip_upload_counts']) { + exit(json_encode( + array( + "result" => "failed", + "code" => 403, + "message" => "游客限制每日上传 " . $config['ip_upload_counts'] . ' 张', + ) + )); + } + clearstatcache(); + } } $handle = new Upload($_FILES['file'], 'zh_CN'); @@ -188,8 +207,6 @@ if ($handle->uploaded) { } /** 后续处理 */ - require __DIR__ . '/process.php'; - // 使用fastcgi_finish_request操作 if (function_exists('fastcgi_finish_request')) { fastcgi_finish_request(); @@ -201,6 +218,8 @@ if ($handle->uploaded) { @water($handle->file_dst_pathname); // 压缩 @compress($handle->file_dst_pathname); + // 记录同IP上传次数 + @ip_upload_counts(); } else { // 普通模式鉴黄 @process_checkImg($processUrl); @@ -210,6 +229,8 @@ if ($handle->uploaded) { @water($handle->file_dst_pathname); // 压缩 @compress($handle->file_dst_pathname); + // 记录同IP上传次数 + @ip_upload_counts(); } unset($handle); diff --git a/config/config.php b/config/config.php index ebd8190..1ea8fb3 100755 --- a/config/config.php +++ b/config/config.php @@ -1,4 +1,4 @@ -'简单图床 - EasyImage', @@ -85,6 +85,7 @@ $config=Array 'check_ip'=>0, 'check_ip_model'=>0, 'check_ip_list'=>'', + 'ip_upload_counts'=>0, 'public'=>0, 'public_list'=>Array ( @@ -112,7 +113,7 @@ $config=Array 'guest_path_status'=>0, 'token_path_status'=>0, 'admin_path'=>'u', - 'update'=>'2023-02-01 02:25:32', + 'update'=>'2023-02-01 22:12:10', 'footer'=>'© Since 2018 EasyImage DMCA