function processAdjustUserDataRequest($request) { $prfx = DB_PREFIX; $user_row = RequestUtils::testSession($request->sessionID); $adjust_user_id = $request->userID; $adjust_user_row = Data::getRow(sprintf("SELECT * FROM {$prfx}user WHERE id=%s", Data::quote_smart($adjust_user_id))); if (!$adjust_user_row) { throwBusinessLogicError(2); } if ($user_row['user_type'] === 'Participant') { throwBusinessLogicError(0); } if ($user_row['user_type'] === 'ContestAdmin' && $user_row['contest_id'] != $adjust_user_row['contest_id']) { throwBusinessLogicError(0); } $queries = array(); if (!is_null($request->login)) { $queries['login'] = $request->login; } if (!is_null($request->password)) { $queries['password'] = $request->password; } if (!is_null($request->userData)) { $queries['user_data'] = @serialize($request->userData); } if (!is_null($request->newType)) { $queries['user_type'] = $request->newType; } $q = Data::composeUpdateQuery("user", $queries, sprintf("id=%s", Data::quote_smart($adjust_user_id))); Data::submitModificationQuery($q); return new AcceptedResponse(); }
function processCreateDataBaseRequest($request) { //test if creation is necessary if (in_array(DB_PREFIX . "user", Data::getTables())) { throwBusinessLogicError(13); } //read queries from file $lines = @file_get_contents("utils/dces-create-db.sql") or throwServerProblem(64); //remove # comments $lines = preg_replace("/^\\s*#.*\$/m", "", $lines); //remove /*! ... */ comments $lines = preg_replace('/\\/\\*!\\d+.*\\*\\//', "", $lines); //replace PREFIX_ with real prefix $lines = preg_replace('/PREFIX_/', DB_PREFIX, $lines); //split requests by ; $requests = preg_split('/\\s*;\\s*$/m', $lines); foreach ($requests as $r) { if (trim($r) !== "") { Data::submitModificationQuery($r); } } $col_value = array('login' => $request->login, 'password' => $request->password, 'user_data' => serialize(array()), 'contest_id' => 0, 'user_type' => 'SuperAdmin'); Data::submitModificationQuery(Data::composeInsertQuery('user', $col_value)); return new AcceptedResponse(); }
function processRemoveContestRequest($request) { $prfx = DB_PREFIX; $user_row = RequestUtils::testSession($request->sessionID); $contest_id = $request->contestID; //simple security check if (!is_numeric($contest_id)) { throwBusinessLogicError(14); } if ($user_row['user_type'] !== 'SuperAdmin') { throwBusinessLogicError(0); } else { if ($contest_id === 0) { throwBusinessLogicError(16); } } //get all users of the contest $contest_user_rows = Data::getRows("SELECT id FROM {$prfx}user WHERE contest_id={$contest_id}"); //compose where clause for delete query $where_user_id = ""; while (list($user_id) = Data::getNextRow($contest_user_rows)) { $where_user_id .= 'user_id=' . $user_id . 'OR'; } $where_user_id .= '0=1'; Data::submitModificationQuery("DELETE FROM {$prfx}contest WHERE id={$contest_id}"); Data::submitModificationQuery("DELETE FROM {$prfx}problem WHERE contest_id={$contest_id}"); Data::submitModificationQuery("DELETE FROM {$prfx}problem_status WHERE {$where_user_id}"); Data::submitModificationQuery("DELETE FROM {$prfx}session WHERE {$where_user_id}"); Data::submitModificationQuery("DELETE FROM {$prfx}submission_history WHERE {$where_user_id}"); Data::submitModificationQuery("DELETE FROM {$prfx}user WHERE contest_id={$contest_id}"); return new AcceptedResponse(); }
function processDisconnectRequest($request) { $prfx = DB_PREFIX; $where = sprintf("WHERE session_id = %s", Data::quote_smart($request->sessionID)); //TODO think how to implement this more efficient in our architecture if (!Data::getRow("SELECT * FROM {$prfx}session {$where}")) { throwBusinessLogicError(3); } Data::submitModificationQuery("DELETE FROM {$prfx}session {$where}"); return new AcceptedResponse(); }
function processAdjustPluginRequest($request) { $prfx = DB_PREFIX; $user_row = RequestUtils::testSession($request->sessionID); //authorize if ($user_row['user_type'] !== 'SuperAdmin') { throwBusinessLogicError(0); } //test plugin alias if (preg_match('/^[\\p{L}0-9 ]+$/', $request->pluginAlias) === 0) { throwBusinessLogicError(238); } $plugin_type = $request->side === 'Client' ? 'client' : 'server'; //test if there already is such plugin $where_clause = sprintf("alias=%s", Data::quote_smart($request->pluginAlias)); $plugin_row = Data::getRow("SELECT * FROM {$prfx}{$plugin_type}_plugin WHERE {$where_clause}"); if ($plugin_row) { $modify = true; } else { $modify = false; } //test all parameters specified if (!$modify && is_null($request->description)) { $request->description = ""; } if (!$modify && (is_null($request->pluginData) || is_null($request->description))) { throwBusinessLogicError(1); } //TODO test pluginAlias to be secure if ($plugin_type === 'client') { $ext = '.jar'; } else { $ext = '.php'; } //set file data if (!is_null($request->pluginData)) { file_put_contents($GLOBALS["dces_dir_{$plugin_type}_plugins"] . '/' . $request->pluginAlias . $ext, $request->pluginData); } //prepare set plugin description $col_value = array(); if (!is_null($request->description)) { $col_value['description'] = $request->description; } if ($modify) { $query = Data::composeUpdateQuery("{$plugin_type}_plugin", $col_value, $where_clause); } else { $col_value['alias'] = $request->pluginAlias; $query = Data::composeInsertQuery("{$plugin_type}_plugin", $col_value); } Data::submitModificationQuery($query); return new AcceptedResponse(); }
function processConnectToContestRequest($request) { $prfx = DB_PREFIX; //find user in table $row = Data::getRow(sprintf("SELECT {$prfx}user.*, {$prfx}contest.settings\r\n FROM {$prfx}user\r\n LEFT JOIN {$prfx}contest\r\n ON {$prfx}user.contest_id = {$prfx}contest.id\r\n WHERE login=%s AND contest_id=%s", Data::quote_smart($request->login), Data::quote_smart($request->contestID))); //test if there is at least one user if (!$row) { throwBusinessLogicError(12); } //test password if ($row['password'] !== $request->password) { throwBusinessLogicError(12); } //get contest settings and contest time $settings = Data::_unserialize($row['settings'], null); if (is_null($row['contest_start'])) { $now = getdate(); $now = $now[0]; $q = Data::composeUpdateQuery('user', array('contest_start' => DatePHPToMySQL($now)), "id={$row['id']}"); Data::submitModificationQuery($q); $row['contest_start'] = $now; } $contest_time = getCurrentContestTime($settings, DateMySQLToPHP($row['contest_start']), DateMySQLToPHP($row['contest_finish'])); if ($contest_time['interval'] === 'before' && $row['user_type'] === 'Participant') { throwBusinessLogicError(19); } //start new session $session_id = RequestUtils::createSession($row['id']); //get finish time if (is_null($settings)) { $finish_time = 0; } elseif ($settings->contestTiming->selfContestStart) { $finish_time = $row['contest_start'] + 60 * $settings->contestTiming->maxContestDuration; } else { $finish_time = $settings->finish; } if (is_null($finish_time)) { $finish_time = 0; } $res = new ConnectToContestResponse(); $res->sessionID = $session_id; $res->finishTime = $finish_time; $res->user = new UserDescription(); $res->user->userID = (int) $row['id']; $res->user->login = $request->login; $res->user->dataValue = Data::_unserialize($row['user_data'], array()); $res->user->userType = $row['user_type']; return $res; }
public static function createSession($user_id) { //returns session string $prfx = DB_PREFIX; //test if session for user_id is already set $open_session_rows = Data::getRow("SELECT * FROM {$prfx}session WHERE user_id={$user_id}"); $session_id = RequestUtils::random_str(24); if (!$open_session_rows) { //session for the user is NOT YET created Data::submitModificationQuery("INSERT INTO {$prfx}session (session_id, user_id) VALUES ('{$session_id}', {$user_id})"); } else { //session for the user is ALREADY created Data::submitModificationQuery("UPDATE {$prfx}session SET session_id='{$session_id}' WHERE user_id={$user_id}"); } return $session_id; }
/** * Created by IntelliJ IDEA. * User: Ilya * Date: 17.04.2009 * Time: 15:57:17 * To change this template use File | Settings | File Templates. */ function processKillDBRequest($request) { //Uncomment to check permissions /* $user_row = RequestUtils::testSession($request->sessionID); if ($user_row['user_type'] !== 'SuperAdmin') throwBusinessLogicError(0); */ $tables = array('client_plugin', 'contest', 'problem', 'problem_status', 'server_plugin', 'session', 'submission_history', 'user'); $prfx = DB_PREFIX; foreach ($tables as $t) { Data::submitModificationQuery("DROP TABLE {$prfx}" . $t); } return new AcceptedResponse(); }
function processCreateContestRequest($request) { //get user_id or die, if session is invalid $user_row = RequestUtils::testSession($request->sessionID); //authorize user for this operation $user_type = $user_row['user_type']; if ($user_type !== 'SuperAdmin') { throwBusinessLogicError(0); } unset($request->contest->contestID); RequestUtils::assertContestSettingsIntegrity($request->contest); $col_value = array('settings' => serialize($request->contest)); Data::submitModificationQuery(Data::composeInsertQuery('contest', $col_value)); Data::execPendingQueries(); $id = Data::getInsertedID(); $ccr = new CreateContestResponse(); $ccr->createdContestID = $id; return $ccr; }
function processRemovePluginRequest($request) { $prfx = DB_PREFIX; $user_row = RequestUtils::testSession($request->sessionID); //authorize if ($user_row['user_type'] !== 'SuperAdmin') { throwBusinessLogicError(0); } //test plugin alias if (preg_match('/^[\\p{L}0-9 ]+$/', $request->pluginAlias) === 0) { throwBusinessLogicError(238); } $plugin_type = $request->side === 'Client' ? 'client' : 'server'; $plugin_ext = $request->side === 'Client' ? '.jar' : '.php'; //remove from db Data::submitModificationQuery(sprintf("DELETE FROM {$prfx}{$plugin_type}_plugin WHERE alias=%s", Data::quote_smart($request->pluginAlias))); //remove from disk //TODO don't remove files outside the client plugins folder unlink("{$plugin_type}_plugins/" . $request->pluginAlias . $plugin_ext); return new AcceptedResponse(); }
/** * Created by IntelliJ IDEA. * User: Посетитель * Date: 17.04.2009 * Time: 15:57:17 * To change this template use File | Settings | File Templates. */ function processStopContestRequest($request) { $user_row = RequestUtils::testSession($request->sessionID); $requested_contest_id = $user_row['contest_id']; if ($requested_contest_id <= 0) { throwBusinessLogicError(0); } $settings = Data::_unserialize($user_row['settings']); if (!$settings->contestTiming->selfContestStart) { throwBusinessLogicError(0); } $time = getCurrentContestTime($settings, DateMySQLToPHP($user_row['contest_start']), DateMySQLToPHP($user_row['contest_finish'])); if ($time['interval'] === 'before') { throwBusinessLogicError(19); } if ($time['interval'] === 'after') { throwBusinessLogicError(20); } $now = getdate(); $now = $now[0]; Data::submitModificationQuery(Data::composeUpdateQuery('user', array('contest_finish' => DatePHPToMySQL($now)), "id={$user_row['id']}")); }
function processRemoveUserRequest($request) { $prfx = DB_PREFIX; $user_row = RequestUtils::testSession($request->sessionID); $remove_user_id = $request->userID; $remove_user_row = Data::getRow(sprintf("SELECT *\r\n FROM {$prfx}user\r\n WHERE id=%s", Data::quote_smart($remove_user_id))); if (!$remove_user_row) { throwBusinessLogicError(2); } if ($user_row['user_type'] === 'Participant') { throwBusinessLogicError(0); } if ($user_row['user_type'] === 'ContestAdmin' && $user_row['contest_id'] != $remove_user_row['contest_id']) { throwBusinessLogicError(0); } //remove user $remove_user_id $prfx = DB_PREFIX; //from 'users' table Data::submitModificationQuery(sprintf("DELETE FROM {$prfx}user WHERE id=%s", Data::quote_smart($remove_user_id))); Data::submitModificationQuery(sprintf("DELETE FROM {$prfx}session WHERE user_id=%s", Data::quote_smart($remove_user_id))); Data::submitModificationQuery(sprintf("DELETE FROM {$prfx}submission_history WHERE user_id=%s", Data::quote_smart($remove_user_id))); Data::submitModificationQuery(sprintf("DELETE FROM {$prfx}problem_status WHERE user_id=%s", Data::quote_smart($remove_user_id))); return new AcceptedResponse(); }
function processSubmitSolutionRequest($request) { $prfx = DB_PREFIX; //get user_id or die, if session is invalid $userRow = RequestUtils::testSession($request->sessionID); $user_id = $userRow['id']; //authorize user for this operation // get contest ID $user_type = $userRow['user_type']; //get problem row $problem_row = Data::getRow(sprintf("SELECT * FROM {$prfx}problem WHERE id=%s", Data::quote_smart($request->problemID))); if (!$problem_row) { throwBusinessLogicError(4); } //get contest id of a problem $problem_contest_id = $problem_row['contest_id']; //test if we have rights to submit solution for the contest $contest_id = RequestUtils::getRequestedContest($problem_contest_id, $userRow['contest_id'], $user_type); if ($contest_id < 0) { throwBusinessLogicError(0); } //get all settings $contest_settings = Data::_unserialize($userRow['settings']); //test submission time $cur_time = getCurrentContestTime($contest_settings, DateMySQLToPHP($userRow['contest_start']), DateMySQLToPHP($userRow['contest_finish'])); if ($cur_time['interval'] === 'before') { throwBusinessLogicError(19); } if ($cur_time['interval'] === 'after') { throwBusinessLogicError(20); } $problem_settings = Data::_unserialize($problem_row['contest_settings']); //test that not all submission attempts were used $hist = Data::getRow(sprintf("SELECT COUNT(*) AS cnt FROM {$prfx}submission_history WHERE (problem_id=%s) AND (user_id=%s)", Data::quote_smart($request->problemID), Data::quote_smart($user_id))); if ($hist >= getSetting($contest_settings->problemsDefaultSettings->sendCount, $problem_settings->sendCount)) { throwBusinessLogicError(21); } //save submission result in history $cur_php_time = getdate(); $col_value = array(); $col_value['problem_id'] = $request->problemID; $col_value['user_id'] = $user_id; $col_value['submission'] = serialize($request->problemResult); $col_value['result'] = null; //serialize($check_result); $col_value['submission_time'] = DatePHPToMySQL($cur_php_time[0]); //TODO implement asynchronous plugin //get problem and create plugin $problem = new Problem(getProblemFile($request->problemID)); $plugin_alias = $problem->getServerPlugin(); require_once getServerPluginFile(); require_once getServerPluginFile($plugin_alias); $plugin = new $plugin_alias($problem); //check solution $last_result = $plugin->checkSolution(Data::getInsertedID(), $request->problemResult); $col_value['result'] = serialize($last_result); Data::submitModificationQuery(Data::composeInsertQuery('submission_history', $col_value)); //get result for result table and store in user $all_results = Data::_unserialize($userRow['results']); $user_result = ResultUtils::getUserResults($user_id, $request->problemID, getSetting($contest_settings->problemsDefaultSettings->tableResultChoice, $problem_settings->tableResultChoice), getSetting($contest_settings->problemsDefaultSettings->resultTransition, $problem_settings->resultTransition), $plugin, $last_result); //update user result for results table $all_results[$request->problemID] = $user_result; Data::submitModificationQuery(Data::composeUpdateQuery('user', array('results' => serialize($all_results)), 'id=' . Data::quote_smart($user_id))); //return submission result $res = new AcceptedResponse(); return $res; }
/** * creates queries to change problem set * @param $problems new problems * @param $contest_id contest id * @return array() list of temporary files. NULL if the existing file was used */ function queriesToAdjustProblems($problems, $contest_id) { $prfx = DB_PREFIX; $changed_probs = array(); //problems that will be changed by request $temp_probs = array(); //find all contest problems $prob2settings = array(); $res = Data::getRows(sprintf("SELECT * FROM {$prfx}problem WHERE contest_id=%s", Data::quote_smart($contest_id))); while ($row = Data::getNextRow($res)) { $prob2settings[$row['id']] = Data::_unserialize($row['contest_settings']); } $contest_pos = 1; foreach ($problems as $p) { $col_value = array(); //new problem must have 1) data 2) settings //set contest id $col_value['contest_id'] = $contest_id; $col_value['contest_pos'] = $contest_pos++; if ($p->id != -1 && !isset($prob2settings[$p->id])) { throwBusinessLogicError(4); } //find problem file or make temporary if a new problem was sent if ($p->problem) { $problem_file = getTemporaryProblemFile(); @file_put_contents($problem_file, $p->problem) or throwServerProblem(200, 'failed to write problem file: ' . $problem_file); $temp_probs[] = $problem_file; } else { if ($p->id < 0) { throwBusinessLogicError(1); } $problem_file = getProblemFile($p->id); $temp_probs[] = NULL; } $problem = new Problem($problem_file); //get server plugin //TODO improve security here $plugin_alias = $problem->getServerPlugin(); require_once getServerPluginFile($plugin_alias); $plugin = new $plugin_alias($problem); //TODO consider calling updaters here instead of manual insertion of values //TODO recheck all values if new plugin specified $col_value['checker_columns'] = serialize($plugin->getColumnNames()); $col_value['result_columns'] = serialize(array()); //copy per contest settings if ($p->settings) { if ($p->id != -1) { $new_settings = $prob2settings[$p->id]; copyValues($p->settings, $new_settings); } else { $new_settings = $p->settings; } $col_value['contest_settings'] = serialize($new_settings); } else { if ($p->id < 0) { throwBusinessLogicError(1); } } //query depends on whether we add or change a problem if ($p->id == -1) { Data::submitModificationQuery(Data::composeInsertQuery('problem', $col_value)); } else { Data::submitModificationQuery(Data::composeUpdateQuery('problem', $col_value, "id='{$p->id}'")); $changed_probs[$p->id] = 1; } } //delete extra problems foreach (array_keys($prob2settings) as $id) { if (!isset($changed_probs[$id])) { Data::submitModificationQuery("DELETE FROM {$prfx}problem WHERE id='{$id}'"); } } return $temp_probs; }
function processRegisterToContestRequest($request) { $prfx = DB_PREFIX; //get user_id or die, if session is invalid if (is_null($request->sessionID)) { if (!is_numeric($request->contestID)) { throwBusinessLogicError(14); } $contest_id = (int) $request->contestID; $request_user_type = '__Anonymous'; } else { $userRow = RequestUtils::testSession($request->sessionID); $request_user_id = $userRow['id']; $request_user_type = $userRow['user_type']; $contest_id = RequestUtils::getRequestedContest($request->contestID, $userRow['contest_id'], $request_user_type); //make possible for superadmin to register users of zero-contest if ($request_user_type == 'SuperAdmin' && ($request->contestID == 0 || $request->contestID == -1)) { $contest_id = 0; } if ($contest_id == -1) { throwBusinessLogicError(0); } } //test permissions if ($contest_id != 0) { $contest_row = Data::getRow(sprintf("SELECT * FROM {$prfx}contest WHERE id=%s", Data::quote_smart($contest_id))) or throwBusinessLogicError(14); //test if this contest gets users only by admins $contest_settings = @unserialize($contest_row['settings']); if ($contest_settings->registrationType === 'ByAdmins') { if ($request_user_type !== "ContestAdmin" && $request_user_type !== "SuperAdmin") { throwBusinessLogicError(0); } } } else { if ($request_user_type !== "ContestAdmin") { throwBusinessLogicError(0); } } //get user from request $u = $request->user; //test that superadmins are registered only for 0 contest if ($u->userType === 'SuperAdmin' && $contest_id != 0) { throwBusinessLogicError(18); } //test that there is no user with the same login in this contest if (Data::hasRows(sprintf("SELECT * FROM {$prfx}user WHERE contest_id=%s AND login=%s", Data::quote_smart($contest_id), Data::quote_smart($u->login)))) { throwBusinessLogicError(14); } //not participants may be added only by admins if ($u->userType !== "Participant") { if ($request_user_type !== "ContestAdmin" && $request_user_type !== "SuperAdmin") { throwBusinessLogicError(0); } } //add user finally $col_value = array(); $col_value['login'] = $u->login; $col_value['password'] = $u->password; $col_value['user_data'] = @serialize($u->dataValue); $col_value['contest_id'] = $contest_id; $col_value['user_type'] = $u->userType; $col_value['results'] = @serialize(array()); if (strlen($u->login) == 0) { throwBusinessLogicError(22); } if (week_password($u->password)) { throwBusinessLogicError(23); } Data::submitModificationQuery(Data::composeInsertQuery('user', $col_value)); return new AcceptedResponse(); }