diff options
| author | Jonah Brüchert <jbb@kaidan.im> | 2022-09-05 19:23:07 +0200 |
|---|---|---|
| committer | Linus Jahn <lnj@kaidan.im> | 2022-09-06 00:46:56 +0200 |
| commit | e2e27c8c953d6650a1ede2596a3537e5ebd5cea5 (patch) | |
| tree | 71229ce7f6a0fe437e69103e0c5355721264ad00 /src/base | |
| parent | 6685217ac78c7588aaea67059a0844d51713dcd5 (diff) | |
| download | qxmpp-e2e27c8c953d6650a1ede2596a3537e5ebd5cea5.tar.gz | |
Add parsing of XEP-0446: File metadata element
This implements version 0.2.0
https://xmpp.org/extensions/xep-0446.html
Diffstat (limited to 'src/base')
| -rw-r--r-- | src/base/QXmppConstants.cpp | 2 | ||||
| -rw-r--r-- | src/base/QXmppConstants_p.h | 2 | ||||
| -rw-r--r-- | src/base/QXmppFileMetadata.cpp | 276 | ||||
| -rw-r--r-- | src/base/QXmppFileMetadata.h | 66 |
4 files changed, 346 insertions, 0 deletions
diff --git a/src/base/QXmppConstants.cpp b/src/base/QXmppConstants.cpp index 30eb8d22..86438f15 100644 --- a/src/base/QXmppConstants.cpp +++ b/src/base/QXmppConstants.cpp @@ -186,5 +186,7 @@ const char *ns_mix_misc = "urn:xmpp:mix:misc:0"; const char *ns_fallback_indication = "urn:xmpp:fallback:0"; // XEP-0434: Trust Messages (TM) const char *ns_tm = "urn:xmpp:tm:1"; +// XEP-0446: File metadata element +const char *ns_file_metadata = "urn:xmpp:file:metadata:0"; // XEP-0450: Automatic Trust Management (ATM) const char *ns_atm = "urn:xmpp:atm:1"; diff --git a/src/base/QXmppConstants_p.h b/src/base/QXmppConstants_p.h index 32c1cdbd..4f8dd2ed 100644 --- a/src/base/QXmppConstants_p.h +++ b/src/base/QXmppConstants_p.h @@ -198,6 +198,8 @@ extern const char *ns_mix_misc; extern const char *ns_fallback_indication; // XEP-0434: Trust Messages (TM) extern const char *ns_tm; +// XEP-0446: File metadata element +extern const char *ns_file_metadata; // XEP-0450: Automatic Trust Management (ATM) extern const char *ns_atm; diff --git a/src/base/QXmppFileMetadata.cpp b/src/base/QXmppFileMetadata.cpp new file mode 100644 index 00000000..35b5b040 --- /dev/null +++ b/src/base/QXmppFileMetadata.cpp @@ -0,0 +1,276 @@ +// SPDX-FileCopyrightText: 2022 Jonah Brüchert <jbb@kaidan.im> +// +// SPDX-License-Identifier: LGPL-2.1-or-later + +#include "QXmppFileMetadata.h" + +#include "QXmppConstants_p.h" +#include "QXmppHash.h" +#include "QXmppUtils.h" +#include "QXmppThumbnail.h" + +#include <utility> + +#include <QDateTime> +#include <QDomElement> +#include <QMimeDatabase> +#include <QMimeType> +#include <QSharedData> + +class QXmppFileMetadataPrivate : public QSharedData +{ +public: + std::optional<QDateTime> date; + std::optional<QString> desc; + QVector<QXmppHash> hashes; + std::optional<uint32_t> height; + std::optional<uint32_t> length; + std::optional<QMimeType> mediaType; + std::optional<QString> name; + std::optional<uint64_t> size; + std::optional<QXmppThumbnail> thumbnail; + std::optional<uint32_t> width; +}; + +/// +/// \class QXmppFileMetadata +/// +/// File metadata from \xep{0446, File metadata element}. +/// +/// \since QXmpp 1.5 +/// + +QXmppFileMetadata::QXmppFileMetadata() + : d(new QXmppFileMetadataPrivate()) +{ +} + +QXMPP_PRIVATE_DEFINE_ROLE_OF_SIX(QXmppFileMetadata) + +/// \cond +QVector<QDomElement> allChildElements(const QDomElement &el, const QString &name) +{ + QVector<QDomElement> out; + + for (auto childEl = el.firstChildElement(name); !childEl.isNull(); childEl = childEl.nextSiblingElement(name)) { + out.push_back(childEl); + } + + return out; +} + +template<typename Func> +QVector<std::invoke_result_t<Func, QDomElement>> forAllChildElements(const QDomElement &el, const QString &name, Func func) +{ + auto elements = allChildElements(el, name); + QVector<std::invoke_result_t<Func, QDomElement>> out; + std::transform(elements.begin(), elements.end(), std::back_inserter(out), func); + return out; +} + +bool QXmppFileMetadata::parse(const QDomElement &el) +{ + if (el.isNull()) + return false; + + if (auto dateEl = el.firstChildElement("date"); !dateEl.isNull()) { + d->date = QXmppUtils::datetimeFromString(dateEl.text()); + } + + if (auto descEl = el.firstChildElement("desc"); !descEl.isNull()) { + d->desc = descEl.text(); + } + + d->hashes = forAllChildElements(el, "hash", [](const auto &el) { + QXmppHash hash; + hash.parse(el); + return hash; + }); + + if (auto heightEl = el.firstChildElement("height"); !heightEl.isNull()) { + d->height = el.firstChildElement("height").text().toUInt(); + } + if (auto lengthEl = el.firstChildElement("length"); !lengthEl.isNull()) { + d->length = lengthEl.text().toUInt(); + } + if (auto mediaTypeEl = el.firstChildElement("media-type"); !mediaTypeEl.isNull()) { + d->mediaType = QMimeDatabase().mimeTypeForName(mediaTypeEl.text()); + } + if (auto nameEl = el.firstChildElement("name"); !nameEl.isNull()) { + d->name = nameEl.text(); + } + if (auto sizeEl = el.firstChildElement("size"); !sizeEl.isNull()) { + d->size = sizeEl.text().toULong(); + } + if (auto thumbEl = el.firstChildElement("thumbnail"); !thumbEl.isNull()) { + d->thumbnail = QXmppThumbnail(); + if (!d->thumbnail->parse(thumbEl)) { + d->thumbnail.reset(); + } + } + if (auto widthEl = el.firstChildElement("width"); !widthEl.isNull()) { + d->width = widthEl.text().toUInt(); + } + return true; +} + +void QXmppFileMetadata::toXml(QXmlStreamWriter *writer) const +{ + writer->writeStartElement("file"); + writer->writeDefaultNamespace(ns_file_metadata); + if (d->date) { + writer->writeTextElement("date", QXmppUtils::datetimeToString(*d->date)); + } + + if (d->desc) { + writer->writeTextElement("desc", *d->desc); + } + + for (const auto &hash : d->hashes) { + hash.toXml(writer); + } + + if (d->height) { + writer->writeTextElement("height", QString::number(*d->height)); + } + if (d->length) { + writer->writeTextElement("length", QString::number(*d->length)); + } + if (d->mediaType) { + writer->writeTextElement("media-type", d->mediaType->name()); + } + if (d->name) { + writer->writeTextElement("name", *d->name); + } + if (d->size) { + writer->writeTextElement("size", QString::number(*d->size)); + } + if (d->thumbnail) { + d->thumbnail->toXml(writer); + } + if (d->width) { + writer->writeTextElement("width", QString::number(*d->width)); + } + writer->writeEndElement(); +} +/// \endcond + +/// Returns when the file was last modified +const std::optional<QDateTime> &QXmppFileMetadata::lastModified() const +{ + return d->date; +} + +/// Sets when the file was last modified +void QXmppFileMetadata::setLastModified(const std::optional<QDateTime> &date) +{ + d->date = date; +} + +/// Returns the description of the file +const std::optional<QString> &QXmppFileMetadata::description() const +{ + return d->desc; +} + +/// Sets the description of the file +void QXmppFileMetadata::setDescription(const std::optional<QString> &description) +{ + d->desc = description; +} + +/// Returns the hashes of the file +const QVector<QXmppHash> &QXmppFileMetadata::hashes() const +{ + return d->hashes; +} + +/// Sets the hashes of the file +void QXmppFileMetadata::setHashes(const QVector<QXmppHash> &hashes) +{ + d->hashes = hashes; +} + +/// Returns the height of the image +std::optional<uint32_t> QXmppFileMetadata::height() const +{ + return d->height; +} + +/// Sets the height of the image +void QXmppFileMetadata::setHeight(std::optional<uint32_t> height) +{ + d->height = height; +} + +/// Returns the length of a video or audio file +std::optional<uint32_t> QXmppFileMetadata::length() const +{ + return d->length; +} + +/// Sets the length of a video or audio file +void QXmppFileMetadata::setLength(std::optional<uint32_t> length) +{ + d->length = length; +} + +/// Returns the media type of the file +const std::optional<QMimeType> &QXmppFileMetadata::mediaType() const +{ + return d->mediaType; +} + +/// Sets the media type of the file +void QXmppFileMetadata::setMediaType(std::optional<QMimeType> mediaType) +{ + d->mediaType = std::move(mediaType); +} + +/// Returns the filename +std::optional<QString> QXmppFileMetadata::filename() const +{ + return d->name; +} + +/// Sets the filename +void QXmppFileMetadata::setFilename(std::optional<QString> name) +{ + d->name = std::move(name); +} + +/// Returns the size of the file in bytes +std::optional<uint64_t> QXmppFileMetadata::size() const +{ + return d->size; +} + +/// Sets the size of the file in bytes +void QXmppFileMetadata::setSize(std::optional<uint64_t> size) +{ + d->size = size; +} + +/// Returns the thumbnail reference. +const std::optional<QXmppThumbnail> &QXmppFileMetadata::thumbnail() const +{ + return d->thumbnail; +} + +/// Sets the thumbnail reference. +void QXmppFileMetadata::setThumbnail(const std::optional<QXmppThumbnail> &thumbnail) +{ + d->thumbnail = thumbnail; +} + +/// Returns the width of the image or video. +std::optional<uint32_t> QXmppFileMetadata::width() const +{ + return d->width; +} + +/// Sets the width of the image or video. +void QXmppFileMetadata::setWidth(std::optional<uint32_t> width) +{ + d->width = width; +} diff --git a/src/base/QXmppFileMetadata.h b/src/base/QXmppFileMetadata.h new file mode 100644 index 00000000..e45e6506 --- /dev/null +++ b/src/base/QXmppFileMetadata.h @@ -0,0 +1,66 @@ +// SPDX-FileCopyrightText: 2022 Jonah Brüchert <jbb@kaidan.im> +// +// SPDX-License-Identifier: LGPL-2.1-or-later + +#ifndef QXMPPFILEMETADATA_H +#define QXMPPFILEMETADATA_H + +#include "QXmppGlobal.h" +#include "QXmppHash.h" + +#include <optional> + +#include <QMimeType> +#include <QSharedDataPointer> + +class QDomElement; +class QDateTime; +class QXmlStreamWriter; +class QXmppThumbnail; +class QXmppFileMetadataPrivate; + +class QXMPP_EXPORT QXmppFileMetadata +{ +public: + QXmppFileMetadata(); + + /// \cond + bool parse(const QDomElement &el); + void toXml(QXmlStreamWriter *writer) const; + /// \endcond + + const std::optional<QDateTime> &lastModified() const; + void setLastModified(const std::optional<QDateTime> &date); + + const std::optional<QString> &description() const; + void setDescription(const std::optional<QString> &description); + + const QVector<QXmppHash> &hashes() const; + void setHashes(const QVector<QXmppHash> &hashes); + + std::optional<uint32_t> height() const; + void setHeight(std::optional<uint32_t> height); + + std::optional<uint32_t> length() const; + void setLength(std::optional<uint32_t> length); + + const std::optional<QMimeType> &mediaType() const; + void setMediaType(std::optional<QMimeType> mediaType); + + std::optional<QString> filename() const; + void setFilename(std::optional<QString>); + + std::optional<uint64_t> size() const; + void setSize(std::optional<uint64_t> size); + + const std::optional<QXmppThumbnail> &thumbnail() const; + void setThumbnail(const std::optional<QXmppThumbnail> &thumbnail); + + std::optional<uint32_t> width() const; + void setWidth(std::optional<uint32_t> width); + +private: + QSharedDataPointer<QXmppFileMetadataPrivate> d; +}; + +#endif |
