Esempio n. 1
0
 public static function isInsideContest(Contests $contest, $user_id)
 {
     if (time() > strtotime($contest->finish_time) || time() < strtotime($contest->start_time)) {
         return false;
     }
     if (is_null($contest->window_length)) {
         return true;
     }
     $contest_user = ContestsUsersDAO::getByPK($user_id, $contest->contest_id);
     $first_access_time = $contest_user->access_time;
     return time() <= strtotime($first_access_time) + $contest->window_length * 60;
 }
Esempio n. 2
0
 /**
  * Show the contest intro unless you are admin, or you
  * already started this contest.
  */
 public static function showContestIntro(Request $r)
 {
     try {
         $r["contest"] = ContestsDAO::getByAlias($r["contest_alias"]);
     } catch (Exception $e) {
         throw new NotFoundException("contestNotFound");
     }
     if (is_null($r['contest'])) {
         throw new NotFoundException("contestNotFound");
     }
     try {
         // Half-authenticate, in case there is no session in place.
         $session = SessionController::apiCurrentSession($r);
         if ($session['valid'] && !is_null($session['user'])) {
             $r["current_user"] = $session['user'];
             $r["current_user_id"] = $session['user']->user_id;
         }
         self::canAccessContest($r);
     } catch (Exception $e) {
         // Could not access contest. Private contests must not be leaked, so
         // unless they were manually added beforehand, show them a 404 error.
         if (!ContestController::isInvitedToContest($r)) {
             throw $e;
         }
         self::$log->error("Exception while trying to verify access: " . $e);
         return ContestController::SHOW_INTRO;
     }
     $cs = SessionController::apiCurrentSession();
     // You already started the contest.
     $contestOpened = ContestsUsersDAO::getByPK($r['current_user_id'], $r["contest"]->getContestId());
     if (!is_null($contestOpened) && $contestOpened->access_time != "0000-00-00 00:00:00") {
         self::$log->debug("Not intro because you already started the contest");
         return !ContestController::SHOW_INTRO;
     }
     return ContestController::SHOW_INTRO;
 }
