Example #1
0
/**
 * Encode file contents for POST-ing to REST API.
 * Returns contents of $file (optionally limited in size, see
 * dj_get_file_contents) as encoded string.
 */
function rest_encode_file($file, $sizelimit = TRUE)
{
    return urlencode(base64_encode(dj_get_file_contents($file, $sizelimit)));
}
Example #2
0
/**
 * This function takes a (set of) temporary file(s) of a submission,
 * validates it and puts it into the database. Additionally it
 * moves it to a backup storage.
 */
function submit_solution($team, $prob, $contest, $lang, $files, $filenames, $origsubmitid = NULL)
{
    global $DB;
    if (empty($team)) {
        error("No value for Team.");
    }
    if (empty($prob)) {
        error("No value for Problem.");
    }
    if (empty($contest)) {
        error("No value for Contest.");
    }
    if (empty($lang)) {
        error("No value for Language.");
    }
    if (!is_array($files) || count($files) == 0) {
        error("No files specified.");
    }
    if (count($files) > dbconfig_get('sourcefiles_limit', 100)) {
        error("Tried to submit more than the allowed number of source files.");
    }
    if (!is_array($filenames) || count($filenames) != count($files)) {
        error("Nonmatching (number of) filenames specified.");
    }
    if (count($filenames) != count(array_unique($filenames))) {
        error("Duplicate filenames detected.");
    }
    $sourcesize = dbconfig_get('sourcesize_limit');
    // If no contest has started yet, refuse submissions.
    $now = now();
    $contestdata = $DB->q('MAYBETUPLE SELECT starttime,endtime FROM contest WHERE cid = %i', $contest);
    if (!isset($contestdata)) {
        error("Contest c{$contest} not found.");
    }
    if (difftime($contestdata['starttime'], $now) > 0) {
        error("The contest is closed, no submissions accepted. [c{$contest}]");
    }
    // Check 2: valid parameters?
    if (!($langid = $DB->q('MAYBEVALUE SELECT langid FROM language
	                        WHERE langid = %s AND allow_submit = 1', $lang))) {
        error("Language '{$lang}' not found in database or not submittable.");
    }
    if (!($teamid = $DB->q('MAYBEVALUE SELECT teamid FROM team
	                        WHERE teamid = %i AND enabled = 1', $team))) {
        error("Team '{$team}' not found in database or not enabled.");
    }
    $probdata = $DB->q('MAYBETUPLE SELECT probid, points FROM problem
	                    INNER JOIN contestproblem USING (probid)
	                    WHERE probid = %s AND cid = %i AND allow_submit = 1', $prob, $contest);
    if (empty($probdata)) {
        error("Problem p{$prob} not found in database or not submittable [c{$contest}].");
    } else {
        $points = $probdata['points'];
        $probid = $probdata['probid'];
    }
    // Reindex arrays numerically to allow simultaneously iterating
    // over both $files and $filenames.
    $files = array_values($files);
    $filenames = array_values($filenames);
    $totalsize = 0;
    for ($i = 0; $i < count($files); $i++) {
        if (!is_readable($files[$i])) {
            error("File '" . $files[$i] . "' not found (or not readable).");
        }
        if (!preg_match(FILENAME_REGEX, $filenames[$i])) {
            error("Illegal filename '" . $filenames[$i] . "'.");
        }
        $totalsize += filesize($files[$i]);
    }
    if ($totalsize > $sourcesize * 1024) {
        error("Submission file(s) are larger than {$sourcesize} kB.");
    }
    logmsg(LOG_INFO, "input verified");
    // Insert submission into the database
    $id = $DB->q('RETURNID INSERT INTO submission
	              (cid, teamid, probid, langid, submittime, origsubmitid)
	              VALUES (%i, %i, %i, %s, %s, %i)', $contest, $teamid, $probid, $langid, $now, $origsubmitid);
    for ($rank = 0; $rank < count($files); $rank++) {
        $DB->q('INSERT INTO submission_file
		        (submitid, filename, rank, sourcecode) VALUES (%i, %s, %i, %s)', $id, $filenames[$rank], $rank, dj_get_file_contents($files[$rank], false));
    }
    // Recalculate scoreboard cache for pending submissions
    calcScoreRow($contest, $teamid, $probid);
    // Log to event table
    $DB->q('INSERT INTO event (eventtime, cid, teamid, langid, probid, submitid, description)
	        VALUES(%s, %i, %i, %s, %i, %i, "problem submitted")', now(), $contest, $teamid, $langid, $probid, $id);
    alert('submit', "submission {$id}: team {$teamid}, language {$langid}, problem {$probid}");
    if (is_writable(SUBMITDIR)) {
        // Copy the submission to SUBMITDIR for safe-keeping
        for ($rank = 0; $rank < count($files); $rank++) {
            $fdata = array('cid' => $contest, 'submitid' => $id, 'teamid' => $teamid, 'probid' => $probid, 'langid' => $langid, 'rank' => $rank, 'filename' => $filenames[$rank]);
            $tofile = SUBMITDIR . '/' . getSourceFilename($fdata);
            if (!@copy($files[$rank], $tofile)) {
                warning("Could not copy '" . $files[$rank] . "' to '" . $tofile . "'");
            }
        }
    } else {
        logmsg(LOG_DEBUG, "SUBMITDIR not writable, skipping");
    }
    if (difftime($contestdata['endtime'], $now) <= 0) {
        logmsg(LOG_INFO, "The contest is closed, submission stored but not processed. [c{$contest}]");
    }
    return $id;
}