From 97b9c31d34bc3c54f699156692adf4a59f846538 Mon Sep 17 00:00:00 2001 From: Nguyen Ngoc Hoang Phuc Date: Mon, 20 Dec 2021 09:12:01 +0700 Subject: [PATCH] S3 pre-signed URL: error with unicode filename #455 --- classes/local/store/s3/client.php | 37 ++++++++++++++++++------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/classes/local/store/s3/client.php b/classes/local/store/s3/client.php index 89febb95..3f10e9d5 100644 --- a/classes/local/store/s3/client.php +++ b/classes/local/store/s3/client.php @@ -486,9 +486,10 @@ public function generate_presigned_url($contenthash, $headers = array()) { /** * @param string $contenthash * @param array $headers + * @param bool $nicefilename * @return signed_url */ - private function generate_presigned_url_s3($contenthash, $headers) { + private function generate_presigned_url_s3($contenthash, array $headers = [], $nicefilename = true) { $contentdisposition = manager::get_header($headers, 'Content-Disposition'); if ($contentdisposition !== '') { $params['ResponseContentDisposition'] = $contentdisposition; @@ -503,14 +504,12 @@ private function generate_presigned_url_s3($contenthash, $headers) { $params['Bucket'] = $this->bucket; $params['Key'] = $this->bucketkeyprefix . $key; - $contentdisposition = manager::get_header($headers, 'Content-Disposition'); - if ($contentdisposition !== '') { - $params['ResponseContentDisposition'] = $contentdisposition; - } - - $contenttype = manager::get_header($headers, 'Content-Type'); - if ($contenttype !== '') { - $params['ResponseContentType'] = $contenttype; + if ($nicefilename) { + $result = $this->get_nice_filename($headers); + if (!empty($result)) { + $params['ResponseContentDisposition'] = $result['Content-Disposition'] . '; ' . $result['filename']; + $params['ResponseContentType'] = $result['Content-Type']; + } } $command = $this->client->getCommand('GetObject', $params); @@ -534,7 +533,14 @@ private function generate_presigned_url_cloudfront($contenthash, array $headers $expires = $this->get_expiration_time(time(), manager::get_header($headers, 'Expires')); if ($nicefilename) { - $key .= $this->get_nice_filename($headers); + $result = $this->get_nice_filename($headers); + if (!empty($result)) { + $key .= '?response-content-disposition=' . + rawurlencode($result['Content-Disposition'] . ';' . $result['filename']) . + '&response-content-type=' . rawurlencode($result['Content-Type']); + } else { + $key .= ''; + } } $resource = $this->config->cloudfrontresourcedomain . '/' . $key; // This is the id of the Cloudfront key pair you generated. @@ -572,11 +578,12 @@ private function generate_presigned_url_cloudfront($contenthash, array $headers /** * @param $headers - * @return string + * @return array */ private function get_nice_filename($headers) { // We are trying to deliver original filename rather than hash filename to client. $originalfilename = ''; + $result = []; $contentdisposition = trim(manager::get_header($headers, 'Content-Disposition')); $originalcontenttype = trim(manager::get_header($headers, 'Content-Type')); @@ -596,12 +603,12 @@ private function get_nice_filename($headers) { } if (!empty($originalfilename)) { - return '?response-content-disposition=' . - rawurlencode($contentdisposition . ';filename="' . utf8_encode($originalfilename) . '"') . - '&response-content-type=' . rawurlencode($originalcontenttype); + $result['Content-Disposition'] = $contentdisposition; + $result['filename'] = 'filename="' . utf8_encode($originalfilename) . '"'; + $result['Content-Type'] = $originalcontenttype; } } - return ''; + return $result; } /**