Esempio n. 3
0
 /**
  * Create a new run
  *
  * @param Request $r
  * @return array
  * @throws Exception
  * @throws InvalidDatabaseOperationException
  * @throws InvalidFilesystemOperationException
  */
 public static function apiCreate(Request $r)
 {
     // Init
     self::initializeGrader();
     // Authenticate user
     self::authenticateRequest($r);
     // Validate request
     self::validateCreateRequest($r);
     self::$log->info('New run being submitted!!');
     $response = array();
     if (self::$practice) {
         if (OMEGAUP_LOCKDOWN) {
             throw new ForbiddenAccessException('lockdown');
         }
         $submit_delay = 0;
         $contest_id = null;
         $test = 0;
     } else {
         //check the kind of penalty_type for this contest
         $penalty_type = $r['contest']->penalty_type;
         switch ($penalty_type) {
             case 'contest_start':
                 // submit_delay is calculated from the start
                 // of the contest
                 $start = $r['contest']->getStartTime();
                 break;
             case 'problem_open':
                 // submit delay is calculated from the
                 // time the user opened the problem
                 $opened = ContestProblemOpenedDAO::getByPK($r['contest']->getContestId(), $r['problem']->getProblemId(), $r['current_user_id']);
                 if (is_null($opened)) {
                     //holy moly, he is submitting a run
                     //and he hasnt even opened the problem
                     //what should be done here?
                     throw new NotAllowedToSubmitException('runEvenOpened');
                 }
                 $start = $opened->getOpenTime();
                 break;
             case 'none':
             case 'runtime':
                 //we dont care
                 $start = null;
                 break;
             default:
                 self::$log->error('penalty_type for this contests is not a valid option, asuming `none`.');
                 $start = null;
         }
         if (!is_null($start)) {
             //ok, what time is it now?
             $c_time = time();
             $start = strtotime($start);
             //asuming submit_delay is in minutes
             $submit_delay = (int) (($c_time - $start) / 60);
         } else {
             $submit_delay = 0;
         }
         $contest_id = $r['contest']->getContestId();
         $test = Authorization::IsContestAdmin($r['current_user_id'], $r['contest']) ? 1 : 0;
     }
     // Populate new run object
     $run = new Runs(array('user_id' => $r['current_user_id'], 'problem_id' => $r['problem']->getProblemId(), 'contest_id' => $contest_id, 'language' => $r['language'], 'source' => $r['source'], 'status' => 'new', 'runtime' => 0, 'penalty' => $submit_delay, 'memory' => 0, 'score' => 0, 'contest_score' => $contest_id != null ? 0 : null, 'submit_delay' => $submit_delay, 'guid' => md5(uniqid(rand(), true)), 'verdict' => 'JE', 'test' => $test));
     try {
         // Push run into DB
         RunsDAO::save($run);
         SubmissionLogDAO::save(new SubmissionLog(array('user_id' => $run->user_id, 'run_id' => $run->run_id, 'contest_id' => $run->contest_id, 'ip' => ip2long($_SERVER['REMOTE_ADDR']))));
         // Update submissions counter++
         $r['problem']->setSubmissions($r['problem']->getSubmissions() + 1);
         ProblemsDAO::save($r['problem']);
     } catch (Exception $e) {
         // Operation failed in the data layer
         throw new InvalidDatabaseOperationException($e);
     }
     try {
         // Create file for the run
         $filepath = RunController::getSubmissionPath($run);
         FileHandler::CreateFile($filepath, $r['source']);
     } catch (Exception $e) {
         throw new InvalidFilesystemOperationException($e);
     }
     // Call Grader
     try {
         self::$grader->Grade([$run->guid], false, false);
     } catch (Exception $e) {
         self::$log->error('Call to Grader::grade() failed:');
         self::$log->error($e);
     }
     if (self::$practice) {
         $response['submission_deadline'] = 0;
     } else {
         // Add remaining time to the response
         try {
             $contest_user = ContestsUsersDAO::getByPK($r['current_user_id'], $r['contest']->getContestId());
             if ($r['contest']->getWindowLength() === null) {
                 $response['submission_deadline'] = strtotime($r['contest']->getFinishTime());
             } else {
                 $response['submission_deadline'] = min(strtotime($r['contest']->getFinishTime()), strtotime($contest_user->getAccessTime()) + $r['contest']->getWindowLength() * 60);
             }
         } catch (Exception $e) {
             // Operation failed in the data layer
             throw new InvalidDatabaseOperationException($e);
         }
     }
     // Happy ending
     $response['guid'] = $run->getGuid();
     $response['status'] = 'ok';
     // Expire rank cache
     UserController::deleteProblemsSolvedRankCacheList();
     return $response;
 }
 /**
  * Validate problem Details API
  *
  * @param Request $r
  * @throws ApiException
  * @throws InvalidDatabaseOperationException
  * @throws NotFoundException
  * @throws ForbiddenAccessException
  */
 private static function validateDetails(Request $r)
 {
     Validators::isStringNonEmpty($r['contest_alias'], 'contest_alias', false);
     Validators::isStringNonEmpty($r['problem_alias'], 'problem_alias');
     // Lang is optional. Default is user's preferred.
     if (!is_null($r['lang'])) {
         Validators::isStringOfMaxLength($r['lang'], 'lang', 2);
     } else {
         $r['lang'] = UserController::getPreferredLanguage($r);
     }
     try {
         $r['problem'] = ProblemsDAO::getByAlias($r['problem_alias']);
     } catch (Exception $e) {
         throw new InvalidDatabaseOperationException($e);
     }
     if (is_null($r['problem'])) {
         throw new NotFoundException('problemNotFound');
     }
     if (isset($r['statement_type']) && !in_array($r['statement_type'], array('html', 'markdown'))) {
         throw new NotFoundException('invalidStatementType');
     }
     // If we request a problem inside a contest
     if (!is_null($r['contest_alias'])) {
         // Is the combination contest_id and problem_id valid?
         try {
             $r['contest'] = ContestsDAO::getByAlias($r['contest_alias']);
             if (is_null($r['contest'])) {
                 throw new NotFoundException('contestNotFound');
             }
             if (is_null(ContestProblemsDAO::getByPK($r['contest']->getContestId(), $r['problem']->getProblemId()))) {
                 throw new NotFoundException('problemNotFoundInContest');
             }
         } catch (ApiException $apiException) {
             throw $apiException;
         } catch (Exception $e) {
             throw new InvalidDatabaseOperationException($e);
         }
         // If the contest is private, verify that our user is invited
         $contest_admin = Authorization::IsContestAdmin($r['current_user_id'], $r['contest']);
         if ($r['contest']->public != '1') {
             if (is_null(ContestsUsersDAO::getByPK($r['current_user_id'], $r['contest']->contest_id)) && !$contest_admin) {
                 throw new ForbiddenAccessException();
             }
         }
         // If the contest has not started, user should not see it, unless
         // it is admin
         if (!ContestsDAO::hasStarted($r['contest']) && !$contest_admin) {
             throw new ForbiddenAccessException('contestNotStarted');
         }
     } else {
         if (!Authorization::CanEditProblem($r['current_user_id'], $r['problem'])) {
             // If the problem is requested outside a contest, we need to
             // check that it is not private
             if ($r['problem']->public != '1') {
                 throw new ForbiddenAccessException('problemIsPrivate');
             }
         }
     }
 }
 /**
  * First access time should not change
  */
 public function testAccessTimeIsAlwaysFirstAccessForPrivate()
 {
     // Get a contest
     $contestData = ContestsFactory::createContest(null, 0);
     // Get a user for our scenario
     $contestant = UserFactory::createUser();
     // Add user to our private contest
     ContestsFactory::addUser($contestData, $contestant);
     // Prepare our request
     $r = new Request();
     $r['contest_alias'] = $contestData['request']['alias'];
     // Log in the user
     $r['auth_token'] = $this->login($contestant);
     // Call api
     $response = ContestController::apiDetails($r);
     // We need to grab the access time from the ContestUsers table
     $contest = ContestsDAO::getByAlias($contestData['request']['alias']);
     $contest_user = ContestsUsersDAO::getByPK($contestant->getUserId(), $contest->getContestId());
     $firstAccessTime = $contest_user->getAccessTime();
     // Call API again, access time should not change
     $response = ContestController::apiDetails($r);
     $contest_user = ContestsUsersDAO::getByPK($contestant->getUserId(), $contest->getContestId());
     $this->assertEquals($firstAccessTime, $contest_user->getAccessTime());
 }
