| [ Index ] |
PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008] |
[Summary view] [Print] [Text view]
1 <?php 2 // Outputs pictures from theme or core pix folder. Only used if $CFG->smartpix is 3 // turned on. 4 5 $matches=array(); // Reusable array variable for preg_match 6 7 // This does NOT use config.php. This is because doing that makes database requests 8 // which cause this to take longer (I benchmarked this at 16ms, 256ms with config.php) 9 // A version using normal Moodle functions is included in comment at end in case we 10 // want to switch to it in future. 11 12 function error($text,$notfound=false) { 13 header($notfound ? 'HTTP/1.0 404 Not Found' : 'HTTP/1.0 500 Internal Server Error'); 14 header('Content-Type: text/plain'); 15 print $text; 16 exit; 17 } 18 19 // Nicked from moodlelib clean_param 20 function makesafe($param) { 21 $param = str_replace('\\\'', '\'', $param); 22 $param = str_replace('\\"', '"', $param); 23 $param = str_replace('\\', '/', $param); 24 $param = ereg_replace('[[:cntrl:]]|[<>"`\|\':]', '', $param); 25 $param = ereg_replace('\.\.+', '', $param); 26 $param = ereg_replace('//+', '/', $param); 27 return ereg_replace('/(\./)+', '/', $param); 28 } 29 30 // Nicked from weblib 31 /** 32 * Remove query string from url 33 * 34 * Takes in a URL and returns it without the querystring portion 35 * 36 * @param string $url the url which may have a query string attached 37 * @return string 38 */ 39 function strip_querystring($url) { 40 41 if ($commapos = strpos($url, '?')) { 42 return substr($url, 0, $commapos); 43 } else { 44 return $url; 45 } 46 } 47 48 // get query string 49 function get_query($name) { 50 if (!empty($_SERVER['REQUEST_URI'])) { 51 return explode($name, $_SERVER['REQUEST_URI']); 52 } else if (!empty($_SERVER['QUERY_STRING'])) { 53 return array('', '?'. $_SERVER['QUERY_STRING']); 54 } else { 55 return false; 56 } 57 } 58 // Nicked from weblib then cutdown 59 /** 60 * Extracts file argument either from file parameter or PATH_INFO. 61 * @param string $scriptname name of the calling script 62 * @return string file path (only safe characters) 63 */ 64 function get_file_argument_limited($scriptname) { 65 $relativepath = FALSE; 66 67 // first try normal parameter (compatible method == no relative links!) 68 if(isset($_GET['file'])) { 69 return makesafe($_GET['file']); 70 } 71 72 // then try extract file from PATH_INFO (slasharguments method) 73 if (!empty($_SERVER['PATH_INFO'])) { 74 $path_info = $_SERVER['PATH_INFO']; 75 // check that PATH_INFO works == must not contain the script name 76 if (!strpos($path_info, $scriptname)) { 77 return makesafe(rawurldecode($path_info)); 78 } 79 } 80 81 // now if both fail try the old way 82 // (for compatibility with misconfigured or older buggy php implementations) 83 $arr = get_query($scriptname); 84 if (!empty($arr[1])) { 85 return makesafe(rawurldecode(strip_querystring($arr[1]))); 86 } 87 88 error('Unexpected PHP set up. Turn off the smartpix config option.'); 89 } 90 91 // We do need to get dirroot from config.php 92 if(!$config=@file_get_contents(dirname(__FILE__).'/../config.php')) { 93 error("Can't open config.php"); 94 } 95 $configlines=preg_split('/[\r\n]+/',$config); 96 foreach($configlines as $configline) { 97 if(preg_match('/^\s?\$CFG->dirroot\s*=\s*[\'"](.*?)[\'"]\s*;/',$configline,$matches)) { 98 $dirroot=$matches[1]; 99 } 100 if(preg_match('/^\s?\$CFG->dataroot\s*=\s*[\'"](.*?)[\'"]\s*;/',$configline,$matches)) { 101 $dataroot=$matches[1]; 102 } 103 if(isset($dirroot) && isset($dataroot)) { 104 break; 105 } 106 } 107 if(!(isset($dirroot) && isset($dataroot))) { 108 error('No line in config.php like $CFG->dirroot=\'/somewhere/whatever\';'); 109 } 110 111 // Split path - starts with theme name, then actual image path inside pix 112 $path=get_file_argument_limited('smartpix.php'); 113 $match=array(); 114 if(!preg_match('|^/([a-z0-9_\-.]+)/([a-z0-9/_\-.]+)$|',$path,$match)) { 115 error('Unexpected request format'); 116 } 117 list($junk,$theme,$path)=$match; 118 119 // Check file type 120 if(preg_match('/\.png$/',$path)) { 121 $mimetype='image/png'; 122 } else if(preg_match('/\.gif$/',$path)) { 123 $mimetype='image/gif'; 124 } else if(preg_match('/\.jpe?g$/',$path)) { 125 $mimetype='image/jpeg'; 126 } else { 127 // Note that this is a security feature as well as a lack of mime type 128 // support :) Means this can't accidentally serve files from places it 129 // shouldn't. Without it, you can actually access any file inside the 130 // module code directory. 131 error('Request for non-image file'); 132 } 133 134 // Find actual location of image as $file 135 $file=false; 136 if(file_exists($possibility="$dirroot/theme/$theme/pix/$path")) { 137 // Found the file in theme, stop looking 138 $file=$possibility; 139 } else { 140 // Is there a parent theme? 141 while(true) { 142 require("$dirroot/theme/$theme/config.php"); // Sets up $THEME 143 if(!$THEME->parent) { 144 break; 145 } 146 $theme=$THEME->parent; 147 if(file_exists($possibility="$dirroot/theme/$theme/pix/$path")) { 148 $file=$possibility; 149 // Found in parent theme 150 break; 151 } 152 } 153 if(!$file) { 154 if(preg_match('|^mod/|',$path)) { 155 if(!file_exists($possibility="$dirroot/$path")) { 156 error('Requested image not found.',true); 157 } 158 } else { 159 if(!file_exists($possibility="$dirroot/pix/$path")) { 160 error('Requested image not found.',true); 161 } 162 } 163 $file=$possibility; 164 } 165 } 166 167 // Now we have a file that exists. Not using send_file since it requires 168 // proper $CFG etc. 169 170 // Handle If-Modified-Since 171 $filedate=filemtime($file); 172 $ifmodifiedsince=isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? $_SERVER['HTTP_IF_MODIFIED_SINCE'] : false; 173 if($ifmodifiedsince && strtotime($ifmodifiedsince)>=$filedate) { 174 header('HTTP/1.0 304 Not Modified'); 175 exit; 176 } 177 header('Last-Modified: '.gmdate('D, d M Y H:i:s',$filedate).' GMT'); 178 179 // As I'm not loading config table from DB, this is hardcoded here; expiry 180 // 4 hours, unless the hacky file reduceimagecache.dat exists in dataroot 181 if(file_exists($reducefile=$dataroot.'/reduceimagecache.dat')) { 182 $lifetime=file_read_contents($reducefile); 183 } else { 184 $lifetime=4*60*60; 185 } 186 187 // Send expire headers 188 header('Cache-Control: max-age='.$lifetime); 189 header('Expires: '. gmdate('D, d M Y H:i:s', time() + $lifetime) .' GMT'); 190 191 // Type 192 header('Content-Type: '.$mimetype); 193 header('Content-Length: '.filesize($file)); 194 195 // Output file 196 $handle=fopen($file,'r'); 197 fpassthru($handle); 198 fclose($handle); 199 200 // Slower Moodle-style version follows: 201 202 //// Outputs pictures from theme or core pix folder. Only used if $CFG->smartpix is 203 //// turned on. 204 // 205 //$nomoodlecookie = true; // Stops it making a session 206 //require_once('../config.php'); 207 //require_once('../lib/filelib.php'); 208 //global $CFG; 209 // 210 //$matches=array(); // Reusable array variable for preg_match 211 // 212 //// Split path - starts with theme name, then actual image path inside pix 213 //$path=get_file_argument('smartpix.php'); 214 //$match=array(); 215 //if(!preg_match('|^/([a-z0-9_\-.]+)/([a-z0-9/_\-.]+)$|',$path,$match)) { 216 // error('Unexpected request format'); 217 //} 218 //list($junk,$theme,$path)=$match; 219 // 220 //// Check file type - this is not needed for the MIME types as we could 221 //// get those by the existing function, but it provides an extra layer of security 222 //// as otherwise this script could be used to view all files within dirroot/mod 223 //if(preg_match('/\.png$/',$path)) { 224 // $mimetype='image/png'; 225 //} else if(preg_match('/\.gif$/',$path)) { 226 // $mimetype='image/gif'; 227 //} else if(preg_match('/\.jpe?g$/',$path)) { 228 // $mimetype='image/jpeg'; 229 //} else { 230 // error('Request for non-image file'); 231 //} 232 // 233 //// Find actual location of image as $file 234 //$file=false; 235 //if(file_exists($possibility="$CFG->dirroot/theme/$theme/pix/$path")) { 236 // // Found the file in theme, stop looking 237 // $file=$possibility; 238 //} else { 239 // // Is there a parent theme? 240 // while(true) { 241 // require("$CFG->dirroot/theme/$theme/config.php"); // Sets up $THEME 242 // if(!$THEME->parent) { 243 // break; 244 // } 245 // $theme=$THEME->parent; 246 // if(file_exists($possibility="$CFG->dirroot/theme/$theme/pix/$path")) { 247 // $file=$possibility; 248 // // Found in parent theme 249 // break; 250 // } 251 // } 252 // if(!$file) { 253 // if(preg_match('|^mod/|',$path)) { 254 // if(!file_exists($possibility="$CFG->dirroot/$path")) { 255 // error('Requested image not found.'); 256 // } 257 // } else { 258 // if(!file_exists($possibility="$CFG->dirroot/pix/$path")) { 259 // error('Requested image not found.'); 260 // } 261 // } 262 // $file=$possibility; 263 // } 264 //} 265 // 266 //// Handle If-Modified-Since because send_file doesn't 267 //$filedate=filemtime($file); 268 //$ifmodifiedsince=isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? $_SERVER['HTTP_IF_MODIFIED_SINCE'] : false; 269 //if($ifmodifiedsince && strtotime($ifmodifiedsince)>=$filedate) { 270 // header('HTTP/1.0 304 Not Modified'); 271 // exit; 272 //} 273 //// Don't need to set last-modified, send_file does that 274 // 275 //if (empty($CFG->filelifetime)) { 276 // $lifetime = 86400; // Seconds for files to remain in caches 277 //} else { 278 // $lifetime = $CFG->filelifetime; 279 //} 280 //send_file($file,preg_replace('|^.*/|','',$file),$lifetime); 281 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Wed Jan 14 11:33:29 2009 | Cross-referenced by PHPXref 0.7 |