diff --git a/CMakeLists.txt b/CMakeLists.txt index a3e52a1..d4eca66 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) include(GenerateExportHeader) diff --git a/networkmanagement/CMakeLists.txt b/networkmanagement/CMakeLists.txt index 48127d1..c514dd4 100644 --- a/networkmanagement/CMakeLists.txt +++ b/networkmanagement/CMakeLists.txt @@ -11,9 +11,6 @@ set(NETWORKMGR_SRCS networkmodelitem.cpp networkmodelitem.h - networking.cpp - networking.h - network.cpp network.h @@ -32,6 +29,21 @@ set(NETWORKMGR_SRCS identitymodel.cpp identitymodel.h + handler.cpp + handler.h + + configuration.cpp + configuration.h + + enabledconnections.cpp + enabledconnections.h + + enums.cpp + enums.h + + wifisettings.cpp + wifisettings.h + qmlplugins.cpp qmlplugins.h ) diff --git a/networkmanagement/configuration.cpp b/networkmanagement/configuration.cpp new file mode 100644 index 0000000..b72ef5e --- /dev/null +++ b/networkmanagement/configuration.cpp @@ -0,0 +1,163 @@ +/* + Copyright 2017 Jan Grulich + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +*/ + +#include "configuration.h" + +#include +#include +#include + +static bool propManageVirtualConnectionsInitialized = false; +static bool propManageVirtualConnections = false; + +Configuration::Configuration() +{ + ::passwd *pw = ::getpwuid(::getuid()); + m_userName = QString::fromLocal8Bit(pw->pw_name); +} + +Configuration &Configuration::self() +{ + static Configuration c; + return c; +} + +bool Configuration::unlockModemOnDetection() +{ + QSettings config(QSettings::UserScope, "cutefishos", "nm"); + config.beginGroup(QLatin1String("General")); + + return config.value("UnlockModemOnDetection", true).toBool(); +} + +void Configuration::setUnlockModemOnDetection(bool unlock) +{ + QSettings config(QSettings::UserScope, "cutefishos", "nm"); + config.beginGroup(QLatin1String("General")); + config.setValue(QLatin1String("UnlockModemOnDetection"), unlock); +} + +bool Configuration::manageVirtualConnections() +{ + // Avoid reading from the config file over and over + if (propManageVirtualConnectionsInitialized) { + return propManageVirtualConnections; + } + + QSettings config(QSettings::UserScope, "cutefishos", "nm"); + config.beginGroup(QLatin1String("General")); + + propManageVirtualConnections = config.value(QLatin1String("ManageVirtualConnections"), false).toBool(); + propManageVirtualConnectionsInitialized = true; + + return propManageVirtualConnections; +} + +void Configuration::setManageVirtualConnections(bool manage) +{ + QSettings config(QSettings::UserScope, "cutefishos", "nm"); + config.beginGroup(QLatin1String("General")); + + config.setValue(QLatin1String("ManageVirtualConnections"), manage); + propManageVirtualConnections = manage; +} + +bool Configuration::airplaneModeEnabled() +{ + // Check whether other devices are disabled to assume airplane mode is enabled + // after suspend + const bool isWifiDisabled = !NetworkManager::isWirelessEnabled() || !NetworkManager::isWirelessHardwareEnabled(); + const bool isWwanDisabled = !NetworkManager::isWwanEnabled() || !NetworkManager::isWwanHardwareEnabled(); + + QSettings config(QSettings::UserScope, "cutefishos", "nm"); + config.beginGroup(QLatin1String("General")); + + if (config.value(QLatin1String("AirplaneModeEnabled"), false).toBool()) { + // We can assume that airplane mode is still activated after resume + if (isWifiDisabled && isWwanDisabled) + return true; + else { + setAirplaneModeEnabled(false); + } + } + + return false; +} + +void Configuration::setAirplaneModeEnabled(bool enabled) +{ + QSettings config(QSettings::UserScope, "cutefishos", "nm"); + config.beginGroup(QLatin1String("General")); + config.setValue(QLatin1String("AirplaneModeEnabled"), enabled); +} + +QString Configuration::hotspotName() +{ + QSettings config(QSettings::UserScope, "cutefishos", "nm"); + config.beginGroup(QLatin1String("General")); + + const QString defaultName = m_userName + QLatin1String("-hotspot"); + + return config.value(QLatin1String("HotspotName"), defaultName).toString(); +} + +void Configuration::setHotspotName(const QString &name) +{ + QSettings config(QSettings::UserScope, "cutefishos", "nm"); + config.beginGroup(QLatin1String("General")); + config.setValue(QLatin1String("HotspotName"), name); +} + +QString Configuration::hotspotPassword() +{ + QSettings config(QSettings::UserScope, "cutefishos", "nm"); + config.beginGroup(QLatin1String("General")); + return config.value(QLatin1String("HotspotPassword"), QString()).toString(); +} + +void Configuration::setHotspotPassword(const QString &password) +{ + QSettings config(QSettings::UserScope, "cutefishos", "nm"); + config.beginGroup(QLatin1String("General")); + config.setValue(QLatin1String("HotspotPassword"), password); +} + +QString Configuration::hotspotConnectionPath() +{ + QSettings config(QSettings::UserScope, "cutefishos", "nm"); + config.beginGroup(QLatin1String("General")); + return config.value(QLatin1String("HotspotConnectionPath"), QString()).toString(); +} + +void Configuration::setHotspotConnectionPath(const QString &path) +{ + QSettings config(QSettings::UserScope, "cutefishos", "nm"); + config.beginGroup(QLatin1String("General")); + config.setValue(QLatin1String("HotspotConnectionPath"), path); +} + +bool Configuration::showPasswordDialog() +{ + QSettings config(QSettings::UserScope, "cutefishos", "nm"); + config.beginGroup(QLatin1String("General")); + + return config.value(QLatin1String("ShowPasswordDialog"), true).toBool(); +} + diff --git a/networkmanagement/configuration.h b/networkmanagement/configuration.h new file mode 100644 index 0000000..fd1bdcc --- /dev/null +++ b/networkmanagement/configuration.h @@ -0,0 +1,71 @@ +/* + Copyright 2017 Jan Grulich + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +*/ + +#ifndef PLASMA_NM_CONFIGURATION_H +#define PLASMA_NM_CONFIGURATION_H + +#include + +#include + +class Q_DECL_EXPORT Configuration : public QObject +{ + Q_PROPERTY(bool unlockModemOnDetection READ unlockModemOnDetection WRITE setUnlockModemOnDetection) + Q_PROPERTY(bool manageVirtualConnections READ manageVirtualConnections WRITE setManageVirtualConnections) + Q_PROPERTY(bool airplaneModeEnabled READ airplaneModeEnabled WRITE setAirplaneModeEnabled) + Q_PROPERTY(QString hotspotName READ hotspotName WRITE setHotspotName) + Q_PROPERTY(QString hotspotPassword READ hotspotPassword WRITE setHotspotPassword) + Q_PROPERTY(QString hotspotConnectionPath READ hotspotConnectionPath WRITE setHotspotConnectionPath) + + //Readonly constant property, as this value should only be set by the platform + Q_PROPERTY(bool showPasswordDialog READ showPasswordDialog CONSTANT) + Q_OBJECT + +public: + Configuration(); + + bool unlockModemOnDetection(); + void setUnlockModemOnDetection(bool unlock); + + bool manageVirtualConnections(); + void setManageVirtualConnections(bool manage); + + bool airplaneModeEnabled(); + void setAirplaneModeEnabled(bool enabled); + + QString hotspotName(); + void setHotspotName(const QString &name); + + QString hotspotPassword(); + void setHotspotPassword(const QString &password); + + QString hotspotConnectionPath(); + void setHotspotConnectionPath(const QString &path); + + bool showPasswordDialog(); + + static Configuration &self(); + +private: + QString m_userName; +}; + +#endif // PLAMA_NM_CONFIGURATION_H + diff --git a/networkmanagement/enabledconnections.cpp b/networkmanagement/enabledconnections.cpp new file mode 100644 index 0000000..adec8fd --- /dev/null +++ b/networkmanagement/enabledconnections.cpp @@ -0,0 +1,96 @@ +/* + Copyright 2013 Jan Grulich + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +*/ + + +#include "enabledconnections.h" + +EnabledConnections::EnabledConnections(QObject* parent) + : QObject(parent) + , m_networkingEnabled(NetworkManager::isNetworkingEnabled()) + , m_wirelessEnabled(NetworkManager::isWirelessEnabled()) + , m_wirelessHwEnabled(NetworkManager::isWirelessHardwareEnabled()) + , m_wwanEnabled(NetworkManager::isWwanEnabled()) + , m_wwanHwEnabled(NetworkManager::isWwanHardwareEnabled()) +{ + connect(NetworkManager::notifier(), &NetworkManager::Notifier::networkingEnabledChanged, this, &EnabledConnections::onNetworkingEnabled); + connect(NetworkManager::notifier(), &NetworkManager::Notifier::wirelessEnabledChanged, this, &EnabledConnections::onWirelessEnabled); + connect(NetworkManager::notifier(), &NetworkManager::Notifier::wirelessHardwareEnabledChanged, this, &EnabledConnections::onWirelessHwEnabled); + connect(NetworkManager::notifier(), &NetworkManager::Notifier::wwanEnabledChanged, this, &EnabledConnections::onWwanEnabled); + connect(NetworkManager::notifier(), &NetworkManager::Notifier::wwanHardwareEnabledChanged, this, &EnabledConnections::onWwanHwEnabled); +} + +EnabledConnections::~EnabledConnections() +{ +} + +bool EnabledConnections::isNetworkingEnabled() const +{ + return m_networkingEnabled; +} + +bool EnabledConnections::isWirelessEnabled() const +{ + return m_wirelessEnabled; +} + +bool EnabledConnections::isWirelessHwEnabled() const +{ + return m_wirelessHwEnabled; +} + +bool EnabledConnections::isWwanEnabled() const +{ + return m_wwanEnabled; +} + +bool EnabledConnections::isWwanHwEnabled() const +{ + return m_wwanHwEnabled; +} + +void EnabledConnections::onNetworkingEnabled(bool enabled) +{ + m_networkingEnabled = enabled; + Q_EMIT networkingEnabled(enabled); +} + +void EnabledConnections::onWirelessEnabled(bool enabled) +{ + m_wirelessEnabled = enabled; + Q_EMIT wirelessEnabled(enabled); +} + +void EnabledConnections::onWirelessHwEnabled(bool enabled) +{ + m_wirelessHwEnabled = enabled; + Q_EMIT wirelessHwEnabled(enabled); +} + +void EnabledConnections::onWwanEnabled(bool enabled) +{ + m_wwanEnabled = enabled; + Q_EMIT wwanEnabled(enabled); +} + +void EnabledConnections::onWwanHwEnabled(bool enabled) +{ + m_wwanHwEnabled = enabled; + Q_EMIT wwanHwEnabled(enabled); +} diff --git a/networkmanagement/enabledconnections.h b/networkmanagement/enabledconnections.h new file mode 100644 index 0000000..8cd3367 --- /dev/null +++ b/networkmanagement/enabledconnections.h @@ -0,0 +1,84 @@ +/* + Copyright 2013 Jan Grulich + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +*/ + +#ifndef PLASMA_NM_ENABLED_CONNECTIONS_H +#define PLASMA_NM_ENABLED_CONNECTIONS_H + +#include + +#include + +class EnabledConnections : public QObject +{ +/** + * Indicates if overall networking is currently enabled or not + */ +Q_PROPERTY(bool networkingEnabled READ isNetworkingEnabled NOTIFY networkingEnabled) +/** + * Indicates if wireless is currently enabled or not + */ +Q_PROPERTY(bool wirelessEnabled READ isWirelessEnabled NOTIFY wirelessEnabled) +/** + * Indicates if the wireless hardware is currently enabled, i.e. the state of the RF kill switch + */ +Q_PROPERTY(bool wirelessHwEnabled READ isWirelessHwEnabled NOTIFY wirelessHwEnabled) +/** + * Indicates if mobile broadband devices are currently enabled or not. + */ +Q_PROPERTY(bool wwanEnabled READ isWwanEnabled NOTIFY wwanEnabled) +/** + * Indicates if the mobile broadband hardware is currently enabled, i.e. the state of the RF kill switch. + */ +Q_PROPERTY(bool wwanHwEnabled READ isWwanHwEnabled NOTIFY wwanHwEnabled) + +Q_OBJECT +public: + explicit EnabledConnections(QObject* parent = nullptr); + ~EnabledConnections() override; + + bool isNetworkingEnabled() const; + bool isWirelessEnabled() const; + bool isWirelessHwEnabled() const; + bool isWwanEnabled() const; + bool isWwanHwEnabled() const; + +public Q_SLOTS: + void onNetworkingEnabled(bool enabled); + void onWirelessEnabled(bool enabled); + void onWirelessHwEnabled(bool enabled); + void onWwanEnabled(bool enabled); + void onWwanHwEnabled(bool enabled); + +Q_SIGNALS: + void networkingEnabled(bool enabled); + void wirelessEnabled(bool enabled); + void wirelessHwEnabled(bool enabled); + void wwanEnabled(bool enabled); + void wwanHwEnabled(bool enabled); + +private: + bool m_networkingEnabled; + bool m_wirelessEnabled; + bool m_wirelessHwEnabled; + bool m_wwanEnabled; + bool m_wwanHwEnabled; +}; + +#endif // PLASMA_NM_ENABLED_CONNECTIONS_H diff --git a/networkmanagement/enums.cpp b/networkmanagement/enums.cpp new file mode 100644 index 0000000..ab17b7e --- /dev/null +++ b/networkmanagement/enums.cpp @@ -0,0 +1,30 @@ +/* + Copyright 2013 Jan Grulich + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +*/ + +#include "enums.h" + +Enums::Enums(QObject* parent) + : QObject(parent) +{ +} + +Enums::~Enums() +{ +} diff --git a/networkmanagement/enums.h b/networkmanagement/enums.h new file mode 100644 index 0000000..4bf414c --- /dev/null +++ b/networkmanagement/enums.h @@ -0,0 +1,77 @@ +/* + Copyright 2013 Jan Grulich + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +*/ + +#ifndef PLASMA_NM_ENUMS_H +#define PLASMA_NM_ENUMS_H + +#include + +class Enums : public QObject +{ +Q_OBJECT +Q_ENUMS(ConnectionStatus) +Q_ENUMS(ConnectionType) +Q_ENUMS(SecurityType) + +public: + explicit Enums(QObject* parent = nullptr); + ~Enums() override; + + enum ConnectionStatus { + UnknownState = 0, + Activating, + Activated, + Deactivating, + Deactivated + }; + + enum ConnectionType { + UnknownConnectionType = 0, + Adsl, + Bluetooth, + Bond, + Bridge, + Cdma, + Gsm, + Infiniband, + OLPCMesh, + Pppoe, + Vlan, + Vpn, + Wimax, + Wired, + Wireless + }; + + enum SecurityType { + UnknownSecurity = -1, + NoneSecurity = 0, + StaticWep, + DynamicWep, + Leap, + WpaPsk, + WpaEap, + Wpa2Psk, + Wpa2Eap, + SAE + }; +}; + +#endif // PLASMA_NM_ENUMS_H diff --git a/networkmanagement/handler.cpp b/networkmanagement/handler.cpp new file mode 100644 index 0000000..b3f5d80 --- /dev/null +++ b/networkmanagement/handler.cpp @@ -0,0 +1,867 @@ +/* + Copyright 2013-2014 Jan Grulich + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +*/ + +#include "handler.h" +#include "configuration.h" +#include "uiutils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#if WITH_MODEMMANAGER_SUPPORT +#include +#include +#endif + +#include +#include +#include +#include + +#include +#include + +#define AGENT_SERVICE "org.kde.kded5" +#define AGENT_PATH "/modules/networkmanagement" +#define AGENT_IFACE "org.kde.plasmanetworkmanagement" + +// 10 seconds +#define NM_REQUESTSCAN_LIMIT_RATE 10000 + +Handler::Handler(QObject *parent) + : QObject(parent) + , m_tmpWirelessEnabled(NetworkManager::isWirelessEnabled()) + , m_tmpWwanEnabled(NetworkManager::isWwanEnabled()) +{ + ::passwd *pw = ::getpwuid(::getuid()); + m_userName = QString::fromLocal8Bit(pw->pw_name); + + QDBusConnection::sessionBus().connect(QStringLiteral(AGENT_SERVICE), + QStringLiteral(AGENT_PATH), + QStringLiteral(AGENT_IFACE), + QStringLiteral("secretsError"), + this, SLOT(secretAgentError(QString, QString))); + + + if (!Configuration::self().hotspotConnectionPath().isEmpty()) { + NetworkManager::ActiveConnection::Ptr hotspot = NetworkManager::findActiveConnection(Configuration::self().hotspotConnectionPath()); + if (!hotspot) { + Configuration::self().setHotspotConnectionPath(QString()); + } + } + + m_hotspotSupported = checkHotspotSupported(); + + if (NetworkManager::checkVersion(1, 16, 0)) { + connect(NetworkManager::notifier(), &NetworkManager::Notifier::primaryConnectionTypeChanged, this, &Handler::primaryConnectionTypeChanged); + } +} + +Handler::~Handler() +{ +} + +void Handler::activateConnection(const QString& connection, const QString& device, const QString& specificObject) +{ + NetworkManager::Connection::Ptr con = NetworkManager::findConnection(connection); + + if (!con) { + qWarning() << "Not possible to activate this connection"; + return; + } + + if (con->settings()->connectionType() == NetworkManager::ConnectionSettings::Vpn) { + NetworkManager::VpnSetting::Ptr vpnSetting = con->settings()->setting(NetworkManager::Setting::Vpn).staticCast(); + if (vpnSetting) { + qDebug() << "Checking VPN" << con->name() << "type:" << vpnSetting->serviceType(); + + // bool pluginMissing = false; + + // // Check missing plasma-nm VPN plugin + // const KService::List services = KServiceTypeTrader::self()->query("PlasmaNetworkManagement/VpnUiPlugin", + // QString::fromLatin1("[X-NetworkManager-Services]=='%1'").arg(vpnSetting->serviceType())); + // pluginMissing = services.isEmpty(); + + // // Check missing NetworkManager VPN plugin + // if (!pluginMissing) { + // GSList *plugins = nullptr; + // plugins = nm_vpn_plugin_info_list_load(); + + // NMVpnPluginInfo *plugin_info = nm_vpn_plugin_info_list_find_by_service(plugins, vpnSetting->serviceType().toStdString().c_str()); + // pluginMissing = !plugin_info; + // } + + // if (pluginMissing) { + // qWarning() << "VPN" << vpnSetting->serviceType() << "not found, skipping"; + // KNotification *notification = new KNotification("MissingVpnPlugin", KNotification::CloseOnTimeout, this); + // notification->setComponentName("networkmanagement"); + // notification->setTitle(con->name()); + // notification->setText(i18n("Missing VPN plugin")); + // notification->setIconName(QStringLiteral("dialog-warning")); + // notification->sendEvent(); + // return; + // } + + } + } + +#if WITH_MODEMMANAGER_SUPPORT + if (con->settings()->connectionType() == NetworkManager::ConnectionSettings::Gsm) { + NetworkManager::ModemDevice::Ptr nmModemDevice = NetworkManager::findNetworkInterface(device).objectCast(); + if (nmModemDevice) { + ModemManager::ModemDevice::Ptr mmModemDevice = ModemManager::findModemDevice(nmModemDevice->udi()); + if (mmModemDevice) { + ModemManager::Modem::Ptr modem = mmModemDevice->interface(ModemManager::ModemDevice::ModemInterface).objectCast(); + NetworkManager::GsmSetting::Ptr gsmSetting = con->settings()->setting(NetworkManager::Setting::Gsm).staticCast(); + if (gsmSetting && gsmSetting->pinFlags() == NetworkManager::Setting::NotSaved && + modem && modem->unlockRequired() > MM_MODEM_LOCK_NONE) { + QDBusInterface managerIface("org.kde.plasmanetworkmanagement", "/org/kde/plasmanetworkmanagement", "org.kde.plasmanetworkmanagement", QDBusConnection::sessionBus(), this); + managerIface.call("unlockModem", mmModemDevice->uni()); + connect(modem.data(), &ModemManager::Modem::unlockRequiredChanged, this, &Handler::unlockRequiredChanged); + m_tmpConnectionPath = connection; + m_tmpDevicePath = device; + m_tmpSpecificPath = specificObject; + return; + } + } + } + } +#endif + + QDBusPendingReply reply = NetworkManager::activateConnection(connection, device, specificObject); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); + watcher->setProperty("action", Handler::ActivateConnection); + watcher->setProperty("connection", con->name()); + connect(watcher, &QDBusPendingCallWatcher::finished, this, &Handler::replyFinished); +} + +QString Handler::wifiCode(const QString& connectionPath, const QString& ssid, int _securityType) const +{ + NetworkManager::WirelessSecurityType securityType = static_cast(_securityType); + + QString ret = QStringLiteral("WIFI:S:") + ssid + QLatin1Char(';'); + if (securityType != NetworkManager::NoneSecurity) { + switch (securityType) { + case NetworkManager::NoneSecurity: + break; + case NetworkManager::StaticWep: + ret += "T:WEP;"; + break; + case NetworkManager::WpaPsk: + case NetworkManager::Wpa2Psk: + ret += "T:WPA;"; + break; + case NetworkManager::SAE: + ret += "T:SAE;"; + break; + default: + case NetworkManager::DynamicWep: + case NetworkManager::WpaEap: + case NetworkManager::Wpa2Eap: + case NetworkManager::Leap: + return {}; + } + } + + NetworkManager::Connection::Ptr connection = NetworkManager::findConnection(connectionPath); + if(!connection) + return {}; + + const auto key = QStringLiteral("802-11-wireless-security"); + auto reply = connection->secrets(key); + + const auto secret = reply.argumentAt<0>()[key]; + QString pass; + switch (securityType) { + case NetworkManager::NoneSecurity: + break; + case NetworkManager::WpaPsk: + case NetworkManager::Wpa2Psk: + case NetworkManager::SAE: + pass = secret["psk"].toString(); + break; + default: + return {}; + } + if (!pass.isEmpty()) + ret += QStringLiteral("P:") + pass + QLatin1Char(';'); + + return ret + QLatin1Char(';'); +} + +void Handler::addAndActivateConnection(const QString& device, const QString& specificObject, const QString& password) +{ + NetworkManager::AccessPoint::Ptr ap; + NetworkManager::WirelessDevice::Ptr wifiDev; + for (const NetworkManager::Device::Ptr &dev : NetworkManager::networkInterfaces()) { + if (dev->type() == NetworkManager::Device::Wifi) { + wifiDev = dev.objectCast(); + ap = wifiDev->findAccessPoint(specificObject); + if (ap) { + break; + } + } + } + + if (!ap) { + return; + } + + NetworkManager::ConnectionSettings::Ptr settings = NetworkManager::ConnectionSettings::Ptr(new NetworkManager::ConnectionSettings(NetworkManager::ConnectionSettings::Wireless)); + settings->setId(ap->ssid()); + settings->setUuid(NetworkManager::ConnectionSettings::createNewUuid()); + settings->setAutoconnect(true); + settings->addToPermissions(m_userName, QString()); + + NetworkManager::WirelessSetting::Ptr wifiSetting = settings->setting(NetworkManager::Setting::Wireless).dynamicCast(); + wifiSetting->setInitialized(true); + wifiSetting = settings->setting(NetworkManager::Setting::Wireless).dynamicCast(); + wifiSetting->setSsid(ap->ssid().toUtf8()); + if (ap->mode() == NetworkManager::AccessPoint::Adhoc) { + wifiSetting->setMode(NetworkManager::WirelessSetting::Adhoc); + } + NetworkManager::WirelessSecuritySetting::Ptr wifiSecurity = settings->setting(NetworkManager::Setting::WirelessSecurity).dynamicCast(); + + NetworkManager::WirelessSecurityType securityType = NetworkManager::findBestWirelessSecurity(wifiDev->wirelessCapabilities(), true, (ap->mode() == NetworkManager::AccessPoint::Adhoc), ap->capabilities(), ap->wpaFlags(), ap->rsnFlags()); + + if (securityType != NetworkManager::NoneSecurity) { + wifiSecurity->setInitialized(true); + wifiSetting->setSecurity("802-11-wireless-security"); + } + + if (securityType == NetworkManager::Leap || + securityType == NetworkManager::DynamicWep || + securityType == NetworkManager::Wpa2Eap || + securityType == NetworkManager::WpaEap) { + if (securityType == NetworkManager::DynamicWep || securityType == NetworkManager::Leap) { + wifiSecurity->setKeyMgmt(NetworkManager::WirelessSecuritySetting::Ieee8021x); + if (securityType == NetworkManager::Leap) { + wifiSecurity->setAuthAlg(NetworkManager::WirelessSecuritySetting::Leap); + } + } else { + wifiSecurity->setKeyMgmt(NetworkManager::WirelessSecuritySetting::WpaEap); + } + m_tmpConnectionUuid = settings->uuid(); + m_tmpDevicePath = device; + m_tmpSpecificPath = specificObject; + + // QPointer editor = new ConnectionEditorDialog(settings); + // editor->show(); + // KWindowSystem::setState(editor->winId(), NET::KeepAbove); + // KWindowSystem::forceActiveWindow(editor->winId()); + // connect(editor.data(), &ConnectionEditorDialog::accepted, + // [editor, this] () { + // addConnection(editor->setting()); + // }); + // connect(editor.data(), &ConnectionEditorDialog::finished, + // [editor] () { + // if (editor) { + // editor->deleteLater(); + // } + // }); + // editor->setModal(true); + // editor->show(); + } else { + if (securityType == NetworkManager::StaticWep) { + wifiSecurity->setKeyMgmt(NetworkManager::WirelessSecuritySetting::Wep); + wifiSecurity->setWepKey0(password); + // if (KWallet::Wallet::isEnabled()) { + // wifiSecurity->setWepKeyFlags(NetworkManager::Setting::AgentOwned); + // } + } else { + if (ap->mode() == NetworkManager::AccessPoint::Adhoc) { + wifiSecurity->setKeyMgmt(NetworkManager::WirelessSecuritySetting::WpaNone); + } else { + wifiSecurity->setKeyMgmt(NetworkManager::WirelessSecuritySetting::WpaPsk); + } + wifiSecurity->setPsk(password); + // if (KWallet::Wallet::isEnabled()) { + // wifiSecurity->setPskFlags(NetworkManager::Setting::AgentOwned); + // } + } + QDBusPendingReply reply = NetworkManager::addAndActivateConnection(settings->toMap(), device, specificObject); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); + watcher->setProperty("action", Handler::AddAndActivateConnection); + watcher->setProperty("connection", settings->name()); + connect(watcher, &QDBusPendingCallWatcher::finished, this, &Handler::replyFinished); + } + + settings.clear(); +} + +void Handler::addConnection(const NMVariantMapMap& map) +{ + QDBusPendingReply reply = NetworkManager::addConnection(map); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); + watcher->setProperty("action", AddConnection); + watcher->setProperty("connection", map.value("connection").value("id")); + connect(watcher, &QDBusPendingCallWatcher::finished, this, &Handler::replyFinished); +} + +void Handler::deactivateConnection(const QString& connection, const QString& device) +{ + NetworkManager::Connection::Ptr con = NetworkManager::findConnection(connection); + + if (!con) { + qWarning() << "Not possible to deactivate this connection"; + return; + } + + QDBusPendingReply<> reply; + for (const NetworkManager::ActiveConnection::Ptr &active : NetworkManager::activeConnections()) { + if (active->uuid() == con->uuid() && ((!active->devices().isEmpty() && active->devices().first() == device) || + active->vpn())) { + if (active->vpn()) { + reply = NetworkManager::deactivateConnection(active->path()); + } else { + NetworkManager::Device::Ptr device = NetworkManager::findNetworkInterface(active->devices().first()); + if (device) { + reply = device->disconnectInterface(); + } + } + } + } + + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); + watcher->setProperty("action", Handler::DeactivateConnection); + connect(watcher, &QDBusPendingCallWatcher::finished, this, &Handler::replyFinished); +} + +void Handler::disconnectAll() +{ + for (const NetworkManager::Device::Ptr &device : NetworkManager::networkInterfaces()) { + device->disconnectInterface(); + } +} + +void Handler::enableAirplaneMode(bool enable) +{ + if (enable) { + m_tmpWirelessEnabled = NetworkManager::isWirelessEnabled(); + m_tmpWwanEnabled = NetworkManager::isWwanEnabled(); + enableBluetooth(false); + enableWireless(false); + enableWwan(false); + } else { + enableBluetooth(true); + if (m_tmpWirelessEnabled) { + enableWireless(true); + } + if (m_tmpWwanEnabled) { + enableWwan(true); + } + } +} + +template +void makeDBusCall(const QDBusMessage &message, QObject *context, std::function)> func) +{ + QDBusPendingReply reply = QDBusConnection::systemBus().asyncCall(message); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, context); + QObject::connect(watcher, &QDBusPendingCallWatcher::finished, context, [func] (QDBusPendingCallWatcher *watcher) { + const QDBusPendingReply reply = *watcher; + if (!reply.isValid()) { + qWarning() << reply.error().message(); + return; + } + func(reply); + watcher->deleteLater(); + }); +} + +void setBluetoothEnabled(QString path, bool enabled) +{ + QDBusMessage message = QDBusMessage::createMethodCall("org.bluez", path, "org.freedesktop.DBus.Properties", "Set"); + QList arguments; + arguments << QLatin1String("org.bluez.Adapter1"); + arguments << QLatin1String("Powered"); + arguments << QVariant::fromValue(QDBusVariant(QVariant(enabled))); + message.setArguments(arguments); + QDBusConnection::systemBus().asyncCall(message); +} + +void Handler::enableBluetooth(bool enable) +{ + qDBusRegisterMetaType< QMap >(); + + const QDBusMessage getObjects = QDBusMessage::createMethodCall("org.bluez", "/", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); + + makeDBusCall>(getObjects, this, [enable, this](const auto reply) { + for (const QDBusObjectPath &path : reply.value().keys()) { + const QString objPath = path.path(); + qDebug() << "inspecting path" << objPath; + const QStringList interfaces = reply.value().value(path).keys(); + qDebug() << "interfaces:" << interfaces; + + if (!interfaces.contains("org.bluez.Adapter1")) { + continue; + } + + // We need to check previous state first + if (!enable) { + QDBusMessage getPowered = QDBusMessage::createMethodCall("org.bluez", objPath, "org.freedesktop.DBus.Properties", "Get"); + const QList arguments { QLatin1String("org.bluez.Adapter1"), QLatin1String("Powered") }; + getPowered.setArguments(arguments); + + makeDBusCall(getPowered, this, [objPath, this](const auto reply){ + m_bluetoothAdapters.insert(objPath, reply.value().toBool()); + setBluetoothEnabled(objPath, false); + }); + } else if (m_bluetoothAdapters.value(objPath)) { + setBluetoothEnabled(objPath, true); + } + } + }); +} + +void Handler::enableNetworking(bool enable) +{ + NetworkManager::setNetworkingEnabled(enable); +} + +void Handler::enableWireless(bool enable) +{ + NetworkManager::setWirelessEnabled(enable); +} + +void Handler::enableWwan(bool enable) +{ + NetworkManager::setWwanEnabled(enable); +} + +void Handler::removeConnection(const QString& connection) +{ + NetworkManager::Connection::Ptr con = NetworkManager::findConnection(connection); + + if (!con || con->uuid().isEmpty()) { + qWarning() << "Not possible to remove connection " << connection; + return; + } + + // Remove slave connections + for (const NetworkManager::Connection::Ptr &connection : NetworkManager::listConnections()) { + NetworkManager::ConnectionSettings::Ptr settings = connection->settings(); + if (settings->master() == con->uuid()) { + connection->remove(); + } + } + + QDBusPendingReply<> reply = con->remove(); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); + watcher->setProperty("action", Handler::RemoveConnection); + watcher->setProperty("connection", con->name()); + connect(watcher, &QDBusPendingCallWatcher::finished, this, &Handler::replyFinished); +} + +void Handler::updateConnection(const NetworkManager::Connection::Ptr& connection, const NMVariantMapMap& map) +{ + QDBusPendingReply<> reply = connection->update(map); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); + watcher->setProperty("action", UpdateConnection); + watcher->setProperty("connection", connection->name()); + connect(watcher, &QDBusPendingCallWatcher::finished, this, &Handler::replyFinished); +} + +void Handler::requestScan(const QString &interface) +{ + for (NetworkManager::Device::Ptr device : NetworkManager::networkInterfaces()) { + if (device->type() == NetworkManager::Device::Wifi) { + NetworkManager::WirelessDevice::Ptr wifiDevice = device.objectCast(); + + if (wifiDevice && wifiDevice->state() != NetworkManager::WirelessDevice::Unavailable) { + if (!interface.isEmpty() && interface != wifiDevice->interfaceName()) { + continue; + } + + if (!checkRequestScanRateLimit(wifiDevice)) { + QDateTime now = QDateTime::currentDateTime(); + // for NM < 1.12, lastScan is not available + QDateTime lastScan = wifiDevice->lastScan(); + QDateTime lastRequestScan = wifiDevice->lastRequestScan(); + // Compute the next time we can run a scan + int timeout = NM_REQUESTSCAN_LIMIT_RATE; + if (lastScan.isValid() && lastScan.msecsTo(now) < NM_REQUESTSCAN_LIMIT_RATE) { + timeout = NM_REQUESTSCAN_LIMIT_RATE - lastScan.msecsTo(now); + } else if (lastRequestScan.isValid() && lastRequestScan.msecsTo(now) < NM_REQUESTSCAN_LIMIT_RATE) { + timeout = NM_REQUESTSCAN_LIMIT_RATE - lastRequestScan.msecsTo(now); + } + qDebug() << "Rescheduling a request scan for" << wifiDevice->interfaceName() << "in" << timeout; + scheduleRequestScan(wifiDevice->interfaceName(), timeout); + + if (!interface.isEmpty()) { + return; + } + continue; + } else if (m_wirelessScanRetryTimer.contains(interface)){ + m_wirelessScanRetryTimer.value(interface)->stop(); + delete m_wirelessScanRetryTimer.take(interface); + } + + qDebug() << "Requesting wifi scan on device" << wifiDevice->interfaceName(); + QDBusPendingReply<> reply = wifiDevice->requestScan(); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); + watcher->setProperty("action", Handler::RequestScan); + watcher->setProperty("interface", wifiDevice->interfaceName()); + connect(watcher, &QDBusPendingCallWatcher::finished, this, &Handler::replyFinished); + } + } + } +} + +void Handler::createHotspot() +{ + bool foundInactive = false; + bool useApMode = false; + NetworkManager::WirelessDevice::Ptr wifiDev; + + NetworkManager::ConnectionSettings::Ptr connectionSettings; + connectionSettings = NetworkManager::ConnectionSettings::Ptr(new NetworkManager::ConnectionSettings(NetworkManager::ConnectionSettings::Wireless)); + + NetworkManager::WirelessSetting::Ptr wifiSetting = connectionSettings->setting(NetworkManager::Setting::Wireless).dynamicCast(); + wifiSetting->setMode(NetworkManager::WirelessSetting::Adhoc); + wifiSetting->setSsid(Configuration::self().hotspotName().toUtf8()); + + for (const NetworkManager::Device::Ptr &device : NetworkManager::networkInterfaces()) { + if (device->type() == NetworkManager::Device::Wifi) { + wifiDev = device.objectCast(); + if (wifiDev) { + if (!wifiDev->isActive()) { + foundInactive = true; + } else { + // Prefer previous device if it was inactive + if (foundInactive) { + break; + } + } + + if (wifiDev->wirelessCapabilities().testFlag(NetworkManager::WirelessDevice::ApCap)) { + useApMode = true; + } + + // We prefer inactive wireless card with AP capabilities + if (foundInactive && useApMode) { + break; + } + } + } + } + + if (!wifiDev) { + qWarning() << "Failed to create hotspot: missing wireless device"; + return; + } + + wifiSetting->setInitialized(true); + wifiSetting->setMode(useApMode ? NetworkManager::WirelessSetting::Ap :NetworkManager::WirelessSetting::Adhoc); + + if (!Configuration::self().hotspotPassword().isEmpty()) { + NetworkManager::WirelessSecuritySetting::Ptr wifiSecurity = connectionSettings->setting(NetworkManager::Setting::WirelessSecurity).dynamicCast(); + wifiSecurity->setInitialized(true); + + if (useApMode) { + // Use WPA2 + wifiSecurity->setKeyMgmt(NetworkManager::WirelessSecuritySetting::WpaPsk); + wifiSecurity->setPsk(Configuration::self().hotspotPassword()); + wifiSecurity->setPskFlags(NetworkManager::Setting::AgentOwned); + } else { + // Use WEP + wifiSecurity->setKeyMgmt(NetworkManager::WirelessSecuritySetting::Wep); + wifiSecurity->setWepKeyType(NetworkManager::WirelessSecuritySetting::Passphrase); + wifiSecurity->setWepTxKeyindex(0); + wifiSecurity->setWepKey0(Configuration::self().hotspotPassword()); + wifiSecurity->setWepKeyFlags(NetworkManager::Setting::AgentOwned); + wifiSecurity->setAuthAlg(NetworkManager::WirelessSecuritySetting::Open); + } + } + + NetworkManager::Ipv4Setting::Ptr ipv4Setting = connectionSettings->setting(NetworkManager::Setting::Ipv4).dynamicCast(); + ipv4Setting->setMethod(NetworkManager::Ipv4Setting::Shared); + ipv4Setting->setInitialized(true); + + connectionSettings->setId(Configuration::self().hotspotName()); + connectionSettings->setAutoconnect(false); + connectionSettings->setUuid(NetworkManager::ConnectionSettings::createNewUuid()); + + const QVariantMap options = { {QLatin1String("persist"), QLatin1String("volatile")} }; + + QDBusPendingReply reply = NetworkManager::addAndActivateConnection2(connectionSettings->toMap(), wifiDev->uni(), QString(), options); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); + watcher->setProperty("action", Handler::CreateHotspot); + watcher->setProperty("connection", Configuration::self().hotspotName()); + connect(watcher, &QDBusPendingCallWatcher::finished, this, &Handler::replyFinished); + connect(watcher, &QDBusPendingCallWatcher::finished, this, QOverload::of(&Handler::hotspotCreated)); +} + +void Handler::stopHotspot() +{ + const QString activeConnectionPath = Configuration::self().hotspotConnectionPath(); + + if (activeConnectionPath.isEmpty()) { + return; + } + + NetworkManager::ActiveConnection::Ptr hotspot = NetworkManager::findActiveConnection(activeConnectionPath); + + if (!hotspot) { + return; + } + + NetworkManager::deactivateConnection(activeConnectionPath); + Configuration::self().setHotspotConnectionPath(QString()); + + Q_EMIT hotspotDisabled(); +} + +bool Handler::checkRequestScanRateLimit(const NetworkManager::WirelessDevice::Ptr &wifiDevice) +{ + QDateTime now = QDateTime::currentDateTime(); + QDateTime lastScan = wifiDevice->lastScan(); + QDateTime lastRequestScan = wifiDevice->lastRequestScan(); + + // if the last scan finished within the last 10 seconds + bool ret = lastScan.isValid() && lastScan.msecsTo(now) < NM_REQUESTSCAN_LIMIT_RATE; + // or if the last Request was sent within the last 10 seconds + ret |= lastRequestScan.isValid() && lastRequestScan.msecsTo(now) < NM_REQUESTSCAN_LIMIT_RATE; + // skip the request scan + if (ret) { + qDebug() << "Last scan finished " << lastScan.msecsTo(now) << "ms ago and last request scan was sent " + << lastRequestScan.msecsTo(now) << "ms ago, Skipping scanning interface:" << wifiDevice->interfaceName(); + return false; + } + return true; +} + +bool Handler::checkHotspotSupported() +{ + if (NetworkManager::checkVersion(1, 16, 0)) { + bool unusedWifiFound = false; + bool wifiFound = false; + + for (const NetworkManager::Device::Ptr &device : NetworkManager::networkInterfaces()) { + if (device->type() == NetworkManager::Device::Wifi) { + wifiFound = true; + + NetworkManager::WirelessDevice::Ptr wifiDev = device.objectCast(); + if (wifiDev && !wifiDev->isActive()) { + unusedWifiFound = true; + } + } + } + + + if (!wifiFound) { + return false; + } + + if (unusedWifiFound) { + return true; + } + + // Check if the primary connection which is used for internet connectivity is not using WiFi + if (NetworkManager::primaryConnectionType() != NetworkManager::ConnectionSettings::Wireless) { + return true; + } + } + + return false; +} + +void Handler::scheduleRequestScan(const QString &interface, int timeout) +{ + QTimer *timer; + if (!m_wirelessScanRetryTimer.contains(interface)) { + // create a timer for the interface + timer = new QTimer(); + timer->setSingleShot(true); + m_wirelessScanRetryTimer.insert(interface, timer); + auto retryAction = [this, interface]() { + requestScan(interface); + }; + connect(timer, &QTimer::timeout, this, retryAction); + } else { + // set the new value for an existing timer + timer = m_wirelessScanRetryTimer.value(interface); + if (timer->isActive()) { + timer->stop(); + } + } + + // +1 ms is added to avoid having the scan being rejetted by nm + // because it is run at the exact last millisecond of the requestScan threshold + timer->setInterval(timeout + 1); + timer->start(); +} + +void Handler::scanRequestFailed(const QString &interface) +{ + scheduleRequestScan(interface, 2000); +} + +void Handler::secretAgentError(const QString &connectionPath, const QString &message) +{ + // If the password was wrong, forget it + removeConnection(connectionPath); + emit connectionActivationFailed(connectionPath, message); +} + +void Handler::replyFinished(QDBusPendingCallWatcher * watcher) +{ + // QDBusPendingReply<> reply = *watcher; + // if (reply.isError() || !reply.isValid()) { + // KNotification *notification = nullptr; + // QString error = reply.error().message(); + // Handler::HandlerAction action = (Handler::HandlerAction)watcher->property("action").toUInt(); + // switch (action) { + // case Handler::ActivateConnection: + // notification = new KNotification("FailedToActivateConnection", KNotification::CloseOnTimeout, this); + // notification->setTitle(i18n("Failed to activate %1", watcher->property("connection").toString())); + // break; + // case Handler::AddAndActivateConnection: + // notification = new KNotification("FailedToAddConnection", KNotification::CloseOnTimeout, this); + // notification->setTitle(i18n("Failed to add %1", watcher->property("connection").toString())); + // break; + // case Handler::AddConnection: + // notification = new KNotification("FailedToAddConnection", KNotification::CloseOnTimeout, this); + // notification->setTitle(i18n("Failed to add connection %1", watcher->property("connection").toString())); + // break; + // case Handler::DeactivateConnection: + // notification = new KNotification("FailedToDeactivateConnection", KNotification::CloseOnTimeout, this); + // notification->setTitle(i18n("Failed to deactivate %1", watcher->property("connection").toString())); + // break; + // case Handler::RemoveConnection: + // notification = new KNotification("FailedToRemoveConnection", KNotification::CloseOnTimeout, this); + // notification->setTitle(i18n("Failed to remove %1", watcher->property("connection").toString())); + // break; + // case Handler::UpdateConnection: + // notification = new KNotification("FailedToUpdateConnection", KNotification::CloseOnTimeout, this); + // notification->setTitle(i18n("Failed to update connection %1", watcher->property("connection").toString())); + // break; + // case Handler::RequestScan: + // { + // const QString interface = watcher->property("interface").toString(); + // qWarning() << "Wireless scan on" << interface << "failed:" << error; + // scanRequestFailed(interface); + // break; + // } + // case Handler::CreateHotspot: + // notification = new KNotification("FailedToCreateHotspot", KNotification::CloseOnTimeout, this); + // notification->setTitle(i18n("Failed to create hotspot %1", watcher->property("connection").toString())); + // break; + // default: + // break; + // } + + // if (notification) { + // notification->setComponentName("networkmanagement"); + // notification->setText(error); + // notification->setIconName(QStringLiteral("dialog-warning")); + // notification->sendEvent(); + // } + // } else { + // KNotification *notification = nullptr; + // Handler::HandlerAction action = (Handler::HandlerAction)watcher->property("action").toUInt(); + + // switch (action) { + // case Handler::AddConnection: + // notification = new KNotification("ConnectionAdded", KNotification::CloseOnTimeout, this); + // notification->setText(i18n("Connection %1 has been added", watcher->property("connection").toString())); + // break; + // case Handler::RemoveConnection: + // notification = new KNotification("ConnectionRemoved", KNotification::CloseOnTimeout, this); + // notification->setText(i18n("Connection %1 has been removed", watcher->property("connection").toString())); + // break; + // case Handler::UpdateConnection: + // notification = new KNotification("ConnectionUpdated", KNotification::CloseOnTimeout, this); + // notification->setText(i18n("Connection %1 has been updated", watcher->property("connection").toString())); + // break; + // case Handler::RequestScan: + // qDebug() << "Wireless scan on" << watcher->property("interface").toString() << "succeeded"; + // break; + // default: + // break; + // } + + // if (notification) { + // notification->setComponentName("networkmanagement"); + // notification->setTitle(watcher->property("connection").toString()); + // notification->setIconName(QStringLiteral("dialog-information")); + // notification->sendEvent(); + // } + // } + + watcher->deleteLater(); +} + +void Handler::hotspotCreated(QDBusPendingCallWatcher *watcher) +{ + QDBusPendingReply reply = *watcher; + + if (!reply.isError() && reply.isValid()) { + const QString activeConnectionPath = reply.argumentAt(1).value().path(); + + if (activeConnectionPath.isEmpty()) { + return; + } + + Configuration::self().setHotspotConnectionPath(activeConnectionPath); + + NetworkManager::ActiveConnection::Ptr hotspot = NetworkManager::findActiveConnection(activeConnectionPath); + + if (!hotspot) { + return; + } + + connect(hotspot.data(), &NetworkManager::ActiveConnection::stateChanged, [=] (NetworkManager::ActiveConnection::State state) { + if (state > NetworkManager::ActiveConnection::Activated) { + Configuration::self().setHotspotConnectionPath(QString()); + Q_EMIT hotspotDisabled(); + } + }); + + Q_EMIT hotspotCreated(); + } +} + +void Handler::primaryConnectionTypeChanged(NetworkManager::ConnectionSettings::ConnectionType type) +{ + Q_UNUSED(type) + m_hotspotSupported = checkHotspotSupported(); + Q_EMIT hotspotSupportedChanged(m_hotspotSupported); +} + +#if WITH_MODEMMANAGER_SUPPORT +void Handler::unlockRequiredChanged(MMModemLock modemLock) +{ + if (modemLock == MM_MODEM_LOCK_NONE) { + activateConnection(m_tmpConnectionPath, m_tmpDevicePath, m_tmpSpecificPath); + } +} +#endif + diff --git a/networkmanagement/handler.h b/networkmanagement/handler.h new file mode 100644 index 0000000..adbc123 --- /dev/null +++ b/networkmanagement/handler.h @@ -0,0 +1,161 @@ +/* + Copyright 2013-2014 Jan Grulich + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +*/ + +#ifndef PLASMA_NM_HANDLER_H +#define PLASMA_NM_HANDLER_H + +#include +#include + +#include +#include +#include +#include +#if WITH_MODEMMANAGER_SUPPORT +#include +#endif + +class Q_DECL_EXPORT Handler : public QObject +{ +Q_OBJECT + +public: + enum HandlerAction { + ActivateConnection, + AddAndActivateConnection, + AddConnection, + DeactivateConnection, + RemoveConnection, + RequestScan, + UpdateConnection, + CreateHotspot, + }; + + explicit Handler(QObject* parent = nullptr); + ~Handler() override; + + Q_PROPERTY(bool hotspotSupported READ hotspotSupported NOTIFY hotspotSupportedChanged); +public: + bool hotspotSupported() const { return m_hotspotSupported; }; + +public Q_SLOTS: + /** + * Activates given connection + * @connection - d-bus path of the connection you want to activate + * @device - d-bus path of the device where the connection should be activated + * @specificParameter - d-bus path of the specific object you want to use for this activation, i.e access point + */ + void activateConnection(const QString &connection, const QString &device, const QString &specificParameter); + /** + * Adds and activates a new wireless connection + * @device - d-bus path of the wireless device where the connection should be activated + * @specificParameter - d-bus path of the accesspoint you want to connect to + * @password - pre-filled password which should be used for the new wireless connection + * @autoConnect - boolean value whether this connection should be activated automatically when it's available + * + * Works automatically for wireless connections with WEP/WPA security, for wireless connections with WPA/WPA + * it will open the connection editor for advanced configuration. + * */ + void addAndActivateConnection(const QString &device, const QString &specificParameter, const QString &password = QString()); + + /** + * Returns a code that includes the credentials to a said wifi connection + * Here's some information on how this information is created, it's generally used to put in QR codes to share. + * https://github.com/zxing/zxing/wiki/Barcode-Contents#wi-fi-network-config-android-ios-11 + * + * @param connectionPath the d-bus path to the connection we want to read + * @param ssid the name of the network being displayed + * @param securityType the authentication protocol used for this specific ssid + */ + QString wifiCode(const QString& connectionPath, const QString& ssid, /*NetworkManager::WirelessSecurityType*/ int securityType) const; + + /** + * Adds a new connection + * @map - NMVariantMapMap with connection settings + */ + void addConnection(const NMVariantMapMap &map); + /** + * Deactivates given connection + * @connection - d-bus path of the connection you want to deactivate + * @device - d-bus path of the connection where the connection is activated + */ + void deactivateConnection(const QString &connection, const QString &device); + /** + * Disconnects all connections + */ + void disconnectAll(); + void enableAirplaneMode(bool enable); + void enableNetworking(bool enable); + void enableWireless(bool enable); + + void enableWwan(bool enable); + + /** + * Removes given connection + * @connection - d-bus path of the connection you want to edit + */ + void removeConnection(const QString & connection); + /** + * Updates given connection + * @connection - connection which should be updated + * @map - NMVariantMapMap with new connection settings + */ + void updateConnection(const NetworkManager::Connection::Ptr &connection, const NMVariantMapMap &map); + void requestScan(const QString &interface = QString()); + + void createHotspot(); + void stopHotspot(); + +private Q_SLOTS: + void secretAgentError(const QString &connectionPath, const QString &message); + void replyFinished(QDBusPendingCallWatcher *watcher); + void hotspotCreated(QDBusPendingCallWatcher *watcher); + void primaryConnectionTypeChanged(NetworkManager::ConnectionSettings::ConnectionType type); +#if WITH_MODEMMANAGER_SUPPORT + void unlockRequiredChanged(MMModemLock modemLock); +#endif + +Q_SIGNALS: + void connectionActivationFailed(const QString &connectionPath, const QString &message); + void hotspotCreated(); + void hotspotDisabled(); + void hotspotSupportedChanged(bool hotspotSupported); +private: + QString m_userName; + bool m_hotspotSupported; + bool m_tmpWirelessEnabled; + bool m_tmpWwanEnabled; +#if WITH_MODEMMANAGER_SUPPORT + QString m_tmpConnectionPath; +#endif + QString m_tmpConnectionUuid; + QString m_tmpDevicePath; + QString m_tmpSpecificPath; + QMap m_bluetoothAdapters; + QMap m_wirelessScanRetryTimer; + + void enableBluetooth(bool enable); + void scanRequestFailed(const QString &interface); + bool checkRequestScanRateLimit(const NetworkManager::WirelessDevice::Ptr &wifiDevice); + bool checkHotspotSupported(); + void scheduleRequestScan(const QString &interface, int timeout); +}; + +#endif // PLASMA_NM_HANDLER_H diff --git a/networkmanagement/networking.cpp b/networkmanagement/networking.cpp deleted file mode 100644 index 4829c5e..0000000 --- a/networkmanagement/networking.cpp +++ /dev/null @@ -1,525 +0,0 @@ -/* - Copyright (C) 2019 Pier Luigi Fiorini - Copyright 2013-2014 Jan Grulich - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 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 6 of version 3 of the license. - This library 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 - Lesser General Public License for more details. - You should have received a copy of the GNU Lesser General Public - License along with this library. If not, see . -*/ - -#include -#include -#include -#include - -#include - -#if WITH_MODEMMANAGER_SUPPORT -# include -# include -# include -#endif - -#include "uiutils.h" -#include "networking.h" -#include "networkmodel.h" - -#include -#include - -#include - -Networking::Networking(QObject *parent) - : QObject(parent) - , m_lastWirelessEnabled(isWirelessEnabled()) - , m_lastMobileEnabled(isMobileEnabled()) -{ - ::passwd *pw = ::getpwuid(::getuid()); - m_userName = QString::fromLocal8Bit(pw->pw_name); - - connect(NetworkManager::notifier(), &NetworkManager::Notifier::networkingEnabledChanged, - this, &Networking::enabledChanged); - connect(NetworkManager::notifier(), &NetworkManager::Notifier::wirelessEnabledChanged, - this, &Networking::wirelessEnabledChanged); - connect(NetworkManager::notifier(), &NetworkManager::Notifier::wirelessHardwareEnabledChanged, - this, &Networking::wirelessHardwareEnabledChanged); - connect(NetworkManager::notifier(), &NetworkManager::Notifier::wwanEnabledChanged, - this, &Networking::mobileEnabledChanged); - connect(NetworkManager::notifier(), &NetworkManager::Notifier::wwanHardwareEnabledChanged, - this, &Networking::mobileHardwareEnabledChanged); - - connect(NetworkManager::notifier(), &NetworkManager::Notifier::statusChanged, - this, &Networking::statusChanged); - doChangeActiveConnections(); - statusChanged(NetworkManager::status()); -} - -bool Networking::isEnabled() const -{ - return NetworkManager::isNetworkingEnabled(); -} - -void Networking::setEnabled(bool enabled) -{ - NetworkManager::setNetworkingEnabled(enabled); -} - -bool Networking::isWirelessEnabled() const -{ - return NetworkManager::isWirelessEnabled(); -} - -void Networking::setWirelessEnabled(bool enabled) -{ - NetworkManager::setWirelessEnabled(enabled); -} - -bool Networking::isWirelessHardwareEnabled() const -{ - return NetworkManager::isWirelessHardwareEnabled(); -} - -bool Networking::isMobileEnabled() const -{ - return NetworkManager::isWwanEnabled(); -} - -void Networking::setMobileEnabled(bool enabled) -{ - NetworkManager::setWwanEnabled(enabled); -} - -bool Networking::isMobileHardwareEnabled() const -{ - return NetworkManager::isWwanHardwareEnabled(); -} - -bool Networking::isAirplaneModeEnabled() const -{ - return !isWirelessEnabled() && !isMobileEnabled(); -} - -void Networking::setAirplaneModeEnabled(bool enabled) -{ - if (isAirplaneModeEnabled() == enabled) - return; - - m_lastWirelessEnabled = isWirelessEnabled(); - m_lastMobileEnabled = isMobileEnabled(); - - if (enabled) { - setWirelessEnabled(false); - setMobileEnabled(false); - } else { - if (m_lastWirelessEnabled) - setWirelessEnabled(true); - if (m_lastMobileEnabled) - setMobileEnabled(true); - } - - Q_EMIT airplaneModeEnabledChanged(); -} - -QString Networking::activeConnections() const -{ - return m_activeConnections; -} - -QString Networking::networkStatus() const -{ - return m_networkStatus; -} - -void Networking::activateConnection(const QString &connectionPath, const QString &device, const QString &specificObject) -{ - NetworkManager::Connection::Ptr connection = NetworkManager::findConnection(connectionPath); - - if (!connection) { - qCWarning(gLcNm, "Unable to activate connection \"%s\"", qPrintable(connectionPath)); - return; - } - - if (connection->settings()->connectionType() == NetworkManager::ConnectionSettings::Vpn) { - NetworkManager::VpnSetting::Ptr vpnSetting = connection->settings()->setting(NetworkManager::Setting::Vpn).staticCast(); - if (vpnSetting) { - qCDebug(gLcNm, "Checking VPN \"%s\" type \"%s\"", qPrintable(connection->name()), qPrintable(vpnSetting->serviceType())); - } - } - -#if 0 -#if WITH_MODEMMANAGER_SUPPORT - if (connection->settings()->connectionType() == NetworkManager::ConnectionSettings::Gsm) { - NetworkManager::ModemDevice::Ptr nmModemDevice = NetworkManager::findNetworkInterface(device).objectCast(); - if (nmModemDevice) { - ModemManager::ModemDevice::Ptr mmModemDevice = ModemManager::findModemDevice(nmModemDevice->udi()); - if (mmModemDevice) { - ModemManager::Modem::Ptr modem = mmModemDevice->interface(ModemManager::ModemDevice::ModemInterface).objectCast(); - NetworkManager::GsmSetting::Ptr gsmSetting = connection->settings()->setting(NetworkManager::Setting::Gsm).staticCast(); - if (gsmSetting && gsmSetting->pinFlags() == NetworkManager::Setting::NotSaved && - modem && modem->unlockRequired() > MM_MODEM_LOCK_NONE) { - QDBusInterface managerIface("org.kde.plasmanetworkmanagement", "/org/kde/plasmanetworkmanagement", "org.kde.plasmanetworkmanagement", QDBusConnection::sessionBus(), this); - managerIface.call("unlockModem", mmModemDevice->uni()); - connect(modem.data(), &ModemManager::Modem::unlockRequiredChanged, this, &Handler::unlockRequiredChanged); - // m_tmpConnectionPath = connectionPath; - // m_tmpDevicePath = device; - // m_tmpSpecificPath = specificObject; - return; - } - } - } - } -#endif -#endif - QDBusPendingReply reply = NetworkManager::activateConnection(connectionPath, device, specificObject); - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); - watcher->setProperty("connectionName", connection->name()); - connect(watcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *self) { - QDBusPendingReply<> reply = *self; - - if (reply.isError() || !reply.isValid()) { - const QString error = reply.error().message(); - const QString connectionName = self->property("connectionName").toString(); - } - - self->deleteLater(); - }); -} - -void Networking::addAndActivateConnection(const QString &device, const QString &specificObject, const QString &password) -{ - NetworkManager::AccessPoint::Ptr ap; - NetworkManager::WirelessDevice::Ptr wifiDev; - for (const NetworkManager::Device::Ptr &dev : NetworkManager::networkInterfaces()) { - if (dev->type() == NetworkManager::Device::Wifi) { - wifiDev = dev.objectCast(); - ap = wifiDev->findAccessPoint(specificObject); - if (ap) - break; - } - } - - if (!ap) - return; - - NetworkManager::ConnectionSettings::Ptr settings = NetworkManager::ConnectionSettings::Ptr(new NetworkManager::ConnectionSettings(NetworkManager::ConnectionSettings::Wireless)); - settings->setId(ap->ssid()); - settings->setUuid(NetworkManager::ConnectionSettings::createNewUuid()); - settings->setAutoconnect(true); - settings->addToPermissions(m_userName, QString()); - - NetworkManager::WirelessSetting::Ptr wifiSetting = settings->setting(NetworkManager::Setting::Wireless).dynamicCast(); - wifiSetting->setInitialized(true); - wifiSetting = settings->setting(NetworkManager::Setting::Wireless).dynamicCast(); - wifiSetting->setSsid(ap->ssid().toUtf8()); - if (ap->mode() == NetworkManager::AccessPoint::Adhoc) { - wifiSetting->setMode(NetworkManager::WirelessSetting::Adhoc); - } - - NetworkManager::WirelessSecuritySetting::Ptr wifiSecurity = settings->setting(NetworkManager::Setting::WirelessSecurity).dynamicCast(); - NetworkManager::WirelessSecurityType securityType = NetworkManager::findBestWirelessSecurity(wifiDev->wirelessCapabilities(), true, (ap->mode() == NetworkManager::AccessPoint::Adhoc), ap->capabilities(), ap->wpaFlags(), ap->rsnFlags()); - - if (securityType != NetworkManager::NoneSecurity) { - wifiSecurity->setInitialized(true); - wifiSetting->setSecurity("802-11-wireless-security"); - } - - if (securityType == NetworkManager::Leap || - securityType == NetworkManager::DynamicWep || - securityType == NetworkManager::Wpa2Eap || - securityType == NetworkManager::WpaEap) { - if (securityType == NetworkManager::DynamicWep || securityType == NetworkManager::Leap) { - wifiSecurity->setKeyMgmt(NetworkManager::WirelessSecuritySetting::Ieee8021x); - if (securityType == NetworkManager::Leap) - wifiSecurity->setAuthAlg(NetworkManager::WirelessSecuritySetting::Leap); - } else { - wifiSecurity->setKeyMgmt(NetworkManager::WirelessSecuritySetting::WpaEap); - } - // m_tmpConnectionUuid = settings->uuid(); - // m_tmpDevicePath = device; - // m_tmpSpecificPath = specificObject; - - // TODO: Edit connection? - } else { - if (securityType == NetworkManager::StaticWep) { - wifiSecurity->setKeyMgmt(NetworkManager::WirelessSecuritySetting::Wep); - wifiSecurity->setWepKey0(password); -#if 0 - if (KWallet::Wallet::isEnabled()) - wifiSecurity->setWepKeyFlags(NetworkManager::Setting::AgentOwned); -#endif - } else { - if (ap->mode() == NetworkManager::AccessPoint::Adhoc) - wifiSecurity->setKeyMgmt(NetworkManager::WirelessSecuritySetting::WpaNone); - else - wifiSecurity->setKeyMgmt(NetworkManager::WirelessSecuritySetting::WpaPsk); - wifiSecurity->setPsk(password); -#if 0 - if (KWallet::Wallet::isEnabled()) - wifiSecurity->setPskFlags(NetworkManager::Setting::AgentOwned); -#endif - } - - QDBusPendingReply reply = NetworkManager::addAndActivateConnection(settings->toMap(), device, specificObject); - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); - watcher->setProperty("connectionName", settings->name()); - connect(watcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *self) { - QDBusPendingReply<> reply = *self; - - if (reply.isError() || !reply.isValid()) { - const QString error = reply.error().message(); - const QString connectionName = self->property("connectionName").toString(); - } - - self->deleteLater(); - }); - } - - settings.clear(); -} - -void Networking::deactivateConnection(const QString &connectionName, const QString &device) -{ - NetworkManager::Connection::Ptr connection = NetworkManager::findConnection(connectionName); - - if (!connection) { - qCWarning(gLcNm, "Failed to deactivate connection \"%s\"", qPrintable(connectionName)); - return; - } - - QDBusPendingReply<> reply; - for (const NetworkManager::ActiveConnection::Ptr &active : NetworkManager::activeConnections()) { - if (active->uuid() == connection->uuid() && ((!active->devices().isEmpty() && active->devices().first() == device) || - active->vpn())) { - if (active->vpn()) { - reply = NetworkManager::deactivateConnection(active->path()); - } else { - NetworkManager::Device::Ptr device = NetworkManager::findNetworkInterface(active->devices().first()); - if (device) - reply = device->disconnectInterface(); - } - } - } - - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); - connect(watcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *self) { - QDBusPendingReply<> reply = *self; - - if (reply.isError() || !reply.isValid()) { - const QString error = reply.error().message(); - const QString connectionName = self->property("connectionName").toString(); - } - - self->deleteLater(); - }); -} - -void Networking::removeConnection(const QString &connectionPath) -{ - NetworkManager::Connection::Ptr con = NetworkManager::findConnection(connectionPath); - - if (!con || con->uuid().isEmpty()) { - qCWarning(gLcNm) << "Not possible to remove connection " << connectionPath; - return; - } - - // Remove slave connections - for (const NetworkManager::Connection::Ptr &connection : NetworkManager::listConnections()) { - NetworkManager::ConnectionSettings::Ptr settings = connection->settings(); - if (settings->master() == con->uuid()) { - connection->remove(); - } - } - - QDBusPendingReply<> reply = con->remove(); - // QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); - // watcher->setProperty("action", Networking::RemoveConnection); - // watcher->setProperty("connection", con->name()); - // connect(watcher, &QDBusPendingCallWatcher::finished, this, [=] (QDBusPendingCallWatcher * watcher) { - // }); -} - -Networking::SortedConnectionType Networking::connectionTypeToSortedType(NetworkManager::ConnectionSettings::ConnectionType type) -{ - switch (type) { - case NetworkManager::ConnectionSettings::Adsl: - return Networking::Adsl; - break; - case NetworkManager::ConnectionSettings::Bluetooth: - return Networking::Bluetooth; - break; - case NetworkManager::ConnectionSettings::Cdma: - return Networking::Cdma; - break; - case NetworkManager::ConnectionSettings::Gsm: - return Networking::Gsm; - break; - case NetworkManager::ConnectionSettings::Infiniband: - return Networking::Infiniband; - break; - case NetworkManager::ConnectionSettings::OLPCMesh: - return Networking::OLPCMesh; - break; - case NetworkManager::ConnectionSettings::Pppoe: - return Networking::Pppoe; - break; - case NetworkManager::ConnectionSettings::Vpn: - return Networking::Vpn; - break; - case NetworkManager::ConnectionSettings::Wired: - return Networking::Wired; - break; - case NetworkManager::ConnectionSettings::Wireless: - return Networking::Wireless; - break; - default: - return Networking::Other; - break; - } -} - -void Networking::doChangeActiveConnections() -{ - for (const NetworkManager::ActiveConnection::Ptr &active : NetworkManager::activeConnections()) { - connect(active.data(), &NetworkManager::ActiveConnection::default4Changed, - this, &Networking::defaultChanged, - Qt::UniqueConnection); - connect(active.data(), &NetworkManager::ActiveConnection::default6Changed, - this, &Networking::defaultChanged, - Qt::UniqueConnection); - connect(active.data(), &NetworkManager::ActiveConnection::stateChanged, - this, &Networking::changeActiveConnections); - } - - changeActiveConnections(); -} - -QString Networking::checkUnknownReason() const -{ - // Check if NetworkManager is running. - if (!QDBusConnection::systemBus().interface()->isServiceRegistered(QLatin1String(NM_DBUS_INTERFACE))) - return tr("NetworkManager not running"); - - // Check for compatible NetworkManager version. - if (NetworkManager::compareVersion(0, 9, 8) < 0) - return tr("NetworkManager 0.9.8 required, found %1").arg(NetworkManager::version()); - - return tr("Unknown"); -} - -void Networking::statusChanged(NetworkManager::Status status) -{ - switch (status) { - case NetworkManager::ConnectedLinkLocal: - case NetworkManager::ConnectedSiteOnly: - case NetworkManager::Connected: - m_networkStatus = tr("Connected"); - break; - case NetworkManager::Asleep: - m_networkStatus = tr("Inactive"); - break; - case NetworkManager::Disconnected: - m_networkStatus = tr("Disconnected"); - break; - case NetworkManager::Disconnecting: - m_networkStatus = tr("Disconnecting"); - break; - case NetworkManager::Connecting: - m_networkStatus = tr("Connecting"); - break; - default: - m_networkStatus = checkUnknownReason(); - break; - } - - if (status == NetworkManager::ConnectedLinkLocal || - status == NetworkManager::ConnectedSiteOnly || - status == NetworkManager::Connected) { - changeActiveConnections(); - } else { - m_activeConnections = m_networkStatus; - Q_EMIT activeConnectionsChanged(); - } - - Q_EMIT networkStatusChanged(); -} - -void Networking::changeActiveConnections() -{ - if (NetworkManager::status() != NetworkManager::Connected && - NetworkManager::status() != NetworkManager::ConnectedLinkLocal && - NetworkManager::status() != NetworkManager::ConnectedSiteOnly) - return; - - QString activeConnections; - const QString format = tr("%1: %2"); - - QList activeConnectionList = NetworkManager::activeConnections(); - std::sort(activeConnectionList.begin(), activeConnectionList.end(), [](const NetworkManager::ActiveConnection::Ptr &left, const NetworkManager::ActiveConnection::Ptr &right) { - return Networking::connectionTypeToSortedType(left->type()) < Networking::connectionTypeToSortedType(right->type()); - }); - - for (const NetworkManager::ActiveConnection::Ptr &active : activeConnectionList) { - if (!active->devices().isEmpty() && UiUtils::isConnectionTypeSupported(active->type())) { - NetworkManager::Device::Ptr device = NetworkManager::findNetworkInterface(active->devices().first()); - if (device && device->type() != NetworkManager::Device::Generic && device->type() <= NetworkManager::Device::Team) { - bool connecting = false; - bool connected = false; - QString conType; - QString status; - NetworkManager::VpnConnection::Ptr vpnConnection; - - if (active->vpn()) { - conType = tr("VPN"); - vpnConnection = active.objectCast(); - } else { - conType = UiUtils::interfaceTypeLabel(device->type(), device); - } - - if (vpnConnection && active->vpn()) { - if (vpnConnection->state() >= NetworkManager::VpnConnection::Prepare && - vpnConnection->state() <= NetworkManager::VpnConnection::GettingIpConfig) - connecting = true; - else if (vpnConnection->state() == NetworkManager::VpnConnection::Activated) - connected = true; - } else { - if (active->state() == NetworkManager::ActiveConnection::Activated) - connected = true; - else if (active->state() == NetworkManager::ActiveConnection::Activating) - connecting = true; - } - - NetworkManager::Connection::Ptr connection = active->connection(); - if (connecting) { - status = tr("Connecting to %1").arg(connection->name()); - } else if (connected) { - status = tr("Connected to %1").arg(connection->name()); - } - - if (!activeConnections.isEmpty()) - activeConnections += QLatin1Char('\n'); - activeConnections += format.arg(conType, status); - - connect(connection.data(), &NetworkManager::Connection::updated, - this, &Networking::changeActiveConnections, - Qt::UniqueConnection); - } - } - } - - m_activeConnections = activeConnections; - Q_EMIT activeConnectionsChanged(); -} - -void Networking::defaultChanged() -{ - statusChanged(NetworkManager::status()); -} diff --git a/networkmanagement/networking.h b/networkmanagement/networking.h deleted file mode 100644 index 02d47a3..0000000 --- a/networkmanagement/networking.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - Copyright (C) 2019 Pier Luigi Fiorini - Copyright 2013-2014 Jan Grulich - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 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 6 of version 3 of the license. - This library 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 - Lesser General Public License for more details. - You should have received a copy of the GNU Lesser General Public - License along with this library. If not, see . -*/ - -#ifndef NETWORKING_H -#define NETWORKING_H - -#include -#include - -#include -#include - -class NETWORKMANAGER_EXPORT Networking : public QObject -{ - Q_OBJECT - Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged) - Q_PROPERTY(bool wirelessEnabled READ isWirelessEnabled WRITE setWirelessEnabled NOTIFY wirelessEnabledChanged) - Q_PROPERTY(bool wirelessHardwareEnabled READ isWirelessHardwareEnabled NOTIFY wirelessHardwareEnabledChanged) - Q_PROPERTY(bool mobileEnabled READ isMobileEnabled WRITE setMobileEnabled NOTIFY mobileEnabledChanged) - Q_PROPERTY(bool mobileHardwareEnabled READ isMobileHardwareEnabled NOTIFY mobileHardwareEnabledChanged) - Q_PROPERTY(bool airplaneModeEnabled READ isAirplaneModeEnabled WRITE setAirplaneModeEnabled NOTIFY airplaneModeEnabledChanged) - Q_PROPERTY(QString activeConnections READ activeConnections NOTIFY activeConnectionsChanged) - Q_PROPERTY(QString networkStatus READ networkStatus NOTIFY networkStatusChanged) - -public: - enum SortedConnectionType { - Wired, - Wireless, - Gsm, - Cdma, - Pppoe, - Adsl, - Infiniband, - OLPCMesh, - Bluetooth, - Vpn, - Other - }; - Q_ENUM(SortedConnectionType) - - enum HandlerAction { - ActivateConnection, - AddAndActivateConnection, - AddConnection, - DeactivateConnection, - RemoveConnection, - RequestScan, - UpdateConnection, - CreateHotspot, - }; - Q_ENUM(HandlerAction) - - explicit Networking(QObject *parent = nullptr); - - bool isEnabled() const; - void setEnabled(bool enabled); - - bool isWirelessEnabled() const; - void setWirelessEnabled(bool enabled); - - bool isWirelessHardwareEnabled() const; - - bool isMobileEnabled() const; - void setMobileEnabled(bool enabled); - - bool isMobileHardwareEnabled() const; - - bool isAirplaneModeEnabled() const; - void setAirplaneModeEnabled(bool enabled); - - QString activeConnections() const; - QString networkStatus() const; - - Q_INVOKABLE void activateConnection(const QString &connectionPath, const QString &device, const QString &specificObject); - Q_INVOKABLE void addAndActivateConnection(const QString &device, const QString &specificObject, const QString &password = QString()); - Q_INVOKABLE void deactivateConnection(const QString &connectionName, const QString &device); - Q_INVOKABLE void removeConnection(const QString &connectionPath); - - static SortedConnectionType connectionTypeToSortedType(NetworkManager::ConnectionSettings::ConnectionType type); - -Q_SIGNALS: - void enabledChanged(); - void wirelessEnabledChanged(); - void wirelessHardwareEnabledChanged(); - void mobileEnabledChanged(); - void mobileHardwareEnabledChanged(); - void airplaneModeEnabledChanged(); - void activeConnectionsChanged(); - void networkStatusChanged(); - -private: - bool m_lastWirelessEnabled = false; - bool m_lastMobileEnabled = false; - QString m_userName; - QString m_activeConnections; - QString m_networkStatus; - - void doChangeActiveConnections(); - QString checkUnknownReason() const; - -private Q_SLOTS: - void statusChanged(NetworkManager::Status status); - void changeActiveConnections(); - void defaultChanged(); -}; - -#endif // NETWORKING_H diff --git a/networkmanagement/qmlplugins.cpp b/networkmanagement/qmlplugins.cpp index 1bfe79a..bade686 100644 --- a/networkmanagement/qmlplugins.cpp +++ b/networkmanagement/qmlplugins.cpp @@ -1,5 +1,4 @@ #include "qmlplugins.h" -#include "networking.h" #include "networkmodel.h" #include "networkmodelitem.h" #include "appletproxymodel.h" @@ -8,6 +7,10 @@ #include "connectionicon.h" #include "network.h" #include "identitymodel.h" +#include "handler.h" +#include "enabledconnections.h" +#include "enums.h" +#include "wifisettings.h" #include @@ -16,11 +19,14 @@ void QmlPlugins::registerTypes(const char* uri) qmlRegisterUncreatableType(uri, 1, 0, "NetworkModelItem", QLatin1String("Cannot instantiate NetworkModelItem")); qmlRegisterType(uri, 1, 0, "AppletProxyModel"); - qmlRegisterType(uri, 1, 0, "Networking"); qmlRegisterType(uri, 1, 0, "NetworkModel"); qmlRegisterType(uri, 1, 0, "TechnologyProxyModel"); qmlRegisterType(uri, 1, 0, "WirelessItemSettings"); qmlRegisterType(uri, 1, 0, "ConnectionIcon"); qmlRegisterType(uri, 1, 0, "Network"); qmlRegisterType(uri, 1, 0, "IdentityModel"); + qmlRegisterType(uri, 1, 0, "Handler"); + qmlRegisterType(uri, 1, 0, "EnabledConnections"); + qmlRegisterType(uri, 1, 0, "WifiSettings"); + qmlRegisterUncreatableType(uri, 1, 0, "Enums", "You cannot create Enums on yourself"); } \ No newline at end of file diff --git a/networkmanagement/wifisettings.cpp b/networkmanagement/wifisettings.cpp new file mode 100644 index 0000000..82a7f3a --- /dev/null +++ b/networkmanagement/wifisettings.cpp @@ -0,0 +1,290 @@ +/* + * Copyright 2018 Martin Kacej + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 or + * (at your option) any later version. + * + * 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 Library General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "wifisettings.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +WifiSettings::WifiSettings(QObject* parent) : QObject(parent) +{ +} + +WifiSettings::~WifiSettings() +{ +} + +QVariantMap WifiSettings::getConnectionSettings(const QString &connection, const QString &type) +{ + if (type.isEmpty()) + return QVariantMap(); + + NetworkManager::Connection::Ptr con = NetworkManager::findConnection(connection); + if (!con) + return QVariantMap(); + + if (type == "secrets") + return con->secrets(QLatin1String("802-11-wireless-security")).value().value(QLatin1String("802-11-wireless-security")); + + QVariantMap map = con->settings()->toMap().value(type); + if (type == "ipv4") { + NetworkManager::Ipv4Setting::Ptr ipSettings = NetworkManager::Ipv4Setting::Ptr(new NetworkManager::Ipv4Setting()); + ipSettings->fromMap(map); + map.clear(); + if (ipSettings->method() == NetworkManager::Ipv4Setting::Automatic) { + map.insert(QLatin1String("method"),QVariant(QLatin1String("auto"))); + } + + if (ipSettings->method() == NetworkManager::Ipv4Setting::Manual) { + map.insert(QLatin1String("method"),QVariant(QLatin1String("manual"))); + map.insert(QLatin1String("address"),QVariant(ipSettings->addresses().first().ip().toString())); + map.insert(QLatin1String("prefix"),QVariant(ipSettings->addresses().first().prefixLength())); + map.insert(QLatin1String("gateway"),QVariant(ipSettings->addresses().first().gateway().toString())); + map.insert(QLatin1String("dns"),QVariant(ipSettings->dns().first().toString())); + } + } + return map; +} + +QVariantMap WifiSettings::getActiveConnectionInfo(const QString &connection) +{ + if (connection.isEmpty()) + return QVariantMap(); + + NetworkManager::ActiveConnection::Ptr activeCon; + NetworkManager::Connection::Ptr con = NetworkManager::findConnection(connection); + foreach (const NetworkManager::ActiveConnection::Ptr &active, NetworkManager::activeConnections()) { + if (active->uuid() == con->uuid()) + activeCon = active; + } + + if (!activeCon) { + qWarning() << "Active" << connection << "not found"; + return QVariantMap(); + } + + QVariantMap map; + if (activeCon->ipV4Config().addresses().count() > 0) { + map.insert("address",QVariant(activeCon->ipV4Config().addresses().first().ip().toString())); + map.insert("prefix",QVariant(activeCon->ipV4Config().addresses().first().netmask().toString())); + } + map.insert("gateway",QVariant(activeCon->ipV4Config().gateway())); + if (activeCon->ipV4Config().nameservers().count() > 0) + map.insert("dns",QVariant(activeCon->ipV4Config().nameservers().first().toString())); + //qWarning() << map; + return map; +} + +void WifiSettings::addConnectionFromQML(const QVariantMap &QMLmap) +{ + if (QMLmap.isEmpty()) + return; + + NetworkManager::ConnectionSettings::Ptr connectionSettings = NetworkManager::ConnectionSettings::Ptr(new NetworkManager::ConnectionSettings(NetworkManager::ConnectionSettings::Wireless)); + connectionSettings->setId(QMLmap.value(QLatin1String("id")).toString()); + connectionSettings->setUuid(NetworkManager::ConnectionSettings::createNewUuid()); + + NetworkManager::WirelessSetting::Ptr wirelessSettings = NetworkManager::WirelessSetting::Ptr(new NetworkManager::WirelessSetting()); + wirelessSettings->setSsid(QMLmap.value(QLatin1String("id")).toString().toUtf8()); + if (QMLmap["mode"].toString() == "infrastructure") { + wirelessSettings->setMode(NetworkManager::WirelessSetting::Infrastructure); + connectionSettings->setAutoconnect(true); + } + if (QMLmap["mode"].toString() == "ap") { + wirelessSettings->setMode(NetworkManager::WirelessSetting::Ap); + connectionSettings->setAutoconnect(false); + } + if (QMLmap.contains("hidden")) { + wirelessSettings->setHidden(QMLmap.value("hidden").toBool()); + } + + NetworkManager::Ipv4Setting::Ptr ipSettings = NetworkManager::Ipv4Setting::Ptr(new NetworkManager::Ipv4Setting()); + if (QMLmap["method"] == QLatin1String("auto")) { + ipSettings->setMethod(NetworkManager::Ipv4Setting::ConfigMethod::Automatic); + } + if (QMLmap["method"] == QLatin1String("shared")) { + ipSettings->setMethod(NetworkManager::Ipv4Setting::ConfigMethod::Shared); + } + if (QMLmap["method"] == QLatin1String("manual")) { + ipSettings->setMethod(NetworkManager::Ipv4Setting::ConfigMethod::Manual); + NetworkManager::IpAddress ipaddr; + ipaddr.setIp(QHostAddress(QMLmap["address"].toString())); + ipaddr.setPrefixLength(QMLmap["prefix"].toInt()); + ipaddr.setGateway(QHostAddress(QMLmap["gateway"].toString())); + ipSettings->setAddresses(QList({ipaddr})); + ipSettings->setDns(QList({QHostAddress(QMLmap["dns"].toString())})); + } + + NMVariantMapMap map = connectionSettings->toMap(); + map.insert("802-11-wireless",wirelessSettings->toMap()); + map.insert("ipv4",ipSettings->toMap()); + + // TODO can't set password for AP + // needs further inspection + + if (QMLmap.contains("802-11-wireless-security")) { + QVariantMap securMap = QMLmap["802-11-wireless-security"].toMap(); + int type = securMap["type"].toInt(); + if (!type == NetworkManager::NoneSecurity) { + NetworkManager::WirelessSecuritySetting::Ptr securitySettings = NetworkManager::WirelessSecuritySetting::Ptr(new NetworkManager::WirelessSecuritySetting()); + if (type == NetworkManager::Wpa2Psk ) { + if (QMLmap["mode"].toString() == "ap") { + securitySettings->setKeyMgmt(NetworkManager::WirelessSecuritySetting::KeyMgmt::WpaNone); + } else { + securitySettings->setKeyMgmt(NetworkManager::WirelessSecuritySetting::KeyMgmt::WpaPsk); + } + securitySettings->setAuthAlg(NetworkManager::WirelessSecuritySetting::AuthAlg::Open); + securitySettings->setPskFlags(NetworkManager::Setting::SecretFlagType::AgentOwned); + securitySettings->setPsk(securMap["password"].toString()); + } + if (type == NetworkManager::StaticWep) { + securitySettings->setKeyMgmt(NetworkManager::WirelessSecuritySetting::KeyMgmt::Wep); + securitySettings->setAuthAlg(NetworkManager::WirelessSecuritySetting::AuthAlg::Open); + securitySettings->setWepKeyType(NetworkManager::WirelessSecuritySetting::WepKeyType::Hex); + securitySettings->setWepKeyFlags(NetworkManager::Setting::SecretFlagType::AgentOwned); + securitySettings->setWepKey0(securMap["password"].toString()); + } + map.insert("802-11-wireless-security",securitySettings->toMap()); + } + } + //qWarning() << map; + NetworkManager::addConnection(map); +} + +void WifiSettings::updateConnectionFromQML(const QString &path, const QVariantMap &map) +{ + NetworkManager::Connection::Ptr con = NetworkManager::findConnection(path); + if (!con) + return; + + //qWarning() << map; + if (map.contains("id")) + con->settings()->setId(map.value("id").toString()); + + NMVariantMapMap toUpdateMap = con->settings()->toMap(); + + NetworkManager::Ipv4Setting::Ptr ipSetting = con->settings()->setting(NetworkManager::Setting::Ipv4).staticCast(); + if (ipSetting->method() == NetworkManager::Ipv4Setting::Automatic || ipSetting->method() == NetworkManager::Ipv4Setting::Manual) { + if (map.value("method") == "auto") { + ipSetting->setMethod(NetworkManager::Ipv4Setting::Automatic); + } + + if (map.value("method") == "manual") { + ipSetting->setMethod(NetworkManager::Ipv4Setting::ConfigMethod::Manual); + NetworkManager::IpAddress ipaddr; + ipaddr.setIp(QHostAddress(map["address"].toString())); + ipaddr.setPrefixLength(map["prefix"].toInt()); + ipaddr.setGateway(QHostAddress(map["gateway"].toString())); + ipSetting->setAddresses(QList({ipaddr})); + ipSetting->setDns(QList({QHostAddress(map["dns"].toString())})); + } + toUpdateMap.insert("ipv4",ipSetting->toMap()); + } + + NetworkManager::WirelessSetting::Ptr wirelessSetting = con->settings()->setting(NetworkManager::Setting::Wireless).staticCast(); + if (map.contains("hidden")) { + wirelessSetting->setHidden(map.value("hidden").toBool()); + } + if (map.contains("id")) { + wirelessSetting->setSsid(map.value("id").toByteArray()); + } + toUpdateMap.insert("802-11-wireless",wirelessSetting->toMap()); + + if (map.contains("802-11-wireless-security")) { + QVariantMap secMap = map.value("802-11-wireless-security").toMap(); + //qWarning() << secMap; + NetworkManager::WirelessSecuritySetting::Ptr securitySetting = con->settings()->setting(NetworkManager::Setting::WirelessSecurity).staticCast(); + if ((securitySetting->keyMgmt() == NetworkManager::WirelessSecuritySetting::Wep) + && (secMap.value("type") == NetworkManager::StaticWep)) + { + securitySetting->setWepKey0(secMap["password"].toString()); + } + + if ((securitySetting->keyMgmt() == NetworkManager::WirelessSecuritySetting::WpaPsk) + && (secMap.value("type") == NetworkManager::Wpa2Psk)) + { + securitySetting->setPsk(secMap["password"].toString()); + } + + // TODO can't set password for AP + // needs further inspection + if (wirelessSetting->mode() == NetworkManager::WirelessSetting::Ap) { + if (securitySetting->toMap().empty()) { //no security + if (secMap.value("type") == NetworkManager::Wpa2Psk) { + securitySetting->setKeyMgmt(NetworkManager::WirelessSecuritySetting::WpaNone); + securitySetting->setPsk(secMap.value("password").toString()); + } + } + if (securitySetting->keyMgmt() == NetworkManager::WirelessSecuritySetting::WpaNone) { + if (secMap.empty()) { + securitySetting->setKeyMgmt(NetworkManager::WirelessSecuritySetting::Unknown); + } + if (secMap.value("type") == NetworkManager::Wpa2Psk) { + securitySetting->setPsk(secMap.value("password").toString()); + } + } + } + + toUpdateMap.insert("802-11-wireless-security",securitySetting->toMap()); + } + qWarning() << toUpdateMap; + con->update(toUpdateMap); +} + +QString WifiSettings::getAccessPointDevice() +{ + NetworkManager::WirelessDevice::Ptr device; + foreach (const NetworkManager::Device::Ptr &dev, NetworkManager::networkInterfaces()) { + if (dev->type() == NetworkManager::Device::Wifi){ + device = dev.staticCast(); + if (device->wirelessCapabilities().testFlag(NetworkManager::WirelessDevice::ApCap)) + break; // we have wireless device with access point capability + } + } + if (device) { + return device->uni(); + } else { + qWarning() << "No wireless device found"; + } + return QString(); +} + +QString WifiSettings::getAccessPointConnection() +{ + foreach (const NetworkManager::Connection::Ptr &con, NetworkManager::listConnections()) { + NetworkManager::Setting::Ptr d = con->settings()->setting(NetworkManager::Setting::Wireless); + if (!d.isNull()){ + if( d.staticCast()->mode() == NetworkManager::WirelessSetting::Ap){ + return con->path(); + } + } + } + return QString(); +} \ No newline at end of file diff --git a/networkmanagement/wifisettings.h b/networkmanagement/wifisettings.h new file mode 100644 index 0000000..8388ece --- /dev/null +++ b/networkmanagement/wifisettings.h @@ -0,0 +1,40 @@ +/* + * Copyright 2018 Martin Kacej + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 or + * (at your option) any later version. + * + * 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 Library General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef WIFISETTINGS_H +#define WIFISETTINGS_H + +#include + +class WifiSettings : public QObject +{ + Q_OBJECT + +public: + WifiSettings(QObject *parent = nullptr); + Q_INVOKABLE QVariantMap getConnectionSettings(const QString &connection, const QString &type); + Q_INVOKABLE QVariantMap getActiveConnectionInfo(const QString &connection); + Q_INVOKABLE void addConnectionFromQML(const QVariantMap &QMLmap); + Q_INVOKABLE void updateConnectionFromQML(const QString &path, const QVariantMap &map); + Q_INVOKABLE QString getAccessPointDevice(); + Q_INVOKABLE QString getAccessPointConnection(); + virtual ~WifiSettings(); +}; + +#endif // WIFISETTINGS_H