MediaWiki REL1_35
OutputHandler.php
Go to the documentation of this file.
1<?php
23namespace MediaWiki;
24
36 public static function handle( $s, $phase ) {
38 if ( $phase | PHP_OUTPUT_HANDLER_CLEAN ) {
39 // Don't send headers if output is being discarded (T278579)
40 return $s;
41 }
43 $s = self::mangleFlashPolicy( $s );
44 }
45 if ( !$wgDisableOutputCompression && !ini_get( 'zlib.output_compression' ) ) {
46 if ( !defined( 'MW_NO_OUTPUT_COMPRESSION' ) ) {
47 $s = self::handleGzip( $s );
48 }
49 if ( !ini_get( 'output_handler' ) ) {
50 self::emitContentLength( strlen( $s ) );
51 }
52 }
53 return $s;
54 }
55
66 private static function findUriExtension() {
68 if ( isset( $_SERVER['REQUEST_URI'] ) ) {
69 // Strip the query string...
70 $path = explode( '?', $_SERVER['REQUEST_URI'], 2 )[0];
71 } elseif ( isset( $_SERVER['SCRIPT_NAME'] ) ) {
72 // Probably IIS. QUERY_STRING appears separately.
73 $path = $_SERVER['SCRIPT_NAME'];
74 } else {
75 // Can't get the path from the server? :(
76 return '';
77 }
78
79 $period = strrpos( $path, '.' );
80 if ( $period !== false ) {
81 return strtolower( substr( $path, $period ) );
82 }
83 return '';
84 }
85
94 private static function handleGzip( $s ) {
95 if ( !function_exists( 'gzencode' ) ) {
96 wfDebug( __METHOD__ . "() skipping compression (gzencode unavailable)" );
97 return $s;
98 }
99 if ( headers_sent() ) {
100 wfDebug( __METHOD__ . "() skipping compression (headers already sent)" );
101 return $s;
102 }
103
104 $ext = self::findUriExtension();
105 if ( $ext == '.gz' || $ext == '.tgz' ) {
106 // Don't do gzip compression if the URL path ends in .gz or .tgz
107 // This confuses Safari and triggers a download of the page,
108 // even though it's pretty clearly labeled as viewable HTML.
109 // Bad Safari! Bad!
110 return $s;
111 }
112
113 if ( wfClientAcceptsGzip() ) {
114 wfDebug( __METHOD__ . "() is compressing output" );
115 header( 'Content-Encoding: gzip' );
116 $s = gzencode( $s, 6 );
117 }
118
119 // Set vary header if it hasn't been set already
120 $headers = headers_list();
121 $foundVary = false;
122 foreach ( $headers as $header ) {
123 $headerName = strtolower( substr( $header, 0, 5 ) );
124 if ( $headerName == 'vary:' ) {
125 $foundVary = true;
126 break;
127 }
128 }
129 if ( !$foundVary ) {
130 header( 'Vary: Accept-Encoding' );
131 }
132 return $s;
133 }
134
141 private static function mangleFlashPolicy( $s ) {
142 # Avoid weird excessive memory usage in PCRE on big articles
143 if ( preg_match( '/<\s*cross-domain-policy(?=\s|>)/i', $s ) ) {
144 return preg_replace( '/<(\s*)(cross-domain-policy(?=\s|>))/i', '<$1NOT-$2', $s );
145 } else {
146 return $s;
147 }
148 }
149
155 private static function emitContentLength( $length ) {
156 if ( !headers_sent()
157 && isset( $_SERVER['SERVER_PROTOCOL'] )
158 && $_SERVER['SERVER_PROTOCOL'] == 'HTTP/1.0'
159 ) {
160 header( "Content-Length: $length" );
161 }
162 }
163}
$wgDisableOutputCompression
Disable output compression (enabled by default if zlib is available)
$wgMangleFlashPolicy
When OutputHandler is used, mangle any output that contains <cross-domain-policy>.
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfClientAcceptsGzip( $force=false)
Whether the client accept gzip encoding.
static handle( $s, $phase)
Standard output handler for use with ob_start.
static handleGzip( $s)
Handler that compresses data with gzip if allowed by the Accept header.
static emitContentLength( $length)
Add a Content-Length header if possible.
static mangleFlashPolicy( $s)
Mangle flash policy tags which open up the site to XSS attacks.
static findUriExtension()
Get the "file extension" that some client apps will estimate from the currently-requested URL.
A helper class for throttling authentication attempts.
if(!is_readable( $file)) $ext
Definition router.php:48
$header