kiobluetooth.cpp 7.79 KB
Newer Older
1
2
3
4
5
6
7
8
/*
 *  SPDX-FileCopyrightText: 2010-2012 Alejandro Fiestas Olivares <afiestas@kde.org>
 *  SPDX-FileCopyrightText: 2010 Eduardo Robles Elvira <edulix@gmail.com>
 *  SPDX-FileCopyrightText: 2010 Rafael Fernández López <ereslibre@kde.org>
 *  SPDX-FileCopyrightText: 2010 UFO Coders <info@ufocoders.com>
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 */
9
10

#include "kiobluetooth.h"
11
#include "filereceiversettings.h"
Alexander Lohnau's avatar
Alexander Lohnau committed
12
#include "version.h"
13

14
#include <QCoreApplication>
15
#include <QDBusMetaType>
Alexander Lohnau's avatar
Alexander Lohnau committed
16
#include <QThread>
17

18
#include <KLocalizedString>
19

David Rosca's avatar
David Rosca committed
20
21
#include <BluezQt/Services>

22
extern "C" int Q_DECL_EXPORT kdemain(int argc, char **argv)
23
{
24
    QCoreApplication app(argc, argv);
25
26
27
28
29
30
31
32
33
34
35

    if (argc != 4) {
        fprintf(stderr, "Usage: kio_bluetooth protocol domain-socket1 domain-socket2\n");
        exit(-1);
    }

    KioBluetooth slave(argv[2], argv[3]);
    slave.dispatchLoop();
    return 0;
}

36
KioBluetooth::KioBluetooth(const QByteArray &pool, const QByteArray &app)
37
    : SlaveBase(QByteArrayLiteral("bluetooth"), pool, app)
38
{
39
40
    qDBusRegisterMetaType<DeviceInfo>();
    qDBusRegisterMetaType<QMapDeviceInfo>();
41
42
43

    m_hasCurrentHost = false;

David Rosca's avatar
David Rosca committed
44
45
46
47
48
49
50
51
52
53
54
    Service sendFile;
    sendFile.name = i18n("Send File");
    sendFile.icon = QStringLiteral("edit-copy");
    sendFile.mimetype = QStringLiteral("application/vnd.kde.bluedevil-sendfile");
    sendFile.uuid = BluezQt::Services::ObexObjectPush;

    Service browseFiles;
    browseFiles.name = i18n("Browse Files");
    browseFiles.icon = QStringLiteral("edit-find");
    browseFiles.mimetype = QString();
    browseFiles.uuid = BluezQt::Services::ObexFileTransfer;
55

David Rosca's avatar
David Rosca committed
56
57
    m_supportedServices.insert(sendFile.uuid, sendFile);
    m_supportedServices.insert(browseFiles.uuid, browseFiles);
58

59
    qCDebug(BLUETOOTH) << "Kio Bluetooth instanced!";
60

Alexander Lohnau's avatar
Alexander Lohnau committed
61
    m_kded = new org::kde::BlueDevil(QStringLiteral("org.kde.kded5"), QStringLiteral("/modules/bluedevil"), QDBusConnection::sessionBus());
62

63
    if (!m_kded->isOnline()) {
David Rosca's avatar
David Rosca committed
64
        qCDebug(BLUETOOTH) << "Bluetooth is offline";
65
        infoMessage(i18n("No Bluetooth adapters have been found."));
David Rosca's avatar
David Rosca committed
66
        return;
67
68
69
    }
}

70
QList<KioBluetooth::Service> KioBluetooth::getSupportedServices(const QStringList &uuids)
Rafael Fernández López's avatar
Rafael Fernández López committed
71
{
72
    qCDebug(BLUETOOTH) << "supported services: " << uuids;
73

Rafael Fernández López's avatar
Rafael Fernández López committed
74
75
    QList<Service> retValue;
    Q_FOREACH (const QString &uuid, uuids) {
76
77
        if (m_supportedServices.contains(uuid)) {
            retValue << m_supportedServices[uuid];
Rafael Fernández López's avatar
Rafael Fernández López committed
78
79
80
81
82
        }
    }
    return retValue;
}

