protected function body()
 {
     if (!$this->userHasPrivileges(User::groupsJoinPrivate, User::groupsJoinPublic, User::groupsRequest)) {
         return false;
     }
     if (!$this->isInputValid(array('id' => 'isIndex'))) {
         return false;
     }
     $groupId = $this->getParams('id');
     /**
      * @var $group \Group
      */
     $group = Repositories::findEntity(Repositories::Group, $groupId);
     // Calculate privileges of the user
     $user = User::instance();
     $canJoinPrivate = User::instance()->hasPrivileges(User::groupsJoinPrivate);
     $groupIsPrivate = $group->getType() == \Group::TYPE_PRIVATE;
     $hasSufficientPrivileges = $groupIsPrivate && ($canJoinPrivate || $user->hasPrivileges(User::groupsRequest)) || !$groupIsPrivate && $user->hasPrivileges(User::groupsJoinPublic);
     if (!$hasSufficientPrivileges) {
         return $this->death(StringID::InsufficientPrivileges);
     }
     $status = $canJoinPrivate || !$groupIsPrivate ? \Subscription::STATUS_SUBSCRIBED : \Subscription::STATUS_REQUESTED;
     // Put into database
     $subscription = new \Subscription();
     $subscription->setGroup($group);
     $subscription->setUser(User::instance()->getEntity());
     $subscription->setStatus($status);
     Repositories::persistAndFlush($subscription);
     return true;
 }
 protected function body()
 {
     if (!$this->isInputSet(array('email'))) {
         return false;
     }
     $email = $this->getParams('email');
     $users = Repositories::getRepository(Repositories::User)->findBy(['email' => $email]);
     foreach ($users as $user) {
         /**
          * @var $user \User
          */
         // Generate reset link.
         $resetLink = StringUtils::randomString(60);
         $now = new \DateTime();
         $expiryDate = $now->add(new \DateInterval('P1D'));
         // Add in in the database (replacing any older reset links in the process)
         $user->setResetLink($resetLink);
         $user->setResetLinkExpiry($expiryDate);
         Repositories::persistAndFlush($user);
         // Send the e-mail
         $body = "A Password Reset Link was requested for your e-mail address on XMLCheck.\n\nYour name: " . $user->getRealName() . "\nYour login: "******"\n\nClick this link to reset your password: \n\n" . Config::get('roots', 'http') . "#resetPassword#" . $resetLink . "\n\nThe link will be valid for the next 24 hours, until " . $expiryDate->format("Y-m-d H:i:s") . ".";
         if (!Core::sendEmail($user->getEmail(), "[XMLCheck] Password Reset Link for '" . $user->getRealName() . "'", $body)) {
             return $this->death(StringID::MailError);
         }
     }
     $this->addOutput('count', count($users));
     return true;
 }
 protected function body()
 {
     if (!$this->isInputValid(['resetLink' => 'isNotEmpty', 'pass' => 'isNotEmpty'])) {
         return false;
     }
     $resetLink = $this->getParams('resetLink');
     if (strlen($resetLink) < 1) {
         // We double-check here. This should not be necessary because the isInputValid function takes care of this.
         // However, if there is a bug in isInputValid that causes the check to be skipped,
         // this will allow the user to change the password of the first user with no resetLink active.
         // This could plausibly be the administrator.
         return $this->death(StringID::HackerError);
     }
     $encryptionType = Security::HASHTYPE_PHPASS;
     $newPassword = $this->getParams('pass');
     $newPasswordHash = Security::hash($newPassword, $encryptionType);
     $usersWithThisResetLink = Repositories::getRepository(Repositories::User)->findBy(['resetLink' => $resetLink]);
     if (count($usersWithThisResetLink) !== 1) {
         return $this->death(StringID::ResetLinkDoesNotExist);
     }
     /**
      * @var $user \User
      */
     $user = $usersWithThisResetLink[0];
     if ($user->getResetLinkExpiry() < new \DateTime()) {
         return $this->death(StringID::ResetLinkExpired);
     }
     $user->setResetLink('');
     $user->setPass($newPasswordHash);
     Repositories::persistAndFlush($user);
     return true;
 }
 protected function body()
 {
     $inputs = array('name' => array('isNotEmpty'), 'description' => 'isNotEmpty');
     if (!$this->isInputValid($inputs)) {
         return false;
     }
     $name = $this->getParams('name');
     $description = $this->getParams('description');
     $id = $this->getParams('id');
     $isIdSet = $id !== null && $id !== '';
     $user = User::instance();
     $userId = $user->getId();
     if (!$isIdSet) {
         if (!$this->userHasPrivileges(User::lecturesAdd)) {
             return false;
         }
         $lecture = new \Lecture();
         $lecture->setName($name);
         $lecture->setDescription($description);
         $lecture->setOwner(User::instance()->getEntity());
         Repositories::persistAndFlush($lecture);
     } else {
         if ($isIdSet) {
             $lecture = Repositories::findEntity(Repositories::Lecture, $id);
             if (!$user->hasPrivileges(User::lecturesManageAll) && (!$user->hasPrivileges(User::lecturesManageOwn) || $lecture->getOwner()->getId() != $userId)) {
                 return $this->death(StringID::InsufficientPrivileges);
             }
             $lecture->setDescription($description);
             Repositories::persistAndFlush($lecture);
         }
     }
     return true;
 }
 protected function body()
 {
     if (!$this->userHasPrivileges(User::pluginsAdd)) {
         return false;
     }
     $inputs = array('name' => array('isName', 'isNotEmpty'));
     if (!$this->isInputValid($inputs)) {
         return false;
     }
     $name = $this->getParams('name');
     $existingPluginsWithSameName = Repositories::getRepository(Repositories::Plugin)->findBy(['name' => $name]);
     if (count($existingPluginsWithSameName) > 0) {
         return $this->death(StringID::PluginNameAlreadyExists);
     }
     $pluginFile = $this->getUploadedFile('plugin');
     if (!$pluginFile) {
         return false;
     }
     $pluginFolder = Config::get('paths', 'plugins') . $name;
     if (file_exists($pluginFolder)) {
         return $this->death(StringID::PluginFolderAlreadyExists);
     }
     if (!Filesystem::createDir($pluginFolder)) {
         return $this->death(StringID::FileSystemError);
     }
     if (!Compression::unzip($pluginFile, $pluginFolder)) {
         $this->death(StringID::UnzipUnsuccessful);
         goto cleanup_error;
     }
     $manifestFile = $pluginFolder . DIRECTORY_SEPARATOR . 'manifest.xml';
     $manifest = null;
     if (!($manifest = $this->parsePluginManifest($manifestFile))) {
         $this->death(StringID::BadlyFormedPlugin);
         goto cleanup_error;
     }
     if (!file_exists($pluginFolder . DIRECTORY_SEPARATOR . $manifest['mainFile'])) {
         $this->death(StringID::BadlyFormedPlugin);
         goto cleanup_error;
     }
     $plugin = new \Plugin();
     $plugin->setIdentifier($manifest['identifier']);
     $plugin->setDescription($manifest['description']);
     $plugin->setConfig($manifest['arguments']);
     $plugin->setMainfile($name . '/' . $manifest['mainFile']);
     $plugin->setName($name);
     $plugin->setType($manifest['type']);
     Repositories::persistAndFlush($plugin);
     Filesystem::removeFile($pluginFile);
     return true;
     cleanup_error:
     Filesystem::removeDir($pluginFolder);
     Filesystem::removeFile($pluginFile);
     return false;
 }
 protected function body()
 {
     $inputs = array('lecture' => 'isIndex', 'name' => array('isName', 'isNotEmpty'), 'type' => array('isEnum' => array('text', 'code', 'image')));
     if (!$this->isInputValid($inputs)) {
         return false;
     }
     $lectureId = $this->getParams('lecture');
     /** @var \Lecture $lecture */
     $lecture = Repositories::findEntity(Repositories::Lecture, $lectureId);
     $name = $this->getParams('name');
     $type = $this->getParams('type');
     $id = $this->getParams('id');
     $isIdSet = $id !== null && $id !== '';
     $originalName = $this->getUploadedFileName('file');
     if (!$originalName) {
         return false;
     }
     $extensionStart = strrpos($originalName, '.');
     $extension = $extensionStart === false ? '' : substr($originalName, strrpos($originalName, '.'));
     $attachmentFolder = Config::get('paths', 'attachments');
     $filename = $id . '_' . $name . $extension;
     if (!$this->checkTestGenerationPrivileges($lecture)) {
         return $this->death(StringID::InsufficientPrivileges);
     }
     /**
      * @var $attachment \Attachment
      */
     $attachment = null;
     if (!$this->saveUploadedFile('file', $attachmentFolder . $filename)) {
         return $this->death(StringID::InsufficientPrivileges);
     }
     /** @var \Attachment[] $attachmentsWithThisName */
     $attachmentsWithThisName = Repositories::getRepository(Repositories::Attachment)->findBy(['lecture' => $lectureId, 'name' => $name]);
     if ($isIdSet) {
         $attachment = Repositories::findEntity(Repositories::Attachment, $id);
         if (count($attachmentsWithThisName) > 0) {
             if ($attachmentsWithThisName[0]->getId() !== $attachment->getId()) {
                 return $this->death(StringID::AttachmentExists);
             }
         }
     } else {
         if (count($attachmentsWithThisName) > 0) {
             return $this->death(StringID::AttachmentExists);
         }
         $attachment = new \Attachment();
     }
     $attachment->setType($type);
     $attachment->setLecture($lecture);
     $attachment->setName($name);
     $attachment->setFile($filename);
     Repositories::persistAndFlush($attachment);
     return true;
 }
 protected function body()
 {
     $inputs = array('lecture' => 'isIndex', 'text' => 'isNotEmpty', 'type' => array('isEnum' => array('text', 'choice', 'multi')));
     if (!$this->isInputValid($inputs)) {
         return false;
     }
     $lectureId = $this->getParams('lecture');
     $text = $this->getParams('text');
     $type = $this->getParams('type');
     $id = $this->getParams('id');
     $isIdSet = $id !== null && $id !== '';
     $options = $this->getParams('options') . '';
     $attachments = $this->getParams('attachments') . '';
     if (!$this->checkTestGenerationPrivileges($lectureId)) {
         return $this->death(StringID::InsufficientPrivileges);
     }
     $visibleAttachments = CommonQueries::GetAttachmentsVisibleToActiveUser();
     $attTmp = $attachments ? explode(';', $attachments) : array();
     foreach ($visibleAttachments as $va) {
         $aId = $va->getId();
         $index = array_search($aId, $attTmp);
         if ($index !== false) {
             array_splice($attTmp, $index, 1);
             if ($va->getLecture()->getId() != $lectureId) {
                 return $this->death(StringID::AttachmentBelongsToAnotherLecture);
             }
         }
     }
     if (count($attTmp)) {
         return $this->stop(ErrorCause::invalidInput('Following attachment IDs are invalid or inaccessible: ' . implode(', ', $attTmp) . '.', 'attachments'));
     }
     /** @var \Question $question */
     $question = null;
     if (!$isIdSet) {
         $question = new \Question();
     } else {
         $question = Repositories::findEntity(Repositories::Question, $id);
         if ($question->getLecture()->getId() != $lectureId) {
             // This must be a weak comparison, because lectureId comes from user and is text.
             return $this->death(StringID::HackerError);
         }
     }
     $question->setAttachments($attachments);
     /** @var \Lecture $lecture */
     $lecture = Repositories::findEntity(Repositories::Lecture, $lectureId);
     $question->setLecture($lecture);
     $question->setOptions($options);
     $question->setText($text);
     $question->setType($type);
     Repositories::persistAndFlush($question);
     return true;
 }
