StreamFile.php 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. <?php
  2. /** */
  3. /** */
  4. function wfStreamFile( $fname, $headers = array() ) {
  5. $stat = @stat( $fname );
  6. if ( !$stat ) {
  7. header( 'HTTP/1.0 404 Not Found' );
  8. header( 'Cache-Control: no-cache' );
  9. header( 'Content-Type: text/html; charset=utf-8' );
  10. $encFile = htmlspecialchars( $fname );
  11. $encScript = htmlspecialchars( $_SERVER['SCRIPT_NAME'] );
  12. echo "<html><body>
  13. <h1>File not found</h1>
  14. <p>Although this PHP script ($encScript) exists, the file requested for output
  15. ($encFile) does not.</p>
  16. </body></html>
  17. ";
  18. return;
  19. }
  20. header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s', $stat['mtime'] ) . ' GMT' );
  21. // Cancel output buffering and gzipping if set
  22. wfResetOutputBuffers();
  23. $type = wfGetType( $fname );
  24. if ( $type and $type!="unknown/unknown") {
  25. header("Content-type: $type");
  26. } else {
  27. header('Content-type: application/x-wiki');
  28. }
  29. // Don't stream it out as text/html if there was a PHP error
  30. if ( headers_sent() ) {
  31. echo "Headers already sent, terminating.\n";
  32. return;
  33. }
  34. global $wgContLanguageCode;
  35. header( "Content-Disposition: inline;filename*=utf-8'$wgContLanguageCode'" . urlencode( basename( $fname ) ) );
  36. foreach ( $headers as $header ) {
  37. header( $header );
  38. }
  39. if ( !empty( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) ) {
  40. $modsince = preg_replace( '/;.*$/', '', $_SERVER['HTTP_IF_MODIFIED_SINCE'] );
  41. $sinceTime = strtotime( $modsince );
  42. if ( $stat['mtime'] <= $sinceTime ) {
  43. ini_set('zlib.output_compression', 0);
  44. header( "HTTP/1.0 304 Not Modified" );
  45. return;
  46. }
  47. }
  48. header( 'Content-Length: ' . $stat['size'] );
  49. readfile( $fname );
  50. }
  51. /** */
  52. function wfGetType( $filename, $safe = true ) {
  53. global $wgTrivialMimeDetection;
  54. $ext = strrchr($filename, '.');
  55. $ext = $ext === false ? '' : strtolower( substr( $ext, 1 ) );
  56. # trivial detection by file extension,
  57. # used for thumbnails (thumb.php)
  58. if ($wgTrivialMimeDetection) {
  59. switch ($ext) {
  60. case 'gif': return 'image/gif';
  61. case 'png': return 'image/png';
  62. case 'jpg': return 'image/jpeg';
  63. case 'jpeg': return 'image/jpeg';
  64. }
  65. return 'unknown/unknown';
  66. }
  67. $magic = MimeMagic::singleton();
  68. // Use the extension only, rather than magic numbers, to avoid opening
  69. // up vulnerabilities due to uploads of files with allowed extensions
  70. // but disallowed types.
  71. $type = $magic->guessTypesForExtension( $ext );
  72. /**
  73. * Double-check some security settings that were done on upload but might
  74. * have changed since.
  75. */
  76. if ( $safe ) {
  77. global $wgFileBlacklist, $wgCheckFileExtensions, $wgStrictFileExtensions,
  78. $wgFileExtensions, $wgVerifyMimeType, $wgMimeTypeBlacklist, $wgRequest;
  79. $form = new UploadForm( $wgRequest );
  80. list( $partName, $extList ) = $form->splitExtensions( $filename );
  81. if ( $form->checkFileExtensionList( $extList, $wgFileBlacklist ) ) {
  82. return 'unknown/unknown';
  83. }
  84. if ( $wgCheckFileExtensions && $wgStrictFileExtensions
  85. && !$form->checkFileExtensionList( $extList, $wgFileExtensions ) )
  86. {
  87. return 'unknown/unknown';
  88. }
  89. if ( $wgVerifyMimeType && in_array( strtolower( $type ), $wgMimeTypeBlacklist ) ) {
  90. return 'unknown/unknown';
  91. }
  92. }
  93. return $type;
  94. }