[ Index ]

PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008]

title

Body

[close]

/pix/ -> smartpix.php (source)

   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  ?>


Generated: Wed Jan 14 11:33:29 2009 Cross-referenced by PHPXref 0.7