File indexing completed on 2024-09-15 04:48:49
0001 /* 0002 * SPDX-FileCopyrightText: 2013 Alejandro Fiestas Fiestas <afiestas@kde.org> 0003 * SPDX-FileCopyrightText: 2014-2015 David Rosca <nowrep@gmail.com> 0004 * 0005 * SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "obexftp.h" 0009 #include "bluedevil_kded.h" 0010 #include "bluedevildaemon.h" 0011 0012 #include <QDBusConnection> 0013 #include <QDBusObjectPath> 0014 #include <QDBusPendingCallWatcher> 0015 #include <QDBusPendingReply> 0016 0017 #include <KLocalizedString> 0018 0019 #include <BluezQt/Device> 0020 #include <BluezQt/InitObexManagerJob> 0021 #include <BluezQt/ObexFileTransfer> 0022 #include <BluezQt/ObexManager> 0023 #include <BluezQt/ObexSession> 0024 #include <BluezQt/PendingCall> 0025 0026 ObexFtp::ObexFtp(BlueDevilDaemon *daemon) 0027 : QDBusAbstractAdaptor(daemon) 0028 , m_daemon(daemon) 0029 { 0030 connect(m_daemon->obexManager(), &BluezQt::ObexManager::sessionRemoved, this, &ObexFtp::sessionRemoved); 0031 } 0032 0033 bool ObexFtp::isOnline() 0034 { 0035 return m_daemon->obexManager()->isOperational(); 0036 } 0037 0038 QString ObexFtp::preferredTarget(const QString &address) 0039 { 0040 BluezQt::DevicePtr device = m_daemon->manager()->deviceForAddress(address); 0041 0042 // Prefer pcsuite target on S60 devices 0043 if (device && device->uuids().contains(QStringLiteral("00005005-0000-1000-8000-0002EE000001"))) { 0044 return QStringLiteral("pcsuite"); 0045 } 0046 return QStringLiteral("ftp"); 0047 } 0048 0049 QString ObexFtp::session(const QString &address, const QString &target, const QDBusMessage &msg) 0050 { 0051 if (!m_daemon->obexManager()->isOperational()) { 0052 return QString(); 0053 } 0054 0055 if (m_sessionMap.contains(address)) { 0056 return m_sessionMap[address]; 0057 } 0058 0059 qCDebug(BLUEDEVIL_KDED_LOG) << "Creating obexftp session for" << address; 0060 0061 // At this point we always want delayed reply 0062 msg.setDelayedReply(true); 0063 0064 if (m_pendingSessions.contains(address)) { 0065 m_pendingSessions[address].append(msg); 0066 return QString(); 0067 } 0068 0069 m_pendingSessions.insert(address, {msg}); 0070 0071 QVariantMap args; 0072 args[QStringLiteral("Target")] = target; 0073 0074 BluezQt::PendingCall *call = m_daemon->obexManager()->createSession(address, args); 0075 call->setUserData(address); 0076 connect(call, &BluezQt::PendingCall::finished, this, &ObexFtp::createSessionFinished); 0077 0078 return QString(); 0079 } 0080 0081 bool ObexFtp::cancelTransfer(const QString &transfer, const QDBusMessage &msg) 0082 { 0083 // We need this function because kio_obexftp is not owner of the transfer, 0084 // and thus cannot cancel it. 0085 0086 msg.setDelayedReply(true); 0087 0088 QDBusMessage call = QDBusMessage::createMethodCall(QStringLiteral("org.bluez.obex"), // 0089 transfer, 0090 QStringLiteral("org.bluez.obex.Transfer1"), 0091 QStringLiteral("Cancel")); 0092 0093 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(QDBusConnection::sessionBus().asyncCall(call)); 0094 watcher->setProperty("ObexFtpDaemon-msg", QVariant::fromValue(msg)); 0095 connect(watcher, &QDBusPendingCallWatcher::finished, this, &ObexFtp::cancelTransferFinished); 0096 0097 return false; 0098 } 0099 0100 void ObexFtp::createSessionFinished(BluezQt::PendingCall *call) 0101 { 0102 QString path; 0103 0104 if (call->error() == BluezQt::PendingCall::AlreadyExists) { 0105 // It may happen when kded crashes, or the session was created by different app 0106 // What to do here? We are not owners of the session... 0107 qCWarning(BLUEDEVIL_KDED_LOG) << "Obex session already exists but it was created by different process!"; 0108 } else if (call->error()) { 0109 qCWarning(BLUEDEVIL_KDED_LOG) << "Error creating Obex session" << call->errorText(); 0110 } else { 0111 path = call->value().value<QDBusObjectPath>().path(); 0112 qCDebug(BLUEDEVIL_KDED_LOG) << "Created Obex session" << path; 0113 } 0114 0115 const QString &address = call->userData().toString(); 0116 0117 // Send reply (empty session path in case of error) 0118 Q_FOREACH (const QDBusMessage &msg, m_pendingSessions[address]) { 0119 QDBusMessage reply = msg.createReply(path); 0120 QDBusConnection::sessionBus().send(reply); 0121 } 0122 0123 m_pendingSessions.remove(address); 0124 0125 if (!call->error()) { 0126 m_sessionMap.insert(address, path); 0127 } 0128 } 0129 0130 void ObexFtp::cancelTransferFinished(QDBusPendingCallWatcher *watcher) 0131 { 0132 const QDBusPendingReply<> &reply = *watcher; 0133 QDBusMessage msg = watcher->property("ObexFtpDaemon-msg").value<QDBusMessage>(); 0134 0135 bool success = !reply.isError(); 0136 QDBusConnection::sessionBus().send(msg.createReply(QVariant(success))); 0137 } 0138 0139 void ObexFtp::sessionRemoved(BluezQt::ObexSessionPtr session) 0140 { 0141 const QString &path = session->objectPath().path(); 0142 const QString &key = m_sessionMap.key(path); 0143 0144 if (!m_sessionMap.contains(key)) { 0145 qCDebug(BLUEDEVIL_KDED_LOG) << "Removed Obex session is not ours" << path; 0146 return; 0147 } 0148 0149 qCDebug(BLUEDEVIL_KDED_LOG) << "Removed Obex session" << path; 0150 m_sessionMap.remove(key); 0151 } 0152 0153 #include "moc_obexftp.cpp"