83
void KioBluetooth::listRemoteDeviceServices()
84
{
85
    infoMessage(i18n("Retrieving services..."));
86

87
    qCDebug(BLUETOOTH) << "Listing remote devices";
88
89
90

    const DeviceInfo &info = m_kded->device(m_currentHostAddress).value();
    if (info.isEmpty()) {
David Rosca's avatar
David Rosca committed
91
        qCDebug(BLUETOOTH) << "Invalid hostname!";
92
93
94
95
96
        infoMessage(i18n("This address is unavailable."));
        finished();
        return;
    }

97
    const QList<Service> &services = getSupportedServices(info.value(QStringLiteral("UUIDs")).split(QLatin1Char(',')));
98

99
    qCDebug(BLUETOOTH) << "Num of supported services: " << services.size();
100

101
    int i = 1;
102
103
104
    totalSize(services.count());

    Q_FOREACH (const Service &service, services) {
105
        KIO::UDSEntry entry;
106
107
108
109
        entry.fastInsert(KIO::UDSEntry::UDS_NAME, service.uuid);
        entry.fastInsert(KIO::UDSEntry::UDS_DISPLAY_NAME, service.name);
        entry.fastInsert(KIO::UDSEntry::UDS_ICON_NAME, service.icon);
        entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, S_IRUSR | S_IRGRP | S_IROTH);
110

111
        // If it is browse files, act as a folder
David Rosca's avatar
David Rosca committed
112
        if (service.uuid == BluezQt::Services::ObexFileTransfer) {
David Rosca's avatar
David Rosca committed
113
            QUrl obexUrl;
114
115
            obexUrl.setScheme(QStringLiteral("obexftp"));
            obexUrl.setHost(m_currentHostname.replace(QLatin1Char(':'), QLatin1Char('-')).toUpper());
116
117
            entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR);
            entry.fastInsert(KIO::UDSEntry::UDS_URL, obexUrl.toString());
118
        } else {
119
            entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFREG);
120
121
        }

Alex Fiestas's avatar
Alex Fiestas committed
122
        if (service.mimetype.isEmpty()) {
123
            entry.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, QStringLiteral("inode/vnd.kde.bluedevil.service"));
Alex Fiestas's avatar
Alex Fiestas committed
124
        } else {
125
            entry.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, service.mimetype);
126
        }
127

128
        listEntry(entry);
129
        processedSize(i++);
130
131
    }

132
    infoMessage(QString());
133
    finished();
134
135
}

136
137
138
139
void KioBluetooth::listDownload()
{
    KIO::UDSEntry entry;
    entry.clear();
140
141
142
143
144
145
    entry.fastInsert(KIO::UDSEntry::UDS_URL, FileReceiverSettings::saveUrl().toDisplayString());
    entry.fastInsert(KIO::UDSEntry::UDS_NAME, i18n("Received Files"));
    entry.fastInsert(KIO::UDSEntry::UDS_ICON_NAME, QStringLiteral("folder-downloads"));
    entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR);
    entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, S_IRUSR | S_IRGRP | S_IROTH);
    entry.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, QStringLiteral("inode/directory"));
146
147
148
    listEntry(entry);
}

149
void KioBluetooth::listDevices()
150
{
151
    qCDebug(BLUETOOTH) << "Asking kded for devices";
David Rosca's avatar
David Rosca committed
152
    const QMapDeviceInfo &devices = m_kded->allDevices().value();
153
    qCDebug(BLUETOOTH) << devices.keys();
154

Alexander Lohnau's avatar
Alexander Lohnau committed
155
    Q_FOREACH (const DeviceInfo &device, devices) {
156
        listDevice(device);
157
    }
158
159
160

    m_kded->startDiscovering(10 * 1000);

161
    infoMessage(i18n("Scanning for new devices..."));
162
    finished();
163
164
}

