diff options
| author | Ahmad Samir <a.samirh78@gmail.com> | 2025-04-26 16:51:30 +0300 |
|---|---|---|
| committer | Ahmad Samir <a.samirh78@gmail.com> | 2025-05-24 01:12:55 +0300 |
| commit | 29a00e959b4d9cc58df3ba080b56eb8a3631eb20 (patch) | |
| tree | c65831cb825b5c300f65b2f3840ae9f0157649d9 /src | |
| parent | d4960f380e718bbc3df3fe33c68ba8c693394892 (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.cpp | 45 |
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; } |
