Handle RFC 5987 in Content-Disposition header

This commit is contained in:
the-djmaze 2024-04-16 02:09:24 +02:00
parent f8790a3a89
commit 1592c84ac0
5 changed files with 31 additions and 19 deletions

View file

@ -85,7 +85,7 @@ class Http
{
$sServerKey = 'HTTP_'.\strtoupper(\str_replace('-', '_', $sHeader));
$sResultHeader = static::GetServer($sServerKey, '');
if (!\strlen($sResultHeader) && \MailSo\Base\Utils::FunctionCallable('apache_request_headers')) {
if (!\strlen($sResultHeader) && Utils::FunctionCallable('apache_request_headers')) {
$sHeaders = \apache_request_headers();
if (isset($sHeaders[$sHeader])) {
$sResultHeader = $sHeaders[$sHeader];
@ -239,6 +239,25 @@ class Http
\header('Location: ' . $sUrl);
}
public static function setContentDisposition(string $type /* inline|attachment */, array $params)
{
$parms = array($type);
if (isset($params['filename'])) {
if (\preg_match('#^[\x01-\x7F]*$#D', $sFilename)) {
$parms[] = "filename=\"{$params['filename']}\"";
} else {
// RFC 5987
// $parms[] = Utils::EncodeHeaderUtf8AttributeValue('filename', $sFileNameOut);
$parms[] = "filename*=utf-8''" . \rawurlencode($sFilename);
}
}
if (isset($params['creation-date'])) $parms[] = 'creation-date=' . \date(DATE_RFC822, $params['creation-date']);
if (isset($params['modification-date'])) $parms[] = 'modification-date=' . \date(DATE_RFC822, $params['modification-date']);
if (isset($params['read-date'])) $parms[] = 'read-date=' . \date(DATE_RFC822, $params['read-date']);
if (isset($params['size'])) $parms[] = 'size=' . \intval($params['size']);
\header('Content-Disposition: ' . \implode('; ', $parms));
}
public function GetPath() : string
{
$sUrl = \ltrim(\substr(static::GetServer('SCRIPT_NAME', ''), 0, \strrpos(static::GetServer('SCRIPT_NAME', ''), '/')), '/');

View file

@ -135,8 +135,7 @@ trait Raw
}
$sFileNameOut = $this->clearFileName($sFileNameIn, $sContentTypeIn, $sMimeIndex);
\header('Content-Type: '.$sContentTypeOut);
\header('Content-Disposition: attachment; '.
\trim(\MailSo\Base\Utils::EncodeHeaderUtf8AttributeValue('filename', $sFileNameOut)));
\MailSo\Base\Http::setContentDisposition('attachment', ['filename' => $sFileNameOut]);
\header('Accept-Ranges: none');
\header('Content-Transfer-Encoding: binary');
\MailSo\Base\Utils::FpassthruWithTimeLimitReset($rResource);
@ -193,15 +192,13 @@ trait Raw
{
if ($bThumbnail) {
$oImage = static::loadImage($rResource, $bDetectImageOrientation, 48);
\header('Content-Disposition: inline; '.
\trim(\MailSo\Base\Utils::EncodeHeaderUtf8AttributeValue('filename', $sFileName.'_thumb60x60.png')));
\MailSo\Base\Http::setContentDisposition('inline', ['filename' => $sFileName.'_thumb60x60.png']);
$oImage->show('png');
// $oImage->show('webp'); // Little Britain: "Safari says NO"
exit;
} else if ($bDetectImageOrientation) {
$oImage = static::loadImage($rResource, $bDetectImageOrientation);
\header('Content-Disposition: inline; '.
\trim(\MailSo\Base\Utils::EncodeHeaderUtf8AttributeValue('filename', $sFileName)));
\MailSo\Base\Http::setContentDisposition('inline', ['filename' => $sFileName]);
$oImage->show();
// $oImage->show('webp'); // Little Britain: "Safari says NO"
exit;
@ -217,9 +214,7 @@ trait Raw
if (!\headers_sent()) {
\header('Content-Type: '.$sContentType);
\header('Content-Disposition: '.($bDownload ? 'attachment' : 'inline').'; '.
\trim(\MailSo\Base\Utils::EncodeHeaderUtf8AttributeValue('filename', $sFileName)));
\MailSo\Base\Http::setContentDisposition($bDownload ? 'attachment' : 'inline', ['filename' => $sFileName]);
\header('Accept-Ranges: bytes');
\header('Content-Transfer-Encoding: binary');
}

View file

@ -219,7 +219,7 @@ class ActionsAdmin extends Actions
$this->IsAdminLoggined();
$file = \SnappyMail\Upgrade::backup();
\header('Content-Type: application/gzip');
\header('Content-Disposition: attachment; filename="' . \basename($file) . '"');
\MailSo\Base\Http::setContentDisposition('attachment', ['filename' => \basename($file)]);
\header('Content-Transfer-Encoding: binary');
\header('Content-Length: ' . \filesize($file));
$fp = \fopen($file, 'rb');

View file

@ -51,15 +51,14 @@ class TAR
\header('Content-Transfer-Encoding: binary');
if (false !== $this->gzip) {
$name .= '.tgz';
$name = \preg_match('#^[\x01-\x7F]*$#D', $name) ? $name : '=?UTF-8?B?'.\base64_encode($name).'?=';
\header("Content-Disposition: attachment; filename={$name}");
\header("Content-Type: application/gzip; name={$name}");
$tname = \preg_match('#^[\x01-\x7F]*$#D', $name) ? $name : '=?UTF-8?B?'.\base64_encode($name).'?=';
\header("Content-Type: application/gzip; name=\"{$tname}\"");
} else {
$name .= '.tar';
$name = \preg_match('#^[\x01-\x7F]*$#D', $name) ? $name : '=?UTF-8?B?'.\base64_encode($name).'?=';
\header("Content-Disposition: attachment; filename={$name}");
\header("Content-Type: application/x-ustar; name={$name}");
$tname = \preg_match('#^[\x01-\x7F]*$#D', $name) ? $name : '=?UTF-8?B?'.\base64_encode($name).'?=';
\header("Content-Type: application/x-ustar; name=\"{$tname}\"");
}
\MailSo\Base\Http::setContentDisposition('attachment', ['filename' => $name]);
}
public function close() : void

View file

@ -80,8 +80,7 @@ class ZIP
\header('Pragma: no-cache');
\header('Content-Transfer-Encoding: binary');
$name .= '.zip';
$name = \preg_match('#^[\x01-\x7F]*$#D', $name) ? $name : '=?UTF-8?B?'.\base64_encode($name).'?=';
\header("Content-Disposition: attachment; filename={$name}");
\MailSo\Base\Http::setContentDisposition('attachment', ['filename' => $name]);
\header("Content-Type: application/zip; name={$name}");
}