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 | |
27 | require_once('config.php'); |
28 | require_once('lib/filelib.php'); |
29 | |
30 | // disable moodle specific debug messages |
31 | disable_debugging(); |
32 | |
33 | $relativepath = get_file_argument(); |
34 | $forcedownload = optional_param('forcedownload', 0, PARAM_BOOL); |
35 | |
36 | // relative path must start with '/' |
37 | if (!$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 | |
46 | if (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 |
53 | if (!$context = get_context_instance_by_id($contextid)) { |
54 | send_file_not_found(); |
55 | } |
d92e7c4d |
56 | $fs = get_file_storage(); |
57 | |
58 | |
59 | if ($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 | } |