File indexing completed on 2024-04-21 04:56:45

0001 /**
0002  * SPDX-FileCopyrightText: 2013 Albert Vaca <albertvaka@gmail.com>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 #include "networkpacket.h"
0008 #include "core_debug.h"
0009 
0010 #include <QByteArray>
0011 #include <QDataStream>
0012 #include <QDateTime>
0013 #include <QDebug>
0014 #include <QJsonDocument>
0015 #include <QMetaObject>
0016 #include <QMetaProperty>
0017 
0018 #include "dbushelper.h"
0019 #include "filetransferjob.h"
0020 #include "kdeconnectconfig.h"
0021 #include "pluginloader.h"
0022 
0023 QDebug operator<<(QDebug s, const NetworkPacket &pkg)
0024 {
0025     s.nospace() << "NetworkPacket(" << pkg.type() << ':' << pkg.body();
0026     if (pkg.hasPayload()) {
0027         s.nospace() << ":withpayload";
0028     }
0029     s.nospace() << ')';
0030     return s.space();
0031 }
0032 
0033 const int NetworkPacket::s_protocolVersion = 7;
0034 
0035 NetworkPacket::NetworkPacket(const QString &type, const QVariantMap &body)
0036     : m_id(QString::number(QDateTime::currentMSecsSinceEpoch()))
0037     , m_type(type)
0038     , m_body(body)
0039     , m_payload()
0040     , m_payloadSize(0)
0041 {
0042 }
0043 
0044 QByteArray NetworkPacket::serialize() const
0045 {
0046     // Object -> QVariant
0047     QVariantMap variant;
0048     variant.insert(QStringLiteral("id"), m_id);
0049     variant.insert(QStringLiteral("type"), m_type);
0050     variant.insert(QStringLiteral("body"), m_body);
0051 
0052     if (hasPayload()) {
0053         variant.insert(QStringLiteral("payloadSize"), m_payloadSize);
0054         variant.insert(QStringLiteral("payloadTransferInfo"), m_payloadTransferInfo);
0055     }
0056 
0057     // QVariant -> json
0058     auto jsonDocument = QJsonDocument::fromVariant(variant);
0059     QByteArray json = jsonDocument.toJson(QJsonDocument::Compact);
0060     if (json.isEmpty()) {
0061         qCDebug(KDECONNECT_CORE) << "Serialization error:";
0062     } else {
0063         /*if (!isEncrypted()) {
0064             //qCDebug(KDECONNECT_CORE) << "Serialized packet:" << json;
0065         }*/
0066         json.append('\n');
0067     }
0068 
0069     return json;
0070 }
0071 
0072 template<class T>
0073 void qvariant2qobject(const QVariantMap &variant, T *object)
0074 {
0075     for (QVariantMap::const_iterator iter = variant.begin(); iter != variant.end(); ++iter) {
0076         const int propertyIndex = T::staticMetaObject.indexOfProperty(iter.key().toLatin1().data());
0077         if (propertyIndex < 0) {
0078             qCWarning(KDECONNECT_CORE) << "missing property" << object << iter.key();
0079             continue;
0080         }
0081 
0082         QMetaProperty property = T::staticMetaObject.property(propertyIndex);
0083         bool ret = property.writeOnGadget(object, *iter);
0084         if (!ret) {
0085             qCWarning(KDECONNECT_CORE) << "couldn't set" << object << "->" << property.name() << '=' << *iter;
0086         }
0087     }
0088 }
0089 
0090 bool NetworkPacket::unserialize(const QByteArray &a, NetworkPacket *np)
0091 {
0092     // Json -> QVariant
0093     QJsonParseError parseError;
0094     auto parser = QJsonDocument::fromJson(a, &parseError);
0095     if (parser.isNull()) {
0096         qCDebug(KDECONNECT_CORE) << "Unserialization error:" << parseError.errorString();
0097         return false;
0098     }
0099 
0100     auto variant = parser.toVariant().toMap();
0101     qvariant2qobject(variant, np);
0102 
0103     np->m_payloadTransferInfo = variant[QStringLiteral("payloadTransferInfo")].toMap(); // Will return an empty qvariantmap if was not present, which is ok
0104 
0105     // Ids containing characters that are not allowed as dbus paths would make app crash
0106     if (np->m_body.contains(QStringLiteral("deviceId"))) {
0107         QString deviceId = np->get<QString>(QStringLiteral("deviceId"));
0108         DBusHelper::filterNonExportableCharacters(deviceId);
0109         np->set(QStringLiteral("deviceId"), deviceId);
0110     }
0111 
0112     return true;
0113 }
0114 
0115 FileTransferJob *NetworkPacket::createPayloadTransferJob(const QUrl &destination) const
0116 {
0117     return new FileTransferJob(this, destination);
0118 }
0119 
0120 #include "moc_networkpacket.cpp"