Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qdataurl.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:critical reason:data-parser
4
5#include "qplatformdefs.h"
6#include "qurl.h"
7#include "private/qdataurl_p.h"
8
10
11using namespace Qt::Literals;
12
13/*!
14 \internal
15
16 Decode a data: URL into its mimetype and payload. Returns a null string if
17 the URL could not be decoded.
18*/
19Q_CORE_EXPORT bool qDecodeDataUrl(const QUrl &uri, QString &mimeType, QByteArray &payload)
20{
21 /* https://www.rfc-editor.org/rfc/rfc2397.html
22
23 data:[<mediatype>][;base64],<data>
24 dataurl := "data:" [ mediatype ] [ ";base64" ] "," data
25 mediatype := [ type "/" subtype ] *( ";" parameter )
26 data := *urlchar
27 parameter := attribute "=" value
28 */
29
30 if (uri.scheme() != "data"_L1 || !uri.host().isEmpty())
31 return false;
32
33 payload = uri.toEncoded(QUrl::RemoveScheme);
34 // parse it:
35 // percent decode after finding the `,`, to workaround parameter
36 // values containing a percent-encoded comma
37 const qsizetype pos = payload.indexOf(',');
38 if (pos != -1) {
39 QByteArray contentType = payload.first(pos).percentDecoded();
40 auto data = QLatin1StringView{contentType};
41 data = data.trimmed();
42
43 QLatin1StringView mime;
44 QLatin1StringView charsetParam;
45 constexpr auto charset = "charset"_L1;
46 bool first = true;
47 for (auto part : qTokenize(data, u';', Qt::SkipEmptyParts)) {
48 part = part.trimmed();
49 if (first) {
50 if (part.contains(u'/'))
51 mime = part;
52 first = false;
53 }
54 // Minimal changes, e.g. if it's "charset=;" or "charset;" without
55 // an encoding, leave it as-is
56 if (part.startsWith(charset, Qt::CaseInsensitive))
57 charsetParam = part;
58
59 if (!mime.isEmpty() && !charsetParam.isEmpty())
60 break;
61 }
62
63 if (mime.isEmpty()) {
64 mime = "text/plain"_L1;
65 if (charsetParam.isEmpty())
66 charsetParam = "charset=US-ASCII"_L1;
67 }
68 if (!charsetParam.isEmpty())
69 mimeType = mime + u';' + charsetParam;
70 else
71 mimeType = mime;
72
73 // find out if the payload is encoded in Base64
74 constexpr auto base64 = ";base64"_L1; // per the RFC, at the end of `data`
75 const bool isBas64 = data.endsWith(base64, Qt::CaseInsensitive);
76
77 payload.slice(pos + 1);
78 data = {};
79 payload = std::move(payload).percentDecoded();
80
81 if (isBas64) {
82 auto r = QByteArray::fromBase64Encoding(std::move(payload));
83 if (!r) {
84 // just in case someone uses `payload` without checking the returned bool
85 payload = {};
86 return false; // decoding failed
87 }
88 payload = std::move(r.decoded);
89 }
90
91 return true;
92 } else {
93 payload = {};
94 }
95
96 return false;
97}
98
99QT_END_NAMESPACE
Q_CORE_EXPORT bool qDecodeDataUrl(const QUrl &uri, QString &mimeType, QByteArray &payload)
Definition qdataurl.cpp:19