165
void KioBluetooth::listDevice(const DeviceInfo device)
166
{
167
168
    qCDebug(BLUETOOTH) << device;
    if (getSupportedServices(device[QStringLiteral("UUIDs")].split(QStringLiteral(","))).isEmpty()) {
169
170
        return;
    }
171
    QString target = QStringLiteral("bluetooth://");
172
    target.append(QString(device[QStringLiteral("address")]).replace(QLatin1Char(':'), QLatin1Char('-')) + QLatin1Char('/'));
173

174
    KIO::UDSEntry entry;
175
176
177
178
179
180
    entry.fastInsert(KIO::UDSEntry::UDS_URL, target);
    entry.fastInsert(KIO::UDSEntry::UDS_NAME, device[QStringLiteral("name")]);
    entry.fastInsert(KIO::UDSEntry::UDS_ICON_NAME, device[QStringLiteral("icon")]);
    entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR);
    entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, S_IRUSR | S_IRGRP | S_IROTH);
    entry.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, QStringLiteral("inode/vnd.kde.bluedevil.device"));
181
    listEntry(entry);
182
183
}

David Rosca's avatar
David Rosca committed
184
void KioBluetooth::listDir(const QUrl &url)
185
{
186
    qCDebug(BLUETOOTH) << "Listing..." << url;
187

David Rosca's avatar
David Rosca committed
188
    // Url is not used here because all we could care about the url is the host, and that's already
189
    // handled in @p setHost
190
191
192
    Q_UNUSED(url);

    // If we are not online (ie. there's no working bluetooth adapter), list an empty dir
193
    qCDebug(BLUETOOTH) << m_kded->isOnline().value();
194
    if (!m_kded->isOnline().value()) {
Pino Toscano's avatar
Pino Toscano committed
195
        infoMessage(i18n("No Bluetooth adapters have been found."));
196
197
198
199
        finished();
        return;
    }

200
    if (!m_hasCurrentHost) {
201
        listDownload();
202
        listDevices();
203
    } else {
204
        listRemoteDeviceServices();
205
206
207
    }
}

David Rosca's avatar
David Rosca committed
208
void KioBluetooth::stat(const QUrl &url)
209
{
210
    qCDebug(BLUETOOTH) << "Stat: " << url;
211
    finished();
212
213
}

David Rosca's avatar
David Rosca committed
214
void KioBluetooth::get(const QUrl &url)
215
{
216
    m_kded->stopDiscovering();
217
218
    qCDebug(BLUETOOTH) << "Get: " << url;
    qCDebug(BLUETOOTH) << m_supportedServices.value(url.fileName()).mimetype;
219
    mimeType(m_supportedServices.value(url.fileName()).mimetype);
220
221
222
    finished();
}

223
void KioBluetooth::setHost(const QString &hostname, quint16 port, const QString &user, const QString &pass)
224
{
David Rosca's avatar
David Rosca committed
225
    qCDebug(BLUETOOTH) << "Setting host: " << hostname;
226

227
228
229
230
231
232
    // In this kio only the hostname (constHostname) is used
    Q_UNUSED(port)
    Q_UNUSED(user)
    Q_UNUSED(pass)

    if (hostname.isEmpty()) {
233
        m_hasCurrentHost = false;
234
    } else {
235
        m_hasCurrentHost = true;
236
237
238
239

        m_currentHostname = hostname;
        m_currentHostAddress = hostname.toUpper();
        m_currentHostAddress.replace(QLatin1Char('-'), QLatin1Char(':'));
240
241
242
    }
}

David Rosca's avatar
David Rosca committed
243
Q_LOGGING_CATEGORY(BLUETOOTH, "bluedevil.kio_bluetooth")