kdeconnect-kde/kio/kiokdeconnect.cpp

285 lines
8.7 KiB
C++
Raw Normal View History

/**
* Copyright 2013 Albert Vaca <albertvaka@gmail.com>
*
* 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
2019-03-23 16:29:26 +00:00
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "kiokdeconnect.h"
2018-10-07 19:23:20 +01:00
#include <QThread>
#include <QDBusMetaType>
2014-09-23 13:26:56 +01:00
#include <KLocalizedString>
#include <QDebug>
#include <QtPlugin>
Q_LOGGING_CATEGORY(KDECONNECT_KIO, "kdeconnect.kio")
class KIOPluginForMetaData : public QObject
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.kde.kio.slave.kdeconnect" FILE "kdeconnect.json")
};
extern "C" int Q_DECL_EXPORT kdemain(int argc, char** argv)
{
QCoreApplication app(argc, argv);
app.setApplicationName(QStringLiteral("kio_kdeconnect"));
2019-07-17 22:37:19 +01:00
if (argc != 4) {
fprintf(stderr, "Usage: kio_kdeconnect protocol pool app\n");
exit(-1);
}
KioKdeconnect slave(argv[2], argv[3]);
slave.dispatchLoop();
return 0;
}
2014-01-21 13:06:51 +00:00
//Some useful error mapping
KIO::Error toKioError(const QDBusError::ErrorType type)
{
2019-07-17 22:37:19 +01:00
switch (type)
2014-01-21 13:06:51 +00:00
{
case QDBusError::NoError:
return KIO::Error(KJob::NoError);
case QDBusError::NoMemory:
return KIO::ERR_OUT_OF_MEMORY;
2019-07-17 22:37:19 +01:00
case QDBusError::Timeout:
2014-01-21 13:06:51 +00:00
return KIO::ERR_SERVER_TIMEOUT;
2019-07-17 22:37:19 +01:00
case QDBusError::TimedOut:
2014-01-21 13:06:51 +00:00
return KIO::ERR_SERVER_TIMEOUT;
default:
2019-03-09 15:27:49 +00:00
return KIO::ERR_SLAVE_DEFINED;
2014-01-21 13:06:51 +00:00
};
};
template <typename T>
bool handleDBusError(QDBusReply<T>& reply, KIO::SlaveBase* slave)
{
if (!reply.isValid())
{
qCDebug(KDECONNECT_KIO) << "Error in DBus request:" << reply.error();
2014-01-21 13:06:51 +00:00
slave->error(toKioError(reply.error().type()),reply.error().message());
return true;
}
return false;
}
KioKdeconnect::KioKdeconnect(const QByteArray& pool, const QByteArray& app)
: SlaveBase("kdeconnect", pool, app),
m_dbusInterface(new DaemonDbusInterface(this))
{
}
void KioKdeconnect::listAllDevices()
{
infoMessage(i18n("Listing devices..."));
2014-10-10 19:47:35 +01:00
//TODO: Change to all devices and show different icons for connected and disconnected?
const QStringList devices = m_dbusInterface->devices(true, true);
for (const QString& deviceId : devices) {
DeviceDbusInterface interface(deviceId);
if (!interface.hasPlugin(QStringLiteral("kdeconnect_sftp"))) continue;
const QString path = QStringLiteral("kdeconnect://").append(deviceId).append(QStringLiteral("/"));
const QString name = interface.name();
const QString icon = QStringLiteral("kdeconnect");
KIO::UDSEntry entry;
2019-05-08 22:29:11 +01:00
entry.reserve(6);
2019-07-17 22:37:19 +01:00
entry.fastInsert(KIO::UDSEntry::UDS_NAME, name);
entry.fastInsert(KIO::UDSEntry::UDS_ICON_NAME, icon);
entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, QT_STAT_DIR);
entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, QFileDevice::ReadOwner | QFileDevice::ExeOwner
| QFileDevice::ReadGroup | QFileDevice::ExeGroup
| QFileDevice::ReadOther | QFileDevice::ExeOther);
2019-07-17 22:37:19 +01:00
entry.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, QLatin1String(""));
entry.fastInsert(KIO::UDSEntry::UDS_URL, path);
2014-09-23 13:26:56 +01:00
listEntry(entry);
}
// We also need a non-null and writable UDSentry for "."
KIO::UDSEntry entry;
2019-05-08 22:29:11 +01:00
entry.reserve(4);
2019-07-17 22:37:19 +01:00
entry.fastInsert(KIO::UDSEntry::UDS_NAME, QStringLiteral("."));
entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, QT_STAT_DIR);
2019-07-17 22:37:19 +01:00
entry.fastInsert(KIO::UDSEntry::UDS_SIZE, 0);
entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, QFileDevice::ReadOwner | QFileDevice::WriteOwner
| QFileDevice::ExeOwner | QFileDevice::ReadGroup | QFileDevice::WriteGroup
| QFileDevice::ExeGroup | QFileDevice::ReadOther | QFileDevice::ExeOther);
listEntry(entry);
infoMessage(QLatin1String(""));
finished();
}
2019-03-09 14:52:29 +00:00
void KioKdeconnect::listDevice(const QString& device)
{
infoMessage(i18n("Accessing device..."));
2019-03-09 14:52:29 +00:00
qCDebug(KDECONNECT_KIO) << "ListDevice" << device;
2019-03-09 14:52:29 +00:00
SftpDbusInterface interface(device);
2015-07-31 10:39:58 +01:00
2014-01-21 13:06:51 +00:00
QDBusReply<bool> mountreply = interface.mountAndWait();
2015-07-31 10:39:58 +01:00
if (mountreply.error().type() == QDBusError::UnknownObject) {
DaemonDbusInterface daemon;
auto devsRepl = daemon.devices(false, false);
devsRepl.waitForFinished();
if (!devsRepl.value().contains(device)) {
error(KIO::ERR_SLAVE_DEFINED, i18n("No such device: %0").arg(device));
return;
}
DeviceDbusInterface dev(device);
if (!dev.isTrusted()) {
error(KIO::ERR_SLAVE_DEFINED, i18n("%0 is not paired").arg(dev.name()));
return;
}
if (!dev.isReachable()) {
error(KIO::ERR_SLAVE_DEFINED, i18n("%0 is not connected").arg(dev.name()));
return;
}
if (!dev.hasPlugin(QStringLiteral("kdeconnect_sftp"))) {
2019-03-13 00:33:51 +00:00
error(KIO::ERR_SLAVE_DEFINED, i18n("%0 has no Remote Filesystem plugin").arg(dev.name()));
return;
}
}
if (handleDBusError(mountreply, this)) {
2014-01-21 13:06:51 +00:00
return;
}
2015-07-31 10:39:58 +01:00
if (!mountreply.value()) {
2019-03-09 15:27:49 +00:00
error(KIO::ERR_SLAVE_DEFINED, interface.getMountError());
2014-01-21 13:06:51 +00:00
return;
}
2015-07-31 10:39:58 +01:00
QDBusReply< QVariantMap > urlreply = interface.getDirectories();
2015-07-31 10:39:58 +01:00
if (handleDBusError(urlreply, this)) {
2014-01-21 13:06:51 +00:00
return;
}
2015-07-31 10:39:58 +01:00
QVariantMap urls = urlreply.value();
2015-07-31 10:39:58 +01:00
for (QVariantMap::iterator it = urls.begin(); it != urls.end(); ++it) {
const QString path = it.key();
const QString name = it.value().toString();
const QString icon = QStringLiteral("folder");
KIO::UDSEntry entry;
2019-05-08 22:29:11 +01:00
entry.reserve(6);
2019-07-17 22:37:19 +01:00
entry.fastInsert(KIO::UDSEntry::UDS_NAME, name);
entry.fastInsert(KIO::UDSEntry::UDS_ICON_NAME, icon);
entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, QT_STAT_DIR);
entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, QFileDevice::ReadOwner | QFileDevice::ExeOwner
| QFileDevice::ReadGroup | QFileDevice::ExeGroup
| QFileDevice::ReadOther | QFileDevice::ExeOther);
2019-07-17 22:37:19 +01:00
entry.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, QLatin1String(""));
entry.fastInsert(KIO::UDSEntry::UDS_URL, QUrl::fromLocalFile(path).toString());
2015-02-24 06:07:28 +00:00
listEntry(entry);
}
// We also need a non-null and writable UDSentry for "."
KIO::UDSEntry entry;
2019-05-08 22:29:11 +01:00
entry.reserve(4);
2019-07-17 22:37:19 +01:00
entry.fastInsert(KIO::UDSEntry::UDS_NAME, QStringLiteral("."));
entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, QT_STAT_DIR);
2019-07-17 22:37:19 +01:00
entry.fastInsert(KIO::UDSEntry::UDS_SIZE, 0);
entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, QFileDevice::ReadOwner | QFileDevice::WriteOwner
| QFileDevice::ExeOwner | QFileDevice::ReadGroup | QFileDevice::WriteGroup
| QFileDevice::ExeGroup | QFileDevice::ReadOther | QFileDevice::ExeOther);
listEntry(entry);
infoMessage(QLatin1String(""));
finished();
}
void KioKdeconnect::listDir(const QUrl& url)
{
qCDebug(KDECONNECT_KIO) << "Listing..." << url;
if (!m_dbusInterface->isValid()) {
infoMessage(i18n("Could not contact background service."));
finished();
return;
}
2019-03-09 14:52:29 +00:00
QString currentDevice = url.host();
if (currentDevice.isEmpty()) {
listAllDevices();
} else {
2019-03-09 14:52:29 +00:00
listDevice(currentDevice);
}
}
void KioKdeconnect::stat(const QUrl& url)
{
qCDebug(KDECONNECT_KIO) << "Stat: " << url;
KIO::UDSEntry entry;
entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, QT_STAT_DIR);
QString currentDevice = url.host();
if (!currentDevice.isEmpty()) {
SftpDbusInterface interface(currentDevice);
if (interface.isValid()) {
2019-07-17 22:37:19 +01:00
entry.fastInsert(KIO::UDSEntry::UDS_LOCAL_PATH, interface.mountPoint());
if (!interface.isMounted()) {
interface.mount();
}
}
}
statEntry(entry);
finished();
}
void KioKdeconnect::get(const QUrl& url)
{
qCDebug(KDECONNECT_KIO) << "Get: " << url;
mimeType(QLatin1String(""));
finished();
}
//needed for JSON file embedding
#include "kiokdeconnect.moc"