From 0a7a6cbe9ec54a1ee9427a51794cb4fe1a2b27a0 Mon Sep 17 00:00:00 2001 From: Baoshuo Date: Thu, 13 Oct 2022 13:34:55 +0800 Subject: [PATCH] feat(web/image_hosting): image upload --- db/app_uoj233.sql | 12 +- docker-compose.development.yml | 8 + web/app/controllers/image_hosting/index.php | 266 +++++++++++++++++- web/app/libs/uoj-rand-lib.php | 2 +- web/app/route.php | 4 +- web/app/upgrade/4_image_hosting/up.sql | 14 +- web/app/views/main-nav.php | 2 +- web/fonts/roboto-mono/RobotoMono-Bold.ttf | Bin 0 -> 87008 bytes .../roboto-mono/RobotoMono-BoldItalic.ttf | Bin 0 -> 94148 bytes .../roboto-mono/RobotoMono-ExtraLight.ttf | Bin 0 -> 87788 bytes .../RobotoMono-ExtraLightItalic.ttf | Bin 0 -> 93408 bytes web/fonts/roboto-mono/RobotoMono-Italic.ttf | Bin 0 -> 93904 bytes web/fonts/roboto-mono/RobotoMono-Light.ttf | Bin 0 -> 87592 bytes .../roboto-mono/RobotoMono-LightItalic.ttf | Bin 0 -> 93760 bytes web/fonts/roboto-mono/RobotoMono-Medium.ttf | Bin 0 -> 86820 bytes .../roboto-mono/RobotoMono-MediumItalic.ttf | Bin 0 -> 93948 bytes web/fonts/roboto-mono/RobotoMono-Regular.ttf | Bin 0 -> 86908 bytes web/fonts/roboto-mono/RobotoMono-SemiBold.ttf | Bin 0 -> 87076 bytes .../roboto-mono/RobotoMono-SemiBoldItalic.ttf | Bin 0 -> 93940 bytes web/fonts/roboto-mono/RobotoMono-Thin.ttf | Bin 0 -> 87872 bytes .../roboto-mono/RobotoMono-ThinItalic.ttf | Bin 0 -> 93056 bytes 21 files changed, 291 insertions(+), 17 deletions(-) create mode 100644 web/fonts/roboto-mono/RobotoMono-Bold.ttf create mode 100644 web/fonts/roboto-mono/RobotoMono-BoldItalic.ttf create mode 100644 web/fonts/roboto-mono/RobotoMono-ExtraLight.ttf create mode 100644 web/fonts/roboto-mono/RobotoMono-ExtraLightItalic.ttf create mode 100644 web/fonts/roboto-mono/RobotoMono-Italic.ttf create mode 100644 web/fonts/roboto-mono/RobotoMono-Light.ttf create mode 100644 web/fonts/roboto-mono/RobotoMono-LightItalic.ttf create mode 100644 web/fonts/roboto-mono/RobotoMono-Medium.ttf create mode 100644 web/fonts/roboto-mono/RobotoMono-MediumItalic.ttf create mode 100644 web/fonts/roboto-mono/RobotoMono-Regular.ttf create mode 100644 web/fonts/roboto-mono/RobotoMono-SemiBold.ttf create mode 100644 web/fonts/roboto-mono/RobotoMono-SemiBoldItalic.ttf create mode 100644 web/fonts/roboto-mono/RobotoMono-Thin.ttf create mode 100644 web/fonts/roboto-mono/RobotoMono-ThinItalic.ttf diff --git a/db/app_uoj233.sql b/db/app_uoj233.sql index cc468cb..bb96614 100644 --- a/db/app_uoj233.sql +++ b/db/app_uoj233.sql @@ -837,16 +837,20 @@ UNLOCK TABLES; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `users_images` ( - `id` varchar(30) NOT NULL, - `username` varchar(20) NOT NULL, + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `path` varchar(100) NOT NULL, + `uploader` varchar(20) NOT NULL, `width` int(11) NOT NULL, `height` int(11) NOT NULL, `upload_time` datetime NOT NULL, `size` int(11) NOT NULL, + `hash` varchar(70) NOT NULL, PRIMARY KEY (`id`), - KEY `username` (`username`), + KEY `uploader` (`uploader`), + KET `path` (`path`), KEY `upload_time` (`upload_time`), - KEY `size` (`size`) + KEY `size` (`size`), + KEY `hash` (`hash`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; diff --git a/docker-compose.development.yml b/docker-compose.development.yml index 531f1a5..2158beb 100644 --- a/docker-compose.development.yml +++ b/docker-compose.development.yml @@ -11,6 +11,14 @@ services: environment: - MYSQL_DATABASE=app_uoj233 - MYSQL_ROOT_PASSWORD=root + + phpmyadmin: + image: phpmyadmin + restart: always + ports: + - 28080:80 + environment: + - PMA_ARBITRARY=1 uoj-judger: build: diff --git a/web/app/controllers/image_hosting/index.php b/web/app/controllers/image_hosting/index.php index ca06821..d86685e 100644 --- a/web/app/controllers/image_hosting/index.php +++ b/web/app/controllers/image_hosting/index.php @@ -1,21 +1,279 @@ 'error', 'message' => $msg])); + } + + $allowedTypes = [IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_GIF]; + if ($_POST['image_upload_file_submit'] == 'submit') { + header('Content-Type: application/json'); + + if (!crsf_check()) { + throwError('expired'); + } + + if (!isset($_SESSION['phrase']) || !PhraseBuilder::comparePhrases($_SESSION['phrase'], $_POST['captcha'])) { + throwError("bad_captcha"); + } + + if ($_FILES["image_upload_file"]["error"] > 0) { + throwError($_FILES["image_upload_file"]["error"]); + } + + if ($_FILES["image_upload_file"]["size"] > 5242880) { // 5 MB + throwError('too_large'); + } + + if ($used + $_FILES["image_upload_file"]["size"] > $limit) { + throwError('storage_limit_exceeded'); + } + + $size = getimagesize($_FILES['image_upload_file']['tmp_name']); + + if (!$size || !in_array($size[2], $allowedTypes)) { + throwError('not_a_image'); + } + + list($width, $height, $type) = $size; + $hash = hash_file("sha256", $_FILES['image_upload_file']['tmp_name']); + + $watermark_text = UOJConfig::$data['profile']['oj-name-short']; + if (isSuperUser($myUser) && $_POST['watermark'] == 'no_watermark') { + $watermark_text = ""; + $hash += "__no"; + } elseif ($_POST['watermark'] == 'site_shortname_and_username') { + $watermark_text .= ' @'.Auth::id(); + $hash += "__id"; + } + + $existing_image = DB::selectFirst("SELECT * FROM users_images WHERE `hash` = '$hash'"); + + if ($existing_image) { + die(json_encode(['status' => 'success', 'path' => $existing_image['path']])); + } + + $img = imagecreatefromstring(file_get_contents($_FILES["image_upload_file"]["tmp_name"])); + $white = imagecolorallocate($img, 255, 255, 255); + $black = imagecolorallocate($img, 150, 150, 150); + + imagettftext($img, '16', 0, 10 + 1, max(0, $height - 20) + 1, $black, UOJContext::documentRoot().'/fonts/roboto-mono/RobotoMono-Bold.ttf', $watermark_text); + imagettftext($img, '16', 0, 10, max(0, $height - 20), $white, UOJContext::documentRoot().'/fonts/roboto-mono/RobotoMono-Bold.ttf', $watermark_text); + imagepng($img, $_FILES["image_upload_file"]["tmp_name"]); + imagedestroy($img); + + $filename = uojRandAvaiableFileName('/image_hosting/', 10, '.png'); + if (!move_uploaded_file($_FILES["image_upload_file"]["tmp_name"], UOJContext::storagePath().$filename)) { + throwError('unknown error'); + } + + DB::insert("INSERT INTO users_images (`path`, uploader, width, height, upload_time, size, `hash`) VALUES ('$filename', '{$myUser['username']}', $width, $height, now(), {$_FILES["image_upload_file"]["size"]}, '$hash')"); + + die(json_encode(['status' => 'success', 'path' => $filename])); + } ?> + +

+
+
+
+
+ + 点击此处选择图片 +
+ + +
+

水印

+ +
+ + +
+ +
+ + +
+
+ + +
+
+
+

上传须知

+
    +
  • 上传的图片必须符合法律与社会道德;
  • +
  • 图床仅供 S2OJ 站内使用;
  • +
  • 在合适的地方插入图片即可引用。
  • +
+
+
+
+
+ + diff --git a/web/app/libs/uoj-rand-lib.php b/web/app/libs/uoj-rand-lib.php index 5c40015..838d777 100644 --- a/web/app/libs/uoj-rand-lib.php +++ b/web/app/libs/uoj-rand-lib.php @@ -17,7 +17,7 @@ function uojRandAvaiableFileName($dir, $length = 20, $suffix = '') { do { $fileName = $dir . uojRandString($length); } while (file_exists(UOJContext::storagePath().$fileName.$suffix)); - return $fileName; + return $fileName.$suffix; } function uojRandAvaiableTmpFileName() { diff --git a/web/app/route.php b/web/app/route.php index 753207d..43377cb 100644 --- a/web/app/route.php +++ b/web/app/route.php @@ -81,8 +81,8 @@ Route::group([ Route::any('/click-zan', '/click_zan.php'); // Image Hosting - Route::any('/image-hosting', '/image_hosting/index.php'); - Route::get('/image-hosting/{image_name}.png', '/image_hosting/get_image.php'); + Route::any('/image_hosting', '/image_hosting/index.php'); + Route::get('/image_hosting/{image_name}.png', '/image_hosting/get_image.php'); } ); diff --git a/web/app/upgrade/4_image_hosting/up.sql b/web/app/upgrade/4_image_hosting/up.sql index 5a64bd1..14a47f6 100644 --- a/web/app/upgrade/4_image_hosting/up.sql +++ b/web/app/upgrade/4_image_hosting/up.sql @@ -6,16 +6,20 @@ ALTER TABLE `user_info` ADD COLUMN `images_size_limit` int(11) UNSIGNED NOT NULL /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8mb4 */; -CREATE TABLE IF NOT EXISTS `users_images` ( - `id` varchar(30) NOT NULL, - `username` varchar(20) NOT NULL, +CREATE TABLE `users_images` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `path` varchar(100) NOT NULL, + `uploader` varchar(20) NOT NULL, `width` int(11) NOT NULL, `height` int(11) NOT NULL, `upload_time` datetime NOT NULL, `size` int(11) NOT NULL, + `hash` varchar(70) NOT NULL, PRIMARY KEY (`id`), - KEY `username` (`username`), + KEY `uploader` (`uploader`), + KEY `path` (`path`), KEY `upload_time` (`upload_time`), - KEY `size` (`size`) + KEY `size` (`size`), + KEY `hash` (`hash`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; /*!40101 SET character_set_client = @saved_cs_client */; diff --git a/web/app/views/main-nav.php b/web/app/views/main-nav.php index 0ad8496..ee77856 100644 --- a/web/app/views/main-nav.php +++ b/web/app/views/main-nav.php @@ -111,7 +111,7 @@ mb-4" role="navigation">