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)); $sServerKey = 'HTTP_'.\strtoupper(\str_replace('-', '_', $sHeader));
$sResultHeader = static::GetServer($sServerKey, ''); $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(); $sHeaders = \apache_request_headers();
if (isset($sHeaders[$sHeader])) { if (isset($sHeaders[$sHeader])) {
$sResultHeader = $sHeaders[$sHeader]; $sResultHeader = $sHeaders[$sHeader];
@ -239,6 +239,25 @@ class Http
\header('Location: ' . $sUrl); \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 public function GetPath() : string
{ {
$sUrl = \ltrim(\substr(static::GetServer('SCRIPT_NAME', ''), 0, \strrpos(static::GetServer('SCRIPT_NAME', ''), '/')), '/'); $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); $sFileNameOut = $this->clearFileName($sFileNameIn, $sContentTypeIn, $sMimeIndex);
\header('Content-Type: '.$sContentTypeOut); \header('Content-Type: '.$sContentTypeOut);
\header('Content-Disposition: attachment; '. \MailSo\Base\Http::setContentDisposition('attachment', ['filename' => $sFileNameOut]);
\trim(\MailSo\Base\Utils::EncodeHeaderUtf8AttributeValue('filename', $sFileNameOut)));
\header('Accept-Ranges: none'); \header('Accept-Ranges: none');
\header('Content-Transfer-Encoding: binary'); \header('Content-Transfer-Encoding: binary');
\MailSo\Base\Utils::FpassthruWithTimeLimitReset($rResource); \MailSo\Base\Utils::FpassthruWithTimeLimitReset($rResource);
@ -193,15 +192,13 @@ trait Raw
{ {
if ($bThumbnail) { if ($bThumbnail) {
$oImage = static::loadImage($rResource, $bDetectImageOrientation, 48); $oImage = static::loadImage($rResource, $bDetectImageOrientation, 48);
\header('Content-Disposition: inline; '. \MailSo\Base\Http::setContentDisposition('inline', ['filename' => $sFileName.'_thumb60x60.png']);
\trim(\MailSo\Base\Utils::EncodeHeaderUtf8AttributeValue('filename', $sFileName.'_thumb60x60.png')));
$oImage->show('png'); $oImage->show('png');
// $oImage->show('webp'); // Little Britain: "Safari says NO" // $oImage->show('webp'); // Little Britain: "Safari says NO"
exit; exit;
} else if ($bDetectImageOrientation) { } else if ($bDetectImageOrientation) {
$oImage = static::loadImage($rResource, $bDetectImageOrientation); $oImage = static::loadImage($rResource, $bDetectImageOrientation);
\header('Content-Disposition: inline; '. \MailSo\Base\Http::setContentDisposition('inline', ['filename' => $sFileName]);
\trim(\MailSo\Base\Utils::EncodeHeaderUtf8AttributeValue('filename', $sFileName)));
$oImage->show(); $oImage->show();
// $oImage->show('webp'); // Little Britain: "Safari says NO" // $oImage->show('webp'); // Little Britain: "Safari says NO"
exit; exit;
@ -217,9 +214,7 @@ trait Raw
if (!\headers_sent()) { if (!\headers_sent()) {
\header('Content-Type: '.$sContentType); \header('Content-Type: '.$sContentType);
\header('Content-Disposition: '.($bDownload ? 'attachment' : 'inline').'; '. \MailSo\Base\Http::setContentDisposition($bDownload ? 'attachment' : 'inline', ['filename' => $sFileName]);
\trim(\MailSo\Base\Utils::EncodeHeaderUtf8AttributeValue('filename', $sFileName)));
\header('Accept-Ranges: bytes'); \header('Accept-Ranges: bytes');
\header('Content-Transfer-Encoding: binary'); \header('Content-Transfer-Encoding: binary');
} }

View file

@ -219,7 +219,7 @@ class ActionsAdmin extends Actions
$this->IsAdminLoggined(); $this->IsAdminLoggined();
$file = \SnappyMail\Upgrade::backup(); $file = \SnappyMail\Upgrade::backup();
\header('Content-Type: application/gzip'); \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-Transfer-Encoding: binary');
\header('Content-Length: ' . \filesize($file)); \header('Content-Length: ' . \filesize($file));
$fp = \fopen($file, 'rb'); $fp = \fopen($file, 'rb');

View file

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

View file

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