/* * Copyright 2015 Aleix Pol Gonzalez * * 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 #include #include #include #include #include #include #include #include "interfaces/devicesmodel.h" #include "interfaces/notificationsmodel.h" #include "interfaces/dbusinterfaces.h" #include "kdeconnect-version.h" int main(int argc, char** argv) { QCoreApplication app(argc, argv); KAboutData about("kdeconnect-cli", "kdeconnect-cli", QLatin1String(KDECONNECT_VERSION_STRING), i18n("KDE Connect CLI tool"), KAboutLicense::GPL, i18n("(C) 2015 Aleix Pol Gonzalez")); KAboutData::setApplicationData(about); about.addAuthor( i18n("Aleix Pol Gonzalez"), QString(), "aleixpol@kde.org" ); about.addAuthor( i18n("Albert Vaca Cintora"), QString(), "albertvaka@gmail.com" ); QCommandLineParser parser; parser.addOption(QCommandLineOption(QStringList("l") << "list-devices", i18n("List all devices"))); parser.addOption(QCommandLineOption(QStringList("a") << "list-available", i18n("List available (paired and reachable) devices"))); parser.addOption(QCommandLineOption("id-only", i18n("Make --list-devices or --list-available print only the devices id, to ease scripting"))); parser.addOption(QCommandLineOption("refresh", i18n("Search for devices in the network and re-establish connections"))); parser.addOption(QCommandLineOption("pair", i18n("Request pairing to a said device"))); parser.addOption(QCommandLineOption("ring", i18n("Find the said device by ringing it."))); parser.addOption(QCommandLineOption("unpair", i18n("Stop pairing to a said device"))); parser.addOption(QCommandLineOption("ping", i18n("Sends a ping to said device"))); parser.addOption(QCommandLineOption("ping-msg", i18n("Same as ping but you can set the message to display"), i18n("message"))); parser.addOption(QCommandLineOption("share", i18n("Share a file to a said device"), "path")); parser.addOption(QCommandLineOption("list-notifications", i18n("Display the notifications on a said device"))); parser.addOption(QCommandLineOption("lock", i18n("Lock the specified device"))); parser.addOption(QCommandLineOption(QStringList("device") << "d", i18n("Device ID"), "dev")); parser.addOption(QCommandLineOption(QStringList("name") << "n", i18n("Device Name"), "name")); parser.addOption(QCommandLineOption("encryption-info", i18n("Get encryption info about said device"))); parser.addOption(QCommandLineOption("list-commands", i18n("Lists remote commands and their ids"))); parser.addOption(QCommandLineOption("execute-command", i18n("Executes a remote command by id"), "id")); about.setupCommandLine(&parser); parser.addHelpOption(); parser.process(app); about.processCommandLine(&parser); const QString id = "kdeconnect-cli-"+QString::number(QCoreApplication::applicationPid()); DaemonDbusInterface iface; if(parser.isSet("l") || parser.isSet("a")) { bool paired = true, reachable = false; if (parser.isSet("a")) { reachable = true; } else { iface.acquireDiscoveryMode(id); QThread::sleep(2); } QDBusPendingReply reply = iface.devices(paired, reachable); reply.waitForFinished(); const QStringList devices = reply.value(); Q_FOREACH (const QString& id, devices) { if (parser.isSet("id-only")) { QTextStream(stdout) << id << endl; } else { DeviceDbusInterface deviceIface(id); QString statusInfo; const bool isReachable = deviceIface.isReachable(), isPaired = deviceIface.property("isPaired").toBool(); if (isReachable && isPaired) { statusInfo = i18n("(paired and reachable)"); } else if (isReachable) { statusInfo = i18n("(reachable)"); } else if (isPaired) statusInfo = i18n("(paired)"); QTextStream(stdout) << "- " << deviceIface.name() << ": " << deviceIface.id() << ' ' << statusInfo << endl; } } if (!parser.isSet("id-only")) { QTextStream(stdout) << i18np("1 device found", "%1 devices found", devices.size()) << endl; } else if (devices.isEmpty()) { QTextStream(stderr) << i18n("No devices found") << endl; } iface.releaseDiscoveryMode(id); } else if(parser.isSet("refresh")) { QDBusMessage msg = QDBusMessage::createMethodCall("org.kde.kdeconnect", "/modules/kdeconnect", "org.kde.kdeconnect.daemon", "forceOnNetworkChange"); QDBusConnection::sessionBus().call(msg); } else { QString device = parser.value("device"); if (device.isEmpty() && parser.isSet("name")) { device = iface.deviceIdByName(parser.value("name")); if (device.isEmpty()) { QTextStream(stderr) << "Couldn't find device: " << parser.value("name") << endl; return 1; } } if(device.isEmpty()) { QTextStream(stderr) << i18n("No device specified") << endl; } if(parser.isSet("share")) { QUrl url = QUrl::fromUserInput(parser.value("share"), QDir::currentPath()); parser.clearPositionalArguments(); if(!url.isEmpty() && !device.isEmpty()) { QDBusMessage msg = QDBusMessage::createMethodCall("org.kde.kdeconnect", "/modules/kdeconnect/devices/"+device+"/share", "org.kde.kdeconnect.device.share", "shareUrl"); msg.setArguments(QVariantList() << url.toString()); QDBusConnection::sessionBus().call(msg); } else { QTextStream(stderr) << (i18n("Couldn't share %1", url.toString())) << endl; } } else if(parser.isSet("pair")) { DeviceDbusInterface dev(device); if (!dev.isReachable()) { //Device doesn't exist, go into discovery mode and wait up to 30 seconds for the device to appear QEventLoop wait; QTextStream(stderr) << i18n("waiting for device...") << endl; iface.acquireDiscoveryMode(id); QObject::connect(&iface, &DaemonDbusInterface::deviceAdded, [&](const QString &deviceAddedId) { if (device == deviceAddedId) { wait.quit(); } }); QTimer::singleShot(30 * 1000, &wait, &QEventLoop::quit); wait.exec(); } if (!dev.isReachable()) { QTextStream(stderr) << i18n("Device not found") << endl; } else if(dev.property("isPaired").toBool()) { QTextStream(stderr) << i18n("Already paired") << endl; } else { QTextStream(stderr) << i18n("Pair requested") << endl; QDBusPendingReply req = dev.requestPair(); req.waitForFinished(); } iface.releaseDiscoveryMode(id); } else if(parser.isSet("unpair")) { DeviceDbusInterface dev(device); if (!dev.isReachable()) { QTextStream(stderr) << i18n("Device does not exist") << endl; } else if(!dev.property("isPaired").toBool()) { QTextStream(stderr) << i18n("Already not paired") << endl; } else { QTextStream(stderr) << i18n("Unpaired") << endl; QDBusPendingReply req = dev.unpair(); req.waitForFinished(); } } else if(parser.isSet("ping") || parser.isSet("ping-msg")) { QDBusMessage msg = QDBusMessage::createMethodCall("org.kde.kdeconnect", "/modules/kdeconnect/devices/"+device+"/ping", "org.kde.kdeconnect.device.ping", "sendPing"); if (parser.isSet("ping-msg")) { QString message = parser.value("ping-msg"); msg.setArguments(QVariantList() << message); } QDBusConnection::sessionBus().call(msg); } else if(parser.isSet("ring")) { QDBusMessage msg = QDBusMessage::createMethodCall("org.kde.kdeconnect", "/modules/kdeconnect/devices/"+device+"/findmyphone", "org.kde.kdeconnect.device.findmyphone", "ring"); QDBusConnection::sessionBus().call(msg); } else if(parser.isSet("list-notifications")) { NotificationsModel notifications; notifications.setDeviceId(device); for(int i=0, rows=notifications.rowCount(); itoObject(); QTextStream(stdout) << it.key() << ": " << cont.value("name").toString() << ": " << cont.value("command").toString() << endl; } const auto err = iface.lastError(); if (err.isValid()) { QTextStream(stderr) << err.message() << endl; } } else if(parser.isSet("execute-command")) { RemoteCommandsDbusInterface iface(device); iface.triggerCommand(parser.value("execute-command")); } else if(parser.isSet("encryption-info")) { DeviceDbusInterface dev(device); QDBusPendingReply devReply = dev.encryptionInfo(); // QSsl::Der = 1 devReply.waitForFinished(); QTextStream(stderr) << devReply.value() << endl; } else { QTextStream(stderr) << i18n("Nothing to be done") << endl; } } QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection); return app.exec(); }