File indexing completed on 2023-12-03 08:28:36

0001 /*
0002     Copyright (C) 2014  Marcin ZiemiƄski   <zieminn@gmail.com>
0003 
0004     This program is free software: you can redistribute it and/or modify
0005     it under the terms of the GNU General Public License as published by
0006     the Free Software Foundation, either version 2 of the License, or
0007     (at your option) any later version.
0008 
0009     This program is distributed in the hope that it will be useful,
0010     but WITHOUT ANY WARRANTY; without even the implied warranty of
0011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0012     GNU General Public License for more details.
0013 
0014     You should have received a copy of the GNU General Public License
0015     along with this program.  If not, see <http://www.gnu.org/licenses/>.
0016 */
0017 
0018 #include "channel-adapter.h"
0019 
0020 #include "channel-proxy-interface.h"
0021 #include "utils.h"
0022 #include "constants.h"
0023 
0024 #include <debug.h>
0025 
0026 #include <TelepathyQt/SharedPtr>
0027 #include <TelepathyQt/ReceivedMessage>
0028 #include <QMap>
0029 #include <QGenericArgument>
0030 
0031 typedef QSharedPointer<KTp::Client::ChannelProxyInterfaceOTRInterface> OTRProxyPtr;
0032 
0033 static int getId(const Tp::ReceivedMessage &recvMes)
0034 {
0035     return recvMes.header()[QLatin1String("pending-message-id")].variant().toUInt(nullptr);
0036 }
0037 
0038 class OTRMessage : public Tp::ReceivedMessage
0039 {
0040     public:
0041         OTRMessage(const Tp::ReceivedMessage &recMes)
0042             : Tp::ReceivedMessage(recMes)
0043         {
0044         }
0045 
0046         OTRMessage(const Tp::MessagePartList &message, const Tp::TextChannelPtr channel)
0047             : Tp::ReceivedMessage(message, channel)
0048         {
0049             setSender(channel->targetContact());
0050         }
0051 
0052         bool hasId() const
0053         {
0054             return header().contains(QLatin1String("pending-message-id"));
0055         }
0056 
0057         int getId() const
0058         {
0059             return ::getId(*this);
0060         }
0061 
0062         void setId(int id)
0063         {
0064             header()[QLatin1String("pending-message-id")] = QDBusVariant(id);
0065         }
0066 
0067         void setSender(const Tp::ContactPtr &contact)
0068         {
0069             ReceivedMessage::setSender(contact);
0070         }
0071 };
0072 
0073 namespace KTp {
0074 
0075 struct ChannelAdapter::Private
0076 {
0077     Private()
0078         : otrConnected(false),
0079         trustLevel(KTp::OTRTrustLevelNotPrivate)
0080     {
0081     }
0082 
0083     Tp::TextChannelPtr textChannel;
0084     OTRProxyPtr otrProxy;
0085 
0086     bool otrConnected;
0087     KTp::OTRTrustLevel trustLevel;
0088     QString remoteFp;
0089 
0090     QMap<uint, OTRMessage> messages;
0091     QMap<uint, OTRMessage> otrEvents;
0092 };
0093 
0094 ChannelAdapter::ChannelAdapter(const Tp::TextChannelPtr &textChannel, QObject *parent)
0095     : QObject(parent),
0096     d(new Private())
0097 {
0098     setChannel(textChannel);
0099 }
0100 
0101 ChannelAdapter::~ChannelAdapter()
0102 {
0103     delete d;
0104 }
0105 
0106 bool ChannelAdapter::isValid() const
0107 {
0108     return d->textChannel->isValid();
0109 }
0110 
0111 void ChannelAdapter::setChannel(const Tp::TextChannelPtr &textChannel)
0112 {
0113     d->textChannel = textChannel;
0114     QDBusConnection dbusConnection = textChannel->dbusConnection();
0115     if(textChannel->targetHandleType() != Tp::HandleTypeContact ||
0116             !dbusConnection.interface()->isServiceRegistered(KTP_PROXY_BUS_NAME))
0117     {
0118         setupTextChannel();
0119         return;
0120     }
0121 
0122     QString otrProxyPath = KTp::Utils::getOtrProxyObjectPathFor(textChannel);
0123     d->otrProxy = OTRProxyPtr(new KTp::Client::ChannelProxyInterfaceOTRInterface(KTP_PROXY_BUS_NAME, otrProxyPath, this));
0124 
0125     if(!d->otrProxy->isValid()) {
0126         qCDebug(KTP_OTR) << "No OTR proxy available for channel: " << textChannel->objectPath();
0127         setupTextChannel();
0128         return;
0129     }
0130 
0131     qCDebug(KTP_OTR) << "Connecting to the OTR proxy: " << d->otrProxy->path();
0132     QDBusPendingReply<> connectResult = d->otrProxy->ConnectProxy();
0133     connectResult.waitForFinished();
0134     if(connectResult.isValid()) {
0135         setupOTRChannel();
0136     } else {
0137         qCWarning(KTP_OTR) << "Could not connect to the proxy" << connectResult.error().message();
0138         setupTextChannel();
0139     }
0140 }
0141 
0142 Tp::TextChannelPtr ChannelAdapter::textChannel()
0143 {
0144     return d->textChannel;
0145 }
0146 
0147 void ChannelAdapter::setupTextChannel()
0148 {
0149     connect(d->textChannel.data(), SIGNAL(messageReceived(Tp::ReceivedMessage)),
0150             SIGNAL(messageReceived(Tp::ReceivedMessage)));
0151     connect(d->textChannel.data(), SIGNAL(pendingMessageRemoved(Tp::ReceivedMessage)),
0152             SIGNAL(pendingMessageRemoved(Tp::ReceivedMessage)));
0153     connect(d->textChannel.data(), SIGNAL(messageSent(Tp::Message,Tp::MessageSendingFlags,QString)),
0154             SIGNAL(messageSent(Tp::Message,Tp::MessageSendingFlags,QString)));
0155 }
0156 
0157 void ChannelAdapter::setupOTRChannel()
0158 {
0159     d->otrConnected = true;
0160     d->trustLevel = KTp::OTRTrustLevelNotPrivate;
0161 
0162     connect(d->otrProxy.data(), SIGNAL(SessionRefreshed()), SIGNAL(sessionRefreshed()));
0163     connect(d->otrProxy.data(), SIGNAL(MessageReceived(const Tp::MessagePartList&)),
0164             SLOT(onMessageReceived(const Tp::MessagePartList&)));
0165     connect(d->otrProxy.data(), SIGNAL(PendingMessagesRemoved(const Tp::UIntList&)),
0166             SLOT(onPendingMessagesRemoved(const Tp::UIntList&)));
0167     connect(d->otrProxy.data(), SIGNAL(MessageSent(const Tp::MessagePartList&, uint, const QString&)),
0168             SLOT(onMessageSent(const Tp::MessagePartList&, uint, const QString&)));
0169     connect(d->otrProxy.data(), SIGNAL(TrustLevelChanged(uint)), SLOT(onTrustLevelChanged(uint)));
0170 
0171     // smp protocol
0172     connect(d->otrProxy.data(), SIGNAL(PeerAuthenticationRequested(const QString&)),
0173            SLOT(onPeerAuthenticationRequested(const QString&)));
0174     connect(d->otrProxy.data(), SIGNAL(PeerAuthenticationConcluded(bool)),
0175            SIGNAL(peerAuthenticationConcluded(bool)));
0176     connect(d->otrProxy.data(), SIGNAL(PeerAuthenticationInProgress()),
0177            SIGNAL(peerAuthenticationInProgress()));
0178     connect(d->otrProxy.data(), SIGNAL(PeerAuthenticationAborted()),
0179            SIGNAL(peerAuthenticationAborted()));
0180     connect(d->otrProxy.data(), SIGNAL(PeerAuthenticationError()),
0181            SIGNAL(peerAuthenticationError()));
0182     connect(d->otrProxy.data(), SIGNAL(PeerAuthenticationCheated()),
0183            SIGNAL(peerAuthenticationCheated()));
0184 
0185     // initialize message queue;
0186     connect(d->otrProxy->requestPropertyPendingMessages(), SIGNAL(finished(Tp::PendingOperation*)),
0187                 SLOT(onPendingMessagesPropertyGet(Tp::PendingOperation*)));
0188     // initialize trust level property
0189     connect(d->otrProxy->requestPropertyTrustLevel(), SIGNAL(finished(Tp::PendingOperation*)),
0190             SLOT(onTrustLevelPropertyGet(Tp::PendingOperation*)));
0191     // initialize remote fingerprint property
0192     connect(d->otrProxy->requestPropertyRemoteFingerprint(), SIGNAL(finished(Tp::PendingOperation*)),
0193             SLOT(onRemoteFingerprintPropertyGet(Tp::PendingOperation*)));
0194 }
0195 
0196 KTp::OTRTrustLevel ChannelAdapter::otrTrustLevel() const
0197 {
0198     return d->trustLevel;
0199 }
0200 
0201 void ChannelAdapter::onTrustLevelPropertyGet(Tp::PendingOperation *op)
0202 {
0203     if(op->isError()) {
0204         qCWarning(KTP_OTR) << "Could not get property: TrustLevel";
0205         return;
0206     }
0207     // we must have received trust level changed signal before
0208     if(d->trustLevel != KTp::OTRTrustLevelNotPrivate) {
0209         return;
0210     }
0211     Tp::PendingVariant *pv = dynamic_cast<Tp::PendingVariant*>(op);
0212     d->trustLevel = static_cast<KTp::OTRTrustLevel>(pv->result().toUInt(nullptr));
0213     Q_EMIT otrTrustLevelChanged(d->trustLevel, KTp::OTRTrustLevelNotPrivate);
0214 }
0215 
0216 bool ChannelAdapter::isOTRsuppored() const
0217 {
0218     return d->otrConnected;
0219 }
0220 
0221 void ChannelAdapter::initializeOTR()
0222 {
0223     qCDebug(KTP_OTR) << "Initializing OTR session";
0224     d->otrProxy->Initialize();
0225 }
0226 
0227 void ChannelAdapter::stopOTR()
0228 {
0229     d->otrProxy->Stop();
0230 }
0231 
0232 QString ChannelAdapter::remoteFingerprint() const
0233 {
0234     return d->remoteFp;
0235 }
0236 
0237 QDBusPendingReply<> ChannelAdapter::trustFingerprint(const QString &fingerprint, bool trust)
0238 {
0239     return d->otrProxy->TrustFingerprint(fingerprint, trust);
0240 }
0241 
0242 void ChannelAdapter::acknowledge(const QList<Tp::ReceivedMessage> &messages)
0243 {
0244     if(messages.isEmpty()) {
0245         return;
0246     }
0247 
0248     if(isOTRsuppored()) {
0249         QList<Tp::ReceivedMessage> toAck;
0250         QList<Tp::ReceivedMessage> eventsToRemove;
0251 
0252         Q_FOREACH(const Tp::ReceivedMessage &mes, messages) {
0253             if(KTp::Utils::isOtrEvent(mes)) {
0254                 d->otrEvents.remove(getId(mes));
0255                 eventsToRemove << mes;
0256             } else {
0257                 toAck << mes;
0258             }
0259         }
0260         d->otrProxy->AcknowledgePendingMessages(KTp::Utils::getPendingMessagesIDs(toAck));
0261         Q_FOREACH(const Tp::ReceivedMessage &mes, eventsToRemove) {
0262             Q_EMIT pendingMessageRemoved(mes);
0263         }
0264     } else {
0265         d->textChannel->acknowledge(messages);
0266     }
0267 }
0268 
0269 void ChannelAdapter::send(const QString& text, Tp::ChannelTextMessageType type, Tp::MessageSendingFlags flags)
0270 {
0271     if(isOTRsuppored()) {
0272         Tp::MessagePartList parts;
0273         parts << Tp::MessagePart() << Tp::MessagePart();
0274         parts[0].insert(QLatin1String("message-type"),
0275                 QDBusVariant(type));
0276         parts[1].insert(QLatin1String("content-type"),
0277                 QDBusVariant(QLatin1String("text/plain")));
0278         parts[1].insert(QLatin1String("content"), QDBusVariant(text));
0279 
0280         d->otrProxy->SendMessage(parts, (uint) flags);
0281     } else {
0282         d->textChannel->send(text, type, flags);
0283     }
0284 }
0285 
0286 bool ChannelAdapter::supportsMessageType(Tp::ChannelTextMessageType messageType) const
0287 {
0288     return d->textChannel->supportsMessageType(messageType);
0289 }
0290 
0291 QList<Tp::ChannelTextMessageType> ChannelAdapter::supportedMessageTypes() const
0292 {
0293     return d->textChannel->supportedMessageTypes();
0294 }
0295 
0296 QStringList ChannelAdapter::supportedContentTypes() const
0297 {
0298     return d->textChannel->supportedContentTypes();
0299 }
0300 
0301 Tp::MessagePartSupportFlags ChannelAdapter::messagePartSupport() const
0302 {
0303     return d->textChannel->messagePartSupport();
0304 }
0305 
0306 Tp::DeliveryReportingSupportFlags ChannelAdapter::deliveryReportingSupport() const
0307 {
0308     return d->textChannel->deliveryReportingSupport();
0309 }
0310 
0311 QList<Tp::ReceivedMessage> ChannelAdapter::messageQueue() const
0312 {
0313     if(isOTRsuppored()) {
0314         QList<Tp::ReceivedMessage> messages;
0315         Q_FOREACH(const Tp::ReceivedMessage &m, d->messages) {
0316             messages << m;
0317         }
0318         Q_FOREACH(const Tp::ReceivedMessage &m, d->otrEvents) {
0319             messages << m;
0320         }
0321         return messages;
0322     } else {
0323         return d->textChannel->messageQueue();
0324     }
0325 }
0326 
0327 void ChannelAdapter::onMessageReceived(const Tp::MessagePartList &message)
0328 {
0329     OTRMessage recvMes(message, d->textChannel);
0330     if(recvMes.hasId()) {
0331         const int id = recvMes.getId();
0332         if(!d->messages.contains(id)) {
0333             d->messages.insert(id, recvMes);
0334             Q_EMIT messageReceived(recvMes);
0335         } else {
0336             qCWarning(KTP_OTR) << "Message already in the queue. Id: " << id;
0337         }
0338     } else if (KTp::Utils::isOtrEvent(recvMes)) {
0339         const int id = d->otrEvents.size();
0340         recvMes.setId(d->otrEvents.size());
0341         d->otrEvents.insert(id, recvMes);
0342         Q_EMIT messageReceived(recvMes);
0343     } else {
0344         qCWarning(KTP_OTR) << "Message has not id and is not an OTR event either";
0345     }
0346 }
0347 
0348 void ChannelAdapter::onPendingMessagesPropertyGet(Tp::PendingOperation *op)
0349 {
0350     Tp::PendingVariant *variant = dynamic_cast<Tp::PendingVariant*>(op);
0351 
0352     if(!variant->isError()) {
0353         QDBusArgument dbusArgument = variant->result().value<QDBusArgument>();
0354         Tp::MessagePartListList pendingMessages;
0355         dbusArgument >> pendingMessages;
0356         Q_FOREACH(const Tp::MessagePartList &message, pendingMessages) {
0357             onMessageReceived(message);
0358         }
0359     } else {
0360         qCWarning(KTP_OTR) << "Could not initialize message queue: " << variant->errorName() << " - "
0361             << variant->errorMessage();
0362     }
0363 }
0364 
0365 void ChannelAdapter::onRemoteFingerprintPropertyGet(Tp::PendingOperation *op)
0366 {
0367     Tp::PendingVariant *variant = dynamic_cast<Tp::PendingVariant*>(op);
0368 
0369     if(!variant->isError()) {
0370         d->remoteFp = variant->result().toString();
0371     } else {
0372         qCWarning(KTP_OTR) << "Could not get remote fingerprint: " << variant->errorName() << " - "
0373             << variant->errorMessage();
0374     }
0375 }
0376 
0377 void ChannelAdapter::onPendingMessagesRemoved(const Tp::UIntList &messageIDs)
0378 {
0379     Q_FOREACH(uint id, messageIDs) {
0380         const QMap<uint, OTRMessage>::Iterator mIt = d->messages.find(id);
0381         if(mIt != d->messages.end()) {
0382             OTRMessage message = *mIt;
0383             d->messages.erase(mIt);
0384             Q_EMIT pendingMessageRemoved(message);
0385         } else {
0386             qCWarning(KTP_OTR) << "No message to remove with id: " << id;
0387         }
0388     }
0389 }
0390 
0391 void ChannelAdapter::onMessageSent(const Tp::MessagePartList &content, uint flags, const QString &messageToken)
0392 {
0393     OTRMessage message(content, d->textChannel);
0394     Q_EMIT messageSent(message, Tp::MessageSendingFlags(flags), messageToken);
0395 }
0396 
0397 void ChannelAdapter::onTrustLevelChanged(uint trustLevel)
0398 {
0399     KTp::OTRTrustLevel oldLevel = d->trustLevel;
0400     d->trustLevel = static_cast<KTp::OTRTrustLevel>(trustLevel);
0401     // get remote's fingerprint
0402     if(oldLevel == KTp::OTRTrustLevelNotPrivate) {
0403         connect(d->otrProxy->requestPropertyRemoteFingerprint(), SIGNAL(finished(Tp::PendingOperation*)),
0404                 SLOT(onRemoteFingerprintPropertyGet(Tp::PendingOperation*)));
0405     }
0406 
0407     // it may be a new session and the fingerprint has to be updated
0408     if(d->trustLevel == KTp::OTRTrustLevelPrivate || d->trustLevel == KTp::OTRTrustLevelUnverified) {
0409         connect(d->otrProxy->requestPropertyRemoteFingerprint(), SIGNAL(finished(Tp::PendingOperation*)),
0410                 SLOT(onRemoteFingerprintPropertyGet(Tp::PendingOperation*)));
0411     }
0412 
0413     Q_EMIT otrTrustLevelChanged(d->trustLevel, oldLevel);
0414 }
0415 
0416 void ChannelAdapter::onPeerAuthenticationRequested(const QString &question)
0417 {
0418     if(question.isEmpty()) {
0419         Q_EMIT peerAuthenticationRequestedSS();
0420     } else {
0421         Q_EMIT peerAuthenticationRequestedQA(question);
0422     }
0423 }
0424 
0425 void ChannelAdapter::startPeerAuthenticationQA(const QString &question, const QString &answer)
0426 {
0427     d->otrProxy->StartPeerAuthentication(question, answer);
0428 }
0429 
0430 void ChannelAdapter::startPeerAuthenticationSS(const QString &secret)
0431 {
0432     startPeerAuthenticationQA(QLatin1String(""), secret);
0433 }
0434 
0435 void ChannelAdapter::respondPeerAuthentication(const QString &secret)
0436 {
0437     d->otrProxy->RespondPeerAuthentication(secret);
0438 }
0439 
0440 void ChannelAdapter::abortPeerAuthentication()
0441 {
0442     d->otrProxy->AbortPeerAuthentication();
0443 }
0444 
0445 } /* namespace KTp */