PageRenderTime 63ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/includes/StreamFile.php

https://bitbucket.org/andersus/querytalogo
PHP | 144 lines | 63 code | 12 blank | 69 comment | 10 complexity | 65f5e71c588daf3b0019eced7294eddd MD5 | raw file
Possible License(s): LGPL-3.0, MPL-2.0-no-copyleft-exception, JSON, MIT, CC0-1.0, BSD-3-Clause, Apache-2.0, BSD-2-Clause, LGPL-2.1, GPL-2.0
  1. <?php
  2. /**
  3. * Functions related to the output of file content.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, write to the Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. * http://www.gnu.org/copyleft/gpl.html
  19. *
  20. * @file
  21. */
  22. /**
  23. * Functions related to the output of file content
  24. */
  25. class StreamFile {
  26. // Do not send any HTTP headers unless requested by caller (e.g. body only)
  27. const STREAM_HEADLESS = HTTPFileStreamer::STREAM_HEADLESS;
  28. // Do not try to tear down any PHP output buffers
  29. const STREAM_ALLOW_OB = HTTPFileStreamer::STREAM_ALLOW_OB;
  30. /**
  31. * Stream a file to the browser, adding all the headings and fun stuff.
  32. * Headers sent include: Content-type, Content-Length, Last-Modified,
  33. * and Content-Disposition.
  34. *
  35. * @param string $fname Full name and path of the file to stream
  36. * @param array $headers Any additional headers to send if the file exists
  37. * @param bool $sendErrors Send error messages if errors occur (like 404)
  38. * @param array $optHeaders HTTP request header map (e.g. "range") (use lowercase keys)
  39. * @param int $flags Bitfield of STREAM_* constants
  40. * @throws MWException
  41. * @return bool Success
  42. */
  43. public static function stream(
  44. $fname, $headers = [], $sendErrors = true, $optHeaders = [], $flags = 0
  45. ) {
  46. if ( FileBackend::isStoragePath( $fname ) ) { // sanity
  47. throw new InvalidArgumentException( __FUNCTION__ . " given storage path '$fname'." );
  48. }
  49. $streamer = new HTTPFileStreamer(
  50. $fname,
  51. [
  52. 'obResetFunc' => 'wfResetOutputBuffers',
  53. 'streamMimeFunc' => [ __CLASS__, 'contentTypeFromPath' ]
  54. ]
  55. );
  56. return $streamer->stream( $headers, $sendErrors, $optHeaders, $flags );
  57. }
  58. /**
  59. * Send out a standard 404 message for a file
  60. *
  61. * @param string $fname Full name and path of the file to stream
  62. * @param int $flags Bitfield of STREAM_* constants
  63. * @since 1.24
  64. */
  65. public static function send404Message( $fname, $flags = 0 ) {
  66. HTTPFileStreamer::send404Message( $fname, $flags );
  67. }
  68. /**
  69. * Convert a Range header value to an absolute (start, end) range tuple
  70. *
  71. * @param string $range Range header value
  72. * @param int $size File size
  73. * @return array|string Returns error string on failure (start, end, length)
  74. * @since 1.24
  75. */
  76. public static function parseRange( $range, $size ) {
  77. return HTTPFileStreamer::parseRange( $range, $size );
  78. }
  79. /**
  80. * Determine the file type of a file based on the path
  81. *
  82. * @param string $filename Storage path or file system path
  83. * @param bool $safe Whether to do retroactive upload blacklist checks
  84. * @return null|string
  85. */
  86. public static function contentTypeFromPath( $filename, $safe = true ) {
  87. global $wgTrivialMimeDetection;
  88. $ext = strrchr( $filename, '.' );
  89. $ext = $ext === false ? '' : strtolower( substr( $ext, 1 ) );
  90. # trivial detection by file extension,
  91. # used for thumbnails (thumb.php)
  92. if ( $wgTrivialMimeDetection ) {
  93. switch ( $ext ) {
  94. case 'gif':
  95. return 'image/gif';
  96. case 'png':
  97. return 'image/png';
  98. case 'jpg':
  99. return 'image/jpeg';
  100. case 'jpeg':
  101. return 'image/jpeg';
  102. }
  103. return 'unknown/unknown';
  104. }
  105. $magic = MimeMagic::singleton();
  106. // Use the extension only, rather than magic numbers, to avoid opening
  107. // up vulnerabilities due to uploads of files with allowed extensions
  108. // but disallowed types.
  109. $type = $magic->guessTypesForExtension( $ext );
  110. /**
  111. * Double-check some security settings that were done on upload but might
  112. * have changed since.
  113. */
  114. if ( $safe ) {
  115. global $wgFileBlacklist, $wgCheckFileExtensions, $wgStrictFileExtensions,
  116. $wgFileExtensions, $wgVerifyMimeType, $wgMimeTypeBlacklist;
  117. list( , $extList ) = UploadBase::splitExtensions( $filename );
  118. if ( UploadBase::checkFileExtensionList( $extList, $wgFileBlacklist ) ) {
  119. return 'unknown/unknown';
  120. }
  121. if ( $wgCheckFileExtensions && $wgStrictFileExtensions
  122. && !UploadBase::checkFileExtensionList( $extList, $wgFileExtensions )
  123. ) {
  124. return 'unknown/unknown';
  125. }
  126. if ( $wgVerifyMimeType && in_array( strtolower( $type ), $wgMimeTypeBlacklist ) ) {
  127. return 'unknown/unknown';
  128. }
  129. }
  130. return $type;
  131. }
  132. }