summaryrefslogtreecommitdiffstats
path: root/src/network/access/qformdatabuilder.cpp
diff options
context:
space:
mode:
authorJuha Vuolle <[email protected]>2024-06-07 07:57:58 +0300
committerJuha Vuolle <[email protected]>2024-06-18 16:56:11 +0300
commit8c8a0c06d4f77ba8a707ec0a101b423543bf30f0 (patch)
tree0d8cc56b67cd3150d0d18a66d24f3a26d8323bb9 /src/network/access/qformdatabuilder.cpp
parentcb8abb718da4e18232de525ef1bb611f3a5dd929 (diff)
Adjust multipart 'filename' parameter encoding
The RFCs around these encodings are loose and allow several ways for dealing with non-ASCII characters. The encoding introduced in this commit should be interoperable and aligns with other frameworks (checked Curl, JS FormData, Postman, and Python requests). This consists of several adjustments: 1. Enclose the filename attribute in double quotes 2. If filename contains only ASCII characters, use them as-is 3. If filename contains characters beyond ASCII: 3.1. Encode them directly as raw UTF-8 to filename= 3.2. Set an additional filename*= parameter with percent encoded UTF-8. This is a legacy encoding for compatibility. Task-number: QTBUG-125985 Pick-to: 6.8 Change-Id: I5a6ad5388e4bb69e142caa7f6de7127526f441ad Reviewed-by: Marc Mutz <[email protected]> Reviewed-by: Thiago Macieira <[email protected]>
Diffstat (limited to 'src/network/access/qformdatabuilder.cpp')
-rw-r--r--src/network/access/qformdatabuilder.cpp41
1 files changed, 17 insertions, 24 deletions
diff --git a/src/network/access/qformdatabuilder.cpp b/src/network/access/qformdatabuilder.cpp
index 9cde45cddde..2cb5cc1f0e8 100644
--- a/src/network/access/qformdatabuilder.cpp
+++ b/src/network/access/qformdatabuilder.cpp
@@ -66,27 +66,6 @@ QFormDataPartBuilder::QFormDataPartBuilder(QLatin1StringView name, PrivateConstr
QFormDataPartBuilder::~QFormDataPartBuilder()
= default;
-
-static auto encodeFileName(QStringView view)
-{
- struct R { QByteArrayView encoding; QByteArray encoded; };
-
- QByteArrayView encoding = "=";
- bool needsUtf8 = false;
-
- for (QChar c : view) {
- if (c > u'\xff') {
- encoding = "*=UTF-8''";
- needsUtf8 = true;
- break;
- } else if (c > u'\x7f') {
- encoding = "*=ISO-8859-1''";
- }
- }
-
- return R{encoding, needsUtf8 ? view.toUtf8() : view.toLatin1()};
-}
-
static void convertInto_impl(QByteArray &dst, QUtf8StringView in)
{
dst.clear();
@@ -199,9 +178,23 @@ QHttpPart QFormDataPartBuilder::build()
QHttpPart httpPart;
if (!m_originalBodyName.isNull()) {
- const auto enc = encodeFileName(m_originalBodyName);
- m_headerValue += "; filename" + enc.encoding
- + enc.encoded.toPercentEncoding(); // RFC 5987 Section 3.2.1
+ const bool utf8 = !QtPrivate::isAscii(m_originalBodyName);
+ const auto enc = utf8 ? m_originalBodyName.toUtf8() : m_originalBodyName.toLatin1();
+ m_headerValue += "; filename=\"";
+ for (auto c : enc) {
+ if (c == '"' || c == '\\')
+ m_headerValue += '\\';
+ m_headerValue += c;
+ }
+ m_headerValue += "\"";
+ if (utf8) {
+ // For 'filename*' production see
+ // https://datatracker.ietf.org/doc/html/rfc5987#section-3.2.1
+ // For providing both filename and filename* parameters see
+ // https://datatracker.ietf.org/doc/html/rfc6266#section-4.3 and
+ // https://datatracker.ietf.org/doc/html/rfc8187#section-4.2
+ m_headerValue += "; filename*=UTF-8''" + enc.toPercentEncoding();
+ }
}
#if QT_CONFIG(mimetype)