/** * Displays detail description of given problem * * @param int $assignment_id * @param int $problem_id */ public function index($assignment_id = NULL, $problem_id = 1) { // If no assignment is given, use selected assignment if ($assignment_id === NULL) { $assignment_id = $this->user->selected_assignment['id']; } if ($assignment_id == 0) { show_error('No assignment selected.'); } $assignment = $this->assignment_model->assignment_info($assignment_id); $data = array('all_assignments' => $this->all_assignments, 'all_problems' => $this->assignment_model->all_problems($assignment_id), 'description_assignment' => $assignment, 'can_submit' => TRUE); if (!is_numeric($problem_id) || $problem_id < 1 || $problem_id > $data['description_assignment']['problems']) { show_404(); } $languages = explode(',', $data['all_problems'][$problem_id]['allowed_languages']); $assignments_root = rtrim($this->settings_model->get_setting('assignments_root'), '/'); $problem_dir = "{$assignments_root}/assignment_{$assignment_id}/p{$problem_id}"; $data['problem'] = array('id' => $problem_id, 'description' => '<p>Description not found</p>', 'allowed_languages' => $languages, 'has_pdf' => glob("{$problem_dir}/*.pdf") != FALSE); $path = "{$problem_dir}/desc.html"; if (file_exists($path)) { $data['problem']['description'] = file_get_contents($path); } if ($assignment['id'] == 0 or $this->user->level == 0 && !$assignment['open'] or shj_now() < strtotime($assignment['start_time']) or shj_now() > strtotime($assignment['finish_time']) + $assignment['extra_time'] or !$this->assignment_model->is_participant($assignment['participants'], $this->user->username)) { $data['can_submit'] = FALSE; } $this->twig->display('pages/problems.twig', $data); }
/** * Returns server time (uses time zone in settings table) */ function shj_now_str() { if (!defined('SHJ_NOW_STR')) { define('SHJ_NOW_STR', date("Y-m-d H:i:s", shj_now())); } return SHJ_NOW_STR; }
/** * Compressing and downloading final codes of an assignment to the browser */ public function download_submissions($type = FALSE, $assignment_id = FALSE) { if ($type !== 'by_user' && $type !== 'by_problem') { show_404(); } if ($assignment_id === FALSE || !is_numeric($assignment_id)) { show_404(); } if ($this->user->level == 0) { // permission denied show_404(); } $this->load->model('submit_model'); $items = $this->submit_model->get_final_submissions($assignment_id, $this->user->level, $this->user->username); $this->load->library('zip'); $assignments_root = rtrim($this->settings_model->get_setting('assignments_root'), '/'); foreach ($items as $item) { $file_path = $assignments_root . "/assignment_{$item['assignment']}/p{$item['problem']}/{$item['username']}/{$item['file_name']}." . filetype_to_extension($item['file_type']); if (!file_exists($file_path)) { continue; } $file = file_get_contents($file_path); if ($type === 'by_user') { $this->zip->add_data("{$item['username']}/p{$item['problem']}." . filetype_to_extension($item['file_type']), $file); } elseif ($type === 'by_problem') { $this->zip->add_data("problem_{$item['problem']}/{$item['username']}." . filetype_to_extension($item['file_type']), $file); } } $this->zip->download("assignment{$assignment_id}_submissions_{$type}_" . date('Y-m-d_H-i', shj_now()) . '.zip'); }
public function mcqproblems($assignment_id = NULL) { // If no assignment is given, use selected assignment if ($assignment_id === NULL) { $assignment_id = $this->user->selected_assignment['id']; } if ($assignment_id == 0) { show_error('No assignment selected.'); } $assignment = $this->assignment_model->assignment_time($assignment_id); //if assignment not started the donot show any data of the assignment if ($this->user->level == 0 && shj_now() < strtotime($assignment['start_time'])) { $this->twig->display('pages/notstarted.twig', array('all_assignments' => $this->all_assignments)); return; } $assignments_root = rtrim($this->settings_model->get_setting('assignments_root'), '/'); $filename = "{$assignments_root}/assignment_{$assignment_id}/mcq/mcq_without_answer.json"; if (!file_exists($filename)) { show_404(); } $data = array('all_assignments' => $this->assignment_model->all_assignments(), 'assignment' => $assignment_id); $this->twig->display("pages/mcqquestion.twig", $data); }
/** * Saves submitted code and adds it to queue for judging */ private function _upload() { $now = shj_now(); foreach ($this->problems as $item) { if ($item['id'] == $this->input->post('problem')) { $this->problem = $item; break; } } $this->filetype = $this->_language_to_type(strtolower(trim($this->input->post('language')))); $this->ext = substr(strrchr($_FILES['userfile']['name'], '.'), 1); // uploaded file extension $this->file_name = basename($_FILES['userfile']['name'], ".{$this->ext}"); // uploaded file name without extension if ($this->queue_model->in_queue($this->user->username, $this->problem['id'])) { show_error('You have already submitted for this problem. Your last submission is still in queue.'); } if ($this->user->level == 0 && !$this->problem['open']) { show_error('Selected problem has been closed.'); } $filetypes = explode(",", $this->problem['allowed_languages']); foreach ($filetypes as &$filetype) { $filetype = $this->_language_to_type(strtolower(trim($filetype))); } if ($_FILES['userfile']['error'] == 4) { show_error('No file chosen.'); } if (!in_array($this->filetype, $filetypes)) { show_error('This file type is not allowed for this problem.'); } if (!$this->_match($this->filetype, $this->ext)) { show_error('This file type does not match your selected language.'); } if (!preg_match('/^[a-zA-Z0-9_\\-()]+$/', $this->file_name)) { show_error('Invalid characters in file name.'); } $user_dir = rtrim($this->problem_root, '/') . '/p' . $this->problem['id'] . '/user/'; if (!file_exists($user_dir)) { mkdir($user_dir, 0700); } $user_dir = rtrim($this->problem_root, '/') . '/p' . $this->problem['id'] . '/user/' . $this->user->username; if (!file_exists($user_dir)) { mkdir($user_dir, 0700); } $config['upload_path'] = $user_dir; $config['allowed_types'] = '*'; $config['max_size'] = $this->settings_model->get_setting('file_size_limit'); $config['file_name'] = $this->file_name . "-" . ($this->problem['total_submits'] + 1) . "." . $this->ext; $config['max_file_name'] = 20; $config['remove_spaces'] = TRUE; $this->upload->initialize($config); if ($this->upload->do_upload('userfile')) { $result = $this->upload->data(); $this->load->model('submit_model'); $submit_info = array('submit_id' => $this->problem_model->increase_total_submits($this->problem['id']), 'username' => $this->user->username, 'problem' => $this->problem['id'], 'file_name' => $result['raw_name'], 'main_file_name' => $this->file_name, 'file_type' => $this->filetype, 'pre_score' => 0, 'time' => shj_now_str()); $this->probleminfo_model->update_last_submissions($this->problem['id'], $submit_info['time']); $this->probleminfo_model->update_total_submissions($problem_id, 1); if ($this->problem['is_upload_only'] == 0) { $this->queue_model->add_to_queue($submit_info); process_the_queue(); } else { $this->submit_model->add_upload_only($submit_info); } return TRUE; } return FALSE; }
/** * Used by ajax request (for selecting final submission) */ public function select() { if (!$this->input->is_ajax_request()) { show_404(); } // Students cannot change their final submission after finish_time + extra_time if ($this->user->level === 0) { if (shj_now() > strtotime($this->user->selected_assignment['finish_time']) + $this->user->selected_assignment['extra_time']) { $json_result = array('done' => 0, 'message' => 'This assignment is finished. You cannot change your final submissions.'); $this->output->set_header('Content-Type: application/json; charset=utf-8'); echo json_encode($json_result); return; } } $this->form_validation->set_rules('submit_id', 'Submit ID', 'integer|greater_than[0]'); $this->form_validation->set_rules('problem', 'problem', 'integer|greater_than[0]'); $this->form_validation->set_rules('username', 'Username', 'required|min_length[3]|max_length[20]|alpha_numeric'); if ($this->form_validation->run()) { $username = $this->input->post('username'); if ($this->user->level === 0) { $username = $this->user->username; } $res = $this->submit_model->set_final_submission($username, $this->user->selected_assignment['id'], $this->input->post('problem'), $this->input->post('submit_id')); if ($res) { // each time a user changes final submission, we should update scoreboard of that assignment $this->load->model('scoreboard_model'); $this->scoreboard_model->update_scoreboard($this->user->selected_assignment['id']); $json_result = array('done' => 1); } else { $json_result = array('done' => 0, 'message' => 'Selecting Final Submission Failed'); } } else { $json_result = array('done' => 0, 'message' => 'Input Error'); } $this->output->set_header('Content-Type: application/json; charset=utf-8'); echo json_encode($json_result); }
/** * Saves submitted code and adds it to queue for judging */ private function _upload() { $now = shj_now(); foreach ($this->problems as $item) { if ($item['id'] == $this->input->post('problem')) { $this->problem = $item; break; } } $this->filetype = $this->_language_to_type(strtolower(trim($this->input->post('language')))); $submitcode = $this->input->post("submitcode"); $this->ext = substr(strrchr($_FILES['userfile']['name'], '.'), 1); // uploaded file extension $this->file_name = basename($_FILES['userfile']['name'], ".{$this->ext}"); // uploaded file name without extension if ($this->queue_model->in_queue($this->user->username, $this->user->selected_assignment['id'], $this->problem['id'])) { show_error('You have already submitted for this problem. Your last submission is still in queue.'); } if ($this->user->level == 0 && !$this->user->selected_assignment['open']) { show_error('Selected assignment has been closed.'); } if ($now < strtotime($this->user->selected_assignment['start_time'])) { show_error('Selected assignment has not started.'); } if ($now > strtotime($this->user->selected_assignment['finish_time']) + $this->user->selected_assignment['extra_time']) { show_error('Selected assignment has finished.'); } if (!$this->assignment_model->is_participant($this->user->selected_assignment['participants'], $this->user->username)) { show_error('You are not registered for submitting.'); } $filetypes = explode(",", $this->problem['allowed_languages']); foreach ($filetypes as &$filetype) { $filetype = $this->_language_to_type(strtolower(trim($filetype))); } $user_dir = rtrim($this->assignment_root, '/') . '/assignment_' . $this->user->selected_assignment['id'] . '/p' . $this->problem['id'] . '/' . $this->user->username; if (!file_exists($user_dir)) { mkdir($user_dir, 0700); } $done = false; if ($submitcode == "" || $this->filetype == 'zip' || $this->filetype == 'pdf') { if ($_FILES['userfile']['error'] == 4) { show_error('No file chosen.'); } if (!in_array($this->filetype, $filetypes)) { show_error('This file type is not allowed for this problem.'); } if (!$this->_match($this->filetype, $this->ext)) { show_error('This file type does not match your selected language.'); } if (!preg_match('/^[a-zA-Z0-9_\\-()]+$/', $this->file_name)) { show_error('Invalid characters in file name.'); } $config['upload_path'] = $user_dir; $config['allowed_types'] = '*'; $config['max_size'] = $this->settings_model->get_setting('file_size_limit'); $config['file_name'] = $this->file_name . "-" . ($this->user->selected_assignment['total_submits'] + 1) . "." . $this->ext; $config['max_file_name'] = 20; $config['remove_spaces'] = TRUE; $this->upload->initialize($config); if ($this->upload->do_upload('userfile')) { $result = $this->upload->data(); $done = true; } } else { $this->load->helper('file'); $this->ext = $this->_retext($this->filetype); $this->file_name = "code"; $file_name = "code-" . ($this->user->selected_assignment['total_submits'] + 1) . "." . $this->ext; $upload_path = $user_dir; $max_size = $this->settings_model->get_setting('file_size_limit'); $fp = fopen($upload_path . "/" . $file_name, 'w'); //show_error($max_size); $wr = fwrite($fp, $submitcode, $max_size * 1024); if (!$wr) { show_error("Code is too large"); } fclose($fp); $result['raw_name'] = "code-" . ($this->user->selected_assignment['total_submits'] + 1); $done = true; } if ($done) { $this->load->model('submit_model'); $submit_info = array('submit_id' => $this->assignment_model->increase_total_submits($this->user->selected_assignment['id']), 'username' => $this->user->username, 'assignment' => $this->user->selected_assignment['id'], 'problem' => $this->problem['id'], 'file_name' => $result['raw_name'], 'main_file_name' => $this->file_name, 'file_type' => $this->filetype, 'coefficient' => $this->coefficient, 'pre_score' => 0, 'time' => shj_now_str()); if ($this->problem['is_upload_only'] == 0) { $this->queue_model->add_to_queue($submit_info); process_the_queue(); } else { $this->submit_model->add_upload_only($submit_info); } $val = $submit_info; return $val; } return FALSE; }
private function _judge_mcq($assignment_id) { $res = $this->assignment_model->assignment_time($assignment_id); if (shj_now() < strtotime($res['finish_time']) + $res['extra_time']) { //assignment not yet finished return FALSE; } else { return TRUE; } }
public function images($assignment_id = NULL, $imagename = NULL) { $assignments_root = rtrim($this->settings_model->get_setting('assignments_root'), '/'); $filename = "{$assignments_root}/assignment_{$assignment_id}/images/{$imagename}"; $assignment = $this->assignment_model->assignment_info($assignment_id); if ($this->user->level == 0 && shj_now() < strtotime($assignment['start_time'])) { show_404(); } if (file_exists($filename)) { header('Content-Length: ' . filesize($filename)); //<-- sends filesize header $mime = $this->_getmime(pathinfo($filename, PATHINFO_EXTENSION)); header("Content-Type: {$mime}"); //<-- send mime-type header header('Content-Disposition: inline; filename="' . $filename . '";'); //<-- sends filename header readfile($filename); //<--reads and outputs the file onto the output buffer die; //<--cleanup exit; //and exit } else { show_404(); } }
/** * The function is polled for new updates aboud the assignment. * @return boolean [description] */ public function is_update() { if (!$this->input->is_ajax_request()) { show_404(); } $assignment_id = $this->input->post('assignment'); if ($assignment_id == 0) { show_404(); } $assignments_root = rtrim($this->settings_model->get_setting('assignments_root'), '/'); $assignment_info = $this->assignment_model->assignment_time($assignment_id); if (shj_now() > strtotime($assignment_info['finish_time']) + $assignment_info['extra_time']) { exit("Assignment Finished"); } $filename = "{$assignments_root}/assignment_{$assignment_id}/mcq/mcq_without_answer.json"; exit(date("Y m d H:i:s", filemtime($filename))); }
public function is_public($assignment_id) { $assignment = $this->assignment_time($assignment_id); return $assignment['public'] && shj_now() > strtotime($assignment['finish_time']) + $assignment['extra_time']; }
/** * Password Reset Key Is Valid * * Returns TRUE if the given password reset key is valid * And returns an error message if key is invalid * * @param $passchange_key * @return bool|string */ public function passchange_is_valid($passchange_key) { $query = $this->db->select('passchange_time')->get_where('users', array('passchange_key' => $passchange_key)); if ($query->num_rows() != 1) { return 'Invalid password reset link.'; } $time = strtotime($query->row()->passchange_time); $now = shj_now(); if ($now - $time > 3600 or $now - $time < 0) { // reset link is valid for 1 hour return 'The link is expired.'; } return TRUE; }