diff options
| author | Juha Vuolle <[email protected]> | 2024-06-07 07:57:58 +0300 |
|---|---|---|
| committer | Juha Vuolle <[email protected]> | 2024-06-18 16:56:11 +0300 |
| commit | 8c8a0c06d4f77ba8a707ec0a101b423543bf30f0 (patch) | |
| tree | 0d8cc56b67cd3150d0d18a66d24f3a26d8323bb9 /src/network/access/qformdatabuilder.cpp | |
| parent | cb8abb718da4e18232de525ef1bb611f3a5dd929 (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.cpp | 41 |
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) |
