/** * Serves the files from the emarking file areas * * @package mod_emarking * @category files * @param stdClass $course * the course object * @param stdClass $cm * the course module object * @param stdClass $context * the emarking's context * @param string $filearea * the name of the file area * @param array $args * extra arguments (itemid, path) * @param bool $forcedownload * whether or not force download * @param array $options * additional options affecting the file serving */ function emarking_pluginfile($course, $cm, $context, $filearea, array $args, $forcedownload, array $options = array()) { global $DB, $CFG, $USER; require_once $CFG->dirroot . '/mod/emarking/locallib.php'; require_once $CFG->dirroot . '/mod/emarking/print/locallib.php'; require_login(); // send_file defaults. $lifetime = null; $filter = 0; $pathisstring = false; $forcedownload = false; $mimetype = ''; $dontdie = false; // end of send_file defaults. $filename = array_pop($args); $itemid = array_pop($args); $contextcategory = context_coursecat::instance($course->category); $contextcourse = context_course::instance($course->id); // Security! We always protect the exams filearea. if ($filearea === 'exams') { send_file_not_found(); } if ($filearea === 'pages') { $parts = explode('-', $filename); if (count($parts) != 3) { send_file_not_found(); } if (!($parts[0] === intval($parts[0]) . "") || !($parts[1] === intval($parts[1]) . "")) { send_file_not_found(); } $subparts = explode('.', $parts[2]); $isanonymous = substr($subparts[0], -strlen('_a')) === '_a'; $imageuser = intval($parts[0]); $usercangrade = has_capability('mod/emarking:grade', $context); $bothenrolled = is_enrolled($contextcourse) && is_enrolled($contextcourse, $imageuser); if ($USER->id != $imageuser && !$usercangrade && !$isanonymous && !is_siteadmin($USER) && !$bothenrolled) { send_file_not_found(); } } if ($filearea === 'response') { $parts = explode('_', $filename); if (count($parts) != 3) { send_file_not_found(); } if (!($parts[0] === "response") || !($parts[1] === intval($parts[1]) . "")) { send_file_not_found(); } $subparts = explode('.', $parts[2]); $studentid = intval($subparts[0]); $emarkingid = intval($parts[1]); if (!($emarking = $DB->get_record('emarking', array('id' => $emarkingid)))) { send_file_not_found(); } if ($studentid != $USER->id && !is_siteadmin($USER) && !has_capability('mod/emarking:supervisegrading', $context)) { send_file_not_found(); } $forcedownload = true; $mimetype = 'application/pdf'; } if ($filearea === 'examstoprint') { if (!has_capability('mod/emarking:downloadexam', $contextcategory)) { // Add to Moodle log so some auditing can be done. \mod_emarking\event\invalidaccessdownload_attempted::create_from_exam($exam, $contextcourse)->trigger(); send_file_not_found(); } $token = required_param('token', PARAM_INT); if ($token > 9999 && $_SESSION[$USER->sesskey . "smstoken"] === $token) { if (!($exam = $DB->get_record('emarking_exams', array('emarking' => $itemid)))) { send_file_not_found(); } $now = new DateTime(); $tokendate = new DateTime(); $tokendate->setTimestamp($_SESSION[$USER->sesskey . "smsdate"]); $diff = $now->diff($tokendate); if ($diff->i > 5 && false) { // Add to Moodle log so some auditing can be done. \mod_emarking\event\invalidtokendownload_attempted::create_from_exam($exam, $contextcourse)->trigger(); send_file_not_found(); } // Everything is fine, now we update the exam status and deliver the file. $exam->status = EMARKING_EXAM_SENT_TO_PRINT; $DB->update_record('emarking_exams', $exam); } else { // Add to Moodle log so some auditing can be done. \mod_emarking\event\invalidtokendownload_attempted::create_from_exam($exam, $contextcourse)->trigger(); send_file_not_found(); } // Notify everyone that the exam was downloaded. emarking_send_examdownloaded_notification($exam, $course, $USER); // Add to Moodle log so some auditing can be done. \mod_emarking\event\exam_downloaded::create_from_exam($exam, $contextcourse)->trigger(); } $fs = get_file_storage(); if (!($file = $fs->get_file($context->id, 'mod_emarking', $filearea, $itemid, '/', $filename))) { echo $context->id . ".." . $filearea . ".." . $itemid . ".." . $filename; echo "File really not found"; send_file_not_found(); } send_file($file, $filename, $lifetime, $filter, $pathisstring, $forcedownload, $mimetype = '', $dontdie); }
/** * Creates a personalized exam file. * * @param unknown $examid * @return NULL */ function emarking_download_exam($examid, $multiplepdfs = false, $groupid = null, progress_bar $pbar = null, $sendprintorder = false, $idprinter = null, $printanswersheet = false, $debugprinting = false, $savetofile = false) { global $DB, $CFG, $USER, $OUTPUT; require_once $CFG->dirroot . '/mod/emarking/lib/openbub/ans_pdf_open.php'; // Validate emarking exam object. if (!($downloadexam = $DB->get_record('emarking_exams', array('id' => $examid)))) { throw new Exception(get_string("invalidexamid", "mod_emarking")); } // Course context for capabilities checking. $context = context_course::instance($downloadexam->course); if (!has_capability('mod/emarking:downloadexam', $context) && false) { throw new Exception(get_string("invalidaccess", "mod_emarking")); } // Verify that remote printing is enable, otherwise disable a printing order. if ($sendprintorder && (!$CFG->emarking_enableprinting || $idprinter == null)) { throw new Exception('Printing is not enabled or printername was absent ' . $idprinter); } // Validate course. if (!($course = $DB->get_record('course', array('id' => $downloadexam->course)))) { throw new Exception(get_string("invalidcourse", "mod_emarking")); } // Validate course category. if (!($coursecat = $DB->get_record('course_categories', array('id' => $course->category)))) { throw new Exception(get_string("invalidcategoryid", "mod_emarking")); } // We tell the user we are setting up the printing. if ($pbar) { $pbar->update(0, 1, get_string('settingupprinting', 'mod_emarking')); } // Default value for enrols that will be included. if ($CFG->emarking_enrolincludes && strlen($CFG->emarking_enrolincludes) > 1) { $enrolincludes = $CFG->emarking_enrolincludes; } // If the exam sets enrolments, we use those. if (isset($downloadexam->enrolments) && strlen($downloadexam->enrolments) > 1) { $enrolincludes = $downloadexam->enrolments; } // Convert enrolments to array. $enrolincludes = explode(",", $enrolincludes); // Produce all PDFs first separatedly. $filedir = $CFG->dataroot . "/temp/emarking/{$context->id}"; $fileimg = $filedir . "/qr"; $userimgdir = $filedir . "/u"; $pdfdir = $filedir . "/pdf"; emarking_initialize_directory($filedir, true); emarking_initialize_directory($fileimg, true); emarking_initialize_directory($userimgdir, true); emarking_initialize_directory($pdfdir, true); // Get all the files uploaded as forms for this exam. $fs = get_file_storage(); $files = $fs->get_area_files($context->id, 'mod_emarking', 'exams', $examid); // We filter only the PDFs. $pdffileshash = array(); foreach ($files as $filepdf) { if ($filepdf->get_mimetype() === 'application/pdf') { $pdffileshash[] = array('hash' => $filepdf->get_pathnamehash(), 'filename' => $filepdf->get_filename(), 'path' => emarking_get_path_from_hash($filedir, $filepdf->get_pathnamehash())); } } // Verify that at least we have a PDF. if (count($pdffileshash) < 1) { throw new Exception(get_string("examhasnopdf", "mod_emarking")); } $students = emarking_get_students_for_printing($downloadexam->course); $studentinfo = array(); $currenttemplate = 0; // Fill studentnames with student info (name, idnumber, id and picture). foreach ($students as $student) { $studentenrolments = explode(",", $student->enrol); // Verifies that the student is enrolled through a valid enrolment and that we haven't added her yet. if (count(array_intersect($studentenrolments, $enrolincludes)) == 0 || isset($studentinfo[$student->id])) { continue; } // We create a student info object. $studentobj = new stdClass(); $studentobj->name = substr("{$student->lastname}, {$student->firstname}", 0, 65); $studentobj->idnumber = $student->idnumber; $studentobj->id = $student->id; $studentobj->picture = emarking_get_student_picture($student, $userimgdir); // Store student info in hash so every student is stored once. $studentinfo[$student->id] = $studentobj; } // We validate the number of students as we are filtering by enrolment. // type after getting the data. $numberstudents = count($studentinfo); if ($numberstudents == 0) { throw new Exception('No students to print/create the exam'); } // Add the extra students to the list. for ($i = $numberstudents; $i < $numberstudents + $downloadexam->extraexams; $i++) { $studentobj = new stdClass(); $studentobj->name = '..............................................................................'; $studentobj->idnumber = 0; $studentobj->id = 0; $studentobj->picture = $CFG->dirroot . "/pix/u/f1.png"; $studentinfo[] = $studentobj; } // Check if there is a logo file. $logofilepath = emarking_get_logo_file($filedir); // If asked to do so we create a PDF witht the students list. if ($downloadexam->printlist == 1) { $pdf = new FPDI(); $pdf->SetPrintHeader(false); $pdf->SetPrintFooter(false); emarking_draw_student_list($pdf, $logofilepath, $downloadexam, $course, $studentinfo); $studentlistpdffile = $pdfdir . "/000-studentslist.pdf"; $pdf->Output($studentlistpdffile, "F"); // Se genera el nuevo pdf. $pdf = null; } // Here we produce a PDF file for each student. $currentstudent = 0; foreach ($studentinfo as $stinfo) { $studentrecord = $DB->get_record('user', array('id' => $stinfo->id)); // If we have a progress bar, we notify the new PDF being created. if ($pbar) { $pbar->update($currentstudent + 1, count($studentinfo), $stinfo->name); } // We create the PDF file. $pdf = new FPDI(); $pdf->SetPrintHeader(false); $pdf->SetPrintFooter(false); // We use the next form available from the list of PDF forms sent. if ($currenttemplate >= count($pdffileshash) - 1) { $currenttemplate = 0; } else { $currenttemplate++; } // Load the PDF from the filesystem as template. $path = $pdffileshash[$currenttemplate]['path']; $originalpdfpages = $pdf->setSourceFile($path); $pdf->SetAutoPageBreak(false); // Add all pages in the template, adding the header if it corresponds. for ($pagenumber = 1; $pagenumber <= $originalpdfpages + $downloadexam->extrasheets; $pagenumber++) { // Adding a page. $pdf->AddPage(); // If the page is not an extra page, we import the page from the template. if ($pagenumber <= $originalpdfpages) { $template = $pdf->importPage($pagenumber); $pdf->useTemplate($template, 0, 0, 0, 0, true); } // If we have a personalized header, we add it. if ($downloadexam->headerqr) { emarking_draw_header($pdf, $stinfo, $downloadexam->name, $pagenumber, $fileimg, $logofilepath, $course, $originalpdfpages + $downloadexam->extrasheets); } } // The filename will be the student id - course id - page number. $qrstringtmp = $stinfo->id > 0 ? "{$stinfo->id}-{$course->id}-{$pagenumber}" : "NN{$currentstudent}+1-{$course->id}-{$pagenumber}"; // Create the PDF file for the student. $pdffile = $pdfdir . "/" . $qrstringtmp . ".pdf"; $pdf->Output($pdffile, "F"); // Store the exam file for printing later. $stinfo->examfile = $pdffile; $stinfo->number = $currentstudent + 1; $stinfo->pdffilename = $qrstringtmp; $currentstudent++; } $sqlprinter = "SELECT id, name, command\n\t\t\tFROM {emarking_printers}\n\t\t\tWHERE id = ?"; $printerinfo = $DB->get_record_sql($sqlprinter, array($idprinter)); // If we have to print directly. $debugprintingmsg = ''; if ($sendprintorder) { // Check if we have to print the students list. if ($downloadexam->printlist == 1) { $printresult = emarking_print_file($printerinfo->name, $printerinfo->command, $studentlistpdffile, $debugprinting); if (!$printresult) { $debugprintingmsg .= 'Problems printing ' . $studentlistpdffile . '<hr>'; } else { $debugprintingmsg .= $printresult . '<hr>'; } } // Print each student. $currentstudent = 0; foreach ($studentinfo as $stinfo) { $currentstudent++; if ($pbar != null) { $pbar->update($currentstudent, count($studentinfo), get_string('printing', 'mod_emarking') . ' ' . $stinfo->name); } if (!isset($stinfo->examfile) || !file_exists($stinfo->examfile)) { continue; } $printresult = emarking_print_file($printerinfo->name, $printerinfo->command, $stinfo->examfile, $debugprinting); if (!$printresult) { $debugprintingmsg .= 'Problems printing ' . $stinfo->examfile . '<hr>'; } else { $debugprintingmsg .= $printresult . '<hr>'; } } if ($CFG->debug || $debugprinting) { echo $debugprintingmsg; } // Notify everyone that the exam was printed. emarking_send_examprinted_notification($downloadexam, $course); $downloadexam->status = EMARKING_EXAM_PRINTED; $downloadexam->printdate = time(); $DB->update_record('emarking_exams', $downloadexam); // Add to Moodle log so some auditing can be done. \mod_emarking\event\exam_downloaded::create_from_exam($downloadexam, $context)->trigger(); return true; } $examfilename = emarking_clean_filename($course->shortname, true) . '_' . emarking_clean_filename($downloadexam->name, true); $zipdebugmsg = ''; if ($multiplepdfs) { $zip = new ZipArchive(); $zipfilename = $filedir . "/" . $examfilename . ".zip"; if ($zip->open($zipfilename, ZipArchive::CREATE) !== true) { throw new Exception('Could not create zip file'); } // Check if we have to print the students list. if ($downloadexam->printlist == 1) { $zip->addFile($studentlistpdffile); } // Add every student PDF to zip file. $currentstudent = 0; foreach ($studentinfo as $stinfo) { $currentstudent++; if ($pbar != null) { $pbar->update($currentstudent, count($studentinfo), get_string('printing', 'mod_emarking') . ' ' . $stinfo->name); } if (!isset($stinfo->examfile) || !file_exists($stinfo->examfile)) { continue; } if (!$zip->addFile($stinfo->examfile, $stinfo->pdffilename . '.pdf')) { $zipdebugmsg .= "Problems adding {$stinfo->examfile} to ZIP file using name {$stinfo->pdffilename} <hr>"; } } $zip->close(); if ($CFG->debug || $debugprinting) { echo $zipdebugmsg; } // Notify everyone that the exam was downloaded. emarking_send_examdownloaded_notification($downloadexam, $course, $USER); $downloadexam->status = EMARKING_EXAM_SENT_TO_PRINT; $downloadexam->printdate = time(); $DB->update_record('emarking_exams', $downloadexam); // Add to Moodle log so some auditing can be done. \mod_emarking\event\exam_downloaded::create_from_exam($downloadexam, $context)->trigger(); // Read zip file from disk and send to the browser. $filename = basename($zipfilename); header("Content-Type: application/zip"); header("Content-Disposition: attachment; filename=" . $examfilename . ".zip"); header("Content-Length: " . filesize($zipfilename)); readfile($zipfilename); exit; } // We create the final big PDF file. $pdf = new FPDI(); $pdf->SetPrintHeader(false); $pdf->SetPrintFooter(false); // We import the students list if required. if ($downloadexam->printlist) { emarking_import_pdf_into_pdf($pdf, $studentlistpdffile); } // Add every student PDF to zip file. $currentstudent = 0; foreach ($studentinfo as $stinfo) { $currentstudent++; if (!isset($stinfo->examfile) || !file_exists($stinfo->examfile)) { continue; } emarking_import_pdf_into_pdf($pdf, $stinfo->examfile); } if ($savetofile) { $savedfile = $filedir . '/' . $examfilename . '.pdf'; $pdf->Output($savedfile, 'F'); $requestedby = $DB->get_record('user', array('id' => $downloadexam->requestedby)); // Copy file from temp folder to Moodle's filesystem. $filerecord = array('contextid' => $context->id, 'component' => 'mod_emarking', 'filearea' => 'examstoprint', 'itemid' => $downloadexam->emarking, 'filepath' => '/', 'filename' => $examfilename . '.pdf', 'timecreated' => time(), 'timemodified' => time(), 'userid' => $requestedby->id, 'author' => $requestedby->firstname . ' ' . $requestedby->lastname, 'license' => 'allrightsreserved'); // Filesystem. $fs = get_file_storage(); // If the file already exists we delete it. if ($fs->file_exists($context->id, 'mod_emarking', 'examstoprint', $downloadexam->emarking, '/', $examfilename . '.pdf')) { $previousfile = $fs->get_file($context->id, 'mod_emarking', 'examstoprint', $downloadexam->emarking, '/', $examfilename . '.pdf'); $previousfile->delete(); } // Info for the new file. $fileinfo = $fs->create_file_from_pathname($filerecord, $filedir . '/' . $examfilename . '.pdf'); // Notify everyone that the exam was downloaded. emarking_send_examgenerated_notification($downloadexam, $course, $requestedby); $downloadexam->status = EMARKING_EXAM_SENT_TO_PRINT; $downloadexam->printdate = time(); $downloadexam->filetoprint = $fileinfo->get_id(); $DB->update_record('emarking_exams', $downloadexam); // Add to Moodle log so some auditing can be done. \mod_emarking\event\exam_downloaded::create_from_exam($downloadexam, $context)->trigger(); return true; } else { // Notify everyone that the exam was downloaded. emarking_send_examdownloaded_notification($downloadexam, $course, $USER); $downloadexam->status = EMARKING_EXAM_SENT_TO_PRINT; $downloadexam->printdate = time(); $DB->update_record('emarking_exams', $downloadexam); // Add to Moodle log so some auditing can be done. \mod_emarking\event\exam_downloaded::create_from_exam($downloadexam, $context)->trigger(); $pdf->Output($examfilename . '.pdf', 'D'); } }
// A token was sent to validate download it will have 5 digits, otherwise it should be 0. if ($token > 9999 && $_SESSION[$USER->sesskey . "smstoken"] === $token) { $now = new DateTime(); $tokendate = new DateTime(); $tokendate->setTimestamp($_SESSION[$USER->sesskey . "smsdate"]); $diff = $now->diff($tokendate); if ($diff->i > 5 && false) { echo $OUTPUT->header(); echo $OUTPUT->notification(get_string("tokenexpired", "mod_emarking"), "notifyproblem"); $buttonurl = $incourse ? $courseurl : $coursecategoryurl; echo $OUTPUT->single_button($buttonurl, get_string("back"), "get"); echo $OUTPUT->footer(); die; } // Add to Moodle log so some auditing can be done. \mod_emarking\event\exam_downloaded::create_from_exam($exam, $contextcourse)->trigger(); // Get all the files uploaded as forms for this exam. $fs = get_file_storage(); $files = $fs->get_area_files($contextcourse->id, 'mod_emarking', 'examstoprint', $exam->emarking); // We filter only the PDFs. $pdffilename = NULL; foreach ($files as $filepdf) { if ($filepdf->get_mimetype() === 'application/pdf') { $pdffilename = $filepdf->get_filename(); } } // Verify that at least we have a PDF. if (!$pdffilename) { throw new Exception(get_string("examhasnopdf", "mod_emarking")); } redirect($CFG->wwwroot . '/pluginfile.php/' . $contextcourse->id . '/mod_emarking/examstoprint/' . $exam->emarking . '/' . $pdffilename . '?token=' . $token);