X-Git-Url: http://git.cyclocoop.org/?a=blobdiff_plain;f=includes%2FStreamFile.php;h=6539e08c991ffb2566b8dcdcc4f0b7e9f38200e1;hb=9948a2a16d95da9d569fb0a113d744761d5fa75b;hp=db470ffb44c8778c52fa3b52273c84cd4e1513d4;hpb=1a1e917c86ca9468bd3f0dfece93ba283552c61f;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/StreamFile.php b/includes/StreamFile.php index db470ffb44..6539e08c99 100644 --- a/includes/StreamFile.php +++ b/includes/StreamFile.php @@ -1,81 +1,153 @@ -

File not found

-

Although this PHP script ($encScript) exists, the file requested for output - ($encFile) does not.

- - "; - return; + + $res = self::prepareForStream( $fname, $stat, $headers, $sendErrors ); + if ( $res == self::NOT_MODIFIED ) { + $ok = true; // use client cache + } elseif ( $res == self::READY_STREAM ) { + wfProfileIn( __METHOD__ . '-send' ); + $ok = readfile( $fname ); + wfProfileOut( __METHOD__ . '-send' ); + } else { + $ok = false; // failed } - header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s', $stat['mtime'] ) . ' GMT' ); + wfProfileOut( __METHOD__ ); + return $ok; + } + + /** + * Call this function used in preparation before streaming a file. + * This function does the following: + * (a) sends Last-Modified, Content-type, and Content-Disposition headers + * (b) cancels any PHP output buffering and automatic gzipping of output + * (c) sends Content-Length header based on HTTP_IF_MODIFIED_SINCE check + * + * @param $path string Storage path or file system path + * @param $info Array|bool File stat info with 'mtime' and 'size' fields + * @param $headers Array Additional headers to send + * @param $sendErrors bool Send error messages if errors occur (like 404) + * @return int|bool READY_STREAM, NOT_MODIFIED, or false on failure + */ + public static function prepareForStream( + $path, $info, $headers = array(), $sendErrors = true + ) { + global $wgLanguageCode; + + if ( !is_array( $info ) ) { + if ( $sendErrors ) { + header( 'HTTP/1.0 404 Not Found' ); + header( 'Cache-Control: no-cache' ); + header( 'Content-Type: text/html; charset=utf-8' ); + $encFile = htmlspecialchars( $path ); + $encScript = htmlspecialchars( $_SERVER['SCRIPT_NAME'] ); + echo " +

File not found

+

Although this PHP script ($encScript) exists, the file requested for output + ($encFile) does not.

+ + "; + } + return false; + } + + // Sent Last-Modified HTTP header for client-side caching + header( 'Last-Modified: ' . wfTimestamp( TS_RFC2822, $info['mtime'] ) ); // Cancel output buffering and gzipping if set wfResetOutputBuffers(); - $type = self::getType( $fname ); + $type = self::contentTypeFromPath( $path ); if ( $type && $type != 'unknown/unknown' ) { header( "Content-type: $type" ); } else { + // Send a content type which is not known to Internet Explorer, to + // avoid triggering IE's content type detection. Sending a standard + // unknown content type here essentially gives IE license to apply + // whatever content type it likes. header( 'Content-type: application/x-wiki' ); } // Don't stream it out as text/html if there was a PHP error if ( headers_sent() ) { echo "Headers already sent, terminating.\n"; - return; + return false; } - global $wgLanguageCode; - header( "Content-Disposition: inline;filename*=utf-8'$wgLanguageCode'" . urlencode( basename( $fname ) ) ); + header( "Content-Disposition: inline;filename*=utf-8'$wgLanguageCode'" . + urlencode( basename( $path ) ) ); + // Send additional headers foreach ( $headers as $header ) { header( $header ); } + // Don't send if client has up to date cache if ( !empty( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) ) { $modsince = preg_replace( '/;.*$/', '', $_SERVER['HTTP_IF_MODIFIED_SINCE'] ); - $sinceTime = strtotime( $modsince ); - if ( $stat['mtime'] <= $sinceTime ) { + if ( wfTimestamp( TS_UNIX, $info['mtime'] ) <= strtotime( $modsince ) ) { ini_set( 'zlib.output_compression', 0 ); header( "HTTP/1.0 304 Not Modified" ); - return; + return self::NOT_MODIFIED; // ok } } - header( 'Content-Length: ' . $stat['size'] ); + header( 'Content-Length: ' . $info['size'] ); - readfile( $fname ); + return self::READY_STREAM; // ok } /** - * Determine the filetype we're dealing with - * @param $filename string - * @param $safe bool + * Determine the file type of a file based on the path + * + * @param $filename string Storage path or file system path + * @param $safe bool Whether to do retroactive upload blacklist checks * @return null|string */ - private static function getType( $filename, $safe = true ) { + public static function contentTypeFromPath( $filename, $safe = true ) { global $wgTrivialMimeDetection; $ext = strrchr( $filename, '.' );