Commit | Line | Data |
---|---|---|
60f2c866 | 1 | <?php |
60f2c866 PS |
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 | * This file is responsible for serving of yui images | |
19 | * | |
574909ef | 20 | * @package core |
60f2c866 PS |
21 | * @copyright 2009 Petr Skoda (skodak) {@link http://skodak.org} |
22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
23 | */ | |
24 | ||
25 | ||
ee891dac PS |
26 | // disable moodle specific debug messages and any errors in output, |
27 | // comment out when debugging or better look into error log! | |
28 | define('NO_DEBUG_DISPLAY', true); | |
29 | ||
60f2c866 PS |
30 | // we need just the values from config.php and minlib.php |
31 | define('ABORT_AFTER_CONFIG', true); | |
32 | require('../config.php'); // this stops immediately at the beginning of lib/setup.php | |
33 | ||
d5222fae PS |
34 | if ($slashargument = min_get_slash_argument()) { |
35 | $path = ltrim($slashargument, '/'); | |
36 | } else { | |
37 | $path = min_optional_param('file', '', 'SAFEPATH'); | |
38 | } | |
60f2c866 | 39 | |
1c6d3af5 | 40 | $etag = sha1($path); |
60f2c866 | 41 | $parts = explode('/', $path); |
2a102b90 | 42 | $version = array_shift($parts); |
03e36e70 AN |
43 | if ($version === 'm') { |
44 | $version = 'moodle'; | |
45 | } | |
3b17690c | 46 | if ($version == 'moodle' && count($parts) >= 3) { |
3b17690c SH |
47 | $frankenstyle = array_shift($parts); |
48 | $module = array_shift($parts); | |
49 | $image = array_pop($parts); | |
50 | $subdir = join('/', $parts); | |
cba94cec | 51 | $dir = core_component::get_component_directory($frankenstyle); |
a45e8fd3 ARN |
52 | |
53 | // For shifted YUI modules, we need the YUI module name in frankenstyle format. | |
54 | $frankenstylemodulename = join('-', array($version, $frankenstyle, $module)); | |
55 | ||
56 | // By default, try and use the /yui/build directory. | |
57 | $imagepath = $dir . '/yui/build/' . $frankenstylemodulename . '/assets/skins/sam/' . $image; | |
58 | ||
59 | // If the shifted versions don't exist, fall back to the non-shifted file. | |
60 | if (!file_exists($imagepath) or !is_file($imagepath)) { | |
61 | $imagepath = $dir . '/yui/' . $module . '/assets/skins/sam/' . $image; | |
62 | } | |
5b49f8b3 AN |
63 | } else if ($version == 'gallery' && count($parts) >= 3) { |
64 | list($revision, $module, , , , $image) = $parts; | |
65 | $imagepath = "$CFG->dirroot/lib/yuilib/gallery/$module/assets/skins/sam/$image"; | |
60f2c866 | 66 | } else { |
aea29737 AN |
67 | // Allow support for revisions on YUI between official releases. |
68 | // We can just discard the subrevision since it is only used to invalidate the browser cache. | |
69 | $yuipatchedversion = explode('_', $version); | |
70 | $yuiversion = $yuipatchedversion[0]; | |
71 | if (count($parts) == 1 && ($yuiversion == $CFG->yui3version || $yuiversion == $CFG->yui2version)) { | |
72 | list($image) = $parts; | |
73 | if ($yuiversion == $CFG->yui3version) { | |
74 | $imagepath = "$CFG->dirroot/lib/yuilib/$CFG->yui3version/assets/skins/sam/$image"; | |
75 | } else { | |
76 | $imagepath = "$CFG->dirroot/lib/yuilib/2in3/$CFG->yui2version/build/assets/skins/sam/$image"; | |
77 | } | |
78 | } else { | |
79 | yui_image_not_found(); | |
80 | } | |
60f2c866 PS |
81 | } |
82 | ||
83 | if (!file_exists($imagepath)) { | |
84 | yui_image_not_found(); | |
85 | } | |
86 | ||
dbe14f39 PS |
87 | $pathinfo = pathinfo($imagepath); |
88 | $imagename = $pathinfo['filename'].'.'.$pathinfo['extension']; | |
89 | ||
90 | switch($pathinfo['extension']) { | |
91 | case 'gif' : $mimetype = 'image/gif'; break; | |
92 | case 'png' : $mimetype = 'image/png'; break; | |
93 | case 'jpg' : $mimetype = 'image/jpeg'; break; | |
94 | case 'jpeg' : $mimetype = 'image/jpeg'; break; | |
95 | case 'ico' : $mimetype = 'image/vnd.microsoft.icon'; break; | |
96 | default: $mimetype = 'document/unknown'; | |
97 | } | |
98 | ||
99 | // if they are requesting a revision that's not -1, and they have supplied an | |
100 | // If-Modified-Since header, we can send back a 304 Not Modified since the | |
101 | // content never changes (the rev number is increased any time the content changes) | |
1c6d3af5 | 102 | if (strpos($path, '/-1/') === false and (!empty($_SERVER['HTTP_IF_NONE_MATCH']) || !empty($_SERVER['HTTP_IF_MODIFIED_SINCE']))) { |
dbe14f39 PS |
103 | $lifetime = 60*60*24*360; // 1 year, we do not change YUI versions often, there are a few custom yui modules |
104 | header('HTTP/1.1 304 Not Modified'); | |
105 | header('Last-Modified: '. gmdate('D, d M Y H:i:s', filemtime($imagepath)) .' GMT'); | |
106 | header('Expires: '. gmdate('D, d M Y H:i:s', time() + $lifetime) .' GMT'); | |
c3a3f540 | 107 | header('Cache-Control: public, max-age='.$lifetime.', no-transform'); |
dbe14f39 | 108 | header('Content-Type: '.$mimetype); |
06eca486 | 109 | header('Etag: "'.$etag.'"'); |
dbe14f39 PS |
110 | die; |
111 | } | |
60f2c866 | 112 | |
dbe14f39 | 113 | yui_image_cached($imagepath, $imagename, $mimetype, $etag); |
60f2c866 PS |
114 | |
115 | ||
dbe14f39 | 116 | function yui_image_cached($imagepath, $imagename, $mimetype, $etag) { |
7e9f1b63 PS |
117 | global $CFG; |
118 | require("$CFG->dirroot/lib/xsendfilelib.php"); | |
119 | ||
dbe14f39 | 120 | $lifetime = 60*60*24*360; // 1 year, we do not change YUI versions often, there are a few custom yui modules |
60f2c866 PS |
121 | |
122 | header('Content-Disposition: inline; filename="'.$imagename.'"'); | |
123 | header('Last-Modified: '. gmdate('D, d M Y H:i:s', filemtime($imagepath)) .' GMT'); | |
124 | header('Expires: '. gmdate('D, d M Y H:i:s', time() + $lifetime) .' GMT'); | |
125 | header('Pragma: '); | |
203c5bce | 126 | header('Cache-Control: public, max-age='.$lifetime.', no-transform, immutable'); |
60f2c866 PS |
127 | header('Accept-Ranges: none'); |
128 | header('Content-Type: '.$mimetype); | |
129 | header('Content-Length: '.filesize($imagepath)); | |
06eca486 | 130 | header('Etag: "'.$etag.'"'); |
60f2c866 | 131 | |
7e9f1b63 PS |
132 | if (xsendfile($imagepath)) { |
133 | die; | |
134 | } | |
135 | ||
7c986f04 PS |
136 | // no need to gzip already compressed images ;-) |
137 | ||
60f2c866 PS |
138 | readfile($imagepath); |
139 | die; | |
140 | } | |
141 | ||
142 | function yui_image_not_found() { | |
143 | header('HTTP/1.0 404 not found'); | |
144 | die('Image was not found, sorry.'); | |
145 | } |