MediaWiki
REL1_19
|
00001 <?php 00007 class StreamFile { 00008 const READY_STREAM = 1; 00009 const NOT_MODIFIED = 2; 00010 00021 public static function stream( $fname, $headers = array(), $sendErrors = true ) { 00022 wfSuppressWarnings(); 00023 $stat = stat( $fname ); 00024 wfRestoreWarnings(); 00025 00026 $res = self::prepareForStream( $fname, $stat, $headers, $sendErrors ); 00027 if ( $res == self::NOT_MODIFIED ) { 00028 return true; // use client cache 00029 } elseif ( $res == self::READY_STREAM ) { 00030 return readfile( $fname ); 00031 } else { 00032 return false; // failed 00033 } 00034 } 00035 00049 public static function prepareForStream( 00050 $path, $info, $headers = array(), $sendErrors = true 00051 ) { 00052 global $wgLanguageCode; 00053 00054 if ( !is_array( $info ) ) { 00055 if ( $sendErrors ) { 00056 header( 'HTTP/1.0 404 Not Found' ); 00057 header( 'Cache-Control: no-cache' ); 00058 header( 'Content-Type: text/html; charset=utf-8' ); 00059 $encFile = htmlspecialchars( $path ); 00060 $encScript = htmlspecialchars( $_SERVER['SCRIPT_NAME'] ); 00061 echo "<html><body> 00062 <h1>File not found</h1> 00063 <p>Although this PHP script ($encScript) exists, the file requested for output 00064 ($encFile) does not.</p> 00065 </body></html> 00066 "; 00067 } 00068 return false; 00069 } 00070 00071 // Sent Last-Modified HTTP header for client-side caching 00072 header( 'Last-Modified: ' . wfTimestamp( TS_RFC2822, $info['mtime'] ) ); 00073 00074 // Cancel output buffering and gzipping if set 00075 wfResetOutputBuffers(); 00076 00077 $type = self::contentTypeFromPath( $path ); 00078 if ( $type && $type != 'unknown/unknown' ) { 00079 header( "Content-type: $type" ); 00080 } else { 00081 // Send a content type which is not known to Internet Explorer, to 00082 // avoid triggering IE's content type detection. Sending a standard 00083 // unknown content type here essentially gives IE license to apply 00084 // whatever content type it likes. 00085 header( 'Content-type: application/x-wiki' ); 00086 } 00087 00088 // Don't stream it out as text/html if there was a PHP error 00089 if ( headers_sent() ) { 00090 echo "Headers already sent, terminating.\n"; 00091 return false; 00092 } 00093 00094 header( "Content-Disposition: inline;filename*=utf-8'$wgLanguageCode'" . 00095 urlencode( basename( $path ) ) ); 00096 00097 // Send additional headers 00098 foreach ( $headers as $header ) { 00099 header( $header ); 00100 } 00101 00102 // Don't send if client has up to date cache 00103 if ( !empty( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) ) { 00104 $modsince = preg_replace( '/;.*$/', '', $_SERVER['HTTP_IF_MODIFIED_SINCE'] ); 00105 if ( wfTimestamp( TS_UNIX, $info['mtime'] ) <= strtotime( $modsince ) ) { 00106 ini_set( 'zlib.output_compression', 0 ); 00107 header( "HTTP/1.0 304 Not Modified" ); 00108 return self::NOT_MODIFIED; // ok 00109 } 00110 } 00111 00112 header( 'Content-Length: ' . $info['size'] ); 00113 00114 return self::READY_STREAM; // ok 00115 } 00116 00124 public static function contentTypeFromPath( $filename, $safe = true ) { 00125 global $wgTrivialMimeDetection; 00126 00127 $ext = strrchr( $filename, '.' ); 00128 $ext = $ext === false ? '' : strtolower( substr( $ext, 1 ) ); 00129 00130 # trivial detection by file extension, 00131 # used for thumbnails (thumb.php) 00132 if ( $wgTrivialMimeDetection ) { 00133 switch ( $ext ) { 00134 case 'gif': return 'image/gif'; 00135 case 'png': return 'image/png'; 00136 case 'jpg': return 'image/jpeg'; 00137 case 'jpeg': return 'image/jpeg'; 00138 } 00139 00140 return 'unknown/unknown'; 00141 } 00142 00143 $magic = MimeMagic::singleton(); 00144 // Use the extension only, rather than magic numbers, to avoid opening 00145 // up vulnerabilities due to uploads of files with allowed extensions 00146 // but disallowed types. 00147 $type = $magic->guessTypesForExtension( $ext ); 00148 00153 if ( $safe ) { 00154 global $wgFileBlacklist, $wgCheckFileExtensions, $wgStrictFileExtensions, 00155 $wgFileExtensions, $wgVerifyMimeType, $wgMimeTypeBlacklist; 00156 list( , $extList ) = UploadBase::splitExtensions( $filename ); 00157 if ( UploadBase::checkFileExtensionList( $extList, $wgFileBlacklist ) ) { 00158 return 'unknown/unknown'; 00159 } 00160 if ( $wgCheckFileExtensions && $wgStrictFileExtensions 00161 && !UploadBase::checkFileExtensionList( $extList, $wgFileExtensions ) ) 00162 { 00163 return 'unknown/unknown'; 00164 } 00165 if ( $wgVerifyMimeType && in_array( strtolower( $type ), $wgMimeTypeBlacklist ) ) { 00166 return 'unknown/unknown'; 00167 } 00168 } 00169 return $type; 00170 } 00171 }