예제 #1
0
 public function testEditProblem()
 {
     // Login
     $author = $this->createUserAndLogin();
     // Create a problem
     $problemData = ProblemsFactory::createProblem(null, null, 1, $author);
     // Open problem create
     $this->open('/problemedit.php');
     sleep(1);
     $this->type('name=edit-problem-list', $problemData["request"]["alias"]);
     $this->waitForValue('name=title', $problemData["request"]["title"]);
     $problemNewData = ProblemsFactory::getRequest();
     $this->type('name=title', $problemNewData["request"]["title"]);
     $this->type('source', $problemNewData["request"]["source"]);
     $this->type('time_limit', '666');
     $this->type('memory_limit', '1234');
     $this->type('validator', 'token-caseless');
     $this->type('public', '1');
     // Click inicia sesion
     $this->clickAndWait("//input[@value='Actualizar problema']");
     $this->assertElementContainsText('//*[@id="content"]/div[2]/div', "Problem updated succesfully!");
     // Verify data in DB
     $problem_mask = new Problems();
     $problem_mask->setTitle($problemNewData["request"]["title"]);
     $problems = ProblemsDAO::search($problem_mask);
     // Check that we only retreived 1 element
     $this->assertEquals(1, count($problems));
     $this->assertEquals($problemNewData["request"]["source"], $problems[0]->getSource());
     $this->assertEquals(666, $problems[0]->getTimeLimit());
     $this->assertEquals(1234, $problems[0]->getMemoryLimit());
     $this->assertEquals('token-caseless', $problems[0]->getValidator());
     $this->assertEquals('1', $problems[0]->getPublic());
 }
예제 #2
0
 public function indexAction()
 {
     $this->checkLogin();
     $this->view->teams = Teams::find();
     $this->view->problems = Problems::find();
     $this->view->serverFiles = ServerFiles::find(array("order" => "friendlyName"));
 }
 /**
  * Test that we can produce a valid alias from the title
  */
 public function testConstructAliasFromTitle()
 {
     // Get the problem data
     $problemData = ProblemsFactory::getRequest();
     $r = $problemData['request'];
     $problemAuthor = $problemData['author'];
     // Set a valid "complex" title
     $r['title'] = 'Lá Venganza Del Malvado Dr. Liraaa';
     // Login user
     $r['auth_token'] = $this->login($problemAuthor);
     // Get File Uploader Mock and tell Omegaup API to use it
     FileHandler::SetFileUploader($this->createFileUploaderMock());
     // Call the API
     $response = ProblemController::apiCreate($r);
     // Validate
     // Verify response
     $this->assertEquals('ok', $response['status']);
     $this->assertEquals('testplan', $response['uploaded_files'][10]);
     // Verify data in DB
     $problem_mask = new Problems();
     $problem_mask->setTitle($r['title']);
     $problems = ProblemsDAO::search($problem_mask);
     // Check that we only retreived 1 element
     $this->assertEquals(1, count($problems));
     $problem = $problems[0];
     // Verify contest was found
     $this->assertNotNull($problem);
     $this->assertNotNull($problem->getProblemId());
     // Verify DB data
     $this->assertEquals($r['title'], $problem->getTitle());
     // Verify problem contents were copied
     $targetpath = PROBLEMS_PATH . DIRECTORY_SEPARATOR . $problem->getAlias() . DIRECTORY_SEPARATOR;
     $this->assertFileExists($targetpath . 'testplan');
     $this->assertFileExists($targetpath . 'cases');
     $this->assertFileExists($targetpath . 'statements' . DIRECTORY_SEPARATOR . 'en.html');
 }
