[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/lib/exe/ -> fetch.php (source)

   1  <?php
   2  /**
   3   * DokuWiki media passthrough file
   4   *
   5   * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
   6   * @author     Andreas Gohr <andi@splitbrain.org>
   7   */
   8  
   9    if(!defined('DOKU_INC')) define('DOKU_INC',dirname(__FILE__).'/../../');
  10    define('DOKU_DISABLE_GZIP_OUTPUT', 1);
  11    require_once (DOKU_INC.'inc/init.php');
  12    require_once (DOKU_INC.'inc/common.php');
  13    require_once (DOKU_INC.'inc/media.php');
  14    require_once (DOKU_INC.'inc/pageutils.php');
  15    require_once (DOKU_INC.'inc/confutils.php');
  16    require_once (DOKU_INC.'inc/auth.php');
  17    //close sesseion
  18    session_write_close();
  19    if(!defined('CHUNK_SIZE')) define('CHUNK_SIZE',16*1024);
  20  
  21    $mimetypes = getMimeTypes();
  22  
  23    //get input
  24    $MEDIA  = stripctl(getID('media',false)); // no cleaning except control chars - maybe external
  25    $CACHE  = calc_cache($_REQUEST['cache']);
  26    $WIDTH  = (int) $_REQUEST['w'];
  27    $HEIGHT = (int) $_REQUEST['h'];
  28    list($EXT,$MIME) = mimetype($MEDIA);
  29    if($EXT === false){
  30      $EXT  = 'unknown';
  31      $MIME = 'application/octet-stream';
  32    }
  33  
  34    //media to local file
  35    if(preg_match('#^(https?)://#i',$MEDIA)){
  36      //handle external images
  37      if(strncmp($MIME,'image/',6) == 0) $FILE = media_get_from_URL($MEDIA,$EXT,$CACHE);
  38      if(!$FILE){
  39        //download failed - redirect to original URL
  40        header('Location: '.$MEDIA);
  41        exit;
  42      }
  43    }else{
  44      $MEDIA = cleanID($MEDIA);
  45      if(empty($MEDIA)){
  46        header("HTTP/1.0 400 Bad Request");
  47        print 'Bad request';
  48        exit;
  49      }
  50  
  51      //check permissions (namespace only)
  52      if(auth_quickaclcheck(getNS($MEDIA).':X') < AUTH_READ){
  53        header("HTTP/1.0 401 Unauthorized");
  54        //fixme add some image for imagefiles
  55        print 'Unauthorized';
  56        exit;
  57      }
  58      $FILE  = mediaFN($MEDIA);
  59    }
  60  
  61    //check file existance
  62    if(!@file_exists($FILE)){
  63      header("HTTP/1.0 404 Not Found");
  64      //FIXME add some default broken image
  65      print 'Not Found';
  66      exit;
  67    }
  68  
  69    $ORIG = $FILE;
  70  
  71    //handle image resizing/cropping
  72    if((substr($MIME,0,5) == 'image') && $WIDTH){
  73      if($HEIGHT){
  74          $FILE = media_crop_image($FILE,$EXT,$WIDTH,$HEIGHT);
  75      }else{
  76          $FILE = media_resize_image($FILE,$EXT,$WIDTH,$HEIGHT);
  77      }
  78    }
  79  
  80    // finally send the file to the client
  81    $data = array('file'   => $FILE,
  82                  'mime'   => $MIME,
  83                  'cache'  => $CACHE,
  84                  'orig'   => $ORIG,
  85                  'ext'    => $EXT,
  86                  'width'  => $WIDTH,
  87                  'height' => $HEIGHT);
  88  
  89    $evt = new Doku_Event('MEDIA_SENDFILE', $data);
  90    if ($evt->advise_before()) {
  91      sendFile($data['file'],$data['mime'],$data['cache']);
  92    }
  93  
  94  /* ------------------------------------------------------------------------ */
  95  
  96  /**
  97   * Set headers and send the file to the client
  98   *
  99   * @author Andreas Gohr <andi@splitbrain.org>
 100   * @author Ben Coburn <btcoburn@silicodon.net>
 101   */
 102  function sendFile($file,$mime,$cache){
 103    global $conf;
 104    $fmtime = @filemtime($file);
 105    // send headers
 106    header("Content-Type: $mime");
 107    // smart http caching headers
 108    if ($cache==-1) {
 109      // cache
 110      // cachetime or one hour
 111      header('Expires: '.gmdate("D, d M Y H:i:s", time()+max($conf['cachetime'], 3600)).' GMT');
 112      header('Cache-Control: public, proxy-revalidate, no-transform, max-age='.max($conf['cachetime'], 3600));
 113      header('Pragma: public');
 114    } else if ($cache>0) {
 115      // recache
 116      // remaining cachetime + 10 seconds so the newly recached media is used
 117      header('Expires: '.gmdate("D, d M Y H:i:s", $fmtime+$conf['cachetime']+10).' GMT');
 118      header('Cache-Control: public, proxy-revalidate, no-transform, max-age='.max($fmtime-time()+$conf['cachetime']+10, 0));
 119      header('Pragma: public');
 120    } else if ($cache==0) {
 121      // nocache
 122      header('Cache-Control: must-revalidate, no-transform, post-check=0, pre-check=0');
 123      header('Pragma: public');
 124    }
 125    //send important headers first, script stops here if '304 Not Modified' response
 126    http_conditionalRequest($fmtime);
 127  
 128  
 129    //application mime type is downloadable
 130    if(substr($mime,0,11) == 'application'){
 131      header('Content-Disposition: attachment; filename="'.basename($file).'";');
 132    }
 133  
 134    //use x-sendfile header to pass the delivery to compatible webservers
 135    if($conf['xsendfile'] == 1){
 136      header("X-LIGHTTPD-send-file: $file");
 137      exit;
 138    }elseif($conf['xsendfile'] == 2){
 139      header("X-Sendfile: $file");
 140      exit;
 141    }elseif($conf['xsendfile'] == 3){
 142      header("X-Accel-Redirect: $file");
 143      exit;
 144    }
 145  
 146    //support download continueing
 147    header('Accept-Ranges: bytes');
 148    list($start,$len) = http_rangeRequest(filesize($file));
 149  
 150    // send file contents
 151    $fp = @fopen($file,"rb");
 152    if($fp){
 153      fseek($fp,$start); //seek to start of range
 154  
 155      $chunk = ($len > CHUNK_SIZE) ? CHUNK_SIZE : $len;
 156      while (!feof($fp) && $chunk > 0) {
 157        @set_time_limit(30); // large files can take a lot of time
 158        print fread($fp, $chunk);
 159        flush();
 160        $len -= $chunk;
 161        $chunk = ($len > CHUNK_SIZE) ? CHUNK_SIZE : $len;
 162      }
 163      fclose($fp);
 164    }else{
 165      header("HTTP/1.0 500 Internal Server Error");
 166      print "Could not read $file - bad permissions?";
 167    }
 168  }
 169  
 170  /**
 171   * Checks and sets headers to handle range requets
 172   *
 173   * @author  Andreas Gohr <andi@splitbrain.org>
 174   * @returns array The start byte and the amount of bytes to send
 175   */
 176  function http_rangeRequest($size){
 177    if(!isset($_SERVER['HTTP_RANGE'])){
 178      // no range requested - send the whole file
 179      header("Content-Length: $size");
 180      return array(0,$size);
 181    }
 182  
 183    $t = explode('=', $_SERVER['HTTP_RANGE']);
 184    if (!$t[0]=='bytes') {
 185      // we only understand byte ranges - send the whole file
 186      header("Content-Length: $size");
 187      return array(0,$size);
 188    }
 189  
 190    $r = explode('-', $t[1]);
 191    $start = (int)$r[0];
 192    $end = (int)$r[1];
 193    if (!$end) $end = $size - 1;
 194    if ($start > $end || $start > $size || $end > $size){
 195      header('HTTP/1.1 416 Requested Range Not Satisfiable');
 196      print 'Bad Range Request!';
 197      exit;
 198    }
 199  
 200    $tot = $end - $start + 1;
 201    header('HTTP/1.1 206 Partial Content');
 202    header("Content-Range: bytes {$start}-{$end}/{$size}");
 203    header("Content-Length: $tot");
 204  
 205    return array($start,$tot);
 206  }
 207  
 208  /**
 209   * Returns the wanted cachetime in seconds
 210   *
 211   * Resolves named constants
 212   *
 213   * @author  Andreas Gohr <andi@splitbrain.org>
 214   */
 215  function calc_cache($cache){
 216    global $conf;
 217  
 218    if(strtolower($cache) == 'nocache') return 0; //never cache
 219    if(strtolower($cache) == 'recache') return $conf['cachetime']; //use standard cache
 220    return -1; //cache endless
 221  }
 222  
 223  //Setup VIM: ex: et ts=2 enc=utf-8 :
 224  ?>


Generated: Tue Dec 2 01:30:01 2008 Cross-referenced by PHPXref 0.7