Skip to content

Commit

Permalink
[BUGFIX] MIME Type Filter (#1419)
Browse files Browse the repository at this point in the history
Co-authored-by: Sebastian Meyer <[email protected]>
  • Loading branch information
fschoelzel and sebastian-meyer authored Feb 26, 2025
1 parent fca97b7 commit 11e66dd
Show file tree
Hide file tree
Showing 4 changed files with 312 additions and 19 deletions.
45 changes: 31 additions & 14 deletions Classes/Common/Helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -946,26 +946,33 @@ private static function getLocalConfigurationByPath(string $path)
}

/**
* Filters a file based on its mimetype categories.
* Filters a file based on its mimetype.
*
* This method checks if the provided file array contains a specified mimetype key and
* verifies if the mimetype belongs to any of the specified categories or matches any of the additional custom mimetypes.
* verifies if the mimetype belongs to any of the allowed mimetypes or matches any of the additional custom mimetypes.
*
* @param mixed $file The file array to filter
* @param array $categories The MIME type categories to filter by (e.g., ['audio'], ['video'] or ['image', 'application'])
* @param array $dlfMimeTypes The custom DLF mimetype keys IIIF, IIP or ZOOMIFY to check against (default is an empty array)
* @param array $allowedCategories The allowed MIME type categories to filter by (e.g., ['audio'], ['video'] or ['image', 'application'])
* @param null|bool|array $dlfMimeTypes Optional array of custom dlf mimetype keys to filter by. Default is null.
* - null: use no custom dlf mimetypes
* - true: use all custom dlf mimetypes
* - array: use only specific types - Accepted values: 'IIIF', 'IIP', 'ZOOMIFY', 'JPG'
* @param string $mimeTypeKey The key used to access the mimetype in the file array (default is 'mimetype')
*
* @return bool True if the file mimetype belongs to any of the specified categories or matches any custom mimetypes, false otherwise
* @return bool True if the file mimetype belongs to any of the allowed mimetypes or matches any custom dlf mimetypes, false otherwise
*/
public static function filterFilesByMimeType($file, array $categories, array $dlfMimeTypes = [], string $mimeTypeKey = 'mimetype'): bool
public static function filterFilesByMimeType($file, array $allowedCategories, null|bool|array $dlfMimeTypes = null, string $mimeTypeKey = 'mimetype'): bool
{
if (empty($allowedCategories) && empty($dlfMimeTypes)) {
return false;
}

// Retrieves MIME types from the TYPO3 Core MimeTypeCollection
$mimeTypeCollection = GeneralUtility::makeInstance(MimeTypeCollection::class);
$mimeTypes = array_filter(
$allowedMimeTypes = array_filter(
$mimeTypeCollection->getMimeTypes(),
function ($mimeType) use ($categories) {
foreach ($categories as $category) {
function ($mimeType) use ($allowedCategories) {
foreach ($allowedCategories as $category) {
if (strpos($mimeType, $category . '/') === 0) {
return true;
}
Expand All @@ -978,16 +985,26 @@ function ($mimeType) use ($categories) {
$dlfMimeTypeArray = [
'IIIF' => 'application/vnd.kitodo.iiif',
'IIP' => 'application/vnd.netfpx',
'ZOOMIFY' => 'application/vnd.kitodo.zoomify'
'ZOOMIFY' => 'application/vnd.kitodo.zoomify',
'JPG' => 'image/jpg' // Wrong declared JPG MIME type in falsy METS Files for JPEG files
];

// Filter custom MIME types based on provided keys
$filteredDlfMimeTypes = array_intersect_key($dlfMimeTypeArray, array_flip($dlfMimeTypes));
// Apply filtering to the custom dlf MIME type array
$filteredDlfMimeTypes = match (true) {
$dlfMimeTypes === null => [],
$dlfMimeTypes === true => $dlfMimeTypeArray,
is_array($dlfMimeTypes) => array_intersect_key($dlfMimeTypeArray, array_flip($dlfMimeTypes)),
default => []
};

// Actual filtering to check if the file's MIME type is allowed
if (is_array($file) && isset($file[$mimeTypeKey])) {
return in_array($file[$mimeTypeKey], $mimeTypes) || in_array($file[$mimeTypeKey], $filteredDlfMimeTypes);
return in_array($file[$mimeTypeKey], $allowedMimeTypes) ||
in_array($file[$mimeTypeKey], $filteredDlfMimeTypes);
} else {
self::log('MIME type validation failed: File array is invalid or MIME type key is not set. File array: ' . json_encode($file) . ', mimeTypeKey: ' . $mimeTypeKey, 2);
return false;
}
return false;
}

/**
Expand Down
5 changes: 3 additions & 2 deletions Classes/Controller/PageViewController.php
Original file line number Diff line number Diff line change
Expand Up @@ -636,13 +636,14 @@ protected function getImage(int $page, MetsDocument $specificDoc = null): array
foreach ($useGroups as $useGroup) {
// Get file info for the specific page and file group
$file = $this->fetchFileInfo($page, $useGroup, $specificDoc);
if ($file && Helper::filterFilesByMimeType($file, ['image', 'application'], ['IIIF', 'IIP', 'ZOOMIFY'], 'mimeType')) {

if ($file && Helper::filterFilesByMimeType($file, ['image'], true, 'mimeType')) {
$image['url'] = $file['location'];
$image['mimetype'] = $file['mimeType'];

// Only deliver static images via the internal PageViewProxy.
// (For IIP and IIIF, the viewer needs to build and access a separate metadata URL, see `getMetadataURL` in `OLSources.js`.)
if ($this->settings['useInternalProxy'] && !Helper::filterFilesByMimeType($file, ['application'], ['IIIF', 'IIP', 'ZOOMIFY'], 'mimeType')) {
if ($this->settings['useInternalProxy'] && !Helper::filterFilesByMimeType($image, ['application'], ['IIIF', 'IIP', 'ZOOMIFY'])) {
$this->configureProxyUrl($image['url']);
}
break;
Expand Down
10 changes: 7 additions & 3 deletions Classes/Controller/ToolboxController.php
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,11 @@ private function getImage(int $page): array
$image = $this->getFile($page, $this->useGroupsConfiguration->getImage());
if (isset($image['mimetype'])) {
$fileExtension = Helper::getFileExtensionsForMimeType($image['mimetype']);
$image['mimetypeLabel'] = !empty($fileExtension) ? ' (' . strtoupper($fileExtension[0]) . ')' : '';
if ($image['mimetype'] == 'image/jpg') {
$image['mimetypeLabel'] = ' (JPG)'; // "image/jpg" is not a valid MIME type, so we need to handle it separately.
} else {
$image['mimetypeLabel'] = !empty($fileExtension) ? ' (' . strtoupper($fileExtension[0]) . ')' : '';
}
}
return $image;
}
Expand Down Expand Up @@ -283,13 +287,13 @@ private function renderImageDownloadTool(): void
$imageArray = [];
// Get left or single page download.
$image = $this->getImage($page);
if (Helper::filterFilesByMimeType($image, ['image'])) {
if (Helper::filterFilesByMimeType($image, ['image'], true)) {
$imageArray[0] = $image;
}

if ($this->requestData['double'] == 1) {
$image = $this->getImage($page + 1);
if (Helper::filterFilesByMimeType($image, ['image'])) {
if (Helper::filterFilesByMimeType($image, ['image'], true)) {
$imageArray[1] = $image;
}
}
Expand Down
Loading

0 comments on commit 11e66dd

Please sign in to comment.