예제 #4
0
 public static final function byUserType($user_type, $order, $mode, $offset, $rowcount, $query, $user_id, $tag, &$total)
 {
     global $conn;
     // Just in case.
     if ($mode !== 'asc' && $mode !== 'desc') {
         $mode = 'desc';
     }
     // Use BINARY mode to force case sensitive comparisons when ordering by title.
     $collation = $order === 'title' ? 'COLLATE utf8_bin' : '';
     $select = '';
     $sql = '';
     $args = array();
     if ($user_type === USER_ADMIN) {
         $args = array($user_id);
         $select = '
             SELECT
                 100 / LOG2(GREATEST(accepted, 1) + 1)   AS points,
                 accepted / GREATEST(1, submissions)     AS ratio,
                 ROUND(100 * COALESCE(ps.score, 0))      AS score,
                 p.*';
         $sql = '
             FROM
                 Problems p
             LEFT JOIN (
                 SELECT
                     Problems.problem_id,
                     MAX(Runs.score) AS score
                 FROM
                     Problems
                 INNER JOIN
                     Runs ON Runs.user_id = ? AND Runs.problem_id = Problems.problem_id
                 GROUP BY
                     Problems.problem_id
                 ) ps ON ps.problem_id = p.problem_id';
         $added_where = false;
         if (!is_null($tag)) {
             $sql .= ' INNER JOIN Problems_Tags pt ON pt.problem_id = p.problem_id';
             $sql .= ' INNER JOIN Tags t ON pt.tag_id = t.tag_id';
             $sql .= ' WHERE t.name = ?';
             $args[] = $tag;
             $added_where = true;
         }
         if (!is_null($query)) {
             if (!$added_where) {
                 $sql .= ' WHERE';
             } else {
                 $sql .= ' AND';
             }
             $sql .= " title LIKE CONCAT('%', ?, '%') ";
             $args[] = $query;
         }
     } elseif ($user_type === USER_NORMAL && !is_null($user_id)) {
         $select = '
             SELECT
                 100 / LOG2(GREATEST(p.accepted, 1) + 1) AS points,
                 p.accepted / GREATEST(1, p.submissions)     AS ratio,
                 ROUND(100 * COALESCE(ps.score, 0), 2)   AS score,
                 p.*';
         $sql = '
             FROM
                 Problems p
             LEFT JOIN (
                 SELECT
                     pi.problem_id,
                     MAX(r.score) AS score
                 FROM
                     Problems pi
                 INNER JOIN
                     Runs r ON r.user_id = ? AND r.problem_id = pi.problem_id
                 GROUP BY
                     pi.problem_id
             ) ps ON ps.problem_id = p.problem_id
             LEFT JOIN
                 User_Roles ur ON ur.user_id = ? AND p.problem_id = ur.contest_id
             LEFT JOIN
                 Groups_Users gu ON gu.user_id = ?
             LEFT JOIN
                 Group_Roles gr ON gr.group_id = gu.group_id AND p.problem_id = gr.contest_id';
         $args[] = $user_id;
         $args[] = $user_id;
         $args[] = $user_id;
         if (!is_null($tag)) {
             $sql .= ' INNER JOIN Problems_Tags pt ON pt.problem_id = p.problem_id';
             $sql .= ' INNER JOIN Tags t ON pt.tag_id = t.tag_id';
             $sql .= ' WHERE t.name = ? AND pt.public = 1 AND';
             $args[] = $tag;
         } else {
             $sql .= ' WHERE';
         }
         $sql .= '
             (p.public = 1 OR p.author_id = ? OR ur.role_id = 3 OR gr.role_id = 3) ';
         $args[] = $user_id;
         if (!is_null($query)) {
             $sql .= " AND p.title LIKE CONCAT('%', ?, '%')";
             $args[] = $query;
         }
     } elseif ($user_type === USER_ANONYMOUS) {
         $select = '
                 SELECT
                     0 AS score,
                     100 / LOG2(GREATEST(p.accepted, 1) + 1) AS points,
                     accepted / GREATEST(1, p.submissions)   AS ratio,
                     p.*';
         $sql = '
                 FROM
                     Problems p';
         if (!is_null($tag)) {
             $sql .= ' INNER JOIN Problems_Tags pt ON pt.problem_id = p.problem_id';
             $sql .= ' INNER JOIN Tags t ON pt.tag_id = t.tag_id';
             $sql .= ' WHERE t.name = ? AND pt.public = 1 AND';
             $args[] = $tag;
         } else {
             $sql .= ' WHERE';
         }
         $sql .= ' p.public = 1 ';
         if (!is_null($query)) {
             $sql .= " AND p.title LIKE CONCAT('%', ?, '%') ";
             $args[] = $query;
         }
     }
     $total = $conn->GetOne("SELECT COUNT(*) {$sql}", $args);
     // Reset the offset to 0 if out of bounds.
     if ($offset < 0 || $offset > $total) {
         $offset = 0;
     }
     if ($order == 'problem_id') {
         $sql .= " ORDER BY p.problem_id {$collation} {$mode}";
     } elseif ($order == 'points' && $mode == 'desc') {
         $sql .= ' ORDER BY `points` DESC, `accepted` ASC, `submissions` DESC';
     } else {
         $sql .= " ORDER BY `{$order}` {$collation} {$mode}";
     }
     $sql .= ' LIMIT ?, ?';
     $args[] = $offset;
     $args[] = $rowcount;
     $result = $conn->Execute("{$select} {$sql}", $args);
     // Only these fields (plus score, points and ratio) will be returned.
     $filters = array('title', 'submissions', 'accepted', 'alias', 'public');
     $problems = array();
     if (!is_null($result)) {
         foreach ($result as $row) {
             $temp = new Problems($row);
             $problem = $temp->asFilteredArray($filters);
             // score, points and ratio are not actually fields of a Problems object.
             $problem['score'] = $row['score'];
             $problem['points'] = $row['points'];
             $problem['ratio'] = $row['ratio'];
             $problem['tags'] = ProblemsDAO::getTagsForProblem($temp, true);
             array_push($problems, $problem);
         }
     }
     return $problems;
 }
 /**
  * Create a new problem
  *
  * @throws ApiException
  * @throws DuplicatedEntryInDatabaseException
  * @throws InvalidDatabaseOperationException
  */
 public static function apiCreate(Request $r)
 {
     self::authenticateRequest($r);
     // Validates request
     self::validateCreateOrUpdate($r);
     // Populate a new Problem object
     $problem = new Problems();
     $problem->setPublic($r['public']);
     /* private by default */
     $problem->setTitle($r['title']);
     $problem->setValidator($r['validator']);
     $problem->setTimeLimit($r['time_limit']);
     $problem->setValidatorTimeLimit($r['validator_time_limit']);
     $problem->setOverallWallTimeLimit($r['overall_wall_time_limit']);
     $problem->setExtraWallTime($r['extra_wall_time']);
     $problem->setMemoryLimit($r['memory_limit']);
     $problem->setOutputLimit($r['output_limit']);
     $problem->setVisits(0);
     $problem->setSubmissions(0);
     $problem->setAccepted(0);
     $problem->setDifficulty(0);
     $problem->setSource($r['source']);
     $problem->setOrder('normal');
     /* defaulting to normal */
     $problem->setAuthorId($r['current_user_id']);
     $problem->setAlias($r['alias']);
     $problem->setLanguages($r['languages']);
     $problem->setStackLimit($r['stack_limit']);
     $problem->setEmailClarifications($r['email_clarifications']);
     if (file_exists(PROBLEMS_PATH . DIRECTORY_SEPARATOR . $r['alias'])) {
         throw new DuplicatedEntryInDatabaseException('problemExists');
     }
     $problemDeployer = new ProblemDeployer($r['alias'], ProblemDeployer::CREATE);
     // Insert new problem
     try {
         ProblemsDAO::transBegin();
         // Create file after we know that alias is unique
         $problemDeployer->deploy();
         if ($problemDeployer->hasValidator) {
             $problem->validator = 'custom';
         } elseif ($problem->validator == 'custom') {
             throw new ProblemDeploymentFailedException('problemDeployerValidatorRequired');
         }
         $problem->slow = $problemDeployer->isSlow($problem);
         // Calculate output limit.
         $output_limit = $problemDeployer->getOutputLimit();
         if ($output_limit != -1) {
             $problem->setOutputLimit($output_limit);
         }
         // Save the contest object with data sent by user to the database
         ProblemsDAO::save($problem);
         ProblemsDAO::transEnd();
         // Commit at the very end
         $problemDeployer->commit('Initial commit', $r['current_user']);
     } catch (ApiException $e) {
         // Operation failed in something we know it could fail, rollback transaction
         ProblemsDAO::transRollback();
         throw $e;
     } catch (Exception $e) {
         self::$log->error('Failed to upload problem');
         self::$log->error($e);
         // Operation failed unexpectedly, rollback transaction
         ProblemsDAO::transRollback();
         // Alias may be duplicated, 1062 error indicates that
         if (strpos($e->getMessage(), '1062') !== false) {
             throw new DuplicatedEntryInDatabaseException('problemTitleExists');
         } else {
             throw new InvalidDatabaseOperationException($e);
         }
     } finally {
         $problemDeployer->cleanup();
     }
     // Adding unzipped files to response
     $result['uploaded_files'] = $problemDeployer->filesToUnzip;
     $result['status'] = 'ok';
     $result['alias'] = $r['alias'];
     return $result;
 }
 /**
  * Tests removed problem admin can't edit a problem anymore
  *
  * @expectedException ForbiddenAccessException
  */
 public function testUpdateProblemWithRemovedProblemAdmin()
 {
     // Get a problem
     $problemData = ProblemsFactory::createProblem();
     // Create our new admin
     $problemAdmin = UserFactory::createUser();
     // Add admin to the problem
     $response = ProblemController::apiAddAdmin(new Request(array('usernameOrEmail' => $problemAdmin->username, 'problem_alias' => $problemData['request']['alias'], 'auth_token' => $this->login($problemData['author']))));
     $this->assertEquals('ok', $response['status']);
     // Then remove the user
     $response = ProblemController::apiRemoveAdmin(new Request(array('usernameOrEmail' => $problemAdmin->username, 'problem_alias' => $problemData['request']['alias'], 'auth_token' => $this->login($problemData['author']))));
     $this->assertEquals('ok', $response['status']);
     //Call API
     $newTitle = 'new title coadmin';
     $response = ProblemController::apiUpdate(new Request(array('problem_alias' => $problemData['request']['alias'], 'title' => $newTitle, 'message' => 'Non-admin powers', 'auth_token' => $this->login($problemAdmin))));
     // Verify data in DB
     $problem_mask = new Problems();
     $problem_mask->setTitle($newTitle);
     $problems = ProblemsDAO::search($problem_mask);
 }
