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;
 }
 /**
  * Creates new unique ID for file.
  * @return string new unique ID (not currently used)
  */
 protected function generateUniqueId()
 {
     do {
         $id = StringUtils::randomString(10);
     } while (isset($_SESSION[UploadManager::sessionSpace][$id]) || file_exists($this->getFilenameFromId($id)));
     return $id;
 }
示例#3
0
 /**
  * Strips XPath comments from supplied XPath expression string.
  * @param string $expr XPath expression
  * @param[out] array $comments stripped comments
  * @return string expression @a $expr stripped of comments
  */
 protected function stripXpathComments($expr, &$comments)
 {
     $com = array();
     $expr = StringUtils::stripComments($expr, '{--', '--}', $com);
     $expr = StringUtils::stripComments($expr, '(:', ':)', $com);
     $comments = implode("\n", $com);
     return $expr;
 }
 /**
  * Turns test results to plugin criteria or error.
  * Goal names will be used as criterion names. Criteria will be passed with
  * 100% fulfillment if goal was reached or failed with goal error as failure
  * info otherwise.
  *	@throws PluginException in case test finished with error(s), so that the
  *		error is returned as plugin error
  */
 private function createCriteriaFromTest()
 {
     if (count($this->results['errors'])) {
         throw new PluginException("Failure. " . StringUtils::indent(implode("\n", $this->results['errors'])));
     }
     foreach ($this->test->getGoals() as $goalId => $goalName) {
         $this->addCriterion($goalName);
         $results = $this->results['results'][$goalId];
         $passed = $results['reached'];
         $fulfillment = $passed ? 100 : 0;
         $details = !$passed && $results['error'] ? StringUtils::indent(trim($results['error'])) . "\n" : '';
         $this->updateCriterion($goalName, $passed, $fulfillment, $details);
     }
 }
 /**
  * Initializes instance members with supplied data.
  * @param mixed $data either error message (string) or criteria info (array)
  * @see create()
  * @see createError()
  * @see fromXml()
  */
 protected function __construct($data)
 {
     if (!is_array($data)) {
         $this->error = StringUtils::stripFunctionLinks($data);
     } else {
         $this->results = $data;
         $this->output = func_get_arg(1);
         $fulfillmentSum = 0;
         $passedCriteria = 0;
         $this->details = '';
         foreach ($data as $name => $criterion) {
             $fulfillmentSum += $criterion['fulfillment'];
             $passedCriteria += (int) $criterion['passed'];
             $this->details .= $name . ' ... ' . ($criterion['passed'] ? 'PASSED' : 'FAILED') . "\n";
             if ($criterion['details']) {
                 $this->details .= $criterion['details'] . "\n";
             }
         }
         $numCriteria = count($data);
         $this->details = "Passed {$passedCriteria} out of {$numCriteria} criteria.\n\n{$this->details}";
         $this->fulfillment = $numCriteria ? $fulfillmentSum / $numCriteria : 0;
     }
 }
 protected function main()
 {
     // Load the two files
     $xmlFile = '';
     $dtdFile = '';
     $this->loadFiles($this->absolutePathToFolder, $xmlFile, $dtdFile);
     // may add errors to the error list
     if ($this->hasErrors()) {
         return;
     }
     // Files loaded.
     $this->addGoals(array(self::goalWellFormedXml => 'XML is well-formed', self::goalValidXml => 'XML is valid to supplied DTD', self::goalValidDtd => 'DTD is valid', self::goalCorrectReferral => 'The XML\'s DOCTYPE declaration refers to the provided DTD.', self::goalCoveredDtd => 'DTD document contains required constructs', self::goalCoveredXml => 'XML document contains required constructs', self::goalCoveredSpecials => 'Documents contain required special constructs'));
     StringUtils::removeBomFromFile($dtdFile);
     $dtdString = file_get_contents($dtdFile);
     $xmlString = file_get_contents($xmlFile);
     $dtdString = $this->convertToUtf8($dtdString);
     $xmlString = $this->convertToUtf8($xmlString);
     if ($xmlString === false) {
         $this->addError("The XML file must be either in UTF-8 or in UTF-16.");
     }
     if ($dtdString === false) {
         $this->addError("The DTD file must be either in UTF-8 or in UTF-16.");
     }
     if ($this->hasErrors()) {
         return;
     }
     if ($this->loadXml($xmlFile, true, $xmlDom, $error)) {
         $xmlDom->formatOutput = true;
         /**
          * @var DOMDocument $xmlDomDocument
          */
         $xmlDomDocument = $xmlDom;
         if (!$xmlDomDocument->doctype) {
             $this->failGoal(self::goalCorrectReferral, "The XML does not have a DOCTYPE declaration.");
             if ($this->checkDTDValidity($dtdString, "", $dtdDoc)) {
                 $this->checkDTDConstructCoverage($dtdDoc);
             } else {
                 $this->failGoal(self::goalCoveredDtd, 'Document did not pass DTD well-formedness and validity checks.');
             }
         } else {
             if ($xmlDomDocument->doctype->systemId === basename($dtdFile) || $xmlDomDocument->doctype->systemId === "./" . basename($dtdFile)) {
                 $this->reachGoal(self::goalCorrectReferral);
             } else {
                 $this->failGoal(self::goalCorrectReferral, "The XML file refers to a different DTD than the one provided.");
             }
             $internalSubset = $xmlDomDocument->doctype->internalSubset;
             if ($this->checkDTDValidity($dtdString, $internalSubset, $dtdDoc)) {
                 $this->checkDTDConstructCoverage($dtdDoc);
             } else {
                 $this->failGoal(self::goalCoveredDtd, 'Document did not pass DTD well-formedness and validity checks.');
             }
         }
         $this->reachGoal(self::goalWellFormedXml);
         $this->checkXMLValidity($xmlDom);
         $this->checkXMLConstructCoverage($xmlDom);
         $this->checkSpecialConstructCoverage($xmlString, $dtdString);
     } else {
         if ($this->checkDTDValidity($dtdString, "", $dtdDoc)) {
             $this->checkDTDConstructCoverage($dtdDoc);
         } else {
             $this->failGoal(self::goalCoveredDtd, 'Document did not pass DTD well-formedness and validity checks.');
         }
         $this->failGoals(array(self::goalWellFormedXml, self::goalValidXml, self::goalCoveredXml, self::goalCoveredSpecials, self::goalCorrectReferral), $error);
     }
 }
