function do_login() { global $DB, $ip, $username, $userdata; switch (AUTH_METHOD) { // Generic authentication code for IPADDRESS and PHP_SESSIONS; // some specializations are handled by if-statements. case 'IPADDRESS': case 'PHP_SESSIONS': $user = trim($_POST['login']); $pass = trim($_POST['passwd']); $title = 'Authenticate user'; $menu = false; if (empty($user) || empty($pass)) { show_failed_login("Please supply a username and password."); } do_login_native($user, $pass); if (AUTH_METHOD == 'IPADDRESS') { $cnt = $DB->q('RETURNAFFECTED UPDATE user SET ip_address = %s WHERE username = %s', $ip, $username); if ($cnt != 1) { error("cannot set IP for '{$username}'"); } } if (AUTH_METHOD == 'PHP_SESSIONS') { session_start(); $_SESSION['username'] = $username; auditlog('user', $userdata['userid'], 'logged in', $ip); } break; case 'LDAP': $user = trim($_POST['login']); $pass = trim($_POST['passwd']); $title = 'Authenticate user'; $menu = false; if (empty($user) || empty($pass)) { show_failed_login("Please supply a username and password."); } $userdata = $DB->q('MAYBETUPLE SELECT * FROM user WHERE username = %s AND enabled = 1', $user); if (!$userdata || !ldap_check_credentials($userdata['username'], $pass)) { sleep(1); show_failed_login("Invalid username or password supplied. " . "Please try again or contact a staff member."); } $username = $userdata['username']; session_start(); $_SESSION['username'] = $username; auditlog('user', $userdata['userid'], 'logged in', $ip); break; case 'EXTERNAL': if (empty($_SERVER['REMOTE_USER'])) { show_failed_login("No authentication data provided by Apache."); } break; default: error("Unknown authentication method '" . AUTH_METHOD . "' requested, or login not supported."); } // Authentication success. We could just return here, but we do a // redirect to clear the POST data from the browser. $DB->q('UPDATE user SET last_login = %s, last_ip_address = %s WHERE username = %s', now(), $ip, $username); $script = $_SERVER['PHP_SELF']; if (preg_match('/\\/public\\/login\\.php$/', $_SERVER['PHP_SELF'])) { logged_in(); // fill userdata if (checkrole('jury') || checkrole('balloon')) { header("Location: ../jury/"); exit; } else { if (checkrole('team')) { header("Location: ../team/"); exit; } } } header("Location: ./"); exit; }
<?php /** * Switch a user to the right site based on whether they can be * authenticated as team, jury, or nothing (public). * * Part of the DOMjudge Programming Contest Jury System and licenced * under the GNU GPL. See README and COPYING for details. */ require_once 'configure.php'; require_once LIBDIR . '/lib.error.php'; require_once LIBDIR . '/lib.misc.php'; require_once LIBDIR . '/use_db.php'; // Team login necessary for checking login credentials: setup_database_connection(); require_once LIBWWWDIR . '/common.php'; require_once LIBWWWDIR . '/auth.php'; $target = 'public/'; if (logged_in()) { if (checkrole('jury')) { $target = 'jury/'; } elseif (checkrole('team', false)) { $target = 'team/'; } elseif (checkrole('balloon')) { $target = 'jury/balloons.php'; } } header('HTTP/1.1 302 Please see this page'); header('Location: ' . $target);
<a href="rejudgings.php" accesskey="r" id="menu_rejudgings"><span class="octicon octicon-sync"></span> rejudgings</a> <?php } } /* checkrole('jury') */ if (have_printing()) { ?> <a href="print.php" accesskey="p"><span class="octicon octicon-file-text"></span> print</a> <?php } if (checkrole('jury')) { ?> <a href="scoreboard.php" accesskey="b"><span class="octicon octicon-list-ordered"></span> scoreboard</a> <?php } if (checkrole('team')) { echo "<a target=\"_top\" href=\"../team/\" accesskey=\"t\"><span class=\"octicon octicon-arrow-right\"></span> team</a>\n"; } ?> </div> <div id="menutopright"> <?php putClock(); $notify_flag = isset($_COOKIE["domjudge_notify"]) && (bool) $_COOKIE["domjudge_notify"]; $refresh_flag = !isset($_COOKIE["domjudge_refresh"]) || (bool) $_COOKIE["domjudge_refresh"]; echo "<div id=\"toggles\">\n"; if (isset($refresh)) { $text = $refresh_flag ? 'Disable' : 'Enable'; echo '<input id="refresh-toggle" type="button" value="' . $text . ' refresh" />'; }
<nav><div id="menutop"> <a href="index.php" accesskey="h"><span class="octicon octicon-home"></span> home</a> <a href="problems.php" accesskey="p"><span class="octicon octicon-book"></span> problems</a> <?php logged_in(); // fill userdata if (checkrole('team')) { echo "<a target=\"_top\" href=\"../team/\" accesskey=\"t\"><span class=\"octicon octicon-arrow-right\"></span> team</a>\n"; } if (checkrole('jury') || checkrole('balloon')) { echo "<a target=\"_top\" href=\"../jury/\" accesskey=\"j\"><span class=\"octicon octicon-arrow-right\"></span> jury</a>\n"; } if (!logged_in()) { echo "<a href=\"login.php\" accesskey=\"l\"><span class=\"octicon octicon-sign-in\"></span> login</a>\n"; } ?> </div></nav>
/** * Call an API function */ public function callFunction($name, $arguments) { if ($_SERVER['REQUEST_METHOD'] == 'PUT') { list($name, $primary_key) = explode('/', $name); $arguments['__primary_key'] = $primary_key; } else { if ($_SERVER['REQUEST_METHOD'] == 'POST') { $postmax = phpini_to_bytes(trim(ini_get('post_max_size'))); if ($postmax != -1 && $postmax < $_SERVER['CONTENT_LENGTH']) { $this->createError("Size of post data too large (" . $_SERVER['CONTENT_LENGTH'] . "), increase post_max_size (" . $postmax . ") in your PHP config."); } } } $name = $name . '#' . $_SERVER['REQUEST_METHOD']; if (!array_key_exists($name, $this->apiFunctions)) { $this->createError("Function '" . $name . "' does not exist.", BAD_REQUEST); } $func = $this->apiFunctions[$name]; // Permissions // no roles = anyone may access; admin may also access all if (!empty($func['roles']) && !checkrole('admin')) { $hasrole = false; foreach ($func['roles'] as $role) { if (checkrole($role)) { $hasrole = TRUE; break; } } if (!$hasrole) { $this->createError("Permission denied " . "' for function '" . $name . "'.", FORBIDDEN); } } // Arguments $args = array(); foreach ($arguments as $key => $value) { if (!array_key_exists($key, $func['optArgs']) && $key != '__primary_key') { $this->createError("Invalid argument '" . $key . "' for function '" . $name . "'.", BAD_REQUEST); } $args[$key] = $value; } // Special case for public: if (array_key_exists('public', $func['optArgs'])) { if (checkrole('jury') && !isset($args['public'])) { // Default for jury is non-public $args['public'] = 0; } elseif (!checkrole('jury')) { // Only allowed for non-jury is public $args['public'] = 1; } } $this->createResponse(call_user_func($func['callback'], $args)); }
$REQUIRED_ROLES = array('jury', 'balloon'); require 'init.php'; $title = 'Jury interface'; require LIBWWWDIR . '/header.php'; echo "<h1>DOMjudge Jury interface</h1>\n\n"; if (is_readable('../images/DOMjudgelogo.png')) { echo "<p><a href=\"https://www.domjudge.org/\">" . "<img src=\"../images/DOMjudgelogo.png\" id=\"djlogo\" " . "alt=\"DOMjudge logo\" title=\"The DOMjudge logo: free as in beer!\" /></a></p>\n\n"; } ?> <h3>Overviews:</h3> <ul> <li><a href="balloons.php">Balloon Status</a></li> <?php if (checkrole('jury')) { ?> <li><a href="clarifications.php">Clarifications</a></li> <li><a href="contests.php">Contests</a></li> <li><a href="executables.php">Executables</a></li> <li><a href="judgehosts.php">Judgehosts</a></li> <li><a href="judgehost_restrictions.php">Judgehost Restrictions</a></li> <li><a href="languages.php">Languages</a></li> <li><a href="problems.php">Problems</a></li> <li><a href="scoreboard.php">Scoreboard</a></li> <li><a href="statistics.php">Statistics</a></li> <li><a href="submissions.php">Submissions</a></li> <li><a href="users.php">Users</a></li> <li><a href="teams.php">Teams</a></li> <li><a href="team_categories.php">Team Categories</a></li> <li><a href="team_affiliations.php">Team Affiliations</a></li>
/** * Submissions information */ function submissions($args) { global $DB, $cdatas, $api; $query = 'SELECT submitid, teamid, probid, langid, submittime, valid FROM submission WHERE TRUE'; $hasCid = array_key_exists('cid', $args); $query .= $hasCid ? ' AND cid = %i' : ' AND TRUE %_'; $cid = $hasCid ? $args['cid'] : 0; $hasLanguage = array_key_exists('language', $args); $query .= $hasLanguage ? ' AND langid = %s' : ' AND TRUE %_'; $language = $hasLanguage ? $args['language'] : 0; $hasFromid = array_key_exists('fromid', $args); $query .= $hasFromid ? ' AND submitid >= %i' : ' AND TRUE %_'; $fromId = $hasFromid ? $args['fromid'] : 0; $hasSubmitid = array_key_exists('id', $args); $query .= $hasSubmitid ? ' AND submitid = %i' : ' AND TRUE %_'; $submitid = $hasSubmitid ? $args['id'] : 0; if ($cid == 0 && !checkrole('jury')) { $api->createError("argument 'cid' is mandatory for non-jury users"); } if ($cid != 0 && infreeze($cdatas[$cid], now()) && !checkrole('jury')) { $query .= ' AND submittime <= %i'; $freezetime = $cdatas[$cid]['freezetime']; } else { $query .= ' AND TRUE %_'; $freezetime = 0; } $query .= ' ORDER BY submitid'; $hasLimit = array_key_exists('limit', $args); $query .= $hasLimit ? ' LIMIT %i' : ' %_'; $limit = $hasLimit ? $args['limit'] : -1; // TODO: validate limit $q = $DB->q($query, $cid, $language, $fromId, $submitid, $freezetime, $limit); $res = array(); while ($row = $q->next()) { $res[] = array('id' => safe_int($row['submitid']), 'team' => safe_int($row['teamid']), 'problem' => safe_int($row['probid']), 'language' => $row['langid'], 'time' => safe_float($row['submittime'])); } return $res; }
setup_database_connection(); require_once LIBWWWDIR . '/common.php'; require_once LIBWWWDIR . '/print.php'; require_once LIBWWWDIR . '/clarification.php'; require_once LIBWWWDIR . '/scoreboard.php'; require_once LIBWWWDIR . '/printing.php'; require_once LIBWWWDIR . '/auth.php'; require_once LIBWWWDIR . '/forms.php'; // The functions do_login and show_loginpage, if called, do not return. if (@$_POST['cmd'] == 'login') { do_login(); } if (!logged_in()) { show_loginpage(); } if (!checkrole('team')) { error("You do not have permission to perform that action (Missing role: 'team')"); } if (empty($teamdata)) { error("You do not have a team associated with your account. Please contact a staff member."); } if ($teamdata['enabled'] != 1) { error("Team is not enabled."); } $cdatas = getCurContests(TRUE, $teamdata['teamid']); $cids = array_keys($cdatas); // If the cookie has a existing contest, use it if (isset($_COOKIE['domjudge_cid']) && isset($cdatas[$_COOKIE['domjudge_cid']])) { $cid = $_COOKIE['domjudge_cid']; $cdata = $cdatas[$cid]; } elseif (count($cids) >= 1) {
/** * POST a new submission */ function submissions_POST($args) { global $userdata, $DB, $api; checkargs($args, array('shortname', 'langid')); checkargs($userdata, array('teamid')); $contests = getCurContests(TRUE, $userdata['teamid'], false, 'shortname'); $contest_shortname = null; if (isset($args['contest'])) { if (isset($contests[$args['contest']])) { $contest_shortname = $args['contest']; } else { $api->createError("Cannot find active contest '{$args['contest']}', or you are not part of it."); } } else { if (count($contests) == 1) { $contest_shortname = key($contests); } else { $api->createError("No contest specified while multiple active contests found."); } } $cid = $contests[$contest_shortname]['cid']; $probid = $DB->q('MAYBEVALUE SELECT probid FROM problem INNER JOIN contestproblem USING (probid) WHERE shortname = %s AND cid = %i AND allow_submit = 1', $args['shortname'], $cid); if (empty($probid)) { error("Problem " . $args['shortname'] . " not found or or not submittable"); } // rebuild array of filenames, paths to get rid of empty upload fields $FILEPATHS = $FILENAMES = array(); foreach ($_FILES['code']['tmp_name'] as $fileid => $tmpname) { if (!empty($tmpname)) { checkFileUpload($_FILES['code']['error'][$fileid]); $FILEPATHS[] = $_FILES['code']['tmp_name'][$fileid]; $FILENAMES[] = $_FILES['code']['name'][$fileid]; } } $sid = submit_solution($userdata['teamid'], $probid, $cid, $args['langid'], $FILEPATHS, $FILENAMES); if (checkrole('jury')) { $results = getExpectedResults(file_get_contents($FILEPATHS[0])); if (!empty($results)) { $DB->q('UPDATE submission SET expected_results=%s WHERE submitid=%i', json_encode($results), $sid); } } auditlog('submission', $sid, 'added', 'via api', null, $cid); return safe_int($sid); }
<?php /** * Include required files. * * Part of the DOMjudge Programming Contest Jury System and licenced * under the GNU GPL. See README and COPYING for details. */ require_once '../configure.php'; /* For plugins to have jury access rights to the DB, they should * successfully authenticate as user 'jury'. */ require_once LIBDIR . '/init.php'; require_once LIBWWWDIR . '/common.php'; require_once LIBWWWDIR . '/print.php'; require_once LIBWWWDIR . '/auth.php'; setup_database_connection(); if (!logged_in() && isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) { do_login_native($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']); $userdata['roles'] = get_user_roles($userdata['userid']); } if (!checkrole('full_event_reader')) { error("User role full_event_reader required."); } define('IS_JURY', true); define('IS_PUBLIC', false); $cdatas = getCurContests(TRUE); $cids = array_keys($cdatas);
ORDER BY shortname', $cid); putgetMainExtension($langdata); echo "function getProbDescription(probid)\n{\n"; echo "\tswitch(probid) {\n"; foreach ($probdata as $probinfo) { echo "\t\tcase '" . specialchars($probinfo['shortname']) . "': return '" . specialchars($probinfo['name']) . "';\n"; } echo "\t\tdefault: return '';\n\t}\n}\n\n"; } echo "initReload(" . $refreshtime . ");\n"; echo "// -->\n</script>\n"; // Put overview of team submissions (like scoreboard) putTeamRow($cdata, array($teamid)); echo "<div id=\"submitlist\">\n"; echo "<h3 class=\"teamoverview\">Submissions</h3>\n\n"; if ($fdata['cstarted'] || checkrole('jury')) { echo <<<HTML <script type="text/javascript"> \$(function() { \tvar matches = location.hash.match(/submitted=(\\d+)/); \tif (matches) { \t\tvar \$p = \$('<p class="submissiondone" />').html('submission done <a href="#">x</a>'); \t\t\$('#submitlist > .teamoverview').after(\$p); \t\t\$('table.submissions tr[data-submission-id=' + matches[1] + ']').addClass('highlight'); \t\t\$('.submissiondone a').on('click', function() { \t\t\t\$(this).parent().remove(); \t\t\t\$('table.submissions tr.highlight').removeClass('highlight'); \t\t\treloadLocation = 'index.php'; \t\t}); \t}
/** * Check whether the logged in user has DOMjudge administrator level, * as defined in passwords.php. If not, error and stop further execution. */ function requireAdmin() { if (!checkrole('admin')) { error("This function is only accessible to administrators."); } }
do_login(); } if (!logged_in()) { show_loginpage(); } if (checkrole('admin')) { define('IS_ADMIN', true); } else { define('IS_ADMIN', false); } if (!isset($REQUIRED_ROLES)) { $REQUIRED_ROLES = array('jury'); } $allowed = false; foreach ($REQUIRED_ROLES as $role) { if (checkrole($role)) { $allowed = true; } } if (!$allowed) { error("You do not have permission to perform that action (Missing role(s): " . implode($REQUIRED_ROLES, ',') . ")"); } require_once LIBWWWDIR . '/common.jury.php'; if ($_SERVER['REQUEST_METHOD'] == 'POST' && empty($_POST) && empty($_FILES) && isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['CONTENT_LENGTH'] > 0) { error("POST data exceeded php.ini's 'post_max_size' directive."); } $cdatas = getCurContests(TRUE, null, TRUE); $cids = array_keys($cdatas); // List of executable script types, used in various places: $executable_types = array('compare' => 'compare', 'compile' => 'compile', 'run' => 'run'); // If the cookie has a existing contest, use it
<?php /** * Edit source code and resubmit to the database. * * Part of the DOMjudge Programming Contest Jury System and licenced * under the GNU GPL. See README and COPYING for details. */ require 'init.php'; if (empty($teamid) || !checkrole('team')) { error("You cannot re-submit code without being a team."); } // submit code if (isset($_POST['origsubmitid'])) { $sources = $DB->q('TABLE SELECT * FROM submission_file LEFT JOIN submission USING(submitid) WHERE submitid = %i ORDER BY rank', $_POST['origsubmitid']); $files = array(); $filenames = array(); foreach ($sources as $sourcedata) { if (!($tmpfname = tempnam(TMPDIR, "edit_source-"))) { error("Could not create temporary file."); } file_put_contents($tmpfname, $_POST['source' . $sourcedata['rank']]); $files[] = $tmpfname; $filenames[] = $sourcedata['filename']; } $cid = $DB->q('VALUE SELECT cid FROM submission WHERE submitid = %i', $_POST['origsubmitid']); $newid = submit_solution($teamid, $_POST['probid'], $cid, $_POST['langid'], $files, $filenames, $_POST['origsubmitid']);
/** * 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 (!checkrole('jury') && 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 $DB->q('START TRANSACTION'); $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)); } $DB->q('COMMIT'); // 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; }
* under the GNU GPL. See README and COPYING for details. */ require 'init.php'; $title = 'Submit'; if (!isset($_POST['submit'])) { header('Location: ./'); return; } if (is_null($cid)) { require LIBWWWDIR . '/header.php'; echo "<p class=\"nodata\">No active contest</p>\n"; require LIBWWWDIR . '/footer.php'; exit; } $now = now(); if (!checkrole('jury') && difftime($cdata['starttime'], $now) > 0) { require LIBWWWDIR . '/header.php'; echo "<p class=\"nodata\">Contest has not yet started.</p>\n"; require LIBWWWDIR . '/footer.php'; exit; } /** helper to output an error message. */ function err($string) { // Annoying PHP: we need to import global variables here... global $title; require LIBWWWDIR . '/header.php'; echo "<h2>Submit - error</h2>\n\n"; echo '<div id="uploadstatus">'; logmsg(LOG_WARNING, $string); echo '</div>';