예제 #7
0
 /** 
  * Tests removed problem admin can't edit a problem anymore
  * 
  * @expectedException ForbiddenAccessException
  */
 public function testUpdateProblemWithRemovedProblemAdmin()
 {
     // Get a problem
     $problemData = ProblemsFactory::createProblem();
     // Create our new admin
     $problemAdmin = UserFactory::createUser();
     // Add admin to the problem
     $response = ProblemController::apiAddAdmin(new Request(array("usernameOrEmail" => $problemAdmin->username, "problem_alias" => $problemData["request"]["alias"], "auth_token" => $this->login($problemData["author"]))));
     $this->assertEquals("ok", $response["status"]);
     // Then remove the user
     $response = ProblemController::apiRemoveAdmin(new Request(array("usernameOrEmail" => $problemAdmin->username, "problem_alias" => $problemData["request"]["alias"], "auth_token" => $this->login($problemData["author"]))));
     $this->assertEquals("ok", $response["status"]);
     //Call API
     $newTitle = "new title coadmin";
     $response = ProblemController::apiUpdate(new Request(array("problem_alias" => $problemData["request"]["alias"], "title" => $newTitle, "message" => 'Non-admin powers', "auth_token" => $this->login($problemAdmin))));
     // Verify data in DB
     $problem_mask = new Problems();
     $problem_mask->setTitle($newTitle);
     $problems = ProblemsDAO::search($problem_mask);
 }
