MDL-20691 "Fatal error: Exception thrown without a stack frame in Unknown on line...
[moodle.git] / pluginfile.php
CommitLineData
d92e7c4d 1<?php
2
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/>.
17
18/**
19 * This script delegates file serving to individual plugins
20 *
21 * @package moodlecore
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 */
26
27require_once('config.php');
28require_once('lib/filelib.php');
29
30// disable moodle specific debug messages
31disable_debugging();
32
33$relativepath = get_file_argument();
34$forcedownload = optional_param('forcedownload', 0, PARAM_BOOL);
35
36// relative path must start with '/'
37if (!$relativepath) {
38 print_error('invalidargorconf');
29afd52b 39} else if ($relativepath[0] != '/') {
d92e7c4d 40 print_error('pathdoesnotstartslash');
41}
42
43// extract relative path components
44$args = explode('/', ltrim($relativepath, '/'));
45
46if (count($args) == 0) { // always at least user id
47 print_error('invalidarguments');
48}
49
50$contextid = (int)array_shift($args);
51$filearea = array_shift($args);
52
49375088 53if (!$context = get_context_instance_by_id($contextid)) {
54 send_file_not_found();
55}
d92e7c4d 56$fs = get_file_storage();
57
58
59if ($context->contextlevel == CONTEXT_SYSTEM) {
1c7b8b93 60 if ($filearea === 'blog_attachment' || $filearea === 'blog_post') {
d92e7c4d 61
62 if (empty($CFG->bloglevel)) {
63 print_error('siteblogdisable', 'blog');
64 }
65 if ($CFG->bloglevel < BLOG_GLOBAL_LEVEL) {
66 require_login();
67 if (isguestuser()) {
68 print_error('noguest');
69 }
70 if ($CFG->bloglevel == BLOG_USER_LEVEL) {
71 if ($USER->id != $entry->userid) {
72 send_file_not_found();
73 }
74 }
75 }
76 $entryid = (int)array_shift($args);
77 if (!$entry = $DB->get_record('post', array('module'=>'blog', 'id'=>$entryid))) {
78 send_file_not_found();
79 }
80 if ('publishstate' === 'public') {
81 if ($CFG->forcelogin) {
82 require_login();
83 }
172dd12c 84
d92e7c4d 85 } else if ('publishstate' === 'site') {
86 require_login();
87 //ok
88 } else if ('publishstate' === 'draft') {
89 require_login();
90 if ($USER->id != $entry->userid) {
91 send_file_not_found();
92 }
93 }
172dd12c 94
d92e7c4d 95 //TODO: implement shared course and shared group access
172dd12c 96
d92e7c4d 97 $relativepath = '/'.implode('/', $args);
1c7b8b93 98 $fullpath = $context->id.$filearea.$entryid.$relativepath;
172dd12c 99
d92e7c4d 100 if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
101 send_file_not_found();
102 }
172dd12c 103
d92e7c4d 104 send_stored_file($file, 10*60, 0, true); // download MUST be forced - security!
172dd12c 105
d92e7c4d 106 } else {
107 send_file_not_found();
172dd12c 108 }
109
172dd12c 110
d92e7c4d 111} else if ($context->contextlevel == CONTEXT_USER) {
112 send_file_not_found();
172dd12c 113
114
d92e7c4d 115} else if ($context->contextlevel == CONTEXT_COURSECAT) {
116 if ($filearea !== 'coursecat_intro') {
117 send_file_not_found();
118 }
172dd12c 119
d92e7c4d 120 if ($CFG->forcelogin) {
121 // no login necessary - unless login forced everywhere
122 require_login();
123 }
172dd12c 124
d92e7c4d 125 $relativepath = '/'.implode('/', $args);
126 $fullpath = $context->id.'coursecat_intro0'.$relativepath;
172dd12c 127
d92e7c4d 128 if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->get_filename() == '.') {
129 send_file_not_found();
130 }
172dd12c 131
d92e7c4d 132 session_get_instance()->write_close(); // unlock session during fileserving
133 send_stored_file($file, 60*60, 0, $forcedownload);
172dd12c 134
172dd12c 135
d92e7c4d 136} else if ($context->contextlevel == CONTEXT_COURSE) {
137 if (!$course = $DB->get_record('course', array('id'=>$context->instanceid))) {
138 print_error('invalidcourseid');
139 }
172dd12c 140
d92e7c4d 141 if ($filearea === 'course_backup') {
142 require_login($course);
143 require_capability('moodle/site:backupdownload', $context);
172dd12c 144
d92e7c4d 145 $relativepath = '/'.implode('/', $args);
146 $fullpath = $context->id.'course_backup0'.$relativepath;
172dd12c 147
d92e7c4d 148 if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
9e5fa330 149 send_file_not_found();
172dd12c 150 }
151
d92e7c4d 152 session_get_instance()->write_close(); // unlock session during fileserving
153 send_stored_file($file, 0, 0, true);
154
155 } else if ($filearea === 'course_intro') {
172dd12c 156 if ($CFG->forcelogin) {
172dd12c 157 require_login();
158 }
159
160 $relativepath = '/'.implode('/', $args);
d92e7c4d 161 $fullpath = $context->id.'course_intro0'.$relativepath;
172dd12c 162
d92e7c4d 163 if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
9e5fa330 164 send_file_not_found();
172dd12c 165 }
166
56949c17 167 session_get_instance()->write_close(); // unlock session during fileserving
d92e7c4d 168 send_stored_file($file, 60*60, 0, false); // TODO: change timeout?
172dd12c 169
d92e7c4d 170 } else if ($filearea === 'course_section') {
171 if ($CFG->forcelogin) {
172dd12c 172 require_login($course);
d92e7c4d 173 } else if ($course->id !== SITEID) {
174 require_login($course);
175 }
106f3b67 176
d92e7c4d 177 $sectionid = (int)array_shift($args);
106f3b67 178
d92e7c4d 179 if ($course->numsections < $sectionid) {
180 if (!has_capability('moodle/course:update', $context)) {
181 // disable access to invisible sections if can not edit course
182 // this is going to break some ugly hacks, but is necessary
106f3b67 183 send_file_not_found();
184 }
d92e7c4d 185 }
106f3b67 186
d92e7c4d 187 $relativepath = '/'.implode('/', $args);
188 $fullpath = $context->id.'course_section'.$sectionid.$relativepath;
172dd12c 189
d92e7c4d 190 if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
191 send_file_not_found();
192 }
172dd12c 193
d92e7c4d 194 session_get_instance()->write_close(); // unlock session during fileserving
195 send_stored_file($file, 60*60, 0, false); // TODO: change timeout?
172dd12c 196
d92e7c4d 197 } else if ($filearea === 'user_profile') {
198 $userid = (int)array_shift($args);
199 $usercontext = get_context_instance(CONTEXT_USER, $userid);
3156b8ca 200
d92e7c4d 201 if (!empty($CFG->forceloginforprofiles)) {
202 require_login();
203 if (isguestuser()) {
204 print_error('noguest');
3156b8ca 205 }
206
d92e7c4d 207 if (!isteacherinanycourse()
208 and !isteacherinanycourse($userid)
209 and !has_capability('moodle/user:viewdetails', $usercontext)) {
210 print_error('usernotavailable');
3156b8ca 211 }
d92e7c4d 212 if (!has_capability('moodle/user:viewdetails', $context) &&
213 !has_capability('moodle/user:viewdetails', $usercontext)) {
214 print_error('cannotviewprofile');
3156b8ca 215 }
d92e7c4d 216 if (!has_capability('moodle/course:view', $context, $userid, false)) {
217 print_error('notenrolledprofile');
106f3b67 218 }
d92e7c4d 219 if (groups_get_course_groupmode($course) == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)) {
220 print_error('groupnotamember');
106f3b67 221 }
d92e7c4d 222 }
106f3b67 223
d92e7c4d 224 $relativepath = '/'.implode('/', $args);
225 $fullpath = $usercontext->id.'user_profile0'.$relativepath;
106f3b67 226
d92e7c4d 227 if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
106f3b67 228 send_file_not_found();
229 }
172dd12c 230
d92e7c4d 231 session_get_instance()->write_close(); // unlock session during fileserving
232 send_stored_file($file, 0, 0, true); // must force download - security!
106f3b67 233
d92e7c4d 234 } else {
235 send_file_not_found();
236 }
237
238} else if ($context->contextlevel == CONTEXT_MODULE) {
239
240 if (!$coursecontext = get_context_instance_by_id(get_parent_contextid($context))) {
241 send_file_not_found();
242 }
243
244 if (!$course = $DB->get_record('course', array('id'=>$coursecontext->instanceid))) {
245 send_file_not_found();
246 }
247 $modinfo = get_fast_modinfo($course);
248 if (empty($modinfo->cms[$context->instanceid])) {
249 send_file_not_found();
250 }
251
252 $cminfo = $modinfo->cms[$context->instanceid];
253 $modname = $cminfo->modname;
254 $libfile = "$CFG->dirroot/mod/$modname/lib.php";
255 if (!file_exists($libfile)) {
256 send_file_not_found();
257 }
172dd12c 258
d92e7c4d 259 require_once($libfile);
260 if ($filearea === $modname.'_intro') {
261 if (!plugin_supports('mod', $modname, FEATURE_MOD_INTRO, true)) {
9e5fa330 262 send_file_not_found();
172dd12c 263 }
d92e7c4d 264 if (!$cminfo->uservisible) {
9e5fa330 265 send_file_not_found();
172dd12c 266 }
d92e7c4d 267 // all users may access it
268 $relativepath = '/'.implode('/', $args);
269 $fullpath = $context->id.$filearea.'0'.$relativepath;
172dd12c 270
d92e7c4d 271 $fs = get_file_storage();
272 if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
dc5c2bd9 273 send_file_not_found();
274 }
275
d92e7c4d 276 $lifetime = isset($CFG->filelifetime) ? $CFG->filelifetime : 86400;
dc5c2bd9 277
d92e7c4d 278 // finally send the file
279 send_stored_file($file, $lifetime, 0);
280 }
281
282 $filefunction = $modname.'_pluginfile';
283 if (function_exists($filefunction)) {
520199ea 284 // if the function exists, it must send the file and terminate. Whatever it returns leads to "not found"
285 $filefunction($course, $cminfo, $context, $filearea, $args, $forcedownload);
b287ea7a 286 }
520199ea 287
288 send_file_not_found();
172dd12c 289
d92e7c4d 290} else if ($context->contextlevel == CONTEXT_BLOCK) {
291 //not supported yet
292 send_file_not_found();
172dd12c 293
294
d92e7c4d 295} else {
296 send_file_not_found();
297}