diff --git a/db/app_uoj233.sql b/db/app_uoj233.sql index db51e85..b20be87 100644 --- a/db/app_uoj233.sql +++ b/db/app_uoj233.sql @@ -697,6 +697,27 @@ LOCK TABLES `user_system_msg` WRITE; /*!40000 ALTER TABLE `user_system_msg` DISABLE KEYS */; /*!40000 ALTER TABLE `user_system_msg` ENABLE KEYS */; UNLOCK TABLES; + +create table pastes +( + `index` varchar(20) null, + creator varchar(20) null, + created_at datetime null, + content text null +); + +create unique index pastes_index_uindex + on pastes (`index`); + +create index pastes_created_at_index + on pastes (created_at); + +alter table pastes + add constraint pastes_pk + primary key (`index`); + + + /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; diff --git a/judger/.gitignore b/judger/.gitignore new file mode 100644 index 0000000..d89c3c0 --- /dev/null +++ b/judger/.gitignore @@ -0,0 +1,20 @@ +.conf.json +log/* +!/log/.gitkeep +uoj_judger/builtin/checker/* +!uoj_judger/builtin/checker/*.cpp +!uoj_judger/builtin/checker/*.h +uoj_judger/builtin/judger/* +!uoj_judger/builtin/judger/*.cpp +!uoj_judger/builtin/judger/*.h +uoj_judger/data +uoj_judger/include/uoj_work_path.h +uoj_judger/main_judger +uoj_judger/run/* +!uoj_judger/run/*.cpp +!uoj_judger/run/*.h +uoj_judger/work/* +uoj_judger/result/* +!uoj_judger/work/.gitkeep +!uoj_judger/result/.gitkeep + diff --git a/judger/judge_client b/judger/judge_client old mode 100644 new mode 100755 index 788049a..a27de0c --- a/judger/judge_client +++ b/judger/judge_client @@ -140,7 +140,7 @@ def handle_task(): uoj_download('/judger', 'judger_update.zip') execute('unzip -o judger_update.zip && cd %s && make clean && make' % uoj_judger_path()) except: - print(sys.stderr, "error when update") + print("error when update", file=sys.stderr) if jconf['judger_name'] == 'main_judger': uoj_sync_judge_client() need_restart = True @@ -149,7 +149,7 @@ def handle_task(): socket_server_thread.join() print_judge_client_status() - print(sys.stderr, "goodbye!") + print("goodbye!", file=sys.stderr) sys.exit(0) diff --git a/judger/log/judge.log b/judger/log/.gitkeep similarity index 100% rename from judger/log/judge.log rename to judger/log/.gitkeep diff --git a/judger/uoj_judger/builtin/judger/judger.cpp b/judger/uoj_judger/builtin/judger/judger.cpp index 273cd32..118e15b 100644 --- a/judger/uoj_judger/builtin/judger/judger.cpp +++ b/judger/uoj_judger/builtin/judger/judger.cpp @@ -34,7 +34,7 @@ void ordinary_test() { po.scr = scale_score(po.scr, conf_int("point_score", i, 100 / n)); add_point_info(po); } - } else if (nT == 1) { + } else if (nT == 1 && conf_str("subtask_type", 1, "packed") == "packed") { for (int i = 1; i <= n; i++) { report_judge_status_f("Judging Test #%d", i); PointInfo po = test_point("answer", i); diff --git a/judger/uoj_judger/run/run_program_conf.h b/judger/uoj_judger/run/run_program_conf.h index 68cf76e..bf1e32c 100644 --- a/judger/uoj_judger/run/run_program_conf.h +++ b/judger/uoj_judger/run/run_program_conf.h @@ -160,7 +160,7 @@ inline bool is_writable_file(string name) { if (name == "/") { return writable_file_name_set.count("system_root"); } - return is_in_set_smart(name, writable_file_name_set) || is_in_set_smart(realpath(name), readable_file_name_set); + return is_in_set_smart(name, writable_file_name_set) || is_in_set_smart(realpath(name), writable_file_name_set); } inline bool is_readable_file(const string &name) { if (is_writable_file(name)) { diff --git a/web/.gitignore b/web/.gitignore index 2bad924..94938ff 100644 --- a/web/.gitignore +++ b/web/.gitignore @@ -3,3 +3,11 @@ composer.phar composer.lock + +app/.config.php +app/storage/tmp/* +app/storage/submission/* +app/storage/paste/* +!app/storage/tmp/.gitkeep +!app/storage/submission/.gitkeep +!app/storage/paste/.gitkeep diff --git a/web/app/.default-config.php b/web/app/.default-config.php index 82c2adc..0981d9d 100644 --- a/web/app/.default-config.php +++ b/web/app/.default-config.php @@ -53,5 +53,10 @@ return [ 'switch' => [ 'web-analytics' => false, 'blog-domain-mode' => 3 + ], + 'tools' => [ + // 请仅在https下启用以下功能. + // 非https下, chrome无法进行复制. + 'map-copy-enabled' => false, ] ]; diff --git a/web/app/controllers/contests.php b/web/app/controllers/contests.php index eea2b46..a1a8e13 100644 --- a/web/app/controllers/contests.php +++ b/web/app/controllers/contests.php @@ -62,13 +62,14 @@ EOD; ); if ($rest_second <= 86400) { + $notification = json_encode($upcoming_contest_name . " 已经开始了。是否要跳转到比赛页面?"); echo <<
$upcoming_contest_name 倒计时
+ + "source code", + "name" => "paste", + "file_name" => "paste.code" + ] + ], + 'uojRandAvaiablePasteFileName', + 'handleUpload'); +$paste_form->succ_href = '/paste'; +$paste_form->runAtServer(); +echoUOJPageHeader("Paste!"); +$paste_form->printHTML(); +echoUOJPageFooter(); \ No newline at end of file diff --git a/web/app/controllers/paste_view.php b/web/app/controllers/paste_view.php new file mode 100644 index 0000000..16b8f65 --- /dev/null +++ b/web/app/controllers/paste_view.php @@ -0,0 +1,12 @@ +' . $errmsg . '返回'); } else { $zip_mime_types = array('application/zip', 'application/x-zip', 'application/x-zip-compressed'); - if (in_array($_FILES["problem_data_file"]["type"], $zip_mime_types)) { + if (in_array($_FILES["problem_data_file"]["type"], $zip_mime_types) || $_FILES["problem_data_file"]["type"] == 'application/octet-stream' && substr($_FILES["problem_data_file"]["name"], -4) == '.zip') { $up_filename="/tmp/".rand(0,100000000)."data.zip"; move_uploaded_file($_FILES["problem_data_file"]["tmp_name"], $up_filename); $zip = new ZipArchive; diff --git a/web/app/controllers/problem_set.php b/web/app/controllers/problem_set.php index 3c0a162..cb10f95 100644 --- a/web/app/controllers/problem_set.php +++ b/web/app/controllers/problem_set.php @@ -24,7 +24,7 @@ if (isProblemVisibleToUser($problem, $myUser)) { echo ''; if ($problem['submission_id']) { - echo ''; + echo ''; } else { echo ''; } diff --git a/web/app/controllers/super_manage.php b/web/app/controllers/super_manage.php index 8c91513..caa3dd2 100644 --- a/web/app/controllers/super_manage.php +++ b/web/app/controllers/super_manage.php @@ -264,6 +264,22 @@ DB::delete("delete from judger_info where judger_name='{$vdata['name']}'"); }; $judger_deleter->runAtServer(); + + $paste_deleter = new UOJForm('paste_deleter'); + $paste_deleter->addInput('paste_deleter_name', 'text', 'Paste ID', '', + function ($x, &$vdata) { + if (DB::selectCount("select count(*) from pastes where `index`='$x'")==0) { + return '不合法'; + } + $vdata['name'] = $x; + return ''; + }, + null + ); + $paste_deleter->handle = function(&$vdata) { + DB::delete("delete from pastes where `index` = '${vdata['name']}'"); + }; + $paste_deleter->runAtServer(); $judgerlist_cols = array('judger_name', 'password'); $judgerlist_config = array(); @@ -328,6 +344,10 @@ EOD; 'judger' => array( 'name' => '评测机管理', 'url' => '/super-manage/judger' + ), + 'paste' => array( + 'name' => 'Paste管理', + 'url' => '/super-manage/paste' ) ); @@ -458,6 +478,11 @@ EOD;

评测机列表

+ +
+

Paste管理

+ +
diff --git a/web/app/controllers/user_info.php b/web/app/controllers/user_info.php index a5ab50c..5daf415 100644 --- a/web/app/controllers/user_info.php +++ b/web/app/controllers/user_info.php @@ -104,20 +104,20 @@ var rating_data = [[ getTimestamp() + $contest_start_time->getOffset()) * 1000; - $last_contest_name = $contest['name']; + $last_contest_name = json_encode($contest['name']); $last_contest_id = $contest['id']; $last_rank = $row['rank']; $last_rating = $row['user_rating']; @@ -134,7 +134,7 @@ var rating_data = [[ echo "[{$time_now_stamp}, {$user['rating']}, 0]"; } else { $rating_delta = $user['rating'] - $last_rating; - echo "[$last_contest_time, {$user['rating']}, $last_contest_id, '$last_contest_name', $last_rank, $rating_delta]"; + echo "[$last_contest_time, {$user['rating']}, $last_contest_id, $last_contest_name, $last_rank, $rating_delta]"; } if ($user['rating'] < $user_rating_min) { $user_rating_min = $user['rating']; diff --git a/web/app/libs/uoj-data-lib.php b/web/app/libs/uoj-data-lib.php index 923c479..b38356b 100644 --- a/web/app/libs/uoj-data-lib.php +++ b/web/app/libs/uoj-data-lib.php @@ -233,7 +233,7 @@ } else { $n_ex_tests = getUOJConfVal($this->problem_conf, 'n_ex_tests', 0); if (!validateUInt($n_ex_tests) || $n_ex_tests < 0) { - throw new UOJProblemConfException("n_ex_tests must be a non-nagative integer"); + throw new UOJProblemConfException("n_ex_tests must be a non-negative integer"); } for ($num = 1; $num <= $n_ex_tests; $num++) { @@ -267,7 +267,7 @@ $n_sample_tests = getUOJConfVal($this->problem_conf, 'n_sample_tests', $n_tests); if (!validateUInt($n_sample_tests) || $n_sample_tests < 0) { - throw new UOJProblemConfException("n_sample_tests must be a non-nagative integer"); + throw new UOJProblemConfException("n_sample_tests must be a non-negative integer"); } if ($n_sample_tests > $n_ex_tests) { throw new UOJProblemConfException("n_sample_tests can't be greater than n_ex_tests"); diff --git a/web/app/libs/uoj-html-lib.php b/web/app/libs/uoj-html-lib.php index b46d987..fbf6981 100644 --- a/web/app/libs/uoj-html-lib.php +++ b/web/app/libs/uoj-html-lib.php @@ -393,6 +393,96 @@ function echoSubmissionsList($cond, $tail, $config, $user) { }, $table_config); } +function echoPastesList() { + $header_row = ''; + $col_names = ['`index`','creator','created_at']; + $header_row .= 'ID'; + $header_row .= ''.UOJLocale::get("problems::submitter").''; + $header_row .= ''.UOJLocale::get('problems::submit time').''; + $header_row .= ' 操作 '; + $header_row .= ''; + $table_name = 'pastes'; + echoLongTable($col_names, $table_name, "1", 'order by created_at desc', $header_row, + function($paste) { + $user = getUserLink($paste['creator']); + $token = HTML::hiddenToken(); + echo << + + {$paste['index']} + + + {$user} + + + {$paste['created_at']} + + +
+ {$token} + + +
+ + +HTML; + }, []); +} + +function echoPasteContent($paste) { + $zip_file = new ZipArchive(); + $submission_content = json_decode($paste['content'], true); + $zip_file->open(UOJContext::storagePath().$submission_content['file_name']); + + $config = array(); + foreach ($submission_content['config'] as $config_key => $config_val) { + $config[$config_val[0]] = $config_val[1]; + } + + $file_content = $zip_file->getFromName("paste.code"); + $file_content = uojTextEncode($file_content, array('allow_CR' => true, 'html_escape' => true)); + $file_language = htmlspecialchars($config["paste_language"]); + $footer_text = UOJLocale::get('problems::source code').', '.UOJLocale::get('problems::language').': '.$file_language; + $footer_text .= ", ".UOJLocale::get("problems::submitter") . <<${paste['creator']} +HTML; + $footer_text .= ", ".UOJLocale::get("problems::submit time").": ".$paste['created_at']; + + switch ($file_language) { + case 'C++': + case 'C++11': + $sh_class = 'sh_cpp'; + break; + case 'Python2': + case 'Python3': + $sh_class = 'sh_python'; + break; + case 'Java8': + case 'Java11': + $sh_class = 'sh_java'; + break; + case 'C': + $sh_class = 'sh_c'; + break; + case 'Pascal': + $sh_class = 'sh_pascal'; + break; + default: + $sh_class = ''; + break; + } + echo '
'; + echo '
'; + echo '

Paste!

'; + echo '
'; + echo '
'; + echo '
'.$file_content."\n".'
'; + echo '
'; + echo ''; + echo '
'; + + $zip_file->close(); +} function echoSubmissionContent($submission, $requirement) { $zip_file = new ZipArchive(); diff --git a/web/app/libs/uoj-rand-lib.php b/web/app/libs/uoj-rand-lib.php index 2e221c1..49e427b 100644 --- a/web/app/libs/uoj-rand-lib.php +++ b/web/app/libs/uoj-rand-lib.php @@ -31,3 +31,7 @@ function uojRandAvaiableSubmissionFileName() { } return uojRandAvaiableFileName("/submission/$num/"); } + +function uojRandAvaiablePasteFileName() { + return uojRandAvaiableFileName('/paste/'); +} diff --git a/web/app/route.php b/web/app/route.php index ecad27c..e406692 100644 --- a/web/app/route.php +++ b/web/app/route.php @@ -65,6 +65,11 @@ Route::group([ Route::any('/download.php', '/download.php'); Route::any('/click-zan', '/click_zan.php'); + + Route::any('/paste', '/paste_post.php'); + Route::any('/pastes/{rand_str_id}', '/paste_view.php'); + + Route::any('/map_visualizer', '/map_visualizer.php'); } ); diff --git a/web/app/storage/paste/.gitkeep b/web/app/storage/paste/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/web/app/views/main-nav.php b/web/app/views/main-nav.php index 62952e9..9edf904 100644 --- a/web/app/views/main-nav.php +++ b/web/app/views/main-nav.php @@ -11,6 +11,16 @@ +
diff --git a/web/app/views/page-header.php b/web/app/views/page-header.php index 4caee96..11d1ea1 100644 --- a/web/app/views/page-header.php +++ b/web/app/views/page-header.php @@ -153,7 +153,7 @@ } }); - + @@ -205,6 +205,16 @@ + + + + + + + + + +