示例#7
0
 /**
  * Creates message with custom formatting from supplied exception.
  * @param Exception $e
  * @return string error message with format: \<message\> (\<file\>:\<line\>)
  */
 protected static function getCustomMessage(Exception $e)
 {
     return StringUtils::stripFunctionLinks($e->getMessage()) . ' (' . basename($e->getFile()) . ':' . $e->getLine() . ')';
 }
    /**
     * 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);
        }
    }
 /**
  * Turns managed tests' results to plugin criteria or errors.
  * For criterion to be passed, all goals specified for that criterion when
  * @ref addTesterCriterion() "adding it" must be reached. Otherwise the
  * criterion is failed with fulfillment percentage based on number of failed
  * goals and failure info created by joining failure information of failed goals.
  */
 private function checkTesterCriteria()
 {
     $failedTests = array();
     foreach ($this->testerCriteria as $criterionName => $criterionConfig) {
         $goalCount = 0;
         $goalsFailed = 0;
         $details = '';
         foreach ($criterionConfig as $testId => $goalIds) {
             if ($goalIds === null) {
                 $goalIds = $criterionConfig[$testId] = array_keys($this->tests[$testId]->getGoals());
             }
             $goalCount += count($goalIds);
             $results = $this->testResults[$testId];
             foreach ($goalIds as $goalId) {
                 $goal = isset($results['results'][$goalId]) ? $results['results'][$goalId] : array();
                 if (count($results['errors'])) {
                     ++$goalsFailed;
                     if (!$failedTests[$testId]) {
                         $failedTests[$testId] = true;
                         $details .= $results['name'] . ' didn\'t successfully finish' . "\n" . StringUtils::indent(implode("\n", $results['errors']));
                     }
                 } elseif (!$goal['reached']) {
                     ++$goalsFailed;
                     $errorStr = $goal['error'] ? StringUtils::indent(trim($goal['error'])) . "\n" : '';
                     $details .= "{$goal['name']} ({$results['name']}) failed\n" . $errorStr;
                 }
             }
         }
         $fulfillment = $goalCount > 0 ? floor(($goalCount - $goalsFailed) * 100 / $goalCount) : 100;
         $this->updateCriterion($criterionName, $goalsFailed == 0, $fulfillment, $details);
     }
 }