From f4080c18382721a1c351b1913a17b0e1ea66af86 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Thu, 19 Jul 2007 19:06:32 +0000 Subject: [PATCH] Don't do gzip compression if the URL path ends in .gz or .tgz This confuses Safari and triggers a download of the page, even though it's pretty clearly labeled as viewable HTML. Bad Safari! Bad! Bug is still present in Safari 2.0.4/Mac and 3.0.2/Win. We have had a live hack for this on Wikimedia sites for .gz files; hadn't noticed the .tgz problem before though. While I was in there, also made a tweak so wfGzipHandler() makes sure the Vary: header is there whether the current agent sent us an Accept-Encoding header or not. --- RELEASE-NOTES | 1 + includes/OutputHandler.php | 73 ++++++++++++++++++++++++++++---------- 2 files changed, 56 insertions(+), 18 deletions(-) diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 0b879c5a1b..d37f86c7bf 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -315,6 +315,7 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN * Fix several JavaScript bugs under MSIE 5/Macintosh * (bug 10591) Use Arabic numerals (0,1,2...) for the Malayam language * (bug 10642) Fix shift-click checkbox behavior for Opera 9.0+ and 6.0 +* Work around Safari bug with pages ending in ".gz" or ".tgz" == API changes since 1.10 == diff --git a/includes/OutputHandler.php b/includes/OutputHandler.php index 6b19afdb91..d8ac12b531 100644 --- a/includes/OutputHandler.php +++ b/includes/OutputHandler.php @@ -17,31 +17,68 @@ function wfOutputHandler( $s ) { return $s; } +/** + * Get the "file extension" that some client apps will estimate from + * the currently-requested URL. + * This isn't on WebRequest because we need it when things aren't initialized + * @private + */ +function wfRequestExtension() { + /// @fixme -- this sort of dupes some code in WebRequest::getRequestUrl() + if( isset( $_SERVER['REQUEST_URI'] ) ) { + // Strip the query string... + list( $path ) = explode( '?', $_SERVER['REQUEST_URI'], 2 ); + } elseif( isset( $_SERVER['SCRIPT_NAME'] ) ) { + // Probably IIS. QUERY_STRING appears separately. + $path = $_SERVER['SCRIPT_NAME']; + } else { + // Can't get the path from the server? :( + return ''; + } + + $period = strrpos( $path, '.' ); + if( $period !== false ) { + return strtolower( substr( $path, $period ) ); + } + return ''; +} + /** * Handler that compresses data with gzip if allowed by the Accept header. * Unlike ob_gzhandler, it works for HEAD requests too. */ function wfGzipHandler( $s ) { - if ( function_exists( 'gzencode' ) && !headers_sent() ) { - $tokens = preg_split( '/[,; ]/', $_SERVER['HTTP_ACCEPT_ENCODING'] ); - if ( in_array( 'gzip', $tokens ) ) { - header( 'Content-Encoding: gzip' ); - $s = gzencode( $s, 3 ); - - # Set vary header if it hasn't been set already - $headers = headers_list(); - $foundVary = false; - foreach ( $headers as $header ) { - if ( substr( $header, 0, 5 ) == 'Vary:' ) { - $foundVary = true; - break; - } - } - if ( !$foundVary ) { - header( 'Vary: Accept-Encoding' ); - } + if( !function_exists( 'gzencode' ) || headers_sent() ) { + return $s; + } + + $ext = wfRequestExtension(); + if( $ext == '.gz' || $ext == '.tgz' ) { + // Don't do gzip compression if the URL path ends in .gz or .tgz + // This confuses Safari and triggers a download of the page, + // even though it's pretty clearly labeled as viewable HTML. + // Bad Safari! Bad! + return $s; + } + + $tokens = preg_split( '/[,; ]/', $_SERVER['HTTP_ACCEPT_ENCODING'] ); + if ( in_array( 'gzip', $tokens ) ) { + header( 'Content-Encoding: gzip' ); + $s = gzencode( $s, 3 ); + } + + // Set vary header if it hasn't been set already + $headers = headers_list(); + $foundVary = false; + foreach ( $headers as $header ) { + if ( substr( $header, 0, 5 ) == 'Vary:' ) { + $foundVary = true; + break; } } + if ( !$foundVary ) { + header( 'Vary: Accept-Encoding' ); + } return $s; } -- 2.20.1