예제 #8
0
 public function problemsAction()
 {
     if (!$this->checkLogin()) {
         return;
     }
     if ($this->request->isPost() && $this->request->hasPost("type") && $this->security->checkToken()) {
         $this->session->set("changeOccurred", true);
         $this->session->set("changeSuccessful", true);
         $this->session->set("teamsGenerated", false);
         switch ($this->request->getPost("type")) {
             case 'update':
                 $problem = Problems::findFirst(intval($this->request->getPost("id")));
                 if ($problem) {
                     $problem->setName($this->request->getPost("name"));
                     $problem->setRuntime($this->request->getPost("runtime"));
                     if ($this->request->hasPost("hasDataFile")) {
                         if ($this->request->hasFiles()) {
                             // Adding data file
                             foreach ($this->request->getUploadedFiles() as $file) {
                                 if ($file->getKey() == "dataFile") {
                                     unlink($problem->getDataFile());
                                     $dataFileLocation = "../app/data/" . Phalcon\Text::random(Phalcon\Text::RANDOM_ALNUM, rand(13, 17));
                                     $problem->setDataFile($dataFileLocation);
                                     $problem->setDataFileFriendly($file->getName());
                                     $file->moveTo($dataFileLocation);
                                 }
                             }
                         }
                     } else {
                         if ($problem->getDataFile() != null) {
                             // Removing data file
                             unlink($problem->getDataFile());
                             $problem->setDataFile(null);
                             $problem->setDataFileFriendly(null);
                         }
                     }
                     if ($this->request->hasPost("hasJudgeFile")) {
                         if ($this->request->hasFiles()) {
                             // Adding judge file
                             foreach ($this->request->getUploadedFiles() as $file) {
                                 if ($file->getKey() == "judgeFile") {
                                     unlink($problem->getJudgeFile());
                                     $judgeFileLocation = "../app/data/" . Phalcon\Text::random(Phalcon\Text::RANDOM_ALNUM, rand(13, 17));
                                     $problem->setJudgeFile($judgeFileLocation);
                                     $problem->setJudgeFileFriendly($file->getName());
                                     $file->moveTo($judgeFileLocation);
                                 }
                             }
                         }
                     } else {
                         // Removing judge file
                         if ($problem->getJudgeFile() != null) {
                             unlink($problem->getJudgeFile());
                             $problem->setJudgeFile(null);
                             $problem->setJudgeFileFriendly(null);
                         }
                     }
                     if (!$problem->save()) {
                         $this->session->set("changeSuccessful", false);
                     }
                 } else {
                     $this->session->set("changeSuccessful", false);
                 }
                 break;
             case 'create':
                 $error = false;
                 $problem = new Problems();
                 $problem->setName($this->request->getPost("name"));
                 $problem->setRuntime($this->request->getPost("runtime"));
                 if ($this->request->hasFiles()) {
                     foreach ($this->request->getUploadedFiles() as $file) {
                         if ($file->getKey() == "dataFile" && $this->request->hasPost("hasDataFile")) {
                             $dataFileLocation = "../app/data/" . Phalcon\Text::random(Phalcon\Text::RANDOM_ALNUM, rand(13, 17));
                             $problem->setDataFile($dataFileLocation);
                             $problem->setDataFileFriendly($file->getName());
                             $file->moveTo($dataFileLocation);
                         }
                         if ($file->getKey() == "judgeFile" && $this->request->hasPost("hasJudgeFile")) {
                             $judgeFileLocation = "../app/data/" . Phalcon\Text::random(Phalcon\Text::RANDOM_ALNUM, rand(13, 17));
                             $problem->setJudgeFile($judgeFileLocation);
                             $problem->setJudgeFileFriendly($file->getName());
                             $file->moveTo($judgeFileLocation);
                         }
                     }
                 }
                 if ($error || !$problem->save()) {
                     $this->session->set("changeSuccessful", false);
                 }
                 break;
             case 'delete':
                 $problem = Problems::findFirst(intval($this->request->getPost("id")));
                 $dataLocation = $problem->getDataFile();
                 $judgeLocation = $problem->getJudgeFile();
                 if ($problem->delete()) {
                     unlink($dataLocation);
                     unlink($judgeLocation);
                 } else {
                     $this->session->set("changeSuccessful", false);
                 }
                 break;
             default:
                 $this->session->set("changeSuccessful", false);
                 break;
         }
         return $this->response->redirect("/admin/problems");
     } else {
         if ($this->session->has("changeOccurred")) {
             $this->view->changeOccurred = $this->session->get("changeOccurred");
             $this->session->remove("changeOccurred");
         }
         if ($this->session->has("changeSuccessful")) {
             $this->view->changeSuccessful = $this->session->get("changeSuccessful");
             $this->session->remove("changeSuccessful");
         }
     }
     $this->view->problems = Problems::find();
 }