MDL-28284 don't load filepicker module for every page
[moodle.git] / pluginfile.php
blobe9e83db506bf93460616916a42a808ec410bba78
1 <?php
3 // This file is part of Moodle - http://moodle.org/
4 //
5 // Moodle is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
18 /**
19 * This script delegates file serving to individual plugins
21 * @package core
22 * @subpackage file
23 * @copyright 2008 Petr Skoda (http://skodak.org)
24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 // disable moodle specific debug messages and any errors in output
28 //define('NO_DEBUG_DISPLAY', true);
29 //TODO: uncomment this once the file api stabilises a bit more
31 require_once('config.php');
32 require_once('lib/filelib.php');
34 $relativepath = get_file_argument();
35 $forcedownload = optional_param('forcedownload', 0, PARAM_BOOL);
37 // relative path must start with '/'
38 if (!$relativepath) {
39 print_error('invalidargorconf');
40 } else if ($relativepath[0] != '/') {
41 print_error('pathdoesnotstartslash');
44 // extract relative path components
45 $args = explode('/', ltrim($relativepath, '/'));
47 if (count($args) < 3) { // always at least context, component and filearea
48 print_error('invalidarguments');
51 $contextid = (int)array_shift($args);
52 $component = clean_param(array_shift($args), PARAM_SAFEDIR);
53 $filearea = clean_param(array_shift($args), PARAM_SAFEDIR);
55 list($context, $course, $cm) = get_context_info_array($contextid);
57 $fs = get_file_storage();
59 // ========================================================================================================================
60 if ($component === 'blog') {
61 // Blog file serving
62 if ($context->contextlevel != CONTEXT_SYSTEM) {
63 send_file_not_found();
65 if ($filearea !== 'attachment' and $filearea !== 'post') {
66 send_file_not_found();
69 if (empty($CFG->bloglevel)) {
70 print_error('siteblogdisable', 'blog');
73 if ($CFG->bloglevel < BLOG_GLOBAL_LEVEL) {
74 require_login();
75 if (isguestuser()) {
76 print_error('noguest');
78 if ($CFG->bloglevel == BLOG_USER_LEVEL) {
79 if ($USER->id != $entry->userid) {
80 send_file_not_found();
84 $entryid = (int)array_shift($args);
85 if (!$entry = $DB->get_record('post', array('module'=>'blog', 'id'=>$entryid))) {
86 send_file_not_found();
89 if ('publishstate' === 'public') {
90 if ($CFG->forcelogin) {
91 require_login();
94 } else if ('publishstate' === 'site') {
95 require_login();
96 //ok
97 } else if ('publishstate' === 'draft') {
98 require_login();
99 if ($USER->id != $entry->userid) {
100 send_file_not_found();
104 $filename = array_pop($args);
105 $filepath = $args ? '/'.implode('/', $args).'/' : '/';
107 if (!$file = $fs->get_file($context->id, $component, $filearea, $entryid, $filepath, $filename) or $file->is_directory()) {
108 send_file_not_found();
111 send_stored_file($file, 10*60, 0, true); // download MUST be forced - security!
113 // ========================================================================================================================
114 } else if ($component === 'grade') {
115 if (($filearea === 'outcome' or $filearea === 'scale') and $context->contextlevel == CONTEXT_SYSTEM) {
116 // Global gradebook files
117 if ($CFG->forcelogin) {
118 require_login();
121 $fullpath = "/$context->id/$component/$filearea/".implode('/', $args);
123 if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
124 send_file_not_found();
127 session_get_instance()->write_close(); // unlock session during fileserving
128 send_stored_file($file, 60*60, 0, $forcedownload);
130 } else if ($filearea === 'feedback' and $context->contextlevel == CONTEXT_COURSE) {
131 //TODO: nobody implemented this yet in grade edit form!!
132 send_file_not_found();
134 if ($CFG->forcelogin || $course->id != SITEID) {
135 require_login($course);
138 $fullpath = "/$context->id/$component/$filearea/".implode('/', $args);
140 if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
141 send_file_not_found();
144 session_get_instance()->write_close(); // unlock session during fileserving
145 send_stored_file($file, 60*60, 0, $forcedownload);
146 } else {
147 send_file_not_found();
150 // ========================================================================================================================
151 } else if ($component === 'tag') {
152 if ($filearea === 'description' and $context->contextlevel == CONTEXT_SYSTEM) {
154 // All tag descriptions are going to be public but we still need to respect forcelogin
155 if ($CFG->forcelogin) {
156 require_login();
159 $fullpath = "/$context->id/tag/description/".implode('/', $args);
161 if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
162 send_file_not_found();
165 session_get_instance()->write_close(); // unlock session during fileserving
166 send_stored_file($file, 60*60, 0, true);
168 } else {
169 send_file_not_found();
172 // ========================================================================================================================
173 } else if ($component === 'calendar') {
174 if ($filearea === 'event_description' and $context->contextlevel == CONTEXT_SYSTEM) {
176 // All events here are public the one requirement is that we respect forcelogin
177 if ($CFG->forcelogin) {
178 require_login();
181 // Get the event if from the args array
182 $eventid = array_shift($args);
184 // Load the event from the database
185 if (!$event = $DB->get_record('event', array('id'=>(int)$eventid, 'eventtype'=>'site'))) {
186 send_file_not_found();
188 // Check that we got an event and that it's userid is that of the user
190 // Get the file and serve if successful
191 $filename = array_pop($args);
192 $filepath = $args ? '/'.implode('/', $args).'/' : '/';
193 if (!$file = $fs->get_file($context->id, $component, $filearea, $eventid, $filepath, $filename) or $file->is_directory()) {
194 send_file_not_found();
197 session_get_instance()->write_close(); // unlock session during fileserving
198 send_stored_file($file, 60*60, 0, $forcedownload);
200 } else if ($filearea === 'event_description' and $context->contextlevel == CONTEXT_USER) {
202 // Must be logged in, if they are not then they obviously can't be this user
203 require_login();
205 // Don't want guests here, potentially saves a DB call
206 if (isguestuser()) {
207 send_file_not_found();
210 // Get the event if from the args array
211 $eventid = array_shift($args);
213 // Load the event from the database - user id must match
214 if (!$event = $DB->get_record('event', array('id'=>(int)$eventid, 'userid'=>$USER->id, 'eventtype'=>'user'))) {
215 send_file_not_found();
218 // Get the file and serve if successful
219 $filename = array_pop($args);
220 $filepath = $args ? '/'.implode('/', $args).'/' : '/';
221 if (!$file = $fs->get_file($context->id, $component, $filearea, $eventid, $filepath, $filename) or $file->is_directory()) {
222 send_file_not_found();
225 session_get_instance()->write_close(); // unlock session during fileserving
226 send_stored_file($file, 60*60, 0, $forcedownload);
228 } else if ($filearea === 'event_description' and $context->contextlevel == CONTEXT_COURSE) {
230 // Respect forcelogin and require login unless this is the site.... it probably
231 // should NEVER be the site
232 if ($CFG->forcelogin || $course->id != SITEID) {
233 require_login($course);
236 // Must be able to at least view the course
237 if (!is_enrolled($context) and !is_viewing($context)) {
238 //TODO: hmm, do we really want to block guests here?
239 send_file_not_found();
242 // Get the event id
243 $eventid = array_shift($args);
245 // Load the event from the database we need to check whether it is
246 // a) valid course event
247 // b) a group event
248 // Group events use the course context (there is no group context)
249 if (!$event = $DB->get_record('event', array('id'=>(int)$eventid, 'courseid'=>$course->id))) {
250 send_file_not_found();
253 // If its a group event require either membership of view all groups capability
254 if ($event->eventtype === 'group') {
255 if (!has_capability('moodle/site:accessallgroups', $context) && !groups_is_member($event->groupid, $USER->id)) {
256 send_file_not_found();
258 } else if ($event->eventtype === 'course') {
259 //ok
260 } else {
261 // some other type
262 send_file_not_found();
265 // If we get this far we can serve the file
266 $filename = array_pop($args);
267 $filepath = $args ? '/'.implode('/', $args).'/' : '/';
268 if (!$file = $fs->get_file($context->id, $component, $filearea, $eventid, $filepath, $filename) or $file->is_directory()) {
269 send_file_not_found();
272 session_get_instance()->write_close(); // unlock session during fileserving
273 send_stored_file($file, 60*60, 0, $forcedownload);
275 } else {
276 send_file_not_found();
279 // ========================================================================================================================
280 } else if ($component === 'user') {
281 if ($filearea === 'icon' and $context->contextlevel == CONTEXT_USER) {
282 // XXX: pix_url will initialize $PAGE, so we have to set up context here
283 // this temp hack should be fixed by better solution
284 $PAGE->set_context(get_system_context());
285 if (!empty($CFG->forcelogin) and !isloggedin()) {
286 // protect images if login required and not logged in;
287 // do not use require_login() because it is expensive and not suitable here anyway
288 redirect($OUTPUT->pix_url('u/f1'));
290 $filename = array_pop($args);
291 if ($filename !== 'f1' and $filename !== 'f2') {
292 redirect($OUTPUT->pix_url('u/f1'));
294 if (!$file = $fs->get_file($context->id, 'user', 'icon', 0, '/', $filename.'/.png')) {
295 if (!$file = $fs->get_file($context->id, 'user', 'icon', 0, '/', $filename.'/.jpg')) {
296 redirect($OUTPUT->pix_url('u/'.$filename));
300 send_stored_file($file, 60*60*24); // enable long caching, there are many images on each page
302 } else if ($filearea === 'private' and $context->contextlevel == CONTEXT_USER) {
303 require_login();
305 if (isguestuser()) {
306 send_file_not_found();
309 if ($USER->id !== $context->instanceid) {
310 send_file_not_found();
313 $filename = array_pop($args);
314 $filepath = $args ? '/'.implode('/', $args).'/' : '/';
315 if (!$file = $fs->get_file($context->id, $component, $filearea, 0, $filepath, $filename) or $file->is_directory()) {
316 send_file_not_found();
319 session_get_instance()->write_close(); // unlock session during fileserving
320 send_stored_file($file, 0, 0, true); // must force download - security!
322 } else if ($filearea === 'profile' and $context->contextlevel == CONTEXT_USER) {
324 if ($CFG->forcelogin) {
325 require_login();
328 $userid = $context->instanceid;
330 if ($USER->id == $userid) {
331 // always can access own
333 } else if (!empty($CFG->forceloginforprofiles)) {
334 require_login();
336 if (isguestuser()) {
337 send_file_not_found();
340 // we allow access to site profile of all course contacts (usually teachers)
341 if (!has_coursecontact_role($userid) && !has_capability('moodle/user:viewdetails', $context)) {
342 send_file_not_found();
345 $canview = false;
346 if (has_capability('moodle/user:viewdetails', $context)) {
347 $canview = true;
348 } else {
349 $courses = enrol_get_my_courses();
352 while (!$canview && count($courses) > 0) {
353 $course = array_shift($courses);
354 if (has_capability('moodle/user:viewdetails', get_context_instance(CONTEXT_COURSE, $course->id))) {
355 $canview = true;
360 $filename = array_pop($args);
361 $filepath = $args ? '/'.implode('/', $args).'/' : '/';
362 if (!$file = $fs->get_file($context->id, $component, $filearea, 0, $filepath, $filename) or $file->is_directory()) {
363 send_file_not_found();
366 session_get_instance()->write_close(); // unlock session during fileserving
367 send_stored_file($file, 0, 0, true); // must force download - security!
369 } else if ($filearea === 'profile' and $context->contextlevel == CONTEXT_COURSE) {
370 $userid = (int)array_shift($args);
371 $usercontext = get_context_instance(CONTEXT_USER, $userid);
373 if ($CFG->forcelogin) {
374 require_login();
377 if (!empty($CFG->forceloginforprofiles)) {
378 require_login();
379 if (isguestuser()) {
380 print_error('noguest');
383 //TODO: review this logic of user profile access prevention
384 if (!has_coursecontact_role($userid) and !has_capability('moodle/user:viewdetails', $usercontext)) {
385 print_error('usernotavailable');
387 if (!has_capability('moodle/user:viewdetails', $context) && !has_capability('moodle/user:viewdetails', $usercontext)) {
388 print_error('cannotviewprofile');
390 if (!is_enrolled($context, $userid)) {
391 print_error('notenrolledprofile');
393 if (groups_get_course_groupmode($course) == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)) {
394 print_error('groupnotamember');
398 $filename = array_pop($args);
399 $filepath = $args ? '/'.implode('/', $args).'/' : '/';
400 if (!$file = $fs->get_file($usercontext->id, 'user', 'profile', 0, $filepath, $filename) or $file->is_directory()) {
401 send_file_not_found();
404 session_get_instance()->write_close(); // unlock session during fileserving
405 send_stored_file($file, 0, 0, true); // must force download - security!
407 } else if ($filearea === 'backup' and $context->contextlevel == CONTEXT_USER) {
408 require_login();
410 if (isguestuser()) {
411 send_file_not_found();
413 $userid = $context->instanceid;
415 if ($USER->id != $userid) {
416 send_file_not_found();
419 $filename = array_pop($args);
420 $filepath = $args ? '/'.implode('/', $args).'/' : '/';
421 if (!$file = $fs->get_file($context->id, 'user', 'backup', 0, $filepath, $filename) or $file->is_directory()) {
422 send_file_not_found();
425 session_get_instance()->write_close(); // unlock session during fileserving
426 send_stored_file($file, 0, 0, true); // must force download - security!
428 } else {
429 send_file_not_found();
432 // ========================================================================================================================
433 } else if ($component === 'coursecat') {
434 if ($context->contextlevel != CONTEXT_COURSECAT) {
435 send_file_not_found();
438 if ($filearea === 'description') {
439 if ($CFG->forcelogin) {
440 // no login necessary - unless login forced everywhere
441 require_login();
444 $filename = array_pop($args);
445 $filepath = $args ? '/'.implode('/', $args).'/' : '/';
446 if (!$file = $fs->get_file($context->id, 'coursecat', 'description', 0, $filepath, $filename) or $file->is_directory()) {
447 send_file_not_found();
450 session_get_instance()->write_close(); // unlock session during fileserving
451 send_stored_file($file, 60*60, 0, $forcedownload);
452 } else {
453 send_file_not_found();
456 // ========================================================================================================================
457 } else if ($component === 'course') {
458 if ($context->contextlevel != CONTEXT_COURSE) {
459 send_file_not_found();
462 if ($filearea === 'summary') {
463 if ($CFG->forcelogin) {
464 require_login();
467 $filename = array_pop($args);
468 $filepath = $args ? '/'.implode('/', $args).'/' : '/';
469 if (!$file = $fs->get_file($context->id, 'course', 'summary', 0, $filepath, $filename) or $file->is_directory()) {
470 send_file_not_found();
473 session_get_instance()->write_close(); // unlock session during fileserving
474 send_stored_file($file, 60*60, 0, $forcedownload);
476 } else if ($filearea === 'section') {
477 if ($CFG->forcelogin) {
478 require_login($course);
479 } else if ($course->id != SITEID) {
480 require_login($course);
483 $sectionid = (int)array_shift($args);
485 if (!$section = $DB->get_record('course_sections', array('id'=>$sectionid, 'course'=>$course->id))) {
486 send_file_not_found();
489 if ($course->numsections < $section->section) {
490 if (!has_capability('moodle/course:update', $context)) {
491 // block access to unavailable sections if can not edit course
492 send_file_not_found();
496 $filename = array_pop($args);
497 $filepath = $args ? '/'.implode('/', $args).'/' : '/';
498 if (!$file = $fs->get_file($context->id, 'course', 'section', $sectionid, $filepath, $filename) or $file->is_directory()) {
499 send_file_not_found();
502 session_get_instance()->write_close(); // unlock session during fileserving
503 send_stored_file($file, 60*60, 0, $forcedownload);
505 } else {
506 send_file_not_found();
509 } else if ($component === 'group') {
510 if ($context->contextlevel != CONTEXT_COURSE) {
511 send_file_not_found();
514 require_course_login($course, true, null, false);
516 $groupid = (int)array_shift($args);
518 $group = $DB->get_record('groups', array('id'=>$groupid, 'courseid'=>$course->id), '*', MUST_EXIST);
519 if (($course->groupmodeforce and $course->groupmode == SEPARATEGROUPS) and !has_capability('moodle/site:accessallgroups', $context) and !groups_is_member($group->id, $USER->id)) {
520 // do not allow access to separate group info if not member or teacher
521 send_file_not_found();
524 if ($filearea === 'description') {
526 require_login($course);
528 $filename = array_pop($args);
529 $filepath = $args ? '/'.implode('/', $args).'/' : '/';
530 if (!$file = $fs->get_file($context->id, 'group', 'description', $group->id, $filepath, $filename) or $file->is_directory()) {
531 send_file_not_found();
534 session_get_instance()->write_close(); // unlock session during fileserving
535 send_stored_file($file, 60*60, 0, $forcedownload);
537 } else if ($filearea === 'icon') {
538 $filename = array_pop($args);
540 if ($filename !== 'f1' and $filename !== 'f2') {
541 send_file_not_found();
543 if (!$file = $fs->get_file($context->id, 'group', 'icon', $group->id, '/', $filename.'.png')) {
544 if (!$file = $fs->get_file($context->id, 'group', 'icon', $group->id, '/', $filename.'.jpg')) {
545 send_file_not_found();
549 session_get_instance()->write_close(); // unlock session during fileserving
550 send_stored_file($file, 60*60);
552 } else {
553 send_file_not_found();
556 } else if ($component === 'grouping') {
557 if ($context->contextlevel != CONTEXT_COURSE) {
558 send_file_not_found();
561 require_login($course);
563 $groupingid = (int)array_shift($args);
565 // note: everybody has access to grouping desc images for now
566 if ($filearea === 'description') {
568 $filename = array_pop($args);
569 $filepath = $args ? '/'.implode('/', $args).'/' : '/';
570 if (!$file = $fs->get_file($context->id, 'grouping', 'description', $groupingid, $filepath, $filename) or $file->is_directory()) {
571 send_file_not_found();
574 session_get_instance()->write_close(); // unlock session during fileserving
575 send_stored_file($file, 60*60, 0, $forcedownload);
577 } else {
578 send_file_not_found();
581 // ========================================================================================================================
582 } else if ($component === 'backup') {
583 if ($filearea === 'course' and $context->contextlevel == CONTEXT_COURSE) {
584 require_login($course);
585 require_capability('moodle/backup:downloadfile', $context);
587 $filename = array_pop($args);
588 $filepath = $args ? '/'.implode('/', $args).'/' : '/';
589 if (!$file = $fs->get_file($context->id, 'backup', 'course', 0, $filepath, $filename) or $file->is_directory()) {
590 send_file_not_found();
593 session_get_instance()->write_close(); // unlock session during fileserving
594 send_stored_file($file, 0, 0, $forcedownload);
596 } else if ($filearea === 'section' and $context->contextlevel == CONTEXT_COURSE) {
597 require_login($course);
598 require_capability('moodle/backup:downloadfile', $context);
600 $sectionid = (int)array_shift($args);
602 $filename = array_pop($args);
603 $filepath = $args ? '/'.implode('/', $args).'/' : '/';
604 if (!$file = $fs->get_file($context->id, 'backup', 'section', $sectionid, $filepath, $filename) or $file->is_directory()) {
605 send_file_not_found();
608 session_get_instance()->write_close();
609 send_stored_file($file, 60*60, 0, $forcedownload);
611 } else if ($filearea === 'activity' and $context->contextlevel == CONTEXT_MODULE) {
612 require_login($course, false, $cm);
613 require_capability('moodle/backup:downloadfile', $context);
615 $filename = array_pop($args);
616 $filepath = $args ? '/'.implode('/', $args).'/' : '/';
617 if (!$file = $fs->get_file($context->id, 'backup', 'activity', 0, $filepath, $filename) or $file->is_directory()) {
618 send_file_not_found();
621 session_get_instance()->write_close();
622 send_stored_file($file, 60*60, 0, $forcedownload);
624 } else if ($filearea === 'automated' and $context->contextlevel == CONTEXT_COURSE) {
625 // Backup files that were generated by the automated backup systems.
627 require_login($course);
628 require_capability('moodle/site:config', $context);
630 $filename = array_pop($args);
631 $filepath = $args ? '/'.implode('/', $args).'/' : '/';
632 if (!$file = $fs->get_file($context->id, 'backup', 'automated', 0, $filepath, $filename) or $file->is_directory()) {
633 send_file_not_found();
636 session_get_instance()->write_close(); // unlock session during fileserving
637 send_stored_file($file, 0, 0, $forcedownload);
639 } else {
640 send_file_not_found();
643 // ========================================================================================================================
644 } else if ($component === 'question') {
645 require_once($CFG->libdir . '/questionlib.php');
646 question_pluginfile($course, $context, 'question', $filearea, $args, $forcedownload);
647 send_file_not_found();
649 // ========================================================================================================================
650 } else if (strpos($component, 'mod_') === 0) {
651 $modname = substr($component, 4);
652 if (!file_exists("$CFG->dirroot/mod/$modname/lib.php")) {
653 send_file_not_found();
655 require_once("$CFG->dirroot/mod/$modname/lib.php");
657 if ($context->contextlevel == CONTEXT_MODULE) {
658 if ($cm->modname !== $modname) {
659 // somebody tries to gain illegal access, cm type must match the component!
660 send_file_not_found();
664 if ($filearea === 'intro') {
665 if (!plugin_supports('mod', $modname, FEATURE_MOD_INTRO, true)) {
666 send_file_not_found();
668 require_course_login($course, true, $cm);
670 // all users may access it
671 $filename = array_pop($args);
672 $filepath = $args ? '/'.implode('/', $args).'/' : '/';
673 if (!$file = $fs->get_file($context->id, 'mod_'.$modname, 'intro', 0, $filepath, $filename) or $file->is_directory()) {
674 send_file_not_found();
677 $lifetime = isset($CFG->filelifetime) ? $CFG->filelifetime : 86400;
679 // finally send the file
680 send_stored_file($file, $lifetime, 0);
683 $filefunction = $component.'_pluginfile';
684 $filefunctionold = $modname.'_pluginfile';
685 if (function_exists($filefunction)) {
686 // if the function exists, it must send the file and terminate. Whatever it returns leads to "not found"
687 $filefunction($course, $cm, $context, $filearea, $args, $forcedownload);
688 } else if (function_exists($filefunctionold)) {
689 // if the function exists, it must send the file and terminate. Whatever it returns leads to "not found"
690 $filefunctionold($course, $cm, $context, $filearea, $args, $forcedownload);
693 send_file_not_found();
695 // ========================================================================================================================
696 } else if (strpos($component, 'block_') === 0) {
697 $blockname = substr($component, 6);
698 // note: no more class methods in blocks please, that is ....
699 if (!file_exists("$CFG->dirroot/blocks/$blockname/lib.php")) {
700 send_file_not_found();
702 require_once("$CFG->dirroot/blocks/$blockname/lib.php");
704 if ($context->contextlevel == CONTEXT_BLOCK) {
705 $birecord = $DB->get_record('block_instances', array('id'=>$context->instanceid), '*',MUST_EXIST);
706 if ($birecord->blockname !== $blockname) {
707 // somebody tries to gain illegal access, cm type must match the component!
708 send_file_not_found();
710 } else {
711 $birecord = null;
714 $filefunction = $component.'_pluginfile';
715 if (function_exists($filefunction)) {
716 // if the function exists, it must send the file and terminate. Whatever it returns leads to "not found"
717 $filefunction($course, $birecord, $context, $filearea, $args, $forcedownload);
720 send_file_not_found();
722 } else if (strpos($component, '_') === false) {
723 // all core subsystems have to be specified above, no more guessing here!
724 send_file_not_found();
726 } else {
727 // try to serve general plugin file in arbitrary context
728 $dir = get_component_directory($component);
729 if (!file_exists("$dir/lib.php")) {
730 send_file_not_found();
732 include_once("$dir/lib.php");
734 $filefunction = $component.'_pluginfile';
735 if (function_exists($filefunction)) {
736 // if the function exists, it must send the file and terminate. Whatever it returns leads to "not found"
737 $filefunction($course, $cm, $context, $filearea, $args, $forcedownload);
740 send_file_not_found();