Merge branch 'MDL-25657' of git://git.luns.net.uk/moodle
[moodle.git] / pluginfile.php
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.
14 //
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
20  *
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
25  */
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');
42 }
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');
49 }
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 // If the file is a Flash file and that the user flash player is outdated return a flash upgrader MDL-20841
60 $mimetype = mimeinfo('type', $args[count($args)-1]);
61 if (!empty($CFG->excludeoldflashclients) && $mimetype == 'application/x-shockwave-flash'&& !empty($SESSION->flashversion)) {
62     $userplayerversion = explode('.', $SESSION->flashversion);
63     $requiredplayerversion = explode('.', $CFG->excludeoldflashclients);
64     if (($userplayerversion[0] <  $requiredplayerversion[0]) ||
65         ($userplayerversion[0] == $requiredplayerversion[0] && $userplayerversion[1] < $requiredplayerversion[1]) ||
66         ($userplayerversion[0] == $requiredplayerversion[0] && $userplayerversion[1] == $requiredplayerversion[1]
67          && $userplayerversion[2] < $requiredplayerversion[2])) {
68         $path = $CFG->dirroot."/lib/flashdetect/flashupgrade.swf";  // Alternate content asking user to upgrade Flash
69         $filename = "flashupgrade.swf";
70         send_file($path, $filename, O, 0, false, false, 'application/x-shockwave-flash'); // Do not cache
71     }
72 }
74 // ========================================================================================================================
75 if ($component === 'blog') {
76     // Blog file serving
77     if ($context->contextlevel != CONTEXT_SYSTEM) {
78         send_file_not_found();
79     }
80     if ($filearea !== 'attachment' and $filearea !== 'post') {
81         send_file_not_found();
82     }
84     if (empty($CFG->bloglevel)) {
85         print_error('siteblogdisable', 'blog');
86     }
88     if ($CFG->bloglevel < BLOG_GLOBAL_LEVEL) {
89         require_login();
90         if (isguestuser()) {
91             print_error('noguest');
92         }
93         if ($CFG->bloglevel == BLOG_USER_LEVEL) {
94             if ($USER->id != $entry->userid) {
95                 send_file_not_found();
96             }
97         }
98     }
99     $entryid = (int)array_shift($args);
100     if (!$entry = $DB->get_record('post', array('module'=>'blog', 'id'=>$entryid))) {
101         send_file_not_found();
102     }
104     if ('publishstate' === 'public') {
105         if ($CFG->forcelogin) {
106             require_login();
107         }
109     } else if ('publishstate' === 'site') {
110         require_login();
111         //ok
112     } else if ('publishstate' === 'draft') {
113         require_login();
114         if ($USER->id != $entry->userid) {
115             send_file_not_found();
116         }
117     }
119     $filename = array_pop($args);
120     $filepath = $args ? '/'.implode('/', $args).'/' : '/';
122     if (!$file = $fs->get_file($context->id, $component, $filearea, $entryid, $filepath, $filename) or $file->is_directory()) {
123         send_file_not_found();
124     }
126     send_stored_file($file, 10*60, 0, true); // download MUST be forced - security!
128 // ========================================================================================================================
129 } else if ($component === 'grade') {
130     if (($filearea === 'outcome' or $filearea === 'scale') and $context->contextlevel == CONTEXT_SYSTEM) {
131         // Global gradebook files
132         if ($CFG->forcelogin) {
133             require_login();
134         }
136         $fullpath = "/$context->id/$component/$filearea/".implode('/', $args);
138         if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
139             send_file_not_found();
140         }
142         session_get_instance()->write_close(); // unlock session during fileserving
143         send_stored_file($file, 60*60, 0, $forcedownload);
145     } else if ($filearea === 'feedback' and $context->contextlevel == CONTEXT_COURSE) {
146         //TODO: nobody implemented this yet in grade edit form!!
147         send_file_not_found();
149         if ($CFG->forcelogin || $course->id != SITEID) {
150             require_login($course);
151         }
153         $fullpath = "/$context->id/$component/$filearea/".implode('/', $args);
155         if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
156             send_file_not_found();
157         }
159         session_get_instance()->write_close(); // unlock session during fileserving
160         send_stored_file($file, 60*60, 0, $forcedownload);
161     } else {
162         send_file_not_found();
163     }
165 // ========================================================================================================================
166 } else if ($component === 'tag') {
167     if ($filearea === 'description' and $context->contextlevel == CONTEXT_SYSTEM) {
169         // All tag descriptions are going to be public but we still need to respect forcelogin
170         if ($CFG->forcelogin) {
171             require_login();
172         }
174         $fullpath = "/$context->id/tag/description/".implode('/', $args);
176         if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
177             send_file_not_found();
178         }
180         session_get_instance()->write_close(); // unlock session during fileserving
181         send_stored_file($file, 60*60, 0, true);
183     } else {
184         send_file_not_found();
185     }
187 // ========================================================================================================================
188 } else if ($component === 'calendar') {
189     if ($filearea === 'event_description'  and $context->contextlevel == CONTEXT_SYSTEM) {
191         // All events here are public the one requirement is that we respect forcelogin
192         if ($CFG->forcelogin) {
193             require_login();
194         }
196         // Get the event if from the args array
197         $eventid = array_shift($args);
199         // Load the event from the database
200         if (!$event = $DB->get_record('event', array('id'=>(int)$eventid, 'eventtype'=>'site'))) {
201             send_file_not_found();
202         }
203         // Check that we got an event and that it's userid is that of the user
205         // Get the file and serve if successful
206         $filename = array_pop($args);
207         $filepath = $args ? '/'.implode('/', $args).'/' : '/';
208         if (!$file = $fs->get_file($context->id, $component, $filearea, $eventid, $filepath, $filename) or $file->is_directory()) {
209             send_file_not_found();
210         }
212         session_get_instance()->write_close(); // unlock session during fileserving
213         send_stored_file($file, 60*60, 0, $forcedownload);
215     } else if ($filearea === 'event_description' and $context->contextlevel == CONTEXT_USER) {
217         // Must be logged in, if they are not then they obviously can't be this user
218         require_login();
220         // Don't want guests here, potentially saves a DB call
221         if (isguestuser()) {
222             send_file_not_found();
223         }
225         // Get the event if from the args array
226         $eventid = array_shift($args);
228         // Load the event from the database - user id must match
229         if (!$event = $DB->get_record('event', array('id'=>(int)$eventid, 'userid'=>$USER->id, 'eventtype'=>'user'))) {
230             send_file_not_found();
231         }
233         // Get the file and serve if successful
234         $filename = array_pop($args);
235         $filepath = $args ? '/'.implode('/', $args).'/' : '/';
236         if (!$file = $fs->get_file($context->id, $component, $filearea, $eventid, $filepath, $filename) or $file->is_directory()) {
237             send_file_not_found();
238         }
240         session_get_instance()->write_close(); // unlock session during fileserving
241         send_stored_file($file, 60*60, 0, $forcedownload);
243     } else if ($filearea === 'event_description' and $context->contextlevel == CONTEXT_COURSE) {
245         // Respect forcelogin and require login unless this is the site.... it probably
246         // should NEVER be the site
247         if ($CFG->forcelogin || $course->id != SITEID) {
248             require_login($course);
249         }
251         // Must be able to at least view the course
252         if (!is_enrolled($context) and !is_viewing($context)) {
253             //TODO: hmm, do we really want to block guests here?
254             send_file_not_found();
255         }
257         // Get the event id
258         $eventid = array_shift($args);
260         // Load the event from the database we need to check whether it is
261         // a) valid course event
262         // b) a group event
263         // Group events use the course context (there is no group context)
264         if (!$event = $DB->get_record('event', array('id'=>(int)$eventid, 'courseid'=>$course->id))) {
265             send_file_not_found();
266         }
268         // If its a group event require either membership of view all groups capability
269         if ($event->eventtype === 'group') {
270             if (!has_capability('moodle/site:accessallgroups', $context) && !groups_is_member($event->groupid, $USER->id)) {
271                 send_file_not_found();
272             }
273         } else if ($event->eventtype === 'course') {
274             //ok
275         } else {
276             // some other type
277             send_file_not_found();
278         }
280         // If we get this far we can serve the file
281         $filename = array_pop($args);
282         $filepath = $args ? '/'.implode('/', $args).'/' : '/';
283         if (!$file = $fs->get_file($context->id, $component, $filearea, $eventid, $filepath, $filename) or $file->is_directory()) {
284             send_file_not_found();
285         }
287         session_get_instance()->write_close(); // unlock session during fileserving
288         send_stored_file($file, 60*60, 0, $forcedownload);
290     } else {
291         send_file_not_found();
292     }
294 // ========================================================================================================================
295 } else if ($component === 'user') {
296     if ($filearea === 'icon' and $context->contextlevel == CONTEXT_USER) {
297         if (!empty($CFG->forcelogin) and !isloggedin()) {
298             // protect images if login required and not logged in;
299             // do not use require_login() because it is expensive and not suitable here anyway
300             redirect($OUTPUT->pix_url('u/f1'));
301         }
302         $filename = array_pop($args);
303         if ($filename !== 'f1' and $filename !== 'f2') {
304             redirect($OUTPUT->pix_url('u/f1'));
305         }
306         if (!$file = $fs->get_file($context->id, 'user', 'icon', 0, '/', $filename.'/.png')) {
307             if (!$file = $fs->get_file($context->id, 'user', 'icon', 0, '/', $filename.'/.jpg')) {
308                 redirect($OUTPUT->pix_url('u/f1'));
309             }
310         }
312         send_stored_file($file, 60*60*24); // enable long caching, there are many images on each page
314     } else if ($filearea === 'private' and $context->contextlevel == CONTEXT_USER) {
315         require_login();
317         if (isguestuser()) {
318             send_file_not_found();
319         }
321         if ($USER->id !== $context->instanceid) {
322             send_file_not_found();
323         }
325         $filename = array_pop($args);
326         $filepath = $args ? '/'.implode('/', $args).'/' : '/';
327         if (!$file = $fs->get_file($context->id, $component, $filearea, 0, $filepath, $filename) or $file->is_directory()) {
328             send_file_not_found();
329         }
331         session_get_instance()->write_close(); // unlock session during fileserving
332         send_stored_file($file, 0, 0, true); // must force download - security!
334     } else if ($filearea === 'profile' and $context->contextlevel == CONTEXT_USER) {
336         if ($CFG->forcelogin) {
337             require_login();
338         }
340         $userid = $context->instanceid;
342         if ($USER->id == $userid) {
343             // always can access own
345         } else if (!empty($CFG->forceloginforprofiles)) {
346             require_login();
348             if (isguestuser()) {
349                 send_file_not_found();
350             }
352             // we allow access to site profile of all course contacts (usually teachers)
353             if (!has_coursecontact_role($userid) && !has_capability('moodle/user:viewdetails', $context)) {
354                 send_file_not_found();
355             }
357             $canview = false;
358             if (has_capability('moodle/user:viewdetails', $context)) {
359                 $canview = true;
360             } else {
361                 $courses = enrol_get_my_courses();
362             }
364             while (!$canview && count($courses) > 0) {
365                 $course = array_shift($courses);
366                 if (has_capability('moodle/user:viewdetails', get_context_instance(CONTEXT_COURSE, $course->id))) {
367                     $canview = true;
368                 }
369             }
370         }
372         $filename = array_pop($args);
373         $filepath = $args ? '/'.implode('/', $args).'/' : '/';
374         if (!$file = $fs->get_file($context->id, $component, $filearea, 0, $filepath, $filename) or $file->is_directory()) {
375             send_file_not_found();
376         }
378         session_get_instance()->write_close(); // unlock session during fileserving
379         send_stored_file($file, 0, 0, true); // must force download - security!
381     } else if ($filearea === 'profile' and $context->contextlevel == CONTEXT_COURSE) {
382         $userid = (int)array_shift($args);
383         $usercontext = get_context_instance(CONTEXT_USER, $userid);
385         if ($CFG->forcelogin) {
386             require_login();
387         }
389         if (!empty($CFG->forceloginforprofiles)) {
390             require_login();
391             if (isguestuser()) {
392                 print_error('noguest');
393             }
395             //TODO: review this logic of user profile access prevention
396             if (!has_coursecontact_role($userid) and !has_capability('moodle/user:viewdetails', $usercontext)) {
397                 print_error('usernotavailable');
398             }
399             if (!has_capability('moodle/user:viewdetails', $context) && !has_capability('moodle/user:viewdetails', $usercontext)) {
400                 print_error('cannotviewprofile');
401             }
402             if (!is_enrolled($context, $userid)) {
403                 print_error('notenrolledprofile');
404             }
405             if (groups_get_course_groupmode($course) == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)) {
406                 print_error('groupnotamember');
407             }
408         }
410         $filename = array_pop($args);
411         $filepath = $args ? '/'.implode('/', $args).'/' : '/';
412         if (!$file = $fs->get_file($usercontext->id, 'user', 'profile', 0, $filepath, $filename) or $file->is_directory()) {
413             send_file_not_found();
414         }
416         session_get_instance()->write_close(); // unlock session during fileserving
417         send_stored_file($file, 0, 0, true); // must force download - security!
419     } else if ($filearea === 'backup' and $context->contextlevel == CONTEXT_USER) {
420         require_login();
422         if (isguestuser()) {
423             send_file_not_found();
424         }
425         $userid = $context->instanceid;
427         if ($USER->id != $userid) {
428             send_file_not_found();
429         }
431         $filename = array_pop($args);
432         $filepath = $args ? '/'.implode('/', $args).'/' : '/';
433         if (!$file = $fs->get_file($context->id, 'user', 'backup', 0, $filepath, $filename) or $file->is_directory()) {
434             send_file_not_found();
435         }
437         session_get_instance()->write_close(); // unlock session during fileserving
438         send_stored_file($file, 0, 0, true); // must force download - security!
440     } else {
441         send_file_not_found();
442     }
444 // ========================================================================================================================
445 } else if ($component === 'coursecat') {
446     if ($context->contextlevel != CONTEXT_COURSECAT) {
447         send_file_not_found();
448     }
450     if ($filearea === 'description') {
451         if ($CFG->forcelogin) {
452             // no login necessary - unless login forced everywhere
453             require_login();
454         }
456         $filename = array_pop($args);
457         $filepath = $args ? '/'.implode('/', $args).'/' : '/';
458         if (!$file = $fs->get_file($context->id, 'coursecat', 'description', 0, $filepath, $filename) or $file->is_directory()) {
459             send_file_not_found();
460         }
462         session_get_instance()->write_close(); // unlock session during fileserving
463         send_stored_file($file, 60*60, 0, $forcedownload);
464     } else {
465         send_file_not_found();
466     }
468 // ========================================================================================================================
469 } else if ($component === 'course') {
470     if ($context->contextlevel != CONTEXT_COURSE) {
471         send_file_not_found();
472     }
474     if ($filearea === 'summary') {
475         if ($CFG->forcelogin) {
476             require_login();
477         }
479         $filename = array_pop($args);
480         $filepath = $args ? '/'.implode('/', $args).'/' : '/';
481         if (!$file = $fs->get_file($context->id, 'course', 'summary', 0, $filepath, $filename) or $file->is_directory()) {
482             send_file_not_found();
483         }
485         session_get_instance()->write_close(); // unlock session during fileserving
486         send_stored_file($file, 60*60, 0, $forcedownload);
488     } else if ($filearea === 'section') {
489         if ($CFG->forcelogin) {
490             require_login($course);
491         } else if ($course->id != SITEID) {
492             require_login($course);
493         }
495         $sectionid = (int)array_shift($args);
497         if (!$section = $DB->get_record('course_sections', array('id'=>$sectionid, 'course'=>$course->id))) {
498             send_file_not_found();
499         }
501         if ($course->numsections < $section->section) {
502             if (!has_capability('moodle/course:update', $context)) {
503                 // block access to unavailable sections if can not edit course
504                 send_file_not_found();
505             }
506         }
508         $filename = array_pop($args);
509         $filepath = $args ? '/'.implode('/', $args).'/' : '/';
510         if (!$file = $fs->get_file($context->id, 'course', 'section', $sectionid, $filepath, $filename) or $file->is_directory()) {
511             send_file_not_found();
512         }
514         session_get_instance()->write_close(); // unlock session during fileserving
515         send_stored_file($file, 60*60, 0, $forcedownload);
517     } else {
518         send_file_not_found();
519     }
521 } else if ($component === 'group') {
522     if ($context->contextlevel != CONTEXT_COURSE) {
523         send_file_not_found();
524     }
526     require_course_login($course, true, null, false);
528     $groupid = (int)array_shift($args);
530     $group = $DB->get_record('groups', array('id'=>$groupid, 'courseid'=>$course->id), '*', MUST_EXIST);
531     if (($course->groupmodeforce and $course->groupmode == SEPARATEGROUPS) and !has_capability('moodle/site:accessallgroups', $context) and !groups_is_member($group->id, $USER->id)) {
532         // do not allow access to separate group info if not member or teacher
533         send_file_not_found();
534     }
536     if ($filearea === 'description') {
538         require_login($course);
540         $filename = array_pop($args);
541         $filepath = $args ? '/'.implode('/', $args).'/' : '/';
542         if (!$file = $fs->get_file($context->id, 'group', 'description', $group->id, $filepath, $filename) or $file->is_directory()) {
543             send_file_not_found();
544         }
546         session_get_instance()->write_close(); // unlock session during fileserving
547         send_stored_file($file, 60*60, 0, $forcedownload);
549     } else if ($filearea === 'icon') {
550         $filename = array_pop($args);
552         if ($filename !== 'f1' and $filename !== 'f2') {
553             send_file_not_found();
554         }
555         if (!$file = $fs->get_file($context->id, 'group', 'icon', $group->id, '/', $filename.'.png')) {
556             if (!$file = $fs->get_file($context->id, 'group', 'icon', $group->id, '/', $filename.'.jpg')) {
557                 send_file_not_found();
558             }
559         }
561         session_get_instance()->write_close(); // unlock session during fileserving
562         send_stored_file($file, 60*60);
564     } else {
565         send_file_not_found();
566     }
568 } else if ($component === 'grouping') {
569     if ($context->contextlevel != CONTEXT_COURSE) {
570         send_file_not_found();
571     }
573     require_login($course);
575     $groupingid = (int)array_shift($args);
577     // note: everybody has access to grouping desc images for now
578     if ($filearea === 'description') {
580         $filename = array_pop($args);
581         $filepath = $args ? '/'.implode('/', $args).'/' : '/';
582         if (!$file = $fs->get_file($context->id, 'grouping', 'description', $groupingid, $filepath, $filename) or $file->is_directory()) {
583             send_file_not_found();
584         }
586         session_get_instance()->write_close(); // unlock session during fileserving
587         send_stored_file($file, 60*60, 0, $forcedownload);
589     } else {
590         send_file_not_found();
591     }
593 // ========================================================================================================================
594 } else if ($component === 'backup') {
595     if ($filearea === 'course' and $context->contextlevel == CONTEXT_COURSE) {
596         require_login($course);
597         require_capability('moodle/backup:downloadfile', $context);
599         $filename = array_pop($args);
600         $filepath = $args ? '/'.implode('/', $args).'/' : '/';
601         if (!$file = $fs->get_file($context->id, 'backup', 'course', 0, $filepath, $filename) or $file->is_directory()) {
602             send_file_not_found();
603         }
605         session_get_instance()->write_close(); // unlock session during fileserving
606         send_stored_file($file, 0, 0, $forcedownload);
608     } else if ($filearea === 'section' and $context->contextlevel == CONTEXT_COURSE) {
609         require_login($course);
610         require_capability('moodle/backup:downloadfile', $context);
612         $sectionid = (int)array_shift($args);
614         $filename = array_pop($args);
615         $filepath = $args ? '/'.implode('/', $args).'/' : '/';
616         if (!$file = $fs->get_file($context->id, 'backup', 'section', $sectionid, $filepath, $filename) or $file->is_directory()) {
617             send_file_not_found();
618         }
620         session_get_instance()->write_close();
621         send_stored_file($file, 60*60, 0, $forcedownload);
623     } else if ($filearea === 'activity' and $context->contextlevel == CONTEXT_MODULE) {
624         require_login($course, false, $cm);
625         require_capability('moodle/backup:downloadfile', $context);
627         $filename = array_pop($args);
628         $filepath = $args ? '/'.implode('/', $args).'/' : '/';
629         if (!$file = $fs->get_file($context->id, 'backup', 'activity', 0, $filepath, $filename) or $file->is_directory()) {
630             send_file_not_found();
631         }
633         session_get_instance()->write_close();
634         send_stored_file($file, 60*60, 0, $forcedownload);
636     } else if ($filearea === 'automated' and $context->contextlevel == CONTEXT_COURSE) {
637         // Backup files that were generated by the automated backup systems.
639         require_login($course);
640         require_capability('moodle/site:config', $context);
642         $filename = array_pop($args);
643         $filepath = $args ? '/'.implode('/', $args).'/' : '/';
644         if (!$file = $fs->get_file($context->id, 'backup', 'automated', 0, $filepath, $filename) or $file->is_directory()) {
645             send_file_not_found();
646         }
648         session_get_instance()->write_close(); // unlock session during fileserving
649         send_stored_file($file, 0, 0, $forcedownload);
651     } else {
652         send_file_not_found();
653     }
655 // ========================================================================================================================
656 } else if ($component === 'question') {
657     require_once($CFG->libdir . '/questionlib.php');
658     question_pluginfile($course, $context, 'question', $filearea, $args, $forcedownload);
659     send_file_not_found();
661 // ========================================================================================================================
662 } else if (strpos($component, 'mod_') === 0) {
663     $modname = substr($component, 4);
664     if (!file_exists("$CFG->dirroot/mod/$modname/lib.php")) {
665         send_file_not_found();
666     }
667     require_once("$CFG->dirroot/mod/$modname/lib.php");
669     if ($context->contextlevel == CONTEXT_MODULE) {
670         if ($cm->modname !== $modname) {
671             // somebody tries to gain illegal access, cm type must match the component!
672             send_file_not_found();
673         }
674     }
676     if ($filearea === 'intro') {
677         if (!plugin_supports('mod', $modname, FEATURE_MOD_INTRO, true)) {
678             send_file_not_found();
679         }
680         require_course_login($course, true, $cm);
682         // all users may access it
683         $filename = array_pop($args);
684         $filepath = $args ? '/'.implode('/', $args).'/' : '/';
685         if (!$file = $fs->get_file($context->id, 'mod_'.$modname, 'intro', 0, $filepath, $filename) or $file->is_directory()) {
686             send_file_not_found();
687         }
689         $lifetime = isset($CFG->filelifetime) ? $CFG->filelifetime : 86400;
691         // finally send the file
692         send_stored_file($file, $lifetime, 0);
693     }
695     $filefunction = $component.'_pluginfile';
696     $filefunctionold = $modname.'_pluginfile';
697     if (function_exists($filefunction)) {
698         // if the function exists, it must send the file and terminate. Whatever it returns leads to "not found"
699         $filefunction($course, $cm, $context, $filearea, $args, $forcedownload);
700     } else if (function_exists($filefunctionold)) {
701         // if the function exists, it must send the file and terminate. Whatever it returns leads to "not found"
702         $filefunctionold($course, $cm, $context, $filearea, $args, $forcedownload);
703     }
705     send_file_not_found();
707 // ========================================================================================================================
708 } else if (strpos($component, 'block_') === 0) {
709     $blockname = substr($component, 6);
710     // note: no more class methods in blocks please, that is ....
711     if (!file_exists("$CFG->dirroot/blocks/$blockname/lib.php")) {
712         send_file_not_found();
713     }
714     require_once("$CFG->dirroot/blocks/$blockname/lib.php");
716     if ($context->contextlevel == CONTEXT_BLOCK) {
717         $birecord = $DB->get_record('block_instances', array('id'=>$context->instanceid), '*',MUST_EXIST);
718         if ($birecord->blockname !== $blockname) {
719             // somebody tries to gain illegal access, cm type must match the component!
720             send_file_not_found();
721         }
722     } else {
723         $birecord = null;
724     }
726     $filefunction = $component.'_pluginfile';
727     if (function_exists($filefunction)) {
728         // if the function exists, it must send the file and terminate. Whatever it returns leads to "not found"
729         $filefunction($course, $birecord, $context, $filearea, $args, $forcedownload);
730     }
732     send_file_not_found();
734 } else if (strpos($component, '_') === false) {
735     // all core subsystems have to be specified above, no more guessing here!
736     send_file_not_found();
738 } else {
739     // try to serve general plugin file in arbitrary context
740     $dir = get_component_directory($component);
741     if (!file_exists("$dir/lib.php")) {
742         send_file_not_found();
743     }
744     include_once("$dir/lib.php");
746     $filefunction = $component.'_pluginfile';
747     if (function_exists($filefunction)) {
748         // if the function exists, it must send the file and terminate. Whatever it returns leads to "not found"
749         $filefunction($course, $cm, $context, $filearea, $args, $forcedownload);
750     }
752     send_file_not_found();