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/httputils.php'); 16 require_once(DOKU_INC.'inc/confutils.php'); 17 require_once(DOKU_INC.'inc/auth.php'); 18 19 //close sesseion 20 session_write_close(); 21 22 $mimetypes = getMimeTypes(); 23 24 //get input 25 $MEDIA = stripctl(getID('media',false)); // no cleaning except control chars - maybe external 26 $CACHE = calc_cache($_REQUEST['cache']); 27 $WIDTH = (int) $_REQUEST['w']; 28 $HEIGHT = (int) $_REQUEST['h']; 29 list($EXT,$MIME,$DL) = mimetype($MEDIA); 30 if($EXT === false){ 31 $EXT = 'unknown'; 32 $MIME = 'application/octet-stream'; 33 $DL = true; 34 } 35 36 //media to local file 37 if(preg_match('#^(https?)://#i',$MEDIA)){ 38 //handle external images 39 if(strncmp($MIME,'image/',6) == 0) $FILE = media_get_from_URL($MEDIA,$EXT,$CACHE); 40 if(!$FILE){ 41 //download failed - redirect to original URL 42 header('Location: '.$MEDIA); 43 exit; 44 } 45 }else{ 46 $MEDIA = cleanID($MEDIA); 47 if(empty($MEDIA)){ 48 header("HTTP/1.0 400 Bad Request"); 49 print 'Bad request'; 50 exit; 51 } 52 53 //check permissions (namespace only) 54 if(auth_quickaclcheck(getNS($MEDIA).':X') < AUTH_READ){ 55 header("HTTP/1.0 401 Unauthorized"); 56 //fixme add some image for imagefiles 57 print 'Unauthorized'; 58 exit; 59 } 60 $FILE = mediaFN($MEDIA); 61 } 62 63 //check file existance 64 if(!@file_exists($FILE)){ 65 header("HTTP/1.0 404 Not Found"); 66 //FIXME add some default broken image 67 print 'Not Found'; 68 exit; 69 } 70 71 $ORIG = $FILE; 72 73 //handle image resizing/cropping 74 if((substr($MIME,0,5) == 'image') && $WIDTH){ 75 if($HEIGHT){ 76 $FILE = media_crop_image($FILE,$EXT,$WIDTH,$HEIGHT); 77 }else{ 78 $FILE = media_resize_image($FILE,$EXT,$WIDTH,$HEIGHT); 79 } 80 } 81 82 // finally send the file to the client 83 $data = array('file' => $FILE, 84 'mime' => $MIME, 85 'download' => $DL, 86 'cache' => $CACHE, 87 'orig' => $ORIG, 88 'ext' => $EXT, 89 'width' => $WIDTH, 90 'height' => $HEIGHT); 91 92 $evt = new Doku_Event('MEDIA_SENDFILE', $data); 93 if ($evt->advise_before()) { 94 sendFile($data['file'],$data['mime'],$data['download'],$data['cache']); 95 } 96 97/* ------------------------------------------------------------------------ */ 98 99/** 100 * Set headers and send the file to the client 101 * 102 * @author Andreas Gohr <andi@splitbrain.org> 103 * @author Ben Coburn <btcoburn@silicodon.net> 104 */ 105function sendFile($file,$mime,$dl,$cache){ 106 global $conf; 107 $fmtime = @filemtime($file); 108 // send headers 109 header("Content-Type: $mime"); 110 // smart http caching headers 111 if ($cache==-1) { 112 // cache 113 // cachetime or one hour 114 header('Expires: '.gmdate("D, d M Y H:i:s", time()+max($conf['cachetime'], 3600)).' GMT'); 115 header('Cache-Control: public, proxy-revalidate, no-transform, max-age='.max($conf['cachetime'], 3600)); 116 header('Pragma: public'); 117 } else if ($cache>0) { 118 // recache 119 // remaining cachetime + 10 seconds so the newly recached media is used 120 header('Expires: '.gmdate("D, d M Y H:i:s", $fmtime+$conf['cachetime']+10).' GMT'); 121 header('Cache-Control: public, proxy-revalidate, no-transform, max-age='.max($fmtime-time()+$conf['cachetime']+10, 0)); 122 header('Pragma: public'); 123 } else if ($cache==0) { 124 // nocache 125 header('Cache-Control: must-revalidate, no-transform, post-check=0, pre-check=0'); 126 header('Pragma: public'); 127 } 128 //send important headers first, script stops here if '304 Not Modified' response 129 http_conditionalRequest($fmtime); 130 131 132 //download or display? 133 if($dl){ 134 header('Content-Disposition: attachment; filename="'.basename($file).'";'); 135 }else{ 136 header('Content-Disposition: inline; filename="'.basename($file).'";'); 137 } 138 139 //use x-sendfile header to pass the delivery to compatible webservers 140 if (http_sendfile($file)) exit; 141 142 // send file contents 143 $fp = @fopen($file,"rb"); 144 if($fp){ 145 http_rangeRequest($fp,filesize($file),$mime); 146 }else{ 147 header("HTTP/1.0 500 Internal Server Error"); 148 print "Could not read $file - bad permissions?"; 149 } 150} 151 152/** 153 * Returns the wanted cachetime in seconds 154 * 155 * Resolves named constants 156 * 157 * @author Andreas Gohr <andi@splitbrain.org> 158 */ 159function calc_cache($cache){ 160 global $conf; 161 162 if(strtolower($cache) == 'nocache') return 0; //never cache 163 if(strtolower($cache) == 'recache') return $conf['cachetime']; //use standard cache 164 return -1; //cache endless 165} 166 167//Setup VIM: ex: et ts=2 enc=utf-8 : 168?> 169