summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAhmad Samir <a.samirh78@gmail.com>2025-04-26 16:51:30 +0300
committerAhmad Samir <a.samirh78@gmail.com>2025-05-24 01:12:55 +0300
commit29a00e959b4d9cc58df3ba080b56eb8a3631eb20 (patch)
treec65831cb825b5c300f65b2f3840ae9f0157649d9 /src
parentd4960f380e718bbc3df3fe33c68ba8c693394892 (diff)
qdataurl: make parsing the content-type more robust
Don't assume `charset` is the first parameter. The parameters (attribute=value pairs) are delemited by a `;`. The order of the parameters isn't specified, (except for `;base64` which is the last one). Add more tests. Add a test for image/png (.png file copied from src/widgets/styles/images/arrow-down-16.png). Change-Id: Ie3e45c607c093695d0c180e9a9783b2b02d7ef70 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/io/qdataurl.cpp45
1 files changed, 35 insertions, 10 deletions
diff --git a/src/corelib/io/qdataurl.cpp b/src/corelib/io/qdataurl.cpp
index ef468f2ea16..eca94443375 100644
--- a/src/corelib/io/qdataurl.cpp
+++ b/src/corelib/io/qdataurl.cpp
@@ -17,6 +17,15 @@ using namespace Qt::Literals;
*/
Q_CORE_EXPORT bool qDecodeDataUrl(const QUrl &uri, QString &mimeType, QByteArray &payload)
{
+ /* https://www.rfc-editor.org/rfc/rfc2397.html
+
+ data:[<mediatype>][;base64],<data>
+ dataurl := "data:" [ mediatype ] [ ";base64" ] "," data
+ mediatype := [ type "/" subtype ] *( ";" parameter )
+ data := *urlchar
+ parameter := attribute "=" value
+ */
+
if (uri.scheme() != "data"_L1 || !uri.host().isEmpty())
return false;
@@ -48,20 +57,36 @@ Q_CORE_EXPORT bool qDecodeDataUrl(const QUrl &uri, QString &mimeType, QByteArray
data.chop(base64.size());
}
- QLatin1StringView textPlain;
+ QLatin1StringView mime;
+ QLatin1StringView charsetParam;
constexpr auto charset = "charset"_L1;
- if (data.startsWith(charset, Qt::CaseInsensitive)) {
- QLatin1StringView copy = data.sliced(charset.size());
- while (copy.startsWith(u' '))
- copy.slice(1);
- if (copy.startsWith(u'='))
- textPlain = "text/plain;"_L1;
+ bool first = true;
+ for (auto part : qTokenize(data, u';', Qt::SkipEmptyParts)) {
+ part = part.trimmed();
+ if (first) {
+ if (part.contains(u'/'))
+ mime = part;
+ first = false;
+ }
+ // Minimal changes, e.g. if it's "charset=;" or "charset;" without
+ // an encoding, leave it as-is
+ if (part.startsWith(charset, Qt::CaseInsensitive))
+ charsetParam = part;
+
+ if (!mime.isEmpty() && !charsetParam.isEmpty())
+ break;
}
- if (!data.isEmpty())
- mimeType = textPlain + data.trimmed();
+ if (mime.isEmpty()) {
+ mime = "text/plain"_L1;
+ if (charsetParam.isEmpty())
+ charsetParam = "charset=US-ASCII"_L1;
+ }
+ if (!charsetParam.isEmpty())
+ mimeType = mime + u';' + charsetParam;
else
- mimeType = QStringLiteral("text/plain;charset=US-ASCII");
+ mimeType = mime;
+
return true;
}