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