Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions build/psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2037,11 +2037,6 @@
<code><![CDATA[!$isDefaultTemplates]]></code>
</RedundantCondition>
</file>
<file src="lib/private/Files/Type/Detection.php">
<ParamNameMismatch>
<code><![CDATA[$mimetype]]></code>
</ParamNameMismatch>
</file>
<file src="lib/private/Files/View.php">
<InvalidScalarArgument>
<code><![CDATA[$mtime]]></code>
Expand Down
103 changes: 52 additions & 51 deletions lib/private/Files/Type/Detection.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
namespace OC\Files\Type;

use OCP\Files\IMimeTypeDetector;
use OCP\ITempManager;
use OCP\IURLGenerator;
use Psr\Log\LoggerInterface;

Expand All @@ -24,10 +25,10 @@ class Detection implements IMimeTypeDetector {
private const CUSTOM_MIMETYPEALIASES = 'mimetypealiases.json';

/** @var array<list{string, string|null}> */
protected array $mimetypes = [];
protected array $mimeTypes = [];
protected array $secureMimeTypes = [];

protected array $mimetypeIcons = [];
protected array $mimeTypeIcons = [];
/** @var array<string,string> */
protected array $mimeTypeAlias = [];

Expand All @@ -40,30 +41,30 @@ public function __construct(
}

/**
* Add an extension -> mimetype mapping
* Add an extension -> MIME type mapping
*
* $mimetype is the assumed correct mime type
* $mimeType is the assumed correct mime type
* The optional $secureMimeType is an alternative to send to send
* to avoid potential XSS.
*
* @param string $extension
* @param string $mimetype
* @param string $mimeType
* @param string|null $secureMimeType
*/
public function registerType(string $extension,
string $mimetype,
string $mimeType,
?string $secureMimeType = null): void {
// Make sure the extension is a string
// https://github.com/nextcloud/server/issues/42902
$this->mimetypes[$extension] = [$mimetype, $secureMimeType];
$this->secureMimeTypes[$mimetype] = $secureMimeType ?: $mimetype;
$this->mimeTypes[$extension] = [$mimeType, $secureMimeType];
$this->secureMimeTypes[$mimeType] = $secureMimeType ?? $mimeType;
}

/**
* Add an array of extension -> mimetype mappings
* Add an array of extension -> MIME type mappings
*
* The mimetype value is in itself an array where the first index is
* the assumed correct mimetype and the second is either a secure alternative
* The mimeType value is in itself an array where the first index is
* the assumed correct mimeType and the second is either a secure alternative
* or null if the correct is considered secure.
*
* @param array $types
Expand All @@ -74,8 +75,8 @@ public function registerTypeArray(array $types): void {
$this->registerType((string)$extension, $mimeType[0], $mimeType[1] ?? null);
}

// Update the alternative mimetypes to avoid having to look them up each time.
foreach ($this->mimetypes as $extension => $mimeType) {
// Update the alternative mimeTypes to avoid having to look them up each time.
foreach ($this->mimeTypes as $extension => $mimeType) {
if (str_starts_with((string)$extension, '_comment')) {
continue;
}
Expand All @@ -100,7 +101,7 @@ private function loadCustomDefinitions(string $fileName, array $definitions): ar
}

/**
* Add the mimetype aliases if they are not yet present
* Add the MIME type aliases if they are not yet present
*/
private function loadAliases(): void {
if (!empty($this->mimeTypeAlias)) {
Expand All @@ -126,29 +127,29 @@ public function getOnlyDefaultAliases(): array {
}

/**
* Add mimetype mappings if they are not yet present
* Add MIME type mappings if they are not yet present
*/
private function loadMappings(): void {
if (!empty($this->mimetypes)) {
if (!empty($this->mimeTypes)) {
return;
}

$mimetypeMapping = json_decode(file_get_contents($this->defaultConfigDir . '/mimetypemapping.dist.json'), true);
$mimetypeMapping = $this->loadCustomDefinitions(self::CUSTOM_MIMETYPEMAPPING, $mimetypeMapping);
$mimeTypeMapping = json_decode(file_get_contents($this->defaultConfigDir . '/mimetypemapping.dist.json'), true);
$mimeTypeMapping = $this->loadCustomDefinitions(self::CUSTOM_MIMETYPEMAPPING, $mimeTypeMapping);

$this->registerTypeArray($mimetypeMapping);
$this->registerTypeArray($mimeTypeMapping);
}

/**
* @return array<list{string, string|null}>
*/
public function getAllMappings(): array {
$this->loadMappings();
return $this->mimetypes;
return $this->mimeTypes;
}

/**
* detect mimetype only based on filename, content of file is not used
* detect MIME type only based on filename, content of file is not used
*
* @param string $path
* @return string
Expand All @@ -171,15 +172,16 @@ public function detectPath($path): string {
if ($extension !== false) {
$extension = strtolower($extension);
$extension = substr($extension, 1); // remove leading .
return $this->mimetypes[$extension][0] ?? 'application/octet-stream';
return $this->mimeTypes[$extension][0] ?? 'application/octet-stream';
}
}

return 'application/octet-stream';
}

/**
* detect mimetype only based on the content of file
* Detect MIME type only based on the content of file.
*
* @param string $path
* @return string
* @since 18.0.0
Expand Down Expand Up @@ -244,7 +246,7 @@ public function detectContent(string $path): string {
}

/**
* detect mimetype based on both filename and content
* Detect MIME type based on both filename and content
*
* @param string $path
* @return string
Expand All @@ -260,7 +262,7 @@ public function detect($path): string {
}

/**
* detect mimetype based on the content of a string
* Detect MIME type based on the content of a string
*
* @param string $data
* @return string
Expand All @@ -272,7 +274,7 @@ public function detectString($data): string {
return str_contains($info, ';') ? substr($info, 0, strpos($info, ';')) : $info;
}

$tmpFile = \OC::$server->getTempManager()->getTemporaryFile();
$tmpFile = \OCP\Server::get(ITempManager::class)->getTemporaryFile();
$fh = fopen($tmpFile, 'wb');
fwrite($fh, $data, 8024);
fclose($fh);
Expand All @@ -282,7 +284,7 @@ public function detectString($data): string {
}

/**
* Get a secure mimetype that won't expose potential XSS.
* Get a secure MIME type that won't expose potential XSS.
*
* @param string $mimeType
* @return string
Expand All @@ -295,57 +297,56 @@ public function getSecureMimeType($mimeType): string {

/**
* Get path to the icon of a file type
* @param string $mimetype the MIME type
* @param string $mimeType the MIME type
* @return string the url
*/
public function mimeTypeIcon($mimetype): string {
public function mimeTypeIcon($mimeType): string {
$this->loadAliases();

while (isset($this->mimeTypeAlias[$mimetype])) {
$mimetype = $this->mimeTypeAlias[$mimetype];
while (isset($this->mimeTypeAlias[$mimeType])) {
$mimeType = $this->mimeTypeAlias[$mimeType];
}
if (isset($this->mimetypeIcons[$mimetype])) {
return $this->mimetypeIcons[$mimetype];
if (isset($this->mimeTypeIcons[$mimeType])) {
return $this->mimeTypeIcons[$mimeType];
}

// Replace slash and backslash with a minus
$icon = str_replace(['/', '\\'], '-', $mimetype);
$icon = str_replace(['/', '\\'], '-', $mimeType);

// Is it a dir?
if ($mimetype === 'dir') {
$this->mimetypeIcons[$mimetype] = $this->urlGenerator->imagePath('core', 'filetypes/folder.svg');
return $this->mimetypeIcons[$mimetype];
if ($mimeType === 'dir') {
$this->mimeTypeIcons[$mimeType] = $this->urlGenerator->imagePath('core', 'filetypes/folder.svg');
return $this->mimeTypeIcons[$mimeType];
}
if ($mimetype === 'dir-shared') {
$this->mimetypeIcons[$mimetype] = $this->urlGenerator->imagePath('core', 'filetypes/folder-shared.svg');
return $this->mimetypeIcons[$mimetype];
if ($mimeType === 'dir-shared') {
$this->mimeTypeIcons[$mimeType] = $this->urlGenerator->imagePath('core', 'filetypes/folder-shared.svg');
return $this->mimeTypeIcons[$mimeType];
}
if ($mimetype === 'dir-external') {
$this->mimetypeIcons[$mimetype] = $this->urlGenerator->imagePath('core', 'filetypes/folder-external.svg');
return $this->mimetypeIcons[$mimetype];
if ($mimeType === 'dir-external') {
$this->mimeTypeIcons[$mimeType] = $this->urlGenerator->imagePath('core', 'filetypes/folder-external.svg');
return $this->mimeTypeIcons[$mimeType];
}

// Icon exists?
try {
$this->mimetypeIcons[$mimetype] = $this->urlGenerator->imagePath('core', 'filetypes/' . $icon . '.svg');
return $this->mimetypeIcons[$mimetype];
$this->mimeTypeIcons[$mimeType] = $this->urlGenerator->imagePath('core', 'filetypes/' . $icon . '.svg');
return $this->mimeTypeIcons[$mimeType];
} catch (\RuntimeException $e) {
// Specified image not found
}

// Try only the first part of the filetype

if (strpos($icon, '-')) {
$mimePart = substr($icon, 0, strpos($icon, '-'));
try {
$this->mimetypeIcons[$mimetype] = $this->urlGenerator->imagePath('core', 'filetypes/' . $mimePart . '.svg');
return $this->mimetypeIcons[$mimetype];
$this->mimeTypeIcons[$mimeType] = $this->urlGenerator->imagePath('core', 'filetypes/' . $mimePart . '.svg');
return $this->mimeTypeIcons[$mimeType];
} catch (\RuntimeException $e) {
// Image for the first part of the mimetype not found
// Image for the first part of the MIME type not found
}
}

$this->mimetypeIcons[$mimetype] = $this->urlGenerator->imagePath('core', 'filetypes/file.svg');
return $this->mimetypeIcons[$mimetype];
$this->mimeTypeIcons[$mimeType] = $this->urlGenerator->imagePath('core', 'filetypes/file.svg');
return $this->mimeTypeIcons[$mimeType];
}
}
12 changes: 6 additions & 6 deletions lib/public/Files/IMimeTypeDetector.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,27 @@
* Interface IMimeTypeDetector
* @since 8.2.0
*
* Interface to handle mimetypes (detection and icon retrieval)
* Interface to handle MIME type (detection and icon retrieval)
**/
interface IMimeTypeDetector {
/**
* detect mimetype only based on filename, content of file is not used
* Detect MIME type only based on filename, content of file is not used
* @param string $path
* @return string
* @since 8.2.0
*/
public function detectPath($path);

/**
* detect mimetype only based on the content of file
* Detect MIME type only based on the content of file
* @param string $path
* @return string
* @since 18.0.0
*/
public function detectContent(string $path): string;

/**
* detect mimetype based on both filename and content
* Detect MIME type based on both filename and content
*
* @param string $path
* @return string
Expand All @@ -43,7 +43,7 @@ public function detectContent(string $path): string;
public function detect($path);

/**
* Get a secure mimetype that won't expose potential XSS.
* Get a secure MIME type that won't expose potential XSS.
*
* @param string $mimeType
* @return string
Expand All @@ -52,7 +52,7 @@ public function detect($path);
public function getSecureMimeType($mimeType);

/**
* detect mimetype based on the content of a string
* Detect MIME type based on the content of a string
*
* @param string $data
* @return string
Expand Down
Loading