Esempio n. 6
0
 /**
  * Show the contest intro unless you are admin, or you 
  * already started this contest.
  */
 public static function showContestIntro(Request $r)
 {
     try {
         $r["contest"] = ContestsDAO::getByAlias($r["contest_alias"]);
     } catch (Exception $e) {
         throw new NotFoundException("contestNotFound");
     }
     try {
         // Half-authenticate, in case there is no session in place.
         $session = SessionController::apiCurrentSession($r);
         if ($session['valid'] && $session['user'] != null) {
             $r["current_user"] = $session['user'];
             $r["current_user_id"] = $session['user']->user_id;
         }
         self::canAccessContest($r);
     } catch (Exception $e) {
         self::$log->error("Exception while trying to verify access: " . $e);
         return ContestController::SHOW_INTRO;
     }
     // You are admin
     if (!is_null($r['current_user_id']) && Authorization::IsContestAdmin($r["current_user_id"], $r["contest"])) {
         self::$log->debug("Not intro because you are admin");
         return !ContestController::SHOW_INTRO;
     }
     $cs = SessionController::apiCurrentSession();
     // You already started the contest.
     $contestOpened = null;
     if (!is_null($clarificationEmailBody = ContestsUsersDAO::getByPK($cs["id"], $r["contest"]->getContestId())) && $contestOpened->access_time != "0000-00-00 00:00:00") {
         self::$log->debug("Not intro because you already started the contest");
         return !ContestController::SHOW_INTRO;
     }
     return ContestController::SHOW_INTRO;
 }