Example #8
0
 protected function body()
 {
     $questions = $this->getParams('questions');
     if ($questions === null || $questions === '') {
         return $this->death(StringID::ChooseAtLeastOneQuestion);
         // Put this in front to have a more specific, comprehensible error message
     }
     $inputs = array('description' => 'isNotEmpty', 'count' => 'isNonNegativeInt', 'questions' => 'isNotEmpty');
     if (!$this->isInputValid($inputs)) {
         return false;
     }
     $description = $this->getParams('description');
     $count = $this->getParams('count');
     $questions = $this->getParams('questions');
     $questionsArray = explode(',', $questions);
     $visibleQuestions = CommonQueries::GetQuestionsVisibleToActiveUser();
     /**
      * @var $lecture \Lecture
      */
     $lecture = null;
     foreach ($visibleQuestions as $vq) {
         $qId = $vq->getId();
         $index = array_search($qId, $questionsArray);
         if ($index !== false) {
             array_splice($questionsArray, $index, 1);
             if ($lecture === null) {
                 $lecture = $vq->getLecture();
             } elseif ($lecture->getId() !== $vq->getLecture()->getId()) {
                 return $this->death(StringID::TestCannotContainQuestionsOfDifferentLectures);
             }
         }
     }
     if (count($questionsArray)) {
         return $this->stop(ErrorCause::invalidInput('Following question IDs are invalid or inaccessible: ' . implode(', ', $questionsArray) . '.', 'questions'));
     }
     if ($lecture === null) {
         return $this->death(StringID::ChooseAtLeastOneQuestion);
     }
     if (!$this->checkTestGenerationPrivileges($lecture->getId())) {
         return $this->death(StringID::InsufficientPrivileges);
     }
     $randomized = $this->generateTest($questions, $count);
     $xtest = new \Xtest();
     $xtest->setDescription($description);
     $xtest->setCount($count);
     $xtest->setLecture($lecture);
     $xtest->setTemplate($questions);
     $xtest->setGenerated(implode(',', $randomized));
     Repositories::persistAndFlush($xtest);
     return true;
 }
 protected function body()
 {
     if (!$this->isInputValid(array('id' => 'isIndex'))) {
         return false;
     }
     /**
      * @var $assignment \Assignment
      */
     $assignment = Repositories::findEntity(Repositories::Assignment, $this->getParams('id'));
     $user = User::instance();
     if (!$user->hasPrivileges(User::groupsManageAll) && (!$user->hasPrivileges(User::groupsManageOwn) || $user->getId() != $assignment->getGroup()->getOwner()->getId())) {
         return $this->death(StringID::InsufficientPrivileges);
     }
     $assignment->setDeleted(true);
     Repositories::persistAndFlush($assignment);
     return true;
 }
 protected function body()
 {
     if (!$this->isInputValid(array('id' => 'isIndex'))) {
         return false;
     }
     $id = $this->getParams('id');
     /**
      * @var $submission \Submission
      */
     $submission = Repositories::findEntity(Repositories::Submission, $id);
     $userId = User::instance()->getId();
     if ($submission->getUser()->getId() != $userId) {
         return $this->death(StringID::HackerError);
     }
     // First, if you handed something off previously, it is no longer handed off
     /**
      * @var $yourSubmissions \Submission[]
      */
     $yourSubmissions = Repositories::getRepository(Repositories::Submission)->findBy(['user' => $userId, 'assignment' => $submission->getAssignment()->getId()]);
     foreach ($yourSubmissions as $previouslyHandedOffSubmission) {
         if ($previouslyHandedOffSubmission->getStatus() == \Submission::STATUS_REQUESTING_GRADING || $previouslyHandedOffSubmission->getStatus() == \Submission::STATUS_LATEST) {
             $previouslyHandedOffSubmission->setStatus(\Submission::STATUS_NORMAL);
             Repositories::persistAndFlush($previouslyHandedOffSubmission);
         }
     }
     // Next, hand off the submission
     $submission->setStatus(\Submission::STATUS_REQUESTING_GRADING);
     Repositories::persistAndFlush($submission);
     $emailText = file_get_contents(Config::get("paths", "newSubmissionEmail"));
     $emailText = str_replace("%{RealName}", User::instance()->getRealName(), $emailText);
     $emailText = str_replace("%{Email}", User::instance()->getEmail(), $emailText);
     $emailText = str_replace("%{Link}", Config::getHttpRoot() . "#correctionAll#submission#" . $submission->getId(), $emailText);
     $lines = explode("\n", $emailText);
     $subject = $lines[0];
     // The first line is subject.
     $text = preg_replace('/^.*\\n/', '', $emailText);
     // Everything except the first line.
     $to = $submission->getAssignment()->getGroup()->getOwner();
     if ($to->getSendEmailOnNewSubmission()) {
         if (!Core::sendEmail($to->getEmail(), $subject, $text)) {
             return $this->death(StringID::MailError);
         }
     }
     return true;
 }
