protected function body() { if (!$this->userHasPrivileges(User::submissionsCorrect)) { return false; } $canViewAuthors = User::instance()->hasPrivileges(User::submissionsViewAuthors); $rated = $this->getParams('rated') ? true : false; $all = $this->getParams('all') ? true : false; $absolutelyAll = $this->getParams('absolutelyAll') ? true : false; $userId = User::instance()->getId(); if ($absolutelyAll) { if (!$this->userHasPrivileges(User::lecturesManageAll, User::groupsManageAll, User::otherAdministration)) { return false; } } /** * @var $submissions \Submission[] */ // group is a DQL reserved word, so we must use _group if ($absolutelyAll) { $submissions = Repositories::makeDqlQuery("SELECT submission, user, assignment, problem, _group FROM \\Submission submission JOIN submission.assignment assignment JOIN assignment.problem problem JOIN submission.user user JOIN assignment.group _group WHERE submission.status <> 'deleted'")->getResult(); } else { $submissions = Repositories::makeDqlQuery("SELECT submission, user, assignment, problem, _group FROM \\Submission submission JOIN submission.assignment assignment JOIN assignment.problem problem JOIN submission.user user JOIN assignment.group _group WHERE _group.owner = :submissionCorrector AND (submission.status = 'graded' OR submission.status = 'latest' OR submission.status = 'handsoff') AND _group.deleted = 0")->setParameter('submissionCorrector', $userId)->getResult(); } foreach ($submissions as $submission) { if (!$all && !$absolutelyAll) { if ($rated && $submission->getStatus() !== \Submission::STATUS_GRADED) { continue; } if (!$rated && $submission->getStatus() === \Submission::STATUS_GRADED) { continue; } } $descriptionForTeacher = $submission->getInfo(); if ($submission->getSimilarityStatus() == \Submission::SIMILARITY_STATUS_GUILTY) { $descriptionForTeacher = Language::get(StringID::ThisSubmissionIsPlagiarism) . "\n======\n" . $descriptionForTeacher; } if ($submission->getSimilarityStatus() == \Submission::SIMILARITY_STATUS_INNOCENT) { $descriptionForTeacher = $descriptionForTeacher . "\n======\n" . Language::get(StringID::ThisSubmissionIsInnocent); } if ($submission->getSimilarityStatus() == \Submission::SIMILARITY_STATUS_NEW) { $descriptionForTeacher = $descriptionForTeacher . "\n======\n" . Language::get(StringID::ThisHasYetToBeCheckedForPlagiarism); } if ($submission->getStatus() == \Submission::STATUS_REQUESTING_GRADING) { $descriptionForTeacher = Language::get(StringID::GradingRequested) . " " . $descriptionForTeacher; } $row = [$submission->getId(), $submission->getAssignment()->getProblem()->getName(), $submission->getAssignment()->getGroup()->getName(), $submission->getDate()->format("Y-m-d H:i:s"), $submission->getSuccess(), $descriptionForTeacher, $submission->getRating(), $submission->getExplanation(), $submission->getAssignment()->getReward(), $submission->getAssignment()->getDeadline()->format("Y-m-d H:i:s"), $canViewAuthors ? $submission->getUser()->getId() : 0, $canViewAuthors ? $submission->getUser()->getRealName() : Language::get(StringID::NotAuthorizedForName), $submission->getOutputfile() != '', $submission->getAssignment()->getId()]; if ($absolutelyAll) { $row[] = $canViewAuthors ? $submission->getUser()->getEmail() : Language::get(StringID::NotAuthorizedForName); $row[] = $submission->getStatus(); } $this->addRowToOutput($row); } return true; }
protected function body() { $plugins = Repositories::getRepository(Repositories::Plugin)->findAll(); $errors = []; foreach ($plugins as $plugin) { /** @var $plugin \Plugin */ $dbPhpFile = $plugin->getMainfile(); $dbDescription = $plugin->getDescription(); $dbIdentifier = $plugin->getIdentifier(); $pluginDirectory = $this->getMainDirectory($dbPhpFile); if ($pluginDirectory === false) { $errors[] = $plugin->getName() . ": " . Language::get(StringID::ReloadManifests_InvalidFolder); continue; } $manifestFile = Filesystem::combinePaths(Config::get('paths', 'plugins'), $pluginDirectory, "manifest.xml"); $xml = new \DOMDocument(); $success = $xml->load(realpath($manifestFile)); if ($success === false) { $errors[] = $plugin->getName() . ": " . Language::get(StringID::ReloadManifests_MalformedXmlOrFileMissing); continue; } $fileDescription = $xml->getElementsByTagName('description')->item(0); $fileArguments = $xml->getElementsByTagName('argument'); $fileIdentifier = $xml->getElementsByTagName('identifier')->item(0); $fileArgumentsArray = []; for ($i = 0; $i < $fileArguments->length; $i++) { $fileArgumentsArray[] = trim($fileArguments->item($i)->nodeValue); } $fileArgumentsString = implode(';', $fileArgumentsArray); if ($dbDescription !== trim($fileDescription->nodeValue)) { $errors[] = $plugin->getName() . ": " . Language::get(StringID::ReloadManifests_DescriptionMismatch); $plugin->setDescription(trim($fileDescription->nodeValue)); Repositories::persist($plugin); } if ($dbIdentifier !== trim($fileIdentifier->nodeValue)) { $errors[] = $plugin->getName() . ": " . Language::get(StringID::ReloadManifests_IdentifierMismatch); $plugin->setIdentifier(trim($fileIdentifier->nodeValue)); Repositories::persist($plugin); } if ($plugin->getConfig() !== $fileArgumentsString) { $errors[] = $plugin->getName() . ": " . Language::get(StringID::ReloadManifests_ArgumentsMismatch); $plugin->setConfig($fileArgumentsString); Repositories::persist($plugin); } } Repositories::flushAll(); if (count($errors) === 0) { $this->addOutput("text", Language::get(StringID::ReloadManifests_DatabaseCorrespondsToManifests)); } else { $this->addOutput("text", implode('<br>', $errors)); } return true; }
protected function body() { if (!$this->isInputSet(array('name', 'pass'))) { return false; } $user = User::instance(); if (!$user->login($this->getParams('name'), $this->getParams('pass'))) { return $this->stop(Language::get(StringID::InvalidLogin)); } $this->setOutput(array('id' => $user->getId(), 'username' => $user->getName(), 'name' => $user->getRealName(), 'email' => $user->getEmail(), 'lastLogin' => $user->getLastAccess(), 'privileges' => $user->unpackPrivileges(), 'timeout' => $user->getTimeout(), User::sendEmailOnSubmissionRatedStudent => $user->getData(User::sendEmailOnSubmissionRatedStudent), User::sendEmailOnSubmissionConfirmedTutor => $user->getData(User::sendEmailOnSubmissionConfirmedTutor), User::sendEmailOnAssignmentAvailableStudent => $user->getData(User::sendEmailOnAssignmentAvailableStudent))); return true; }
protected function body() { if (!$this->userHasPrivileges()) { return; } $query = "SELECT a, p, l, z, g FROM Assignment a JOIN a.problem p LEFT JOIN p.plugin z JOIN p.lecture l JOIN a.group g WITH g.id IN (SELECT IDENTITY(k.group) FROM \\Subscription k WHERE k.user = :id AND a.deleted = false)"; /** * @var $assignments \Assignment[] */ $userId = User::instance()->getId(); $assignments = Repositories::getEntityManager()->createQuery($query)->setParameter('id', $userId)->getResult(); foreach ($assignments as $assignment) { $submissionGraded = count(Repositories::getRepository(Repositories::Submission)->findBy(['assignment' => $assignment->getId(), 'user' => $userId, 'status' => \Submission::STATUS_GRADED])) > 0; $submissionExists = count(Repositories::getRepository(Repositories::Submission)->findBy(['assignment' => $assignment->getId(), 'user' => $userId])) > 0; $row = [$assignment->getId(), $assignment->getProblem()->getName(), $assignment->getProblem()->getDescription(), $assignment->getProblem()->getPlugin() ? $assignment->getProblem()->getPlugin()->getDescription() : Language::get(StringID::NoPluginUsed), $assignment->getDeadline()->format("Y-m-d H:i:s"), $assignment->getReward(), $assignment->getProblem()->getLecture()->getName(), $assignment->getProblem()->getLecture()->getDescription(), $assignment->getGroup()->getName(), $assignment->getGroup()->getDescription(), $submissionExists, $submissionGraded]; $this->addRowToOutput($row); } }
protected function body() { if (!$this->userHasPrivileges(User::otherAdministration, User::groupsManageAll, User::lecturesManageAll)) { return false; } $newId = $this->getParams('newId'); if (!$newId) { return true; } $canViewAuthors = User::instance()->hasPrivileges(User::submissionsViewAuthors); /** @var \Similarity[] $similarities */ $similarities = Repositories::getRepository(Repositories::Similarity)->findBy(['newSubmission' => $newId]); foreach ($similarities as $similarity) { $row = [$similarity->getId(), $similarity->getOldSubmission()->getId(), $similarity->getSuspicious() ? "yes" : false, $similarity->getScore(), $similarity->getDetails(), $canViewAuthors ? $similarity->getOldSubmission()->getUser()->getRealName() : Language::get(StringID::NotAuthorizedForName), $similarity->getOldSubmission()->getDate()->format("Y-m-d H:i:s"), $similarity->getOldSubmission()->getStatus()]; $this->addRowToOutput($row); } return true; }
<?php use asm\core\Config, asm\core\Core, asm\utils\ErrorHandler, asm\core\UiResponse, asm\core\Error; /** * @file * Handles core requests coming from UI. * * 1. Starts session. * 2. Starts the Composer autoloader. * 3. Loads configuration from the config.ini and internal.ini files. * 4. Activates the custom error handler. * 5. Calls Core::handleUiRequest with data from user. */ // Session is used to keep track of logged in user, and is used for file uploads. session_start(); // Load up the Composer-generated autoloader. All PHP classes are loaded using this autoloader. require_once __DIR__ . "/../vendor/autoload.php"; // Load configuration from the "config.ini" file. Config::init(__DIR__ . '/config.ini', __DIR__ . '/internal.ini'); // If ever an exception occurs or a PHP error occurs, log it and send it to the user. ErrorHandler::register(); ErrorHandler::bind(['asm\\core\\Core', 'logException']); ErrorHandler::bind(function (Exception $e) { Core::sendUiResponse(UiResponse::create([], [Error::create(Error::levelFatal, $e->getMessage() . "[details: code " . $e->getCode() . ", file " . $e->getFile() . ", line " . $e->getLine() . ", trace: \n" . $e->getTraceAsString() . "]", \asm\core\lang\Language::get(\asm\core\lang\StringID::ServerSideRuntimeError))])); }); // Process the AJAX request. // Usually, the Javascript part of XML Check sends a POST request but in some special cases, a GET request is needed. Core::handleUiRequest(empty($_POST) ? $_GET : $_POST, $_FILES);
protected function body() { // Validate input. $inputs = array('group' => 'isIndex', 'problem' => 'isIndex', 'deadline' => 'isDate', 'reward' => 'isNonNegativeInt'); if (!$this->isInputValid($inputs)) { return false; } // Load input $id = $this->getParams('id'); $group = $this->getParams('group'); $problem = $this->getParams('problem'); $deadline = $this->getParams('deadline'); $reward = $this->getParams('reward'); // Adjust input $deadline = $deadline . ' 23:59:59'; // Load from database /** * @var $groupEntity \Group * @var $assignmentEntity \Assignment * @var $problemEntity \Problem */ $groupEntity = Repositories::getEntityManager()->find('Group', $group); $problemEntity = Repositories::getEntityManager()->find('Problem', $problem); if ($groupEntity === null || $problemEntity === null) { return $this->stop('Group or problem does not exist.', 'Assignment cannot be edited.'); } // Authenticate $user = User::instance(); if (!$user->hasPrivileges(User::groupsManageAll) && (!$user->hasPrivileges(User::groupsManageOwn) || $groupEntity->getOwner()->getId() !== $user->getId())) { return $this->stop(Language::get(StringID::InsufficientPrivileges)); } // Already exists? if ($id !== null && $id !== '') { $assignmentEntity = Repositories::getEntityManager()->find('Assignment', $id); $assignmentEntity->setDeadline(\DateTime::createFromFormat("Y-m-d H:i:s", $deadline)); $assignmentEntity->setReward($reward); Repositories::getEntityManager()->persist($assignmentEntity); Repositories::getEntityManager()->flush($assignmentEntity); } else { // Verify integrity if ($problemEntity->getLecture()->getId() !== $groupEntity->getLecture()->getId()) { return $this->stop('You are adding an assignment for problem belonging to lecture X to a group that belongs to lecture Y. This is not possible.'); } // Create new $assignmentEntity = new \Assignment(); $assignmentEntity->setGroup($groupEntity); $assignmentEntity->setProblem($problemEntity); $assignmentEntity->setDeadline(\DateTime::createFromFormat("Y-m-d H:i:s", $deadline)); $assignmentEntity->setReward($reward); Repositories::getEntityManager()->persist($assignmentEntity); Repositories::getEntityManager()->flush($assignmentEntity); // Send e-mail /** * @var $subscription \Subscription */ $query = Repositories::getEntityManager()->createQuery('SELECT s, u FROM Subscription s JOIN s.user u WHERE s.group = :group'); $query->setParameter('group', $groupEntity); $subscriptions = $query->getResult(); foreach ($subscriptions as $subscription) { if (!$subscription->getUser()->getSendEmailOnNewAssignment()) { continue; } $to = $subscription->getUser()->getEmail(); $email = file_get_contents(Config::get("paths", "newAssignmentEmail")); $email = str_replace("%{Problem}", $problemEntity->getName(), $email); $email = str_replace("%{Deadline}", $deadline, $email); $email = str_replace("%{Group}", $groupEntity->getName(), $email); $email = str_replace("%{Link}", Config::getHttpRoot() . "#studentAssignments#" . $assignmentEntity->getId(), $email); $email = str_replace("%{Date}", date("Y-m-d H:i:s"), $email); $lines = explode("\n", $email); $subject = $lines[0]; // The first line is subject. $text = preg_replace('/^.*\\n/', '', $email); // Everything except the first line. if (!Core::sendEmail($to, trim($subject), $text)) { Core::logError(Error::create(Error::levelWarning, "E-mail could not be sent to {$to}.")); } } } return true; }
/** * Checks whether user has at least one the given sets of privileges [stopping]. * @param int $privileges sets of privileges to check against * @return bool true if he has * @see User::hasPrivileges() */ protected final function userHasPrivileges(...$privileges) { $reason = ""; if (!User::instance()->isSessionValid($reason)) { return $this->stop(Language::get(StringID::SessionInvalidated)); } if (!User::instance()->hasPrivileges(...$privileges)) { return $this->stop(Language::get(StringID::InsufficientPrivileges)); } return true; }
/** * Performs the function of this script. */ protected function body() { if (!$this->userHasPrivileges(User::assignmentsSubmit)) { return; } if (!$this->isInputValid(array('assignmentId' => 'isIndex'))) { return; } $userId = User::instance()->getId(); $assignmentId = $this->getParams('assignmentId'); /** * @var $assignment \Assignment */ $assignment = Repositories::getEntityManager()->find('Assignment', $assignmentId); $query = "SELECT s, a FROM Subscription s, Assignment a WHERE s.group = a.group AND s.user = "******" AND a.id = " . $assignmentId; /** * @var $result \Subscription[] */ $result = Repositories::getEntityManager()->createQuery($query)->getResult(); if (count($result) === 0) { $this->stop(Language::get(StringID::HackerError)); return; } if ($result[0]->getStatus() == \Subscription::STATUS_REQUESTED) { $this->stop(Language::get(StringID::SubscriptionNotYetAccepted)); return; } $submissionsFolder = Config::get('paths', 'submissions'); $file = date('Y-m-d_H-i-s_') . $userId . '_' . StringUtils::randomString(10) . '.zip'; if (!$this->saveUploadedFile('submission', $submissionsFolder . $file)) { return; } // Create submission $newSubmission = new \Submission(); $newSubmission->setAssignment($assignment); $newSubmission->setSubmissionFile($file); $newSubmission->setUser(User::instance()->getEntity()); $newSubmission->setDate(new \DateTime()); // Put into database Repositories::persistAndFlush($newSubmission); // Launch plugin, or set full success if not connected to any plugin if ($assignment->getProblem()->getPlugin() === null) { $newSubmission->setSuccess(100); $newSubmission->setInfo(Language::get(StringID::NoPluginUsed)); $previousSubmissions = Repositories::makeDqlQuery("SELECT s FROM \\Submission s WHERE s.user = :sameUser AND s.assignment = :sameAssignment AND s.status != 'graded' AND s.status != 'deleted'")->setParameter('sameUser', User::instance()->getEntity()->getId())->setParameter('sameAssignment', $assignment->getId())->getResult(); foreach ($previousSubmissions as $previousSubmission) { $previousSubmission->setStatus(\Submission::STATUS_NORMAL); Repositories::getEntityManager()->persist($previousSubmission); } $newSubmission->setStatus(\Submission::STATUS_LATEST); Repositories::getEntityManager()->persist($newSubmission); Repositories::flushAll(); } else { Core::launchPlugin($assignment->getProblem()->getPlugin()->getType(), Config::get('paths', 'plugins') . $assignment->getProblem()->getPlugin()->getMainfile(), $submissionsFolder . $file, false, $newSubmission->getId(), explode(';', $assignment->getProblem()->getConfig())); } // Run checking for plagiarism $similarityJar = Config::get('paths', 'similarity'); if ($similarityJar != null && is_file($similarityJar)) { $arguments = "comparenew"; // Get config file and autoloader file $paths = Config::get('paths'); $vendorAutoload = $paths['composerAutoload']; $java = Config::get('bin', 'java'); $javaArguments = Config::get('bin', 'javaArguments'); $pathToCore = Config::get('paths', 'core'); // This code will be passed, shell-escaped to the PHP CLI $launchCode = <<<LAUNCH_CODE require_once '{$vendorAutoload}'; chdir("{$pathToCore}"); `"{$java}" {$javaArguments} -Dfile.encoding=UTF-8 -jar "{$similarityJar}" {$arguments}`; LAUNCH_CODE; ShellUtils::phpExecInBackground(Config::get('bin', 'phpCli'), $launchCode); } }