/** * Get input=hidden stuffs for login * @return Hidden params in string */ string CCJudger::getLoginHiddenParams() { prepareCurl(); curl_easy_setopt(curl, CURLOPT_URL, "https://www.codechef.com/"); performCurl(); string html = loadAllFromFile(tmpfilename); string form; // login form if (!RE2::PartialMatch(html, "(?s)(<form.*?user-login-form.*?</form>)", &form)) { throw Exception("Failed to get hidden params."); } string key, value, result = ""; // get all hidden params re2::StringPiece formString(form); while (RE2::FindAndConsume( &formString, "(?s)<input type=\"hidden\".*?name=\"(.*?)\".*?value=\"(.*?)\"", &key, &value)) { result += escapeURL(key) + "=" + escapeURL(value) + "&"; } return result; }
/** * Get input=hidden stuffs for submit * @param code Problem code * @return Hidden params in pairs */ vector< pair<string, string> > CCJudger::getSubmitHiddenParams(string code) { prepareCurl(); curl_easy_setopt(curl, CURLOPT_URL, ((string) "https://www.codechef.com/submit/" + code).c_str()); performCurl(); string html = loadAllFromFile(tmpfilename); string form; // login form if (!RE2::PartialMatch(html, "(?s)(<form.*?submit-form.*?</form>)", &form)) { throw Exception("Failed to get hidden params."); } string key, value; vector< pair<string, string> > result; // get all hidden params re2::StringPiece formString(form); while (RE2::FindAndConsume( &formString, "(?s)<input type=\"hidden\".*?name=\"(.*?)\".*?value=\"(.*?)\"", &key, &value)) { result.push_back(make_pair(key, value)); } return result; }
/** * Submit a run * @param bott Bott file for Run info * @return Submit status */ int ZJUJudger::submit(Bott * bott) { prepareCurl(); curl_easy_setopt(curl, CURLOPT_URL, "http://acm.zju.edu.cn/onlinejudge/submit.do"); string post = (string) "problemCode=" + bott->Getvid() + "&languageId=" + convertLanguage(bott->Getlanguage()) + "&source=" + escapeURL(bott->Getsrc()); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post.c_str()); performCurl(); // check submit status string html = loadAllFromFile(tmpfilename); if (html.find("Submit Successfully</div>") == string::npos) { return SUBMIT_OTHER_ERROR; } // parse remote runid from submit page string runid; if (!RE2::PartialMatch(html, "(?s)The submission id is.*?>(.*?)<", &runid)) { return SUBMIT_OTHER_ERROR; } bott->Setremote_runid(runid); return VirtualJudger::SUBMIT_NORMAL; }
/** * Get result and related info * @param bott Original Bott info * @return Result Bott file */ Bott *CCJudger::getStatus(Bott * bott) { time_t begin_time = time(NULL); Bott *result_bott; while (true) { // check wait time if (time(NULL) - begin_time > info->GetMax_wait_time()) { throw Exception ("Failed to get current result, judge time out."); } prepareCurl(); curl_easy_setopt(curl, CURLOPT_URL, ((string) "http://www.codechef.com/get_submission_status/" + bott-> Getremote_runid()).c_str ()); performCurl(); string html = loadAllFromFile(tmpfilename); string result, time_used, memory_used; // get result if (!RE2::PartialMatch (html, "\"result_code\":\"(.*?)\"", &result)) { throw Exception("Failed to get current result."); } result = convertResult(result); if (isFinalResult(result)) { // if result if final, get details if (!RE2::PartialMatch(html, "(?s)\"time\":\"(.*?)\"", &time_used)) { throw Exception ("Failed to parse details from status row."); } int time_ms = stringToDouble(time_used) * 1000 + 0.001; int memory_kb; result_bott = new Bott; result_bott->Settype(RESULT_REPORT); result_bott->Setresult(result); result_bott->Settime_used(intToString(time_ms)); if (result != "Compile Error") { // CodeChef will update Memory usage later in submission table // Weird... why don't they put in get_submission_status api... memory_used = "0"; prepareCurl(); curl_easy_setopt(curl, CURLOPT_URL, ((string) "http://www.codechef.com/submissions?handle=" + escapeURL (info-> GetUsername ()) + "&pcode=" + escapeURL (bott->Getvid ())). c_str()); performCurl(); html = loadAllFromFile(tmpfilename); string status; if (!RE2::PartialMatch(html, "(?s)(<tr class=\"kol.*?<td width=\"60\">" + bott->Getremote_runid() + "</td>.*?</tr>)", &status)) { // Status row is not updated in time... log("Memory data not ready yet... Never mind, use 0 instead."); memory_used = "0"; } else if (!RE2::PartialMatch (status, ">([0-9\\.]*)M", &memory_used)) { memory_used = "0"; } memory_kb = stringToDouble(memory_used) * 1024 + 0.001; } result_bott->Setmemory_used(intToString(memory_kb)); result_bott->Setremote_runid(bott->Getremote_runid()); break; } } return result_bott; }
/** * Submit a run * @param bott Bott file for Run info * @return Submit status */ int CCJudger::submit(Bott * bott) { vector < pair < string, string > >hiddenParams; try { hiddenParams = getSubmitHiddenParams(bott->Getvid()); } catch(Exception & e) { // mostly because frequecy limit return SUBMIT_OTHER_ERROR; } // prepare form for post struct curl_httppost *formpost = NULL; struct curl_httppost *lastptr = NULL; for (vector < pair < string, string > >::iterator it = hiddenParams.begin(); it != hiddenParams.end(); ++it) { curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, it->first.c_str(), CURLFORM_COPYCONTENTS, it->second.c_str(), CURLFORM_END); } curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "submission_language", CURLFORM_COPYCONTENTS, bott->Getlanguage().c_str(), CURLFORM_END); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "body", CURLFORM_COPYCONTENTS, bott->Getsrc().c_str(), CURLFORM_END); // WTF moment... CodeChef checks the filename of the uploaded file to determine whether to read source from // text area or uploaded file, so we must upload something, otherwise it'll stop you from submitting... curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "files[program_file]", CURLFORM_FILE, "/dev/null", CURLFORM_FILENAME, "", CURLFORM_END); prepareCurl(); curl_easy_setopt(curl, CURLOPT_URL, ((string) "http://www.codechef.com/submit/" + bott->Getvid()).c_str()); curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); performCurl(); curl_formfree(formpost); // check submit status string html = loadAllFromFile(tmpfilename); if (html.find ("<li>You can\'t submit in this language for this problem!</li>") != string::npos) { return SUBMIT_INVALID_LANGUAGE; } if (html.find("<div class=\"messages error\">") != string::npos || html.find("<a class=\"login-link\"") != string::npos) { return SUBMIT_OTHER_ERROR; } // parse remote runid from submit page string runid; if (!RE2::PartialMatch(html, "(?s)var submission_id = (.*?);", &runid)) { return SUBMIT_OTHER_ERROR; } bott->Setremote_runid(runid); return VirtualJudger::SUBMIT_NORMAL; }
/** * Get validation code from file * @return validation code */ string SCUJudger::getCode() { prepareCurl(); curl_easy_setopt(curl, CURLOPT_URL, "http://cstest.scu.edu.cn/soj/validation_code"); performCurl(); int *jpg, width, height; jpg = NULL; loadImage(tmpfilename, width, height, jpg); if (jpg == NULL) return ""; // for (int i = 0; i < height; ++i, printf("\n")) { // for (int j = 0; j < width; ++j) { // printf("%c", jpg[i * width + j] > 0x600000 ? ' ' : 'x'); // } // } string code; for (int n = 0; n < 4; ++n) { if (getNXY(n, 5, 1, width, height, jpg) == 'x' && getNXY(n, 5, 2, width, height, jpg) == ' ' && getNXY(n, 5, 5, width, height, jpg) == ' ' && getNXY(n, 5, 6, width, height, jpg) == 'x') code += '0'; else if (getNXY(n, 2, 2, width, height, jpg) == ' ' && getNXY(n, 2, 3, width, height, jpg) == 'x' && getNXY(n, 2, 4, width, height, jpg) == ' ') code += '1'; else if (getNXY(n, 9, 1, width, height, jpg) == 'x' && getNXY(n, 9, 2, width, height, jpg) == 'x' && getNXY(n, 9, 3, width, height, jpg) == 'x' && getNXY(n, 9, 4, width, height, jpg) == 'x' && getNXY(n, 9, 5, width, height, jpg) == 'x') code += '2'; else if (getNXY(n, 5, 1, width, height, jpg) == ' ' && getNXY(n, 5, 2, width, height, jpg) == ' ' && getNXY(n, 5, 3, width, height, jpg) == 'x' && getNXY(n, 5, 4, width, height, jpg) == 'x' && getNXY(n, 5, 6, width, height, jpg) == ' ') code += '3'; else if (getNXY(n, 2, 3, width, height, jpg) == ' ' && getNXY(n, 2, 4, width, height, jpg) == 'x' && getNXY(n, 2, 5, width, height, jpg) == 'x') code += '4'; else if (getNXY(n, 4, 1, width, height, jpg) == 'x' && getNXY(n, 4, 2, width, height, jpg) == 'x' && getNXY(n, 4, 3, width, height, jpg) == 'x' && getNXY(n, 4, 6, width, height, jpg) == ' ') code += '5'; else if (getNXY(n, 4, 1, width, height, jpg) == 'x' && getNXY(n, 4, 2, width, height, jpg) == ' ' && getNXY(n, 4, 3, width, height, jpg) == 'x' && getNXY(n, 4, 4, width, height, jpg) == 'x') code += '6'; else if (getNXY(n, 1, 1, width, height, jpg) == 'x' && getNXY(n, 1, 6, width, height, jpg) == 'x') code += '7'; else if (getNXY(n, 5, 2, width, height, jpg) == 'x' && getNXY(n, 5, 3, width, height, jpg) == 'x' && getNXY(n, 5, 4, width, height, jpg) == 'x' && getNXY(n, 5, 5, width, height, jpg) == 'x') code += '8'; else if (getNXY(n, 6, 3, width, height, jpg) == 'x' && getNXY(n, 6, 4, width, height, jpg) == 'x' && getNXY(n, 6, 5, width, height, jpg) == ' ' && getNXY(n, 6, 6, width, height, jpg) == 'x') code += '9'; else code += '-'; } // cout << code << endl; delete[]jpg; return code; }
/** * Get result and related info * @param bott Original Bott info * @return Result Bott file */ Bott * ZJUJudger::getStatus(Bott * bott) { time_t begin_time = time(NULL); Bott * result_bott; while (true) { // check wait time if (time(NULL) - begin_time > info->GetMax_wait_time()) { throw Exception("Failed to get current result, judge time out."); } prepareCurl(); curl_easy_setopt( curl, CURLOPT_URL, ((string) "http://acm.zju.edu.cn/onlinejudge/showRuns.do?" "contestId=1&idStart=" + bott->Getremote_runid() + "&idEnd=" + bott->Getremote_runid()).c_str()); performCurl(); string html = loadAllFromFile(tmpfilename); string status; string result, time_used, memory_used; // get first row if (!RE2::PartialMatch(html, "(?s)(<tr class=\"rowOdd\">.*?</tr>)", &status)) { continue; } // get result if (!RE2::PartialMatch( status, "(?s)<td class=\"runJudgeStatus\".*?<span.*?>(.*?)</span>", &result)) { throw Exception("Failed to get current result."); } result = trim(result); if (isFinalResult(result)) { // result is the final one result = convertResult(result); if (!RE2::PartialMatch( status, "(?s)<td class=\"runTime\".*?>(.*?)</td>.*" "<td class=\"runMemory\".*?>(.*?)</td>", &time_used, &memory_used)) { throw Exception("Failed to parse details from status row."); } result_bott = new Bott; result_bott->Setremote_runid(bott->Getremote_runid()); result_bott->Settype(RESULT_REPORT); result_bott->Setresult(result); result_bott->Settime_used(stringToInt(time_used)); result_bott->Setmemory_used(stringToInt(memory_used)); if (result == "Compile Error") { // hack for ZJU, don't know why its submission id is inconsistent with // judge protocol if (!RE2::PartialMatch( status, "(?s)showJudgeComment\\.do\\?submissionId=([0-9]*)", &submission_id_for_ce)) { submission_id_for_ce = bott->Getremote_runid(); } } break; } } return result_bott; }
/** * Get result and related info * @param bott Original Bott info * @return Result Bott file */ Bott *NJUPTJudger::getStatus(Bott * bott) { time_t begin_time = time(NULL); Bott *result_bott; while (true) { // check wait time if (time(NULL) - begin_time > info->GetMax_wait_time()) { throw Exception ("Failed to get current result, judge time out."); } prepareCurl(); curl_easy_setopt(curl, CURLOPT_URL, ((string) "http://acm.njupt.edu.cn/acmhome/showstatus.do"). c_str()); string post = (string) "problemId=" + bott->Getvid() + "&languageS=" + escapeURL(bott->Getlanguage()) + "&userName="******"&resultS=All"; curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post.c_str()); performCurl(); string html = loadAllFromFile(tmpfilename); string status; string runid, result, time_used, memory_used; // get first row if (!RE2::PartialMatch (html, "(?s)<table.*?</thead>.*?(<tr.*?</tr>)", &status)) { throw Exception("Failed to get status row."); } // get result if (!RE2::PartialMatch(status, "(?s)method=showdetail.*?value=\"(.*?)\".*?<b acc=\"acc\"></b>\\s*(.*?)\\s*<b acc=\"acc\"></b>", &runid, &result)) { throw Exception("Failed to get current result."); } result = convertResult(trim(result)); if (isFinalResult(result)) { // result is the final one, get details if (result == "Accepted") { // only accepted run has details if (!RE2::PartialMatch(status, "(?s)([0-9]*)<b ms=\"ms\"></b>MS.*?([0-9]*)<b k=\"k\"></b>K", &time_used, &memory_used)) { throw Exception ("Failed to parse details from status row."); } } else { memory_used = time_used = "0"; } result_bott = new Bott; result_bott->Settype(RESULT_REPORT); result_bott->Setresult(convertResult(result)); result_bott->Settime_used(trim(time_used)); result_bott->Setmemory_used(trim(memory_used)); result_bott->Setremote_runid(trim(runid)); break; } } return result_bott; }
/** * Get result and related info * @param bott Original Bott info * @return Result Bott file */ Bott * SPOJJudger::getStatus(Bott * bott) { time_t begin_time = time(NULL); Bott * result_bott; while (true) { // check wait time if (time(NULL) - begin_time > info->GetMax_wait_time()) { throw Exception("Failed to get current result, judge time out."); } prepareCurl(); curl_easy_setopt(curl, CURLOPT_URL, ("http://www.spoj.com/status/" + info->GetUsername() + "/ajax=1").c_str()); performCurl(); string html = loadAllFromFile(tmpfilename); string status; string runid, result, time_used, memory_used; // get first row if (!RE2::PartialMatch(html, "(?s)(<tr class=\"kol.*?</tr>)", &status)) { throw Exception("Failed to get status row."); } // get result if (!RE2::PartialMatch(status, "(?s)statusres_([0-9]*).*?>\\w*(?:<.*?>)?(.*?)\\w*<span", &runid, &result)) { throw Exception("Failed to get current result."); } result = trim(result); if (isFinalResult(result)) { // result is the final one result = convertResult(result); if (result == "Accepted" || result == "Runtime Error" || result == "Wrong Answer") { // only have details for these three results string unit; if (!RE2::PartialMatch( status, "(?s)statustime_.*?<a.*?>(.*?)</a>.*?statusmem_.*?>\\s*(.*?)(M|k)", &time_used, &memory_used, &unit)) { throw Exception("Failed to parse details from status row."); } int time_ms = stringToDouble(time_used) * 1000 + 0.001; time_used = intToString(time_ms); if (unit == "M") { int memory_mb = stringToDouble(memory_used) * 1024 + 0.001; memory_used = intToString(memory_mb); } } else { time_used = memory_used = "0"; } result_bott = new Bott; result_bott->Setremote_runid(runid); result_bott->Settype(RESULT_REPORT); result_bott->Setresult(result); result_bott->Settime_used(stringToInt(time_used)); result_bott->Setmemory_used(stringToInt(memory_used)); break; } } return result_bott; }
/** * Get result and related info * @param bott Original Bott info * @return Result Bott file */ Bott * AizuJudger::getStatus(Bott * bott) { time_t begin_time = time(NULL); Bott * result_bott; while (true) { // check wait time if (time(NULL) - begin_time > info->GetMax_wait_time()) { throw Exception("Failed to get current result, judge time out."); } prepareCurl(); curl_easy_setopt( curl, CURLOPT_URL, ((string) "http://judge.u-aizu.ac.jp/onlinejudge/status.jsp").c_str()); performCurl(); string html = loadAllFromFile(tmpfilename); string status; string runid, result, time_used, memory_used; // get first row of current user if (!RE2::PartialMatch( html, "(?s)(<tr *class=\"dat\".*?>" + info->GetUsername() + "<.*?</tr>)", &status)) { throw Exception("Failed to get status row."); } html = status; if (!RE2::PartialMatch( html, "(?s).*(<tr *class=\"dat\".*?>" + info->GetUsername() + "<.*?</tr>)", &status)) { throw Exception("Failed to get status row."); } // get result if (!RE2::PartialMatch( status, "(?s)rid=([0-9]*).*status.*?<a href=\"review.*?>(.*?)</a>", &runid, &result)) { throw Exception("Failed to get current result."); } result = convertResult(trim(result)); if (isFinalResult(result)) { // result is the final one, get details if (result != "Runtime Error" && result != "Compile Error") { if (!RE2::PartialMatch( status, "(?s)<td class=\"text-center\">([0-9\\.]*) s.*?<td.*?>([0-9]*) KB", &time_used, &memory_used)) { throw Exception("Failed to parse details from status row."); } } else { memory_used = time_used = "0"; } result_bott = new Bott; result_bott->Settype(RESULT_REPORT); result_bott->Setresult(convertResult(result)); result_bott->Settime_used( (int)(stringToDouble(time_used) * 100 + 0.1)); result_bott->Setmemory_used(stringToInt(memory_used)); result_bott->Setremote_runid(trim(runid)); break; } } return result_bott; }
/** * Get result and related info * @param bott Original Bott info * @return Result Bott file */ Bott * CFJudger::getStatus(Bott * bott) { time_t begin_time = time(NULL); Bott * result_bott; while (true) { // check wait time if (time(NULL) - begin_time > info->GetMax_wait_time()) { throw Exception("Failed to get current result, judge time out."); } prepareCurl(); curl_easy_setopt(curl, CURLOPT_URL, ((string) "http://codeforces.com/submissions/" + info->GetUsername()).c_str()); performCurl(); string html = loadAllFromFile(tmpfilename); string status; string runid, result, time_used, memory_used; // get first result row if (!RE2::PartialMatch(html, "(?s)<tr.*first-row.*?(<tr.*?</tr>)", &status)) { throw Exception("Failed to get status row."); } // get result if (!RE2::PartialMatch(status, "(?s)status-cell.*?>(.*?)</td>", &result)) { throw Exception("Failed to get current result."); } if (isFinalResult(result)) { // if result if final, get details if (!RE2::PartialMatch( status, "(?s)data-submission-id=\"([0-9]*)\".*submissionVerdict" "=\"(.*?)\".*time-consumed-cell.*?>(.*?) ms.*memory-consumed" "-cell.*?>(.*?) KB", &runid, &result, &time_used, &memory_used)) { // try api when failed log("Failed to parse details from status row, try API."); prepareCurl(); curl_easy_setopt( curl, CURLOPT_URL, ((string) "http://codeforces.com/api/user.status?handle=" + info->GetUsername() + "&from=1&count=1").c_str()); performCurl(); string json = loadAllFromFile(tmpfilename); if (!RE2::PartialMatch( json, "(?s)\"id\":([0-9]*)\"verdict\":\"(.*?)\".*\"timeConsumed" "Millis\":([0-9]*),\"memeryConsumedBytes\":([0-9]*)", &runid, &result, &time_used, &memory_used)) { throw Exception("Failed to parse details from API."); } } result_bott = new Bott; result_bott->Settype(RESULT_REPORT); result_bott->Setresult(convertResult(result)); result_bott->Settime_used(stringToInt(time_used)); result_bott->Setmemory_used(stringToInt(memory_used)); result_bott->Setremote_runid(trim(runid)); break; } } // for CodeForces, we can store extra infos in ce_info column string contest; // no need to check fail or not, since submit function has already done it RE2::PartialMatch(bott->Getvid(), "(^[0-9]{1,6})", &contest); if (result_bott->Getresult() != "Accepted" && result_bott->Getresult() != "Compile Error") { result_bott->Setce_info( getVerdict(contest, result_bott->Getremote_runid())); } return result_bott; }
/** * Submit a run * @param bott Bott file for Run info * @return Submit status */ int CFJudger::submit(Bott * bott) { string csrf = getCsrfParams("http://codeforces.com/problemset/submit"); // prepare cid and pid from vid string contest, problem; if (!RE2::PartialMatch(bott->Getvid(), "^([0-9]{1,6})(.*)", &contest, &problem)) { throw Exception("Invalid vid."); } string source = bott->Getsrc(); // add random extra spaces in the end to avoid same code error srand(time(NULL)); source += '\n'; while (rand() % 120) source += ' '; // prepare form for post struct curl_httppost * formpost = NULL; struct curl_httppost * lastptr = NULL; curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "action", CURLFORM_COPYCONTENTS, "submitSolutionFormSubmitted", CURLFORM_END); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "contestId", CURLFORM_COPYCONTENTS, contest.c_str(), CURLFORM_END); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "submittedProblemIndex", CURLFORM_COPYCONTENTS, problem.c_str(), CURLFORM_END); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "programTypeId", CURLFORM_COPYCONTENTS, convertLanguage(bott->Getlanguage()).c_str(), CURLFORM_END); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "source", CURLFORM_COPYCONTENTS, source.c_str(), CURLFORM_END); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "sourceCodeConfirmed", CURLFORM_COPYCONTENTS, "true", CURLFORM_END); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "_tta", CURLFORM_COPYCONTENTS, getttaValue().c_str(), CURLFORM_END); prepareCurl(); curl_easy_setopt(curl, CURLOPT_URL, (getSubmitUrl(contest) + "?csrf_token=" + csrf).c_str()); curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); performCurl(); curl_formfree(formpost); // check submit status string html = loadAllFromFile(tmpfilename); if (html.find( "You have submitted exactly the same code before") != string::npos) { return VirtualJudger::SUBMIT_SAME_CODE; } else if (html.find("Choose valid language") != string::npos) { return VirtualJudger::SUBMIT_INVALID_LANGUAGE; } else if (html.find("<span class=\"error for__source\">") != string::npos) { return VirtualJudger::SUBMIT_COMPILE_ERROR; } else if (html.find("<a href=\"/enter\">Enter</a>") != string::npos) { return SUBMIT_OTHER_ERROR; } return VirtualJudger::SUBMIT_NORMAL; }