diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2013-07-13 12:04:40 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-14 03:20:25 +0200 |
commit | cc741597021dd5e9c7ca2caffaf8a15181f68e89 (patch) | |
tree | 5269f5485422717baedfc651af5decbe5a8b5875 /src/corelib | |
parent | 3154e1ccaabfbdb42aa48cbb5805b23442cdc33e (diff) |
Base64: Implement the "base64url" encoding and the stripping of '='
The "base64url" encoding is defined in RFC 4648, which is the newest
version of Base64. There are also a few situations where the ending
'=' is not desired.
Change-Id: I9bb9fa55817b57d125189e4e795d6fde97caea6d
Reviewed-by: Richard J. Moore <rich@kde.org>
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp | 13 | ||||
-rw-r--r-- | src/corelib/doc/src/external-resources.qdoc | 5 | ||||
-rw-r--r-- | src/corelib/tools/qbytearray.cpp | 95 | ||||
-rw-r--r-- | src/corelib/tools/qbytearray.h | 17 |
4 files changed, 116 insertions, 14 deletions
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp index c2a375f498..003fce580b 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp @@ -352,6 +352,14 @@ QByteArray text("Qt is great!"); text.toBase64(); // returns "UXQgaXMgZ3JlYXQh" //! [39] +//! [39bis] +QByteArray text("<p>Hello?</p>"); +text.toBase64(QByteArray::Base64 | QByteArray::OmitTrailingEquals); // returns "PHA+SGVsbG8/PC9wPg" +text.toBase64(QByteArray::Base64); // returns "PHA+SGVsbG8/PC9wPg==" +text.toBase64(QByteArray::Base64Url); // returns "PHA-SGVsbG8_PC9wPg==" +text.toBase64(QByteArray::Base64Url | QByteArray::OmitTrailingEquals); // returns "PHA-SGVsbG8_PC9wPg" +//! [39bis] + //! [40] QByteArray ba; @@ -394,6 +402,11 @@ QByteArray text = QByteArray::fromBase64("UXQgaXMgZ3JlYXQh"); text.data(); // returns "Qt is great!" //! [44] +//! [44bis] +QByteArray::fromBase64("PHA+SGVsbG8/PC9wPg==", QByteArray::Base64Encoding); // returns "<p>Hello?</p>" +QByteArray::fromBase64("PHA-SGVsbG8_PC9wPg==", QByteArray::Base64UrlEncoding); // returns "<p>Hello?</p>" +//! [44bis] + //! [45] QByteArray text = QByteArray::fromHex("517420697320677265617421"); diff --git a/src/corelib/doc/src/external-resources.qdoc b/src/corelib/doc/src/external-resources.qdoc index 86df385d9e..d1c7eb5d1b 100644 --- a/src/corelib/doc/src/external-resources.qdoc +++ b/src/corelib/doc/src/external-resources.qdoc @@ -67,6 +67,11 @@ */ /*! + \externalpage http://www.ietf.org/rfc/rfc4648.txt + \title RFC 4648 +*/ + +/*! \externalpage http://www.iana.org/assignments/character-sets/character-sets.xml \title IANA character-sets encoding file */ diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index 7ec7333054..975894a516 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -795,6 +795,27 @@ static inline char qToLower(char c) \sa QString, QBitArray */ +/*! + \enum QByteArray::Base64Option + \since 5.2 + + This enum contains the options available for encoding and decoding Base64. + Base64 is defined by \l{RFC 4648}, with the following options: + + \value Base64Encoding (default) The regular Base64 alphabet, called simply "base64" + \value Base64UrlEncoding An alternate alphabet, called "base64url", which replaces two + characters in the alphabet to be more friendly to URLs. + \value KeepTrailingEquals (default) Keeps the trailing padding equal signs at the end + of the encoded data, so the data is always a size multiple of + four. + \value OmitTrailingEquals Omits adding the padding equal signs at the end of the encoded + data. + + QByteArray::fromBase64() ignores the KeepTrailingEquals and + OmitTrailingEquals options and will not flag errors in case they are + missing or if there are too many of them. +*/ + /*! \fn QByteArray::iterator QByteArray::begin() \internal @@ -3539,14 +3560,34 @@ float QByteArray::toFloat(bool *ok) const \snippet code/src_corelib_tools_qbytearray.cpp 39 - The algorithm used to encode Base64-encoded data is defined in \l{RFC 2045}. + The algorithm used to encode Base64-encoded data is defined in \l{RFC 4648}. \sa fromBase64() */ QByteArray QByteArray::toBase64() const { - const char alphabet[] = "ABCDEFGH" "IJKLMNOP" "QRSTUVWX" "YZabcdef" - "ghijklmn" "opqrstuv" "wxyz0123" "456789+/"; + return toBase64(Base64Encoding); +} + +/*! + \since 5.2 + \overload + + Returns a copy of the byte array, encoded using the options \a options. + + \snippet code/src_corelib_tools_qbytearray.cpp 39bis + + The algorithm used to encode Base64-encoded data is defined in \l{RFC 4648}. + + \sa fromBase64() +*/ +QByteArray QByteArray::toBase64(Base64Options options) const +{ + const char alphabet_base64[] = "ABCDEFGH" "IJKLMNOP" "QRSTUVWX" "YZabcdef" + "ghijklmn" "opqrstuv" "wxyz0123" "456789+/"; + const char alphabet_base64url[] = "ABCDEFGH" "IJKLMNOP" "QRSTUVWX" "YZabcdef" + "ghijklmn" "opqrstuv" "wxyz0123" "456789-_"; + const char *const alphabet = options & Base64UrlEncoding ? alphabet_base64url : alphabet_base64; const char padchar = '='; int padlen = 0; @@ -3575,14 +3616,18 @@ QByteArray QByteArray::toBase64() const *out++ = alphabet[j]; *out++ = alphabet[k]; - if (padlen > 1) - *out++ = padchar; - else + if (padlen > 1) { + if ((options & OmitTrailingEquals) == 0) + *out++ = padchar; + } else { *out++ = alphabet[l]; - if (padlen > 0) - *out++ = padchar; - else + } + if (padlen > 0) { + if ((options & OmitTrailingEquals) == 0) + *out++ = padchar; + } else { *out++ = alphabet[m]; + } } tmp.truncate(out - tmp.data()); @@ -3941,12 +3986,34 @@ QByteArray &QByteArray::setRawData(const char *data, uint size) \snippet code/src_corelib_tools_qbytearray.cpp 44 - The algorithm used to decode Base64-encoded data is defined in \l{RFC 2045}. + The algorithm used to decode Base64-encoded data is defined in \l{RFC 4648}. \sa toBase64() */ QByteArray QByteArray::fromBase64(const QByteArray &base64) { + return fromBase64(base64, Base64Encoding); +} + +/*! + \since 5.2 + \overload + + Returns a decoded copy of the Base64 array \a base64, using the alphabet + defined by \a options. Input is not checked for validity; invalid + characters in the input are skipped, enabling the decoding process to + continue with subsequent characters. + + For example: + + \snippet code/src_corelib_tools_qbytearray.cpp 44bis + + The algorithm used to decode Base64-encoded data is defined in \l{RFC 4648}. + + \sa toBase64() +*/ +QByteArray QByteArray::fromBase64(const QByteArray &base64, Base64Options options) +{ unsigned int buf = 0; int nbits = 0; QByteArray tmp((base64.size() * 3) / 4, Qt::Uninitialized); @@ -3962,9 +4029,13 @@ QByteArray QByteArray::fromBase64(const QByteArray &base64) d = ch - 'a' + 26; else if (ch >= '0' && ch <= '9') d = ch - '0' + 52; - else if (ch == '+') + else if (ch == '+' && (options & Base64UrlEncoding) == 0) d = 62; - else if (ch == '/') + else if (ch == '-' && (options & Base64UrlEncoding) != 0) + d = 62; + else if (ch == '/' && (options & Base64UrlEncoding) == 0) + d = 63; + else if (ch == '_' && (options & Base64UrlEncoding) != 0) d = 63; else d = -1; diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h index 85d1f0ab90..ae8166db81 100644 --- a/src/corelib/tools/qbytearray.h +++ b/src/corelib/tools/qbytearray.h @@ -173,6 +173,15 @@ private: typedef QTypedArrayData<char> Data; public: + enum Base64Option { + Base64Encoding = 0, + Base64UrlEncoding = 1, + + KeepTrailingEquals = 0, + OmitTrailingEquals = 2 + }; + Q_DECLARE_FLAGS(Base64Options, Base64Option) + inline QByteArray(); QByteArray(const char *, int size = -1); QByteArray(int size, char c); @@ -317,7 +326,8 @@ public: qulonglong toULongLong(bool *ok = 0, int base = 10) const; float toFloat(bool *ok = 0) const; double toDouble(bool *ok = 0) const; - QByteArray toBase64() const; + QByteArray toBase64(Base64Options options) const; + QByteArray toBase64() const; // ### Qt6 merge with previous QByteArray toHex() const; QByteArray toPercentEncoding(const QByteArray &exclude = QByteArray(), const QByteArray &include = QByteArray(), @@ -339,7 +349,8 @@ public: static QByteArray number(qulonglong, int base = 10); static QByteArray number(double, char f = 'g', int prec = 6); static QByteArray fromRawData(const char *, int size); - static QByteArray fromBase64(const QByteArray &base64); + static QByteArray fromBase64(const QByteArray &base64, Base64Options options); + static QByteArray fromBase64(const QByteArray &base64); // ### Qt6 merge with previous static QByteArray fromHex(const QByteArray &hexEncoded); static QByteArray fromPercentEncoding(const QByteArray &pctEncoded, char percent = '%'); @@ -392,6 +403,8 @@ public: inline DataPtr &data_ptr() { return d; } }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QByteArray::Base64Options) + inline QByteArray::QByteArray(): d(Data::sharedNull()) { } inline QByteArray::~QByteArray() { if (!d->ref.deref()) Data::deallocate(d); } inline int QByteArray::size() const |