Skip to content
This repository has been archived by the owner on Apr 24, 2024. It is now read-only.

Commit

Permalink
Fixing problem with UTF8 and long filenames when downloading mediafiles.
Browse files Browse the repository at this point in the history
  • Loading branch information
rblanker committed Oct 9, 2017
1 parent 1b1638b commit 184a42d
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 28 deletions.
Expand Up @@ -1153,8 +1153,8 @@ class mediamosa_asset_mediafile {
*
* @param array $mediafile
* The mediafile.
* @param string $default
* The default value for extension when not available.
* @param string|bool $default
* (default FALSE) The default value for extension when not available.
*
* @return string
* The file extension (e.g. 'jpeg') without the dot or FALSE ($default).
Expand All @@ -1178,7 +1178,7 @@ class mediamosa_asset_mediafile {
// Try to match against the container type.
$file_ext = isset($container2ext[$container_type]) ? $container2ext[$container_type] : '';

// No extension yet? Try to get one based on mimetype.
// No extension yet? Try to get one based on mime-type.
if (empty($file_ext)) {
$file_ext = $mediafile[mediamosa_asset_mediafile_db::FILE_EXTENSION];
}
Expand Down
16 changes: 6 additions & 10 deletions sites/all/modules/mediamosa/core/media/mediamosa_media.class.inc
Expand Up @@ -87,7 +87,7 @@ class mediamosa_media {
*
* @return array
* An associative array containing;
* 'basename' (always)
* 'filename' (always)
* 'style_id' (always or 0)
* 'ext' (no dot).
*/
Expand All @@ -103,8 +103,9 @@ class mediamosa_media {
);
}

// If its not in our format, then return it as is.
return array($filename, 0, '');
// Fallback to default.
$path_info = pathinfo($filename);
return array($path_info['filename'], 0, $path_info['extension']);
}

/**
Expand Down Expand Up @@ -166,7 +167,6 @@ class mediamosa_media {
protected static function serve_media($file, $mimetype) {
// Build up the default headers.
$headers = mediamosa_io::file_get_content_headers($file, $mimetype);

// Serve file.
mediamosa_io::file_transfer($file, $headers);
}
Expand All @@ -180,6 +180,8 @@ class mediamosa_media {
* The mediafile ID.
* @param string $filename
* The filename. May contain style info when file is still.
*
* @throws mediamosa_exception_error_404
*/
public static function handle_media_request_permanent($app_id, $mediafile_id, $filename) {
// Get the parts.
Expand All @@ -204,12 +206,6 @@ class mediamosa_media {
)
);

// The mimetypes must match.
if ($mimetype_extension != $mimetype) {
throw new mediamosa_exception_error_mediafile_not_found(array('@mediafile_id' => $mediafile_id));
}

// We can trust the extension.
// At this point the mediafile exists, and we have access.
//
// Any style_id?
Expand Down
21 changes: 13 additions & 8 deletions sites/all/modules/mediamosa/lib/mediamosa_io.class.inc
Expand Up @@ -501,16 +501,17 @@ class mediamosa_io {
/**
* Return the filename without extension.
*
* FIXME: Name of function is wrong:
* FIXME: The basename of a file path is filename with possible extension.
*
* @param string $filename
* The filename to process.
*
* @return string
* The filename without extension.
*/
public static function get_base_filename($filename) {
$first_dot = stripos($filename, '.');

return $first_dot === FALSE ? $filename : mediamosa_unicode::substr($filename, 0, $first_dot);
return pathinfo($filename, PATHINFO_FILENAME);
}

/**
Expand Down Expand Up @@ -1113,11 +1114,15 @@ class mediamosa_io {
*
* @see file_get_content_headers()
*/
public static function file_get_content_headers($filename, $mimetype) {
public static function file_get_content_headers($filename, $mime_type) {
$content_length = self::filesize($filename);
$last_modified = filemtime($filename);
$filename = mime_header_encode($filename);
$mimetype = mime_header_encode($mimetype);
// Hotfix: mime_header_encode() generates multi-line when utf-8 is used.
// But drupal_add_http_header() can not handle multi-line header
// items. We do break max line-length of 76 for HTTP, but seems no
// browser has a issue with this.
$filename = rawurlencode(pathinfo($filename, PATHINFO_BASENAME));
$mime_type = mime_header_encode($mime_type);

// Serve images, text, and flash content for display rather than download.
$inline_types = variable_get('file_inline_types', array(
Expand All @@ -1128,13 +1133,13 @@ class mediamosa_io {
$disposition = 'attachment';
foreach ($inline_types as $inline_type) {
// Exclamation marks are used as delimiters to avoid escaping slashes.
if (preg_match('!' . $inline_type . '!', $mimetype)) {
if (preg_match('!' . $inline_type . '!', $mime_type)) {
$disposition = 'inline';
}
}

return array(
'Content-Type' => $mimetype . '; name="' . $filename . '"',
'Content-Type' => $mime_type . '; name="' . $filename . '"',
'Content-Length' => $content_length,
'Content-Disposition' => $disposition . '; filename="' . $filename . '"',
'Cache-Control' => 'private, max-age=' . mediamosa_settings::MEDIA_CACHE_SECOND . ', must-revalidate',
Expand Down
Expand Up @@ -195,6 +195,42 @@ class MediaMosaAssetMediafileDownloadTestCaseEga extends MediaMosaTestCaseEga {
$this->assertTrue($result->headers['content-type'] == 'application/octet-stream', 'Got download.');
$this->assertTrue(mediamosa_unicode::strpos($result->headers['content-disposition'], '.docx"') !== FALSE, 'Is correct extension.');

// Update the mediafile to our filename and see if it downloads.
$this->updateMediafile($mediafile_id, array(
'filename' => 'toestemming café De Broodwinning BOSG20173183 20171011 - Varkensmarkt 4.msg',
'mime_type' => 'CDF V2 Document, No summary info',
));

// Hard update the file extension.
mediamosa_db::db_update(mediamosa_asset_mediafile_db::TABLE_NAME)
->fields(array(mediamosa_asset_mediafile_db::FILE_EXTENSION => 'msg'))
->condition(mediamosa_asset_mediafile_db::ID, $mediafile_id)
->execute();

// Ask mediafile download url.
$parameters = array(
mediamosa_rest_call_media_view::RESPONSE => mediamosa_media::RESPONSE_DOWNLOAD,
mediamosa_rest_call_media_view::MEDIAFILE_ID => $mediafile_id,
);
$xml = $this->do_media_view($asset_id, $parameters);

// Check the download url.
$download = (string) $xml->items->item->output;
$this->assertTrue(
!empty($download),
t('Download url is exists: @download', array('@download' => $download))
);

$this->var_export($download);

// Download the file.
$result = mediamosa_http::drupal_http_request($download);

$this->var_export($result->headers);
if (isset($_SERVER['REDIRECT_STATUS'])) {
$this->assertTrue($_SERVER['REDIRECT_STATUS'] == 200, 'Got 200 HTTP response download.');
}
$this->assertTrue($result->headers['content-type'] == 'application/octet-stream', 'Got download.');
$this->assertTrue(mediamosa_unicode::strpos($result->headers['content-disposition'], '.msg"') !== FALSE, 'Is correct extension.');
}
}
Expand Up @@ -242,7 +242,7 @@ class mediamosa_rest_call_media_view extends mediamosa_rest_call {
// Get the asset.
$asset = mediamosa_asset::must_exists($asset_id);

// Test if access on unappropriate flag.
// Test if access on inappropriate flag.
mediamosa_asset::is_inappropriate($app_ids, $asset_id, $user_id, $is_app_admin, TRUE);

// Check play restrictions.
Expand Down Expand Up @@ -453,8 +453,6 @@ class mediamosa_rest_call_media extends mediamosa_rest_call {

// ------------------------------------------------------------ Get Var Setup.
public function get_var_setup() {
$var_setup = array();

$var_setup = array(
self::VARS => array(
self::APP_ID => array(
Expand Down Expand Up @@ -508,7 +506,7 @@ class mediamosa_rest_call_media extends mediamosa_rest_call {
if ($ticket_id) {
// Before 3.1 we always served the mediafile here. Now we don't because
// the REST call should not have been triggered in the first place with
// tickets (Your webserver is handeling this). Need to warn admin that his
// tickets (Your webserver is handling this). Need to warn admin that his
// configuration does not include the correct configuration for his
// webserver.

Expand Down Expand Up @@ -696,9 +694,8 @@ class mediamosa_rest_call_media_download extends mediamosa_rest_call {
header('Content-Description: Download');
header('Content-Type: application/octet-stream');
header('Content-Length: ' . filesize($file));

// Force a save dialog.
header('Content-Disposition: attachment; filename="' . mime_header_encode($filename) . '"');
header(strtr('Content-Disposition: attachment; filename="{filename}"; filename*=utf-8\'\'{filename}', array('{filename}' => rawurlencode($filename))));
header('Content-Transfer-Encoding: binary');

$handle = fopen($file, 'rb');
Expand Down Expand Up @@ -727,7 +724,7 @@ class mediamosa_rest_call_media_download extends mediamosa_rest_call {
// Close the file.
fclose($handle);

// Set the result, reponse object will know what to do.
// Set the result, response object will know what to do.
$mediamosa->set_result(mediamosa_response::SUCCESS, 200, $file);
}
}
Expand Down

0 comments on commit 184a42d

Please sign in to comment.