File indexing completed on 2024-04-28 05:26:13
0001 /* 0002 * SPDX-FileCopyrightText: 2010-2012 Alejandro Fiestas Olivares <afiestas@kde.org> 0003 * SPDX-FileCopyrightText: 2010 Eduardo Robles Elvira <edulix@gmail.com> 0004 * SPDX-FileCopyrightText: 2010 Rafael Fernández López <ereslibre@kde.org> 0005 * SPDX-FileCopyrightText: 2010 UFO Coders <info@ufocoders.com> 0006 * 0007 * SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 #include "kiobluetooth.h" 0011 #include "filereceiversettings.h" 0012 #include "version.h" 0013 0014 #include <QCoreApplication> 0015 #include <QDBusMetaType> 0016 #include <QThread> 0017 0018 #include <KLocalizedString> 0019 0020 #include <BluezQt/Services> 0021 0022 // Pseudo plugin class to embed meta data 0023 class KIOPluginForMetaData : public QObject 0024 { 0025 Q_OBJECT 0026 Q_PLUGIN_METADATA(IID "org.kde.kio.worker.bluetooth" FILE "bluetooth.json") 0027 }; 0028 0029 extern "C" int Q_DECL_EXPORT kdemain(int argc, char **argv) 0030 { 0031 QCoreApplication app(argc, argv); 0032 0033 if (argc != 4) { 0034 fprintf(stderr, "Usage: kio_bluetooth protocol domain-socket1 domain-socket2\n"); 0035 exit(-1); 0036 } 0037 0038 KioBluetooth worker(argv[2], argv[3]); 0039 worker.dispatchLoop(); 0040 return 0; 0041 } 0042 0043 KioBluetooth::KioBluetooth(const QByteArray &pool, const QByteArray &app) 0044 : KIO::WorkerBase(QByteArrayLiteral("bluetooth"), pool, app) 0045 { 0046 qDBusRegisterMetaType<DeviceInfo>(); 0047 qDBusRegisterMetaType<QMapDeviceInfo>(); 0048 0049 m_hasCurrentHost = false; 0050 0051 Service sendFile; 0052 sendFile.name = i18n("Send File"); 0053 sendFile.icon = QStringLiteral("edit-copy"); 0054 sendFile.mimetype = QStringLiteral("application/vnd.kde.bluedevil-sendfile"); 0055 sendFile.uuid = BluezQt::Services::ObexObjectPush; 0056 0057 Service browseFiles; 0058 browseFiles.name = i18n("Browse Files"); 0059 browseFiles.icon = QStringLiteral("edit-find"); 0060 browseFiles.mimetype = QString(); 0061 browseFiles.uuid = BluezQt::Services::ObexFileTransfer; 0062 0063 m_supportedServices.insert(sendFile.uuid, sendFile); 0064 m_supportedServices.insert(browseFiles.uuid, browseFiles); 0065 0066 qCDebug(BLUETOOTH) << "Kio Bluetooth instanced!"; 0067 0068 m_kded = new org::kde::BlueDevil(QStringLiteral("org.kde.kded6"), QStringLiteral("/modules/bluedevil"), QDBusConnection::sessionBus()); 0069 0070 if (!m_kded->isOnline()) { 0071 qCDebug(BLUETOOTH) << "Bluetooth is offline"; 0072 infoMessage(i18n("No Bluetooth adapters have been found.")); 0073 return; 0074 } 0075 } 0076 0077 QList<KioBluetooth::Service> KioBluetooth::getSupportedServices(const QStringList &uuids) 0078 { 0079 qCDebug(BLUETOOTH) << "supported services: " << uuids; 0080 0081 QList<Service> retValue; 0082 for (const QString &uuid : uuids) { 0083 if (m_supportedServices.contains(uuid)) { 0084 retValue << m_supportedServices[uuid]; 0085 } 0086 } 0087 return retValue; 0088 } 0089 0090 KIO::WorkerResult KioBluetooth::listRemoteDeviceServices() 0091 { 0092 infoMessage(i18n("Retrieving services…")); 0093 0094 qCDebug(BLUETOOTH) << "Listing remote devices"; 0095 0096 const DeviceInfo &info = m_kded->device(m_currentHostAddress).value(); 0097 if (info.isEmpty()) { 0098 qCDebug(BLUETOOTH) << "Invalid hostname!"; 0099 infoMessage(i18n("This address is unavailable.")); 0100 return KIO::WorkerResult::pass(); 0101 } 0102 0103 const QList<Service> &services = getSupportedServices(info.value(QStringLiteral("UUIDs")).split(QLatin1Char(','))); 0104 0105 qCDebug(BLUETOOTH) << "Num of supported services: " << services.size(); 0106 0107 int i = 1; 0108 totalSize(services.count()); 0109 0110 for (const Service &service : services) { 0111 KIO::UDSEntry entry; 0112 entry.fastInsert(KIO::UDSEntry::UDS_NAME, service.uuid); 0113 entry.fastInsert(KIO::UDSEntry::UDS_DISPLAY_NAME, service.name); 0114 entry.fastInsert(KIO::UDSEntry::UDS_ICON_NAME, service.icon); 0115 entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, S_IRUSR | S_IRGRP | S_IROTH); 0116 0117 // If it is browse files, act as a folder 0118 if (service.uuid == BluezQt::Services::ObexFileTransfer) { 0119 QUrl obexUrl; 0120 obexUrl.setScheme(QStringLiteral("obexftp")); 0121 obexUrl.setHost(m_currentHostname.replace(QLatin1Char(':'), QLatin1Char('-')).toUpper()); 0122 entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); 0123 entry.fastInsert(KIO::UDSEntry::UDS_URL, obexUrl.toString()); 0124 } else { 0125 entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFREG); 0126 } 0127 0128 if (service.mimetype.isEmpty()) { 0129 entry.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, QStringLiteral("inode/vnd.kde.bluedevil.service")); 0130 } else { 0131 entry.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, service.mimetype); 0132 } 0133 0134 listEntry(entry); 0135 processedSize(i++); 0136 } 0137 0138 infoMessage(QString()); 0139 return KIO::WorkerResult::pass(); 0140 } 0141 0142 void KioBluetooth::listDownload() 0143 { 0144 KIO::UDSEntry entry; 0145 entry.clear(); 0146 entry.fastInsert(KIO::UDSEntry::UDS_URL, FileReceiverSettings::saveUrl().toDisplayString()); 0147 entry.fastInsert(KIO::UDSEntry::UDS_NAME, i18n("Received Files")); 0148 entry.fastInsert(KIO::UDSEntry::UDS_ICON_NAME, QStringLiteral("folder-downloads")); 0149 entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); 0150 entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, S_IRUSR | S_IRGRP | S_IROTH); 0151 entry.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, QStringLiteral("inode/directory")); 0152 listEntry(entry); 0153 } 0154 0155 void KioBluetooth::listDevices() 0156 { 0157 qCDebug(BLUETOOTH) << "Asking kded for devices"; 0158 const QMapDeviceInfo &devices = m_kded->allDevices().value(); 0159 qCDebug(BLUETOOTH) << devices.keys(); 0160 0161 for (const DeviceInfo &device : devices) { 0162 listDevice(device); 0163 } 0164 0165 m_kded->startDiscovering(10 * 1000); 0166 0167 infoMessage(i18n("Scanning for new devices…")); 0168 } 0169 0170 void KioBluetooth::listDevice(const DeviceInfo device) 0171 { 0172 qCDebug(BLUETOOTH) << device; 0173 if (getSupportedServices(device[QStringLiteral("UUIDs")].split(QStringLiteral(","))).isEmpty()) { 0174 return; 0175 } 0176 QString target = QStringLiteral("bluetooth://"); 0177 target.append(QString(device[QStringLiteral("address")]).replace(QLatin1Char(':'), QLatin1Char('-')) + QLatin1Char('/')); 0178 0179 KIO::UDSEntry entry; 0180 entry.fastInsert(KIO::UDSEntry::UDS_URL, target); 0181 entry.fastInsert(KIO::UDSEntry::UDS_NAME, device[QStringLiteral("name")]); 0182 entry.fastInsert(KIO::UDSEntry::UDS_ICON_NAME, device[QStringLiteral("icon")]); 0183 entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); 0184 entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, S_IRUSR | S_IRGRP | S_IROTH); 0185 entry.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, QStringLiteral("inode/vnd.kde.bluedevil.device")); 0186 listEntry(entry); 0187 } 0188 0189 KIO::WorkerResult KioBluetooth::listDir(const QUrl &url) 0190 { 0191 qCDebug(BLUETOOTH) << "Listing..." << url; 0192 0193 // Url is not used here because all we could care about the url is the host, and that's already 0194 // handled in @p setHost 0195 Q_UNUSED(url); 0196 0197 // If we are not online (ie. there's no working bluetooth adapter), list an empty dir 0198 qCDebug(BLUETOOTH) << m_kded->isOnline().value(); 0199 if (!m_kded->isOnline().value()) { 0200 infoMessage(i18n("No Bluetooth adapters have been found.")); 0201 return KIO::WorkerResult::pass(); 0202 } 0203 0204 if (!m_hasCurrentHost) { 0205 listDownload(); 0206 listDevices(); 0207 return KIO::WorkerResult::pass(); 0208 } else { 0209 return listRemoteDeviceServices(); 0210 } 0211 } 0212 0213 KIO::WorkerResult KioBluetooth::stat(const QUrl &url) 0214 { 0215 qCDebug(BLUETOOTH) << "Stat: " << url; 0216 return KIO::WorkerResult::pass(); 0217 } 0218 0219 KIO::WorkerResult KioBluetooth::get(const QUrl &url) 0220 { 0221 m_kded->stopDiscovering(); 0222 qCDebug(BLUETOOTH) << "Get: " << url; 0223 qCDebug(BLUETOOTH) << m_supportedServices.value(url.fileName()).mimetype; 0224 mimeType(m_supportedServices.value(url.fileName()).mimetype); 0225 return KIO::WorkerResult::pass(); 0226 } 0227 0228 void KioBluetooth::setHost(const QString &hostname, quint16 port, const QString &user, const QString &pass) 0229 { 0230 qCDebug(BLUETOOTH) << "Setting host: " << hostname; 0231 0232 // In this kio only the hostname (constHostname) is used 0233 Q_UNUSED(port) 0234 Q_UNUSED(user) 0235 Q_UNUSED(pass) 0236 0237 if (hostname.isEmpty()) { 0238 m_hasCurrentHost = false; 0239 } else { 0240 m_hasCurrentHost = true; 0241 0242 m_currentHostname = hostname; 0243 m_currentHostAddress = hostname.toUpper(); 0244 m_currentHostAddress.replace(QLatin1Char('-'), QLatin1Char(':')); 0245 } 0246 } 0247 0248 Q_LOGGING_CATEGORY(BLUETOOTH, "bluedevil.kio_bluetooth") 0249 0250 #include "kiobluetooth.moc" 0251 0252 #include "moc_kiobluetooth.cpp"