MDL-9268
[moodle-pu.git] / file.php
blobd047f9d96c115d044c29d4e80d4511932d881085
1 <?php // $Id$
2 // This script fetches files from the dataroot directory
3 // Syntax: file.php/courseid/dir/dir/dir/filename.ext
4 // file.php/courseid/dir/dir/dir/filename.ext?forcedownload=1 (download instead of inline)
5 // file.php/courseid/dir (returns index.html from dir)
6 // Workaround: file.php?file=/courseid/dir/dir/dir/filename.ext
7 // Test: file.php/testslasharguments
10 //TODO: Blog attachments do not have access control implemented - anybody can read them!
11 // It might be better to move the code to separate file because the access
12 // control is quite complex - see bolg/index.php
14 require_once('config.php');
15 require_once('lib/filelib.php');
17 if (empty($CFG->filelifetime)) {
18 $lifetime = 86400; // Seconds for files to remain in caches
19 } else {
20 $lifetime = $CFG->filelifetime;
23 // disable moodle specific debug messages
24 disable_debugging();
26 $relativepath = get_file_argument('file.php');
27 $forcedownload = optional_param('forcedownload', 0, PARAM_BOOL);
29 // relative path must start with '/', because of backup/restore!!!
30 if (!$relativepath) {
31 error('No valid arguments supplied or incorrect server configuration');
32 } else if ($relativepath{0} != '/') {
33 error('No valid arguments supplied, path does not start with slash!');
36 $pathname = $CFG->dataroot.$relativepath;
38 // extract relative path components
39 $args = explode('/', trim($relativepath, '/'));
40 if (count($args) == 0) { // always at least courseid, may search for index.html in course root
41 error('No valid arguments supplied');
44 // security: limit access to existing course subdirectories
45 if (($args[0]!='blog') and (!$course = get_record_sql("SELECT * FROM {$CFG->prefix}course WHERE id='".(int)$args[0]."'"))) {
46 error('Invalid course ID');
49 // security: prevent access to "000" or "1 something" directories
50 // hack for blogs, needs proper security check too
51 if (($args[0] != 'blog') and ($args[0] != $course->id)) {
52 error('Invalid course ID');
55 // security: login to course if necessary
56 if ($args[0] == 'blog') {
57 if (empty($CFG->bloglevel)) {
58 error('Blogging is disabled!');
59 } else if ($CFG->bloglevel < BLOG_GLOBAL_LEVEL) {
60 require_login();
61 } else if ($CFG->forcelogin) {
62 require_login();
64 } else if ($course->id != SITEID) {
65 require_login($course->id);
66 } else if ($CFG->forcelogin) {
67 if (!empty($CFG->sitepolicy)
68 and ($CFG->sitepolicy == $CFG->wwwroot.'/file.php'.$relativepath
69 or $CFG->sitepolicy == $CFG->wwwroot.'/file.php?file='.$relativepath)) {
70 //do not require login for policy file
71 } else {
72 require_login();
76 // security: only editing teachers can access backups
77 if ((count($args) >= 2) and (strtolower($args[1]) == 'backupdata')) {
78 if (!has_capability('moodle/site:backup', get_context_instance(CONTEXT_COURSE, $course->id))) {
79 error('Access not allowed');
80 } else {
81 $lifetime = 0; //disable browser caching for backups
85 if (is_dir($pathname)) {
86 if (file_exists($pathname.'/index.html')) {
87 $pathname = rtrim($pathname, '/').'/index.html';
88 $args[] = 'index.html';
89 } else if (file_exists($pathname.'/index.htm')) {
90 $pathname = rtrim($pathname, '/').'/index.htm';
91 $args[] = 'index.htm';
92 } else if (file_exists($pathname.'/Default.htm')) {
93 $pathname = rtrim($pathname, '/').'/Default.htm';
94 $args[] = 'Default.htm';
95 } else {
96 // security: do not return directory node!
97 not_found($course->id);
101 // security: teachers can view all assignments, students only their own
102 if ((count($args) >= 3)
103 and (strtolower($args[1]) == 'moddata')
104 and (strtolower($args[2]) == 'assignment')) {
106 $lifetime = 0; // do not cache assignments, students may reupload them
107 if (!has_capability('mod/assignment:grade', get_context_instance(CONTEXT_COURSE, $course->id))
108 and $args[4] != $USER->id) {
109 error('Access not allowed');
113 // security: force download of all attachments submitted by students
114 if ((count($args) >= 3)
115 and (strtolower($args[1]) == 'moddata')
116 and ((strtolower($args[2]) == 'forum')
117 or (strtolower($args[2]) == 'assignment')
118 or (strtolower($args[2]) == 'data')
119 or (strtolower($args[2]) == 'glossary')
120 or (strtolower($args[2]) == 'wiki')
121 or (strtolower($args[2]) == 'exercise')
122 or (strtolower($args[2]) == 'workshop')
123 )) {
124 $forcedownload = 1; // force download of all attachments
126 if ($args[0] == 'blog') {
127 $forcedownload = 1; // force download of all attachments
130 // security: some protection of hidden resource files
131 // warning: it may break backwards compatibility
132 if ((!empty($CFG->preventaccesstohiddenfiles))
133 and (count($args) >= 2)
134 and (!(strtolower($args[1]) == 'moddata' and strtolower($args[2]) != 'resource')) // do not block files from other modules!
135 and (!has_capability('moodle/course:viewhiddenactivities', get_context_instance(CONTEXT_COURSE, $course->id)))) {
137 $rargs = $args;
138 array_shift($rargs);
139 $reference = implode('/', $rargs);
141 $sql = "SELECT COUNT(r.id) " .
142 "FROM {$CFG->prefix}resource r, " .
143 "{$CFG->prefix}course_modules cm, " .
144 "{$CFG->prefix}modules m " .
145 "WHERE r.course = '{$course->id}' " .
146 "AND m.name = 'resource' " .
147 "AND cm.module = m.id " .
148 "AND cm.instance = r.id " .
149 "AND cm.visible = 0 " .
150 "AND r.type = 'file' " .
151 "AND r.reference = '{$reference}'";
152 if (count_records_sql($sql)) {
153 error('Access not allowed');
157 // check that file exists
158 if (!file_exists($pathname)) {
159 not_found($course->id);
162 // ========================================
163 // finally send the file
164 // ========================================
165 session_write_close(); // unlock session during fileserving
166 $filename = $args[count($args)-1];
167 send_file($pathname, $filename, $lifetime, $CFG->filteruploadedfiles, false, $forcedownload);
169 function not_found($courseid) {
170 global $CFG;
171 header('HTTP/1.0 404 not found');
172 error(get_string('filenotfound', 'error'), $CFG->wwwroot.'/course/view.php?id='.$courseid); //this is not displayed on IIS??