From 50e7fdf1ccadde84a04b20b987231b39b3e28fd6 Mon Sep 17 00:00:00 2001 From: Baoshuo Date: Fri, 3 Feb 2023 19:35:04 +0800 Subject: [PATCH] feat(problem/remote): validate remote account status --- .../remote_judge/custom_account_validator.php | 86 +++++++++++++++++++ web/app/controllers/subdomain/api/route.php | 12 +++ web/index.php | 1 + web/js/uoj.js | 78 ++++++++++++++++- 4 files changed, 173 insertions(+), 4 deletions(-) create mode 100644 web/app/controllers/subdomain/api/remote_judge/custom_account_validator.php create mode 100644 web/app/controllers/subdomain/api/route.php diff --git a/web/app/controllers/subdomain/api/remote_judge/custom_account_validator.php b/web/app/controllers/subdomain/api/remote_judge/custom_account_validator.php new file mode 100644 index 0000000..f655b20 --- /dev/null +++ b/web/app/controllers/subdomain/api/remote_judge/custom_account_validator.php @@ -0,0 +1,86 @@ +setUserAgent(UOJRemoteProblem::USER_AGENT); +$res = false; + +function validateLuogu($response) { + $response = json_decode(json_encode($response), true); + + return $response['currentTemplate'] !== 'AuthLogin'; +} + +if ($type == 'luogu') { + $curl->setFollowLocation(); + $curl->setCookie('_uid', UOJRequest::post('_uid', 'is_string', '')); + $curl->setCookie('__client_id', UOJRequest::post('__client_id', 'is_string', '')); + + retry_loop(function () use (&$curl, &$res) { + $curl->get(UOJRemoteProblem::$providers['luogu']['url'] . '/user/setting?_contentOnly=1'); + + if ($curl->error) { + return false; + } + + if ($curl->responseHeaders['Content-Type'] == 'text/html') { + $sec = $curl->getResponseCookie('sec'); + + if ($sec) { + $curl->setCookie('sec', $sec); + $curl->get(UOJRemoteProblem::$providers['luogu']['url'] . '/user/setting?_contentOnly=1'); + + if ($curl->responseHeaders['Content-Type'] == 'application/json') { + $res = validateLuogu($curl->response); + + return true; + } + + return false; + } + + return false; + } else if ($curl->responseHeaders['Content-Type'] == 'application/json') { + $res = validateLuogu($curl->response); + + return true; + } + + return false; + }, 3); + + die(json_encode(['ok' => $res === true])); +} else if ($type == 'codeforces') { + $curl->setFollowLocation(); + $curl->setCookie('JSESSIONID', UOJRequest::post('JSESSIONID', 'is_string', '')); + + retry_loop(function () use (&$curl, &$res) { + $curl->get(UOJRemoteProblem::$providers['codeforces']['url'] . '/enter'); + + if ($curl->error) { + return false; + } + + if (str_starts_with($curl->responseHeaders['Content-Type'], 'text/html')) { + if (str_contains($curl->response, 'Login into Codeforces')) { + return false; + } + + if (strlen($curl->response) < 1000 && str_contains($curl->response, 'Redirecting...')) { + return false; + } + + $res = true; + + return true; + } + + return false; + }, 3); +} else { + UOJResponse::page406(); +} + +die(json_encode(['ok' => $res === true])); diff --git a/web/app/controllers/subdomain/api/route.php b/web/app/controllers/subdomain/api/route.php new file mode 100644 index 0000000..ae169a7 --- /dev/null +++ b/web/app/controllers/subdomain/api/route.php @@ -0,0 +1,12 @@ + UOJConfig::$data['web']['main']['host'], + ], + function () { + Route::post("/api/remote_judge/custom_account_validator", '/subdomain/api/remote_judge/custom_account_validator.php'); + } + ); +}); diff --git a/web/index.php b/web/index.php index 6e29eca..0953945 100644 --- a/web/index.php +++ b/web/index.php @@ -5,6 +5,7 @@ require $_SERVER['DOCUMENT_ROOT'] . '/app/libs/uoj-lib.php'; require UOJContext::documentRoot().'/app/route.php'; require UOJContext::documentRoot().'/app/controllers/subdomain/blog/route.php'; +require UOJContext::documentRoot().'/app/controllers/subdomain/api/route.php'; include UOJContext::documentRoot().'/app/controllers'.call_user_func(function() { $route = Route::dispatch(); diff --git a/web/js/uoj.js b/web/js/uoj.js index 43ba550..cec7c0e 100644 --- a/web/js/uoj.js +++ b/web/js/uoj.js @@ -958,11 +958,48 @@ $.fn.remote_submit_type_group = function(oj, pid, url, submit_type) { var input_submit_type_bot = $(''); var input_submit_type_my = $(''); var input_my_account_data = $(''); + + var my_account_validation_status = $('').append('待验证'); + var my_account_validation_btn = $(''); + + var validate_my_account = function(data) { + my_account_validation_btn.html(''); + my_account_validation_btn.addClass('disabled'); + + $.ajax({ + type: 'POST', + url: '/api/remote_judge/custom_account_validator?type=' + oj, + data: data, + success: function(res) { + my_account_validation_btn.html('验证'); + my_account_validation_btn.removeClass('disabled'); + + console.log('Validation status', res); + + if (res.ok) { + my_account_validation_status.html('可用'); + } else { + my_account_validation_status.html('不可用'); + } + }, + error: function() { + my_account_validation_btn.html('验证'); + my_account_validation_btn.removeClass('disabled'); + my_account_validation_status.html('待验证'); + }, + dataType: 'json', + }); + }; var div_submit_type_bot = $('
') .append('
将使用公用账号提交本题。
'); var div_submit_type_my = $('
') - .append('
将使用您的账号提交本题。
'); + .append($('
') + .append('将使用您的账号提交本题。') + .append('账号状态:') + .append(my_account_validation_status) + .append(my_account_validation_btn) + ); if ('localStorage' in window) { var prefer_submit_type = localStorage.getItem('uoj_remote_judge_save_prefer_submit_type__' + oj) || null; @@ -1035,28 +1072,46 @@ $.fn.remote_submit_type_group = function(oj, pid, url, submit_type) { luogu_account_data._uid = $(this).val(); input_my_account_data.val(JSON.stringify(luogu_account_data)); save_luogu_account_data(); + my_account_validation_status.html('待验证'); }); input_luogu_client_id.change(function() { luogu_account_data.__client_id = $(this).val(); input_my_account_data.val(JSON.stringify(luogu_account_data)); save_luogu_account_data(); + my_account_validation_status.html('待验证'); + }); + + my_account_validation_btn.click(function() { + validate_my_account({ + type: 'luogu', + _uid: input_luogu_uid.val(), + __client_id: input_luogu_client_id.val(), + }); }); input_my_account_data.val(JSON.stringify(luogu_account_data)); input_luogu_uid.val(luogu_account_data._uid); input_luogu_client_id.val(luogu_account_data.__client_id); + if (luogu_account_data._uid && luogu_account_data.__client_id){ + validate_my_account({ + type: 'luogu', + _uid: luogu_account_data._uid, + __client_id: luogu_account_data.__client_id, + }); + } + div_submit_type_my.append( $('
') .append($('
').append('')) .append($('
').append(input_luogu_uid)) - .append($('
').append($('
').append('请填入 Cookie 中的 _uid。'))) + .append($('
').append($('
').append('请填入 Cookie 中的 _uid。'))) ).append( $('
') .append($('
').append('')) .append($('
').append(input_luogu_client_id)) - .append($('
').append($('
').append('请填入 Cookie 中的 __client_id。'))) + .append($('
').append($('
').append('请填入 Cookie 中的 __client_id。'))) ).append(input_my_account_data); } else if (oj == 'codeforces') { var codeforces_account_data = {"JSESSIONID": ""}; @@ -1079,16 +1134,31 @@ $.fn.remote_submit_type_group = function(oj, pid, url, submit_type) { codeforces_account_data.JSESSIONID = $(this).val(); input_my_account_data.val(JSON.stringify(codeforces_account_data)); save_codeforces_account_data(); + my_account_validation_status.html('待验证'); + }); + + my_account_validation_btn.click(function() { + validate_my_account({ + type: 'codeforces', + JSESSIONID: input_codeforces_jsessionid.val(), + }); }); input_my_account_data.val(JSON.stringify(codeforces_account_data)); input_codeforces_jsessionid.val(codeforces_account_data.JSESSIONID); + if (codeforces_account_data.JSESSIONID) { + validate_my_account({ + type: 'codeforces', + JSESSIONID: codeforces_account_data.JSESSIONID, + }); + } + div_submit_type_my.append( $('
') .append($('
').append('')) .append($('
').append(input_codeforces_jsessionid)) - .append($('
').append($('
').append('请填入 Cookie 中的 JSESSIONID。'))) + .append($('
').append($('
').append('请填入 Cookie 中的 JSESSIONID。'))) ).append(input_my_account_data); }