/** * Copyright 2013 Albert Vaca * * 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 * along with this program. If not, see . */ #include "kiokdeconnect.h" #include #include #include #include #include #include #include #include #include #include "kdebugnamespace.h" extern "C" int KDE_EXPORT kdemain(int argc, char **argv) { KAboutData about("kiokdeconnect", "kdeconnect-kio", ki18n("kiokdeconnect"), "1.0"); KCmdLineArgs::init(&about); KApplication app; if (argc != 4) { fprintf(stderr, "Usage: kio_kdeconnect protocol pool app\n"); exit(-1); } KioKdeconnect slave(argv[2], argv[3]); slave.dispatchLoop(); return 0; } //Some useful error mapping KIO::Error toKioError(const QDBusError::ErrorType type) { switch (type) { case QDBusError::NoError: return KIO::Error(KJob::NoError); case QDBusError::NoMemory: return KIO::ERR_OUT_OF_MEMORY; case QDBusError::Timeout: return KIO::ERR_SERVER_TIMEOUT; case QDBusError::TimedOut: return KIO::ERR_SERVER_TIMEOUT; default: return KIO::ERR_INTERNAL; }; }; template bool handleDBusError(QDBusReply& reply, KIO::SlaveBase* slave) { if (!reply.isValid()) { kDebug(kdeconnect_kio()) << "Error in DBus request:" << reply.error(); 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...")); QStringList devices = m_dbusInterface->devices(true, true); //TODO: Change to all devices and show different icons for connected and disconnected? totalSize(devices.length()); int i = 0; Q_FOREACH(const QString& deviceId, devices) { DeviceDbusInterface interface(deviceId); if (!interface.hasPlugin("kdeconnect_sftp")) continue; const QString target = QString("kdeconnect://").append(deviceId).append("/"); const QString name = interface.name(); const QString icon = "smartphone"; KIO::UDSEntry entry; entry.insert(KIO::UDSEntry::UDS_NAME, name); entry.insert(KIO::UDSEntry::UDS_ICON_NAME, icon); entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); entry.insert(KIO::UDSEntry::UDS_ACCESS, S_IRUSR | S_IRGRP | S_IROTH); entry.insert(KIO::UDSEntry::UDS_MIME_TYPE, ""); entry.insert(KIO::UDSEntry::UDS_URL, target); listEntry(entry, false); processedSize(i++); } listEntry(KIO::UDSEntry(), true); infoMessage(""); finished(); } void KioKdeconnect::listDevice() { infoMessage(i18n("Accessing device...")); kDebug(kdeconnect_kio()) << "ListDevice" << m_currentDevice; SftpDbusInterface interface(m_currentDevice); QDBusReply mountreply = interface.mountAndWait(); if (handleDBusError(mountreply, this)) { return; } if (!mountreply.value()) { error(KIO::ERR_COULD_NOT_MOUNT, i18n("Could not mount device filesystem")); return; } QDBusReply urlreply = interface.mountPoint(); if (handleDBusError(urlreply, this)) { return; } QString url = urlreply.value(); KIO::UDSEntry entry; entry.insert(KIO::UDSEntry::UDS_NAME, "files"); entry.insert(KIO::UDSEntry::UDS_DISPLAY_NAME, i18n("Camera pictures")); entry.insert(KIO::UDSEntry::UDS_ICON_NAME, "folder"); entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); entry.insert(KIO::UDSEntry::UDS_ACCESS, S_IRUSR | S_IRGRP | S_IROTH); entry.insert(KIO::UDSEntry::UDS_MIME_TYPE, ""); entry.insert(KIO::UDSEntry::UDS_URL, url + "/DCIM/Camera"); listEntry(entry, false); entry.insert(KIO::UDSEntry::UDS_NAME, "files"); entry.insert(KIO::UDSEntry::UDS_DISPLAY_NAME, i18n("All files")); entry.insert(KIO::UDSEntry::UDS_ICON_NAME, "folder"); entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); entry.insert(KIO::UDSEntry::UDS_ACCESS, S_IRUSR | S_IRGRP | S_IROTH); entry.insert(KIO::UDSEntry::UDS_MIME_TYPE, ""); entry.insert(KIO::UDSEntry::UDS_URL, url); listEntry(entry, false); listEntry(KIO::UDSEntry(), true); infoMessage(""); finished(); } void KioKdeconnect::listDir(const KUrl &url) { kDebug(kdeconnect_kio()) << "Listing..." << url; /// Url is not used here becuase all we could care about the url is the host, and that's already /// handled in @p setHost Q_UNUSED(url); if (!m_dbusInterface->isValid()) { infoMessage(i18n("Could not contact background service.")); listEntry(KIO::UDSEntry(), true); finished(); return; } if (m_currentDevice.isEmpty()) { listAllDevices(); } else { listDevice(); } } void KioKdeconnect::stat(const KUrl &url) { kDebug(kdeconnect_kio()) << "Stat: " << url; KIO::UDSEntry entry; entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); statEntry(entry); finished(); } void KioKdeconnect::get(const KUrl &url) { kDebug(kdeconnect_kio()) << "Get: " << url; mimeType(""); finished(); } void KioKdeconnect::setHost(const QString &hostName, quint16 port, const QString &user, const QString &pass) { //This is called before everything else to set the file we want to show kDebug(kdeconnect_kio()) << "Setting host: " << hostName; // In this kio only the hostname is used Q_UNUSED(port) Q_UNUSED(user) Q_UNUSED(pass) m_currentDevice = hostName; }