Exemplo n.º 1
0
/**
 * 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;
}
Exemplo n.º 2
0
/**
 * 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;
}
Exemplo n.º 3
0
/**
 * 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;
}
Exemplo n.º 4
0
/**
 * 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;
}
Exemplo n.º 5
0
/**
 * 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;
}
Exemplo n.º 6
0
/**
 * 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;
}
Exemplo n.º 7
0
/**
 * 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;
}
Exemplo n.º 8
0
/**
 * 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;
}
Exemplo n.º 9
0
/**
 * 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;
}
Exemplo n.º 10
0
/**
 * 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;
}
Exemplo n.º 11
0
/**
 * 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.*?>(.*?)&nbsp;ms.*memory-consumed"
              "-cell.*?>(.*?)&nbsp;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;
}
Exemplo n.º 12
0
/**
 * 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;
}