diff options
| author | Linus Jahn <lnj@kaidan.im> | 2019-11-16 22:39:26 +0100 |
|---|---|---|
| committer | LNJ <lnj@kaidan.im> | 2019-12-06 22:26:12 +0100 |
| commit | c470dbdfe053ef0e8d7e196982013f1edf2aaff5 (patch) | |
| tree | 863217f93b2071caab71b343c12bc59af875d33d /src/base | |
| parent | eb3e44bbe886315de76c89555403c95cd28e182f (diff) | |
| download | qxmpp-c470dbdfe053ef0e8d7e196982013f1edf2aaff5.tar.gz | |
Implement XEP-0231: Bits of Binary: content identifiers
This implements parsing and serialization of content identifiers from
XEP-0231: Bits of Binary in version 1.0.
Diffstat (limited to 'src/base')
| -rw-r--r-- | src/base/QXmppBitsOfBinaryContentId.cpp | 232 | ||||
| -rw-r--r-- | src/base/QXmppBitsOfBinaryContentId.h | 70 |
2 files changed, 302 insertions, 0 deletions
diff --git a/src/base/QXmppBitsOfBinaryContentId.cpp b/src/base/QXmppBitsOfBinaryContentId.cpp new file mode 100644 index 00000000..8e289c5f --- /dev/null +++ b/src/base/QXmppBitsOfBinaryContentId.cpp @@ -0,0 +1,232 @@ +/* + * Copyright (C) 2008-2019 The QXmpp developers + * + * Author: + * Linus Jahn + * + * Source: + * https://github.com/qxmpp-project/qxmpp + * + * This file is a part of QXmpp library. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + */ + +#include "QXmppBitsOfBinaryContentId.h" + +#include <QMap> +#include <QSharedData> +#include <QString> + +#define CONTENTID_URL QStringLiteral("cid:") +#define CONTENTID_URL_LENGTH 4 +#define CONTENTID_POSTFIX QStringLiteral("@bob.xmpp.org") +#define CONTENTID_POSTFIX_LENGTH 13 +#define CONTENTID_HASH_SEPARATOR QStringLiteral("+") + +static const QMap<QCryptographicHash::Algorithm, QString> HASH_ALGORITHMS = { + {QCryptographicHash::Sha1, QStringLiteral("sha1")}, +#ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1 + {QCryptographicHash::Md4, QStringLiteral("md4")}, + {QCryptographicHash::Md5, QStringLiteral("md5")}, + {QCryptographicHash::Sha224, QStringLiteral("sha224")}, + {QCryptographicHash::Sha256, QStringLiteral("sha256")}, + {QCryptographicHash::Sha384, QStringLiteral("sha384")}, + {QCryptographicHash::Sha512, QStringLiteral("sha512")}, + {QCryptographicHash::Sha3_224, QStringLiteral("sha3-224")}, + {QCryptographicHash::Sha3_256, QStringLiteral("sha3-256")}, + {QCryptographicHash::Sha3_384, QStringLiteral("sha3-384")}, + {QCryptographicHash::Sha3_512, QStringLiteral("sha3-512")}, +#endif +}; + +class QXmppBitsOfBinaryContentIdPrivate : public QSharedData +{ +public: + QXmppBitsOfBinaryContentIdPrivate(); + + QCryptographicHash::Algorithm algorithm; + QByteArray hash; +}; + +QXmppBitsOfBinaryContentIdPrivate::QXmppBitsOfBinaryContentIdPrivate() + : algorithm(QCryptographicHash::Sha1) +{ +} + +/// Parses a \c QXmppBitsOfBinaryContentId from a XEP-0231: Bits of Binary +/// \c cid: URL +/// +/// In case parsing failed, the returned \c QXmppBitsOfBinaryContentId is +/// empty. +/// +/// \see QXmppBitsOfBinaryContentId::fromContentId + +QXmppBitsOfBinaryContentId QXmppBitsOfBinaryContentId::fromCidUrl(const QString &input) +{ + if (input.startsWith(CONTENTID_URL)) + return fromContentId(input.mid(CONTENTID_URL_LENGTH)); + + return {}; +} + +/// Parses a \c QXmppBitsOfBinaryContentId from a XEP-0231: Bits of Binary +/// content id +/// +/// In case parsing failed, the returned \c QXmppBitsOfBinaryContentId is +/// empty. +/// +/// \note This does not allow \c cid: URLs to be passed. Use +/// \c QXmppBitsOfBinaryContentId::fromCidUrl for that purpose. +/// +/// \see QXmppBitsOfBinaryContentId::fromCidUrl + +QXmppBitsOfBinaryContentId QXmppBitsOfBinaryContentId::fromContentId(const QString &input) +{ + if (input.startsWith(CONTENTID_URL) || !input.endsWith(CONTENTID_POSTFIX)) + return {}; + + // remove '@bob.xmpp.org' + QString hashAndAlgoStr = input.left(input.size() - CONTENTID_POSTFIX_LENGTH); + // get size of hash algo id + QStringList algoAndHash = hashAndAlgoStr.split(CONTENTID_HASH_SEPARATOR); + if (algoAndHash.size() != 2) + return {}; + + QCryptographicHash::Algorithm algo = HASH_ALGORITHMS.key(algoAndHash.first(), QCryptographicHash::Algorithm(-1)); + if (int(algo) == -1) + return {}; + + QXmppBitsOfBinaryContentId cid; + cid.setAlgorithm(algo); + cid.setHash(QByteArray::fromHex(algoAndHash.last().toUtf8())); + + return cid; +} + +/// Default contructor + +QXmppBitsOfBinaryContentId::QXmppBitsOfBinaryContentId() + : d(new QXmppBitsOfBinaryContentIdPrivate) +{ +} + +/// Returns true, if two \c QXmppBitsOfBinaryContentId equal + +bool QXmppBitsOfBinaryContentId::operator==(const QXmppBitsOfBinaryContentId &other) const +{ + return d->algorithm == other.algorithm() && d->hash == other.hash(); +} + +QXmppBitsOfBinaryContentId::~QXmppBitsOfBinaryContentId() = default; + +QXmppBitsOfBinaryContentId::QXmppBitsOfBinaryContentId(const QXmppBitsOfBinaryContentId &cid) = default; + +QXmppBitsOfBinaryContentId &QXmppBitsOfBinaryContentId::operator=(const QXmppBitsOfBinaryContentId &other) = default; + +/// Returns a XEP-0231: Bits of Binary content id + +QString QXmppBitsOfBinaryContentId::toContentId() const +{ + if (!isValid()) + return {}; + + return HASH_ALGORITHMS.value(d->algorithm) + + CONTENTID_HASH_SEPARATOR + + d->hash.toHex() + + CONTENTID_POSTFIX; +} + +/// Returns a XEP-0231: Bits of Binary \c cid: URL + +QString QXmppBitsOfBinaryContentId::toCidUrl() const +{ + if (!isValid()) + return {}; + + return toContentId().prepend(CONTENTID_URL); +} + +/// Returns the hash value in binary form + +QByteArray QXmppBitsOfBinaryContentId::hash() const +{ + return d->hash; +} + +/// Sets the hash value in binary form + +void QXmppBitsOfBinaryContentId::setHash(const QByteArray &hash) +{ + d->hash = hash; +} + +/// Returns the hash algorithm used to calculate the \c hash value +/// +/// The default value is \c QCryptographicHash::Sha1. +/// +/// This currently supports MD4, MD5, SHA-1, SHA-2 (SHA224 - SHA512) and SHA-3 +/// (SHA3-224 - SHA3-512). + +QCryptographicHash::Algorithm QXmppBitsOfBinaryContentId::algorithm() const +{ + return d->algorithm; +} + +/// Sets the hash algorithm used to calculate the \c hash value +/// +/// The default value is \c QCryptographicHash::Sha1. +/// +/// This currently supports MD4, MD5, SHA-1, SHA-2 (SHA224 - SHA512) and SHA-3 +/// (SHA3-224 - SHA3-512). +/// +/// \note Only change this, if you know what you do. The XEP allows other +/// hashing algorithms than SHA-1 to be used, but not all clients support this. +/// Since in most cases the content id is not security relevant it is not a +/// problem to continue using SHA-1. + +void QXmppBitsOfBinaryContentId::setAlgorithm(QCryptographicHash::Algorithm algo) +{ + d->algorithm = algo; +} + +/// Checks whether the content id is valid and can be serialized into a string. +/// +/// \note Checking the hash length requires QXmpp to be built with Qt 5.12.0 or +/// later. +/// +/// \returns True, if the set hashing algorithm is supported, a hash value is +/// set and its length is correct, false otherwise. + +bool QXmppBitsOfBinaryContentId::isValid() const +{ +#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) + return !d->hash.isEmpty() && + HASH_ALGORITHMS.contains(d->algorithm) && + d->hash.length() == QCryptographicHash::hashLength(d->algorithm); +#else + return !d->hash.isEmpty() && HASH_ALGORITHMS.contains(d->algorithm); +#endif +} + +/// Checks whether \c input is a Bits of Binary content id or \c cid: URL +/// +/// \param checkIsCidUrl If true, it only accepts \c cid: URLs. +/// +/// \returns True, if \c input is valid. + +bool QXmppBitsOfBinaryContentId::isBitsOfBinaryContentId(const QString &input, bool checkIsCidUrl) +{ + return input.endsWith(CONTENTID_POSTFIX) && + input.contains(CONTENTID_HASH_SEPARATOR) && + (!checkIsCidUrl || input.startsWith(CONTENTID_URL)); +} diff --git a/src/base/QXmppBitsOfBinaryContentId.h b/src/base/QXmppBitsOfBinaryContentId.h new file mode 100644 index 00000000..7bf93685 --- /dev/null +++ b/src/base/QXmppBitsOfBinaryContentId.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2008-2019 The QXmpp developers + * + * Author: + * Linus Jahn + * + * Source: + * https://github.com/qxmpp-project/qxmpp + * + * This file is a part of QXmpp library. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + */ + +#ifndef QXMPPBITSOFBINARYCONTENTID_H +#define QXMPPBITSOFBINARYCONTENTID_H + +#include <QSharedDataPointer> +#include <QCryptographicHash> + +#include "QXmppGlobal.h" + +class QXmppBitsOfBinaryContentIdPrivate; + +/// \class QXmppBitsOfBinaryContentId represents a link to or an identifier of +/// XEP-0231: Bits of Binary data. +/// +/// \since QXmpp 1.2 + +class QXMPP_EXPORT QXmppBitsOfBinaryContentId +{ +public: + static QXmppBitsOfBinaryContentId fromCidUrl(const QString &input); + static QXmppBitsOfBinaryContentId fromContentId(const QString &input); + + QXmppBitsOfBinaryContentId(); + QXmppBitsOfBinaryContentId(const QXmppBitsOfBinaryContentId &cid); + ~QXmppBitsOfBinaryContentId(); + + QXmppBitsOfBinaryContentId &operator=(const QXmppBitsOfBinaryContentId &other); + + QString toContentId() const; + QString toCidUrl() const; + + QByteArray hash() const; + void setHash(const QByteArray &hash); + + QCryptographicHash::Algorithm algorithm() const; + void setAlgorithm(QCryptographicHash::Algorithm algo); + + bool isValid() const; + + static bool isBitsOfBinaryContentId(const QString &uri, bool checkIsCidUrl = false); + + bool operator==(const QXmppBitsOfBinaryContentId &other) const; + +private: + QSharedDataPointer<QXmppBitsOfBinaryContentIdPrivate> d; +}; + +#endif // QXMPPBITSOFBINARYCONTENTID_H |
