Commit | Line | Data |
---|---|---|
63c88397 PS |
1 | <?php |
2 | // This file is part of Moodle - http://moodle.org/ | |
3 | // | |
4 | // Moodle is free software: you can redistribute it and/or modify | |
5 | // it under the terms of the GNU General Public License as published by | |
6 | // the Free Software Foundation, either version 3 of the License, or | |
7 | // (at your option) any later version. | |
8 | // | |
9 | // Moodle is distributed in the hope that it will be useful, | |
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | // GNU General Public License for more details. | |
13 | // | |
14 | // You should have received a copy of the GNU General Public License | |
15 | // along with Moodle. If not, see <http://www.gnu.org/licenses/>. | |
16 | ||
17 | /** | |
18 | * jQuery serving script. | |
19 | * | |
20 | * Do not include jQuery scripts or CSS directly, always use | |
21 | * $PAGE->requires->jquery() or $PAGE->requires->jquery_plugin('xx', 'yy'). | |
22 | * | |
23 | * @package core | |
24 | * @copyright 2013 Petr Skoda {@link http://skodak.org} | |
25 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
26 | */ | |
27 | ||
28 | // Disable moodle specific debug messages and any errors in output, | |
29 | // comment out when debugging or better look into error log! | |
30 | define('NO_DEBUG_DISPLAY', true); | |
31 | ||
32 | // We need just the values from config.php and minlib.php. | |
33 | define('ABORT_AFTER_CONFIG', true); | |
34 | require('../config.php'); // This stops immediately at the beginning of lib/setup.php. | |
35 | ||
36 | if ($slashargument = min_get_slash_argument()) { | |
37 | $path = ltrim($slashargument, '/'); | |
38 | } else { | |
39 | $path = min_optional_param('file', '', 'SAFEPATH'); | |
40 | $path = ltrim($path, '/'); | |
41 | } | |
42 | ||
43 | if (strpos($path, '/') === false) { | |
44 | jquery_file_not_found(); | |
45 | } | |
46 | ||
47 | list($component, $path) = explode('/', $path, 2); | |
48 | ||
49 | if (empty($path) or empty($component)) { | |
50 | jquery_file_not_found(); | |
51 | } | |
52 | ||
53 | // Find the jQuery dir for this component. | |
54 | if ($component === 'core') { | |
55 | $componentdir = "$CFG->dirroot/lib"; | |
56 | ||
57 | } else if (strpos($component, 'theme_')) { | |
58 | if (!empty($CFG->themedir)) { | |
59 | $componentdir = "$CFG->themedir/$component"; | |
60 | } else { | |
61 | $componentdir = "$CFG->dirroot/theme/$component"; | |
62 | } | |
63 | ||
64 | } else { | |
9ad8b423 | 65 | $componentdir = core_component::get_component_directory($component); |
63c88397 PS |
66 | } |
67 | ||
68 | if (!file_exists($componentdir) or !file_exists("$componentdir/jquery/plugins.php")) { | |
69 | jquery_file_not_found(); | |
70 | } | |
71 | ||
72 | $file = realpath("$componentdir/jquery/$path"); | |
73 | ||
74 | if (!$file or is_dir($file)) { | |
75 | jquery_file_not_found(); | |
76 | } | |
77 | ||
78 | $etag = sha1("$component/$path"); | |
203c5bce MS |
79 | // 90 days only - based on Moodle point release cadence being every 3 months. |
80 | $lifetime = 60 * 60 * 24 * 90; | |
63c88397 PS |
81 | $pathinfo = pathinfo($path); |
82 | ||
83 | if (empty($pathinfo['extension'])) { | |
84 | jquery_file_not_found(); | |
85 | } | |
86 | ||
87 | $filename = $pathinfo['filename'].'.'.$pathinfo['extension']; | |
88 | ||
89 | switch($pathinfo['extension']) { | |
90 | case 'gif' : $mimetype = 'image/gif'; | |
91 | break; | |
92 | case 'png' : $mimetype = 'image/png'; | |
93 | break; | |
94 | case 'jpg' : $mimetype = 'image/jpeg'; | |
95 | break; | |
96 | case 'jpeg' : $mimetype = 'image/jpeg'; | |
97 | break; | |
98 | case 'ico' : $mimetype = 'image/vnd.microsoft.icon'; | |
99 | break; | |
100 | case 'svg' : $mimetype = 'image/svg+xml'; | |
101 | break; | |
102 | case 'js' : $mimetype = 'application/javascript'; | |
103 | break; | |
104 | case 'css' : $mimetype = 'text/css'; | |
105 | break; | |
106 | case 'php' : jquery_file_not_found(); | |
107 | break; | |
108 | default : $mimetype = 'document/unknown'; | |
109 | } | |
110 | ||
111 | if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) || !empty($_SERVER['HTTP_IF_MODIFIED_SINCE'])) { | |
112 | // We do not actually need to verify the etag value because these files | |
113 | // never change, devs need to change file names on update! | |
114 | header('HTTP/1.1 304 Not Modified'); | |
115 | header('Expires: '. gmdate('D, d M Y H:i:s', time() + $lifetime) .' GMT'); | |
116 | header('Cache-Control: public, max-age='.$lifetime); | |
117 | header('Content-Type: '.$mimetype); | |
06eca486 | 118 | header('Etag: "'.$etag.'"'); |
63c88397 PS |
119 | die; |
120 | } | |
121 | ||
122 | require_once("$CFG->dirroot/lib/xsendfilelib.php"); | |
123 | ||
06eca486 | 124 | header('Etag: "'.$etag.'"'); |
63c88397 PS |
125 | header('Content-Disposition: inline; filename="'.$filename.'"'); |
126 | header('Last-Modified: '. gmdate('D, d M Y H:i:s', filemtime($file)) .' GMT'); | |
127 | header('Expires: '. gmdate('D, d M Y H:i:s', time() + $lifetime) .' GMT'); | |
128 | header('Pragma: '); | |
ed0a1cd7 | 129 | header('Cache-Control: public, max-age='.$lifetime.', immutable'); |
63c88397 PS |
130 | header('Accept-Ranges: none'); |
131 | header('Content-Type: '.$mimetype); | |
132 | ||
133 | if (xsendfile($file)) { | |
134 | die; | |
135 | } | |
136 | ||
137 | if ($mimetype === 'text/css' or $mimetype === 'application/javascript') { | |
138 | if (!min_enable_zlib_compression()) { | |
139 | header('Content-Length: '.filesize($file)); | |
140 | } | |
141 | } else { | |
142 | // No need to compress images. | |
143 | header('Content-Length: '.filesize($file)); | |
144 | } | |
145 | ||
146 | readfile($file); | |
147 | die; | |
148 | ||
149 | ||
150 | ||
151 | function jquery_file_not_found() { | |
152 | // Note: we can not disclose the exact file path here, sorry. | |
153 | header('HTTP/1.0 404 not found'); | |
154 | die('File was not found, sorry.'); | |
155 | } |