Esempio n. 7
0
 /**
  * Test sending runs after the window length expired
  *
  * @expectedException NotAllowedToSubmitException
  */
 public function testNewRunOutWindowLengthPublicContest()
 {
     // Set the context for the first contest
     $r = $this->setValidRequest();
     // Alter Contest window length to 20
     // This means: once I started the contest, I have 20 more mins
     // to finish it.
     $contest = ContestsDAO::getByAlias($r["contest_alias"]);
     $contest->setWindowLength(20);
     ContestsDAO::save($contest);
     // Alter first access time of our contestant such that he started
     // 21 minutes ago, this is, window length has expired by 1 minute
     $contest_user = ContestsUsersDAO::getByPK($this->contestant->getUserId(), $contest->getContestId());
     $contest_user->setAccessTime(date("Y-m-d H:i:s", time() - 21 * 60));
     //Window length is in minutes
     ContestsUsersDAO::save($contest_user);
     // Call API
     RunController::apiCreate($r);
 }
Esempio n. 8
0
 /**
  * Validate problem Details API
  * 
  * @param Request $r
  * @throws ApiException
  * @throws InvalidDatabaseOperationException
  * @throws NotFoundException
  * @throws ForbiddenAccessException
  */
 private static function validateDetails(Request $r)
 {
     Validators::isStringNonEmpty($r["contest_alias"], "contest_alias", false);
     Validators::isStringNonEmpty($r["problem_alias"], "problem_alias");
     // Lang is optional. Default is user's preferred.
     if (!is_null($r["lang"])) {
         Validators::isStringOfMaxLength($r["lang"], "lang", 2);
     } else {
         $r['lang'] = UserController::getPreferredLanguage($r);
     }
     try {
         $r["problem"] = ProblemsDAO::getByAlias($r["problem_alias"]);
     } catch (Exception $e) {
         throw new InvalidDatabaseOperationException($e);
     }
     if (is_null($r["problem"])) {
         throw new NotFoundException("problemNotFound");
     }
     if (isset($r["statement_type"]) && !in_array($r["statement_type"], array("html", "markdown"))) {
         throw new NotFoundException("invalidStatementType");
     }
     // If we request a problem inside a contest
     if (!is_null($r["contest_alias"])) {
         // Is the combination contest_id and problem_id valid?
         try {
             $r["contest"] = ContestsDAO::getByAlias($r["contest_alias"]);
             if (is_null($r["contest"])) {
                 throw new NotFoundException("contestNotFound");
             }
             if (is_null(ContestProblemsDAO::getByPK($r["contest"]->getContestId(), $r["problem"]->getProblemId()))) {
                 throw new NotFoundException("problemNotFoundInContest");
             }
         } catch (ApiException $apiException) {
             throw $apiException;
         } catch (Exception $e) {
             throw new InvalidDatabaseOperationException($e);
         }
         // If the contest is private, verify that our user is invited
         if ($r["contest"]->getPublic() === 0) {
             if (is_null(ContestsUsersDAO::getByPK($r["current_user_id"], $r["contest"]->getContestId())) && !Authorization::IsContestAdmin($r["current_user_id"], $r["contest"])) {
                 throw new ForbiddenAccessException();
             }
         }
         // If the contest has not started, user should not see it, unless it is admin
         if (!ContestsDAO::hasStarted($r["contest"]) && !Authorization::IsContestAdmin($r["current_user_id"], $r["contest"])) {
             throw new ForbiddenAccessException("contestNotStarted");
         }
     } else {
         if (!Authorization::CanEditProblem($r["current_user_id"], $r["problem"])) {
             // If the problem is requested outside a contest, we need to check that it is not private
             if ($r["problem"]->getPublic() == "0") {
                 throw new ForbiddenAccessException("problemIsPrivate");
             }
         }
     }
 }