/* * 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(QStringLiteral("kdeconnect-cli"), QStringLiteral("kdeconnect-cli"), QStringLiteral(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(), QStringLiteral("aleixpol@kde.org") ); about.addAuthor( i18n("Albert Vaca Cintora"), QString(), QStringLiteral("albertvaka@gmail.com") ); QCommandLineParser parser; parser.addOption(QCommandLineOption(QStringList(QStringLiteral("l")) << QStringLiteral("list-devices"), i18n("List all devices"))); parser.addOption(QCommandLineOption(QStringList(QStringLiteral("a")) << QStringLiteral("list-available"), i18n("List available (paired and reachable) devices"))); parser.addOption(QCommandLineOption(QStringLiteral("id-only"), i18n("Make --list-devices or --list-available print only the devices id, to ease scripting"))); parser.addOption(QCommandLineOption(QStringLiteral("refresh"), i18n("Search for devices in the network and re-establish connections"))); parser.addOption(QCommandLineOption(QStringLiteral("pair"), i18n("Request pairing to a said device"))); parser.addOption(QCommandLineOption(QStringLiteral("ring"), i18n("Find the said device by ringing it."))); parser.addOption(QCommandLineOption(QStringLiteral("unpair"), i18n("Stop pairing to a said device"))); parser.addOption(QCommandLineOption(QStringLiteral("ping"), i18n("Sends a ping to said device"))); parser.addOption(QCommandLineOption(QStringLiteral("ping-msg"), i18n("Same as ping but you can set the message to display"), i18n("message"))); parser.addOption(QCommandLineOption(QStringLiteral("share"), i18n("Share a file to a said device"), QStringLiteral("path"))); parser.addOption(QCommandLineOption(QStringLiteral("list-notifications"), i18n("Display the notifications on a said device"))); parser.addOption(QCommandLineOption(QStringLiteral("lock"), i18n("Lock the specified device"))); parser.addOption(QCommandLineOption(QStringLiteral("send-sms"), i18n("Sends an SMS. Requires destination"), i18n("message"))); parser.addOption(QCommandLineOption(QStringLiteral("destination"), i18n("Phone number to send the message"), i18n("phone number"))); parser.addOption(QCommandLineOption(QStringList(QStringLiteral("device")) << QStringLiteral("d"), i18n("Device ID"), QStringLiteral("dev"))); parser.addOption(QCommandLineOption(QStringList(QStringLiteral("name")) << QStringLiteral("n"), i18n("Device Name"), QStringLiteral("name"))); parser.addOption(QCommandLineOption(QStringLiteral("encryption-info"), i18n("Get encryption info about said device"))); parser.addOption(QCommandLineOption(QStringLiteral("list-commands"), i18n("Lists remote commands and their ids"))); parser.addOption(QCommandLineOption(QStringLiteral("execute-command"), i18n("Executes a remote command by id"), QStringLiteral("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(QStringLiteral("l")) || parser.isSet(QStringLiteral("a"))) { bool paired = true, reachable = false; if (parser.isSet(QStringLiteral("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(QStringLiteral("id-only"))) { QTextStream(stdout) << id << endl; } else { DeviceDbusInterface deviceIface(id); QString statusInfo; const bool isReachable = deviceIface.isReachable(); const bool isTrusted = deviceIface.isTrusted(); if (isReachable && isTrusted) { statusInfo = i18n("(paired and reachable)"); } else if (isReachable) { statusInfo = i18n("(reachable)"); } else if (isTrusted) { statusInfo = i18n("(paired)"); } QTextStream(stdout) << "- " << deviceIface.name() << ": " << deviceIface.id() << ' ' << statusInfo << endl; } } if (!parser.isSet(QStringLiteral("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(QStringLiteral("refresh"))) { QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kdeconnect"), QStringLiteral("/modules/kdeconnect"), QStringLiteral("org.kde.kdeconnect.daemon"), QStringLiteral("forceOnNetworkChange")); QDBusConnection::sessionBus().call(msg); } else { QString device = parser.value(QStringLiteral("device")); if (device.isEmpty() && parser.isSet(QStringLiteral("name"))) { device = iface.deviceIdByName(parser.value(QStringLiteral("name"))); if (device.isEmpty()) { QTextStream(stderr) << "Couldn't find device: " << parser.value(QStringLiteral("name")) << endl; return 1; } } if(device.isEmpty()) { QTextStream(stderr) << i18n("No device specified") << endl; parser.showHelp(1); } if(parser.isSet(QStringLiteral("share"))) { QUrl url = QUrl::fromUserInput(parser.value(QStringLiteral("share")), QDir::currentPath()); parser.clearPositionalArguments(); if(!url.isEmpty() && !device.isEmpty()) { QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kdeconnect"), "/modules/kdeconnect/devices/"+device+"/share", QStringLiteral("org.kde.kdeconnect.device.share"), QStringLiteral("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(QStringLiteral("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(QStringLiteral("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(QStringLiteral("ping")) || parser.isSet(QStringLiteral("ping-msg"))) { QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kdeconnect"), "/modules/kdeconnect/devices/"+device+"/ping", QStringLiteral("org.kde.kdeconnect.device.ping"), QStringLiteral("sendPing")); if (parser.isSet(QStringLiteral("ping-msg"))) { QString message = parser.value(QStringLiteral("ping-msg")); msg.setArguments(QVariantList() << message); } QDBusConnection::sessionBus().call(msg); } else if(parser.isSet(QStringLiteral("send-sms"))) { if (parser.isSet(QStringLiteral("destination"))) { QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kdeconnect"), "/modules/kdeconnect/devices/"+device+"/telephony", QStringLiteral("org.kde.kdeconnect.device.telephony"), QStringLiteral("sendSms")); msg.setArguments({ parser.value("destination"), parser.value("send-sms") }); QDBusConnection::sessionBus().call(msg); } else { QTextStream(stderr) << i18n("error: should specify the SMS's recipient by passing --destination "); return 1; } } else if(parser.isSet(QStringLiteral("ring"))) { QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kdeconnect"), "/modules/kdeconnect/devices/"+device+"/findmyphone", QStringLiteral("org.kde.kdeconnect.device.findmyphone"), QStringLiteral("ring")); QDBusConnection::sessionBus().call(msg); } else if(parser.isSet(QStringLiteral("list-notifications"))) { NotificationsModel notifications; notifications.setDeviceId(device); for(int i=0, rows=notifications.rowCount(); itoObject(); QTextStream(stdout) << it.key() << ": " << cont.value(QStringLiteral("name")).toString() << ": " << cont.value(QStringLiteral("command")).toString() << endl; } const auto err = iface.lastError(); if (err.isValid()) { QTextStream(stderr) << err.message() << endl; } } else if(parser.isSet(QStringLiteral("execute-command"))) { RemoteCommandsDbusInterface iface(device); iface.triggerCommand(parser.value(QStringLiteral("execute-command"))); } else if(parser.isSet(QStringLiteral("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(); }