/** * Copyright 2013 Albert Vaca * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "networkpacket.h" #include "core_debug.h" #include #include #include #include #include #include #include #include "dbushelper.h" #include "filetransferjob.h" #include "pluginloader.h" #include "kdeconnectconfig.h" QDebug operator<<(QDebug s, const NetworkPacket& pkg) { s.nospace() << "NetworkPacket(" << pkg.type() << ':' << pkg.body(); if (pkg.hasPayload()) { s.nospace() << ":withpayload"; } s.nospace() << ')'; return s.space(); } const int NetworkPacket::s_protocolVersion = 7; NetworkPacket::NetworkPacket(const QString& type, const QVariantMap& body) : m_id(QString::number(QDateTime::currentMSecsSinceEpoch())) , m_type(type) , m_body(body) , m_payload() , m_payloadSize(0) { } void NetworkPacket::createIdentityPacket(NetworkPacket* np) { np->m_id = QString::number(QDateTime::currentMSecsSinceEpoch()); np->m_type = PACKET_TYPE_IDENTITY; np->m_payload = QSharedPointer(); np->m_payloadSize = 0; np->set(QStringLiteral("deviceId"), KdeConnectConfig::instance().deviceId()); np->set(QStringLiteral("deviceName"), KdeConnectConfig::instance().name()); np->set(QStringLiteral("deviceType"), KdeConnectConfig::instance().deviceType()); np->set(QStringLiteral("protocolVersion"), NetworkPacket::s_protocolVersion); np->set(QStringLiteral("incomingCapabilities"), PluginLoader::instance()->incomingCapabilities()); np->set(QStringLiteral("outgoingCapabilities"), PluginLoader::instance()->outgoingCapabilities()); //qCDebug(KDECONNECT_CORE) << "createIdentityPacket" << np->serialize(); } QByteArray NetworkPacket::serialize() const { //Object -> QVariant QVariantMap variant; variant.insert(QStringLiteral("id"), m_id); variant.insert(QStringLiteral("type"), m_type); variant.insert(QStringLiteral("body"), m_body); if (hasPayload()) { variant.insert(QStringLiteral("payloadSize"), m_payloadSize); variant.insert(QStringLiteral("payloadTransferInfo"), m_payloadTransferInfo); } //QVariant -> json auto jsonDocument = QJsonDocument::fromVariant(variant); QByteArray json = jsonDocument.toJson(QJsonDocument::Compact); if (json.isEmpty()) { qCDebug(KDECONNECT_CORE) << "Serialization error:"; } else { /*if (!isEncrypted()) { //qCDebug(KDECONNECT_CORE) << "Serialized packet:" << json; }*/ json.append('\n'); } return json; } template void qvariant2qobject(const QVariantMap& variant, T* object) { for ( QVariantMap::const_iterator iter = variant.begin(); iter != variant.end(); ++iter ) { const int propertyIndex = T::staticMetaObject.indexOfProperty(iter.key().toLatin1()); if (propertyIndex < 0) { qCWarning(KDECONNECT_CORE) << "missing property" << object << iter.key(); continue; } QMetaProperty property = T::staticMetaObject.property(propertyIndex); bool ret = property.writeOnGadget(object, *iter); if (!ret) { qCWarning(KDECONNECT_CORE) << "couldn't set" << object << "->" << property.name() << '=' << *iter; } } } bool NetworkPacket::unserialize(const QByteArray& a, NetworkPacket* np) { //Json -> QVariant QJsonParseError parseError; auto parser = QJsonDocument::fromJson(a, &parseError); if (parser.isNull()) { qCDebug(KDECONNECT_CORE) << "Unserialization error:" << parseError.errorString(); return false; } auto variant = parser.toVariant().toMap(); qvariant2qobject(variant, np); if (np->m_payloadSize == -1) { np->m_payloadSize = np->get(QStringLiteral("size"), -1); } np->m_payloadTransferInfo = variant[QStringLiteral("payloadTransferInfo")].toMap(); //Will return an empty qvariantmap if was not present, which is ok //Ids containing characters that are not allowed as dbus paths would make app crash if (np->m_body.contains(QStringLiteral("deviceId"))) { QString deviceId = np->get(QStringLiteral("deviceId")); DBusHelper::filterNonExportableCharacters(deviceId); np->set(QStringLiteral("deviceId"), deviceId); } return true; } FileTransferJob* NetworkPacket::createPayloadTransferJob(const QUrl& destination) const { return new FileTransferJob(this, destination); }