Example #11
0
 protected function body()
 {
     if (!$this->isInputSet(array('code'))) {
         return false;
     }
     $code = $this->getParams('code');
     /**
      * @var $users \User[]
      */
     $users = Repositories::getRepository(Repositories::User)->findBy(['activationCode' => $code]);
     if (count($users) === 1) {
         $users[0]->setActivationCode('');
         Repositories::persistAndFlush($users[0]);
         return true;
     } else {
         return $this->death(StringID::InvalidActivationCode);
     }
 }
Example #12
0
 protected function body()
 {
     $inputs = array('lecture' => 'isIndex', 'name' => 'isNotEmpty', 'description' => array());
     if (!$this->isInputValid($inputs)) {
         return false;
     }
     $lectureIndex = $this->getParams('lecture');
     $groupName = $this->getParams('name');
     $groupDescription = $this->getParams('description');
     $public = $this->paramExists('public') ? 'public' : 'private';
     $groupId = $this->getParams('id');
     $editing = $groupId !== null && $groupId !== '';
     $user = User::instance();
     /** @var \Lecture $lecture */
     $lecture = Repositories::findEntity(Repositories::Lecture, $lectureIndex);
     if ($editing) {
         /**
          * @var $group \Group
          */
         $group = Repositories::findEntity(Repositories::Group, $groupId);
         $group->setName($groupName);
         $group->setDescription($groupDescription);
         $group->setType($public);
         Repositories::persistAndFlush($group);
     } else {
         if (!$this->userHasPrivileges(User::groupsAdd)) {
             return $this->death(StringID::InsufficientPrivileges);
         }
         $group = new \Group();
         $group->setDeleted(false);
         $group->setDescription($groupDescription);
         $group->setLecture($lecture);
         $group->setName($groupName);
         $group->setOwner($user->getEntity());
         $group->setType($public);
         Repositories::persistAndFlush($group);
     }
     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);
        }
    }
 /**
  * Deletes attachment with supplied ID. Removes the attachment from questions that referenced it. This will not delete the attachment file from disk.
  *
  * @param int $id attachment ID
  * @return array error properties provided by removalError() or retrievalError(),
  * or false in case of success
  */
 public static function deleteAttachmentById($id)
 {
     /**
      * @var $attachment \Attachment
      */
     $attachment = Repositories::findEntity(Repositories::Attachment, $id);
     $questions = CommonQueries::getQuestionsVisibleToActiveUser();
     foreach ($questions as $question) {
         $modificationMade = false;
         $attachments = explode(';', $question->getAttachments());
         for ($i = 0; $i < count($attachments); $i++) {
             if ($attachments[$i] === (string) $id) {
                 unset($attachments[$i]);
                 $modificationMade = true;
             }
         }
         if ($modificationMade) {
             $question->setAttachments(implode(';', $attachments));
             Repositories::persistAndFlush($question);
         }
     }
     Repositories::remove($attachment);
     return false;
 }
