| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- <?php
- requirePHPLib('judger');
- requirePHPLib('data');
-
- if (!authenticateJudger()) {
- become404Page();
- }
-
- // $_POST['result'] is attacker-controllable whenever the judger password is
- // weak or leaked (the repo used to ship a placeholder), so decode it once
- // and refuse anything that is not an object.
- function judgeResultFromPost() {
- $result = json_decode($_POST['result'] ?? '', true);
- if (!is_array($result)) {
- die("Wow! hacker! T_T....");
- }
- return $result;
- }
- function submissionJudged() {
- $submission = DB::selectFirst("select submitter, status, content, result, problem_id from submissions where id = {$_POST['id']}");
- if ($submission == null) {
- return;
- }
- if ($submission['status'] != 'Judging' && $submission['status'] != 'Judged, Judging') {
- return;
- }
- $content = json_decode($submission['content'], true);
-
- if (isset($content['first_test_config'])) {
- $result = json_decode($submission['result'], true);
- $result['final_result'] = judgeResultFromPost();
- $result['final_result']['details'] = uojTextEncode($result['final_result']['details']);
- $esc_result = DB::escape(json_encode($result, JSON_UNESCAPED_UNICODE));
-
- $content['final_test_config'] = $content['config'];
- $content['config'] = $content['first_test_config'];
- unset($content['first_test_config']);
- $esc_content = DB::escape(json_encode($content));
-
- DB::update("update submissions set status = 'Judged', result = '$esc_result', content = '$esc_content' where id = {$_POST['id']}");
- } else {
- $result = judgeResultFromPost();
- $result['details'] = uojTextEncode($result['details']);
- $esc_result = DB::escape(json_encode($result, JSON_UNESCAPED_UNICODE));
- // status/result_error are varchar and score/used_* are int, so
- // escape the former and cast the latter.
- $status = DB::escape($result['status']);
- if (isset($result["error"])) {
- $error = DB::escape($result['error']);
- DB::update("update submissions set status = '$status', result_error = '$error', result = '$esc_result', score = null, used_time = null, used_memory = null where id = {$_POST['id']}");
- } else {
- $score = (int)$result['score'];
- $time = (int)$result['time'];
- $memory = (int)$result['memory'];
- DB::update("update submissions set status = '$status', result_error = null, result = '$esc_result', score = $score, used_time = $time, used_memory = $memory where id = {$_POST['id']}");
- }
-
- if (isset($content['final_test_config'])) {
- $content['first_test_config'] = $content['config'];
- $content['config'] = $content['final_test_config'];
- unset($content['final_test_config']);
- $esc_content = DB::escape(json_encode($content));
-
- DB::update("update submissions set status = 'Judged, Waiting', content = '$esc_content' where id = ${_POST['id']}");
- }
- }
- DB::update("update submissions set status_details = '' where id = {$_POST['id']}");
- updateBestACSubmissions($submission['submitter'], $submission['problem_id']);
- }
- function customTestSubmissionJudged() {
- $submission = DB::selectFirst("select submitter, status, content, result, problem_id from custom_test_submissions where id = {$_POST['id']}");
- if ($submission == null) {
- return;
- }
- if ($submission['status'] != 'Judging') {
- return;
- }
- $content = json_decode($submission['content'], true);
- $result = judgeResultFromPost();
- $result['details'] = uojTextEncode($result['details']);
- $esc_result = DB::escape(json_encode($result, JSON_UNESCAPED_UNICODE));
- $status = DB::escape($result['status']);
- if (isset($result["error"])) {
- DB::update("update custom_test_submissions set status = '$status', result = '$esc_result' where id = {$_POST['id']}");
- } else {
- DB::update("update custom_test_submissions set status = '$status', result = '$esc_result' where id = {$_POST['id']}");
- }
- DB::update("update custom_test_submissions set status_details = '' where id = {$_POST['id']}");
- }
-
- function hackJudged() {
- $result = judgeResultFromPost();
- $esc_details = DB::escape(uojTextEncode($result['details']));
- $success = (int)$result['score'];
- $ok = DB::update("update hacks set success = $success, details = '$esc_details' where id = {$_POST['id']}");
-
- if ($ok) {
- list($hack_input) = DB::fetch(DB::query("select input from hacks where id = {$_POST['id']}"), MYSQLI_NUM);
- unlink(UOJContext::storagePath().$hack_input);
- if ($result['score']) {
- list($problem_id) = DB::selectFirst("select problem_id from hacks where id = ${_POST['id']}", MYSQLI_NUM);
- if (validateUploadedFile('hack_input') && validateUploadedFile('std_output')) {
- dataAddExtraTest(queryProblemBrief($problem_id), $_FILES["hack_input"]["tmp_name"], $_FILES["std_output"]["tmp_name"]);
- } else {
- error_log("hack successfully but received no data. id: ${_POST['id']}");
- }
- }
- }
- }
-
- if (isset($_POST['submit'])) {
- if (!validateUInt($_POST['id'])) {
- die("Wow! hacker! T_T....");
- }
- if (isset($_POST['is_hack'])) {
- hackJudged();
- } elseif (isset($_POST['is_custom_test'])) {
- customTestSubmissionJudged();
- } else {
- submissionJudged();
- }
- }
- if (isset($_POST['update-status'])) {
- if (!validateUInt($_POST['id'])) {
- die("Wow! hacker! T_T....");
- }
- $esc_status_details = DB::escape($_POST['status']);
- if (isset($_POST['is_custom_test'])) {
- DB::update("update custom_test_submissions set status_details = '$esc_status_details' where id = {$_POST['id']}");
- } else {
- DB::update("update submissions set status_details = '$esc_status_details' where id = {$_POST['id']}");
- }
- die();
- }
-
- $submission = null;
- $hack = null;
- function querySubmissionToJudge($status, $set_q) {
- global $submission;
- $submission = DB::selectFirst("select id, problem_id, content from submissions where status = '$status' order by id limit 1");
- if ($submission) {
- DB::update("update submissions set $set_q where id = {$submission['id']} and status = '$status'");
- if (DB::affected_rows() != 1) {
- $submission = null;
- }
- }
- }
- function queryCustomTestSubmissionToJudge() {
- global $submission;
- $submission = DB::selectFirst("select id, problem_id, content from custom_test_submissions where judge_time is null order by id limit 1");
- if ($submission) {
- DB::update("update custom_test_submissions set judge_time = now(), status = 'Judging' where id = {$submission['id']} and judge_time is null");
- if (DB::affected_rows() != 1) {
- $submission = null;
- }
- }
- if ($submission) {
- $submission['is_custom_test'] = '';
- }
- }
- function queryHackToJudge() {
- global $hack;
- $hack = DB::selectFirst("select id, submission_id, input, input_type from hacks where judge_time is null order by id limit 1");
- if ($hack) {
- DB::update("update hacks set judge_time = now() where id = {$hack['id']} and judge_time is null");
- if (DB::affected_rows() != 1) {
- $hack = null;
- }
- }
- }
- function findSubmissionToJudge() {
- global $submission, $hack;
- querySubmissionToJudge('Waiting', "judge_time = now(), status = 'Judging'");
- if ($submission) {
- return true;
- }
- queryCustomTestSubmissionToJudge();
- if ($submission) {
- return true;
- }
-
- querySubmissionToJudge('Waiting Rejudge', "judge_time = now(), status = 'Judging'");
- if ($submission) {
- return true;
- }
-
- querySubmissionToJudge('Judged, Waiting', "status = 'Judged, Judging'");
- if ($submission) {
- return true;
- }
-
- queryHackToJudge();
- if ($hack) {
- $submission = DB::selectFirst("select id, problem_id, content from submissions where id = {$hack['submission_id']} and score = 100");
- if (!$submission) {
- $details = "<error>the score gained by the hacked submission is not 100.\n</error>";
- $esc_details = DB::escape(uojTextEncode($details));
- DB::update("update hacks set success = 0, details = '$esc_details' where id = {$hack['id']}");
- return false;
- }
- return true;
- }
- return false;
- }
-
-
-
- if (isset($_POST['fetch_new']) && !$_POST['fetch_new']) {
- die("Nothing to judge");
- }
- if (!findSubmissionToJudge()) {
- die("Nothing to judge");
- }
-
- $submission['id'] = (int)$submission['id'];
- $submission['problem_id'] = (int)$submission['problem_id'];
- $submission['problem_mtime'] = filemtime("/var/uoj_data/{$submission['problem_id']}");
- $submission['content'] = json_decode($submission['content']);
-
- if ($hack) {
- $submission['is_hack'] = "";
- $submission['hack']['id'] = (int)$hack['id'];
- $submission['hack']['input'] = $hack['input'];
- $submission['hack']['input_type'] = $hack['input_type'];
- }
-
- echo json_encode($submission);
- ?>
|