Accept QASV for multipart 'name' field
And adjust the encoding of 'name' parameter to always use UTF-8 / ASCII. This aligns with how other frameworks behave. Also amended docs to recommend ASCII for 'name'. Found in API review. Pick-to: 6.8 Change-Id: I54d1148bf95dece54b75c76914c49985da05e0b2 Reviewed-by: Marc Mutz <marc.mutz@qt.io>
This commit is contained in:
parent
8c8a0c06d4
commit
6b23a3c5e4
@ -28,17 +28,37 @@ QT_BEGIN_NAMESPACE
|
||||
\sa QHttpPart, QHttpMultiPart, QFormDataBuilder
|
||||
*/
|
||||
|
||||
static QByteArray nameToByteArray(QStringView view)
|
||||
{
|
||||
return view.toUtf8();
|
||||
}
|
||||
|
||||
static QByteArray nameToByteArray(QLatin1StringView view)
|
||||
{
|
||||
if (!QtPrivate::isAscii(view))
|
||||
return view.toString().toUtf8(); // ### optimize
|
||||
|
||||
return QByteArray::fromRawData(view.data(), view.size());
|
||||
}
|
||||
|
||||
static QByteArray nameToByteArray(QUtf8StringView view)
|
||||
{
|
||||
return QByteArray::fromRawData(view.data(), view.size());
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a QFormDataPartBuilder object and sets \a name as the name
|
||||
parameter of the form-data.
|
||||
*/
|
||||
QFormDataPartBuilder::QFormDataPartBuilder(QLatin1StringView name, PrivateConstructor /*unused*/)
|
||||
QFormDataPartBuilder::QFormDataPartBuilder(QAnyStringView name, PrivateConstructor /*unused*/)
|
||||
{
|
||||
static_assert(std::is_nothrow_move_constructible_v<decltype(m_body)>);
|
||||
static_assert(std::is_nothrow_move_assignable_v<decltype(m_body)>);
|
||||
|
||||
const auto enc = name.visit([](auto name) { return nameToByteArray(name); });
|
||||
|
||||
m_headerValue += "form-data; name=\"";
|
||||
for (auto c : name) {
|
||||
for (auto c : enc) {
|
||||
if (c == '"' || c == '\\')
|
||||
m_headerValue += '\\';
|
||||
m_headerValue += c;
|
||||
@ -292,10 +312,14 @@ QFormDataBuilder::~QFormDataBuilder()
|
||||
\a name as the name parameter of the form-data. The returned reference is
|
||||
valid until the next call to this function.
|
||||
|
||||
Limiting \a name characters to US-ASCII is
|
||||
\l {https://datatracker.ietf.org/doc/html/rfc7578#section-5.1.1}{strongly recommended}
|
||||
for interoperability reasons.
|
||||
|
||||
\sa QFormDataPartBuilder, QHttpPart
|
||||
*/
|
||||
|
||||
QFormDataPartBuilder &QFormDataBuilder::part(QLatin1StringView name)
|
||||
QFormDataPartBuilder &QFormDataBuilder::part(QAnyStringView name)
|
||||
{
|
||||
static_assert(std::is_nothrow_move_constructible_v<decltype(m_parts)>);
|
||||
static_assert(std::is_nothrow_move_assignable_v<decltype(m_parts)>);
|
||||
|
@ -32,7 +32,7 @@ class QFormDataPartBuilder
|
||||
{
|
||||
struct PrivateConstructor { explicit PrivateConstructor() = default; };
|
||||
public:
|
||||
Q_NETWORK_EXPORT explicit QFormDataPartBuilder(QLatin1StringView name, PrivateConstructor);
|
||||
Q_NETWORK_EXPORT explicit QFormDataPartBuilder(QAnyStringView name, PrivateConstructor);
|
||||
|
||||
QFormDataPartBuilder(QFormDataPartBuilder &&other) noexcept
|
||||
: m_headerValue(std::move(other.m_headerValue)),
|
||||
@ -109,7 +109,7 @@ public:
|
||||
}
|
||||
|
||||
Q_NETWORK_EXPORT ~QFormDataBuilder();
|
||||
Q_NETWORK_EXPORT QFormDataPartBuilder &part(QLatin1StringView name);
|
||||
Q_NETWORK_EXPORT QFormDataPartBuilder &part(QAnyStringView name);
|
||||
Q_NETWORK_EXPORT std::unique_ptr<QHttpMultiPart> buildMultiPart();
|
||||
private:
|
||||
std::vector<QFormDataPartBuilder> m_parts;
|
||||
|
@ -29,6 +29,9 @@ private Q_SLOTS:
|
||||
|
||||
void specifyMimeType_data();
|
||||
void specifyMimeType();
|
||||
|
||||
void picksUtf8NameEncodingIfAsciiDoesNotSuffice_data();
|
||||
void picksUtf8NameEncodingIfAsciiDoesNotSuffice();
|
||||
};
|
||||
|
||||
void tst_QFormDataBuilder::generateQHttpPartWithDevice_data()
|
||||
@ -325,6 +328,35 @@ void tst_QFormDataBuilder::specifyMimeType()
|
||||
QVERIFY(msg.contains(expected_content_type_data));
|
||||
}
|
||||
|
||||
void tst_QFormDataBuilder::picksUtf8NameEncodingIfAsciiDoesNotSuffice_data()
|
||||
{
|
||||
QTest::addColumn<QAnyStringView>("name_data");
|
||||
QTest::addColumn<QString>("expected_content_disposition_data");
|
||||
|
||||
QTest::newRow("latin1-ascii") << QAnyStringView("text"_L1) << uR"(form-data; name="text")"_s;
|
||||
QTest::newRow("u8-ascii") << QAnyStringView(u8"text") << uR"(form-data; name="text")"_s;
|
||||
QTest::newRow("u-ascii") << QAnyStringView(u"text") << uR"(form-data; name="text")"_s;
|
||||
|
||||
// 0xF6 is 'ö', use hex value with Latin-1 to avoid interpretation as UTF-8
|
||||
QTest::newRow("latin1-latin") << QAnyStringView("t\xF6xt"_L1) << uR"(form-data; name="töxt")"_s;
|
||||
QTest::newRow("u8-latin") << QAnyStringView(u8"töxt") << uR"(form-data; name="töxt")"_s;
|
||||
QTest::newRow("u-latin") << QAnyStringView(u"töxt") << uR"(form-data; name="töxt")"_s;
|
||||
|
||||
QTest::newRow("u8-u8") << QAnyStringView(u8"テキスト") << uR"(form-data; name="テキスト")"_s;
|
||||
}
|
||||
|
||||
void tst_QFormDataBuilder::picksUtf8NameEncodingIfAsciiDoesNotSuffice()
|
||||
{
|
||||
QFETCH(const QAnyStringView, name_data);
|
||||
QFETCH(const QString, expected_content_disposition_data);
|
||||
|
||||
QFormDataBuilder qfdb;
|
||||
QFormDataPartBuilder &qfdpb = qfdb.part(name_data).setBody("some"_ba);
|
||||
auto msg = QDebug::toString(qfdpb.build());
|
||||
|
||||
QVERIFY2(msg.contains(expected_content_disposition_data),
|
||||
qPrintable(u"content-disposition not found : "_s + expected_content_disposition_data));
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QFormDataBuilder)
|
||||
#include "tst_qformdatabuilder.moc"
|
||||
|
Loading…
x
Reference in New Issue
Block a user