Example #15
0
 /**
  * Launches plugin and updates database with results.
  * @param string $pluginType one of 'php', 'java', or 'exe'
  * @param string $pluginFile plugin file path
  * @param string $inputFile input file path
  * @param boolean $isTest is this a plugin test or a submission? true if plugin test
  * @param int $rowId ID of row to be updated
  * @param array $arguments plugin arguments
  * @return bool true if no error occurred
  */
 public static function launchPlugin($pluginType, $pluginFile, $inputFile, $isTest, $rowId, $arguments = array())
 {
     try {
         $response = null;
         if (!is_file($pluginFile) || !is_file($inputFile)) {
             $error = "plugin file and/or input file don't exist";
         } else {
             array_unshift($arguments, $inputFile);
             $cwd = getcwd();
             chdir(dirname($pluginFile));
             switch ($pluginType) {
                 case 'php':
                     $launcher = new PhpLauncher();
                     ob_start();
                     $error = $launcher->launch($pluginFile, $arguments, $response);
                     ob_end_clean();
                     break;
                 case 'java':
                     $launcher = new JavaLauncher();
                     $error = $launcher->launch($pluginFile, $arguments, $responseString);
                     break;
                 case 'exe':
                     $launcher = new ExeLauncher();
                     $error = $launcher->launch($pluginFile, $arguments, $responseString);
                     break;
                 default:
                     $error = "unsupported plugin type '{$pluginType}'";
             }
             chdir($cwd);
         }
         if (!$error) {
             if (isset($responseString)) {
                 try {
                     $response = PluginResponse::fromXmlString($responseString);
                 } catch (Exception $ex) {
                     $response = PluginResponse::createError('Internal error. Plugin did not supply valid response XML and this error occurred: ' . $ex->getMessage() . '. Plugin instead supplied this response string: ' . $responseString);
                 }
             }
         } else {
             $response = PluginResponse::createError('Plugin cannot be launched (' . $error . ').');
         }
         $outputFile = $response->getOutput();
         if ($outputFile) {
             $outputFolder = Config::get('paths', 'output');
             $newFile = $outputFolder . date('Y-m-d_H-i-s_') . StringUtils::randomString(10) . '.zip';
             if (rename($outputFile, $newFile)) {
                 $outputFile = $newFile;
             } else {
                 $outputFile = 'tmp-file-rename-failed';
             }
         }
         /**
          * @var $pluginTest \PluginTest
          * @var $submission \Submission
          * @var $previousSubmissions \Submission[]
          */
         if ($isTest) {
             $pluginTest = Repositories::findEntity(Repositories::PluginTest, $rowId);
             $pluginTest->setStatus(\PluginTest::STATUS_COMPLETED);
             $pluginTest->setSuccess($response->getFulfillment());
             $pluginTest->setInfo($response->getDetails());
             $pluginTest->setOutput($outputFile);
             Repositories::persistAndFlush($pluginTest);
         } else {
             $submission = Repositories::findEntity(Repositories::Submission, $rowId);
             // There is a sort of a race condition in here.
             // It is, in theory, possible, that there will be two submissions with the "latest" status after all is done
             // This should not happen in practice, though, and even if it does, it will have negligible negative effects.
             $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', $submission->getUser()->getId())->setParameter('sameAssignment', $submission->getAssignment()->getId())->getResult();
             foreach ($previousSubmissions as $previousSubmission) {
                 $previousSubmission->setStatus(\Submission::STATUS_NORMAL);
                 Repositories::getEntityManager()->persist($previousSubmission);
             }
             $submission->setStatus(\Submission::STATUS_LATEST);
             $submission->setInfo($response->getDetails());
             $submission->setSuccess($response->getFulfillment());
             $submission->setOutputfile($outputFile);
             Repositories::getEntityManager()->persist($submission);
             Repositories::flushAll();
         }
         return !$error;
     } catch (Exception $exception) {
         $errorInformation = "Internal error. Plugin launcher or plugin failed with an internal error. Exception information: " . $exception->getMessage() . " in " . $exception->getFile() . " at " . $exception->getLine();
         if ($isTest) {
             $pluginTest = Repositories::findEntity(Repositories::PluginTest, $rowId);
             $pluginTest->setStatus(\PluginTest::STATUS_COMPLETED);
             $pluginTest->setSuccess(0);
             $pluginTest->setInfo($errorInformation);
             Repositories::persistAndFlush($pluginTest);
         } else {
             $submission = Repositories::findEntity(Repositories::Submission, $rowId);
             $submission->setStatus(\Submission::STATUS_NORMAL);
             $submission->setInfo($errorInformation);
             Repositories::persistAndFlush($submission);
         }
         return false;
     }
 }
