Cleanups in view.php. Also moved logging of a forum view so that the event is not...
[moodle.git] / file.php
CommitLineData
e7f927a0 1<?php // $Id$
2 // This script fetches files from the dataroot directory
3 // Syntax: file.php/courseid/dir/dir/dir/filename.ext
69faecce 4 // file.php/courseid/dir/dir/dir/filename.ext?forcedownload=1 (download instead of inline)
e7f927a0 5 // file.php/courseid/dir (returns index.html from dir)
6 // Workaround: file.php?file=/courseid/dir/dir/dir/filename.ext
48283ff6 7 // Test: file.php/testslasharguments
e7f927a0 8
822a1063 9 require_once('config.php');
4d68dff4 10 require_once('lib/filelib.php');
f9903ed0 11
66e5f959 12 if (empty($CFG->filelifetime)) {
e7f927a0 13 $lifetime = 86400; // Seconds for files to remain in caches
6ed3da1d 14 } else {
e7f927a0 15 $lifetime = $CFG->filelifetime;
ea8158c1 16 }
3f8247c2 17
e7f927a0 18 $relativepath = get_file_argument('file.php');
69faecce 19 $forcedownload = optional_param('forcedownload', 0, PARAM_BOOL);
e7f927a0 20
21 // relative path must start with '/', because of backup/restore!!!
22 if (!$relativepath) {
23 error('No valid arguments supplied or incorrect server configuration');
24 } else if ($relativepath{0} != '/') {
25 error('No valid arguments supplied, path does not start with slash!');
f9903ed0 26 }
27
e7f927a0 28 $pathname = $CFG->dataroot.$relativepath;
ae67d9cd 29
e7f927a0 30 // extract relative path components
31 $args = explode('/', trim($relativepath, '/'));
32 if (count($args) == 0) { // always at least courseid, may search for index.html in course root
822a1063 33 error('No valid arguments supplied');
55b8ac31 34 }
35
e7f927a0 36 // security: limit access to existing course subdirectories
ba4e0b05 37 if (!$course = get_record_sql("SELECT * FROM {$CFG->prefix}course WHERE id='".(int)$args[0]."'")) {
e7f927a0 38 error('Invalid course ID');
a4557331 39 }
40
e7f927a0 41 // security: prevent access to "000" or "1 something" directories
42 if ($args[0] != $course->id) {
822a1063 43 error('Invalid course ID');
76112421 44 }
21ddaf60 45
e7f927a0 46 // security: login to course if necessary
47 if ($course->id != SITEID) {
48 require_login($course->id);
f57cd38b 49 } else if ($CFG->forcelogin) {
50 require_login();
f9903ed0 51 }
52
e7f927a0 53 // security: only editing teachers can access backups
de9a33f3 54 if ((count($args) >= 2) and (strtolower($args[1]) == 'backupdata')) {
55 if (!has_capability('moodle/site:backup', get_context_instance(CONTEXT_COURSE, $course->id))) {
56 error('Access not allowed');
57 } else {
58 $lifetime = 0; //disable browser caching for backups
59 }
e7f927a0 60 }
f9903ed0 61
e7f927a0 62 if (is_dir($pathname)) {
63 if (file_exists($pathname.'/index.html')) {
64 $pathname = rtrim($pathname, '/').'/index.html';
65 $args[] = 'index.html';
66 } else if (file_exists($pathname.'/index.htm')) {
67 $pathname = rtrim($pathname, '/').'/index.htm';
68 $args[] = 'index.htm';
69 } else if (file_exists($pathname.'/Default.htm')) {
70 $pathname = rtrim($pathname, '/').'/Default.htm';
71 $args[] = 'Default.htm';
72 } else {
73 // security: do not return directory node!
74 not_found($course->id);
75 }
76 }
3cf4ab97 77
fd05dffe 78 // security: teachers can view all assignments, students only their own
79 if ((count($args) >= 3)
80 and (strtolower($args[1]) == 'moddata')
81 and (strtolower($args[2]) == 'assignment')) {
82
83 $lifetime = 0; // do not cache assignments, students may reupload them
3924b988 84 if ((!has_capability('mod/assignment:grade', get_context_instance(CONTEXT_COURSE, $course->id))) && (count($args) != 6 || $args[4] != $USER->id)) {
fd05dffe 85 error('Access not allowed');
86 }
87 }
88
69faecce 89 // security: force download of all attachments submitted by students
90 if ((count($args) >= 3)
91 and (strtolower($args[1]) == 'moddata')
92 and ((strtolower($args[2]) == 'forum')
93 or (strtolower($args[2]) == 'assignment')
3d050945 94 or (strtolower($args[2]) == 'data')
69faecce 95 or (strtolower($args[2]) == 'glossary')
96 or (strtolower($args[2]) == 'wiki')
97 or (strtolower($args[2]) == 'exercise')
98 or (strtolower($args[2]) == 'workshop')
99 )) {
100 $forcedownload = 1; // force download of all attachments
101 }
102
fd05dffe 103 // security: some protection of hidden resource files
104 // warning: it may break backwards compatibility
fd05dffe 105 if ((!empty($CFG->preventaccesstohiddenfiles))
106 and (count($args) >= 2)
c5a3467a 107 and (!has_capability('moodle/course:viewhiddenactivities', get_context_instance(CONTEXT_COURSE, $course->id)))) {
fd05dffe 108
109 $reference = ltrim($relativepath, "/{$args[0]}/");
110
111 $sql = "SELECT COUNT(r.id) " .
112 "FROM {$CFG->prefix}resource r, " .
113 "{$CFG->prefix}course_modules cm, " .
114 "{$CFG->prefix}modules m " .
115 "WHERE r.course = '{$course->id}' " .
116 "AND m.name = 'resource' " .
117 "AND cm.module = m.id " .
118 "AND cm.instance = r.id " .
119 "AND cm.visible = 0 " .
120 "AND r.type = 'file' " .
121 "AND r.reference = '{$reference}'";
122 if (count_records_sql($sql)) {
123 error('Access not allowed');
124 }
125 }
126
e7f927a0 127 // check that file exists
128 if (!file_exists($pathname)) {
129 not_found($course->id);
130 }
e5890e71 131
e7f927a0 132 // extra security: keep symbolic links inside dataroot/courseid if required
133 /*if (!empty($CFG->checksymlinks)) {
134 $realpath = realpath($pathname);
135 $realdataroot = realpath($CFG->dataroot.'/'.$course->id);
136 if (strpos($realpath, $realdataroot) !== 0) {
137 not_found($course->id);
f0507011 138 }
e7f927a0 139 }*/
140
141 // ========================================
142 // finally send the file
143 // ========================================
2ea55bc0 144 session_write_close(); // unlock session during fileserving
e7f927a0 145 $filename = $args[count($args)-1];
b9709b76 146 send_file($pathname, $filename, $lifetime, $CFG->filteruploadedfiles, false, $forcedownload);
e7f927a0 147
148 function not_found($courseid) {
149 global $CFG;
822a1063 150 header('HTTP/1.0 404 not found');
e7f927a0 151 error(get_string('filenotfound', 'error'), $CFG->wwwroot.'/course/view.php?id='.$courseid); //this is not displayed on IIS??
f9903ed0 152 }
e7f927a0 153?>