Fix various issues when downloading files with names containing non-ascii chars, use RFC 2231 (#5772)

pull/5815/head
Aleksander Machniak 7 years ago
parent 7b4b36b16c
commit bcc6405552

@ -10,6 +10,7 @@ CHANGELOG Roundcube Webmail
- Support LDAP GSSAPI authentication (#5703)
- Allow contacts without an email address (#5079)
- Localized timezone selector (#4983)
- Fix various issues when downloading files with names containing non-ascii chars, use RFC 2231 (#5772)
- Update to TinyMCE 4.5.7
- Fix bug where invalid recipients could be silently discarded (#5739)
- Fix conflict with _gid cookie of Google Analytics (#5748)

@ -414,26 +414,11 @@ class rcube_sieve_engine
$script_name = rcube_utils::get_input_value('_set', rcube_utils::INPUT_GPC, true);
$script = $this->sieve->get_script($script_name);
if ($script === false) {
exit;
if ($script !== false) {
$this->rc->output->download_headers($script_name . '.txt', array('length' => strlen($script)));
echo $script;
}
$browser = new rcube_browser;
// send download headers
header("Content-Type: application/octet-stream");
header("Content-Length: ".strlen($script));
if ($browser->ie) {
header("Content-Type: application/force-download");
$filename = rawurlencode($script_name);
}
else {
$filename = addcslashes($script_name, '\\"');
}
header("Content-Disposition: attachment; filename=\"$filename.txt\"");
echo $script;
exit;
}
else if ($action == 'list') {

@ -329,26 +329,10 @@ class zipdownload extends rcube_plugin
*/
private function _deliver_zipfile($tmpfname, $filename)
{
$browser = new rcube_browser;
$rcmail = rcmail::get_instance();
$rcmail->output->nocacheing_headers();
if ($browser->ie)
$filename = rawurlencode($filename);
else
$filename = addcslashes($filename, '"');
$rcmail = rcmail::get_instance();
// send download headers
header("Content-Type: application/octet-stream");
if ($browser->ie) {
header("Content-Type: application/force-download");
}
$rcmail->output->download_headers($filename, array('length' => filesize($tmpfname)));
// don't kill the connection if download takes more than 30 sec.
@set_time_limit(0);
header("Content-Disposition: attachment; filename=\"". $filename ."\"");
header("Content-length: " . filesize($tmpfname));
readfile($tmpfname);
}

@ -197,6 +197,60 @@ abstract class rcube_output
}
}
/**
* Send headers related to file downloads
*
* @param string $filename File name
* @param array $params Optional parameters:
* type - File content type (default: 'application/octet-stream')
* disposition - Download type: 'inline' or 'attachment' (default)
* length - Content length
* charset - File name character set
* type_charset - Content character set
* time_limit - Script execution limit (default: 3600)
*/
public function download_headers($filename, $params = array())
{
if (empty($params['disposition'])) {
$params['disposition'] = 'attachment';
}
if ($params['disposition'] == 'inline' && stripos($params['type'], 'text') === 0) {
$params['type'] .= '; charset=' . ($params['type_charset'] ?: $this->charset);
}
header("Content-Type: " . ($params['type'] ?: "application/octet-stream"));
if ($params['disposition'] == 'attachment' && $this->browser->ie) {
header("Content-Type: application/force-download");
}
$disposition = "Content-Disposition: " . $params['disposition'];
// For non-ascii characters we'll use RFC2231 syntax
if (!preg_match('/[^a-zA-Z0-9_.:,?;@+ -]/', $filename)) {
$disposition .= sprintf("; filename=\"%s\"", $filename);
}
else {
$disposition .= sprintf("; filename*=\"%s''%s\"", $params['charset'] ?: $this->charset, rawurlencode($filename));
}
header($disposition);
if (isset($params['length'])) {
header("Content-Length: " . $params['length']);
}
// don't kill the connection if download takes more than 30 sec.
if (!array_key_exists('time_limit', $params)) {
$params['time_limit'] = 3600;
}
if (is_numeric($params['time_limit'])) {
@set_time_limit($params['time_limit']);
}
}
/**
* Show error page and terminate script execution
*

@ -220,19 +220,10 @@ if (empty($_GET['_thumb']) && $attachment->is_valid()) {
}
}
$browser = $RCMAIL->output->browser;
list($ctype_primary, $ctype_secondary) = explode('/', $mimetype);
if (!empty($_GET['_download']) && $ctype_primary == 'text') {
header("Content-Type: text/$ctype_secondary; charset=" . $attachment->charset);
}
else {
header("Content-Type: $mimetype");
header("Content-Transfer-Encoding: binary");
}
// deliver part content
if ($mimetype == 'text/html' && empty($_GET['_download'])) {
header("Content-Type: text/html; charset=" . $attachment->charset);
// Check if we have enough memory to handle the message in it
// #1487424: we need up to 10x more memory than the body
if (!rcube_utils::mem_check($attachment->size * 10)) {
@ -268,18 +259,16 @@ if (empty($_GET['_thumb']) && $attachment->is_valid()) {
exit;
}
// don't kill the connection if download takes some more time
@set_time_limit(3600);
$filename = $browser->ie ? rawurlencode($filename) : addcslashes($filename, '"');
$disposition = !empty($_GET['_download']) ? 'attachment' : 'inline';
// add filename extension if missing
if (!pathinfo($filename, PATHINFO_EXTENSION) && ($extensions = rcube_mime::get_mime_extensions($mimetype))) {
$filename .= '.' . $extensions[0];
}
header("Content-Disposition: $disposition; filename=\"$filename\"");
$OUTPUT->download_headers($filename, array(
'type' => $mimetype,
'type_charset' => $attachment->charset,
'disposition' => !empty($_GET['_download']) ? 'attachment' : 'inline',
));
// handle tiff to jpeg conversion
if (!empty($convert2jpeg)) {

@ -38,17 +38,19 @@ if ($uid = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_GET)) {
$charset = $headers->charset ?: $RCMAIL->config->get('default_charset');
header("Content-Type: text/plain; charset={$charset}");
if (!empty($_GET['_save'])) {
$browser = $RCMAIL->output->browser;
$subject = rcube_mime::decode_header($headers->subject, $headers->charset);
$filename = rcmail_filename_from_subject(mb_substr($subject, 0, 128));
$filename = ($filename ?: $uid) . '.eml';
$filename = $browser->ie ? rawurlencode($filename) : addcslashes($filename, '"');
header("Content-Length: {$headers->size}");
header("Content-Disposition: attachment; filename=\"$filename\"");
$RCMAIL->output->download_headers($filename, array(
'length' => $headers->size,
'type' => 'text/plain',
'type_charset' => $charset,
));
}
else {
header("Content-Type: text/plain; charset={$charset}");
}
if (isset($message)) {

Loading…
Cancel
Save