Example #16
0
 /**
  * Runs this script.
  * @return bool Is it successful?
  * @throws \Exception Should never occur.
  */
 protected function body()
 {
     $inputs = array('name' => array('isAlphaNumeric', 'hasLength' => array('min_length' => Constants::UsernameMinLength, 'max_length' => Constants::UsernameMaxLength)), 'realname' => array('isNotEmpty', 'isName'), 'email' => 'isEmail', 'pass' => array(), 'repass' => array());
     if (!$this->isInputValid($inputs)) {
         return false;
     }
     // Extract input data
     $username = strtolower($this->getParams('name'));
     $realname = $this->getParams('realname');
     $email = $this->getParams('email');
     $pass = $this->getParams('pass');
     $repass = $this->getParams('repass');
     $id = $this->getParams('id');
     $type = $this->getParams('type');
     $user = null;
     $isIdSet = $id !== null && $id !== '';
     $isTypeSet = $type !== null && $type !== '';
     // Extract database data
     if ($id) {
         $user = Repositories::findEntity(Repositories::User, $id);
     }
     $userExists = $user != null;
     $sameNameUserExists = count(Repositories::getRepository(Repositories::User)->findBy(['name' => $username])) > 0;
     // Custom verification of input data
     if ($pass !== $repass) {
         return $this->death(StringID::InvalidInput);
     }
     if ($userExists) {
         if ((strlen($pass) < Constants::PasswordMinLength || strlen($pass) > Constants::PasswordMaxLength) && $pass !== "") {
             return $this->death(StringID::InvalidInput);
         }
     } else {
         // A new user must have full password
         if (strlen($pass) < Constants::PasswordMinLength || strlen($pass) > Constants::PasswordMaxLength) {
             return $this->death(StringID::InvalidInput);
         }
     }
     $code = '';
     $unhashedPass = $pass;
     $pass = Security::hash($pass, Security::HASHTYPE_PHPASS);
     $canAddUsers = User::instance()->hasPrivileges(User::usersAdd);
     $canEditUsers = User::instance()->hasPrivileges(User::usersManage);
     $isEditingSelf = $id == User::instance()->getId();
     // This must not be a strict comparison.
     /**
      * @var $user \User
      */
     if (!$userExists && !$sameNameUserExists) {
         if ($this->getParams('fromRegistrationForm')) {
             if ($type != Repositories::StudentUserType) {
                 return $this->death(StringID::InsufficientPrivileges);
             }
             $code = md5(uniqid(mt_rand(), true));
             $emailText = file_get_contents(Config::get("paths", "registrationEmail"));
             $emailText = str_replace("%{Username}", $username, $emailText);
             $emailText = str_replace("%{ActivationCode}", $code, $emailText);
             $emailText = str_replace("%{Link}", Config::getHttpRoot() . "#activate", $emailText);
             $lines = explode("\n", $emailText);
             $subject = $lines[0];
             // The first line is subject.
             $text = preg_replace('/^.*\\n/', '', $emailText);
             // Everything except the first line.
             $returnCode = Core::sendEmail($email, $subject, $text);
             if (!$returnCode) {
                 return $this->stop(ErrorCode::mail, 'user registration failed', 'email could not be sent');
             }
         } else {
             if (!$canAddUsers) {
                 return $this->death(StringID::InsufficientPrivileges);
             }
         }
         $user = new \User();
         /** @var \UserType $typeEntity */
         $typeEntity = Repositories::findEntity(Repositories::UserType, $type);
         $user->setType($typeEntity);
         $user->setPass($pass);
         $user->setName($username);
         $user->setEmail($email);
         $user->setActivationCode($code);
         $user->setEncryptionType(Security::HASHTYPE_PHPASS);
         $user->setRealName($realname);
         Repositories::persistAndFlush($user);
     } elseif ($isIdSet) {
         if (!$canEditUsers && ($isTypeSet || !$isEditingSelf)) {
             return $this->stop(ErrorCode::lowPrivileges, 'cannot edit data of users other than yourself');
         }
         $type = $isTypeSet ? $type : $user->getType()->getId();
         /** @var \UserType $typeEntity */
         $typeEntity = Repositories::findEntity(Repositories::UserType, $type);
         if ($unhashedPass) {
             $user->setPass($pass);
             $user->setEncryptionType(Security::HASHTYPE_PHPASS);
         }
         $user->setType($typeEntity);
         $user->setEmail($email);
         $user->setActivationCode('');
         $user->setRealName($realname);
         Repositories::persistAndFlush($user);
     } else {
         return $this->death(StringID::UserNameExists);
     }
     return true;
 }
