Bumped to 1.7.6
[moodle.git] / file.php
blobe6bb63af2b72105c6bd25980ab3fbb40d1369beb
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
9 require_once('config.php');
10 require_once('lib/filelib.php');
12 if (empty($CFG->filelifetime)) {
13 $lifetime = 86400; // Seconds for files to remain in caches
14 } else {
15 $lifetime = $CFG->filelifetime;
18 // disable moodle specific debug messages
19 disable_debugging();
21 $relativepath = get_file_argument('file.php');
22 $forcedownload = optional_param('forcedownload', 0, PARAM_BOOL);
24 // relative path must start with '/', because of backup/restore!!!
25 if (!$relativepath) {
26 error('No valid arguments supplied or incorrect server configuration');
27 } else if ($relativepath{0} != '/') {
28 error('No valid arguments supplied, path does not start with slash!');
31 $pathname = $CFG->dataroot.$relativepath;
33 // extract relative path components
34 $args = explode('/', trim($relativepath, '/'));
35 if (count($args) == 0) { // always at least courseid, may search for index.html in course root
36 error('No valid arguments supplied');
39 // security: limit access to existing course subdirectories
40 if (!$course = get_record_sql("SELECT * FROM {$CFG->prefix}course WHERE id='".(int)$args[0]."'")) {
41 error('Invalid course ID');
44 // security: prevent access to "000" or "1 something" directories
45 if ($args[0] != $course->id) {
46 error('Invalid course ID');
49 // security: login to course if necessary
50 if ($course->id != SITEID) {
51 require_login($course->id);
52 } else if ($CFG->forcelogin) {
53 require_login();
56 // security: only editing teachers can access backups
57 if ((count($args) >= 2) and (strtolower($args[1]) == 'backupdata')) {
58 if (!has_capability('moodle/site:backup', get_context_instance(CONTEXT_COURSE, $course->id))) {
59 error('Access not allowed');
60 } else {
61 $lifetime = 0; //disable browser caching for backups
65 if (is_dir($pathname)) {
66 if (file_exists($pathname.'/index.html')) {
67 $pathname = rtrim($pathname, '/').'/index.html';
68 $args[] = 'index.html';
69 } else if (file_exists($pathname.'/index.htm')) {
70 $pathname = rtrim($pathname, '/').'/index.htm';
71 $args[] = 'index.htm';
72 } else if (file_exists($pathname.'/Default.htm')) {
73 $pathname = rtrim($pathname, '/').'/Default.htm';
74 $args[] = 'Default.htm';
75 } else {
76 // security: do not return directory node!
77 not_found($course->id);
81 // security: teachers can view all assignments, students only their own
82 if ((count($args) >= 3)
83 and (strtolower($args[1]) == 'moddata')
84 and (strtolower($args[2]) == 'assignment')) {
86 $lifetime = 0; // do not cache assignments, students may reupload them
87 if (!has_capability('mod/assignment:grade', get_context_instance(CONTEXT_COURSE, $course->id))
88 and $args[4] != $USER->id) {
89 error('Access not allowed');
93 // security: force download of all attachments submitted by students
94 if ((count($args) >= 3)
95 and (strtolower($args[1]) == 'moddata')
96 and ((strtolower($args[2]) == 'forum')
97 or (strtolower($args[2]) == 'assignment')
98 or (strtolower($args[2]) == 'data')
99 or (strtolower($args[2]) == 'glossary')
100 or (strtolower($args[2]) == 'wiki')
101 or (strtolower($args[2]) == 'exercise')
102 or (strtolower($args[2]) == 'workshop')
103 )) {
104 $forcedownload = 1; // force download of all attachments
107 // security: some protection of hidden resource files
108 // warning: it may break backwards compatibility
109 if ((!empty($CFG->preventaccesstohiddenfiles))
110 and (count($args) >= 2)
111 and (!(strtolower($args[1]) == 'moddata' and strtolower($args[2]) != 'resource')) // do not block files from other modules!
112 and (!has_capability('moodle/course:viewhiddenactivities', get_context_instance(CONTEXT_COURSE, $course->id)))) {
114 $rargs = $args;
115 array_shift($rargs);
116 $reference = implode('/', $rargs);
118 $sql = "SELECT COUNT(r.id) " .
119 "FROM {$CFG->prefix}resource r, " .
120 "{$CFG->prefix}course_modules cm, " .
121 "{$CFG->prefix}modules m " .
122 "WHERE r.course = '{$course->id}' " .
123 "AND m.name = 'resource' " .
124 "AND cm.module = m.id " .
125 "AND cm.instance = r.id " .
126 "AND cm.visible = 0 " .
127 "AND r.type = 'file' " .
128 "AND r.reference = '{$reference}'";
129 if (count_records_sql($sql)) {
130 error('Access not allowed');
134 // check that file exists
135 if (!file_exists($pathname)) {
136 not_found($course->id);
139 // extra security: keep symbolic links inside dataroot/courseid if required
140 /*if (!empty($CFG->checksymlinks)) {
141 $realpath = realpath($pathname);
142 $realdataroot = realpath($CFG->dataroot.'/'.$course->id);
143 if (strpos($realpath, $realdataroot) !== 0) {
144 not_found($course->id);
148 // ========================================
149 // finally send the file
150 // ========================================
151 session_write_close(); // unlock session during fileserving
152 $filename = $args[count($args)-1];
153 send_file($pathname, $filename, $lifetime, $CFG->filteruploadedfiles, false, $forcedownload);
155 function not_found($courseid) {
156 global $CFG;
157 header('HTTP/1.0 404 not found');
158 error(get_string('filenotfound', 'error'), $CFG->wwwroot.'/course/view.php?id='.$courseid); //this is not displayed on IIS??