PageRenderTime 67ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/private/files/type/detection.php

https://gitlab.com/Red54/core
PHP | 173 lines | 77 code | 15 blank | 81 comment | 13 complexity | adb43fd5436b10da0b572ca8eaa2457b MD5 | raw file
  1. <?php
  2. /**
  3. * @author Andreas Fischer <bantu@owncloud.com>
  4. * @author Jens-Christian Fischer <jens-christian.fischer@switch.ch>
  5. * @author Morris Jobke <hey@morrisjobke.de>
  6. * @author Robin Appelman <icewind@owncloud.com>
  7. * @author Thomas Tanghus <thomas@tanghus.net>
  8. *
  9. * @copyright Copyright (c) 2015, ownCloud, Inc.
  10. * @license AGPL-3.0
  11. *
  12. * This code is free software: you can redistribute it and/or modify
  13. * it under the terms of the GNU Affero General Public License, version 3,
  14. * as published by the Free Software Foundation.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU Affero General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU Affero General Public License, version 3,
  22. * along with this program. If not, see <http://www.gnu.org/licenses/>
  23. *
  24. */
  25. namespace OC\Files\Type;
  26. /**
  27. * Class Detection
  28. *
  29. * Mimetype detection
  30. *
  31. * @package OC\Files\Type
  32. */
  33. class Detection {
  34. protected $mimetypes = array();
  35. protected $secureMimeTypes = array();
  36. /**
  37. * Add an extension -> mimetype mapping
  38. *
  39. * $mimetype is the assumed correct mime type
  40. * The optional $secureMimeType is an alternative to send to send
  41. * to avoid potential XSS.
  42. *
  43. * @param string $extension
  44. * @param string $mimetype
  45. * @param string|null $secureMimeType
  46. */
  47. public function registerType($extension, $mimetype, $secureMimeType = null) {
  48. $this->mimetypes[$extension] = array($mimetype, $secureMimeType);
  49. $this->secureMimeTypes[$mimetype] = $secureMimeType ?: $mimetype;
  50. }
  51. /**
  52. * Add an array of extension -> mimetype mappings
  53. *
  54. * The mimetype value is in itself an array where the first index is
  55. * the assumed correct mimetype and the second is either a secure alternative
  56. * or null if the correct is considered secure.
  57. *
  58. * @param array $types
  59. */
  60. public function registerTypeArray($types) {
  61. $this->mimetypes = array_merge($this->mimetypes, $types);
  62. // Update the alternative mimetypes to avoid having to look them up each time.
  63. foreach ($this->mimetypes as $mimeType) {
  64. $this->secureMimeTypes[$mimeType[0]] = $mimeType[1] ?: $mimeType[0];
  65. }
  66. }
  67. /**
  68. * detect mimetype only based on filename, content of file is not used
  69. *
  70. * @param string $path
  71. * @return string
  72. */
  73. public function detectPath($path) {
  74. if (strpos($path, '.')) {
  75. //try to guess the type by the file extension
  76. $extension = strtolower(strrchr(basename($path), "."));
  77. $extension = substr($extension, 1); //remove leading .
  78. return (isset($this->mimetypes[$extension]) && isset($this->mimetypes[$extension][0]))
  79. ? $this->mimetypes[$extension][0]
  80. : 'application/octet-stream';
  81. } else {
  82. return 'application/octet-stream';
  83. }
  84. }
  85. /**
  86. * detect mimetype based on both filename and content
  87. *
  88. * @param string $path
  89. * @return string
  90. */
  91. public function detect($path) {
  92. if (@is_dir($path)) {
  93. // directories are easy
  94. return "httpd/unix-directory";
  95. }
  96. $mimeType = $this->detectPath($path);
  97. if ($mimeType === 'application/octet-stream' and function_exists('finfo_open')
  98. and function_exists('finfo_file') and $finfo = finfo_open(FILEINFO_MIME)
  99. ) {
  100. $info = @strtolower(finfo_file($finfo, $path));
  101. finfo_close($finfo);
  102. if ($info) {
  103. $mimeType = substr($info, 0, strpos($info, ';'));
  104. return empty($mimeType) ? 'application/octet-stream' : $mimeType;
  105. }
  106. }
  107. $isWrapped = (strpos($path, '://') !== false) and (substr($path, 0, 7) === 'file://');
  108. if (!$isWrapped and $mimeType === 'application/octet-stream' && function_exists("mime_content_type")) {
  109. // use mime magic extension if available
  110. $mimeType = mime_content_type($path);
  111. }
  112. if (!$isWrapped and $mimeType === 'application/octet-stream' && \OC_Helper::canExecute("file")) {
  113. // it looks like we have a 'file' command,
  114. // lets see if it does have mime support
  115. $path = escapeshellarg($path);
  116. $fp = popen("file -b --mime-type $path 2>/dev/null", "r");
  117. $reply = fgets($fp);
  118. pclose($fp);
  119. //trim the newline
  120. $mimeType = trim($reply);
  121. if (empty($mimeType)) {
  122. $mimeType = 'application/octet-stream';
  123. }
  124. }
  125. return $mimeType;
  126. }
  127. /**
  128. * detect mimetype based on the content of a string
  129. *
  130. * @param string $data
  131. * @return string
  132. */
  133. public function detectString($data) {
  134. if (function_exists('finfo_open') and function_exists('finfo_file')) {
  135. $finfo = finfo_open(FILEINFO_MIME);
  136. return finfo_buffer($finfo, $data);
  137. } else {
  138. $tmpFile = \OC_Helper::tmpFile();
  139. $fh = fopen($tmpFile, 'wb');
  140. fwrite($fh, $data, 8024);
  141. fclose($fh);
  142. $mime = $this->detect($tmpFile);
  143. unset($tmpFile);
  144. return $mime;
  145. }
  146. }
  147. /**
  148. * Get a secure mimetype that won't expose potential XSS.
  149. *
  150. * @param string $mimeType
  151. * @return string
  152. */
  153. public function getSecureMimeType($mimeType) {
  154. return isset($this->secureMimeTypes[$mimeType])
  155. ? $this->secureMimeTypes[$mimeType]
  156. : 'application/octet-stream';
  157. }
  158. }