Example #17
0
 /**
  * Tries to log user in with supplied credentials.
  * @param string $name username
  * @param string $pass password
  * @return bool true if login was successful
  */
 public function login($name, $pass)
 {
     if ($this->data != null) {
         $this->logout();
     }
     /// Username is case-insensitive.
     $name = strtolower($name);
     $users = Repositories::getRepository(Repositories::User)->findBy(['name' => $name]);
     if (!empty($users)) {
         /**
          * @var $user \User
          */
         $user = $users[0];
         if ($user->getActivationCode() !== '') {
             // Non-empty activation code means the account is not yet activated.
             return false;
         }
         $authenticationSuccess = Security::check($pass, $user->getPass(), $user->getEncryptionType());
         if ($authenticationSuccess) {
             $this->data = array('id' => $user->getId(), 'name' => $user->getName(), 'privileges' => $user->getType()->getPrivileges(), 'realName' => $user->getRealName(), 'email' => $user->getEmail(), 'lastAccess' => $user->getLastAccess()->format("Y-m-d H:i:s"), 'applicationVersion' => implode('.', Config::get('version')), User::sendEmailOnAssignmentAvailableStudent => $user->getSendEmailOnNewAssignment() ? 1 : 0, User::sendEmailOnSubmissionConfirmedTutor => $user->getSendEmailOnNewSubmission() ? 1 : 0, User::sendEmailOnSubmissionRatedStudent => $user->getSendEmailOnSubmissionRated() ? 1 : 0);
             $this->refresh();
             $user->setLastAccess(new \DateTime());
             Repositories::persistAndFlush($user);
             $this->entity = $user;
             return true;
         } else {
             return false;
         }
     }
     return false;
 }