diff --git a/applet/contents/ui/ConnectionItem.qml b/applet/contents/ui/ConnectionItem.qml index 1deb0295..5fa6aa36 100644 --- a/applet/contents/ui/ConnectionItem.qml +++ b/applet/contents/ui/ConnectionItem.qml @@ -1,375 +1,404 @@ /* Copyright 2013-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 . */ import QtQuick 2.2 import QtQuick.Layouts 1.2 +import QtQuick.Controls 2.4 as Controls import org.kde.kcoreaddons 1.0 as KCoreAddons +import org.kde.kquickcontrolsaddons 2.0 import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.networkmanagement 0.2 as PlasmaNM PlasmaComponents.ListItem { id: connectionItem property bool activating: ConnectionState == PlasmaNM.Enums.Activating property int baseHeight: Math.max(units.iconSizes.medium, connectionNameLabel.height + connectionStatusLabel.height) + Math.round(units.gridUnit / 2) property bool expanded: visibleDetails || visiblePasswordDialog property bool predictableWirelessPassword: !Uuid && Type == PlasmaNM.Enums.Wireless && (SecurityType == PlasmaNM.Enums.StaticWep || SecurityType == PlasmaNM.Enums.WpaPsk || SecurityType == PlasmaNM.Enums.Wpa2Psk) property bool showSpeed: plasmoid.expanded && ConnectionState == PlasmaNM.Enums.Activated && (Type == PlasmaNM.Enums.Wired || Type == PlasmaNM.Enums.Wireless || Type == PlasmaNM.Enums.Gsm || Type == PlasmaNM.Enums.Cdma) property bool visibleDetails: false property bool visiblePasswordDialog: false property real rxBytes: 0 property real txBytes: 0 checked: connectionItem.containsMouse enabled: true height: expanded ? baseHeight + separator.height + expandableComponentLoader.height + (2 * Math.round(units.gridUnit / 3)) : baseHeight ColumnLayout { anchors.fill: parent RowLayout { Layout.fillWidth: true spacing: Math.round(units.gridUnit / 2) PlasmaCore.SvgItem { id: connectionSvgIcon Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft Layout.preferredHeight: units.iconSizes.medium Layout.preferredWidth: units.iconSizes.medium elementId: ConnectionIcon svg: PlasmaCore.Svg { multipleImages: true imagePath: "icons/network" colorGroup: PlasmaCore.ColorScope.colorGroup } } ColumnLayout { Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft spacing: 0 PlasmaComponents.Label { id: connectionNameLabel Layout.fillWidth: true height: paintedHeight elide: Text.ElideRight font.weight: ConnectionState == PlasmaNM.Enums.Activated ? Font.DemiBold : Font.Normal font.italic: ConnectionState == PlasmaNM.Enums.Activating ? true : false text: ItemUniqueName textFormat: Text.PlainText } PlasmaComponents.Label { id: connectionStatusLabel Layout.fillWidth: true height: paintedHeight elide: Text.ElideRight font.pointSize: theme.smallestFont.pointSize opacity: 0.6 text: itemText() } } PlasmaComponents.BusyIndicator { id: connectingIndicator Layout.alignment: Qt.AlignVCenter | Qt.AlignRight Layout.fillHeight: true running: plasmoid.expanded && !stateChangeButton.visible && ConnectionState == PlasmaNM.Enums.Activating visible: running opacity: visible } PlasmaComponents.Button { id: stateChangeButton Layout.alignment: Qt.AlignVCenter | Qt.AlignRight opacity: connectionView.currentVisibleButtonIndex == index ? 1 : 0 visible: opacity != 0 text: (ConnectionState == PlasmaNM.Enums.Deactivated) ? i18n("Connect") : i18n("Disconnect") Behavior on opacity { NumberAnimation { duration: units.shortDuration } } onClicked: changeState() } } PlasmaCore.SvgItem { id: separator height: lineSvg.elementSize("horizontal-line").height Layout.fillWidth: true Layout.maximumHeight: height elementId: "horizontal-line" svg: PlasmaCore.Svg { id: lineSvg; imagePath: "widgets/line" } visible: connectionItem.expanded opacity: visible } Loader { id: expandableComponentLoader Layout.fillHeight: true Layout.fillWidth: true height: childrenRect.height } } + MouseArea { + acceptedButtons: Qt.RightButton + anchors.fill: parent + onPressed: { + contextMenu.visualParent = parent + contextMenu.open() + } + } + + PlasmaComponents.Menu { + id: contextMenu + PlasmaComponents.MenuItem { + text: ItemUniqueName + enabled: false + } + PlasmaComponents.MenuItem { + text: stateChangeButton.text + icon: (ConnectionState == PlasmaNM.Enums.Deactivated) ? "network-connect" : "network-disconnect" + onClicked: changeState() + } + PlasmaComponents.MenuItem { + text: i18n("Configure...") + icon: "settings-configure" + onClicked: KCMShell.open([mainWindow.kcm, "--args", "Uuid=" + Uuid]) + } + } + Component { id: detailsComponent Item { height: childrenRect.height PlasmaComponents.TabBar { id: detailsTabBar anchors { left: parent.left right: parent.right top: parent.top } height: visible ? implicitHeight : 0 visible: showSpeed PlasmaComponents.TabButton { id: speedTabButton text: i18n("Speed") } PlasmaComponents.TabButton { id: detailsTabButton text: i18n("Details") } Component.onCompleted: { if (!speedTabButton.visible) { currentTab = detailsTabButton } } } DetailsText { anchors { left: parent.left leftMargin: units.iconSizes.medium right: parent.right top: detailsTabBar.visible ? detailsTabBar.bottom : parent.top topMargin: Math.round(units.gridUnit / 3) } details: ConnectionDetails visible: detailsTabBar.currentTab == detailsTabButton } TrafficMonitor { anchors { left: parent.left right: parent.right top: detailsTabBar.visible ? detailsTabBar.bottom : parent.top topMargin: Math.round(units.gridUnit / 3) } rxBytes: RxBytes txBytes: TxBytes interval: 2000 visible: detailsTabBar.currentTab == speedTabButton } } } Component { id: passwordDialogComponent Item { property alias password: passwordField.text property alias passwordInput: passwordField height: childrenRect.height PasswordField { id: passwordField anchors { left: parent.left right: parent.right top: parent.top } securityType: SecurityType onAccepted: { stateChangeButton.clicked() } onAcceptableInputChanged: { stateChangeButton.enabled = acceptableInput } Component.onCompleted: { stateChangeButton.enabled = false } Component.onDestruction: { stateChangeButton.enabled = true } } } } Timer { id: timer repeat: true interval: 2000 running: showSpeed property real prevRxBytes property real prevTxBytes Component.onCompleted: { prevRxBytes = RxBytes prevTxBytes = TxBytes } onTriggered: { rxBytes = (RxBytes - prevRxBytes) * 1000 / interval txBytes = (TxBytes - prevTxBytes) * 1000 / interval prevRxBytes = RxBytes prevTxBytes = TxBytes } } states: [ State { name: "collapsed" when: !(visibleDetails || visiblePasswordDialog) StateChangeScript { script: if (expandableComponentLoader.status == Loader.Ready) {expandableComponentLoader.sourceComponent = undefined} } }, State { name: "expandedDetails" when: visibleDetails StateChangeScript { script: createContent() } }, State { name: "expandedPasswordDialog" when: visiblePasswordDialog StateChangeScript { script: createContent() } PropertyChanges { target: stateChangeButton; opacity: 1 } } ] function createContent() { if (visibleDetails) { expandableComponentLoader.sourceComponent = detailsComponent } else if (visiblePasswordDialog) { expandableComponentLoader.sourceComponent = passwordDialogComponent expandableComponentLoader.item.passwordInput.forceActiveFocus() } } function changeState() { visibleDetails = false if (Uuid || !predictableWirelessPassword || visiblePasswordDialog) { if (ConnectionState == PlasmaNM.Enums.Deactivated) { if (!predictableWirelessPassword && !Uuid) { handler.addAndActivateConnection(DevicePath, SpecificPath) } else if (visiblePasswordDialog) { if (expandableComponentLoader.item.password != "") { handler.addAndActivateConnection(DevicePath, SpecificPath, expandableComponentLoader.item.password) visiblePasswordDialog = false } else { connectionItem.clicked() } } else { handler.activateConnection(ConnectionPath, DevicePath, SpecificPath) } } else { handler.deactivateConnection(ConnectionPath, DevicePath) } } else if (predictableWirelessPassword) { appletProxyModel.dynamicSortFilter = false visiblePasswordDialog = true } } function itemText() { if (ConnectionState == PlasmaNM.Enums.Activating) { if (Type == PlasmaNM.Enums.Vpn) return VpnState else return DeviceState } else if (ConnectionState == PlasmaNM.Enums.Deactivating) { if (Type == PlasmaNM.Enums.Vpn) return VpnState else return DeviceState } else if (ConnectionState == PlasmaNM.Enums.Deactivated) { var result = LastUsed if (SecurityType > PlasmaNM.Enums.NoneSecurity) result += ", " + SecurityTypeString return result } else if (ConnectionState == PlasmaNM.Enums.Activated) { if (showSpeed) { var downloadColor = theme.highlightColor // cycle upload color by 180 degrees var uploadColor = Qt.hsva((downloadColor.hsvHue + 0.5) % 1, downloadColor.hsvSaturation, downloadColor.hsvValue, downloadColor.a) return i18n("Connected, %2/s, %4/s", downloadColor, KCoreAddons.Format.formatByteSize(rxBytes), uploadColor, KCoreAddons.Format.formatByteSize(txBytes)) } else { return i18n("Connected") } } } onShowSpeedChanged: { connectionModel.setDeviceStatisticsRefreshRateMs(DevicePath, showSpeed ? 2000 : 0) } onActivatingChanged: { if (ConnectionState == PlasmaNM.Enums.Activating) { ListView.view.positionViewAtBeginning() } } onClicked: { if (visiblePasswordDialog) { appletProxyModel.dynamicSortFilter = true visiblePasswordDialog = false } else { visibleDetails = !visibleDetails } if (visibleDetails || visiblePasswordDialog) { ListView.view.currentIndex = index } else { ListView.view.currentIndex = -1 } } onContainsMouseChanged: { if (connectionItem.containsMouse) { connectionView.currentVisibleButtonIndex = index } } } diff --git a/applet/contents/ui/PopupDialog.qml b/applet/contents/ui/PopupDialog.qml index 329cfbed..ac1c564b 100644 --- a/applet/contents/ui/PopupDialog.qml +++ b/applet/contents/ui/PopupDialog.qml @@ -1,105 +1,102 @@ /* Copyright 2013-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 . */ import QtQuick 2.2 +import QtQuick.Layouts 1.2 +import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.plasma.networkmanagement 0.2 as PlasmaNM FocusScope { property var notificationInhibitorLock: undefined PlasmaNM.AvailableDevices { id: availableDevices } PlasmaNM.NetworkModel { id: connectionModel } PlasmaNM.AppletProxyModel { id: appletProxyModel sourceModel: connectionModel } - Toolbar { - id: toolbar + ColumnLayout { + anchors.fill: parent - anchors { - left: parent.left - right: parent.right - top: parent.top - } - } - - PlasmaExtras.ScrollArea { - id: scrollView - - anchors { - bottom: parent.bottom - left: parent.left - right: parent.right - top: toolbar.bottom + Toolbar { + id: toolbar + Layout.fillWidth: true } - ListView { - id: connectionView - - property bool availableConnectionsVisible: false - property int currentVisibleButtonIndex: -1 - - anchors.fill: parent - clip: true - model: appletProxyModel - currentIndex: -1 - boundsBehavior: Flickable.StopAtBounds - section.property: showSections ? "Section" : "" - section.delegate: Header { text: section } - delegate: ConnectionItem { } + PlasmaExtras.ScrollArea { + id: scrollView + Layout.fillWidth: true + Layout.fillHeight: true + + ListView { + id: connectionView + + property bool availableConnectionsVisible: false + property int currentVisibleButtonIndex: -1 + + anchors.fill: parent + clip: true + model: appletProxyModel + currentIndex: -1 + boundsBehavior: Flickable.StopAtBounds + section.property: showSections ? "Section" : "" + section.delegate: Header { text: section } + delegate: ConnectionItem { } + } } } Connections { target: plasmoid onExpandedChanged: { connectionView.currentVisibleButtonIndex = -1; if (expanded) { var service = notificationsEngine.serviceForSource("notifications"); var operation = service.operationDescription("inhibit"); operation.hint = "x-kde-appname"; operation.value = "networkmanagement"; var job = service.startOperationCall(operation); job.finished.connect(function(job) { if (expanded) { notificationInhibitorLock = job.result; } }); } else { notificationInhibitorLock = undefined; + toolbar.closeSearch() } } } PlasmaCore.DataSource { id: notificationsEngine engine: "notifications" } } diff --git a/applet/contents/ui/Toolbar.qml b/applet/contents/ui/Toolbar.qml index b1a21513..fb8ae3d2 100644 --- a/applet/contents/ui/Toolbar.qml +++ b/applet/contents/ui/Toolbar.qml @@ -1,131 +1,164 @@ /* Copyright 2013-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 . */ import QtQuick 2.2 +import QtQuick.Layouts 1.2 import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.networkmanagement 0.2 as PlasmaNM import org.kde.kquickcontrolsaddons 2.0 -Item { +GridLayout { id: toolbar - height: wifiSwitchButton.height + function closeSearch() { + searchToggleButton.checked = false + } + + rows: 2 + columns: 2 PlasmaCore.Svg { id: lineSvg imagePath: "widgets/line" } PlasmaNM.EnabledConnections { id: enabledConnections onWirelessEnabledChanged: { wifiSwitchButton.checked = wifiSwitchButton.enabled && enabled } onWirelessHwEnabledChanged: { wifiSwitchButton.enabled = enabled && availableDevices.wirelessDeviceAvailable && !planeModeSwitchButton.airplaneModeEnabled } onWwanEnabledChanged: { wwanSwitchButton.checked = wwanSwitchButton.enabled && enabled } onWwanHwEnabledChanged: { wwanSwitchButton.enabled = enabled && availableDevices.modemDeviceAvailable && !planeModeSwitchButton.airplaneModeEnabled } } Row { - anchors { - bottom: parent.bottom - left: parent.left - top: parent.top - } + Layout.fillWidth: true SwitchButton { id: wifiSwitchButton checked: enabled && enabledConnections.wirelessEnabled enabled: enabledConnections.wirelessHwEnabled && availableDevices.wirelessDeviceAvailable && !planeModeSwitchButton.airplaneModeEnabled tooltip: i18n("Enable wireless") icon: enabled ? "network-wireless-on" : "network-wireless-off" visible: availableDevices.wirelessDeviceAvailable onClicked: { handler.enableWireless(checked); } } SwitchButton { id: wwanSwitchButton checked: enabled && enabledConnections.wwanEnabled enabled: enabledConnections.wwanHwEnabled && availableDevices.modemDeviceAvailable && !planeModeSwitchButton.airplaneModeEnabled tooltip: i18n("Enable mobile network") icon: enabled ? "network-mobile-on" : "network-mobile-off" visible: availableDevices.modemDeviceAvailable onClicked: { handler.enableWwan(checked); } } SwitchButton { id: planeModeSwitchButton property bool airplaneModeEnabled: false checked: airplaneModeEnabled tooltip: i18n("Enable airplane mode") icon: airplaneModeEnabled ? "network-flightmode-on" : "network-flightmode-off" onClicked: { handler.enableAirplaneMode(checked); airplaneModeEnabled = !airplaneModeEnabled; } Binding { target: connectionIconProvider property: "airplaneMode" value: planeModeSwitchButton.airplaneModeEnabled } } } - PlasmaComponents.ToolButton { - id: openEditorButton + Row { + Layout.column: 1 + + PlasmaComponents.ToolButton { + id: searchToggleButton + iconSource: "search" + tooltip: i18ndc("plasma-nm", "button tooltip", "Search the connections") + checkable: true + } + + PlasmaComponents.ToolButton { + id: openEditorButton + iconSource: "configure" + tooltip: i18n("Configure network connections...") + visible: mainWindow.kcmAuthorized - anchors { - right: parent.right - rightMargin: Math.round(units.gridUnit / 2) - verticalCenter: parent.verticalCenter + onClicked: { + KCMShell.open(mainWindow.kcm) + } } + } + + PlasmaComponents.TextField { + id: searchTextField - iconSource: "configure" - tooltip: i18n("Configure network connections...") - visible: mainWindow.kcmAuthorized + Layout.row: 1 + Layout.columnSpan: 2 + Layout.fillWidth: true + Layout.leftMargin: units.smallSpacing + Layout.rightMargin: units.smallSpacing + Layout.bottomMargin: units.smallSpacing - onClicked: { - KCMShell.open(mainWindow.kcm) + focus: true + clearButtonShown: true + placeholderText: i18ndc("plasma-nm", "text field placeholder text", "Search...") + + visible: searchToggleButton.checked + onVisibleChanged: if (!visible) text = "" + Keys.onEscapePressed: searchToggleButton.checked = false + + onTextChanged: { + // Show search field when starting to type directly + if (text.length && !searchToggleButton.checked) { + searchToggleButton.checked = true + } + appletProxyModel.setFilterRegExp(text) } } } diff --git a/kcm/kcm.cpp b/kcm/kcm.cpp index 574c9d52..110c3d94 100755 --- a/kcm/kcm.cpp +++ b/kcm/kcm.cpp @@ -1,460 +1,486 @@ /* Copyright 2016-2018 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 "kcm.h" #include "debug.h" #include "settings/connectionsettings.h" // #include "mobileconnectionwizard.h" #include "uiutils.h" // #include "vpnuiplugin.h" // KDE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Qt #include #include #include Q_LOGGING_CATEGORY(KCM_NETWORKMANAGEMENT, "kcm_networkmanagement") K_PLUGIN_FACTORY_WITH_JSON(KCMNetworkmanagementFactory, "kcm_networkmanagement.json", registerPlugin();) KCMNetworkmanagement::KCMNetworkmanagement(QObject *parent, const QVariantList &args) : KQuickAddons::ConfigModule(parent, args) , m_handler(new Handler(this)) { KAboutData* about = new KAboutData(QStringLiteral("kcm_networkmanagement"), i18n("Edit your Network Connections"), QStringLiteral("0.1"), QString(), KAboutLicense::LGPL); about->addAuthor(i18n("Jan Grulich"), QString(), QStringLiteral("jgrulich@redhat.com")); setAboutData(about); setButtons(Apply); m_connectionSettings = new ConnectionSettings(this); connect(m_connectionSettings, &ConnectionSettings::settingChanged, [this] () { if (m_connectionSettings->isInitialized() && m_connectionSettings->isValid()) { setNeedsSave(true); } }); connect(m_connectionSettings, &ConnectionSettings::validityChanged, [this] (bool valid) { if (m_connectionSettings->isInitialized()) { setNeedsSave(true); } }); - // Pre-select currently active primary connection and if there is none then just select - // the very first connection -// NetworkManager::ActiveConnection::Ptr activeConnection = NetworkManager::primaryConnection(); -// if (activeConnection && activeConnection->isValid()) { -// // Also check if the connection type is supported by KCM -// const NetworkManager::ConnectionSettings::ConnectionType type = activeConnection->type(); -// if (UiUtils::isConnectionTypeSupported(type)) { -// QMetaObject::invokeMethod(mainUi(), "selectConnectionInView", Q_ARG(QVariant, activeConnection->id()), Q_ARG(QVariant, activeConnection->connection()->path())); +// NetworkManager::Connection::Ptr selectedConnection; +// +// // Look in the arguments for a connection ID to preselect +// static const QLatin1Literal uuidArgumentMarker { "Uuid=" }; +// for (QVariant arg : args) { +// if (arg.canConvert(QMetaType::QString)) { +// QString uuid = arg.toString(); +// if (uuid.startsWith(uuidArgumentMarker)) { +// uuid = uuid.replace(uuidArgumentMarker, QString()); +// selectedConnection = NetworkManager::findConnectionByUuid(uuid); +// qDebug() << "Selecting user connection:" << uuid; +// break; +// } // } -// } else { -// // Select first connection +// } +// +// // Pre-select the currently active primary connection +// if (!selectedConnection || !selectedConnection->isValid()) { +// NetworkManager::ActiveConnection::Ptr activeConnection = NetworkManager::primaryConnection(); +// if (activeConnection && activeConnection->isValid()) { +// selectedConnection = activeConnection->connection(); +// qDebug() << "Selecting active connection:" << selectedConnection->uuid(); +// } +// } +// +// // Select the very first connection as a fallback +// if (!selectedConnection || !selectedConnection->isValid()) { // NetworkManager::Connection::List connectionList = NetworkManager::listConnections(); // std::sort(connectionList.begin(), connectionList.end(), [] (const NetworkManager::Connection::Ptr &left, const NetworkManager::Connection::Ptr &right) // { // const QString leftName = left->settings()->id(); // const UiUtils::SortedConnectionType leftType = UiUtils::connectionTypeToSortedType(left->settings()->connectionType()); // const QDateTime leftDate = left->settings()->timestamp(); // // const QString rightName = right->settings()->id(); // const UiUtils::SortedConnectionType rightType = UiUtils::connectionTypeToSortedType(right->settings()->connectionType()); // const QDateTime rightDate = right->settings()->timestamp(); // // if (leftType < rightType) { // return true; // } else if (leftType > rightType) { // return false; // } // // if (leftDate > rightDate) { // return true; // } else if (leftDate < rightDate) { // return false; // } // // if (QString::localeAwareCompare(leftName, rightName) > 0) { // return true; // } else { // return false; // } // }); // -// Q_FOREACH (const NetworkManager::Connection::Ptr &connection, connectionList) { +// for (const NetworkManager::Connection::Ptr &connection : connectionList) { // const NetworkManager::ConnectionSettings::ConnectionType type = connection->settings()->connectionType(); // if (UiUtils::isConnectionTypeSupported(type)) { -// QMetaObject::invokeMethod(mainUi(), "selectConnectionInView", Q_ARG(QVariant, connection->settings()->id()), Q_ARG(QVariant, connection->path())); +// selectedConnection = connection; +// qDebug() << "Selecting first connection:" << connection->uuid(); // break; // } // } +// } +// +// if (selectedConnection && selectedConnection->isValid()) { +// const NetworkManager::ConnectionSettings::Ptr settings = selectedConnection->settings(); +// if (UiUtils::isConnectionTypeSupported(settings->connectionType())) { +// QMetaObject::invokeMethod(rootItem, "selectConnection", Q_ARG(QVariant, settings->id()), Q_ARG(QVariant, selectedConnection->path())); +// } +// } else { +// qDebug() << "Cannot preselect a connection"; // } connect(NetworkManager::settingsNotifier(), &NetworkManager::SettingsNotifier::connectionAdded, this, &KCMNetworkmanagement::onConnectionAdded, Qt::UniqueConnection); // Initialize first scan and then scan every 15 seconds m_handler->requestScan(); m_timer = new QTimer(this); m_timer->setInterval(15000); connect(m_timer, &QTimer::timeout, [this] () { m_handler->requestScan(); m_timer->start(); }); m_timer->start(); } KCMNetworkmanagement::~KCMNetworkmanagement() { delete m_handler; } void KCMNetworkmanagement::defaults() { KQuickAddons::ConfigModule::defaults(); } void KCMNetworkmanagement::load() { // If there is no loaded connection do nothing if (m_currentConnectionPath.isEmpty()) { return; } NetworkManager::Connection::Ptr connection = NetworkManager::findConnection(m_currentConnectionPath); if (connection) { NetworkManager::ConnectionSettings::Ptr connectionSettings = connection->settings(); // Re-load the connection again to load stored values m_connectionSettings->loadConfig(connectionSettings->toMap()); } KQuickAddons::ConfigModule::load(); } void KCMNetworkmanagement::save() { NetworkManager::Connection::Ptr connection = NetworkManager::findConnection(m_currentConnectionPath); if (connection) { m_handler->updateConnection(connection, m_connectionSettings->settingMap()); } KQuickAddons::ConfigModule::save(); } void KCMNetworkmanagement::onConnectionAdded(const QString &connection) { if (m_createdConnectionUuid.isEmpty()) { return; } NetworkManager::Connection::Ptr newConnection = NetworkManager::findConnection(connection); if (newConnection) { NetworkManager::ConnectionSettings::Ptr connectionSettings = newConnection->settings(); if (connectionSettings && connectionSettings->uuid() == m_createdConnectionUuid) { loadConnectionSettings(connectionSettings->toMap()); QMetaObject::invokeMethod(mainUi(), "selectConnectionInView", Q_ARG(QVariant, connectionSettings->id()), Q_ARG(QVariant, newConnection->path())); m_createdConnectionUuid.clear(); } } } void KCMNetworkmanagement::selectConnection(const QString &connectionPath) { if (connectionPath.isEmpty()) { resetSelection(); return; } m_currentConnectionPath = connectionPath; NetworkManager::Connection::Ptr connection = NetworkManager::findConnection(m_currentConnectionPath); if (connection) { NetworkManager::ConnectionSettings::Ptr connectionSettings = connection->settings(); loadConnectionSettings(connectionSettings->toMap()); } } void KCMNetworkmanagement::requestCreateConnection(int connectionType, const QString &vpnType, const QString &specificType, bool shared) { NetworkManager::ConnectionSettings::ConnectionType type = static_cast(connectionType); if (type == NetworkManager::ConnectionSettings::Vpn && vpnType == "imported") { importVpn(); } else if (type == NetworkManager::ConnectionSettings::Gsm) { // launch the mobile broadband wizard, both gsm/cdma // #if WITH_MODEMMANAGER_SUPPORT // QPointer wizard = new MobileConnectionWizard(NetworkManager::ConnectionSettings::Unknown, this); // connect(wizard.data(), &MobileConnectionWizard::accepted, // [wizard, this] () { // if (wizard->getError() == MobileProviders::Success) { // qCDebug(KCM_NETWORKMANAGEMENT) << "Mobile broadband wizard finished:" << wizard->type() << wizard->args(); // // if (wizard->args().count() == 2) { // QVariantMap tmp = qdbus_cast(wizard->args().value(1)); // // NetworkManager::ConnectionSettings::Ptr connectionSettings; // connectionSettings = NetworkManager::ConnectionSettings::Ptr(new NetworkManager::ConnectionSettings(wizard->type())); // connectionSettings->setId(wizard->args().value(0).toString()); // if (wizard->type() == NetworkManager::ConnectionSettings::Gsm) { // NetworkManager::GsmSetting::Ptr gsmSetting = connectionSettings->setting(NetworkManager::Setting::Gsm).staticCast(); // gsmSetting->fromMap(tmp); // gsmSetting->setPasswordFlags(NetworkManager::Setting::NotRequired); // gsmSetting->setPinFlags(NetworkManager::Setting::NotRequired); // } else if (wizard->type() == NetworkManager::ConnectionSettings::Cdma) { // connectionSettings->setting(NetworkManager::Setting::Cdma)->fromMap(tmp); // } else { // qCWarning(KCM_NETWORKMANAGEMENT) << Q_FUNC_INFO << "Unhandled setting type"; // } // // Generate new UUID // connectionSettings->setUuid(NetworkManager::ConnectionSettings::createNewUuid()); // addConnection(connectionSettings); // } else { // qCWarning(KCM_NETWORKMANAGEMENT) << Q_FUNC_INFO << "Unexpected number of args to parse"; // } // } // }); // connect(wizard.data(), &MobileConnectionWizard::finished, // [wizard] () { // if (wizard) { // wizard->deleteLater(); // } // }); // wizard->setModal(true); // wizard->show(); // #endif } else { NetworkManager::ConnectionSettings::Ptr connectionSettings; connectionSettings = NetworkManager::ConnectionSettings::Ptr(new NetworkManager::ConnectionSettings(type)); if (type == NetworkManager::ConnectionSettings::Vpn) { NetworkManager::VpnSetting::Ptr vpnSetting = connectionSettings->setting(NetworkManager::Setting::Vpn).dynamicCast(); vpnSetting->setServiceType(vpnType); // Set VPN subtype in case of Openconnect to add support for juniper if (vpnType == QLatin1String("org.freedesktop.NetworkManager.openconnect")) { NMStringMap data = vpnSetting->data(); data.insert(QLatin1String("protocol"), specificType); vpnSetting->setData(data); } } if (type == NetworkManager::ConnectionSettings::Wired || type == NetworkManager::ConnectionSettings::Wireless) { // Set auto-negotiate to true, NM sets it to false by default, but we used to have this before and also // I don't think it's wise to request users to specify speed and duplex as most of them don't know what is that // and what to set if (type == NetworkManager::ConnectionSettings::Wired) { NetworkManager::WiredSetting::Ptr wiredSetting = connectionSettings->setting(NetworkManager::Setting::Wired).dynamicCast(); wiredSetting->setAutoNegotiate(true); } if (shared) { if (type == NetworkManager::ConnectionSettings::Wireless) { NetworkManager::WirelessSetting::Ptr wifiSetting = connectionSettings->setting(NetworkManager::Setting::Wireless).dynamicCast(); wifiSetting->setMode(NetworkManager::WirelessSetting::Adhoc); wifiSetting->setSsid(i18n("my_shared_connection").toUtf8()); - Q_FOREACH (const NetworkManager::Device::Ptr & device, NetworkManager::networkInterfaces()) { + for (const NetworkManager::Device::Ptr & device : NetworkManager::networkInterfaces()) { if (device->type() == NetworkManager::Device::Wifi) { NetworkManager::WirelessDevice::Ptr wifiDev = device.objectCast(); if (wifiDev) { if (wifiDev->wirelessCapabilities().testFlag(NetworkManager::WirelessDevice::ApCap)) { wifiSetting->setMode(NetworkManager::WirelessSetting::Ap); wifiSetting->setMacAddress(NetworkManager::macAddressFromString(wifiDev->permanentHardwareAddress())); } } } } } NetworkManager::Ipv4Setting::Ptr ipv4Setting = connectionSettings->setting(NetworkManager::Setting::Ipv4).dynamicCast(); ipv4Setting->setMethod(NetworkManager::Ipv4Setting::Shared); connectionSettings->setAutoconnect(false); } } // Generate new UUID connectionSettings->setUuid(NetworkManager::ConnectionSettings::createNewUuid()); addConnection(connectionSettings); } } void KCMNetworkmanagement::requestExportConnection(const QString &connectionPath) { NetworkManager::Connection::Ptr connection = NetworkManager::findConnection(connectionPath); if (!connection) { return; } NetworkManager::ConnectionSettings::Ptr connSettings = connection->settings(); if (connSettings->connectionType() != NetworkManager::ConnectionSettings::Vpn) return; NetworkManager::VpnSetting::Ptr vpnSetting = connSettings->setting(NetworkManager::Setting::Vpn).dynamicCast(); qCDebug(KCM_NETWORKMANAGEMENT) << "Exporting VPN connection" << connection->name() << "type:" << vpnSetting->serviceType(); QString error; // VpnUiPlugin * vpnPlugin = KServiceTypeTrader::createInstanceFromQuery(QStringLiteral("PlasmaNetworkManagement/VpnUiPlugin"), // QStringLiteral("[X-NetworkManager-Services]=='%1'").arg(vpnSetting->serviceType()), // this, QVariantList(), &error); // if (vpnPlugin) { // if (vpnPlugin->suggestedFileName(connSettings).isEmpty()) { // this VPN doesn't support export // qCWarning(KCM_NETWORKMANAGEMENT) << "This VPN doesn't support export"; // return; // } // // const QString url = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + QDir::separator() + vpnPlugin->suggestedFileName(connSettings); // const QString filename = QFileDialog::getSaveFileName(this, i18n("Export VPN Connection"), url, vpnPlugin->supportedFileExtensions()); // if (!filename.isEmpty()) { // if (!vpnPlugin->exportConnectionSettings(connSettings, filename)) { // // TODO display failure // qCWarning(KCM_NETWORKMANAGEMENT) << "Failed to export VPN connection"; // } else { // // TODO display success // } // } // delete vpnPlugin; // } else { // qCWarning(KCM_NETWORKMANAGEMENT) << "Error getting VpnUiPlugin for export:" << error; // } } QObject * KCMNetworkmanagement::connectionSettings() const { return m_connectionSettings; } void KCMNetworkmanagement::addConnection(const NetworkManager::ConnectionSettings::Ptr &connectionSettings) { // QPointer editor = new ConnectionEditorDialog(connectionSettings); // connect(editor.data(), &ConnectionEditorDialog::accepted, // [connectionSettings, editor, this] () { // // We got confirmation so watch this connection and select it once it is created // m_createdConnectionUuid = connectionSettings->uuid(); // m_handler->addConnection(editor->setting()); // }); // connect(editor.data(), &ConnectionEditorDialog::finished, // [editor] () { // if (editor) { // editor->deleteLater(); // } // }); // editor->setModal(true); // editor->show(); } void KCMNetworkmanagement::loadConnectionSettings(const NMVariantMapMap &connectionSettings) { m_connectionSettings->loadConfig(connectionSettings); QMetaObject::invokeMethod(mainUi(), "loadConnectionSetting"); setNeedsSave(false); } void KCMNetworkmanagement::importVpn() { // get the list of supported extensions // const KService::List services = KServiceTypeTrader::self()->query("PlasmaNetworkManagement/VpnUiPlugin"); // QString extensions; // Q_FOREACH (const KService::Ptr &service, services) { // VpnUiPlugin * vpnPlugin = service->createInstance(this); // if (vpnPlugin) { // extensions += vpnPlugin->supportedFileExtensions() % QStringLiteral(" "); // delete vpnPlugin; // } // } // // const QString &filename = QFileDialog::getOpenFileName(this, i18n("Import VPN Connection"), QDir::homePath(), extensions.simplified()); // // if (!filename.isEmpty()) { // const KService::List services = KServiceTypeTrader::self()->query("PlasmaNetworkManagement/VpnUiPlugin"); // // QFileInfo fi(filename); // const QString ext = QStringLiteral("*.") % fi.suffix(); // qCDebug(KCM_NETWORKMANAGEMENT) << "Importing VPN connection " << filename << "extension:" << ext; // // Q_FOREACH (const KService::Ptr &service, services) { // VpnUiPlugin * vpnPlugin = service->createInstance(this); // if (vpnPlugin && vpnPlugin->supportedFileExtensions().contains(ext)) { // qCDebug(KCM_NETWORKMANAGEMENT) << "Found VPN plugin" << service->name() << ", type:" << service->property("X-NetworkManager-Services", QVariant::String).toString(); // // NMVariantMapMap connection = vpnPlugin->importConnectionSettings(filename); // // // qCDebug(KCM_NETWORKMANAGEMENT) << "Raw connection:" << connection; // // NetworkManager::ConnectionSettings connectionSettings; // connectionSettings.fromMap(connection); // connectionSettings.setUuid(NetworkManager::ConnectionSettings::createNewUuid()); // // // qCDebug(KCM_NETWORKMANAGEMENT) << "Converted connection:" << connectionSettings; // // m_handler->addConnection(connectionSettings.toMap()); // // qCDebug(KCM_NETWORKMANAGEMENT) << "Adding imported connection under id:" << conId; // // if (connection.isEmpty()) { // the "positive" part will arrive with connectionAdded // // TODO display success // } else { // delete vpnPlugin; // break; // stop iterating over the plugins if the import produced at least some output // } // // delete vpnPlugin; // } // } // } } void KCMNetworkmanagement::resetSelection() { // Reset selected connections m_currentConnectionPath.clear(); QMetaObject::invokeMethod(mainUi(), "deselectConnectionsInView"); // if (m_connectionSetting) { // delete m_connectionSetting; // m_connectionSetting = nullptr; // } setNeedsSave(false); } #include "kcm.moc" diff --git a/kded/bluetoothmonitor.cpp b/kded/bluetoothmonitor.cpp index 99d85fbc..caa66e2e 100644 --- a/kded/bluetoothmonitor.cpp +++ b/kded/bluetoothmonitor.cpp @@ -1,146 +1,146 @@ /* Copyright 2011 Lamarque Souza Copyright 2013 Lukas Tinkl Copyright 2013-2014 Jan Grulich Copyright 2015 David Rosca 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 "bluetoothmonitor.h" #include "debug.h" #include #include #include #include #include #include #include BluetoothMonitor::BluetoothMonitor(QObject * parent) : QObject(parent) { } BluetoothMonitor::~BluetoothMonitor() { } bool BluetoothMonitor::bluetoothConnectionExists(const QString &bdAddr, const QString &service) { if (bdAddr.isEmpty() || service.isEmpty()) { return false; } NetworkManager::BluetoothSetting::ProfileType profile; if (service == QLatin1String("dun")) { profile = NetworkManager::BluetoothSetting::Dun; } else if (service == QLatin1String("nap")) { profile = NetworkManager::BluetoothSetting::Panu; } else { return false; } - Q_FOREACH (const NetworkManager::Connection::Ptr &con, NetworkManager::listConnections()) { + for (const NetworkManager::Connection::Ptr &con : NetworkManager::listConnections()) { if (con && con->settings() && con->settings()->connectionType() == NetworkManager::ConnectionSettings::Bluetooth) { NetworkManager::BluetoothSetting::Ptr btSetting = con->settings()->setting(NetworkManager::Setting::Bluetooth).staticCast(); if (btSetting->profileType() == profile && btSetting->bluetoothAddress() == NetworkManager::macAddressFromString(bdAddr)) { return true; } } } return false; } void BluetoothMonitor::addBluetoothConnection(const QString &bdAddr, const QString &service, const QString &connectionName) { qCDebug(PLASMA_NM) << "Adding BT connection:" << bdAddr << service; if (bdAddr.isEmpty() || service.isEmpty() || connectionName.isEmpty()) { return; } if (service != QLatin1String("dun") && service != QLatin1String("nap")) { KMessageBox::sorry(nullptr, i18n("Only 'dun' and 'nap' services are supported.")); return; } qCDebug(PLASMA_NM) << "Bdaddr == " << bdAddr; if (bluetoothConnectionExists(bdAddr, service)) { return; } if (service == QLatin1String("nap")) { NetworkManager::ConnectionSettings connectionSettings(NetworkManager::ConnectionSettings::Bluetooth, NM_BT_CAPABILITY_NAP); connectionSettings.setUuid(NetworkManager::ConnectionSettings::createNewUuid()); connectionSettings.setId(connectionName); NetworkManager::BluetoothSetting::Ptr btSetting = connectionSettings.setting(NetworkManager::Setting::Bluetooth).staticCast(); btSetting->setBluetoothAddress(NetworkManager::macAddressFromString(bdAddr)); btSetting->setProfileType(NetworkManager::BluetoothSetting::Panu); btSetting->setInitialized(true); NetworkManager::addConnection(connectionSettings.toMap()); } #if WITH_MODEMMANAGER_SUPPORT else if (service == QLatin1String("dun")) { QPointer mobileConnectionWizard = new MobileConnectionWizard(NetworkManager::ConnectionSettings::Bluetooth); connect(mobileConnectionWizard.data(), &MobileConnectionWizard::accepted, [bdAddr, connectionName, mobileConnectionWizard, this] () { if (mobileConnectionWizard->getError() == MobileProviders::Success) { qCDebug(PLASMA_NM) << "Mobile broadband wizard finished:" << mobileConnectionWizard->type() << mobileConnectionWizard->args(); if (mobileConnectionWizard->args().count() == 2) { //GSM or CDMA qCDebug(PLASMA_NM) << "Creating new DUN connection for BT device:" << bdAddr; QVariantMap tmp = qdbus_cast(mobileConnectionWizard->args().value(1)); NetworkManager::ConnectionSettings connectionSettings(NetworkManager::ConnectionSettings::Bluetooth, NM_BT_CAPABILITY_DUN); connectionSettings.setUuid(NetworkManager::ConnectionSettings::createNewUuid()); connectionSettings.setId(connectionName); NetworkManager::BluetoothSetting::Ptr btSetting = connectionSettings.setting(NetworkManager::Setting::Bluetooth).staticCast(); btSetting->setBluetoothAddress(NetworkManager::macAddressFromString(bdAddr)); btSetting->setProfileType(NetworkManager::BluetoothSetting::Dun); btSetting->setInitialized(true); if (mobileConnectionWizard->type() == NetworkManager::ConnectionSettings::Gsm) { connectionSettings.setting(NetworkManager::Setting::Gsm)->fromMap(tmp); connectionSettings.setting(NetworkManager::Setting::Gsm)->setInitialized(true); } else if (mobileConnectionWizard->type() == NetworkManager::ConnectionSettings::Cdma) { connectionSettings.setting(NetworkManager::Setting::Cdma)->fromMap(tmp); connectionSettings.setting(NetworkManager::Setting::Cdma)->setInitialized(true); } qCDebug(PLASMA_NM) << "Adding DUN connection" << connectionSettings; NetworkManager::addConnection(connectionSettings.toMap()); } } }); connect(mobileConnectionWizard.data(), &MobileConnectionWizard::finished, [mobileConnectionWizard] () { if (mobileConnectionWizard) { mobileConnectionWizard->deleteLater(); } }); mobileConnectionWizard->setModal(true); mobileConnectionWizard->show(); } #endif } diff --git a/kded/modemmonitor.cpp b/kded/modemmonitor.cpp index 27eee8a8..a03a6aa8 100644 --- a/kded/modemmonitor.cpp +++ b/kded/modemmonitor.cpp @@ -1,209 +1,209 @@ /* Copyright 2009 Will Stephenson Copyright 2013 Lukas Tinkl Copyright 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 "debug.h" #include "modemmonitor.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pindialog.h" class ModemMonitorPrivate { public: QWeakPointer dialog; }; ModemMonitor::ModemMonitor(QObject * parent) :QObject(parent), d_ptr(new ModemMonitorPrivate) { Q_D(ModemMonitor); d->dialog.clear(); KSharedConfigPtr config = KSharedConfig::openConfig(QLatin1String("plasma-nm")); KConfigGroup grp(config, QLatin1String("General")); if (grp.isValid()) { if (grp.readEntry(QLatin1String("UnlockModemOnDetection"), true)) { connect(ModemManager::notifier(), &ModemManager::Notifier::modemAdded, this, &ModemMonitor::unlockModem); - Q_FOREACH (const ModemManager::ModemDevice::Ptr &iface, ModemManager::modemDevices()) { + for (const ModemManager::ModemDevice::Ptr &iface : ModemManager::modemDevices()) { unlockModem(iface->uni()); } } } } ModemMonitor::~ModemMonitor() { delete d_ptr; } void ModemMonitor::unlockModem(const QString &modemUni) { Q_D(ModemMonitor); ModemManager::Modem::Ptr modem; ModemManager::ModemDevice::Ptr modemDevice = ModemManager::findModemDevice(modemUni); if (modemDevice) { modem = modemDevice->interface(ModemManager::ModemDevice::ModemInterface).objectCast(); } else { return; } connect(modem.data(), &ModemManager::Modem::unlockRequiredChanged, this, &ModemMonitor::requestPin, Qt::UniqueConnection); if (d->dialog || (modem && modem->unlockRequired() == MM_MODEM_LOCK_NONE) || (modem && modem->unlockRequired() == MM_MODEM_LOCK_UNKNOWN)) { return; } if (modem) { // Using queued invocation to prevent kded stalling here until user enters the pin. QMetaObject::invokeMethod(modem.data(), "unlockRequiredChanged", Qt::QueuedConnection, Q_ARG(MMModemLock, modem->unlockRequired())); } } void ModemMonitor::requestPin(MMModemLock lock) { Q_D(ModemMonitor); qCDebug(PLASMA_NM) << "unlockRequired == " << lock; // Handle just SIM-PIN and SIM-PUK, because some other types may cause problems and they are not also handled by nm-applet if (lock == MM_MODEM_LOCK_NONE || lock == MM_MODEM_LOCK_UNKNOWN || (lock != MM_MODEM_LOCK_SIM_PIN && lock != MM_MODEM_LOCK_SIM_PUK)) { return; } ModemManager::Modem *modem = qobject_cast(sender()); if (!modem) { return; } if (d->dialog) { qCDebug(PLASMA_NM) << "PinDialog already running"; return; } if (lock == MM_MODEM_LOCK_SIM_PIN) { d->dialog = new PinDialog(modem, PinDialog::SimPin); } else if (lock == MM_MODEM_LOCK_SIM_PIN2) { d->dialog = new PinDialog(modem, PinDialog::SimPin2); } else if (lock == MM_MODEM_LOCK_SIM_PUK) { d->dialog = new PinDialog(modem, PinDialog::SimPuk); } else if (lock == MM_MODEM_LOCK_SIM_PUK2 ) { d->dialog = new PinDialog(modem, PinDialog::SimPuk); } else if (lock == MM_MODEM_LOCK_PH_SP_PIN) { d->dialog = new PinDialog(modem, PinDialog::ModemServiceProviderPin); } else if (lock == MM_MODEM_LOCK_PH_SP_PUK) { d->dialog = new PinDialog(modem, PinDialog::ModemServiceProviderPuk); } else if (lock == MM_MODEM_LOCK_PH_NET_PIN) { d->dialog = new PinDialog(modem, PinDialog::ModemNetworkPin); } else if (lock == MM_MODEM_LOCK_PH_NET_PUK) { d->dialog = new PinDialog(modem, PinDialog::ModemNetworkPuk); } else if (lock == MM_MODEM_LOCK_PH_SIM_PIN) { d->dialog = new PinDialog(modem, PinDialog::ModemPin); } else if (lock == MM_MODEM_LOCK_PH_CORP_PIN) { d->dialog = new PinDialog(modem, PinDialog::ModemCorporatePin); } else if (lock == MM_MODEM_LOCK_PH_CORP_PUK) { d->dialog = new PinDialog(modem, PinDialog::ModemCorporatePuk); } else if (lock == MM_MODEM_LOCK_PH_FSIM_PIN) { d->dialog = new PinDialog(modem, PinDialog::ModemPhFsimPin); } else if (lock == MM_MODEM_LOCK_PH_FSIM_PUK) { d->dialog = new PinDialog(modem, PinDialog::ModemPhFsimPuk); } else if (lock == MM_MODEM_LOCK_PH_NETSUB_PIN) { d->dialog = new PinDialog(modem, PinDialog::ModemNetworkSubsetPin); } else if (lock == MM_MODEM_LOCK_PH_NETSUB_PUK) { d->dialog = new PinDialog(modem, PinDialog::ModemNetworkSubsetPuk); } if (d->dialog.data()->exec() != QDialog::Accepted) { goto OUT; } qCDebug(PLASMA_NM) << "Sending unlock code"; { ModemManager::Sim::Ptr sim; ModemManager::ModemDevice::Ptr modemDevice = ModemManager::findModemDevice(modem->uni()); if (modemDevice && modemDevice->sim()) { sim = modemDevice->sim(); } if (!sim) { return; } QDBusPendingCallWatcher *watcher = nullptr; PinDialog::Type type = d->dialog.data()->type(); if (type == PinDialog::SimPin || type == PinDialog::SimPin2 || type == PinDialog::ModemServiceProviderPin || type == PinDialog::ModemNetworkPin || type == PinDialog::ModemPin || type == PinDialog::ModemCorporatePin || type == PinDialog::ModemPhFsimPin || type == PinDialog::ModemNetworkSubsetPin) { QDBusPendingCall reply = sim->sendPin(d->dialog.data()->pin()); watcher = new QDBusPendingCallWatcher(reply, sim.data()); } else if (type == PinDialog::SimPuk || type == PinDialog::SimPuk2 || type == PinDialog::ModemServiceProviderPuk || type == PinDialog::ModemNetworkPuk || type == PinDialog::ModemCorporatePuk || type == PinDialog::ModemPhFsimPuk || type == PinDialog::ModemNetworkSubsetPuk) { QDBusPendingCall reply = sim->sendPuk(d->dialog.data()->puk(), d->dialog.data()->pin()); watcher = new QDBusPendingCallWatcher(reply, sim.data()); } connect(watcher, &QDBusPendingCallWatcher::finished, this, &ModemMonitor::onSendPinArrived); } OUT: if(d->dialog) { d->dialog.data()->deleteLater(); } d->dialog.clear(); } void ModemMonitor::onSendPinArrived(QDBusPendingCallWatcher * watcher) { QDBusPendingReply<> reply = *watcher; if (reply.isValid()) { // Automatically enabling this for cell phones with expensive data plans is not a good idea. //NetworkManager::setWwanEnabled(true); } else { KMessageBox::error(nullptr, i18nc("Text in GSM PIN/PUK unlock error dialog", "Error unlocking modem: %1", reply.error().message()), i18nc("Title for GSM PIN/PUK unlock error dialog", "PIN/PUK unlock error")); } watcher->deleteLater(); } diff --git a/kded/notification.cpp b/kded/notification.cpp index 8456307b..09e1d449 100644 --- a/kded/notification.cpp +++ b/kded/notification.cpp @@ -1,610 +1,610 @@ /* Copyright 2009 Will Stephenson Copyright 2013 by Daniel Nicoletti Copyright 2013 Lukas Tinkl 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 "debug.h" #include "notification.h" #include #include #include #include #include #include #include #include Notification::Notification(QObject *parent) : QObject(parent) { // devices - Q_FOREACH (const NetworkManager::Device::Ptr &device, NetworkManager::networkInterfaces()) { + for (const NetworkManager::Device::Ptr &device : NetworkManager::networkInterfaces()) { addDevice(device); } connect(NetworkManager::notifier(), &NetworkManager::Notifier::deviceAdded, this, &Notification::deviceAdded); // connections - Q_FOREACH (const NetworkManager::ActiveConnection::Ptr &ac, NetworkManager::activeConnections()) { + for (const NetworkManager::ActiveConnection::Ptr &ac : NetworkManager::activeConnections()) { addActiveConnection(ac); } connect(NetworkManager::notifier(), &NetworkManager::Notifier::activeConnectionAdded, this, QOverload::of(&Notification::addActiveConnection)); QDBusConnection::systemBus().connect(QStringLiteral("org.freedesktop.login1"), QStringLiteral("/org/freedesktop/login1"), QStringLiteral("org.freedesktop.login1.Manager"), QStringLiteral("PrepareForSleep"), this, SLOT(onPrepareForSleep(bool))); } void Notification::deviceAdded(const QString &uni) { NetworkManager::Device::Ptr device = NetworkManager::findNetworkInterface(uni); addDevice(device); } void Notification::addDevice(const NetworkManager::Device::Ptr &device) { connect(device.data(), &NetworkManager::Device::stateChanged, this, &Notification::stateChanged); } void Notification::stateChanged(NetworkManager::Device::State newstate, NetworkManager::Device::State oldstate, NetworkManager::Device::StateChangeReason reason) { Q_UNUSED(oldstate) NetworkManager::Device *device = qobject_cast(sender()); if (newstate == NetworkManager::Device::Activated && m_notifications.contains(device->uni())) { KNotification *notify = m_notifications.value(device->uni()); notify->deleteLater(); m_notifications.remove(device->uni()); return; } else if (newstate != NetworkManager::Device::Failed) { return; } const QString identifier = UiUtils::prettyInterfaceName(device->type(), device->interfaceName()); QString text; switch (reason) { case NetworkManager::Device::NoReason: case NetworkManager::Device::UnknownReason: case NetworkManager::Device::NowManagedReason: case NetworkManager::Device::NowUnmanagedReason: return; case NetworkManager::Device::ConfigFailedReason: text = i18nc("@info:status Notification when the device failed due to ConfigFailedReason", "The device could not be configured"); break; case NetworkManager::Device::ConfigUnavailableReason: text = i18nc("@info:status Notification when the device failed due to ConfigUnavailableReason", "IP configuration was unavailable"); break; case NetworkManager::Device::ConfigExpiredReason: text = i18nc("@info:status Notification when the device failed due to ConfigExpiredReason", "IP configuration expired"); break; case NetworkManager::Device::NoSecretsReason: text = i18nc("@info:status Notification when the device failed due to NoSecretsReason", "No secrets were provided"); break; case NetworkManager::Device::AuthSupplicantDisconnectReason: text = i18nc("@info:status Notification when the device failed due to AuthSupplicantDisconnectReason", "Authorization supplicant disconnected"); break; case NetworkManager::Device::AuthSupplicantConfigFailedReason: text = i18nc("@info:status Notification when the device failed due to AuthSupplicantConfigFailedReason", "Authorization supplicant's configuration failed"); break; case NetworkManager::Device::AuthSupplicantFailedReason: text = i18nc("@info:status Notification when the device failed due to AuthSupplicantFailedReason", "Authorization supplicant failed"); break; case NetworkManager::Device::AuthSupplicantTimeoutReason: text = i18nc("@info:status Notification when the device failed due to AuthSupplicantTimeoutReason", "Authorization supplicant timed out"); break; case NetworkManager::Device::PppStartFailedReason: text = i18nc("@info:status Notification when the device failed due to PppStartFailedReason", "PPP failed to start"); break; case NetworkManager::Device::PppDisconnectReason: text = i18nc("@info:status Notification when the device failed due to PppDisconnectReason", "PPP disconnected"); break; case NetworkManager::Device::PppFailedReason: text = i18nc("@info:status Notification when the device failed due to PppFailedReason", "PPP failed"); break; case NetworkManager::Device::DhcpStartFailedReason: text = i18nc("@info:status Notification when the device failed due to DhcpStartFailedReason", "DHCP failed to start"); break; case NetworkManager::Device::DhcpErrorReason: text = i18nc("@info:status Notification when the device failed due to DhcpErrorReason", "A DHCP error occurred"); break; case NetworkManager::Device::DhcpFailedReason: text = i18nc("@info:status Notification when the device failed due to DhcpFailedReason", "DHCP failed "); break; case NetworkManager::Device::SharedStartFailedReason: text = i18nc("@info:status Notification when the device failed due to SharedStartFailedReason", "The shared service failed to start"); break; case NetworkManager::Device::SharedFailedReason: text = i18nc("@info:status Notification when the device failed due to SharedFailedReason", "The shared service failed"); break; case NetworkManager::Device::AutoIpStartFailedReason: text = i18nc("@info:status Notification when the device failed due to AutoIpStartFailedReason", "The auto IP service failed to start"); break; case NetworkManager::Device::AutoIpErrorReason: text = i18nc("@info:status Notification when the device failed due to AutoIpErrorReason", "The auto IP service reported an error"); break; case NetworkManager::Device::AutoIpFailedReason: text = i18nc("@info:status Notification when the device failed due to AutoIpFailedReason", "The auto IP service failed"); break; case NetworkManager::Device::ModemBusyReason: text = i18nc("@info:status Notification when the device failed due to ModemBusyReason", "The modem is busy"); break; case NetworkManager::Device::ModemNoDialToneReason: text = i18nc("@info:status Notification when the device failed due to ModemNoDialToneReason", "The modem has no dial tone"); break; case NetworkManager::Device::ModemNoCarrierReason: text = i18nc("@info:status Notification when the device failed due to ModemNoCarrierReason", "The modem shows no carrier"); break; case NetworkManager::Device::ModemDialTimeoutReason: text = i18nc("@info:status Notification when the device failed due to ModemDialTimeoutReason", "The modem dial timed out"); break; case NetworkManager::Device::ModemDialFailedReason: text = i18nc("@info:status Notification when the device failed due to ModemDialFailedReason", "The modem dial failed"); break; case NetworkManager::Device::ModemInitFailedReason: text = i18nc("@info:status Notification when the device failed due to ModemInitFailedReason", "The modem could not be initialized"); break; case NetworkManager::Device::GsmApnSelectFailedReason: text = i18nc("@info:status Notification when the device failed due to GsmApnSelectFailedReason", "The GSM APN could not be selected"); break; case NetworkManager::Device::GsmNotSearchingReason: text = i18nc("@info:status Notification when the device failed due to GsmNotSearchingReason", "The GSM modem is not searching"); break; case NetworkManager::Device::GsmRegistrationDeniedReason: text = i18nc("@info:status Notification when the device failed due to GsmRegistrationDeniedReason", "GSM network registration was denied"); break; case NetworkManager::Device::GsmRegistrationTimeoutReason: text = i18nc("@info:status Notification when the device failed due to GsmRegistrationTimeoutReason", "GSM network registration timed out"); break; case NetworkManager::Device::GsmRegistrationFailedReason: text = i18nc("@info:status Notification when the device failed due to GsmRegistrationFailedReason", "GSM registration failed"); break; case NetworkManager::Device::GsmPinCheckFailedReason: text = i18nc("@info:status Notification when the device failed due to GsmPinCheckFailedReason", "The GSM PIN check failed"); break; case NetworkManager::Device::FirmwareMissingReason: text = i18nc("@info:status Notification when the device failed due to FirmwareMissingReason", "Device firmware is missing"); break; case NetworkManager::Device::DeviceRemovedReason: text = i18nc("@info:status Notification when the device failed due to DeviceRemovedReason", "The device was removed"); break; case NetworkManager::Device::SleepingReason: text = i18nc("@info:status Notification when the device failed due to SleepingReason", "The networking system is now sleeping"); break; case NetworkManager::Device::ConnectionRemovedReason: text = i18nc("@info:status Notification when the device failed due to ConnectionRemovedReason", "The connection was removed"); break; case NetworkManager::Device::UserRequestedReason: return; case NetworkManager::Device::CarrierReason: text = i18nc("@info:status Notification when the device failed due to CarrierReason", "The cable was disconnected"); break; case NetworkManager::Device::ConnectionAssumedReason: case NetworkManager::Device::SupplicantAvailableReason: return; case NetworkManager::Device::ModemNotFoundReason: text = i18nc("@info:status Notification when the device failed due to ModemNotFoundReason", "The modem could not be found"); break; case NetworkManager::Device::BluetoothFailedReason: text = i18nc("@info:status Notification when the device failed due to BluetoothFailedReason", "The bluetooth connection failed or timed out"); break; case NetworkManager::Device::GsmSimNotInserted: text = i18nc("@info:status Notification when the device failed due to GsmSimNotInserted", "GSM Modem's SIM Card not inserted"); break; case NetworkManager::Device::GsmSimPinRequired: text = i18nc("@info:status Notification when the device failed due to GsmSimPinRequired", "GSM Modem's SIM Pin required"); break; case NetworkManager::Device::GsmSimPukRequired: text = i18nc("@info:status Notification when the device failed due to GsmSimPukRequired", "GSM Modem's SIM Puk required"); break; case NetworkManager::Device::GsmSimWrong: text = i18nc("@info:status Notification when the device failed due to GsmSimWrong", "GSM Modem's SIM wrong"); break; case NetworkManager::Device::InfiniBandMode: text = i18nc("@info:status Notification when the device failed due to InfiniBandMode", "InfiniBand device does not support connected mode"); break; case NetworkManager::Device::DependencyFailed: text = i18nc("@info:status Notification when the device failed due to DependencyFailed", "A dependency of the connection failed"); break; case NetworkManager::Device::Br2684Failed: text = i18nc("@info:status Notification when the device failed due to Br2684Failed", "Problem with the RFC 2684 Ethernet over ADSL bridge"); break; case NetworkManager::Device::ModemManagerUnavailable: text = i18nc("@info:status Notification when the device failed due to ModemManagerUnavailable", "ModemManager not running"); break; case NetworkManager::Device::SsidNotFound: text = i18nc("@info:status Notification when the device failed due to SsidNotFound", "The WiFi network could not be found"); break; case NetworkManager::Device::SecondaryConnectionFailed: text = i18nc("@info:status Notification when the device failed due to SecondaryConnectionFailed", "A secondary connection of the base connection failed"); break; #if NM_CHECK_VERSION(0, 9, 10) case NetworkManager::Device::DcbFcoeFailed: text = i18nc("@info:status Notification when the device failed due to DcbFcoeFailed", "DCB or FCoE setup failed"); break; case NetworkManager::Device::TeamdControlFailed: text = i18nc("@info:status Notification when the device failed due to TeamdControlFailed", "teamd control failed"); break; case NetworkManager::Device::ModemFailed: text = i18nc("@info:status Notification when the device failed due to ModemFailed", "Modem failed or no longer available"); break; case NetworkManager::Device::ModemAvailable: text = i18nc("@info:status Notification when the device failed due to ModemAvailable", "Modem now ready and available"); break; case NetworkManager::Device::SimPinIncorrect: text = i18nc("@info:status Notification when the device failed due to SimPinIncorrect", "The SIM PIN was incorrect"); break; #endif #if NM_CHECK_VERSION(1, 0, 4) case NetworkManager::Device::NewActivation: text = i18nc("@info:status Notification when the device failed due to NewActivation", "A new connection activation was enqueued"); break; case NetworkManager::Device::ParentChanged: text = i18nc("@info:status Notification when the device failed due to ParentChanged", "The device's parent changed"); break; case NetworkManager::Device::ParentManagedChanged: text = i18nc("@info:status Notification when the device failed due to ParentManagedChanged", "The device parent's management changed"); break; #endif case NetworkManager::Device::Reserved: return; } if (m_notifications.contains(device->uni())) { KNotification *notify = m_notifications.value(device->uni()); notify->setText(text); notify->update(); } else { KNotification *notify = new KNotification(QStringLiteral("DeviceFailed"), KNotification::CloseOnTimeout, this); connect(notify, &KNotification::closed, this, &Notification::notificationClosed); notify->setProperty("uni", device->uni()); notify->setComponentName(QStringLiteral("networkmanagement")); notify->setPixmap(QIcon::fromTheme(QStringLiteral("dialog-warning")).pixmap(KIconLoader::SizeHuge)); notify->setTitle(identifier); notify->setText(text); notify->sendEvent(); if (notify->id() != -1) { m_notifications[device->uni()] = notify; } } } void Notification::addActiveConnection(const QString &path) { NetworkManager::ActiveConnection::Ptr ac = NetworkManager::findActiveConnection(path); if (ac && ac->isValid()) { addActiveConnection(ac); } } void Notification::addActiveConnection(const NetworkManager::ActiveConnection::Ptr &ac) { if (ac->vpn()) { NetworkManager::VpnConnection::Ptr vpnConnection = ac.objectCast(); connect(vpnConnection.data(), &NetworkManager::VpnConnection::stateChanged, this, &Notification::onVpnConnectionStateChanged); #if NM_CHECK_VERSION(0, 9, 10) } else if (ac->type() != NetworkManager::ConnectionSettings::Bond && ac->type() != NetworkManager::ConnectionSettings::Bridge && ac->type() != NetworkManager::ConnectionSettings::Generic && ac->type() != NetworkManager::ConnectionSettings::Infiniband && ac->type() != NetworkManager::ConnectionSettings::Team && #if NM_CHECK_VERSION(1, 1, 92) ac->type() != NetworkManager::ConnectionSettings::Vlan && ac->type() != NetworkManager::ConnectionSettings::Tun) { #else ac->type() != NetworkManager::ConnectionSettings::Vlan) { #endif #else } else if (ac->type() != NetworkManager::ConnectionSettings::Bond && ac->type() != NetworkManager::ConnectionSettings::Bridge && ac->type() != NetworkManager::ConnectionSettings::Infiniband && ac->type() != NetworkManager::ConnectionSettings::Vlan) { #endif connect(ac.data(), &NetworkManager::ActiveConnection::stateChanged, this, &Notification::onActiveConnectionStateChanged); } } void Notification::onActiveConnectionStateChanged(NetworkManager::ActiveConnection::State state) { NetworkManager::ActiveConnection *ac = qobject_cast(sender()); QString eventId, text, iconName; const QString acName = ac->id(); const QString connectionId = ac->path(); if (state == NetworkManager::ActiveConnection::Activated) { auto foundConnection = std::find_if(m_activeConnectionsBeforeSleep.constBegin(), m_activeConnectionsBeforeSleep.constEnd(), [ac](const QString &uuid) { return uuid == ac->uuid(); }); if (foundConnection != m_activeConnectionsBeforeSleep.constEnd()) { qCDebug(PLASMA_NM) << "Not emitting connection activated notification as the connection was active prior to suspend"; return; } eventId = QStringLiteral("ConnectionActivated"); text = i18n("Connection '%1' activated.", acName); switch (ac->type()) { case NetworkManager::ConnectionSettings::Wireless: iconName = QStringLiteral("network-wireless-on"); break; case NetworkManager::ConnectionSettings::Wired: iconName = QStringLiteral("network-wired-activated"); break; default: // silence warning break; } } else if (state == NetworkManager::ActiveConnection::Deactivated) { if (m_preparingForSleep) { qCDebug(PLASMA_NM) << "Not emitting connection deactivated notification as we're about to suspend"; return; } eventId = QStringLiteral("ConnectionDeactivated"); text = i18n("Connection '%1' deactivated.", acName); switch (ac->type()) { case NetworkManager::ConnectionSettings::Wireless: iconName = QStringLiteral("network-wireless-disconnected"); break; case NetworkManager::ConnectionSettings::Wired: iconName = QStringLiteral("network-unavailable"); break; default: // silence warning break; } } else { qCWarning(PLASMA_NM) << "Unhandled active connection state change: " << state; return; } KNotification *notify = new KNotification(eventId, KNotification::CloseOnTimeout, this); connect(notify, &KNotification::closed, this, &Notification::notificationClosed); notify->setProperty("uni", connectionId); notify->setComponentName(QStringLiteral("networkmanagement")); if (!iconName.isEmpty()) { notify->setIconName(iconName); } else { if (state == NetworkManager::ActiveConnection::Activated) { notify->setIconName(QStringLiteral("dialog-information")); } else { notify->setIconName(QStringLiteral("dialog-warning")); } } notify->setTitle(acName); notify->setText(text); notify->sendEvent(); if (notify->id() != -1) { m_notifications[connectionId] = notify; } } void Notification::onVpnConnectionStateChanged(NetworkManager::VpnConnection::State state, NetworkManager::VpnConnection::StateChangeReason reason) { NetworkManager::VpnConnection *vpn = qobject_cast(sender()); QString eventId, text; const QString vpnName = vpn->connection()->name(); const QString connectionId = vpn->path(); if (state == NetworkManager::VpnConnection::Activated) { eventId = QStringLiteral("ConnectionActivated"); text = i18n("VPN connection '%1' activated.", vpnName); } else if (state == NetworkManager::VpnConnection::Failed) { eventId = QStringLiteral("FailedToActivateConnection"); text = i18n("VPN connection '%1' failed.", vpnName); } else if (state == NetworkManager::VpnConnection::Disconnected) { eventId = QStringLiteral("ConnectionDeactivated"); text = i18n("VPN connection '%1' disconnected.", vpnName); } else { qCWarning(PLASMA_NM) << "Unhandled VPN connection state change: " << state; return; } switch (reason) { case NetworkManager::VpnConnection::UserDisconnectedReason: text = i18n("The VPN connection changed state because the user disconnected it."); break; case NetworkManager::VpnConnection::DeviceDisconnectedReason: text = i18n("The VPN connection changed state because the device it was using was disconnected."); break; case NetworkManager::VpnConnection::ServiceStoppedReason: text = i18n("The service providing the VPN connection was stopped."); break; case NetworkManager::VpnConnection::IpConfigInvalidReason: text = i18n("The IP config of the VPN connection was invalid."); break; case NetworkManager::VpnConnection::ConnectTimeoutReason: text = i18n("The connection attempt to the VPN service timed out."); break; case NetworkManager::VpnConnection::ServiceStartTimeoutReason: text = i18n("A timeout occurred while starting the service providing the VPN connection."); break; case NetworkManager::VpnConnection::ServiceStartFailedReason: text = i18n("Starting the service providing the VPN connection failed."); break; case NetworkManager::VpnConnection::NoSecretsReason: text = i18n("Necessary secrets for the VPN connection were not provided."); break; case NetworkManager::VpnConnection::LoginFailedReason: text = i18n("Authentication to the VPN server failed."); break; case NetworkManager::VpnConnection::ConnectionRemovedReason: text = i18n("The connection was deleted from settings."); break; default: case NetworkManager::VpnConnection::UnknownReason: case NetworkManager::VpnConnection::NoneReason: break; } KNotification *notify = new KNotification(eventId, KNotification::CloseOnTimeout, this); connect(notify, &KNotification::closed, this, &Notification::notificationClosed); notify->setProperty("uni", connectionId); notify->setComponentName("networkmanagement"); if (state == NetworkManager::VpnConnection::Activated) { notify->setIconName(QStringLiteral("dialog-information")); } else { notify->setIconName(QStringLiteral("dialog-warning")); } notify->setTitle(vpnName); notify->setText(text); notify->sendEvent(); if (notify->id() != -1) { m_notifications[connectionId] = notify; } } void Notification::notificationClosed() { KNotification *notify = qobject_cast(sender()); m_notifications.remove(notify->property("uni").toString()); notify->deleteLater(); } void Notification::onPrepareForSleep(bool sleep) { m_preparingForSleep = sleep; if (m_checkActiveConnectionOnResumeTimer) { m_checkActiveConnectionOnResumeTimer->stop(); } if (sleep) { // store all active notifications so we don't show a "is connected" notification // on resume if we were connected previously m_activeConnectionsBeforeSleep.clear(); const auto &connections = NetworkManager::activeConnections(); for (const auto &connection : connections) { if (!connection->vpn() && connection->state() == NetworkManager::ActiveConnection::State::Activated) { m_activeConnectionsBeforeSleep << connection->uuid(); } } } else { if (!m_checkActiveConnectionOnResumeTimer) { m_checkActiveConnectionOnResumeTimer = new QTimer(this); m_checkActiveConnectionOnResumeTimer->setInterval(10000); m_checkActiveConnectionOnResumeTimer->setSingleShot(true); connect(m_checkActiveConnectionOnResumeTimer, &QTimer::timeout, this, &Notification::onCheckActiveConnectionOnResume); } m_checkActiveConnectionOnResumeTimer->start(); } } void Notification::onCheckActiveConnectionOnResume() { if (m_activeConnectionsBeforeSleep.isEmpty()) { // if we weren't connected before, don't bother telling us now :) return; } m_activeConnectionsBeforeSleep.clear(); const auto &connections = NetworkManager::activeConnections(); for (const auto &connection : connections) { if (connection->state() == NetworkManager::ActiveConnection::State::Activated || connection->state() == NetworkManager::ActiveConnection::State::Activating) { // we have an active or activating connection, don't tell the user we're no longer connected return; } } KNotification *notify = new KNotification(QStringLiteral("NoLongerConnected"), KNotification::CloseOnTimeout, this); connect(notify, &KNotification::closed, this, &Notification::notificationClosed); const QString uni = QStringLiteral("offlineNotification"); notify->setProperty("uni", uni); notify->setComponentName("networkmanagement"); notify->setIconName(QStringLiteral("dialog-warning")); notify->setTitle(i18n("No Network Connection")); notify->setText(i18n("You are no longer connected to a network.")); notify->sendEvent(); if (notify->id() != -1) { m_notifications[uni] = notify; } } diff --git a/kded/pindialog.cpp b/kded/pindialog.cpp index b256fc9c..ed4ab3d4 100644 --- a/kded/pindialog.cpp +++ b/kded/pindialog.cpp @@ -1,270 +1,270 @@ /* Copyright 2011 Lamarque Souza Copyright 2013 Lukas Tinkl This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License or (at your option) version 3 or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of version 3 of the license. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "pindialog.h" #include #include #include #include #include #include #include PinDialog::PinDialog(ModemManager::Modem *modem, const Type type, QWidget *parent) : QDialog(parent), m_type(type) { if (modem) { m_udi = modem->uni(); m_name = modem->device(); - Q_FOREACH (const Solid::Device &d, Solid::Device::allDevices()) { + for (const Solid::Device &d : Solid::Device::allDevices()) { if (d.udi().contains(m_name, Qt::CaseInsensitive)) { m_name = d.product(); if (!m_name.startsWith(d.vendor())) { m_name = d.vendor() % ' ' % m_name; } break; } } } ui = new Ui::PinWidget(); ui->setupUi(this); ui->pin->setPasswordMode(true); QIntValidator * validator = new QIntValidator(this); validator->setRange(1000, 99999999); ui->pin->setValidator(validator); ui->pin2->setValidator(validator); QIntValidator * validator2 = new QIntValidator(this); validator2->setRange(10000000, 99999999); ui->puk->setValidator(validator2); ui->errorMessage->setHidden(true); QRect desktop = QApplication::desktop()->screenGeometry(topLevelWidget()); setMinimumWidth(qMin(1000, qMax(sizeHint().width(), desktop.width() / 4))); pixmapLabel = new QLabel(this); pixmapLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop); ui->gridLayout->addWidget(pixmapLabel, 0, 0); pixmapLabel->setPixmap(QIcon::fromTheme(QStringLiteral("dialog-password")).pixmap(KIconLoader::SizeMedium)); connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &PinDialog::accept); connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &PinDialog::reject); if (isPukDialog()) { QString pukType; if (m_type == PinDialog::SimPuk) { pukType = i18n("SIM PUK"); } else if (m_type == PinDialog::SimPuk2) { pukType = i18n("SIM PUK2"); } else if (m_type == PinDialog::ModemServiceProviderPuk) { pukType = i18n("Service provider PUK"); } else if (m_type == PinDialog::ModemNetworkPuk) { pukType = i18n("Network PUK"); } else if (m_type == PinDialog::ModemCorporatePuk) { pukType = i18n("Corporate PUK"); } else if (m_type == PinDialog::ModemPhFsimPuk) { pukType = i18n("PH-FSIM PUK"); } else { pukType = i18n("Network Subset PUK"); } setWindowTitle(i18n("%1 unlock required", pukType)); ui->title->setText(i18n("%1 Unlock Required", pukType)); ui->prompt->setText(i18n("The mobile broadband device '%1' requires a %2 code before it can be used.", m_name, pukType)); ui->pukLabel->setText(i18n("%1 code:",pukType)); ui->pinLabel->setText(i18n("New PIN code:")); ui->pin2Label->setText(i18n("Re-enter new PIN code:")); ui->chkShowPass->setText(i18n("Show PIN/PUK code")); ui->puk->setFocus(); ui->pukLabel->show(); ui->puk->show(); ui->pin2Label->show(); ui->pin2->show(); } else if (isPinDialog()) { QString pinType; if (m_type == PinDialog::SimPin) { pinType = i18n("SIM PIN"); } else if (m_type == PinDialog::SimPin2) { pinType = i18n("SIM PIN2"); } else if (m_type == PinDialog::ModemServiceProviderPin) { pinType = i18n("Service provider PIN"); } else if (m_type == PinDialog::ModemNetworkPin) { pinType = i18n("Network PIN"); } else if (m_type == PinDialog::ModemPin) { pinType = i18n("PIN"); } else if (m_type == PinDialog::ModemCorporatePin) { pinType = i18n("Corporate PIN"); } else if (m_type == PinDialog::ModemPhFsimPin) { pinType = i18n("PH-FSIM PIN"); } else { pinType = i18n("Network Subset PIN"); } setWindowTitle(i18n("%1 unlock required", pinType)); ui->title->setText(i18n("%1 Unlock Required", pinType)); ui->prompt->setText(i18n("The mobile broadband device '%1' requires a %2 code before it can be used.", m_name, pinType)); ui->pinLabel->setText(i18n("%1 code:", pinType)); ui->chkShowPass->setText(i18n("Show PIN code")); ui->pin->setFocus(); ui->pukLabel->hide(); ui->puk->hide(); ui->pin2Label->hide(); ui->pin2->hide(); } ui->puk->clear(); ui->pin->clear(); ui->pin2->clear(); ui->puk->setCursorPosition(0); ui->pin->setCursorPosition(0); ui->pin2->setCursorPosition(0); KWindowSystem::setState(winId(), NET::KeepAbove); KWindowSystem::activateWindow(winId()); move((desktop.width() - width()) / 2, (desktop.height() - height()) / 2); connect(ui->chkShowPass, &QCheckBox::toggled, this, &PinDialog::chkShowPassToggled); connect(ModemManager::notifier(), &ModemManager::Notifier::modemRemoved, this, &PinDialog::modemRemoved); } PinDialog::~PinDialog() { delete ui; } void PinDialog::chkShowPassToggled(bool on) { ui->pin->setPasswordMode(!on); ui->pin2->setPasswordMode(!on); ui->puk->setPasswordMode(!on); ui->puk->setCursorPosition(0); ui->pin->setCursorPosition(0); ui->pin2->setCursorPosition(0); if (isPukDialog()) { ui->puk->setFocus(); } else { ui->pin->setFocus(); } } void PinDialog::modemRemoved(const QString &udi) { if (udi == m_udi) { reject(); } } PinDialog::Type PinDialog::type() const { return m_type; } QString PinDialog::pin() const { return ui->pin->text(); } QString PinDialog::pin2() const { return ui->pin2->text(); } QString PinDialog::puk() const { return ui->puk->text(); } void PinDialog::showErrorMessage(const PinDialog::ErrorCode error) { QString msg; QFont bold = font(); ui->pinLabel->setFont(bold); ui->pin2Label->setFont(bold); ui->pukLabel->setFont(bold); bold.setBold(true); switch(error) { case PinCodeTooShort: msg = i18n("PIN code too short. It should be at least 4 digits."); ui->pin->setFocus(); ui->pinLabel->setFont(bold); break; case PinCodesDoNotMatch: msg = i18n("The two PIN codes do not match"); ui->pin2->setFocus(); ui->pin2Label->setFont(bold); break; case PukCodeTooShort: msg = i18n("PUK code too short. It should be 8 digits."); ui->puk->setFocus(); ui->pukLabel->setFont(bold); break; default: msg = i18n("Unknown Error"); } ui->errorMessage->setText(msg, KTitleWidget::ErrorMessage); adjustSize(); } void PinDialog::accept() { if (isPukDialog()) { if (pin() != pin2()) { showErrorMessage(PinCodesDoNotMatch); return; } else if (puk().length() < 8) { showErrorMessage(PukCodeTooShort); return; } } if (pin().length() < 4) { showErrorMessage(PinCodeTooShort); return; } QDialog::accept(); } bool PinDialog::isPinDialog() const { return (m_type == PinDialog::SimPin || m_type == PinDialog::SimPin2 || m_type == PinDialog::ModemServiceProviderPin || m_type == PinDialog::ModemNetworkPin || m_type == PinDialog::ModemPin || m_type == PinDialog::ModemCorporatePin || m_type == PinDialog::ModemPhFsimPin || m_type == PinDialog::ModemNetworkSubsetPin); } bool PinDialog::isPukDialog() const { return !isPinDialog(); } diff --git a/kded/secretagent.cpp b/kded/secretagent.cpp index 702c4a5a..def38d4b 100644 --- a/kded/secretagent.cpp +++ b/kded/secretagent.cpp @@ -1,645 +1,650 @@ /* Copyright 2013 Jan Grulich Copyright 2013 Lukas Tinkl Copyright 2013 by Daniel Nicoletti 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 "passworddialog.h" #include "secretagent.h" #include "debug.h" +#include "configuration.h" + #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include SecretAgent::SecretAgent(QObject* parent) : NetworkManager::SecretAgent("org.kde.plasma.networkmanagement", parent) , m_openWalletFailed(false) , m_wallet(nullptr) , m_dialog(nullptr) { connect(NetworkManager::notifier(), &NetworkManager::Notifier::serviceDisappeared, this, &SecretAgent::killDialogs); // We have to import secrets previously stored in plaintext files importSecretsFromPlainTextFiles(); } SecretAgent::~SecretAgent() { } NMVariantMapMap SecretAgent::GetSecrets(const NMVariantMapMap &connection, const QDBusObjectPath &connection_path, const QString &setting_name, const QStringList &hints, uint flags) { qCDebug(PLASMA_NM) << Q_FUNC_INFO; qCDebug(PLASMA_NM) << "Path:" << connection_path.path(); qCDebug(PLASMA_NM) << "Setting name:" << setting_name; qCDebug(PLASMA_NM) << "Hints:" << hints; qCDebug(PLASMA_NM) << "Flags:" << flags; const QString callId = connection_path.path() % setting_name; - Q_FOREACH (const SecretsRequest & request, m_calls) { + for (const SecretsRequest &request : m_calls) { if (request == callId) { qCWarning(PLASMA_NM) << "GetSecrets was called again! This should not happen, cancelling first call" << connection_path.path() << setting_name; CancelGetSecrets(connection_path, setting_name); break; } } setDelayedReply(true); SecretsRequest request(SecretsRequest::GetSecrets); request.callId = callId; request.connection = connection; request.connection_path = connection_path; request.flags = static_cast(flags); request.hints = hints; request.setting_name = setting_name; request.message = message(); m_calls << request; processNext(); return NMVariantMapMap(); } void SecretAgent::SaveSecrets(const NMVariantMapMap &connection, const QDBusObjectPath &connection_path) { qCDebug(PLASMA_NM) << Q_FUNC_INFO; qCDebug(PLASMA_NM) << "Path:" << connection_path.path(); // qCDebug(PLASMA_NM) << "Setting:" << connection; setDelayedReply(true); SecretsRequest::Type type; if (hasSecrets(connection)) { type = SecretsRequest::SaveSecrets; } else { type = SecretsRequest::DeleteSecrets; } SecretsRequest request(type); request.connection = connection; request.connection_path = connection_path; request.message = message(); m_calls << request; processNext(); } void SecretAgent::DeleteSecrets(const NMVariantMapMap &connection, const QDBusObjectPath &connection_path) { qCDebug(PLASMA_NM) << Q_FUNC_INFO; qCDebug(PLASMA_NM) << "Path:" << connection_path.path(); // qCDebug(PLASMA_NM) << "Setting:" << connection; setDelayedReply(true); SecretsRequest request(SecretsRequest::DeleteSecrets); request.connection = connection; request.connection_path = connection_path; request.message = message(); m_calls << request; processNext(); } void SecretAgent::CancelGetSecrets(const QDBusObjectPath &connection_path, const QString &setting_name) { qCDebug(PLASMA_NM) << Q_FUNC_INFO; qCDebug(PLASMA_NM) << "Path:" << connection_path.path(); qCDebug(PLASMA_NM) << "Setting name:" << setting_name; QString callId = connection_path.path() % setting_name; for (int i = 0; i < m_calls.size(); ++i) { SecretsRequest request = m_calls.at(i); if (request.type == SecretsRequest::GetSecrets && callId == request.callId) { if (m_dialog == request.dialog) { m_dialog = nullptr; } delete request.dialog; sendError(SecretAgent::AgentCanceled, QLatin1String("Agent canceled the password dialog"), request.message); m_calls.removeAt(i); break; } } processNext(); } void SecretAgent::dialogAccepted() { for (int i = 0; i < m_calls.size(); ++i) { SecretsRequest request = m_calls[i]; if (request.type == SecretsRequest::GetSecrets && request.dialog == m_dialog) { NMStringMap tmpOpenconnectSecrets; NMVariantMapMap connection = request.dialog->secrets(); if (connection.contains(QLatin1String("vpn"))) { if (connection.value(QStringLiteral("vpn")).contains(QLatin1String("tmp-secrets"))) { QVariantMap vpnSetting = connection.value(QLatin1String("vpn")); tmpOpenconnectSecrets = qdbus_cast(vpnSetting.take(QLatin1String("tmp-secrets"))); connection.insert(QLatin1String("vpn"), vpnSetting); } } sendSecrets(connection, request.message); NetworkManager::ConnectionSettings::Ptr connectionSettings = NetworkManager::ConnectionSettings::Ptr(new NetworkManager::ConnectionSettings(connection)); NetworkManager::ConnectionSettings::Ptr completeConnectionSettings; NetworkManager::Connection::Ptr con = NetworkManager::findConnectionByUuid(connectionSettings->uuid()); if (con) { completeConnectionSettings = con->settings(); } else { completeConnectionSettings = connectionSettings; } if (request.saveSecretsWithoutReply && completeConnectionSettings->connectionType() != NetworkManager::ConnectionSettings::Vpn) { bool requestOffline = true; if (completeConnectionSettings->connectionType() == NetworkManager::ConnectionSettings::Gsm) { NetworkManager::GsmSetting::Ptr gsmSetting = completeConnectionSettings->setting(NetworkManager::Setting::Gsm).staticCast(); if (gsmSetting) { if (gsmSetting->passwordFlags().testFlag(NetworkManager::Setting::NotSaved) || gsmSetting->passwordFlags().testFlag(NetworkManager::Setting::NotRequired)) { requestOffline = false; } else if (gsmSetting->pinFlags().testFlag(NetworkManager::Setting::NotSaved) || gsmSetting->pinFlags().testFlag(NetworkManager::Setting::NotRequired)) { requestOffline = false; } } } else if (completeConnectionSettings->connectionType() == NetworkManager::ConnectionSettings::Wireless) { NetworkManager::WirelessSecuritySetting::Ptr wirelessSecuritySetting = completeConnectionSettings->setting(NetworkManager::Setting::WirelessSecurity).staticCast(); if (wirelessSecuritySetting && wirelessSecuritySetting->keyMgmt() == NetworkManager::WirelessSecuritySetting::WpaEap) { NetworkManager::Security8021xSetting::Ptr security8021xSetting = completeConnectionSettings->setting(NetworkManager::Setting::Security8021x).staticCast(); if (security8021xSetting) { if (security8021xSetting->eapMethods().contains(NetworkManager::Security8021xSetting::EapMethodFast) || security8021xSetting->eapMethods().contains(NetworkManager::Security8021xSetting::EapMethodTtls) || security8021xSetting->eapMethods().contains(NetworkManager::Security8021xSetting::EapMethodPeap)) { if (security8021xSetting->passwordFlags().testFlag(NetworkManager::Setting::NotSaved) || security8021xSetting->passwordFlags().testFlag(NetworkManager::Setting::NotRequired)) { requestOffline = false; } } } } } if (requestOffline) { SecretsRequest requestOffline(SecretsRequest::SaveSecrets); requestOffline.connection = connection; requestOffline.connection_path = request.connection_path; requestOffline.saveSecretsWithoutReply = true; m_calls << requestOffline; } } else if (request.saveSecretsWithoutReply && completeConnectionSettings->connectionType() == NetworkManager::ConnectionSettings::Vpn && !tmpOpenconnectSecrets.isEmpty()) { NetworkManager::VpnSetting::Ptr vpnSetting = completeConnectionSettings->setting(NetworkManager::Setting::Vpn).staticCast(); if (vpnSetting) { NMStringMap data = vpnSetting->data(); NMStringMap secrets = vpnSetting->secrets(); // Load secrets from auth dialog which are returned back to NM if (connection.value(QLatin1String("vpn")).contains(QLatin1String("secrets"))) { secrets.unite(qdbus_cast(connection.value(QLatin1String("vpn")).value(QLatin1String("secrets")))); } // Load temporary secrets from auth dialog which are not returned to NM - Q_FOREACH (const QString &key, tmpOpenconnectSecrets.keys()) { + for (const QString &key : tmpOpenconnectSecrets.keys()) { if (secrets.contains(QLatin1Literal("save_passwords")) && secrets.value(QLatin1Literal("save_passwords")) == QLatin1String("yes")) { data.insert(key + QLatin1String("-flags"), QString::number(NetworkManager::Setting::AgentOwned)); } else { data.insert(key + QLatin1String("-flags"), QString::number(NetworkManager::Setting::NotSaved)); } secrets.insert(key, tmpOpenconnectSecrets.value(key)); } vpnSetting->setData(data); vpnSetting->setSecrets(secrets); if (!con) { con = NetworkManager::findConnection(request.connection_path.path()); } if (con) { con->update(completeConnectionSettings->toMap()); } } } m_calls.removeAt(i); break; } } m_dialog->deleteLater(); m_dialog = nullptr; processNext(); } void SecretAgent::dialogRejected() { for (int i = 0; i < m_calls.size(); ++i) { SecretsRequest request = m_calls[i]; if (request.type == SecretsRequest::GetSecrets && request.dialog == m_dialog) { sendError(SecretAgent::UserCanceled, QLatin1String("User canceled the password dialog"), request.message); m_calls.removeAt(i); break; } } m_dialog->deleteLater(); m_dialog = nullptr; processNext(); } void SecretAgent::killDialogs() { int i = 0; while (i < m_calls.size()) { SecretsRequest request = m_calls[i]; if (request.type == SecretsRequest::GetSecrets) { delete request.dialog; m_calls.removeAt(i); } ++i; } } void SecretAgent::walletOpened(bool success) { if (!success) { m_openWalletFailed = true; m_wallet->deleteLater(); m_wallet = nullptr; } else { m_openWalletFailed = false; } processNext(); } void SecretAgent::walletClosed() { if (m_wallet) { m_wallet->deleteLater(); } m_wallet = nullptr; } void SecretAgent::processNext() { int i = 0; while (i < m_calls.size()) { SecretsRequest &request = m_calls[i]; switch (request.type) { case SecretsRequest::GetSecrets: if (processGetSecrets(request)) { m_calls.removeAt(i); continue; } break; case SecretsRequest::SaveSecrets: if (processSaveSecrets(request)) { m_calls.removeAt(i); continue; } break; case SecretsRequest::DeleteSecrets: if (processDeleteSecrets(request)) { m_calls.removeAt(i); continue; } break; } ++i; } } bool SecretAgent::processGetSecrets(SecretsRequest &request) const { if (m_dialog) { return false; } NetworkManager::ConnectionSettings::Ptr connectionSettings = NetworkManager::ConnectionSettings::Ptr(new NetworkManager::ConnectionSettings(request.connection)); NetworkManager::Setting::Ptr setting = connectionSettings->setting(request.setting_name); const bool requestNew = request.flags & RequestNew; const bool userRequested = request.flags & UserRequested; const bool allowInteraction = request.flags & AllowInteraction; const bool isVpn = (setting->type() == NetworkManager::Setting::Vpn); if (isVpn) { NetworkManager::VpnSetting::Ptr vpnSetting = connectionSettings->setting(NetworkManager::Setting::Vpn).dynamicCast(); if (vpnSetting->serviceType() == QLatin1String("org.freedesktop.NetworkManager.ssh") && vpnSetting->data()["auth-type"] == QLatin1String("ssh-agent")) { QString authSock = qgetenv("SSH_AUTH_SOCK"); qCDebug(PLASMA_NM) << Q_FUNC_INFO << "Sending SSH auth socket" << authSock; if (authSock.isEmpty()) { sendError(SecretAgent::NoSecrets, QLatin1String("SSH_AUTH_SOCK not present"), request.message); } else { NMStringMap secrets; secrets.insert(QLatin1String("ssh-auth-sock"), authSock); QVariantMap secretData; secretData.insert(QLatin1String("secrets"), QVariant::fromValue(secrets)); request.connection[request.setting_name] = secretData; sendSecrets(request.connection, request.message); } return true; } } NMStringMap secretsMap; if (!requestNew && useWallet()) { if (m_wallet->isOpen()) { if (m_wallet->hasFolder("Network Management") && m_wallet->setFolder("Network Management")) { QString key = QLatin1Char('{') % connectionSettings->uuid() % QLatin1Char('}') % QLatin1Char(';') % request.setting_name; m_wallet->readMap(key, secretsMap); } } else { qCDebug(PLASMA_NM) << Q_FUNC_INFO << "Waiting for the wallet to open"; return false; } } if (!secretsMap.isEmpty()) { setting->secretsFromStringMap(secretsMap); if (!isVpn && setting->needSecrets(requestNew).isEmpty()) { // Enough secrets were retrieved from storage request.connection[request.setting_name] = setting->secretsToMap(); sendSecrets(request.connection, request.message); return true; } } - if (requestNew || (allowInteraction && !setting->needSecrets(requestNew).isEmpty()) || (allowInteraction && userRequested) || (isVpn && allowInteraction)) { + if (!Configuration::showPasswordDialog()) { + sendError(SecretAgent::NoSecrets, "Cannot authenticate", request.message); + return true; + } else if (requestNew || (allowInteraction && !setting->needSecrets(requestNew).isEmpty()) || (allowInteraction && userRequested) || (isVpn && allowInteraction)) { m_dialog = new PasswordDialog(connectionSettings, request.flags, request.setting_name); connect(m_dialog, &PasswordDialog::accepted, this, &SecretAgent::dialogAccepted); connect(m_dialog, &PasswordDialog::rejected, this, &SecretAgent::dialogRejected); if (m_dialog->hasError()) { sendError(m_dialog->error(), m_dialog->errorMessage(), request.message); delete m_dialog; m_dialog = nullptr; return true; } else { request.dialog = m_dialog; request.saveSecretsWithoutReply = !connectionSettings->permissions().isEmpty(); m_dialog->show(); KWindowSystem::setState(m_dialog->winId(), NET::KeepAbove); KWindowSystem::forceActiveWindow(m_dialog->winId()); return false; } } else if (isVpn && userRequested) { // just return what we have NMVariantMapMap result; NetworkManager::VpnSetting::Ptr vpnSetting; vpnSetting = connectionSettings->setting(NetworkManager::Setting::Vpn).dynamicCast(); //FIXME workaround when NM is asking for secrets which should be system-stored, if we send an empty map it // won't ask for additional secrets with AllowInteraction flag which would display the authentication dialog if (vpnSetting->secretsToMap().isEmpty()) { // Insert an empty secrets map as it was before I fixed it in NetworkManagerQt to make sure NM will ask again // with flags we need QVariantMap secretsMap; secretsMap.insert(QLatin1String("secrets"), QVariant::fromValue(NMStringMap())); result.insert("vpn", secretsMap); } else { result.insert("vpn", vpnSetting->secretsToMap()); } sendSecrets(result, request.message); return true; } else if (setting->needSecrets().isEmpty()) { NMVariantMapMap result; result.insert(setting->name(), setting->secretsToMap()); sendSecrets(result, request.message); return true; } else { sendError(SecretAgent::InternalError, QLatin1String("Plasma-nm did not know how to handle the request"), request.message); return true; } } bool SecretAgent::processSaveSecrets(SecretsRequest &request) const { if (useWallet()) { if (m_wallet->isOpen()) { NetworkManager::ConnectionSettings connectionSettings(request.connection); if (!m_wallet->hasFolder("Network Management")) { m_wallet->createFolder("Network Management"); } if (m_wallet->setFolder("Network Management")) { - Q_FOREACH (const NetworkManager::Setting::Ptr &setting, connectionSettings.settings()) { + for (const NetworkManager::Setting::Ptr &setting : connectionSettings.settings()) { NMStringMap secretsMap = setting->secretsToStringMap(); if (!secretsMap.isEmpty()) { QString entryName = QLatin1Char('{') % connectionSettings.uuid() % QLatin1Char('}') % QLatin1Char(';') % setting->name(); m_wallet->writeMap(entryName, secretsMap); } } } else if (!request.saveSecretsWithoutReply) { sendError(SecretAgent::InternalError, QLatin1String("Could not store secrets in the wallet."), request.message); return true; } } else { qCDebug(PLASMA_NM) << Q_FUNC_INFO << "Waiting for the wallet to open"; return false; } } if (!request.saveSecretsWithoutReply) { QDBusMessage reply = request.message.createReply(); if (!QDBusConnection::systemBus().send(reply)) { qCWarning(PLASMA_NM) << "Failed put save secrets reply into the queue"; } } return true; } bool SecretAgent::processDeleteSecrets(SecretsRequest &request) const { if (useWallet()) { if (m_wallet->isOpen()) { if (m_wallet->hasFolder("Network Management") && m_wallet->setFolder("Network Management")) { NetworkManager::ConnectionSettings connectionSettings(request.connection); - Q_FOREACH (const NetworkManager::Setting::Ptr &setting, connectionSettings.settings()) { + for (const NetworkManager::Setting::Ptr &setting : connectionSettings.settings()) { QString entryName = QLatin1Char('{') % connectionSettings.uuid() % QLatin1Char('}') % QLatin1Char(';') % setting->name(); - Q_FOREACH (const QString &entry, m_wallet->entryList()) { + for (const QString &entry : m_wallet->entryList()) { if (entry.startsWith(entryName)) { m_wallet->removeEntry(entryName); } } } } } else { qCDebug(PLASMA_NM) << Q_FUNC_INFO << "Waiting for the wallet to open"; return false; } } QDBusMessage reply = request.message.createReply(); if (!QDBusConnection::systemBus().send(reply)) { qCWarning(PLASMA_NM) << "Failed put delete secrets reply into the queue"; } return true; } bool SecretAgent::useWallet() const { if (m_wallet) { return true; } /* If opening of KWallet failed before, we should not try to open it again and * we should return false instead */ if (m_openWalletFailed) { m_openWalletFailed = false; return false; } if (KWallet::Wallet::isEnabled()) { m_wallet = KWallet::Wallet::openWallet(KWallet::Wallet::LocalWallet(), 0, KWallet::Wallet::Asynchronous); if (m_wallet) { connect(m_wallet, &KWallet::Wallet::walletOpened, this, &SecretAgent::walletOpened); connect(m_wallet, &KWallet::Wallet::walletClosed, this, &SecretAgent::walletClosed); return true; } else { qCWarning(PLASMA_NM) << "Error opening kwallet."; } } else if (m_wallet) { m_wallet->deleteLater(); m_wallet = nullptr; } return false; } bool SecretAgent::hasSecrets(const NMVariantMapMap &connection) const { NetworkManager::ConnectionSettings connectionSettings(connection); - Q_FOREACH (const NetworkManager::Setting::Ptr &setting, connectionSettings.settings()) { + for (const NetworkManager::Setting::Ptr &setting : connectionSettings.settings()) { if (!setting->secretsToMap().isEmpty()) { return true; } } return false; } void SecretAgent::sendSecrets(const NMVariantMapMap &secrets, const QDBusMessage &message) const { QDBusMessage reply; reply = message.createReply(QVariant::fromValue(secrets)); if (!QDBusConnection::systemBus().send(reply)) { qCWarning(PLASMA_NM) << "Failed put the secret into the queue"; } } void SecretAgent::importSecretsFromPlainTextFiles() { KConfig config(QLatin1String("plasma-networkmanagement"), KConfig::SimpleConfig); // No action is required when the list of secrets is empty if (!config.groupList().isEmpty()) { - Q_FOREACH (const QString &groupName, config.groupList()) { + for (const QString &groupName : config.groupList()) { QString loadedUuid = groupName.split(';').first().remove('{').remove('}'); QString loadedSettingType = groupName.split(';').last(); NetworkManager::Connection::Ptr connection = NetworkManager::findConnectionByUuid(loadedUuid); if (connection) { NetworkManager::Setting::SecretFlags secretFlags = KWallet::Wallet::isEnabled() ? NetworkManager::Setting::AgentOwned : NetworkManager::Setting::None; QMap secrets = config.entryMap(groupName); NMVariantMapMap settings = connection->settings()->toMap(); - Q_FOREACH (const QString &setting, settings.keys()) { + for (const QString &setting : settings.keys()) { if (setting == QLatin1String("vpn")) { NetworkManager::VpnSetting::Ptr vpnSetting = connection->settings()->setting(NetworkManager::Setting::Vpn).staticCast(); if (vpnSetting) { // Add loaded secrets from the config file vpnSetting->secretsFromStringMap(secrets); NMStringMap vpnData = vpnSetting->data(); // Reset flags, we can't save secrets to our secret agent when KWallet is not enabled, because // we dropped support for plaintext files, therefore they need to be stored to NetworkManager - Q_FOREACH (const QString &key, vpnData.keys()) { + for (const QString &key : vpnData.keys()) { if (key.endsWith(QLatin1String("-flags"))) { vpnData.insert(key, QString::number((int)secretFlags)); } } vpnSetting->setData(vpnData); settings.insert(setting, vpnSetting->toMap()); connection->update(settings); } } else { if (setting == loadedSettingType) { QVariantMap tmpSetting = settings.value(setting); // Reset flags, we can't save secrets to our secret agent when KWallet is not enabled, because // we dropped support for plaintext files, therefore they need to be stored to NetworkManager - Q_FOREACH (const QString &key, tmpSetting.keys()) { + for (const QString &key : tmpSetting.keys()) { if (key.endsWith(QLatin1String("-flags"))) { tmpSetting.insert(key, (int)secretFlags); } } // Add loaded secrets from the config file QMap::const_iterator it = secrets.constBegin(); QMap::const_iterator end = secrets.constEnd(); for (; it != end; ++it) { tmpSetting.insert(it.key(), it.value()); } // Replace the old setting with the new one settings.insert(setting, tmpSetting); // Update the connection which re-saves secrets connection->update(settings); } } } } // Remove the group KConfigGroup group(&config, groupName); group.deleteGroup(); } } } diff --git a/libs/configuration.cpp b/libs/configuration.cpp index c230e0dc..75273290 100644 --- a/libs/configuration.cpp +++ b/libs/configuration.cpp @@ -1,68 +1,81 @@ /* 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 bool Configuration::unlockModemOnDetection() { KSharedConfigPtr config = KSharedConfig::openConfig(QLatin1String("plasma-nm")); KConfigGroup grp(config, QLatin1String("General")); if (grp.isValid()) { return grp.readEntry(QLatin1String("UnlockModemOnDetection"), true); } return true; } void Configuration::setUnlockModemOnDetection(bool unlock) { KSharedConfigPtr config = KSharedConfig::openConfig(QLatin1String("plasma-nm")); KConfigGroup grp(config, QLatin1String("General")); if (grp.isValid()) { grp.writeEntry(QLatin1String("UnlockModemOnDetection"), unlock); } } bool Configuration::manageVirtualConnections() { KSharedConfigPtr config = KSharedConfig::openConfig(QLatin1String("plasma-nm")); KConfigGroup grp(config, QLatin1String("General")); if (grp.isValid()) { return grp.readEntry(QLatin1String("ManageVirtualConnections"), false); } return true; } void Configuration::setManageVirtualConnections(bool manage) { KSharedConfigPtr config = KSharedConfig::openConfig(QLatin1String("plasma-nm")); KConfigGroup grp(config, QLatin1String("General")); if (grp.isValid()) { grp.writeEntry(QLatin1String("ManageVirtualConnections"), manage); } } + +bool Configuration::showPasswordDialog() +{ + KSharedConfigPtr config = KSharedConfig::openConfig(QLatin1String("plasma-nm")); + KConfigGroup grp(config, QLatin1String("General")); + + if (grp.isValid()) { + return grp.readEntry(QLatin1String("ShowPasswordDialog"), true); + } + + return true; +} + diff --git a/libs/configuration.h b/libs/configuration.h index 3392564c..6c2a1231 100644 --- a/libs/configuration.h +++ b/libs/configuration.h @@ -1,42 +1,46 @@ /* 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) + //Readonly constant property, as this value should only be set by the platform + Q_PROPERTY(bool showPasswordDialog READ showPasswordDialog CONSTANT) Q_OBJECT public: static bool unlockModemOnDetection(); static void setUnlockModemOnDetection(bool unlock); static bool manageVirtualConnections(); static void setManageVirtualConnections(bool manage); + + static bool showPasswordDialog(); }; #endif // PLAMA_NM_CONFIGURATION_H diff --git a/libs/declarative/availabledevices.cpp b/libs/declarative/availabledevices.cpp index 0e312c6f..73356abc 100644 --- a/libs/declarative/availabledevices.cpp +++ b/libs/declarative/availabledevices.cpp @@ -1,131 +1,131 @@ /* 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 "availabledevices.h" #include AvailableDevices::AvailableDevices(QObject* parent) : QObject(parent) , m_wiredDeviceAvailable(false) , m_wirelessDeviceAvailable(false) , m_modemDeviceAvailable(false) , m_bluetoothDeviceAvailable(false) { - Q_FOREACH (const NetworkManager::Device::Ptr& device, NetworkManager::networkInterfaces()) { + for (const NetworkManager::Device::Ptr &device : NetworkManager::networkInterfaces()) { if (device->type() == NetworkManager::Device::Modem) { m_modemDeviceAvailable = true; } else if (device->type() == NetworkManager::Device::Wifi) { m_wirelessDeviceAvailable = true; } else if (device->type() == NetworkManager::Device::Ethernet) { m_wiredDeviceAvailable = true; } else if (device->type() == NetworkManager::Device::Bluetooth) { m_bluetoothDeviceAvailable = true; } } connect(NetworkManager::notifier(), &NetworkManager::Notifier::deviceAdded, this, &AvailableDevices::deviceAdded); connect(NetworkManager::notifier(), &NetworkManager::Notifier::deviceRemoved, this, &AvailableDevices::deviceRemoved); } AvailableDevices::~AvailableDevices() { } bool AvailableDevices::isWiredDeviceAvailable() const { return m_wiredDeviceAvailable; } bool AvailableDevices::isWirelessDeviceAvailable() const { return m_wirelessDeviceAvailable; } bool AvailableDevices::isModemDeviceAvailable() const { return m_modemDeviceAvailable; } bool AvailableDevices::isBluetoothDeviceAvailable() const { return m_bluetoothDeviceAvailable; } void AvailableDevices::deviceAdded(const QString& dev) { NetworkManager::Device::Ptr device = NetworkManager::findNetworkInterface(dev); if (device) { if (device->type() == NetworkManager::Device::Modem && !m_modemDeviceAvailable) { m_modemDeviceAvailable = true; Q_EMIT modemDeviceAvailableChanged(true); } else if (device->type() == NetworkManager::Device::Wifi && !m_wirelessDeviceAvailable) { m_wirelessDeviceAvailable = true; Q_EMIT wirelessDeviceAvailableChanged(true); } else if (device->type() == NetworkManager::Device::Ethernet && !m_wiredDeviceAvailable) { m_wiredDeviceAvailable = true; Q_EMIT wiredDeviceAvailableChanged(true); } else if (device->type() == NetworkManager::Device::Bluetooth && !m_bluetoothDeviceAvailable) { m_bluetoothDeviceAvailable = true; Q_EMIT bluetoothDeviceAvailableChanged(true); } } } void AvailableDevices::deviceRemoved() { bool wired = false; bool wireless = false; bool modem = false; bool bluetooth = false; - Q_FOREACH (const NetworkManager::Device::Ptr& device, NetworkManager::networkInterfaces()) { + for (const NetworkManager::Device::Ptr &device : NetworkManager::networkInterfaces()) { if (device->type() == NetworkManager::Device::Modem) { modem = true; } else if (device->type() == NetworkManager::Device::Wifi) { wireless = true; } else if (device->type() == NetworkManager::Device::Ethernet) { wired = true; } else if (device->type() == NetworkManager::Device::Bluetooth) { bluetooth = true; } } if (!wired && m_wiredDeviceAvailable) { m_wiredDeviceAvailable = false; Q_EMIT wiredDeviceAvailableChanged(false); } if (!wireless && m_wirelessDeviceAvailable) { m_wirelessDeviceAvailable = false; Q_EMIT wirelessDeviceAvailableChanged(false); } if (!modem && m_modemDeviceAvailable) { m_modemDeviceAvailable = false; Q_EMIT modemDeviceAvailableChanged(false); } if (!bluetooth && m_bluetoothDeviceAvailable) { m_bluetoothDeviceAvailable = false; Q_EMIT bluetoothDeviceAvailableChanged(false); } } diff --git a/libs/declarative/connectionicon.cpp b/libs/declarative/connectionicon.cpp index 566eeae9..39281015 100644 --- a/libs/declarative/connectionicon.cpp +++ b/libs/declarative/connectionicon.cpp @@ -1,681 +1,637 @@ /* 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 "connectionicon.h" #include "uiutils.h" #include #include #include #include #include #include #include #include #include #if WITH_MODEMMANAGER_SUPPORT #include #include #endif ConnectionIcon::ConnectionIcon(QObject* parent) : QObject(parent) , m_signal(0) , m_wirelessNetwork(nullptr) , m_connecting(false) , m_limited(false) , m_vpn(false) , m_airplaneMode(false) #if WITH_MODEMMANAGER_SUPPORT , m_modemNetwork(nullptr) #endif { connect(NetworkManager::notifier(), &NetworkManager::Notifier::primaryConnectionChanged, this, &ConnectionIcon::primaryConnectionChanged); connect(NetworkManager::notifier(), &NetworkManager::Notifier::activatingConnectionChanged, this, &ConnectionIcon::activatingConnectionChanged); connect(NetworkManager::notifier(), &NetworkManager::Notifier::activeConnectionAdded, this, &ConnectionIcon::activeConnectionAdded); connect(NetworkManager::notifier(), &NetworkManager::Notifier::connectivityChanged, this, &ConnectionIcon::connectivityChanged); connect(NetworkManager::notifier(), &NetworkManager::Notifier::deviceAdded, this, &ConnectionIcon::deviceAdded); connect(NetworkManager::notifier(), &NetworkManager::Notifier::deviceRemoved, this, &ConnectionIcon::deviceRemoved); connect(NetworkManager::notifier(), &NetworkManager::Notifier::networkingEnabledChanged, this, &ConnectionIcon::networkingEnabledChanged); connect(NetworkManager::notifier(), &NetworkManager::Notifier::statusChanged, this, &ConnectionIcon::statusChanged); connect(NetworkManager::notifier(), &NetworkManager::Notifier::wirelessEnabledChanged, this, &ConnectionIcon::wirelessEnabledChanged); connect(NetworkManager::notifier(), &NetworkManager::Notifier::wirelessHardwareEnabledChanged, this, &ConnectionIcon::wirelessEnabledChanged); connect(NetworkManager::notifier(), &NetworkManager::Notifier::wwanEnabledChanged, this, &ConnectionIcon::wwanEnabledChanged); connect(NetworkManager::notifier(), &NetworkManager::Notifier::wwanHardwareEnabledChanged, this, &ConnectionIcon::wwanEnabledChanged); - Q_FOREACH (NetworkManager::Device::Ptr device, NetworkManager::networkInterfaces()) { + for (const NetworkManager::Device::Ptr &device : NetworkManager::networkInterfaces()) { if (device->type() == NetworkManager::Device::Ethernet) { NetworkManager::WiredDevice::Ptr wiredDevice = device.staticCast(); if (wiredDevice) { connect(wiredDevice.data(), &NetworkManager::WiredDevice::carrierChanged, this, &ConnectionIcon::carrierChanged); } } else if (device->type() == NetworkManager::Device::Wifi) { NetworkManager::WirelessDevice::Ptr wifiDevice = device.staticCast(); if (wifiDevice) { connect(wifiDevice.data(), &NetworkManager::WirelessDevice::availableConnectionAppeared, this, &ConnectionIcon::wirelessNetworkAppeared); connect(wifiDevice.data(), &NetworkManager::WirelessDevice::networkAppeared, this, &ConnectionIcon::wirelessNetworkAppeared); } } } - Q_FOREACH (NetworkManager::ActiveConnection::Ptr activeConnection, NetworkManager::activeConnections()) { + for (const NetworkManager::ActiveConnection::Ptr &activeConnection : NetworkManager::activeConnections()) { addActiveConnection(activeConnection->path()); } setStates(); connectivityChanged(); setIcons(); } ConnectionIcon::~ConnectionIcon() { } bool ConnectionIcon::connecting() const { return m_connecting; } QString ConnectionIcon::connectionIcon() const { if (m_vpn && !m_connectionIcon.contains("available")) { return m_connectionIcon + "-locked"; } if (m_limited && !m_connectionIcon.contains("available")) { return m_connectionIcon + "-limited"; } return m_connectionIcon; } QString ConnectionIcon::connectionTooltipIcon() const { return m_connectionTooltipIcon; } bool ConnectionIcon::airplaneMode() const { return m_airplaneMode; } void ConnectionIcon::setAirplaneMode(bool airplaneMode) { if (m_airplaneMode != airplaneMode) { m_airplaneMode = airplaneMode; Q_EMIT airplaneModeChanged(airplaneMode); setIcons(); } } void ConnectionIcon::activatingConnectionChanged(const QString& connection) { Q_UNUSED(connection); setIcons(); } void ConnectionIcon::addActiveConnection(const QString &activeConnection) { NetworkManager::ActiveConnection::Ptr active = NetworkManager::findActiveConnection(activeConnection); if (active) { NetworkManager::VpnConnection::Ptr vpnConnection; connect(active.data(), &NetworkManager::ActiveConnection::destroyed, this, &ConnectionIcon::activeConnectionDestroyed); if (active->vpn()) { vpnConnection = active.objectCast(); connect(vpnConnection.data(), &NetworkManager::VpnConnection::stateChanged, this, &ConnectionIcon::vpnConnectionStateChanged); } else { connect(active.data(), &NetworkManager::ActiveConnection::stateChanged, this, &ConnectionIcon::activeConnectionStateChanged, Qt::UniqueConnection); } } } void ConnectionIcon::activeConnectionAdded(const QString &activeConnection) { addActiveConnection(activeConnection); setStates(); } void ConnectionIcon::activeConnectionStateChanged(NetworkManager::ActiveConnection::State state) { Q_UNUSED(state); setStates(); } void ConnectionIcon::activeConnectionDestroyed() { setStates(); } void ConnectionIcon::carrierChanged(bool carrier) { Q_UNUSED(carrier); setIcons(); } void ConnectionIcon::connectivityChanged() { NetworkManager::Connectivity conn = NetworkManager::connectivity(); setLimited(conn == NetworkManager::Portal || conn == NetworkManager::Limited); } void ConnectionIcon::deviceAdded(const QString& device) { NetworkManager::Device::Ptr dev = NetworkManager::findNetworkInterface(device); if (!dev) { return; } if (dev->type() == NetworkManager::Device::Ethernet) { NetworkManager::WiredDevice::Ptr wiredDev = dev.objectCast(); connect(wiredDev.data(), &NetworkManager::WiredDevice::carrierChanged, this, &ConnectionIcon::carrierChanged); } } void ConnectionIcon::deviceRemoved(const QString& device) { Q_UNUSED(device); if (NetworkManager::status() == NetworkManager::Disconnected) { setDisconnectedIcon(); } } #if WITH_MODEMMANAGER_SUPPORT void ConnectionIcon::modemNetworkRemoved() { m_modemNetwork.clear(); } void ConnectionIcon::modemSignalChanged(const ModemManager::SignalQualityPair &signalQuality) { int diff = m_signal - signalQuality.signal; if (diff >= 10 || diff <= -10) { m_signal = signalQuality.signal; setIconForModem(); } } #endif void ConnectionIcon::networkingEnabledChanged(bool enabled) { if (!enabled) { setConnectionIcon("network-unavailable"); } } void ConnectionIcon::primaryConnectionChanged(const QString& connection) { if (!connection.isEmpty()) { setIcons(); } } void ConnectionIcon::statusChanged(NetworkManager::Status status) { if (status == NetworkManager::Disconnected) { setDisconnectedIcon(); } } void ConnectionIcon::vpnConnectionStateChanged(NetworkManager::VpnConnection::State state, NetworkManager::VpnConnection::StateChangeReason reason) { Q_UNUSED(state); Q_UNUSED(reason); setStates(); setIcons(); } void ConnectionIcon::wirelessEnabledChanged(bool enabled) { Q_UNUSED(enabled); setIcons(); } void ConnectionIcon::wwanEnabledChanged(bool enabled) { Q_UNUSED(enabled); setIcons(); } void ConnectionIcon::wirelessNetworkAppeared(const QString& network) { Q_UNUSED(network); setIcons(); } void ConnectionIcon::setStates() { bool connecting = false; bool vpn = false; - Q_FOREACH (NetworkManager::ActiveConnection::Ptr activeConnection, NetworkManager::activeConnections()) { + for (const NetworkManager::ActiveConnection::Ptr &activeConnection : NetworkManager::activeConnections()) { NetworkManager::VpnConnection::Ptr vpnConnection; if (activeConnection->vpn()) { vpnConnection = activeConnection.objectCast(); } if (!vpnConnection) { if (activeConnection->state() == NetworkManager::ActiveConnection::Activating && UiUtils::isConnectionTypeSupported(activeConnection->type())) { connecting = true; } } else { if (vpnConnection->state() == NetworkManager::VpnConnection::Activated) { vpn = true; } else if (vpnConnection->state() == NetworkManager::VpnConnection::Prepare || vpnConnection->state() == NetworkManager::VpnConnection::NeedAuth || vpnConnection->state() == NetworkManager::VpnConnection::Connecting || vpnConnection->state() == NetworkManager::VpnConnection::GettingIpConfig) { connecting = true; } } } setVpn(vpn); setConnecting(connecting); } void ConnectionIcon::setIcons() { m_signal = 0; #if WITH_MODEMMANAGER_SUPPORT if (m_modemNetwork) { disconnect(m_modemNetwork.data(), nullptr, this, nullptr); m_modemNetwork.clear(); } #endif if (m_wirelessNetwork) { disconnect(m_wirelessNetwork.data(), nullptr, this, nullptr); m_wirelessNetwork.clear(); } NetworkManager::ActiveConnection::Ptr connection = NetworkManager::activatingConnection(); if (!connection) { connection = NetworkManager::primaryConnection(); } - // Workaround, because PrimaryConnection is kinda broken in NM 0.9.8.x and - // doesn't work correctly with some VPN connections. This shouldn't be necessary - // for NM 0.9.9.0 or the upcoming bugfix release NM 0.9.8.10 -#if !NM_CHECK_VERSION(0, 9, 10) - if (!connection) { - bool defaultRoute = false; - NetworkManager::ActiveConnection::Ptr mainActiveConnection; - Q_FOREACH (const NetworkManager::ActiveConnection::Ptr & activeConnection, NetworkManager::activeConnections()) { - if ((activeConnection->default4() || activeConnection->default6()) && activeConnection->vpn()) { - defaultRoute = true; - mainActiveConnection = activeConnection; - break; - } - } - - if (!defaultRoute) { - Q_FOREACH (const NetworkManager::ActiveConnection::Ptr & activeConnection, NetworkManager::activeConnections()) { - if (activeConnection->vpn()) { - mainActiveConnection = activeConnection; - break; - } - } - } - - if (mainActiveConnection) { - NetworkManager::ActiveConnection::Ptr baseActiveConnection; - baseActiveConnection = NetworkManager::findActiveConnection(mainActiveConnection->specificObject()); - if (baseActiveConnection) { - connection = baseActiveConnection; - } - } - } -#endif - /* Fallback: If we still don't have an active connection with default route or the default route goes through a connection of generic type (some type of VPNs) we need to go through all other active connections and pick the one with highest probability of being the main one (order is: vpn, wired, wireless, gsm, cdma, bluetooth) */ -#if NM_CHECK_VERSION(1, 2, 0) if ((!connection && !NetworkManager::activeConnections().isEmpty()) || (connection && connection->type() == NetworkManager::ConnectionSettings::Generic) || (connection && connection->type() == NetworkManager::ConnectionSettings::Tun)) { -#elif NM_CHECK_VERSION(0, 9, 10) - if ((!connection && !NetworkManager::activeConnections().isEmpty()) || (connection && connection->type() == NetworkManager::ConnectionSettings::Generic)) { -#else - if (!connection && !NetworkManager::activeConnections().isEmpty()) { -#endif -#if NM_CHECK_VERSION(0, 9, 10) - Q_FOREACH (const NetworkManager::ActiveConnection::Ptr &activeConnection, NetworkManager::activeConnections()) { + for (const NetworkManager::ActiveConnection::Ptr &activeConnection : NetworkManager::activeConnections()) { const NetworkManager::ConnectionSettings::ConnectionType type = activeConnection->type(); if (type == NetworkManager::ConnectionSettings::Bluetooth) { if (connection && connection->type() <= NetworkManager::ConnectionSettings::Bluetooth) { connection = activeConnection; } } else if (type == NetworkManager::ConnectionSettings::Cdma) { if (connection && connection->type() <= NetworkManager::ConnectionSettings::Cdma) { connection = activeConnection; } } else if (type == NetworkManager::ConnectionSettings::Gsm) { if (connection && connection->type() <= NetworkManager::ConnectionSettings::Gsm) { connection = activeConnection; } } else if (type == NetworkManager::ConnectionSettings::Vpn) { connection = activeConnection; } else if (type == NetworkManager::ConnectionSettings::Wired) { if (connection && connection->type() != NetworkManager::ConnectionSettings::Vpn) { connection = activeConnection; } } else if (type == NetworkManager::ConnectionSettings::Wireless) { if (connection && (connection->type() != NetworkManager::ConnectionSettings::Vpn && (connection->type() != NetworkManager::ConnectionSettings::Wired))) { connection = activeConnection; } } } -#else - connection = NetworkManager::activeConnections().first(); -#endif } if (connection && !connection->devices().isEmpty()) { NetworkManager::Device::Ptr device = NetworkManager::findNetworkInterface(connection->devices().first()); if (device) { NetworkManager::Device::Type type = device->type(); if (type == NetworkManager::Device::Wifi) { NetworkManager::WirelessDevice::Ptr wifiDevice = device.objectCast(); if (wifiDevice->mode() == NetworkManager::WirelessDevice::Adhoc) { setWirelessIconForSignalStrength(100); } else { NetworkManager::AccessPoint::Ptr ap = wifiDevice->activeAccessPoint(); if (ap) { setWirelessIcon(device, ap->ssid()); } } } else if (type == NetworkManager::Device::Ethernet) { setConnectionIcon("network-wired-activated"); setConnectionTooltipIcon("network-wired-activated"); } else if (type == NetworkManager::Device::Modem) { #if WITH_MODEMMANAGER_SUPPORT setModemIcon(device); #else setConnectionIcon("network-mobile-0"); setConnectionTooltipIcon("phone"); #endif } else if (type == NetworkManager::Device::Bluetooth) { NetworkManager::BluetoothDevice::Ptr btDevice = device.objectCast(); if (btDevice) { if (btDevice->bluetoothCapabilities().testFlag(NetworkManager::BluetoothDevice::Dun)) { #if WITH_MODEMMANAGER_SUPPORT setModemIcon(device); #else setConnectionIcon("network-mobile-0"); setConnectionTooltipIcon("phone"); #endif } else { setConnectionIcon("network-bluetooth-activated"); setConnectionTooltipIcon("preferences-system-bluetooth"); } } } else { // Ignore other devices (bond/bridge/team etc.) setDisconnectedIcon(); } } } else { setDisconnectedIcon(); } } void ConnectionIcon::setDisconnectedIcon() { if (m_airplaneMode) { setConnectionIcon(QStringLiteral("network-flightmode-on")); return; } if (NetworkManager::status() == NetworkManager::Unknown || NetworkManager::status() == NetworkManager::Asleep) { setConnectionIcon("network-unavailable"); return; } bool wired = false; bool wireless = false; bool modem = false; m_limited = false; m_vpn = false; - Q_FOREACH (const NetworkManager::Device::Ptr &device, NetworkManager::networkInterfaces()) { + for (const NetworkManager::Device::Ptr &device : NetworkManager::networkInterfaces()) { if (device->type() == NetworkManager::Device::Ethernet) { NetworkManager::WiredDevice::Ptr wiredDev = device.objectCast(); if (wiredDev->carrier()) { wired = true; } } else if (device->type() == NetworkManager::Device::Wifi && NetworkManager::isWirelessEnabled() && NetworkManager::isWirelessHardwareEnabled()) { NetworkManager::WirelessDevice::Ptr wifiDevice = device.objectCast(); if (!wifiDevice->accessPoints().isEmpty() || !wifiDevice->availableConnections().isEmpty()) { wireless = true; } } else if (device->type() == NetworkManager::Device::Modem && NetworkManager::isWwanEnabled() && NetworkManager::isWwanHardwareEnabled()) { modem = true; } } if (wired) { setConnectionIcon("network-wired-available"); setConnectionTooltipIcon("network-wired"); return; } else if (wireless) { setConnectionIcon("network-wireless-available"); setConnectionTooltipIcon("network-wireless-connected-00"); return; } else if (modem) { setConnectionIcon("network-mobile-available"); setConnectionTooltipIcon("phone"); return; } else { setConnectionIcon("network-unavailable"); setConnectionTooltipIcon("network-wired"); } } #if WITH_MODEMMANAGER_SUPPORT void ConnectionIcon::setModemIcon(const NetworkManager::Device::Ptr & device) { NetworkManager::ModemDevice::Ptr modemDevice = device.objectCast(); if (!modemDevice) { setConnectionIcon("network-mobile-100"); return; } ModemManager::ModemDevice::Ptr modem = ModemManager::findModemDevice(device->udi()); if (modem) { if (modem->hasInterface(ModemManager::ModemDevice::ModemInterface)) { m_modemNetwork = modem->interface(ModemManager::ModemDevice::ModemInterface).objectCast(); } } if (m_modemNetwork) { connect(m_modemNetwork.data(), &ModemManager::Modem::signalQualityChanged, this, &ConnectionIcon::modemSignalChanged, Qt::UniqueConnection); connect(m_modemNetwork.data(), &ModemManager::Modem::accessTechnologiesChanged, this, &ConnectionIcon::setIconForModem, Qt::UniqueConnection); connect(m_modemNetwork.data(), &ModemManager::Modem::destroyed, this, &ConnectionIcon::modemNetworkRemoved); m_signal = m_modemNetwork->signalQuality().signal; setIconForModem(); } else { setConnectionIcon("network-mobile-0"); setConnectionTooltipIcon("phone"); return; } } void ConnectionIcon::setIconForModem() { if (!m_signal) { m_signal = m_modemNetwork->signalQuality().signal; } QString strength = "00"; if (m_signal == 0) { strength = '0'; } else if (m_signal < 20) { strength = "20"; } else if (m_signal < 40) { strength = "40"; } else if (m_signal < 60) { strength = "60"; } else if (m_signal < 80) { strength = "80"; } else { strength = "100"; } QString result; switch(m_modemNetwork->accessTechnologies()) { case MM_MODEM_ACCESS_TECHNOLOGY_GSM: case MM_MODEM_ACCESS_TECHNOLOGY_GSM_COMPACT: result = "network-mobile-%1"; break; case MM_MODEM_ACCESS_TECHNOLOGY_GPRS: result = "network-mobile-%1-gprs"; break; case MM_MODEM_ACCESS_TECHNOLOGY_EDGE: result = "network-mobile-%1-edge"; break; case MM_MODEM_ACCESS_TECHNOLOGY_UMTS: result = "network-mobile-%1-umts"; break; case MM_MODEM_ACCESS_TECHNOLOGY_HSDPA: result = "network-mobile-%1-hsdpa"; break; case MM_MODEM_ACCESS_TECHNOLOGY_HSUPA: result = "network-mobile-%1-hsupa"; break; case MM_MODEM_ACCESS_TECHNOLOGY_HSPA: case MM_MODEM_ACCESS_TECHNOLOGY_HSPA_PLUS: result = "network-mobile-%1-hspa"; break; case MM_MODEM_ACCESS_TECHNOLOGY_LTE: result = "network-mobile-%1-lte"; break; default: result = "network-mobile-%1"; break; } setConnectionIcon(QString(result).arg(strength)); setConnectionTooltipIcon("phone"); } #endif void ConnectionIcon::setWirelessIcon(const NetworkManager::Device::Ptr &device, const QString& ssid) { NetworkManager::WirelessDevice::Ptr wirelessDevice = device.objectCast(); if (device) { m_wirelessNetwork = wirelessDevice->findNetwork(ssid); } else { m_wirelessNetwork.clear(); } if (m_wirelessNetwork) { connect(m_wirelessNetwork.data(), &NetworkManager::WirelessNetwork::signalStrengthChanged, this, &ConnectionIcon::setWirelessIconForSignalStrength, Qt::UniqueConnection); setWirelessIconForSignalStrength(m_wirelessNetwork->signalStrength()); } else { setDisconnectedIcon(); } } void ConnectionIcon::setWirelessIconForSignalStrength(int strength) { int iconStrength = 100; if (strength == 0) { iconStrength = 0; setConnectionTooltipIcon("network-wireless-connected-00"); } else if (strength < 20) { iconStrength = 20; setConnectionTooltipIcon("network-wireless-connected-20"); } else if (strength < 40) { iconStrength = 40; setConnectionTooltipIcon("network-wireless-connected-40"); } else if (strength < 60) { iconStrength = 60; setConnectionTooltipIcon("network-wireless-connected-60"); } else if (strength < 80) { iconStrength = 80; setConnectionTooltipIcon("network-wireless-connected-80"); } else if (strength < 100) { setConnectionTooltipIcon("network-wireless-connected-100"); } QString icon = QString("network-wireless-%1").arg(iconStrength); setConnectionIcon(icon); } void ConnectionIcon::setConnecting(bool connecting) { if (connecting != m_connecting) { m_connecting = connecting; Q_EMIT connectingChanged(m_connecting); } } void ConnectionIcon::setConnectionIcon(const QString & icon) { if (icon != m_connectionIcon) { m_connectionIcon = icon; Q_EMIT connectionIconChanged(connectionIcon()); } } void ConnectionIcon::setConnectionTooltipIcon(const QString & icon) { if (icon != m_connectionTooltipIcon) { m_connectionTooltipIcon = icon; Q_EMIT connectionTooltipIconChanged(m_connectionTooltipIcon); } } void ConnectionIcon::setVpn(bool vpn) { if (m_vpn != vpn) { m_vpn = vpn; Q_EMIT connectionIconChanged(connectionIcon()); } } void ConnectionIcon::setLimited(bool limited) { if (m_limited != limited) { m_limited = limited; Q_EMIT connectionIconChanged(connectionIcon()); } } diff --git a/libs/declarative/models/appletproxymodel.cpp b/libs/declarative/models/appletproxymodel.cpp index 4944b6c8..2b89388a 100644 --- a/libs/declarative/models/appletproxymodel.cpp +++ b/libs/declarative/models/appletproxymodel.cpp @@ -1,128 +1,133 @@ /* 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 "appletproxymodel.h" #include "networkmodel.h" #include "uiutils.h" AppletProxyModel::AppletProxyModel(QObject *parent) : QSortFilterProxyModel(parent) { setDynamicSortFilter(true); + setFilterCaseSensitivity(Qt::CaseInsensitive); sort(0, Qt::DescendingOrder); } AppletProxyModel::~AppletProxyModel() { } bool AppletProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { const QModelIndex index = sourceModel()->index(source_row, 0, source_parent); - // slaves are always filtered-out + // slaves are filtered-out when not searching for a connection (makes the state of search results clear) const bool isSlave = sourceModel()->data(index, NetworkModel::SlaveRole).toBool(); - if (isSlave) { + if (isSlave && filterRegExp().isEmpty()) { return false; } const NetworkManager::ConnectionSettings::ConnectionType type = (NetworkManager::ConnectionSettings::ConnectionType) sourceModel()->data(index, NetworkModel::TypeRole).toUInt(); if (!UiUtils::isConnectionTypeSupported(type)) { return false; } NetworkModelItem::ItemType itemType = (NetworkModelItem::ItemType)sourceModel()->data(index, NetworkModel::ItemTypeRole).toUInt(); - if (itemType == NetworkModelItem::AvailableConnection || - itemType == NetworkModelItem::AvailableAccessPoint) { + if (itemType != NetworkModelItem::AvailableConnection && + itemType != NetworkModelItem::AvailableAccessPoint) { + return false; + } + + if (filterRegExp().isEmpty()) { return true; } - return false; + return sourceModel()->data(index, NetworkModel::ItemUniqueNameRole).toString().contains(filterRegExp()); } bool AppletProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const { const bool leftAvailable = (NetworkModelItem::ItemType)sourceModel()->data(left, NetworkModel::ItemTypeRole).toUInt() != NetworkModelItem::UnavailableConnection; const bool leftConnected = sourceModel()->data(left, NetworkModel::ConnectionStateRole).toUInt() == NetworkManager::ActiveConnection::Activated; const int leftConnectionState = sourceModel()->data(left, NetworkModel::ConnectionStateRole).toUInt(); const QString leftName = sourceModel()->data(left, NetworkModel::NameRole).toString(); const UiUtils::SortedConnectionType leftType = UiUtils::connectionTypeToSortedType((NetworkManager::ConnectionSettings::ConnectionType) sourceModel()->data(left, NetworkModel::TypeRole).toUInt()); const QString leftUuid = sourceModel()->data(left, NetworkModel::UuidRole).toString(); const int leftSignal = sourceModel()->data(left, NetworkModel::SignalRole).toInt(); const QDateTime leftDate = sourceModel()->data(left, NetworkModel::TimeStampRole).toDateTime(); const bool rightAvailable = (NetworkModelItem::ItemType)sourceModel()->data(right, NetworkModel::ItemTypeRole).toUInt() != NetworkModelItem::UnavailableConnection; const bool rightConnected = sourceModel()->data(right, NetworkModel::ConnectionStateRole).toUInt() == NetworkManager::ActiveConnection::Activated; const int rightConnectionState = sourceModel()->data(right, NetworkModel::ConnectionStateRole).toUInt(); const QString rightName = sourceModel()->data(right, NetworkModel::NameRole).toString(); const UiUtils::SortedConnectionType rightType = UiUtils::connectionTypeToSortedType((NetworkManager::ConnectionSettings::ConnectionType) sourceModel()->data(right, NetworkModel::TypeRole).toUInt()); const QString rightUuid = sourceModel()->data(right, NetworkModel::UuidRole).toString(); const int rightSignal = sourceModel()->data(right, NetworkModel::SignalRole).toInt(); const QDateTime rightDate = sourceModel()->data(right, NetworkModel::TimeStampRole).toDateTime(); if (leftAvailable < rightAvailable) { return true; } else if (leftAvailable > rightAvailable) { return false; } if (leftConnected < rightConnected) { return true; } else if (leftConnected > rightConnected) { return false; } if (leftConnectionState > rightConnectionState) { return true; } else if (leftConnectionState < rightConnectionState) { return false; } if (leftUuid.isEmpty() && !rightUuid.isEmpty()) { return true; } else if (!leftUuid.isEmpty() && rightUuid.isEmpty()) { return false; } if (leftType < rightType) { return false; } else if (leftType > rightType) { return true; } if (leftDate > rightDate) { return false; } else if (leftDate < rightDate) { return true; } if (leftSignal < rightSignal) { return true; } else if (leftSignal > rightSignal) { return false; } if (QString::localeAwareCompare(leftName, rightName) > 0) { return true; } else { return false; } } diff --git a/libs/declarative/networkstatus.cpp b/libs/declarative/networkstatus.cpp index 21abd950..7ddf121f 100644 --- a/libs/declarative/networkstatus.cpp +++ b/libs/declarative/networkstatus.cpp @@ -1,239 +1,239 @@ /* 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 "networkstatus.h" #include "uiutils.h" #include #include #include #include NetworkStatus::SortedConnectionType NetworkStatus::connectionTypeToSortedType(NetworkManager::ConnectionSettings::ConnectionType type) { switch (type) { case NetworkManager::ConnectionSettings::Adsl: return NetworkStatus::NetworkStatus::Adsl; break; case NetworkManager::ConnectionSettings::Bluetooth: return NetworkStatus::Bluetooth; break; case NetworkManager::ConnectionSettings::Cdma: return NetworkStatus::Cdma; break; case NetworkManager::ConnectionSettings::Gsm: return NetworkStatus::Gsm; break; case NetworkManager::ConnectionSettings::Infiniband: return NetworkStatus::Infiniband; break; case NetworkManager::ConnectionSettings::OLPCMesh: return NetworkStatus::OLPCMesh; break; case NetworkManager::ConnectionSettings::Pppoe: return NetworkStatus::Pppoe; break; case NetworkManager::ConnectionSettings::Vpn: return NetworkStatus::Vpn; break; case NetworkManager::ConnectionSettings::Wired: return NetworkStatus::Wired; break; case NetworkManager::ConnectionSettings::Wireless: return NetworkStatus::Wireless; break; default: return NetworkStatus::Other; break; } } NetworkStatus::NetworkStatus(QObject* parent) : QObject(parent) { connect(NetworkManager::notifier(), &NetworkManager::Notifier::statusChanged, this, &NetworkStatus::statusChanged); connect(NetworkManager::notifier(), &NetworkManager::Notifier::activeConnectionsChanged, this, QOverload<>::of(&NetworkStatus::activeConnectionsChanged)); activeConnectionsChanged(); statusChanged(NetworkManager::status()); } NetworkStatus::~NetworkStatus() { } QString NetworkStatus::activeConnections() const { return m_activeConnections; } QString NetworkStatus::networkStatus() const { return m_networkStatus; } void NetworkStatus::activeConnectionsChanged() { - Q_FOREACH (const NetworkManager::ActiveConnection::Ptr & active, NetworkManager::activeConnections()) { + for (const NetworkManager::ActiveConnection::Ptr & active : NetworkManager::activeConnections()) { connect(active.data(), &NetworkManager::ActiveConnection::default4Changed, this, &NetworkStatus::defaultChanged, Qt::UniqueConnection); connect(active.data(), &NetworkManager::ActiveConnection::default6Changed, this, &NetworkStatus::defaultChanged, Qt::UniqueConnection); connect(active.data(), &NetworkManager::ActiveConnection::stateChanged, this, &NetworkStatus::changeActiveConnections); } changeActiveConnections(); } void NetworkStatus::defaultChanged() { statusChanged(NetworkManager::status()); } void NetworkStatus::statusChanged(NetworkManager::Status status) { switch (status) { case NetworkManager::ConnectedLinkLocal: m_networkStatus = i18nc("A network device is connected, but there is only link-local connectivity", "Connected"); break; case NetworkManager::ConnectedSiteOnly: m_networkStatus = i18nc("A network device is connected, but there is only site-local connectivity", "Connected"); break; case NetworkManager::Connected: m_networkStatus = i18nc("A network device is connected, with global network connectivity", "Connected"); break; case NetworkManager::Asleep: m_networkStatus = i18nc("Networking is inactive and all devices are disabled", "Inactive"); break; case NetworkManager::Disconnected: m_networkStatus = i18nc("There is no active network connection", "Disconnected"); break; case NetworkManager::Disconnecting: m_networkStatus = i18nc("Network connections are being cleaned up", "Disconnecting"); break; case NetworkManager::Connecting: m_networkStatus = i18nc("A network device is connecting to a network and there is no other available network connection", "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(m_activeConnections); } Q_EMIT networkStatusChanged(m_networkStatus); } void NetworkStatus::changeActiveConnections() { if (NetworkManager::status() != NetworkManager::Connected && NetworkManager::status() != NetworkManager::ConnectedLinkLocal && NetworkManager::status() != NetworkManager::ConnectedSiteOnly) { return; } QString activeConnections; const QString format = QStringLiteral("%1: %2"); QList activeConnectionList = NetworkManager::activeConnections(); std::sort(activeConnectionList.begin(), activeConnectionList.end(), [] (const NetworkManager::ActiveConnection::Ptr &left, const NetworkManager::ActiveConnection::Ptr &right) { return NetworkStatus::connectionTypeToSortedType(left->type()) < NetworkStatus::connectionTypeToSortedType(right->type()); }); - Q_FOREACH (const NetworkManager::ActiveConnection::Ptr & active, activeConnectionList) { + 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 NM_CHECK_VERSION(0, 9, 10) if (device && device->type() != NetworkManager::Device::Generic && device->type() <= NetworkManager::Device::Team) { #else if (device) { #endif bool connecting = false; bool connected = false; QString conType; QString status; NetworkManager::VpnConnection::Ptr vpnConnection; if (active->vpn()) { conType = i18n("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 = i18n("Connecting to %1", connection->name()); } else if (connected) { status = i18n("Connected to %1", connection->name()); } if (!activeConnections.isEmpty()) { activeConnections += '\n'; } activeConnections += format.arg(conType, status); connect(connection.data(), &NetworkManager::Connection::updated, this, &NetworkStatus::changeActiveConnections, Qt::UniqueConnection); } } } m_activeConnections = activeConnections; Q_EMIT activeConnectionsChanged(activeConnections); } QString NetworkStatus::checkUnknownReason() const { // Check if NetworkManager is running. if (!QDBusConnection::systemBus().interface()->isServiceRegistered(NM_DBUS_INTERFACE)) { return i18n("NetworkManager not running"); } // Check for compatible NetworkManager version. if (NetworkManager::compareVersion(0, 9, 8) < 0) { return i18n("NetworkManager 0.9.8 required, found %1.", NetworkManager::version()); } return i18nc("global connection state", "Unknown"); } diff --git a/libs/editor/mobileproviders.cpp b/libs/editor/mobileproviders.cpp index 113458ff..cdff32c7 100644 --- a/libs/editor/mobileproviders.cpp +++ b/libs/editor/mobileproviders.cpp @@ -1,337 +1,337 @@ /* Copyright 2010-2012 Lamarque Souza This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License or (at your option) version 3 or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of version 3 of the license. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "debug.h" #include "mobileproviders.h" #include #include #include const QString MobileProviders::ProvidersFile = "/usr/share/mobile-broadband-provider-info/serviceproviders.xml"; bool localeAwareCompare(const QString & one, const QString & two) { return one.localeAwareCompare(two) < 0; } MobileProviders::MobileProviders() { for (int c = 1; c <= QLocale::LastCountry; c++) { const auto country = static_cast(c); QLocale locale(QLocale::AnyLanguage, country); if (locale.country() == country) { const QString localeName = locale.name(); const auto idx = localeName.indexOf(QLatin1Char('_')); if (idx != -1) { const QString countryCode = localeName.mid(idx + 1); QString countryName = locale.nativeCountryName(); if (countryName.isEmpty()) { countryName = QLocale::countryToString(country); } mCountries.insert(countryCode, countryName); } } } mError = Success; QFile file2(ProvidersFile); if (file2.open(QIODevice::ReadOnly)) { if (mDocProviders.setContent(&file2)) { docElement = mDocProviders.documentElement(); if (docElement.isNull()) { qCWarning(PLASMA_NM) << ProvidersFile << ": document is null"; mError = ProvidersIsNull; } else { if (docElement.isNull() || docElement.tagName() != "serviceproviders") { qCWarning(PLASMA_NM) << ProvidersFile << ": wrong format"; mError = ProvidersWrongFormat; } else { if (docElement.attribute("format") != "2.0") { qCWarning(PLASMA_NM) << ProvidersFile << ": mobile broadband provider database format '" << docElement.attribute("format") << "' not supported."; mError = ProvidersFormatNotSupported; } else { // qCDebug(PLASMA_NM) << "Everything is alright so far"; } } } } file2.close(); } else { qCWarning(PLASMA_NM) << "Error opening providers file" << ProvidersFile; mError = ProvidersMissing; } } MobileProviders::~MobileProviders() { } QStringList MobileProviders::getCountryList() const { QStringList temp = mCountries.values(); qSort(temp.begin(), temp.end(), localeAwareCompare); return temp; } QString MobileProviders::countryFromLocale() const { const QString localeName = QLocale().name(); const auto idx = localeName.indexOf(QLatin1Char('_')); if (idx != -1) { return localeName.mid(idx + 1); } return QString(); } QStringList MobileProviders::getProvidersList(QString country, NetworkManager::ConnectionSettings::ConnectionType type) { mProvidersGsm.clear(); mProvidersCdma.clear(); QDomNode n = docElement.firstChild(); // country is a country name and we parse country codes. if (!mCountries.key(country).isNull()) { country = mCountries.key(country); } QMap sortedGsm; QMap sortedCdma; while (!n.isNull()) { QDomElement e = n.toElement(); // if (!e.isNull() && e.attribute("code").toUpper() == country) { QDomNode n2 = e.firstChild(); while (!n2.isNull()) { QDomElement e2 = n2.toElement(); // if (!e2.isNull() && e2.tagName().toLower() == "provider") { QDomNode n3 = e2.firstChild(); bool hasGsm = false; bool hasCdma = false; QMap localizedProviderNames; while (!n3.isNull()) { QDomElement e3 = n3.toElement(); // if (!e3.isNull()) { if (e3.tagName().toLower() == "gsm") { hasGsm = true; } else if (e3.tagName().toLower() == "cdma") { hasCdma = true; } else if (e3.tagName().toLower() == "name") { QString lang = e3.attribute("xml:lang"); if (lang.isEmpty()) { lang = "en"; // English is default } else { lang = lang.toLower(); lang.remove(QRegExp("\\-.*$")); // Remove everything after '-' in xml:lang attribute. } localizedProviderNames.insert(lang, e3.text()); } } n3 = n3.nextSibling(); } const QString name = getNameByLocale(localizedProviderNames); if (hasGsm) { mProvidersGsm.insert(name, e2.firstChild()); sortedGsm.insert(name.toLower(), name); } if (hasCdma) { mProvidersCdma.insert(name, e2.firstChild()); sortedCdma.insert(name.toLower(), name); } } n2 = n2.nextSibling(); } break; } n = n.nextSibling(); } if (type == NetworkManager::ConnectionSettings::Gsm) { return sortedGsm.values(); } return sortedCdma.values(); } QStringList MobileProviders::getApns(const QString & provider) { mApns.clear(); mNetworkIds.clear(); if (!mProvidersGsm.contains(provider)) { return QStringList(); } QDomNode n = mProvidersGsm[provider]; while (!n.isNull()) { QDomElement e = n.toElement(); // if (!e.isNull() && e.tagName().toLower() == "gsm") { QDomNode n2 = e.firstChild(); while (!n2.isNull()) { QDomElement e2 = n2.toElement(); // if (!e2.isNull() && e2.tagName().toLower() == "apn") { bool isInternet = true; QDomNode n3 = e2.firstChild(); while (!n3.isNull()) { QDomElement e3 = n3.toElement(); // if (!e3.isNull() && e3.tagName().toLower() == "usage" && !e3.attribute("type").isNull() && e3.attribute("type").toLower() != "internet") { // qCDebug(PLASMA_NM) << "apn" << e2.attribute("value") << "ignored because of usage" << e3.attribute("type"); isInternet = false; break; } n3 = n3.nextSibling(); } if (isInternet) { mApns.insert(e2.attribute("value"), e2.firstChild()); } } else if (!e2.isNull() && e2.tagName().toLower() == "network-id") { mNetworkIds.append(e2.attribute("mcc") + '-' + e2.attribute("mnc")); } n2 = n2.nextSibling(); } } n = n.nextSibling(); } QStringList temp = mApns.keys(); temp.sort(); return temp; } QStringList MobileProviders::getNetworkIds(const QString & provider) { if (mNetworkIds.isEmpty()) { getApns(provider); } return mNetworkIds; } QVariantMap MobileProviders::getApnInfo(const QString & apn) { QVariantMap temp; QDomNode n = mApns[apn]; QStringList dnsList; QMap localizedPlanNames; while (!n.isNull()) { QDomElement e = n.toElement(); // if (!e.isNull()) { if (e.tagName().toLower() == "name") { QString lang = e.attribute("xml:lang"); if (lang.isEmpty()) { lang = "en"; // English is default } else { lang = lang.toLower(); lang.remove(QRegExp("\\-.*$")); // Remove everything after '-' in xml:lang attribute. } localizedPlanNames.insert(lang, e.text()); } else if (e.tagName().toLower() == "username") { temp.insert("username", e.text()); } else if (e.tagName().toLower() == "password") { temp.insert("password", e.text()); } else if (e.tagName().toLower() == "dns") { dnsList.append(e.text()); } } n = n.nextSibling(); } QString name = getNameByLocale(localizedPlanNames); if (!name.isEmpty()) { temp.insert("name", QVariant::fromValue(name)); } temp.insert("number", getGsmNumber()); temp.insert("apn", apn); temp.insert("dnsList", dnsList); return temp; } QVariantMap MobileProviders::getCdmaInfo(const QString & provider) { if (!mProvidersCdma.contains(provider)) { return QVariantMap(); } QVariantMap temp; QDomNode n = mProvidersCdma[provider]; QStringList sidList; while (!n.isNull()) { QDomElement e = n.toElement(); // if (!e.isNull() && e.tagName().toLower() == "cdma") { QDomNode n2 = e.firstChild(); while (!n2.isNull()) { QDomElement e2 = n2.toElement(); // if (!e2.isNull()) { if (e2.tagName().toLower() == "username") { temp.insert("username", e2.text()); } else if (e2.tagName().toLower() == "password") { temp.insert("password", e2.text()); } else if (e2.tagName().toLower() == "sid") { sidList.append(e2.text()); } } n2 = n2.nextSibling(); } } n = n.nextSibling(); } temp.insert("number", getCdmaNumber()); temp.insert("sidList", sidList); return temp; } -QString MobileProviders::getNameByLocale(const QMap & localizedNames) const +QString MobileProviders::getNameByLocale(const QMap &localizedNames) const { QString name; const QStringList locales = QLocale().uiLanguages(); - Q_FOREACH (const QString & locale, locales) { + for (const QString &locale : locales) { QString language = locale.split(QLatin1Char('-')).at(0); if (localizedNames.contains(language)) { return localizedNames[language]; } } name = localizedNames["en"]; // Use any language if no proper localized name were found. if (name.isEmpty() && !localizedNames.isEmpty()) { name = localizedNames.constBegin().value(); } return name; } diff --git a/libs/editor/simpleipv4addressvalidator.cpp b/libs/editor/simpleipv4addressvalidator.cpp index ce0af31e..235b7ec5 100644 --- a/libs/editor/simpleipv4addressvalidator.cpp +++ b/libs/editor/simpleipv4addressvalidator.cpp @@ -1,169 +1,169 @@ /* Copyright 2009 Paul Marchouk This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License or (at your option) version 3 or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of version 3 of the license. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "simpleipv4addressvalidator.h" #include #include SimpleIpV4AddressValidator::SimpleIpV4AddressValidator(QObject *parent, AddressStyle style) : QValidator(parent) , m_addressStyle(style) { switch (style) { case Base: m_validator.setRegularExpression(QRegularExpression(QLatin1String("[0-9, ]{1,3}\\.[0-9, ]{1,3}\\.[0-9, ]{1,3}\\.[0-9, ]{1,3}"))); break; case WithCidr: m_validator.setRegularExpression(QRegularExpression(QLatin1String("([0-9]{1,3}\\.){3,3}[0-9]{1,3}/[0-9]{1,2}"))); break; case WithPort: m_validator.setRegularExpression(QRegularExpression(QLatin1String("([0-9]{1,3}\\.){3,3}[0-9]{1,3}:[0-9]{1,5}"))); break; } } SimpleIpV4AddressValidator::~SimpleIpV4AddressValidator() { } QValidator::State SimpleIpV4AddressValidator::validate(QString &address, int &pos) const { QValidator::State maskResult = checkWithInputMask(address, pos); if (QValidator::Invalid == maskResult) { return QValidator::Invalid; } // this list will be filled with tetrad values. It can be used to make // some additional correctness checks on the last validation step. QList tetrads; QValidator::State tetradResult = checkTetradsRanges(address, tetrads); if (QValidator::Invalid == tetradResult) return QValidator::Invalid; else if (QValidator::Intermediate == tetradResult || QValidator::Intermediate == maskResult) return QValidator::Intermediate; else return QValidator::Acceptable; } QValidator::State SimpleIpV4AddressValidator::checkWithInputMask(QString &value, int &pos) const { return m_validator.validate(value, pos); } QValidator::State SimpleIpV4AddressValidator::checkTetradsRanges(QString &value, QList &tetrads) const { QStringList temp; QVector addrParts; QStringList cidrParts; QStringList portParts; switch (m_addressStyle) { case Base: addrParts = value.splitRef(QLatin1Char('.')); break; case WithCidr: cidrParts = value.split(QLatin1Char('/')); addrParts = cidrParts[0].splitRef(QLatin1Char('.')); break; case WithPort: portParts = value.split(QLatin1Char(':')); addrParts = portParts[0].splitRef(QLatin1Char('.')); break; } int i = 0; // fill in the list with invalid values tetrads << -1 << -1 << -1 << -1; // lets check address parts - Q_FOREACH (const QStringRef &part, addrParts) { + for (const QStringRef &part : addrParts) { if (part.isEmpty()) { if (i != (addrParts.size() - 1)) { // qCDebug(PLASMA_NM) << "part.isEmpty()"; return QValidator::Invalid; } // the last tetrad can be empty, continue... return QValidator::Intermediate; } tetrads[i] = part.toInt(); if (tetrads[i] > 255) { // qCDebug(PLASMA_NM) << "tetrads[i] > 255"; return QValidator::Invalid; } // correct tetrad value: for example, 001 -> 1 temp.append(QString::number(tetrads[i])); i++; } // replace input string with the corrected version value = temp.join(QLatin1String(".")); if (i < 4) { // not all tetrads are filled... continue // qCDebug(PLASMA_NM) << "QValidator::Intermediate"; return QValidator::Intermediate; } else { if (m_addressStyle == WithCidr) { if (cidrParts.size() > 1) { value += QLatin1String("/"); if (!cidrParts[1].isEmpty()) { int cidrValue = cidrParts[1].toInt(); if (cidrValue > 32) { return QValidator::Invalid; } else { value += cidrParts[1]; return QValidator::Acceptable; } } else { return QValidator::Intermediate; } } } else if (m_addressStyle == WithPort) { if (portParts.size() > 1) { value += QLatin1String(":"); if (!portParts[1].isEmpty()) { int portValue = portParts[1].toInt(); if (portValue > 65535) { return QValidator::Invalid; } else { value += portParts[1]; return QValidator::Acceptable; } } else { return QValidator::Intermediate; } } } // qCDebug(PLASMA_NM) << "QValidator::Acceptable"; return QValidator::Acceptable; } } diff --git a/libs/editor/simpleipv6addressvalidator.cpp b/libs/editor/simpleipv6addressvalidator.cpp index 483c4f54..93cf464c 100644 --- a/libs/editor/simpleipv6addressvalidator.cpp +++ b/libs/editor/simpleipv6addressvalidator.cpp @@ -1,187 +1,187 @@ /* Copyright 2011 Ilia Kats , based on work by Paul Marchouk This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License or (at your option) version 3 or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of version 3 of the license. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "simpleipv6addressvalidator.h" #include #include SimpleIpV6AddressValidator::SimpleIpV6AddressValidator(QObject *parent, AddressStyle style) : QValidator(parent) , m_addressStyle(style) { switch (style) { case Base: m_validator.setRegularExpression(QRegularExpression(QLatin1String("([0-9a-fA-F]{1,4}|:)+"))); break; case WithCidr: m_validator.setRegularExpression(QRegularExpression(QLatin1String("([0-9a-fA-F]{1,4}|:){2,15}/[0-9]{1,3}"))); break; case WithPort: m_validator.setRegularExpression(QRegularExpression(QLatin1String("\\[([0-9a-fA-F]{1,4}|:)+\\]:[0-9]{1,5}"))); } } SimpleIpV6AddressValidator::~SimpleIpV6AddressValidator() { } QValidator::State SimpleIpV6AddressValidator::validate(QString &address, int &pos) const { if (QValidator::Invalid == checkWithInputMask(address, pos)) { return QValidator::Invalid; } return checkTetradsRanges(address); } QValidator::State SimpleIpV6AddressValidator::checkWithInputMask(QString &value, int &pos) const { return m_validator.validate(value, pos); } QValidator::State SimpleIpV6AddressValidator::checkTetradsRanges(QString &value) const { QStringList addrParts; QStringList cidrParts; QStringList portParts; bool foundBracket = false; QValidator::State result = QValidator::Acceptable; switch (m_addressStyle) { case Base: addrParts = value.split(QLatin1Char(':')); break; case WithCidr: cidrParts = value.split(QLatin1Char('/')); addrParts = cidrParts[0].split(QLatin1Char(':')); break; case WithPort: if (value.isEmpty()) return QValidator::Intermediate; if (value[0] != '[') { return QValidator::Invalid; } else { // Input: "[1:2:3:4:5:6:7:8]:123" // bracketParts: "[1:2:3:4:5:6:7:8" , ":123" // addrParts: "" , "1:2:3:4:5:6:7:8" // portParts: "", "123" QStringList bracketParts = value.split(QLatin1Char(']')); if (bracketParts.size() < 2) portParts = QStringList(); else { foundBracket = true; if (!bracketParts[1].isEmpty() && bracketParts[1][0] != ':') return QValidator::Invalid; else portParts = bracketParts[1].split(QLatin1Char(':')); } addrParts = bracketParts[0].split(QLatin1Char('['))[1].split(QLatin1Char(':')); } } int number = addrParts.size(); // There is no case where can be more than 8 colons (9 parts) // and only one unusual case where there are 8 colons (1:2:3:4:5:6:7::) if (number > 9) return QValidator::Invalid; else if (number == 9 && (!addrParts[7].isEmpty() || !addrParts[8].isEmpty())) return QValidator::Invalid; // lets check address parts bool emptypresent = false; int i = 1; - Q_FOREACH (QString part, addrParts) { // krazy:exclude=Q_FOREACH + for (QString part : addrParts) { if (part.isEmpty() && i < number) { // There is only one case where you can have 3 empty parts // and that is when you have the string: "::" which is valid // and useful and of course it can also be extended to ::123 for // instance. Anywhere other than the beginning though, having 3 empty // parts indicates either a run of 3 colons ("1:::6")" or two sets of // 2 colons ("1:2::3:4::") which are always invalid if (emptypresent && i != 2) { // qCDebug(PLASMA_NM) << "part.isEmpty()"; return QValidator::Invalid; } else { // If this is an empty part then set it to zero to not fail // the next test part.setNum(0,16); emptypresent = true; } } i++; bool ok; if (part.toInt(&ok, 16) > 65535) { return QValidator::Invalid; } } // A special case: a single colon needs to be Intermediate not Acceptable if (number == 2 && addrParts[0].isEmpty() && addrParts[1].isEmpty()) result = QValidator::Intermediate; // Another special case: a single colon followed by something (i.e. ":123" // is invalid else if (number > 1 && addrParts[0].isEmpty() && !addrParts[1].isEmpty()) result = QValidator::Invalid; // If we don't have 8 parts yet and none of them are empty we aren't done yet else if (number < 8 && !emptypresent) result = QValidator::Intermediate; // If we have 8 parts but the last one is empty we aren't done yet else if (number == 8 && addrParts[7].isEmpty()) result = QValidator::Intermediate; if (m_addressStyle == WithCidr) { int cidrSize = cidrParts.size(); // If we have a '/' and the basic address portion is not // yet complete (i.e. Intermediate) then the whole thing is Invalid if (cidrSize == 2 && result == QValidator::Intermediate) return QValidator::Invalid; if (cidrSize == 1 || (cidrSize == 2 && cidrParts[1].isEmpty())) return QValidator::Intermediate; int cidrValue = cidrParts[1].toInt(); if (cidrValue > 128) return QValidator::Invalid; } else if (m_addressStyle == WithPort) { int portSize = portParts.size(); // If we have a ']' and the basic address portion is not // yet complete (i.e. Intermediate) then the whole thing is Invalid if (foundBracket && result == QValidator::Intermediate) return QValidator::Invalid; if (portSize < 2 || (portSize == 2 && portParts[1].isEmpty())) { return QValidator::Intermediate; } else { int portValue = portParts[1].toInt(); if (portValue > 65535) return QValidator::Invalid; } } return result; } diff --git a/libs/editor/widgets/mobileconnectionwizard.cpp b/libs/editor/widgets/mobileconnectionwizard.cpp index 54e0bd11..51133a1a 100644 --- a/libs/editor/widgets/mobileconnectionwizard.cpp +++ b/libs/editor/widgets/mobileconnectionwizard.cpp @@ -1,573 +1,573 @@ /* Copyright 2010-2012 Lamarque Souza Copyright 2013 Lukas Tinkl This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License or (at your option) version 3 or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of version 3 of the license. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "mobileconnectionwizard.h" #include "uiutils.h" #include #include #include #include #include #include #include #define NUMBER_OF_STATIC_ENTRIES 3 MobileConnectionWizard::MobileConnectionWizard(NetworkManager::ConnectionSettings::ConnectionType connectionType, QWidget * parent) : QWizard(parent) { if (connectionType == NetworkManager::ConnectionSettings::Unknown) { mInitialMethodType = false; } else { mInitialMethodType = true; if (connectionType == NetworkManager::ConnectionSettings::Bluetooth) { mType = NetworkManager::ConnectionSettings::Gsm; } else { mType = connectionType; } } mProviders = new MobileProviders(); setWindowTitle(i18nc("Mobile Connection Wizard", "New Mobile Broadband Connection")); addPage(createIntroPage()); addPage(createCountryPage()); addPage(createProvidersPage()); addPage(createPlansPage()); addPage(createConfirmPage()); setOptions(QWizard::NoBackButtonOnStartPage); } MobileConnectionWizard::~MobileConnectionWizard() { delete mProviders; } MobileProviders::ErrorCodes MobileConnectionWizard::getError() { if (mProviders) { return mProviders->getError(); } return MobileProviders::Success; } void MobileConnectionWizard::initializePage(int id) { switch (id) { case 1: { // Country Page if (country.isEmpty()) { country = mProviders->countryFromLocale(); } if (country.isEmpty()) mCountryList->setCurrentRow(0); else { QList items = mCountryList->findItems(mProviders->getCountryName(country), Qt::MatchExactly); if (!items.empty()) { mCountryList->setCurrentItem(items.first()); } } if (!mInitialMethodType) { NetworkManager::Device::Ptr iface = NetworkManager::findNetworkInterface(mDeviceComboBox->itemData(mDeviceComboBox->currentIndex()).toString()); if (iface) { NetworkManager::ModemDevice::Ptr nmModemIface = iface.objectCast(); if (nmModemIface && UiUtils::modemSubType(nmModemIface->currentCapabilities()) == NetworkManager::ModemDevice::CdmaEvdo) { mType = NetworkManager::ConnectionSettings::Cdma; } else { mType = NetworkManager::ConnectionSettings::Gsm; } } else { mType = static_cast(mDeviceComboBox->itemData(mDeviceComboBox->currentIndex()).toUInt()); } } if (mProviders->getError() != MobileProviders::Success) { accept(); } break; } case 2: // Providers Page country = mCountryList->currentItem()->text(); mProvidersList->clear(); lineEditProvider->clear(); radioAutoProvider->setChecked(true); switch (type()) { case NetworkManager::ConnectionSettings::Gsm: mProvidersList->insertItems(0, mProviders->getProvidersList(country, NetworkManager::ConnectionSettings::Gsm)); break; case NetworkManager::ConnectionSettings::Cdma: mProvidersList->insertItems(0, mProviders->getProvidersList(country, NetworkManager::ConnectionSettings::Cdma)); break; default: break; } mProvidersList->setCurrentRow(0); if (mProvidersList->count() > 0) { mProvidersList->setEnabled(true); radioAutoProvider->setEnabled(true); mProvidersList->setFocus(); } else { mProvidersList->setEnabled(false); radioAutoProvider->setEnabled(false); radioManualProvider->setChecked(true); // TODO: this does not work, try reimplementing QWizardPage::isComplete() //button(QWizard::NextButton)->setEnabled(false); } break; case 3: // Plans Page disconnect(mPlanComboBox, QOverload::of(&KComboBox::currentIndexChanged), this, &MobileConnectionWizard::slotEnablePlanEditBox); mPlanComboBox->clear(); if (type() != NetworkManager::ConnectionSettings::Gsm) { goto OUT_3; } if (radioManualProvider->isChecked()) { mPlanComboBox->addItem(i18nc("Mobile Connection Wizard", "My plan is not listed...")); if (lineEditProvider->text().isEmpty()) { lineEditProvider->setText(i18nc("Mobile Connection Wizard", "Unknown Provider")); } } else { if (mProvidersList->currentItem() != nullptr) { const QStringList mApns = mProviders->getApns(mProvidersList->currentItem()->text()); if (!mApns.isEmpty()) { mPlanComboBox->insertItems(0, mApns); mPlanComboBox->setItemText(0, i18nc("Mobile Connection Wizard", "Default")); } } if (mPlanComboBox->count()) { mPlanComboBox->insertSeparator(1); } mPlanComboBox->addItem(i18nc("Mobile Connection Wizard", "My plan is not listed...")); } mPlanComboBox->setCurrentIndex(0); slotEnablePlanEditBox(mPlanComboBox->currentText()); OUT_3: connect(mPlanComboBox, QOverload::of(&KComboBox::currentIndexChanged), this, &MobileConnectionWizard::slotEnablePlanEditBox); break; case 4: // Confirm Page if (radioManualProvider->isChecked()) { labelProvider->setText(" " + lineEditProvider->text() + ", " + country); provider = lineEditProvider->text(); } else { labelProvider->setText(" " + mProvidersList->currentItem()->text() + ", " + country); provider = mProvidersList->currentItem()->text(); } if (type() == NetworkManager::ConnectionSettings::Cdma) { labelPlanLabel->hide(); labelPlan->hide(); labelApn->hide(); userApn->clear(); apn.clear(); } else { labelPlanLabel->show(); labelPlan->show(); labelApn->show(); if (mPlanComboBox->currentText() == i18nc("Mobile Connection Wizard", "My plan is not listed...")) { labelPlan->setText(" " + userApn->text()); labelApn->setText(" " + i18nc("Mobile Connection Wizard", "APN: %1", userApn->text())); apn = userApn->text(); } else { int i = mPlanComboBox->currentIndex(); i = i > 1 ? (i-1) : 0; // ignores separator's index (i == 1). QStringList mApns = mProviders->getApns(mProvidersList->currentItem()->text()); labelPlan->setText(" " + mPlanComboBox->currentText()); labelApn->setText(" " + i18nc("Mobile Connection Wizard", "APN: %1", mApns.at(i))); apn = mApns.at(i); } } break; } } int MobileConnectionWizard::nextId() const { // Providers page if (currentId() == 2 && type() != NetworkManager::ConnectionSettings::Gsm) { // Jumps to Confirm page instead of Plans page if type != Gsm. return 4; } else { return QWizard::nextId(); } } QVariantList MobileConnectionWizard::args() { QVariantList temp; switch (type()) { case NetworkManager::ConnectionSettings::Cdma: temp << provider << mProviders->getCdmaInfo(provider); break; case NetworkManager::ConnectionSettings::Gsm: temp << provider /*<< mProviders->getNetworkIds(provider)*/ << mProviders->getApnInfo(apn); break; default: break; } return temp; } /**********************************************************/ /* Intro page */ /**********************************************************/ QWizardPage * MobileConnectionWizard::createIntroPage() { QWizardPage *page = new QWizardPage(); page->setTitle(i18nc("Mobile Connection Wizard", "Set up a Mobile Broadband Connection")); QVBoxLayout *layout = new QVBoxLayout; QLabel *label = new QLabel(i18nc("Mobile Connection Wizard", "This assistant helps you easily set up a mobile broadband connection to a cellular (3G) network.")); label->setWordWrap(true); layout->addWidget(label); label = new QLabel('\n' + i18nc("Mobile Connection Wizard", "You will need the following information:")); layout->addWidget(label); label = new QLabel(QString(" . %1\n . %2\n . %3"). arg(i18nc("Mobile Connection Wizard", "Your broadband provider's name")). arg(i18nc("Mobile Connection Wizard", "Your broadband billing plan name")). arg(i18nc("Mobile Connection Wizard", "(in some cases) Your broadband billing plan APN (Access Point Name)"))); layout->addWidget(label); if (!mInitialMethodType) { label = new QLabel('\n' + i18nc("Mobile Connection Wizard", "Create a connection for &this mobile broadband device:")); layout->addWidget(label); mDeviceComboBox = new KComboBox(); mDeviceComboBox->addItem(i18nc("Mobile Connection Wizard", "Any GSM device")); mDeviceComboBox->setItemData(0, NetworkManager::ConnectionSettings::Gsm); mDeviceComboBox->addItem(i18nc("Mobile Connection Wizard", "Any CDMA device")); mDeviceComboBox->setItemData(1, NetworkManager::ConnectionSettings::Cdma); mDeviceComboBox->insertSeparator(NUMBER_OF_STATIC_ENTRIES-1); label->setBuddy(mDeviceComboBox); layout->addWidget(mDeviceComboBox); connect(NetworkManager::notifier(), &NetworkManager::Notifier::deviceAdded, this, &MobileConnectionWizard::introDeviceAdded); connect(NetworkManager::notifier(), &NetworkManager::Notifier::deviceRemoved, this, &MobileConnectionWizard::introDeviceRemoved); connect(NetworkManager::notifier(), &NetworkManager::Notifier::statusChanged, this, &MobileConnectionWizard::introStatusChanged); introAddInitialDevices(); } page->setLayout(layout); return page; } void MobileConnectionWizard::introAddDevice(const NetworkManager::Device::Ptr &device) { QString desc; ModemManager::ModemDevice::Ptr modem = ModemManager::findModemDevice(device->udi()); if (modem) { ModemManager::Modem::Ptr modemInterface = modem->interface(ModemManager::ModemDevice::ModemInterface).objectCast(); if (modemInterface->powerState() == MM_MODEM_POWER_STATE_ON) { desc.append(modemInterface->manufacturer()); desc.append(" "); desc.append(modemInterface->model()); } else { QString deviceName = modemInterface->device(); - Q_FOREACH (const Solid::Device &d, Solid::Device::allDevices()) { + for (const Solid::Device &d : Solid::Device::allDevices()) { if (d.udi().contains(deviceName, Qt::CaseInsensitive)) { deviceName = d.product(); if (!deviceName.startsWith(d.vendor())) { deviceName = d.vendor() + ' ' + deviceName; } desc.append(deviceName); break; } } } } NetworkManager::ModemDevice::Ptr nmModemIface = device.objectCast(); if (!nmModemIface) { return; } if (UiUtils::modemSubType(nmModemIface->currentCapabilities()) == NetworkManager::ModemDevice::GsmUmts) { if (desc.isEmpty()) { desc.append(i18nc("Mobile Connection Wizard", "Installed GSM device")); } } else if (UiUtils::modemSubType(nmModemIface->currentCapabilities()) == NetworkManager::ModemDevice::CdmaEvdo) { if (desc.isEmpty()) { desc.append(i18nc("Mobile Connection Wizard", "Installed CDMA device")); } } else { return; } mDeviceComboBox->addItem(desc, device->uni()); if (mDeviceComboBox->count() == NUMBER_OF_STATIC_ENTRIES) { mDeviceComboBox->setCurrentIndex(0); } else { mDeviceComboBox->setCurrentIndex(NUMBER_OF_STATIC_ENTRIES); } } void MobileConnectionWizard::introDeviceAdded(const QString &uni) { introAddDevice(NetworkManager::findNetworkInterface(uni)); } void MobileConnectionWizard::introDeviceRemoved(const QString &uni) { int index = mDeviceComboBox->findData(uni); mDeviceComboBox->removeItem(index); if (mDeviceComboBox->count() == NUMBER_OF_STATIC_ENTRIES) { mDeviceComboBox->setCurrentIndex(0); if (currentId() > 0) { close(); } } else { mDeviceComboBox->setCurrentIndex(NUMBER_OF_STATIC_ENTRIES); } } void MobileConnectionWizard::introStatusChanged(NetworkManager::Status status) { switch (status) { case NetworkManager::Unknown: case NetworkManager::Asleep: case NetworkManager::Disconnected: case NetworkManager::Disconnecting: introRemoveAllDevices(); break; case NetworkManager::Connecting: case NetworkManager::ConnectedLinkLocal: case NetworkManager::ConnectedSiteOnly: case NetworkManager::Connected: introAddInitialDevices(); break; } } void MobileConnectionWizard::introAddInitialDevices() { - Q_FOREACH (const NetworkManager::Device::Ptr & n, NetworkManager::networkInterfaces()) { + for (const NetworkManager::Device::Ptr &n : NetworkManager::networkInterfaces()) { introAddDevice(n); } if (mDeviceComboBox->count() == NUMBER_OF_STATIC_ENTRIES) { mDeviceComboBox->setCurrentIndex(0); } else { mDeviceComboBox->setCurrentIndex(NUMBER_OF_STATIC_ENTRIES); } } void MobileConnectionWizard::introRemoveAllDevices() { mDeviceComboBox->clear(); mDeviceComboBox->addItem(i18nc("Mobile Connection Wizard", "Any GSM device")); mDeviceComboBox->setItemData(0, NetworkManager::ConnectionSettings::Gsm); mDeviceComboBox->addItem(i18nc("Mobile Connection Wizard", "Any CDMA device")); mDeviceComboBox->setItemData(1, NetworkManager::ConnectionSettings::Cdma); mDeviceComboBox->insertSeparator(NUMBER_OF_STATIC_ENTRIES-1); mDeviceComboBox->setCurrentIndex(0); } /**********************************************************/ /* Country page */ /**********************************************************/ QWizardPage * MobileConnectionWizard::createCountryPage() { QWizardPage *page = new QWizardPage(); page->setTitle(i18nc("Mobile Connection Wizard", "Choose your Provider's Country")); QVBoxLayout *layout = new QVBoxLayout; QLabel *label = new QLabel(i18nc("Mobile Connection Wizard", "Country List:")); layout->addWidget(label); mCountryList = new QListWidget(); mCountryList->addItem(i18nc("Mobile Connection Wizard", "My country is not listed")); mCountryList->insertItems(1, mProviders->getCountryList()); layout->addWidget(mCountryList); page->setLayout(layout); return page; } /**********************************************************/ /* Providers page */ /**********************************************************/ QWizardPage * MobileConnectionWizard::createProvidersPage() { QWizardPage *page = new QWizardPage(); page->setTitle(i18nc("Mobile Connection Wizard", "Choose your Provider")); QVBoxLayout *layout = new QVBoxLayout; radioAutoProvider = new QRadioButton(i18nc("Mobile Connection Wizard", "Select your provider from a &list:")); radioAutoProvider->setChecked(true); layout->addWidget(radioAutoProvider); mProvidersList = new QListWidget(); connect(mProvidersList, &QListWidget::itemSelectionChanged, this, &MobileConnectionWizard::slotCheckProviderList); connect(mProvidersList, &QListWidget::itemClicked, this, &MobileConnectionWizard::slotCheckProviderList); layout->addWidget(mProvidersList); radioManualProvider = new QRadioButton(i18nc("Mobile Connection Wizard", "I cannot find my provider and I wish to enter it &manually:")); layout->addWidget(radioManualProvider); connect(radioManualProvider, &QRadioButton::toggled, this, &MobileConnectionWizard::slotEnableProviderEdit); lineEditProvider = new KLineEdit(); layout->addWidget(lineEditProvider); connect(lineEditProvider, &KLineEdit::textEdited, this, &MobileConnectionWizard::slotCheckProviderEdit); page->setLayout(layout); return page; } void MobileConnectionWizard::slotEnableProviderEdit(bool checked) { if (checked) { lineEditProvider->setFocus(); } else { mProvidersList->setFocus(); } } void MobileConnectionWizard::slotCheckProviderEdit() { radioManualProvider->setChecked(true); // TODO: this does not work, try reimplementing QWizardPage::isComplete() //button(QWizard::NextButton)->setEnabled(true); } void MobileConnectionWizard::slotCheckProviderList() { radioAutoProvider->setChecked(true); lineEditProvider->clear(); } /**********************************************************/ /* Plan page */ /**********************************************************/ QWizardPage * MobileConnectionWizard::createPlansPage() { QWizardPage *page = new QWizardPage(); page->setTitle(i18nc("Mobile Connection Wizard", "Choose your Billing Plan")); QBoxLayout *layout = new QBoxLayout(QBoxLayout::TopToBottom); QLabel *label = new QLabel(i18nc("Mobile Connection Wizard", "&Select your plan:")); layout->addWidget(label); mPlanComboBox = new KComboBox(); label->setBuddy(mPlanComboBox); layout->addWidget(mPlanComboBox); label = new QLabel('\n' + i18nc("Mobile Connection Wizard", "Selected plan &APN (Access Point Name):")); layout->addWidget(label); userApn = new KLineEdit(); userApn->setEnabled(false); label->setBuddy(userApn); layout->addWidget(userApn); QHBoxLayout *layout2 = new QHBoxLayout(); label = new QLabel(); label->setPixmap(KIconLoader::global()->loadIcon("dialog-warning", KIconLoader::Dialog)); layout2->addWidget(label, 0, Qt::AlignTop); label = new QLabel(i18nc("Mobile Connection Wizard", "Warning: Selecting an incorrect plan may result in billing issues for your broadband account or may prevent connectivity.\n\nIf you are unsure of your plan please ask your provider for your plan's APN.")); label->setWordWrap(true); layout2->addWidget(label); layout->addWidget(new QLabel("")); layout->addLayout(layout2); page->setLayout(layout); return page; } void MobileConnectionWizard::slotEnablePlanEditBox(const QString & text) { if (type() != NetworkManager::ConnectionSettings::Gsm) { return; } if (text == i18nc("Mobile Connection Wizard", "My plan is not listed...")) { userApn->clear(); userApn->setEnabled(true); } else { if (mProvidersList->currentItem() != nullptr) { int i = mPlanComboBox->currentIndex(); if (i>0) i=i-1; // Skipping the separator (i==1) QStringList mApns = mProviders->getApns(mProvidersList->currentItem()->text()); userApn->setText(mApns.at(i)); } userApn->setEnabled(false); } } /**********************************************************/ /* Confirm page */ /**********************************************************/ QWizardPage * MobileConnectionWizard::createConfirmPage() { QWizardPage *page = new QWizardPage(); page->setTitle(i18nc("Mobile Connection Wizard", "Confirm Mobile Broadband Settings")); QVBoxLayout *layout = new QVBoxLayout; QLabel *label = new QLabel(i18nc("Mobile Connection Wizard", "Your mobile broadband connection is configured with the following settings:")); label->setWordWrap(true); layout->addWidget(label); label = new QLabel('\n' + i18nc("Mobile Connection Wizard", "Your Provider:")); layout->addWidget(label); labelProvider = new QLabel(); layout->addWidget(labelProvider); labelPlanLabel = new QLabel('\n' + i18nc("Mobile Connection Wizard", "Your Plan:")); layout->addWidget(labelPlanLabel); labelPlan = new QLabel(); layout->addWidget(labelPlan); labelApn = new QLabel(); labelApn->setEnabled(false); layout->addWidget(labelApn); page->setLayout(layout); return page; } diff --git a/libs/editor/widgets/settingwidget.cpp b/libs/editor/widgets/settingwidget.cpp index cb1a4d57..f9ab7354 100644 --- a/libs/editor/widgets/settingwidget.cpp +++ b/libs/editor/widgets/settingwidget.cpp @@ -1,139 +1,139 @@ /* 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 "settingwidget.h" #include "passwordfield.h" #include #include #include #include #include #include #include SettingWidget::SettingWidget(const NetworkManager::Setting::Ptr &setting, QWidget* parent, Qt::WindowFlags f): QWidget(parent, f), m_type(setting->name()) { } SettingWidget::~SettingWidget() { } void SettingWidget::loadConfig(const NetworkManager::Setting::Ptr &setting) { Q_UNUSED(setting); } void SettingWidget::loadSecrets(const NetworkManager::Setting::Ptr &setting) { Q_UNUSED(setting); } void SettingWidget::watchChangedSetting() { // Attempt to connect to all widgets representing various configurations // to notify about setting change /************ Qt Widgets ************/ // Connect all QLineEdit widgets QList lineEdits = findChildren(); - Q_FOREACH (QLineEdit *lineedit, lineEdits) { + for (QLineEdit *lineedit : lineEdits) { connect(lineedit, &QLineEdit::textChanged, this, &SettingWidget::settingChanged); } // Connect all QComboBox widgets QList comboboxes = findChildren(); - Q_FOREACH (QComboBox *combobox, comboboxes) { + for (QComboBox *combobox : comboboxes) { connect(combobox, QOverload::of(&QComboBox::currentIndexChanged), this, &SettingWidget::settingChanged); connect(combobox, &QComboBox::currentTextChanged, this, &SettingWidget::settingChanged); } // Connect all QCheckBox widgets QList checkboxes = findChildren(); - Q_FOREACH (QCheckBox *checkbox, checkboxes) { + for (QCheckBox *checkbox : checkboxes) { connect(checkbox, &QCheckBox::stateChanged, this, &SettingWidget::settingChanged); } // Connect all QPushButton widgets QList pushbuttons = findChildren(); - Q_FOREACH (QPushButton *pushbutton, pushbuttons) { + for (QPushButton *pushbutton : pushbuttons) { connect(pushbutton, &QPushButton::clicked, this, &SettingWidget::settingChanged); } // Connect all QSpinBox widgets QList spinboxes = findChildren(); - Q_FOREACH (QSpinBox *spinbox, spinboxes) { + for (QSpinBox *spinbox : spinboxes) { connect(spinbox, QOverload::of(&QSpinBox::valueChanged), this, &SettingWidget::settingChanged); } // Connect all KUrlRequester widgets QList urlrequesters = findChildren(); - Q_FOREACH (KUrlRequester *urlrequester, urlrequesters) { + for (KUrlRequester *urlrequester : urlrequesters) { connect(urlrequester, &KUrlRequester::textChanged, this, &SettingWidget::settingChanged); connect(urlrequester, &KUrlRequester::urlSelected, this, &SettingWidget::settingChanged); } // Connect all QTableView widgets QList tableviews = findChildren(); - Q_FOREACH(QTableView *tableview, tableviews) { + for(QTableView *tableview : tableviews) { connect(tableview, &QTableView::clicked, this, &SettingWidget::settingChanged); } /********** OUR CUSTOM WIDGETS **********/ // Connect all PasswordField widgets QList passwordfields = findChildren(); - Q_FOREACH (PasswordField *passwordfield, passwordfields) { + for (PasswordField *passwordfield : passwordfields) { connect(passwordfield, &PasswordField::textChanged, this, &SettingWidget::settingChanged); connect(passwordfield, &PasswordField::passwordOptionChanged, this, &SettingWidget::settingChanged); } // Connect all HwAddrComboBox widgets // QList hwAddrcomboboxes = findChildren(); -// Q_FOREACH (HwAddrComboBox *combobox, hwAddrcomboboxes) { +// for (HwAddrComboBox *combobox : hwAddrcomboboxes) { // connect(combobox, &HwAddrComboBox::hwAddressChanged, this, &SettingWidget::settingChanged); // } // // // Connect all SssidComboBox widgets // QList ssidcomboboxes = findChildren(); -// Q_FOREACH (SsidComboBox *combobox, ssidcomboboxes) { +// for (SsidComboBox *combobox : ssidcomboboxes) { // connect(combobox, &SsidComboBox::ssidChanged, this, &SettingWidget::settingChanged); // } // // // Connect all BssidComboBox widgets // QList bssidcomboboxes = findChildren(); -// Q_FOREACH (BssidComboBox *combobox, bssidcomboboxes) { +// for (BssidComboBox *combobox : bssidcomboboxes) { // connect(combobox, &BssidComboBox::bssidChanged, this, &SettingWidget::settingChanged); // } } QString SettingWidget::type() const { return m_type; } void SettingWidget::slotWidgetChanged() { Q_EMIT validChanged(isValid()); } diff --git a/libs/handler.cpp b/libs/handler.cpp index 2103864d..071b077f 100644 --- a/libs/handler.cpp +++ b/libs/handler.cpp @@ -1,522 +1,522 @@ /* 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 "uiutils.h" #include "debug.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if WITH_MODEMMANAGER_SUPPORT #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #define AGENT_SERVICE "org.kde.kded5" #define AGENT_PATH "/modules/networkmanagement" #define AGENT_IFACE "org.kde.plasmanetworkmanagement" Handler::Handler(QObject *parent) : QObject(parent) , m_tmpWirelessEnabled(NetworkManager::isWirelessEnabled()) , m_tmpWwanEnabled(NetworkManager::isWwanEnabled()) { initKdedModule(); QDBusConnection::sessionBus().connect(QStringLiteral(AGENT_SERVICE), QStringLiteral(AGENT_PATH), QStringLiteral(AGENT_IFACE), QStringLiteral("registered"), this, SLOT(initKdedModule())); } Handler::~Handler() { } void Handler::activateConnection(const QString &connection, const QString &device, const QString &specificObject) { NetworkManager::Connection::Ptr con = NetworkManager::findConnection(connection); if (!con) { qCWarning(PLASMA_NM) << "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) { qCDebug(PLASMA_NM) << "Checking VPN" << con->name() << "type:" << vpnSetting->serviceType(); // get the list of supported VPN service types const KService::List services = KServiceTypeTrader::self()->query("PlasmaNetworkManagement/VpnUiPlugin", QString::fromLatin1("[X-NetworkManager-Services]=='%1'").arg(vpnSetting->serviceType())); if (services.isEmpty()) { qCWarning(PLASMA_NM) << "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->setPixmap(QIcon::fromTheme("dialog-warning").pixmap(KIconLoader::SizeHuge)); 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); } void Handler::addAndActivateConnection(const QString &device, const QString &specificObject, const QString &password) { NetworkManager::AccessPoint::Ptr ap; NetworkManager::WirelessDevice::Ptr wifiDev; - foreach (const NetworkManager::Device::Ptr &dev, NetworkManager::networkInterfaces()) { + 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(KUser().loginName(), 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) { qCWarning(PLASMA_NM) << "Not possible to deactivate this connection"; return; } QDBusPendingReply<> reply; - foreach (const NetworkManager::ActiveConnection::Ptr &active, NetworkManager::activeConnections()) { + 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() { - foreach (const NetworkManager::Device::Ptr &device, NetworkManager::networkInterfaces()) { + 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); } } } void Handler::enableBluetooth(bool enable) { qDBusRegisterMetaType< QMap >(); QDBusMessage message = QDBusMessage::createMethodCall("org.bluez", "/", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); QDBusPendingReply > reply = QDBusConnection::systemBus().asyncCall(message); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); connect(watcher, &QDBusPendingCallWatcher::finished, [this, enable] (QDBusPendingCallWatcher *watcher) { QDBusPendingReply > reply = *watcher; if (reply.isValid()) { - foreach (const QDBusObjectPath &path, reply.value().keys()) { + for (const QDBusObjectPath &path : reply.value().keys()) { const QString objPath = path.path(); qCDebug(PLASMA_NM) << "inspecting path" << objPath; const QStringList interfaces = reply.value().value(path).keys(); qCDebug(PLASMA_NM) << "interfaces:" << interfaces; if (interfaces.contains("org.bluez.Adapter1")) { // We need to check previous state first if (!enable) { QDBusMessage message = QDBusMessage::createMethodCall("org.bluez", objPath, "org.freedesktop.DBus.Properties", "Get"); QList arguments; arguments << QLatin1Literal("org.bluez.Adapter1"); arguments << QLatin1Literal("Powered"); message.setArguments(arguments); QDBusPendingReply getReply = QDBusConnection::systemBus().asyncCall(message); QDBusPendingCallWatcher *getWatcher = new QDBusPendingCallWatcher(getReply, this); connect(getWatcher, &QDBusPendingCallWatcher::finished, [this, objPath] (QDBusPendingCallWatcher *watcher) { QDBusPendingReply reply = *watcher; if (reply.isValid()) { m_bluetoothAdapters.insert(objPath, reply.value().toBool()); QDBusMessage message = QDBusMessage::createMethodCall("org.bluez", objPath, "org.freedesktop.DBus.Properties", "Set"); QList arguments; arguments << QLatin1Literal("org.bluez.Adapter1"); arguments << QLatin1Literal("Powered"); arguments << QVariant::fromValue(QDBusVariant(QVariant(false))); message.setArguments(arguments); QDBusConnection::systemBus().asyncCall(message); } }); getWatcher->deleteLater(); } else if (enable && m_bluetoothAdapters.value(objPath)) { QDBusMessage message = QDBusMessage::createMethodCall("org.bluez", objPath, "org.freedesktop.DBus.Properties", "Set"); QList arguments; arguments << QLatin1Literal("org.bluez.Adapter1"); arguments << QLatin1Literal("Powered"); arguments << QVariant::fromValue(QDBusVariant(QVariant(enable))); message.setArguments(arguments); QDBusConnection::systemBus().asyncCall(message); } } } } }); watcher->deleteLater(); } 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()) { qCWarning(PLASMA_NM) << "Not possible to remove connection " << connection; return; } // Remove slave connections - foreach (const NetworkManager::Connection::Ptr &connection, NetworkManager::listConnections()) { + 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() { - foreach (NetworkManager::Device::Ptr device, NetworkManager::networkInterfaces()) { + for (NetworkManager::Device::Ptr device : NetworkManager::networkInterfaces()) { if (device->type() == NetworkManager::Device::Wifi) { NetworkManager::WirelessDevice::Ptr wifiDevice = device.objectCast(); if (wifiDevice) { QDBusPendingReply<> reply = wifiDevice->requestScan(); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); watcher->setProperty("action", Handler::RequestScan); connect(watcher, &QDBusPendingCallWatcher::finished, this, &Handler::replyFinished); } } } } void Handler::initKdedModule() { QDBusMessage initMsg = QDBusMessage::createMethodCall(QStringLiteral(AGENT_SERVICE), QStringLiteral(AGENT_PATH), QStringLiteral(AGENT_IFACE), QStringLiteral("init")); QDBusConnection::sessionBus().send(initMsg); } 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::RequestScan: /* INFO: Disabled for now as wifi scanning is now automatic notification = new KNotification("FailedToRequestScan", KNotification::CloseOnTimeout, this); notification->setTitle(i18n("Failed to request scan")); */ break; case Handler::UpdateConnection: notification = new KNotification("FailedToUpdateConnection", KNotification::CloseOnTimeout, this); notification->setTitle(i18n("Failed to update connection %1", watcher->property("connection").toString())); break; default: break; } if (notification) { notification->setComponentName("networkmanagement"); notification->setText(error); notification->setPixmap(QIcon::fromTheme("dialog-warning").pixmap(KIconLoader::SizeHuge)); 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; default: break; } if (notification) { notification->setComponentName("networkmanagement"); notification->setTitle(watcher->property("connection").toString()); notification->setPixmap(QIcon::fromTheme("dialog-information").pixmap(KIconLoader::SizeHuge)); notification->sendEvent(); } } watcher->deleteLater(); } #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/vpn/openconnect/openconnectwidget.cpp b/vpn/openconnect/openconnectwidget.cpp index e81e13be..58dc6fde 100644 --- a/vpn/openconnect/openconnectwidget.cpp +++ b/vpn/openconnect/openconnectwidget.cpp @@ -1,136 +1,136 @@ /* Copyright 2011 Ilia Kats Copyright 2013 Lukas Tinkl 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 "openconnectwidget.h" #include #include #include "ui_openconnectprop.h" #include #include "nm-openconnect-service.h" #include class OpenconnectSettingWidgetPrivate { public: Ui_OpenconnectProp ui; NetworkManager::VpnSetting::Ptr setting; }; OpenconnectSettingWidget::OpenconnectSettingWidget(const NetworkManager::VpnSetting::Ptr &setting, QWidget * parent) : SettingWidget(setting, parent) , d_ptr(new OpenconnectSettingWidgetPrivate) { Q_D(OpenconnectSettingWidget); d->ui.setupUi(this); d->setting = setting; // Connect for setting check watchChangedSetting(); // Connect for validity check connect(d->ui.leGateway, &QLineEdit::textChanged, this, &OpenconnectSettingWidget::slotWidgetChanged); KAcceleratorManager::manage(this); if (d->setting) { loadConfig(d->setting); } } OpenconnectSettingWidget::~OpenconnectSettingWidget() { delete d_ptr; } void OpenconnectSettingWidget::loadConfig(const NetworkManager::Setting::Ptr &setting) { Q_D(OpenconnectSettingWidget); Q_UNUSED(setting) // General settings const NMStringMap dataMap = d->setting->data(); d->ui.cmbProtocol->setCurrentIndex(dataMap[NM_OPENCONNECT_KEY_PROTOCOL] != QLatin1String("anyconnect")); d->ui.leGateway->setText(dataMap[NM_OPENCONNECT_KEY_GATEWAY]); d->ui.leCaCertificate->setUrl(QUrl::fromLocalFile(dataMap[NM_OPENCONNECT_KEY_CACERT])); d->ui.leProxy->setText(dataMap[NM_OPENCONNECT_KEY_PROXY]); d->ui.chkAllowTrojan->setChecked(dataMap[NM_OPENCONNECT_KEY_CSD_ENABLE] == "yes"); d->ui.leCsdWrapperScript->setUrl(QUrl::fromLocalFile(dataMap[NM_OPENCONNECT_KEY_CSD_WRAPPER])); d->ui.leUserCert->setUrl(QUrl::fromLocalFile(dataMap[NM_OPENCONNECT_KEY_USERCERT])); d->ui.leUserPrivateKey->setUrl(QUrl::fromLocalFile(dataMap[NM_OPENCONNECT_KEY_PRIVKEY])); d->ui.chkUseFsid->setChecked(dataMap[NM_OPENCONNECT_KEY_PEM_PASSPHRASE_FSID] == "yes"); } QVariantMap OpenconnectSettingWidget::setting() const { Q_D(const OpenconnectSettingWidget); NetworkManager::VpnSetting setting; setting.setServiceType(QLatin1String(NM_DBUS_SERVICE_OPENCONNECT)); NMStringMap data; data.insert(NM_OPENCONNECT_KEY_PROTOCOL, d->ui.cmbProtocol->currentIndex() ? QLatin1String("nc") : QLatin1String("anyconnect")); data.insert(QLatin1String(NM_OPENCONNECT_KEY_GATEWAY), d->ui.leGateway->text()); if (d->ui.leCaCertificate->url().isValid()) { data.insert(QLatin1String(NM_OPENCONNECT_KEY_CACERT), d->ui.leCaCertificate->url().toLocalFile()); } if (!d->ui.leProxy->text().isEmpty()) { data.insert(QLatin1String(NM_OPENCONNECT_KEY_PROXY), d->ui.leProxy->text()); } data.insert(QLatin1String(NM_OPENCONNECT_KEY_CSD_ENABLE), d->ui.chkAllowTrojan->isChecked() ? "yes" : "no"); if (d->ui.leCsdWrapperScript->url().isValid()) { data.insert(QLatin1String(NM_OPENCONNECT_KEY_CSD_WRAPPER), d->ui.leCsdWrapperScript->url().toLocalFile()); } if (d->ui.leUserCert->url().isValid()) { data.insert(QLatin1String(NM_OPENCONNECT_KEY_USERCERT), d->ui.leUserCert->url().toLocalFile()); } if (d->ui.leUserPrivateKey->url().isValid()) { data.insert(QLatin1String(NM_OPENCONNECT_KEY_PRIVKEY), d->ui.leUserPrivateKey->url().toLocalFile()); } data.insert(QLatin1String(NM_OPENCONNECT_KEY_PEM_PASSPHRASE_FSID), d->ui.chkUseFsid->isChecked() ? "yes" : "no"); // Restore previous flags, this is necessary for keeping secrets stored in KWallet - Q_FOREACH (const QString &key, d->setting->data().keys()) { + for (const QString &key : d->setting->data().keys()) { if (key.contains(QLatin1String("-flags"))) { data.insert(key, d->setting->data().value(key)); } } /* These are different for every login session, and should not be stored */ data.insert(QLatin1String(NM_OPENCONNECT_KEY_COOKIE"-flags"), QString::number(NetworkManager::Setting::NotSaved)); data.insert(QLatin1String(NM_OPENCONNECT_KEY_GWCERT"-flags"), QString::number(NetworkManager::Setting::NotSaved)); data.insert(QLatin1String(NM_OPENCONNECT_KEY_GATEWAY"-flags"), QString::number(NetworkManager::Setting::NotSaved)); setting.setData(data); setting.setSecrets(d->setting->secrets()); return setting.toMap(); } bool OpenconnectSettingWidget::isValid() const { Q_D(const OpenconnectSettingWidget); return !d->ui.leGateway->text().isEmpty(); } diff --git a/vpn/openvpn/openvpn.cpp b/vpn/openvpn/openvpn.cpp index e1d8de9e..41918de6 100644 --- a/vpn/openvpn/openvpn.cpp +++ b/vpn/openvpn/openvpn.cpp @@ -1,884 +1,884 @@ /* Copyright 2008 Will Stephenson Copyright 2011-2012 Rajeesh K Nambiar Copyright 2011 Ilia Kats Copyright 2012-2016 Lamarque V. Souza This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License or (at your option) version 3 or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of version 3 of the license. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "openvpn.h" #include #include #include #include #include #include #include #include #include #include "openvpnwidget.h" #include "openvpnauth.h" #include #include "nm-openvpn-service.h" K_PLUGIN_CLASS_WITH_JSON(OpenVpnUiPlugin, "plasmanetworkmanagement_openvpnui.json") #define AUTH_TAG "auth" #define AUTH_USER_PASS_TAG "auth-user-pass" #define CA_TAG "ca" #define CERT_TAG "cert" #define CIPHER_TAG "cipher" #define CLIENT_TAG "client" #define COMP_TAG "comp-lzo" #define DEV_TAG "dev" #define FRAGMENT_TAG "fragment" #define IFCONFIG_TAG "ifconfig" #define KEY_TAG "key" #define MSSFIX_TAG "mssfix" #define PKCS12_TAG "pkcs12" #define PORT_TAG "port" #define PROTO_TAG "proto" #define HTTP_PROXY_TAG "http-proxy" #define HTTP_PROXY_RETRY_TAG "http-proxy-retry" #define SOCKS_PROXY_TAG "socks-proxy" #define SOCKS_PROXY_RETRY_TAG "socks-proxy-retry" #define REMOTE_TAG "remote" #define RENEG_SEC_TAG "reneg-sec" #define RPORT_TAG "rport" #define SECRET_TAG "secret" #define TLS_AUTH_TAG "tls-auth" #define TLS_CLIENT_TAG "tls-client" #define TLS_REMOTE_TAG "tls-remote" #define TUNMTU_TAG "tun-mtu" #define KEY_DIRECTION_TAG "key-direction" #define BEGIN_KEY_CA_TAG "" #define END_KEY_CA_TAG "" #define BEGIN_KEY_CERT_TAG "" #define END_KEY_CERT_TAG "" #define BEGIN_KEY_KEY_TAG "" #define END_KEY_KEY_TAG "" #define BEGIN_KEY_SECRET_TAG "" #define END_KEY_SECRET_TAG "" #define BEGIN_TLS_AUTH_TAG "" #define END_TLS_AUTH_TAG "" #define PROC_TYPE_TAG "Proc-Type: 4,ENCRYPTED" #define PKCS8_TAG "-----BEGIN ENCRYPTED PRIVATE KEY-----" QString localCertPath() { return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/networkmanagement/certificates/"); } QString unQuote(QString &certVal, const QString &fileName) { /* Unquote according to openvpn rules * Unquoted filename is returned, and @certVal is modified * to the leftover string */ int nextSep; QString certFile = certVal.trimmed(); if (certFile.startsWith('"') || certFile.startsWith('\'')) { // Quoted certFile.remove(0,1); // Remove the starting quote nextSep = 0; while ((nextSep = certFile.indexOf(QRegExp("\"|'"), nextSep)) != -1) { if (nextSep > 0 && certFile.at(nextSep - 1) != '\\') { // Quote not escaped certVal = certFile.right(certFile.length() - nextSep - 1); // Leftover string certFile.truncate(nextSep); // Quoted string break; } } } else { nextSep = certFile.indexOf(QRegExp("\\s")); // First whitespace if (nextSep != -1) { certVal = certFile.right(certFile.length() - nextSep - 1); // Leftover certFile = certFile.left(nextSep); // value } else { certVal.clear(); } } certFile.replace("\\\\", "\\"); // Replace '\\' with '\' certFile.replace("\\ ", " "); // Replace escaped space with space if (QFileInfo(certFile).isRelative()) { certFile = QFileInfo(fileName).dir().absolutePath() + '/' + certFile; } return certFile; } bool isEncrypted(const QString &fileName) { bool encrypted = false; // TODO: if is_pkcs12(fileName) return true; // NOTE: will have to use SEC_PKCS12DecoderStart and friends from , which will // build a new dependency on nss-devel. See NetworkManager/libnm-util/crypto_nss.c+453 QFile inFile(fileName); if (!inFile.open(QFile::ReadOnly)) { return false; } QTextStream in(&inFile); while (!in.atEnd()) { QString line = in.readLine(); if (!line.isEmpty() && (line.startsWith(PROC_TYPE_TAG) || line.startsWith(PKCS8_TAG))) { encrypted = true; break; } } inFile.close(); return encrypted; } OpenVpnUiPlugin::OpenVpnUiPlugin(QObject * parent, const QVariantList &) : VpnUiPlugin(parent) { } OpenVpnUiPlugin::~OpenVpnUiPlugin() { } SettingWidget * OpenVpnUiPlugin::widget(const NetworkManager::VpnSetting::Ptr &setting, QWidget * parent) { OpenVpnSettingWidget * wid = new OpenVpnSettingWidget(setting, parent); return wid; } SettingWidget * OpenVpnUiPlugin::askUser(const NetworkManager::VpnSetting::Ptr &setting, QWidget * parent) { return new OpenVpnAuthWidget(setting, parent); } QString OpenVpnUiPlugin::suggestedFileName(const NetworkManager::ConnectionSettings::Ptr &connection) const { return connection->id() + "_openvpn.conf"; } QString OpenVpnUiPlugin::supportedFileExtensions() const { return "*.ovpn *.conf"; } NMVariantMapMap OpenVpnUiPlugin::importConnectionSettings(const QString &fileName) { NMVariantMapMap result; QFile impFile(fileName); if (!impFile.open(QFile::ReadOnly|QFile::Text)) { mError = VpnUiPlugin::Error; mErrorMessage = i18n("Could not open file"); return result; } bool copyCertificates; KMessageBox::ButtonCode buttonCode; if (KMessageBox::shouldBeShownYesNo(QLatin1String("copyCertificatesDialog"), buttonCode)) { copyCertificates = KMessageBox::questionYesNo(nullptr, i18n("Do you want to copy your certificates to %1?", localCertPath()), i18n("Copy certificates"), KStandardGuiItem::yes(), KStandardGuiItem::no(), QLatin1String("copyCertificatesDialog")) == KMessageBox::Yes; } else { copyCertificates = buttonCode == KMessageBox::Yes; } const QString connectionName = QFileInfo(fileName).completeBaseName(); NMStringMap dataMap; NMStringMap secretData; QVariantMap ipv4Data; QString proxy_type; QString proxy_user; QString proxy_passwd; bool have_client = false; bool have_remote = false; bool proxy_set = false; bool have_pass = false; bool have_sk = false; int key_direction = -1; QTextStream in(&impFile); while (!in.atEnd()) { QStringList key_value; QString line = in.readLine(); // Skip comments if (line.indexOf('#') >= 0) { line.truncate(line.indexOf('#')); } if (line.indexOf(';') >= 0) { line.truncate(line.indexOf(';')); } if (line.isEmpty()) { continue; } key_value.clear(); key_value << line.split(QRegExp("\\s+")); // Split at one or more whitespaces if (key_value[0] == CLIENT_TAG || key_value[0] == TLS_CLIENT_TAG) { have_client = true; continue; } if (key_value[0] == DEV_TAG) { if (key_value.count() == 2) { if (key_value[1].startsWith(QLatin1String("tun"))) { // ignore; default is tun } else if (key_value[1].startsWith(QLatin1String("tap"))) { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_TAP_DEV), "yes"); } else { KMessageBox::information(nullptr, i18n("Unknown option: %1", line)); } } else { KMessageBox::information(nullptr, i18n("Invalid number of arguments (expected 1) in option: %1", line)); } continue; } if (key_value[0] == PROTO_TAG) { if (key_value.count() == 2) { /* Valid parameters are "udp", "tcp-client" and "tcp-server". * 'tcp' isn't technically valid, but it used to be accepted so * we'll handle it here anyway. */ if (key_value[1] == "udp") { // ignore; default is udp } else if (key_value[1] == "tcp-client" || key_value[1] == "tcp-server" || key_value[1] == "tcp") { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_PROTO_TCP), "yes"); } else { KMessageBox::information(nullptr, i18n("Unknown option: %1", line)); } } else { KMessageBox::information(nullptr, i18n("Invalid number of arguments (expected 1) in option: %1", line)); } continue; } if (key_value[0] == MSSFIX_TAG) { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_MSSFIX), "yes"); continue; } if (key_value[0] == TUNMTU_TAG) { if (key_value.count() == 2) { if (key_value[1].toLong() >= 0 && key_value[1].toLong() < 0xFFFF ) { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_TUNNEL_MTU), key_value[1]); } else { KMessageBox::information(nullptr, i18n("Invalid size (should be between 0 and 0xFFFF) in option: %1", line)); } } else { KMessageBox::information(nullptr, i18n("Invalid number of arguments (expected 1) in option: %1", line)); } continue; } if (key_value[0] == FRAGMENT_TAG) { if (key_value.count() == 2) { if (key_value[1].toLong() >= 0 && key_value[1].toLong() < 0xFFFF ) { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_FRAGMENT_SIZE), key_value[1]); } else { KMessageBox::information(nullptr, i18n("Invalid size (should be between 0 and 0xFFFF) in option: %1", line)); } } else { KMessageBox::information(nullptr, i18n("Invalid number of arguments (expected 1) in option: %1", line)); } continue; } if (key_value[0] == COMP_TAG) { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_COMP_LZO), "yes"); continue; } if (key_value[0] == RENEG_SEC_TAG) { if (key_value.count() == 2) { if (key_value[1].toLong() >= 0 && key_value[1].toLong() <= 604800 ) { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_RENEG_SECONDS), key_value[1]); } else { KMessageBox::information(nullptr, i18n("Invalid size (should be between 0 and 604800) in option: %1", line)); } } else { KMessageBox::information(nullptr, i18n("Invalid number of arguments (expected 1) in option: %1", line)); } continue; } if (key_value[0] == HTTP_PROXY_RETRY_TAG || key_value[0] == SOCKS_PROXY_RETRY_TAG) { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_PROXY_RETRY), "yes"); continue; } if (key_value[0] == HTTP_PROXY_TAG) { proxy_type = "http"; } if (key_value[0] == SOCKS_PROXY_TAG) { proxy_type = "socks"; } if (!proxy_type.isEmpty() && !proxy_set && key_value.count() >= 3) { bool success = true; if (proxy_type == "http" && key_value.count() >= 4) { // Parse the HTTP proxy file QFile httpProxyFile(QFileInfo(fileName).dir().absolutePath() + '/' + key_value[3]); if (httpProxyFile.open(QFile::ReadOnly|QFile::Text)) { QTextStream httpProxyIn(&httpProxyFile); while (!httpProxyIn.atEnd()) { QString httpProxyLine = httpProxyIn.readLine(); if (httpProxyLine.isEmpty()) { continue; } if (proxy_user.isEmpty()) { proxy_user = httpProxyLine; } if (proxy_passwd.isEmpty()) { proxy_passwd = httpProxyLine; break; } } if (proxy_user.isEmpty()||proxy_passwd.isEmpty()) { success = false; } } } if (success && !proxy_type.isEmpty() && key_value[2].toLong() > 0 // Port && key_value[2].toLong() < 65536) { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_PROXY_TYPE), proxy_type); dataMap.insert(QLatin1String(NM_OPENVPN_KEY_PROXY_SERVER), key_value[1]); // Proxy server dataMap.insert(QLatin1String(NM_OPENVPN_KEY_PROXY_PORT), key_value[2]); // Port if (!proxy_user.isEmpty()) { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_HTTP_PROXY_USERNAME), proxy_user); } if (!proxy_passwd.isEmpty()) { secretData.insert(QLatin1String(NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD), proxy_passwd); dataMap.insert(QLatin1String(NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD"-flags"), QString::number(NetworkManager::Setting::NotSaved)); } proxy_set = true; } if (!success) { KMessageBox::information(nullptr, i18n("Invalid proxy option: %1", line)); } continue; } if (key_value[0] == REMOTE_TAG) { if (key_value.count() >= 2 && key_value.count() <= 4) { QString remote = key_value[1]; if (remote.startsWith(QLatin1Char('\'')) || remote.startsWith(QLatin1Char('"'))) { remote.remove(0, 1); // Remove first quote remote.remove(remote.size() - 1, 1); // Remove last quote } dataMap.insert(QLatin1String(NM_OPENVPN_KEY_REMOTE), remote); have_remote = true; if (key_value.count() >= 3 && key_value[2].toLong() > 0 && key_value[2].toLong() < 65536) { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_PORT), key_value[2]); if (key_value.count() == 4) { QString protocol = key_value[3]; if(protocol.startsWith(QLatin1String("tcp"))) { dataMap[QLatin1String(NM_OPENVPN_KEY_PROTO_TCP)] = QLatin1String("yes"); } } } } } if (key_value[0] == PORT_TAG || key_value[0] == RPORT_TAG) { // Port specified in 'remote' always takes precedence if (!dataMap.contains(NM_OPENVPN_KEY_PORT)) { if (key_value.count() == 2 ) { if (key_value[1].toLong() > 0 && key_value[1].toLong() < 65536) { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_PORT), key_value[1]); } else { KMessageBox::information(nullptr, i18n("Invalid port (should be between 1 and 65535) in option: %1", line)); } } else KMessageBox::information(nullptr, i18n("Invalid number of arguments (expected 1) in option: %1", line)); } continue; } if (key_value[0] == PKCS12_TAG && key_value.count() > 1) { key_value[1] = line.right(line.length() - line.indexOf(QRegExp("\\s"))); // Get whole string after key QString certFile = unQuote(key_value[1], fileName); dataMap.insert(QLatin1String(NM_OPENVPN_KEY_CA), certFile); dataMap.insert(QLatin1String(NM_OPENVPN_KEY_CERT), certFile); dataMap.insert(QLatin1String(NM_OPENVPN_KEY_KEY), certFile); continue; } if (key_value[0] == CA_TAG && key_value.count() > 1) { key_value[1] = line.right(line.length() - line.indexOf(QRegExp("\\s"))); // Get whole string after key if (key_value[1].trimmed() == QLatin1String("[inline]")) { // No data or file to copy for now, it will be available later when we reach tag. continue; } if (copyCertificates) { const QString absoluteFilePath = tryToCopyToCertificatesDirectory(connectionName, unQuote(key_value[1], fileName)); dataMap.insert(QLatin1String(NM_OPENVPN_KEY_CA), absoluteFilePath); } else { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_CA), unQuote(key_value[1], fileName)); } continue; } if (key_value[0] == CERT_TAG && key_value.count() > 1) { key_value[1] = line.right(line.length() - line.indexOf(QRegExp("\\s"))); // Get whole string after key if (key_value[1].trimmed() == QLatin1String("[inline]")) { // No data or file to copy for now, it will be available later when we reach tag. continue; } if (copyCertificates) { const QString absoluteFilePath = tryToCopyToCertificatesDirectory(connectionName, unQuote(key_value[1], fileName)); dataMap.insert(QLatin1String(NM_OPENVPN_KEY_CERT), absoluteFilePath); } else { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_CERT), unQuote(key_value[1], fileName)); } continue; } if (key_value[0] == KEY_TAG && key_value.count() > 1) { key_value[1] = line.right(line.length() - line.indexOf(QRegExp("\\s"))); // Get whole string after key if (key_value[1].trimmed() == QLatin1String("[inline]")) { // No data or file to copy for now, it will be available later when we reach tag. continue; } if (copyCertificates) { const QString absoluteFilePath = tryToCopyToCertificatesDirectory(connectionName, unQuote(key_value[1], fileName)); dataMap.insert(QLatin1String(NM_OPENVPN_KEY_KEY), absoluteFilePath); } else { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_KEY), unQuote(key_value[1], fileName)); } continue; } if (key_value[0] == SECRET_TAG && key_value.count() > 1) { key_value[1] = line.right(line.length() - line.indexOf(QRegExp("\\s"))); // Get whole string after key if (copyCertificates) { const QString absoluteFilePath = tryToCopyToCertificatesDirectory(connectionName, unQuote(key_value[1], fileName)); dataMap.insert(QLatin1String(NM_OPENVPN_KEY_STATIC_KEY), absoluteFilePath); } else { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_STATIC_KEY), unQuote(key_value[1], fileName)); } if (key_value.count() > 2) { key_value[2] = key_value[1]; if (!key_value[2].isEmpty() && (key_value[2].toLong() == 0 ||key_value[2].toLong() == 1)) { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_STATIC_KEY_DIRECTION), key_value[2]); } } have_sk = true; continue; } if (key_value[0] == TLS_AUTH_TAG && key_value.count() >1) { key_value[1] = line.right(line.length() - line.indexOf(QRegExp("\\s"))); // Get whole string after key // We will copy inline certificate later when we reach tag. if (key_value[1].trimmed() != QLatin1String("[inline]")) { if (copyCertificates) { const QString absoluteFilePath = tryToCopyToCertificatesDirectory(connectionName, unQuote(key_value[1], fileName)); dataMap.insert(QLatin1String(NM_OPENVPN_KEY_TA), absoluteFilePath); } else { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_TA), unQuote(key_value[1], fileName)); } } if (key_value.count() > 2) { key_value[2] = key_value[1]; if (!key_value[2].isEmpty() && (key_value[2].toLong() == 0 ||key_value[2].toLong() == 1)) { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_TA_DIR), key_value[2]); } } continue; } if (key_value[0] == CIPHER_TAG) { if (key_value.count() == 2) { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_CIPHER), key_value[1]); } else { KMessageBox::information(nullptr, i18n("Invalid number of arguments (expected 1) in option: %1", line)); } continue; } if (key_value[0] == TLS_REMOTE_TAG) { if (!unQuote(key_value[1], fileName).isEmpty()) { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_TLS_REMOTE), key_value[1]); } else { KMessageBox::information(nullptr, i18n("Unknown option: %1", line)); } continue; } if (key_value[0] == IFCONFIG_TAG) { if (key_value.count() == 3) { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_LOCAL_IP), key_value[1]); dataMap.insert(QLatin1String(NM_OPENVPN_KEY_REMOTE_IP), key_value[2]); } else { KMessageBox::information(nullptr, i18n("Invalid number of arguments (expected 2) in option: %1", line)); } continue; } if (key_value[0] == AUTH_USER_PASS_TAG) { have_pass = true; } if (key_value[0] == AUTH_TAG) { if (key_value.count() == 2) { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_AUTH), key_value[1]); } else { KMessageBox::information(nullptr, i18n("Invalid number of arguments (expected 1) in option: %1", line)); } continue; } if (key_value[0] == KEY_DIRECTION_TAG) { if (key_value.count() == 2) { key_direction = key_value[1].toInt(); } if (key_direction != 0 && key_direction != 1) { KMessageBox::information(nullptr, i18n("Invalid argument in option: %1", line)); key_direction = -1; } continue; } if (key_value[0] == BEGIN_KEY_CA_TAG) { const QString caAbsolutePath = saveFile(in, QLatin1String(END_KEY_CA_TAG), connectionName, "ca.crt"); if (!caAbsolutePath.isEmpty()) { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_CA), caAbsolutePath); } continue; } else if (key_value[0] == BEGIN_KEY_CERT_TAG) { const QString certAbsolutePath = saveFile(in, QLatin1String(END_KEY_CERT_TAG), connectionName, "cert.crt"); if (!certAbsolutePath.isEmpty()) { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_CERT), certAbsolutePath); } continue; } else if (key_value[0] == BEGIN_KEY_KEY_TAG) { const QString keyAbsolutePath = saveFile(in, QLatin1String(END_KEY_KEY_TAG), connectionName, "private.key"); if (!keyAbsolutePath.isEmpty()) { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_KEY), keyAbsolutePath); } continue; } else if (key_value[0] == BEGIN_KEY_SECRET_TAG) { const QString secretAbsolutePath = saveFile(in, QLatin1String(END_KEY_SECRET_TAG), connectionName, "secret.key"); if (!secretAbsolutePath.isEmpty()) { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_KEY), secretAbsolutePath); have_sk = true; if (key_direction > -1) { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_STATIC_KEY_DIRECTION), QString().setNum(key_direction)); } } continue; } else if (key_value[0] == BEGIN_TLS_AUTH_TAG) { const QString tlsAuthAbsolutePath = saveFile(in, QLatin1String(END_TLS_AUTH_TAG), connectionName, "tls_auth.key"); if (!tlsAuthAbsolutePath.isEmpty()) { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_TA), tlsAuthAbsolutePath); if (key_direction > -1) { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_TA_DIR), QString().setNum(key_direction)); } } continue; } // Import X-NM-Routes if present if (key_value[0] == "X-NM-Routes") { QList list; for (int i = 1; i < key_value.count(); i++) { NetworkManager::IpRoute ipRoute; ipRoute.setIp(QHostAddress(key_value[1].split('/').first())); ipRoute.setPrefixLength(key_value[1].split('/').at(1).toInt()); list << ipRoute; } QList > dbusRoutes; - Q_FOREACH (const NetworkManager::IpRoute &route, list) { + for (const NetworkManager::IpRoute &route : list) { QList dbusRoute; dbusRoute << htonl(route.ip().toIPv4Address()) << route.prefixLength() << htonl(route.nextHop().toIPv4Address()) << route.metric(); dbusRoutes << dbusRoute; } ipv4Data.insert("routes", QVariant::fromValue(dbusRoutes)); continue; } } if (!have_client && !have_sk) { mError = VpnUiPlugin::Error; mErrorMessage = i18n("File %1 is not a valid OpenVPN's client configuration file", fileName); return result; } else if (!have_remote) { mError = VpnUiPlugin::Error; mErrorMessage = i18n("File %1 is not a valid OpenVPN configuration (no remote).", fileName); return result; } else { QString conType; bool have_certs = false; bool have_ca = false; if (dataMap.contains(NM_OPENVPN_KEY_CA)) { have_ca = true; } if (have_ca && dataMap.contains(NM_OPENVPN_KEY_CERT) && dataMap.contains(NM_OPENVPN_KEY_KEY)) { have_certs = true; } // Determine connection type if (have_pass) { if (have_certs) { conType = NM_OPENVPN_CONTYPE_PASSWORD_TLS; } else if (have_ca) { conType = NM_OPENVPN_CONTYPE_PASSWORD; } } else if (have_certs) { conType = NM_OPENVPN_CONTYPE_TLS; } else if (have_sk) { conType = NM_OPENVPN_CONTYPE_STATIC_KEY; } if (conType.isEmpty()) { conType = NM_OPENVPN_CONTYPE_TLS; } dataMap.insert(QLatin1String(NM_OPENVPN_KEY_CONNECTION_TYPE), conType); // Default secret flags to be agent-owned if (have_pass) { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_PASSWORD"-flags"), QString::number(NetworkManager::Setting::AgentOwned)); } if (have_certs) { if (dataMap.contains(NM_OPENVPN_KEY_KEY) && isEncrypted(dataMap[NM_OPENVPN_KEY_KEY])) { dataMap.insert(QLatin1String(NM_OPENVPN_KEY_CERTPASS"-flags"), QString::number(NetworkManager::Setting::AgentOwned)); } } } // Set the '...-type' and '...-flags' value also NetworkManager::VpnSetting setting; setting.setServiceType("org.freedesktop.NetworkManager.openvpn"); setting.setData(dataMap); setting.setSecrets(secretData); QVariantMap conn; conn.insert("id", connectionName); conn.insert("type", "vpn"); result.insert("connection", conn); result.insert("vpn", setting.toMap()); if (!ipv4Data.isEmpty()) { result.insert("ipv4", ipv4Data); } impFile.close(); return result; } QString OpenVpnUiPlugin::saveFile(QTextStream &in, const QString &endTag, const QString &connectionName, const QString &fileName) { const QString certificatesDirectory = localCertPath() + connectionName; const QString absoluteFilePath = certificatesDirectory + '/' + fileName; QFile outFile(absoluteFilePath); QDir().mkpath(certificatesDirectory); if (!outFile.open(QFile::WriteOnly | QFile::Text)) { KMessageBox::information(nullptr, i18n("Error saving file %1: %2", absoluteFilePath, outFile.errorString())); return QString(); } QTextStream out(&outFile); while (!in.atEnd()) { const QString line = in.readLine(); if (line.indexOf(endTag) >= 0) { break; } out << line << "\n"; } outFile.close(); return absoluteFilePath; } QString OpenVpnUiPlugin::tryToCopyToCertificatesDirectory(const QString &connectionName, const QString &sourceFilePath) { const QString certificatesDirectory = localCertPath(); const QString absoluteFilePath = certificatesDirectory + connectionName + '_' + QFileInfo(sourceFilePath).fileName(); QFile sourceFile(sourceFilePath); QDir().mkpath(certificatesDirectory); if (!sourceFile.copy(absoluteFilePath)) { KMessageBox::information(nullptr, i18n("Error copying certificate to %1: %2", absoluteFilePath, sourceFile.errorString())); return sourceFilePath; } return absoluteFilePath; } bool OpenVpnUiPlugin::exportConnectionSettings(const NetworkManager::ConnectionSettings::Ptr &connection, const QString &fileName) { QFile expFile(fileName); if (! expFile.open(QIODevice::WriteOnly | QIODevice::Text) ) { mError = VpnUiPlugin::Error; mErrorMessage = i18n("Could not open file for writing"); return false; } NMStringMap dataMap; NMStringMap secretData; NetworkManager::VpnSetting::Ptr vpnSetting = connection->setting(NetworkManager::Setting::Vpn).dynamicCast(); dataMap = vpnSetting->data(); secretData = vpnSetting->secrets(); QString line; QString cacert, user_cert, private_key; line = QString(CLIENT_TAG) + '\n'; expFile.write(line.toLatin1()); line = QString(REMOTE_TAG) + ' ' + dataMap[NM_OPENVPN_KEY_REMOTE] + (dataMap[NM_OPENVPN_KEY_PORT].isEmpty() ? "\n" : (' ' + dataMap[NM_OPENVPN_KEY_PORT]) + '\n'); expFile.write(line.toLatin1()); if (dataMap[NM_OPENVPN_KEY_CONNECTION_TYPE] == NM_OPENVPN_CONTYPE_TLS || dataMap[NM_OPENVPN_KEY_CONNECTION_TYPE] == NM_OPENVPN_CONTYPE_PASSWORD || dataMap[NM_OPENVPN_KEY_CONNECTION_TYPE] == NM_OPENVPN_CONTYPE_PASSWORD_TLS) { if (!dataMap[NM_OPENVPN_KEY_CA].isEmpty()) { cacert = dataMap[NM_OPENVPN_KEY_CA]; } } if (dataMap[NM_OPENVPN_KEY_CONNECTION_TYPE] == NM_OPENVPN_CONTYPE_TLS || dataMap[NM_OPENVPN_KEY_CONNECTION_TYPE] == NM_OPENVPN_CONTYPE_PASSWORD_TLS) { if (!dataMap[NM_OPENVPN_KEY_CERT].isEmpty()) { user_cert = dataMap[NM_OPENVPN_KEY_CERT]; } if (!dataMap[NM_OPENVPN_KEY_KEY].isEmpty()) { private_key = dataMap[NM_OPENVPN_KEY_KEY]; } } // Handle PKCS#12 (all certs are the same file) if (!cacert.isEmpty() && !user_cert.isEmpty() && !private_key.isEmpty() && cacert == user_cert && cacert == private_key) { line = QString("%1 \"%2\"\n").arg(PKCS12_TAG, cacert); expFile.write(line.toLatin1()); } else { if (!cacert.isEmpty()) { line = QString("%1 \"%2\"\n").arg(CA_TAG, cacert); expFile.write(line.toLatin1()); } if (!user_cert.isEmpty()) { line = QString("%1 \"%2\"\n").arg(CERT_TAG, user_cert); expFile.write(line.toLatin1()); } if (!private_key.isEmpty()) { line = QString("%1 \"%2\"\n").arg(KEY_TAG, private_key); expFile.write(line.toLatin1()); } } if (dataMap[NM_OPENVPN_KEY_CONNECTION_TYPE] == NM_OPENVPN_CONTYPE_TLS || dataMap[NM_OPENVPN_KEY_CONNECTION_TYPE] == NM_OPENVPN_CONTYPE_STATIC_KEY || dataMap[NM_OPENVPN_KEY_CONNECTION_TYPE] == NM_OPENVPN_CONTYPE_PASSWORD || dataMap[NM_OPENVPN_KEY_CONNECTION_TYPE] == NM_OPENVPN_CONTYPE_PASSWORD_TLS) { line = QString(AUTH_USER_PASS_TAG) + '\n'; expFile.write(line.toLatin1()); if (!dataMap[NM_OPENVPN_KEY_TLS_REMOTE].isEmpty()) { line = QString(TLS_REMOTE_TAG) + " \"" + dataMap[NM_OPENVPN_KEY_TLS_REMOTE] + "\"\n"; expFile.write(line.toLatin1()); } if (!dataMap[NM_OPENVPN_KEY_TA].isEmpty()) { line = QString(TLS_AUTH_TAG) + " \"" + dataMap[NM_OPENVPN_KEY_TA] + '\"' + (dataMap[NM_OPENVPN_KEY_TA_DIR].isEmpty() ? "\n" : (' ' + dataMap[NM_OPENVPN_KEY_TA_DIR]) + '\n'); expFile.write(line.toLatin1()); } } if (dataMap[NM_OPENVPN_KEY_CONNECTION_TYPE] == NM_OPENVPN_CONTYPE_STATIC_KEY) { line = QString(SECRET_TAG) + " \"" + dataMap[NM_OPENVPN_KEY_STATIC_KEY] + '\"' + (dataMap[NM_OPENVPN_KEY_STATIC_KEY_DIRECTION].isEmpty() ? "\n" : (' ' + dataMap[NM_OPENVPN_KEY_STATIC_KEY_DIRECTION]) + '\n'); expFile.write(line.toLatin1()); } if (dataMap.contains(NM_OPENVPN_KEY_RENEG_SECONDS) && !dataMap[NM_OPENVPN_KEY_RENEG_SECONDS].isEmpty()) { line = QString(RENEG_SEC_TAG) + ' ' + dataMap[NM_OPENVPN_KEY_RENEG_SECONDS] + '\n'; expFile.write(line.toLatin1()); } if (!dataMap[NM_OPENVPN_KEY_CIPHER].isEmpty()) { line = QString(CIPHER_TAG) + ' ' + dataMap[NM_OPENVPN_KEY_CIPHER] + '\n'; expFile.write(line.toLatin1()); } if (dataMap[NM_OPENVPN_KEY_COMP_LZO] == "yes") { line = QString(COMP_TAG) + " yes\n"; expFile.write(line.toLatin1()); } if (dataMap[NM_OPENVPN_KEY_MSSFIX] == "yes") { line = QString(MSSFIX_TAG) + '\n'; expFile.write(line.toLatin1()); } if (!dataMap[NM_OPENVPN_KEY_TUNNEL_MTU].isEmpty()) { line = QString(TUNMTU_TAG) + ' ' + dataMap[NM_OPENVPN_KEY_TUNNEL_MTU] + '\n'; expFile.write(line.toLatin1()); } if (!dataMap[NM_OPENVPN_KEY_FRAGMENT_SIZE].isEmpty()) { line = QString(FRAGMENT_TAG) + ' ' + dataMap[NM_OPENVPN_KEY_FRAGMENT_SIZE] + '\n'; expFile.write(line.toLatin1()); } line = QString(DEV_TAG) + (dataMap[NM_OPENVPN_KEY_TAP_DEV] == "yes" ? " tap\n" : " tun\n"); expFile.write(line.toLatin1()); line = QString(PROTO_TAG) + (dataMap[NM_OPENVPN_KEY_PROTO_TCP] == "yes" ? " tcp\n" : " udp\n"); expFile.write(line.toLatin1()); // Proxy stuff if (!dataMap[NM_OPENVPN_KEY_PROXY_TYPE].isEmpty()) { QString proxy_port = dataMap[NM_OPENVPN_KEY_PROXY_PORT]; if (dataMap[NM_OPENVPN_KEY_PROXY_TYPE] == "http" && !dataMap[NM_OPENVPN_KEY_PROXY_SERVER].isEmpty() && dataMap.contains(NM_OPENVPN_KEY_PROXY_PORT)) { if (proxy_port.toInt() == 0) { proxy_port = "8080"; } line = QString(HTTP_PROXY_TAG) + ' ' + dataMap[NM_OPENVPN_KEY_PROXY_SERVER] + ' ' + proxy_port + (dataMap[NM_OPENVPN_KEY_HTTP_PROXY_USERNAME].isEmpty() ? "\n" : (' ' + fileName + "-httpauthfile") + '\n'); expFile.write(line.toLatin1()); if (dataMap[NM_OPENVPN_KEY_PROXY_RETRY] == "yes") { line = QString(HTTP_PROXY_RETRY_TAG) + '\n'; expFile.write(line.toLatin1()); } // If there is a username, need to write an authfile if (!dataMap[NM_OPENVPN_KEY_HTTP_PROXY_USERNAME].isEmpty()) { QFile authFile(fileName + "-httpauthfile"); if (authFile.open(QFile::WriteOnly | QFile::Text)) { line = dataMap[NM_OPENVPN_KEY_HTTP_PROXY_USERNAME] + (dataMap[NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD].isEmpty()? "\n" : (dataMap[NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD] + '\n')); authFile.write(line.toLatin1()); authFile.close(); } } } else if (dataMap[NM_OPENVPN_KEY_PROXY_TYPE] == "socks" && !dataMap[NM_OPENVPN_KEY_PROXY_SERVER].isEmpty() && dataMap.contains(NM_OPENVPN_KEY_PROXY_PORT)) { if (proxy_port.toInt() == 0) { proxy_port = "1080"; } line = QString(SOCKS_PROXY_TAG) + dataMap[NM_OPENVPN_KEY_PROXY_SERVER] + ' ' + proxy_port + '\n'; expFile.write(line.toLatin1()); if (dataMap[NM_OPENVPN_KEY_PROXY_RETRY] == "yes") { line = QString(SOCKS_PROXY_RETRY_TAG) + '\n'; expFile.write(line.toLatin1()); } } } NetworkManager::Ipv4Setting::Ptr ipv4Setting = connection->setting(NetworkManager::Setting::Ipv4).dynamicCast(); // Export X-NM-Routes if (!ipv4Setting->routes().isEmpty()) { QString routes; - Q_FOREACH (const NetworkManager::IpRoute &route, ipv4Setting->routes()) { + for (const NetworkManager::IpRoute &route : ipv4Setting->routes()) { routes += route.ip().toString() % QLatin1Char('/') % QString::number(route.prefixLength()) % QLatin1Char(' '); } if (!routes.isEmpty()) { routes = "X-NM-Routes " + routes.trimmed(); expFile.write(routes.toLatin1() + '\n'); } } // Add hard-coded stuff expFile.write("nobind\n" "auth-nocache\n" "script-security 2\n" "persist-key\n" "persist-tun\n" "user nobody\n" "group nobody\n"); expFile.close(); return true; } #include "openvpn.moc" diff --git a/vpn/openvpn/openvpnadvancedwidget.cpp b/vpn/openvpn/openvpnadvancedwidget.cpp index 2f37e86c..64c1a62f 100644 --- a/vpn/openvpn/openvpnadvancedwidget.cpp +++ b/vpn/openvpn/openvpnadvancedwidget.cpp @@ -1,703 +1,703 @@ /* Copyright 2013 Lukas Tinkl Copyright 2015 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 "openvpnadvancedwidget.h" #include "ui_openvpnadvanced.h" #include "nm-openvpn-service.h" #include "settingwidget.h" #include #include #include #include #include #include class OpenVpnAdvancedWidget::Private { public: NetworkManager::VpnSetting::Ptr setting; KProcess *openvpnCipherProcess = nullptr; KProcess *openvpnVersionProcess = nullptr; QByteArray openvpnCiphers; QByteArray openVpnVersion; bool gotOpenVpnCiphers = false; bool gotOpenVpnVersion = false; bool readConfig = false; int versionX = 0; int versionY = 0; int versionZ = 0; class EnumProxyType { public: enum ProxyType {NotRequired = 0, HTTP = 1, SOCKS = 2}; }; class EnumHashingAlgorithms { public: enum HashingAlgorithms {Default = 0, None, Md4, Md5, Sha1, Sha224, Sha256, Sha384, Sha512, Ripemd160}; }; }; OpenVpnAdvancedWidget::OpenVpnAdvancedWidget(const NetworkManager::VpnSetting::Ptr &setting, QWidget *parent) : QDialog(parent) , m_ui(new Ui::OpenVpnAdvancedWidget) , d(new Private) { m_ui->setupUi(this); setWindowTitle(i18nc("@title: window advanced openvpn properties", "Advanced OpenVPN properties")); d->setting = setting; m_ui->proxyPassword->setPasswordOptionsEnabled(true); m_ui->proxyPassword->setPasswordNotRequiredEnabled(true); connect(m_ui->cbCertCheck, QOverload::of(&QComboBox::currentIndexChanged), this, &OpenVpnAdvancedWidget::certCheckTypeChanged); connect(m_ui->cmbProxyType, QOverload::of(&QComboBox::currentIndexChanged), this, &OpenVpnAdvancedWidget::proxyTypeChanged); connect(m_ui->cboTLSMode, QOverload::of(&QComboBox::currentIndexChanged), this, [this] (int index) { if (index == 0) { m_ui->kurlTlsAuthKey->setDisabled(true); m_ui->cboDirection->setDisabled(true); } else if (index == 1) { // TLS-Auth m_ui->kurlTlsAuthKey->setEnabled(true); m_ui->cboDirection->setEnabled(true); } else { // TLS-Crypt m_ui->kurlTlsAuthKey->setEnabled(true); m_ui->cboDirection->setDisabled(true); } }); // start openVPN process and get its cipher list const QString openVpnBinary = QStandardPaths::findExecutable("openvpn", QStringList() << "/sbin" << "/usr/sbin"); const QStringList ciphersArgs(QLatin1String("--show-ciphers")); const QStringList versionArgs(QLatin1String("--version")); d->openvpnCipherProcess = new KProcess(this); d->openvpnCipherProcess->setOutputChannelMode(KProcess::OnlyStdoutChannel); d->openvpnCipherProcess->setReadChannel(QProcess::StandardOutput); connect(d->openvpnCipherProcess, QOverload::of(&KProcess::error), this, &OpenVpnAdvancedWidget::openVpnCipherError); connect(d->openvpnCipherProcess, &KProcess::readyReadStandardOutput, this, &OpenVpnAdvancedWidget::gotOpenVpnCipherOutput); connect(d->openvpnCipherProcess, QOverload::of(&KProcess::finished), this, &OpenVpnAdvancedWidget::openVpnCipherFinished); d->openvpnCipherProcess->setProgram(openVpnBinary, ciphersArgs); d->openvpnVersionProcess = new KProcess(this); d->openvpnVersionProcess->setOutputChannelMode(KProcess::OnlyStdoutChannel); d->openvpnVersionProcess->setReadChannel(QProcess::StandardOutput); connect(d->openvpnVersionProcess, QOverload::of(&KProcess::error), this, &OpenVpnAdvancedWidget::openVpnVersionError); connect(d->openvpnVersionProcess, &KProcess::readyReadStandardOutput, this, &OpenVpnAdvancedWidget::gotOpenVpnVersionOutput); connect(d->openvpnVersionProcess, QOverload::of(&KProcess::finished), this, &OpenVpnAdvancedWidget::openVpnVersionFinished); d->openvpnVersionProcess->setProgram(openVpnBinary, versionArgs); connect(m_ui->buttonBox, &QDialogButtonBox::accepted, this, &OpenVpnAdvancedWidget::accept); connect(m_ui->buttonBox, &QDialogButtonBox::rejected, this, &OpenVpnAdvancedWidget::reject); KAcceleratorManager::manage(this); if (d->setting) { loadConfig(); } } OpenVpnAdvancedWidget::~OpenVpnAdvancedWidget() { delete d; } void OpenVpnAdvancedWidget::init() { d->openvpnCipherProcess->start(); d->openvpnVersionProcess->start(); } void OpenVpnAdvancedWidget::gotOpenVpnCipherOutput() { d->openvpnCiphers.append(d->openvpnCipherProcess->readAll()); } void OpenVpnAdvancedWidget::openVpnCipherError(QProcess::ProcessError) { m_ui->cboCipher->removeItem(0); m_ui->cboCipher->addItem(i18nc("@item:inlistbox Item added when OpenVPN cipher lookup failed", "OpenVPN cipher lookup failed")); } void OpenVpnAdvancedWidget::openVpnCipherFinished(int exitCode, QProcess::ExitStatus exitStatus) { m_ui->cboCipher->removeItem(0); if (!exitCode && exitStatus == QProcess::NormalExit) { m_ui->cboCipher->addItem(i18nc("@item::inlist Default openvpn cipher item", "Default")); const QList rawOutputLines = d->openvpnCiphers.split('\n'); bool foundFirstSpace = false; - Q_FOREACH (const QByteArray &cipher, rawOutputLines) { + for (const QByteArray &cipher : rawOutputLines) { if (cipher.length() == 0) { foundFirstSpace = true; } else if (foundFirstSpace) { m_ui->cboCipher->addItem(QString::fromLocal8Bit(cipher.left(cipher.indexOf(' ')))); } } if (m_ui->cboCipher->count()) { m_ui->cboCipher->setEnabled(true); } else { m_ui->cboCipher->addItem(i18nc("@item:inlistbox Item added when OpenVPN cipher lookup failed", "No OpenVPN ciphers found")); } } else { m_ui->cboCipher->addItem(i18nc("@item:inlistbox Item added when OpenVPN cipher lookup failed", "OpenVPN cipher lookup failed")); } delete d->openvpnCipherProcess; d->openvpnCipherProcess = nullptr; d->openvpnCiphers = QByteArray(); d->gotOpenVpnCiphers = true; if (d->readConfig) { const NMStringMap dataMap = d->setting->data(); if (dataMap.contains(NM_OPENVPN_KEY_CIPHER)) { m_ui->cboCipher->setCurrentIndex(m_ui->cboCipher->findText(dataMap.value(NM_OPENVPN_KEY_CIPHER))); } } } void OpenVpnAdvancedWidget::gotOpenVpnVersionOutput() { d->openVpnVersion.append(d->openvpnVersionProcess->readAll()); } void OpenVpnAdvancedWidget::openVpnVersionError(QProcess::ProcessError) { // We couldn't identify OpenVPN version so disable tls-remote disableLegacySubjectMatch(); } void OpenVpnAdvancedWidget::openVpnVersionFinished(int exitCode, QProcess::ExitStatus exitStatus) { // OpenVPN returns 1 when you use "--help" and unfortunately returns 1 even when some error occurs if (exitCode == 1 && exitStatus == QProcess::NormalExit) { QStringList list = QString(d->openVpnVersion).split(QLatin1Char(' ')); if (list.count() > 2) { const QStringList versionList = list.at(1).split(QLatin1Char('.')); if (versionList.count() == 3) { d->versionX = versionList.at(0).toInt(); d->versionY = versionList.at(1).toInt(); d->versionZ = versionList.at(2).toInt(); if (compareVersion(2, 4, 0) >= 0) { disableLegacySubjectMatch(); } } } } else { disableLegacySubjectMatch(); } delete d->openvpnVersionProcess; d->openvpnVersionProcess = nullptr; d->openVpnVersion = QByteArray(); d->gotOpenVpnVersion = true; if (d->readConfig) { const NMStringMap dataMap = d->setting->data(); if (dataMap.contains(NM_OPENVPN_KEY_TLS_REMOTE)) { m_ui->subjectMatch->setText(dataMap.value(NM_OPENVPN_KEY_TLS_REMOTE)); } } } int OpenVpnAdvancedWidget::compareVersion(const int x, const int y, const int z) const { if (d->versionX == 0) { // Not valid version return -2; } if (d->versionX > x) { return 1; } else if (d->versionX < x) { return -1; } else if (d->versionY > y) { return 1; } else if (d->versionY < y) { return -1; } else if (d->versionZ > z) { return 1; } else if (d->versionZ < z) { return -1; } return 0; } void OpenVpnAdvancedWidget::disableLegacySubjectMatch() { m_ui->cbCertCheck->removeItem(CertCheckType::VerifySubjectPartially); } void OpenVpnAdvancedWidget::loadConfig() { const NMStringMap dataMap = d->setting->data(); const NMStringMap secrets = d->setting->secrets(); // Optional Settings if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_PORT))) { m_ui->chkCustomPort->setChecked(true); m_ui->sbCustomPort->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_PORT)].toUInt()); } else { m_ui->chkCustomPort->setChecked(false); m_ui->sbCustomPort->setValue(1194); // Default value } if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_TUNNEL_MTU))) { m_ui->chkMtu->setChecked(true); m_ui->sbMtu->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_TUNNEL_MTU)].toUInt()); } else { m_ui->chkMtu->setChecked(false); m_ui->sbMtu->setValue(1500); // Default value } if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_FRAGMENT_SIZE))) { m_ui->chkCustomFragmentSize->setChecked(true); m_ui->sbCustomFragmentSize->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_FRAGMENT_SIZE)].toUInt()); } else { m_ui->chkCustomFragmentSize->setChecked(false); m_ui->sbCustomFragmentSize->setValue(1300); } if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_RENEG_SECONDS))) { m_ui->chkUseCustomReneg->setChecked(true); m_ui->sbCustomReneg->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_RENEG_SECONDS)].toUInt()); } else { m_ui->chkUseCustomReneg->setChecked(false); m_ui->sbCustomReneg->setValue(0); } if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_COMP_LZO))) { const QString compLzo = dataMap[QLatin1String(NM_OPENVPN_KEY_COMP_LZO)]; if (compLzo == QLatin1String("no-by-default")) { m_ui->cmbUseLZO->setCurrentIndex(0); } else if (compLzo == QLatin1String("yes")) { m_ui->cmbUseLZO->setCurrentIndex(1); } else { m_ui->cmbUseLZO->setCurrentIndex(2); } m_ui->chkUseLZO->setChecked(true); } m_ui->chkUseTCP->setChecked(dataMap[QLatin1String(NM_OPENVPN_KEY_PROTO_TCP)] == QLatin1String("yes")); if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_DEV_TYPE))) { m_ui->chkUseVirtualDeviceType->setChecked(true); if (dataMap[QLatin1String(NM_OPENVPN_KEY_DEV_TYPE)] == QLatin1String("tap")) { m_ui->cmbDeviceType->setCurrentIndex(1); } } if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_DEV))) { m_ui->chkUseVirtualDeviceName->setChecked(true); m_ui->leVirtualDeviceName->setText(dataMap[QLatin1String(NM_OPENVPN_KEY_DEV)]); } m_ui->chkMssRestrict->setChecked(dataMap[QLatin1String(NM_OPENVPN_KEY_MSSFIX)] == QLatin1String("yes")); m_ui->chkRandRemHosts->setChecked(dataMap[QLatin1String(NM_OPENVPN_KEY_REMOTE_RANDOM)] == QLatin1String("yes")); m_ui->chkIpv6TunLink->setChecked(dataMap[QLatin1String(NM_OPENVPN_KEY_TUN_IPV6)] == QLatin1String("yes")); if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_PING))) { m_ui->chkPingInterval->setChecked(true); m_ui->sbPingInterval->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_PING)].toInt()); } if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_PING_EXIT)) || dataMap.contains(QLatin1String(NM_OPENVPN_KEY_PING_RESTART))) { m_ui->chkSpecifyExitRestartPing->setChecked(true); if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_PING_EXIT))) { m_ui->cbSpecifyExitRestartPing->setCurrentIndex(0); // Exit m_ui->sbSpecifyExitRestartPing->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_PING_EXIT)].toInt()); } else { m_ui->cbSpecifyExitRestartPing->setCurrentIndex(1); // Restart m_ui->sbSpecifyExitRestartPing->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_PING_RESTART)].toInt()); } } m_ui->chkAcceptAuthenticatedPackets->setChecked(dataMap[QLatin1String(NM_OPENVPN_KEY_FLOAT)] == QLatin1String("yes")); if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_MAX_ROUTES))) { m_ui->chkMaxRoutes->setChecked(true); m_ui->sbMaxRoutes->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_MAX_ROUTES)].toInt()); } // Optional Security Settings const QString hmacKeyAuth = dataMap[QLatin1String(NM_OPENVPN_KEY_AUTH)]; if (hmacKeyAuth == QLatin1String(NM_OPENVPN_AUTH_NONE)) { m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::None); } else if (hmacKeyAuth == QLatin1String(NM_OPENVPN_AUTH_RSA_MD4)) { m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::Md4); } else if (hmacKeyAuth == QLatin1String(NM_OPENVPN_AUTH_MD5)) { m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::Md5); } else if (hmacKeyAuth == QLatin1String(NM_OPENVPN_AUTH_SHA1)) { m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::Sha1); } else if (hmacKeyAuth == QLatin1String(NM_OPENVPN_AUTH_SHA224)) { m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::Sha224); } else if (hmacKeyAuth == QLatin1String(NM_OPENVPN_AUTH_SHA256)) { m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::Sha256); } else if (hmacKeyAuth == QLatin1String(NM_OPENVPN_AUTH_SHA384)) { m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::Sha384); } else if (hmacKeyAuth == QLatin1String(NM_OPENVPN_AUTH_SHA512)) { m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::Sha512); } else if (hmacKeyAuth == QLatin1String(NM_OPENVPN_AUTH_RIPEMD160)) { m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::Ripemd160); } else { m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::Default); } if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_KEYSIZE))) { m_ui->chkUseCustomCipherKey->setChecked(true); m_ui->sbCustomCipherKey->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_KEYSIZE)].toUInt()); } // ciphers populated above? if (d->gotOpenVpnCiphers && dataMap.contains(QLatin1String(NM_OPENVPN_KEY_CIPHER))) { m_ui->cboCipher->setCurrentIndex(m_ui->cboCipher->findText(dataMap[QLatin1String(NM_OPENVPN_KEY_CIPHER)])); } // Optional TLS if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_TLS_REMOTE))) { m_ui->cbCertCheck->setCurrentIndex(CertCheckType::VerifySubjectPartially); m_ui->subjectMatch->setText(dataMap[QLatin1String(NM_OPENVPN_KEY_TLS_REMOTE)]); } if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_VERIFY_X509_NAME))) { const QString x509Value = dataMap.value(QLatin1String(NM_OPENVPN_KEY_VERIFY_X509_NAME)); const QStringList x509List = x509Value.split(QLatin1Char(':')); if (x509List.size() == 2) { if (x509List.at(0) == QLatin1String(NM_OPENVPN_VERIFY_X509_NAME_TYPE_SUBJECT)) { m_ui->cbCertCheck->setCurrentIndex(CertCheckType::VerifyWholeSubjectExactly); } else if (x509List.at(0) == QLatin1String(NM_OPENVPN_VERIFY_X509_NAME_TYPE_NAME)) { m_ui->cbCertCheck->setCurrentIndex(CertCheckType::VerifyNameExactly); } else if (x509List.at(0) == QLatin1String(NM_OPENVPN_VERIFY_X509_NAME_TYPE_NAME_PREFIX)) { m_ui->cbCertCheck->setCurrentIndex(CertCheckType::VerifyNameByPrefix); } m_ui->subjectMatch->setText(x509List.at(1)); } } else { m_ui->cbCertCheck->setCurrentIndex(CertCheckType::DontVerify); } if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_REMOTE_CERT_TLS))) { const QString remoteCertTls = dataMap[QLatin1String(NM_OPENVPN_KEY_REMOTE_CERT_TLS)]; m_ui->chkRemoteCertTls->setChecked(true); m_ui->labelRemoteCertTls->setEnabled(true); m_ui->cmbRemoteCertTls->setEnabled(true); m_ui->cmbRemoteCertTls->setCurrentIndex(remoteCertTls == QLatin1String(NM_OPENVPN_REM_CERT_TLS_SERVER) ? 0 : 1); } if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_NS_CERT_TYPE))) { const QString remoteCertTls = dataMap[QLatin1String(NM_OPENVPN_KEY_NS_CERT_TYPE)]; m_ui->chkNsCertType->setChecked(true); m_ui->lblNsCertType->setEnabled(true); m_ui->cmbNsCertType->setEnabled(true); m_ui->cmbNsCertType->setCurrentIndex(remoteCertTls == QLatin1String(NM_OPENVPN_NS_CERT_TYPE_SERVER) ? 0 : 1); } const QString openvpnKeyTa = dataMap[QLatin1String(NM_OPENVPN_KEY_TA)]; const QString openvpnKeyTlsCrypt = dataMap[QLatin1String(NM_OPENVPN_KEY_TLS_CRYPT)]; if (!openvpnKeyTlsCrypt.isEmpty()) { m_ui->cboTLSMode->setCurrentIndex(2); // TLS-Crypt m_ui->kurlTlsAuthKey->setUrl(QUrl::fromLocalFile(openvpnKeyTlsCrypt)); } else if (!openvpnKeyTa.isEmpty()) { m_ui->cboTLSMode->setCurrentIndex(1); // TLS-Auth m_ui->kurlTlsAuthKey->setUrl(QUrl::fromLocalFile(openvpnKeyTa)); if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_TA_DIR))) { const uint tlsAuthDirection = dataMap[QLatin1String(NM_OPENVPN_KEY_TA_DIR)].toUInt(); m_ui->cboDirection->setCurrentIndex(tlsAuthDirection + 1); } } // Proxies if (dataMap[QLatin1String(NM_OPENVPN_KEY_PROXY_TYPE)] == QLatin1String("http")) { m_ui->cmbProxyType->setCurrentIndex(Private::EnumProxyType::HTTP); } else if (dataMap[QLatin1String(NM_OPENVPN_KEY_PROXY_TYPE)] == QLatin1String("socks")) { m_ui->cmbProxyType->setCurrentIndex(Private::EnumProxyType::SOCKS); } else { m_ui->cmbProxyType->setCurrentIndex(Private::EnumProxyType::NotRequired); } proxyTypeChanged(m_ui->cmbProxyType->currentIndex()); m_ui->proxyServerAddress->setText(dataMap[QLatin1String(NM_OPENVPN_KEY_PROXY_SERVER)]); if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_PROXY_PORT))) { m_ui->sbProxyPort->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_PROXY_PORT)].toUInt()); } else { m_ui->sbProxyPort->setValue(0); } m_ui->chkProxyRetry->setChecked(dataMap[QLatin1String(NM_OPENVPN_KEY_PROXY_RETRY)] == QLatin1String("yes")); m_ui->proxyUsername->setText(dataMap[QLatin1String(NM_OPENVPN_KEY_HTTP_PROXY_USERNAME)]); d->readConfig = true; NetworkManager::Setting::SecretFlags type; type = (NetworkManager::Setting::SecretFlags)dataMap[NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD"-flags"].toInt(); if (!(type & NetworkManager::Setting::NotSaved || type & NetworkManager::Setting::NotRequired)) { m_ui->proxyPassword->setText(secrets.value(QLatin1String(NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD))); } fillOnePasswordCombo(m_ui->proxyPassword, type); } void OpenVpnAdvancedWidget::fillOnePasswordCombo(PasswordField *passwordField, NetworkManager::Setting::SecretFlags type) { if (type.testFlag(NetworkManager::Setting::None)) { passwordField->setPasswordOption(PasswordField::StoreForAllUsers); } else if (type.testFlag(NetworkManager::Setting::AgentOwned)) { passwordField->setPasswordOption(PasswordField::StoreForUser); } else if (type.testFlag(NetworkManager::Setting::NotSaved)) { passwordField->setPasswordOption(PasswordField::AlwaysAsk); } else { passwordField->setPasswordOption(PasswordField::PasswordField::NotRequired); } } NetworkManager::VpnSetting::Ptr OpenVpnAdvancedWidget::setting() const { NMStringMap data; NMStringMap secretData; // optional settings if (m_ui->chkCustomPort->isChecked()) { data.insert(QLatin1String(NM_OPENVPN_KEY_PORT), QString::number(m_ui->sbCustomPort->value())); } if (m_ui->chkMtu->isChecked()) { data.insert(QLatin1String(NM_OPENVPN_KEY_TUNNEL_MTU), QString::number(m_ui->sbMtu->value())); } if (m_ui->chkCustomFragmentSize->isChecked() ) { data.insert(QLatin1String(NM_OPENVPN_KEY_FRAGMENT_SIZE), QString::number(m_ui->sbCustomFragmentSize->value())); } if (m_ui->chkUseCustomReneg->isChecked()) { data.insert(QLatin1String(NM_OPENVPN_KEY_RENEG_SECONDS), QString::number(m_ui->sbCustomReneg->value())); } data.insert(QLatin1String(NM_OPENVPN_KEY_PROTO_TCP), m_ui->chkUseTCP->isChecked() ? QLatin1String("yes") : QLatin1String("no")); if (m_ui->chkUseLZO->isChecked()) { switch (m_ui->cmbUseLZO->currentIndex()) { case 0: data.insert(QLatin1String(NM_OPENVPN_KEY_COMP_LZO), QLatin1String("no-by-default")); break; case 1: data.insert(QLatin1String(NM_OPENVPN_KEY_COMP_LZO), QLatin1String("yes")); break; case 2: data.insert(QLatin1String(NM_OPENVPN_KEY_COMP_LZO), QLatin1String("adaptive")); break; } } if (m_ui->chkUseVirtualDeviceType->isChecked()) { data.insert(QLatin1String(NM_OPENVPN_KEY_DEV_TYPE), m_ui->cmbDeviceType->currentIndex() == 0 ? QLatin1String("tun") : QLatin1String("tap")); } if (m_ui->chkUseVirtualDeviceName->isChecked()) { data.insert(QLatin1String(NM_OPENVPN_KEY_DEV), m_ui->leVirtualDeviceName->text()); } data.insert(QLatin1String(NM_OPENVPN_KEY_MSSFIX), m_ui->chkMssRestrict->isChecked() ? QLatin1String("yes") : QLatin1String("no")); data.insert(QLatin1String(NM_OPENVPN_KEY_REMOTE_RANDOM), m_ui->chkRandRemHosts->isChecked() ? QLatin1String("yes") : QLatin1String("no")); data.insert(QLatin1String(NM_OPENVPN_KEY_TUN_IPV6), m_ui->chkIpv6TunLink->isChecked() ? QLatin1String("yes") : QLatin1String("no")); if (m_ui->chkPingInterval->isChecked()) { data.insert(QLatin1String(NM_OPENVPN_KEY_PING), QString::number(m_ui->sbPingInterval->value())); } if (m_ui->chkSpecifyExitRestartPing->isChecked()) { if (m_ui->cbSpecifyExitRestartPing->currentIndex() == 0) { // Exit data.insert(QLatin1String(NM_OPENVPN_KEY_PING_EXIT), QString::number(m_ui->sbSpecifyExitRestartPing->value())); } else { // Restart data.insert(QLatin1String(NM_OPENVPN_KEY_PING_RESTART), QString::number(m_ui->sbSpecifyExitRestartPing->value())); } } data.insert(QLatin1String(NM_OPENVPN_KEY_FLOAT), m_ui->chkAcceptAuthenticatedPackets->isChecked() ? QLatin1String("yes") : QLatin1String("no")); if (m_ui->chkMaxRoutes->isChecked()) { data.insert(QLatin1String(NM_OPENVPN_KEY_MAX_ROUTES), QString::number(m_ui->sbMaxRoutes->value())); } // Optional Security switch (m_ui->cboHmac->currentIndex()) { case Private::EnumHashingAlgorithms::Default: break; case Private::EnumHashingAlgorithms::None: data.insert(QLatin1String(NM_OPENVPN_KEY_AUTH), QLatin1String(NM_OPENVPN_AUTH_NONE)); break; case Private::EnumHashingAlgorithms::Md4: data.insert(QLatin1String(NM_OPENVPN_KEY_AUTH), QLatin1String(NM_OPENVPN_AUTH_RSA_MD4)); break; case Private::EnumHashingAlgorithms::Md5: data.insert(QLatin1String(NM_OPENVPN_KEY_AUTH), QLatin1String(NM_OPENVPN_AUTH_MD5)); break; case Private::EnumHashingAlgorithms::Sha1: data.insert(QLatin1String(NM_OPENVPN_KEY_AUTH), QLatin1String(NM_OPENVPN_AUTH_SHA1)); break; case Private::EnumHashingAlgorithms::Sha224: data.insert(QLatin1String(NM_OPENVPN_KEY_AUTH), QLatin1String(NM_OPENVPN_AUTH_SHA224)); break; case Private::EnumHashingAlgorithms::Sha256: data.insert(QLatin1String(NM_OPENVPN_KEY_AUTH), QLatin1String(NM_OPENVPN_AUTH_SHA256)); break; case Private::EnumHashingAlgorithms::Sha384: data.insert(QLatin1String(NM_OPENVPN_KEY_AUTH), QLatin1String(NM_OPENVPN_AUTH_SHA384)); break; case Private::EnumHashingAlgorithms::Sha512: data.insert(QLatin1String(NM_OPENVPN_KEY_AUTH), QLatin1String(NM_OPENVPN_AUTH_SHA512)); break; case Private::EnumHashingAlgorithms::Ripemd160: data.insert(QLatin1String(NM_OPENVPN_KEY_AUTH), QLatin1String(NM_OPENVPN_AUTH_RIPEMD160)); break; } if (m_ui->chkUseCustomCipherKey->isChecked()) { data.insert(QLatin1String(NM_OPENVPN_KEY_KEYSIZE), QString::number(m_ui->sbCustomCipherKey->value())); } if (m_ui->cboCipher->currentIndex() != 0) { data.insert(QLatin1String(NM_OPENVPN_KEY_CIPHER), m_ui->cboCipher->currentText()); } // optional tls authentication switch (m_ui->cbCertCheck->currentIndex()) { case CertCheckType::DontVerify: break; case CertCheckType::VerifyWholeSubjectExactly: data.insert(QLatin1String(NM_OPENVPN_KEY_VERIFY_X509_NAME), QStringLiteral("%1:%2").arg(NM_OPENVPN_VERIFY_X509_NAME_TYPE_SUBJECT).arg(m_ui->subjectMatch->text())); break; case CertCheckType::VerifyNameExactly: data.insert(QLatin1String(NM_OPENVPN_KEY_VERIFY_X509_NAME), QStringLiteral("%1:%2").arg(NM_OPENVPN_VERIFY_X509_NAME_TYPE_NAME).arg(m_ui->subjectMatch->text())); break; case CertCheckType::VerifyNameByPrefix: data.insert(QLatin1String(NM_OPENVPN_KEY_VERIFY_X509_NAME), QStringLiteral("%1:%2").arg(NM_OPENVPN_VERIFY_X509_NAME_TYPE_NAME_PREFIX).arg(m_ui->subjectMatch->text())); break; case CertCheckType::VerifySubjectPartially: data.insert(QLatin1String(NM_OPENVPN_KEY_TLS_REMOTE), m_ui->subjectMatch->text()); break; } if (m_ui->chkRemoteCertTls->isChecked()) { if (m_ui->cmbRemoteCertTls->currentIndex() == 0) { data.insert(QLatin1String(NM_OPENVPN_KEY_REMOTE_CERT_TLS), NM_OPENVPN_REM_CERT_TLS_SERVER); } else { data.insert(QLatin1String(NM_OPENVPN_KEY_REMOTE_CERT_TLS), NM_OPENVPN_REM_CERT_TLS_CLIENT); } } if (m_ui->chkNsCertType->isChecked()) { if (m_ui->cmbNsCertType->currentIndex() == 0) { data.insert(QLatin1String(NM_OPENVPN_KEY_NS_CERT_TYPE), NM_OPENVPN_NS_CERT_TYPE_SERVER); } else { data.insert(QLatin1String(NM_OPENVPN_KEY_NS_CERT_TYPE), NM_OPENVPN_NS_CERT_TYPE_CLIENT); } } if (m_ui->cboTLSMode->currentIndex() == 1) { // TLS-Auth QUrl tlsAuthKeyUrl = m_ui->kurlTlsAuthKey->url(); if (!tlsAuthKeyUrl.isEmpty()) { data.insert(QLatin1String(NM_OPENVPN_KEY_TA), tlsAuthKeyUrl.path()); } if (m_ui->cboDirection->currentIndex() > 0) { data.insert(QLatin1String(NM_OPENVPN_KEY_TA_DIR), QString::number(m_ui->cboDirection->currentIndex() - 1)); } } else if (m_ui->cboTLSMode->currentIndex() == 2) { // TLS-Crypt QUrl tlsCryptKeyUrl = m_ui->kurlTlsAuthKey->url(); if (!tlsCryptKeyUrl.isEmpty()) { data.insert(QLatin1String(NM_OPENVPN_KEY_TLS_CRYPT), tlsCryptKeyUrl.path()); } } // Proxies switch (m_ui->cmbProxyType->currentIndex()) { case Private::EnumProxyType::NotRequired: break; case Private::EnumProxyType::HTTP: data.insert(QLatin1String(NM_OPENVPN_KEY_PROXY_TYPE), QLatin1String("http")); data.insert(QLatin1String(NM_OPENVPN_KEY_PROXY_SERVER), m_ui->proxyServerAddress->text()); data.insert(QLatin1String(NM_OPENVPN_KEY_PROXY_PORT), QString::number(m_ui->sbProxyPort->value())); data.insert(QLatin1String(NM_OPENVPN_KEY_PROXY_RETRY), m_ui->chkProxyRetry->isChecked() ? QLatin1String("yes") : QLatin1String("no")); if (!m_ui->proxyUsername->text().isEmpty()) { data.insert(QLatin1String(NM_OPENVPN_KEY_HTTP_PROXY_USERNAME), m_ui->proxyUsername->text()); secretData.insert(QLatin1String(NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD), m_ui->proxyPassword->text()); handleOnePasswordType(m_ui->proxyPassword, QLatin1String(NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD"-flags"), data); } break; case Private::EnumProxyType::SOCKS: data.insert(QLatin1String(NM_OPENVPN_KEY_PROXY_TYPE), QLatin1String("socks")); data.insert(QLatin1String(NM_OPENVPN_KEY_PROXY_SERVER), m_ui->proxyServerAddress->text()); data.insert(QLatin1String(NM_OPENVPN_KEY_PROXY_PORT), QString::number(m_ui->sbProxyPort->value())); data.insert(QLatin1String(NM_OPENVPN_KEY_PROXY_RETRY), m_ui->chkProxyRetry->isChecked() ? QLatin1String("yes") : QLatin1String("no")); break; } d->setting->setData(data); d->setting->setSecrets(secretData); return d->setting; } void OpenVpnAdvancedWidget::certCheckTypeChanged(int type) { if (type == CertCheckType::DontVerify) { m_ui->lbSubjectMatch->setEnabled(false); m_ui->subjectMatch->setEnabled(false); } else { m_ui->lbSubjectMatch->setEnabled(true); m_ui->subjectMatch->setEnabled(true); } } void OpenVpnAdvancedWidget::proxyTypeChanged(int type) { switch (type) { case Private::EnumProxyType::NotRequired: m_ui->proxyServerAddress->setEnabled(false); m_ui->sbProxyPort->setEnabled(false); m_ui->chkProxyRetry->setEnabled(false); m_ui->proxyUsername->setEnabled(false); m_ui->proxyPassword->setEnabled(false); break; case Private::EnumProxyType::HTTP: m_ui->proxyServerAddress->setEnabled(true); m_ui->sbProxyPort->setEnabled(true); m_ui->chkProxyRetry->setEnabled(true); m_ui->proxyUsername->setEnabled(true); m_ui->proxyPassword->setEnabled(true); break; case Private::EnumProxyType::SOCKS: m_ui->proxyServerAddress->setEnabled(true); m_ui->sbProxyPort->setEnabled(true); m_ui->chkProxyRetry->setEnabled(true); m_ui->proxyUsername->setEnabled(false); m_ui->proxyPassword->setEnabled(false); break; } } void OpenVpnAdvancedWidget::handleOnePasswordType(const PasswordField *passwordField, const QString & key, NMStringMap & data) const { const PasswordField::PasswordOption option = passwordField->passwordOption(); switch (option) { case PasswordField::StoreForAllUsers: data.insert(key, QString::number(NetworkManager::Setting::None)); break; case PasswordField::StoreForUser: data.insert(key, QString::number(NetworkManager::Setting::AgentOwned)); break; case PasswordField::AlwaysAsk: data.insert(key, QString::number(NetworkManager::Setting::NotSaved)); break; case PasswordField::NotRequired: data.insert(key, QString::number(NetworkManager::Setting::NotRequired)); break; } } diff --git a/vpn/openvpn/openvpnwidget.cpp b/vpn/openvpn/openvpnwidget.cpp index 1b666899..7bdcd7af 100644 --- a/vpn/openvpn/openvpnwidget.cpp +++ b/vpn/openvpn/openvpnwidget.cpp @@ -1,354 +1,354 @@ /* Copyright 2008 Will Stephenson Copyright 2013 Lukáš Tinkl This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License or (at your option) version 3 or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of version 3 of the license. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "debug.h" #include "openvpnwidget.h" #include "openvpnadvancedwidget.h" #include #include #include #include #include #include #include #include "nm-openvpn-service.h" class OpenVpnSettingWidget::Private { public: Ui_OpenVPNProp ui; NetworkManager::VpnSetting::Ptr setting; class EnumConnectionType { public: enum ConnectionType {Certificates = 0, Psk, Password, CertsPassword}; }; class EnumKeyDirection { public: enum KeyDirection {None = 0, D0, D1}; }; }; OpenVpnSettingWidget::OpenVpnSettingWidget(const NetworkManager::VpnSetting::Ptr &setting, QWidget *parent) : SettingWidget(setting, parent) , d(new Private) { qDBusRegisterMetaType(); d->ui.setupUi(this); d->setting = setting; d->ui.x509KeyPassword->setPasswordOptionsEnabled(true); d->ui.x509KeyPassword->setPasswordNotRequiredEnabled(true); d->ui.passPassword->setPasswordOptionsEnabled(true); d->ui.passPassword->setPasswordNotRequiredEnabled(true); d->ui.x509PassKeyPassword->setPasswordOptionsEnabled(true); d->ui.x509PassKeyPassword->setPasswordNotRequiredEnabled(true); d->ui.x509PassPassword->setPasswordOptionsEnabled(true); d->ui.x509PassPassword->setPasswordNotRequiredEnabled(true); // use requesters' urlSelected signals to set other requester's startDirs to save clicking // around the filesystem QList requesters; requesters << d->ui.x509CaFile << d->ui.x509Cert << d->ui.x509Key << d->ui.pskSharedKey << d->ui.passCaFile << d->ui.x509PassCaFile << d->ui.x509PassCert << d->ui.x509PassKey; - Q_FOREACH (const KUrlRequester * requester, requesters) { + for (const KUrlRequester *requester : requesters) { connect(requester, &KUrlRequester::urlSelected, this, &OpenVpnSettingWidget::updateStartDir); } connect(d->ui.btnAdvanced, &QPushButton::clicked, this, &OpenVpnSettingWidget::showAdvanced); // Connect for setting check watchChangedSetting(); // Connect for validity check connect(d->ui.gateway, &QLineEdit::textChanged, this, &OpenVpnSettingWidget::slotWidgetChanged); KAcceleratorManager::manage(this); if (setting && !setting->isNull()) { loadConfig(d->setting); } } OpenVpnSettingWidget::~OpenVpnSettingWidget() { delete d; } void OpenVpnSettingWidget::loadConfig(const NetworkManager::Setting::Ptr &setting) { Q_UNUSED(setting) // General settings const NMStringMap dataMap = d->setting->data(); const QString cType = dataMap.value(NM_OPENVPN_KEY_CONNECTION_TYPE); if (cType == QLatin1String(NM_OPENVPN_CONTYPE_PASSWORD_TLS)) { d->ui.cmbConnectionType->setCurrentIndex(Private::EnumConnectionType::CertsPassword); d->ui.x509PassUsername->setText(dataMap[NM_OPENVPN_KEY_USERNAME]); d->ui.x509PassCaFile->setUrl(QUrl::fromLocalFile(dataMap[NM_OPENVPN_KEY_CA])); d->ui.x509PassCert->setUrl(QUrl::fromLocalFile(dataMap[NM_OPENVPN_KEY_CERT])); d->ui.x509PassKey->setUrl(QUrl::fromLocalFile(dataMap[NM_OPENVPN_KEY_KEY])); } else if (cType == QLatin1String( NM_OPENVPN_CONTYPE_STATIC_KEY)) { d->ui.cmbConnectionType->setCurrentIndex( Private::EnumConnectionType::Psk ); d->ui.pskSharedKey->setText( dataMap[NM_OPENVPN_KEY_STATIC_KEY]); if (dataMap.contains(NM_OPENVPN_KEY_STATIC_KEY_DIRECTION)) { switch (dataMap[NM_OPENVPN_KEY_STATIC_KEY_DIRECTION].toUInt()) { case 0: d->ui.cmbKeyDirection->setCurrentIndex(Private::EnumKeyDirection::D0); break; case 1: d->ui.cmbKeyDirection->setCurrentIndex(Private::EnumKeyDirection::D1); break; } } else { d->ui.cmbKeyDirection->setCurrentIndex(Private::EnumKeyDirection::None); } d->ui.pskRemoteIp->setText(dataMap[NM_OPENVPN_KEY_REMOTE_IP]); d->ui.pskLocalIp->setText(dataMap[NM_OPENVPN_KEY_LOCAL_IP]); } else if (cType == QLatin1String(NM_OPENVPN_CONTYPE_PASSWORD)) { d->ui.cmbConnectionType->setCurrentIndex(Private::EnumConnectionType::Password); d->ui.passUserName->setText(dataMap[NM_OPENVPN_KEY_USERNAME] ); d->ui.passCaFile->setUrl(QUrl::fromLocalFile(dataMap[NM_OPENVPN_KEY_CA])); } else if (cType == QLatin1String(NM_OPENVPN_CONTYPE_TLS)) { d->ui.cmbConnectionType->setCurrentIndex(Private::EnumConnectionType::Certificates); d->ui.x509CaFile->setUrl(QUrl::fromLocalFile(dataMap[NM_OPENVPN_KEY_CA])); d->ui.x509Cert->setUrl(QUrl::fromLocalFile(dataMap[NM_OPENVPN_KEY_CERT])); d->ui.x509Key->setUrl(QUrl::fromLocalFile(dataMap[NM_OPENVPN_KEY_KEY])); } d->ui.gateway->setText( dataMap[NM_OPENVPN_KEY_REMOTE] ); NetworkManager::Setting::SecretFlags type; if (cType == QLatin1String(NM_OPENVPN_CONTYPE_TLS)) { type = (NetworkManager::Setting::SecretFlags)dataMap[NM_OPENVPN_KEY_CERTPASS"-flags"].toInt(); fillOnePasswordCombo(d->ui.x509KeyPassword, type); } else if (cType == QLatin1String(NM_OPENVPN_CONTYPE_PASSWORD)) { type = (NetworkManager::Setting::SecretFlags)dataMap[NM_OPENVPN_KEY_PASSWORD"-flags"].toInt(); fillOnePasswordCombo(d->ui.passPassword, type); } else if (cType == QLatin1String(NM_OPENVPN_CONTYPE_PASSWORD_TLS)) { type = (NetworkManager::Setting::SecretFlags)dataMap[NM_OPENVPN_KEY_PASSWORD"-flags"].toInt(); fillOnePasswordCombo(d->ui.x509PassPassword, type); type = (NetworkManager::Setting::SecretFlags)dataMap[NM_OPENVPN_KEY_CERTPASS"-flags"].toInt(); fillOnePasswordCombo(d->ui.x509PassKeyPassword, type); } loadSecrets(setting); } void OpenVpnSettingWidget::loadSecrets(const NetworkManager::Setting::Ptr &setting) { NetworkManager::VpnSetting::Ptr vpnSetting = setting.staticCast(); if (vpnSetting) { const QString cType = d->setting->data().value(NM_OPENVPN_KEY_CONNECTION_TYPE); const NMStringMap secrets = vpnSetting->secrets(); if (cType == QLatin1String(NM_OPENVPN_CONTYPE_TLS)) { d->ui.x509KeyPassword->setText(secrets.value(NM_OPENVPN_KEY_CERTPASS)); } else if (cType == QLatin1String(NM_OPENVPN_CONTYPE_PASSWORD)) { d->ui.passPassword->setText(secrets.value(NM_OPENVPN_KEY_PASSWORD)); } else if (cType == QLatin1String(NM_OPENVPN_CONTYPE_PASSWORD_TLS)) { d->ui.x509PassPassword->setText(secrets.value(NM_OPENVPN_KEY_PASSWORD)); d->ui.x509PassKeyPassword->setText(secrets.value(NM_OPENVPN_KEY_CERTPASS)); } } } QVariantMap OpenVpnSettingWidget::setting() const { NMStringMap data = d->setting->data(); NMStringMap secretData = d->setting->secrets(); NetworkManager::VpnSetting setting; setting.setServiceType(QLatin1String(NM_DBUS_SERVICE_OPENVPN)); // required settings data.insert(QLatin1String(NM_OPENVPN_KEY_REMOTE), d->ui.gateway->text()); QString contype; switch ( d->ui.cmbConnectionType->currentIndex()) { case Private::EnumConnectionType::Certificates: contype = QLatin1String(NM_OPENVPN_CONTYPE_TLS); // qCDebug(PLASMA_NM) << "saving VPN TLS settings as urls:" << d->ui.x509CaFile->url() << d->ui.x509Cert->url() << d->ui.x509Key->url(); data.insert(QLatin1String(NM_OPENVPN_KEY_CA), d->ui.x509CaFile->url().toLocalFile()); data.insert(QLatin1String(NM_OPENVPN_KEY_CERT), d->ui.x509Cert->url().toLocalFile()); data.insert(QLatin1String(NM_OPENVPN_KEY_KEY), d->ui.x509Key->url().toLocalFile()); // key password if (!d->ui.x509KeyPassword->text().isEmpty()) { secretData.insert(QLatin1String(NM_OPENVPN_KEY_CERTPASS), d->ui.x509KeyPassword->text()); } else { secretData.remove(QLatin1String(NM_OPENVPN_KEY_CERTPASS)); } handleOnePasswordType(d->ui.x509KeyPassword, QLatin1String(NM_OPENVPN_KEY_CERTPASS"-flags"), data); break; case Private::EnumConnectionType::Psk: contype = QLatin1String(NM_OPENVPN_CONTYPE_STATIC_KEY); data.insert(QLatin1String(NM_OPENVPN_KEY_STATIC_KEY), d->ui.pskSharedKey->url().toLocalFile()); switch (d->ui.cmbKeyDirection->currentIndex()) { case Private::EnumKeyDirection::None: break; case Private::EnumKeyDirection::D0: data.insert(QLatin1String(NM_OPENVPN_KEY_STATIC_KEY_DIRECTION), QString::number(0)); break; case Private::EnumKeyDirection::D1: data.insert(QLatin1String(NM_OPENVPN_KEY_STATIC_KEY_DIRECTION), QString::number(1)); break; } // ip addresses data.insert(QLatin1String(NM_OPENVPN_KEY_REMOTE_IP), d->ui.pskRemoteIp->text()); data.insert(QLatin1String(NM_OPENVPN_KEY_LOCAL_IP), d->ui.pskLocalIp->text()); break; case Private::EnumConnectionType::Password: contype = QLatin1String(NM_OPENVPN_CONTYPE_PASSWORD); // username if (!d->ui.passUserName->text().isEmpty()) { data.insert(QLatin1String(NM_OPENVPN_KEY_USERNAME), d->ui.passUserName->text()); } else { data.remove(QLatin1String(NM_OPENVPN_KEY_USERNAME)); } // password if (!d->ui.passPassword->text().isEmpty()) { secretData.insert(QLatin1String(NM_OPENVPN_KEY_PASSWORD), d->ui.passPassword->text()); } else { secretData.remove(QLatin1String(NM_OPENVPN_KEY_PASSWORD)); } handleOnePasswordType(d->ui.passPassword, QLatin1String(NM_OPENVPN_KEY_PASSWORD"-flags"), data); // ca data.insert(QLatin1String(NM_OPENVPN_KEY_CA), d->ui.passCaFile->url().toLocalFile()); break; case Private::EnumConnectionType::CertsPassword: contype = QLatin1String(NM_OPENVPN_CONTYPE_PASSWORD_TLS); // username if (!d->ui.x509PassUsername->text().isEmpty()) { data.insert(QLatin1String(NM_OPENVPN_KEY_USERNAME), d->ui.x509PassUsername->text()); } else { data.remove(QLatin1String(NM_OPENVPN_KEY_USERNAME)); } // ca data.insert(QLatin1String(NM_OPENVPN_KEY_CA), d->ui.x509PassCaFile->url().toLocalFile()); // cert data.insert(QLatin1String(NM_OPENVPN_KEY_CERT), d->ui.x509PassCert->url().toLocalFile()); // key file data.insert(QLatin1String(NM_OPENVPN_KEY_KEY), d->ui.x509PassKey->url().toLocalFile()); // key password if (!d->ui.x509PassKeyPassword->text().isEmpty()) { secretData.insert(QLatin1String(NM_OPENVPN_KEY_CERTPASS), d->ui.x509PassKeyPassword->text()); } else { secretData.remove(QLatin1String(NM_OPENVPN_KEY_CERTPASS)); } handleOnePasswordType(d->ui.x509PassKeyPassword, QLatin1String(NM_OPENVPN_KEY_CERTPASS"-flags"), data); // password if (!d->ui.x509PassPassword->text().isEmpty()) { secretData.insert(QLatin1String(NM_OPENVPN_KEY_PASSWORD), d->ui.x509PassPassword->text()); } else { secretData.remove(QLatin1String(NM_OPENVPN_KEY_PASSWORD)); } handleOnePasswordType(d->ui.x509PassPassword, QLatin1String(NM_OPENVPN_KEY_PASSWORD"-flags"), data); break; } data.insert(QLatin1String(NM_OPENVPN_KEY_CONNECTION_TYPE), contype); setting.setData(data); setting.setSecrets(secretData); return setting.toMap(); } void OpenVpnSettingWidget::updateStartDir(const QUrl &url) { QList requesters; requesters << d->ui.x509CaFile << d->ui.x509Cert << d->ui.x509Key << d->ui.pskSharedKey << d->ui.passCaFile << d->ui.x509PassCaFile << d->ui.x509PassCert << d->ui.x509PassKey; - Q_FOREACH (KUrlRequester * requester, requesters) { + for (KUrlRequester *requester : requesters) { requester->setStartDir(url.adjusted(QUrl::RemoveFilename | QUrl::StripTrailingSlash)); } } void OpenVpnSettingWidget::setPasswordType(QLineEdit *edit, int type) { edit->setEnabled(type == SettingWidget::EnumPasswordStorageType::Store); } void OpenVpnSettingWidget::fillOnePasswordCombo(PasswordField *passwordField, NetworkManager::Setting::SecretFlags type) { if (type.testFlag(NetworkManager::Setting::None)) { passwordField->setPasswordOption(PasswordField::StoreForAllUsers); } else if (type.testFlag(NetworkManager::Setting::AgentOwned)) { passwordField->setPasswordOption(PasswordField::StoreForUser); } else if (type.testFlag(NetworkManager::Setting::NotSaved)) { passwordField->setPasswordOption(PasswordField::AlwaysAsk); } else if (type.testFlag(NetworkManager::Setting::NotRequired)) { passwordField->setPasswordOption(PasswordField::NotRequired); } } void OpenVpnSettingWidget::handleOnePasswordType(const PasswordField *passwordField, const QString &key, NMStringMap &data) const { const PasswordField::PasswordOption option = passwordField->passwordOption(); switch (option) { case PasswordField::StoreForAllUsers: data.insert(key, QString::number(NetworkManager::Setting::None)); break; case PasswordField::StoreForUser: data.insert(key, QString::number(NetworkManager::Setting::AgentOwned)); break; case PasswordField::AlwaysAsk: data.insert(key, QString::number(NetworkManager::Setting::NotSaved)); break; case PasswordField::NotRequired: data.insert(key, QString::number(NetworkManager::Setting::NotRequired)); break; } } void OpenVpnSettingWidget::showAdvanced() { QPointer adv = new OpenVpnAdvancedWidget(d->setting, this); adv->init(); connect(adv.data(), &OpenVpnAdvancedWidget::accepted, [adv, this] () { NetworkManager::VpnSetting::Ptr advData = adv->setting(); if (!advData.isNull()) { d->setting->setData(advData->data()); d->setting->setSecrets(advData->secrets()); } }); connect(adv.data(), &OpenVpnAdvancedWidget::finished, [adv] () { if (adv) { adv->deleteLater(); } }); adv->setModal(true); adv->show(); } bool OpenVpnSettingWidget::isValid() const { return !d->ui.gateway->text().isEmpty(); } diff --git a/vpn/vpnc/vpnc.cpp b/vpn/vpnc/vpnc.cpp index 27678319..26dff8a6 100644 --- a/vpn/vpnc/vpnc.cpp +++ b/vpn/vpnc/vpnc.cpp @@ -1,418 +1,418 @@ /* Copyright 2008 Will Stephenson Copyright 2011-2012 Rajeesh K Nambiar Copyright 2011-2012 Lamarque V. Souza Copyright 2013 Lukas Tinkl This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License or (at your option) version 3 or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of version 3 of the license. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "debug.h" #include "vpnc.h" #include #include #include #include #include #include #include #include "nm-vpnc-service.h" #include #include #include #include #include "vpncwidget.h" #include "vpncauth.h" VpncUiPluginPrivate::VpncUiPluginPrivate() { decryptedPasswd.clear(); ciscoDecrypt = nullptr; } VpncUiPluginPrivate::~VpncUiPluginPrivate() { } QString VpncUiPluginPrivate::readStringKeyValue(const KConfigGroup & configGroup, const QString & key) { const QString retValue = configGroup.readEntry(key); if (retValue.isEmpty()) { // String key can also start with "!" in CISCO pcf file. return configGroup.readEntry('!' + key); } else { return retValue; } } void VpncUiPluginPrivate::gotCiscoDecryptOutput() { QByteArray output = ciscoDecrypt->readAll(); if (!output.isEmpty()) { QList lines = output.split('\n'); if (!lines.isEmpty()) { decryptedPasswd = QString::fromUtf8(lines.first()); } } } void VpncUiPluginPrivate::ciscoDecryptFinished(int exitCode, QProcess::ExitStatus exitStatus) { if (exitCode || exitStatus != QProcess::NormalExit) { decryptedPasswd.clear(); } } void VpncUiPluginPrivate::ciscoDecryptError(QProcess::ProcessError pError) { if (!pError) { qCWarning(PLASMA_NM) << "Error in executing cisco-decrypt"; KMessageBox::error(nullptr, i18n("Error decrypting the obfuscated password"), i18n("Error"), KMessageBox::Notify); } decryptedPasswd.clear(); } #define NM_VPNC_LOCAL_PORT_DEFAULT 500 K_PLUGIN_CLASS_WITH_JSON(VpncUiPlugin, "plasmanetworkmanagement_vpncui.json") VpncUiPlugin::VpncUiPlugin(QObject * parent, const QVariantList &) : VpnUiPlugin(parent) { } VpncUiPlugin::~VpncUiPlugin() { } SettingWidget * VpncUiPlugin::widget(const NetworkManager::VpnSetting::Ptr &setting, QWidget * parent) { return new VpncWidget(setting, parent); } SettingWidget *VpncUiPlugin::askUser(const NetworkManager::VpnSetting::Ptr &setting, QWidget * parent) { return new VpncAuthDialog(setting, parent); } QString VpncUiPlugin::suggestedFileName(const NetworkManager::ConnectionSettings::Ptr &connection) const { return connection->id() + ".pcf"; } QString VpncUiPlugin::supportedFileExtensions() const { return "*.pcf"; } NMVariantMapMap VpncUiPlugin::importConnectionSettings(const QString &fileName) { // qCDebug(PLASMA_NM) << "Importing Cisco VPN connection from " << fileName; VpncUiPluginPrivate * decrPlugin = nullptr; NMVariantMapMap result; if (!fileName.endsWith(QLatin1String(".pcf"), Qt::CaseInsensitive)) { return result; } mError = VpnUiPlugin::Error; // NOTE: Cisco VPN pcf files follow ini style matching KConfig files // http://www.cisco.com/en/US/docs/security/vpn_client/cisco_vpn_client/vpn_client46/administration/guide/vcAch2.html#wp1155033 KSharedConfig::Ptr config = KSharedConfig::openConfig(fileName); if (!config) { mErrorMessage = i18n("File %1 could not be opened.", fileName); return result; } KConfigGroup cg(config, "main"); // Keys&Values are stored under [main] if (cg.exists()) { // Setup cisco-decrypt binary to decrypt the passwords const QString ciscoDecryptBinary = QStandardPaths::findExecutable("cisco-decrypt"); if (ciscoDecryptBinary.isEmpty()) { mErrorMessage = i18n("Needed executable cisco-decrypt could not be found."); return result; } decrPlugin = new VpncUiPluginPrivate(); decrPlugin->ciscoDecrypt = new KProcess(decrPlugin); decrPlugin->ciscoDecrypt->setOutputChannelMode(KProcess::OnlyStdoutChannel); decrPlugin->ciscoDecrypt->setReadChannel(QProcess::StandardOutput); connect(decrPlugin->ciscoDecrypt, QOverload::of(&KProcess::error), decrPlugin, &VpncUiPluginPrivate::ciscoDecryptError); connect(decrPlugin->ciscoDecrypt, QOverload::of(&KProcess::finished), decrPlugin, &VpncUiPluginPrivate::ciscoDecryptFinished); connect(decrPlugin->ciscoDecrypt, &KProcess::readyReadStandardOutput, decrPlugin, &VpncUiPluginPrivate::gotCiscoDecryptOutput); NMStringMap data; NMStringMap secretData; QVariantMap ipv4Data; // gateway data.insert(NM_VPNC_KEY_GATEWAY, decrPlugin->readStringKeyValue(cg,"Host")); // group name data.insert(NM_VPNC_KEY_ID, decrPlugin->readStringKeyValue(cg,"GroupName")); // user password if (!decrPlugin->readStringKeyValue(cg,"UserPassword").isEmpty()) { secretData.insert(NM_VPNC_KEY_XAUTH_PASSWORD, decrPlugin->readStringKeyValue(cg,"UserPassword")); } else if (!decrPlugin->readStringKeyValue(cg,"enc_UserPassword").isEmpty() && !ciscoDecryptBinary.isEmpty()) { // Decrypt the password and insert into map decrPlugin->ciscoDecrypt->setProgram(ciscoDecryptBinary); decrPlugin->ciscoDecrypt->start(); decrPlugin->ciscoDecrypt->waitForStarted(); decrPlugin->ciscoDecrypt->write(decrPlugin->readStringKeyValue(cg,"enc_UserPassword").toUtf8()); if (decrPlugin->ciscoDecrypt->waitForFinished()) { secretData.insert(NM_VPNC_KEY_XAUTH_PASSWORD, decrPlugin->decryptedPasswd); } } // Save user password switch (cg.readEntry("SaveUserPassword").toInt()) { case 0: data.insert(NM_VPNC_KEY_XAUTH_PASSWORD"-flags", QString::number(NetworkManager::Setting::NotSaved)); break; case 1: data.insert(NM_VPNC_KEY_XAUTH_PASSWORD"-flags", QString::number(NetworkManager::Setting::AgentOwned)); break; case 2: data.insert(NM_VPNC_KEY_XAUTH_PASSWORD"-flags", QString::number(NetworkManager::Setting::NotRequired)); break; } // group password if (!decrPlugin->readStringKeyValue(cg,"GroupPwd").isEmpty()) { secretData.insert(NM_VPNC_KEY_SECRET, decrPlugin->readStringKeyValue(cg,"GroupPwd")); data.insert(NM_VPNC_KEY_SECRET"-flags", QString::number(NetworkManager::Setting::AgentOwned)); } else if (!decrPlugin->readStringKeyValue(cg,"enc_GroupPwd").isEmpty() && !ciscoDecryptBinary.isEmpty()) { //Decrypt the password and insert into map decrPlugin->ciscoDecrypt->setProgram(ciscoDecryptBinary); decrPlugin->ciscoDecrypt->start(); decrPlugin->ciscoDecrypt->waitForStarted(); decrPlugin->ciscoDecrypt->write(decrPlugin->readStringKeyValue(cg,"enc_GroupPwd").toUtf8()); if (decrPlugin->ciscoDecrypt->waitForFinished()) { secretData.insert(NM_VPNC_KEY_SECRET, decrPlugin->decryptedPasswd); data.insert(NM_VPNC_KEY_SECRET"-flags", QString::number(NetworkManager::Setting::AgentOwned)); } } // Auth Type if (!cg.readEntry("AuthType").isEmpty() && cg.readEntry("AuthType").toInt() == 5) { data.insert(NM_VPNC_KEY_AUTHMODE, QLatin1String("hybrid")); } // Optional settings // username if (!decrPlugin->readStringKeyValue(cg,"Username").isEmpty()) { data.insert(NM_VPNC_KEY_XAUTH_USER, decrPlugin->readStringKeyValue(cg,"Username")); } // domain if (!decrPlugin->readStringKeyValue(cg,"NTDomain").isEmpty()) { data.insert(NM_VPNC_KEY_DOMAIN, decrPlugin->readStringKeyValue(cg,"NTDomain")); } // encryption if (!cg.readEntry("SingleDES").isEmpty() && cg.readEntry("SingleDES").toInt() != 0) { data.insert(NM_VPNC_KEY_SINGLE_DES, QLatin1String("yes")); } /* Disable all NAT Traversal if explicit EnableNat=0 exists, otherwise * default to NAT-T which is newer and standardized. If EnableNat=1, then * use Cisco-UDP like always; but if the key "X-NM-Use-NAT-T" is set, then * use NAT-T. If the key "X-NM-Force-NAT-T" is set then force NAT-T always * on. See vpnc documentation for more information on what the different * NAT modes are. */ // enable NAT if (cg.readEntry("EnableNat").toInt() == 1) { data.insert(NM_VPNC_KEY_NAT_TRAVERSAL_MODE, QLatin1String(NM_VPNC_NATT_MODE_CISCO)); // NAT traversal if (!cg.readEntry("X-NM-Use-NAT-T").isEmpty()) { if (cg.readEntry("X-NM-Use-NAT-T").toInt() == 1) { data.insert(NM_VPNC_KEY_NAT_TRAVERSAL_MODE, QLatin1String(NM_VPNC_NATT_MODE_NATT)); } if (cg.readEntry("X-NM-Force-NAT-T").toInt() == 1) { data.insert(NM_VPNC_KEY_NAT_TRAVERSAL_MODE, QLatin1String(NM_VPNC_NATT_MODE_NATT_ALWAYS)); } } } else { data.insert(NM_VPNC_KEY_NAT_TRAVERSAL_MODE, QLatin1String(NM_VPNC_NATT_MODE_NONE)); } // dead peer detection data.insert(NM_VPNC_KEY_DPD_IDLE_TIMEOUT, cg.readEntry("PeerTimeout")); // UseLegacyIKEPort=0 uses dynamic source IKE port instead of 500. if (cg.readEntry("UseLegacyIKEPort").isEmpty() || cg.readEntry("UseLegacyIKEPort").toInt() != 0) { data.insert(NM_VPNC_KEY_LOCAL_PORT, QString::number(NM_VPNC_LOCAL_PORT_DEFAULT)); } // DH Group data.insert(NM_VPNC_KEY_DHGROUP, decrPlugin->readStringKeyValue(cg,"DHGroup")); // Tunneling Mode - not supported by vpnc if (cg.readEntry("TunnelingMode").toInt() == 1) { KMessageBox::error(nullptr, i18n("The VPN settings file '%1' specifies that VPN traffic should be tunneled through TCP which is currently not supported in the vpnc software.\n\nThe connection can still be created, with TCP tunneling disabled, however it may not work as expected.", fileName), i18n("Not supported"), KMessageBox::Notify); } // EnableLocalLAN and X-NM-Routes are to be added to IPv4Setting if (!cg.readEntry("EnableLocalLAN").isEmpty()) { ipv4Data.insert("never-default", cg.readEntry("EnableLocalLAN")); } if (!decrPlugin->readStringKeyValue(cg,"X-NM-Routes").isEmpty()) { QList list; - Q_FOREACH (const QString &route, decrPlugin->readStringKeyValue(cg,"X-NM-Routes").split(' ')) { + for (const QString &route : decrPlugin->readStringKeyValue(cg,"X-NM-Routes").split(' ')) { NetworkManager::IpRoute ipRoute; ipRoute.setIp(QHostAddress(route.split('/').first())); ipRoute.setPrefixLength(route.split('/').at(1).toInt()); list << ipRoute; } QList > dbusRoutes; - Q_FOREACH (const NetworkManager::IpRoute &route, list) { + for (const NetworkManager::IpRoute &route : list) { QList dbusRoute; dbusRoute << htonl(route.ip().toIPv4Address()) << route.prefixLength() << htonl(route.nextHop().toIPv4Address()) << route.metric(); dbusRoutes << dbusRoute; } ipv4Data.insert("routes", QVariant::fromValue(dbusRoutes)); } // Set the '...-type' and '...-flags' value also NetworkManager::VpnSetting setting; setting.setServiceType("org.freedesktop.NetworkManager.vpnc"); setting.setData(data); setting.setSecrets(secretData); QVariantMap conn; if (decrPlugin->readStringKeyValue(cg,"Description").isEmpty()) { QFileInfo fileInfo(fileName); conn.insert("id", fileInfo.fileName().remove(QLatin1String(".pcf"), Qt::CaseInsensitive)); } else { conn.insert("id", decrPlugin->readStringKeyValue(cg,"Description")); } conn.insert("type", "vpn"); result.insert("connection", conn); result.insert("vpn", setting.toMap()); if (!ipv4Data.isEmpty()) { result.insert("ipv4", ipv4Data); } delete decrPlugin; } else { mErrorMessage = i18n("%1: file format error.", fileName); return result; } mError = VpncUiPlugin::NoError; return result; } bool VpncUiPlugin::exportConnectionSettings(const NetworkManager::ConnectionSettings::Ptr &connection, const QString &fileName) { NMStringMap data; NMStringMap secretData; NetworkManager::VpnSetting::Ptr vpnSetting = connection->setting(NetworkManager::Setting::Vpn).dynamicCast(); data = vpnSetting->data(); secretData = vpnSetting->secrets(); KSharedConfig::Ptr config = KSharedConfig::openConfig(fileName); if (!config) { mErrorMessage = i18n("%1: file could not be created", fileName); return false; } KConfigGroup cg(config,"main"); cg.writeEntry("Description", connection->id()); cg.writeEntry("Host", data.value(NM_VPNC_KEY_GATEWAY)); if (data.value(NM_VPNC_KEY_AUTHMODE) == QLatin1String("hybrid")) { cg.writeEntry("AuthType", "5"); } else { cg.writeEntry("AuthType", "1"); } cg.writeEntry("GroupName", data.value(NM_VPNC_KEY_ID)); cg.writeEntry("GroupPwd", secretData.value(NM_VPNC_KEY_SECRET)); cg.writeEntry("UserPassword", secretData.value(NM_VPNC_KEY_XAUTH_PASSWORD)); cg.writeEntry("enc_GroupPwd", ""); cg.writeEntry("enc_UserPassword", ""); if ((NetworkManager::Setting::SecretFlags)data.value(NM_VPNC_KEY_XAUTH_PASSWORD"-flags").toInt() & NetworkManager::Setting::NotSaved) { cg.writeEntry("SaveUserPassword", "0"); } if ((NetworkManager::Setting::SecretFlags)data.value(NM_VPNC_KEY_XAUTH_PASSWORD"-flags").toInt() & NetworkManager::Setting::AgentOwned) { cg.writeEntry("SaveUserPassword", "1"); } if ((NetworkManager::Setting::SecretFlags)data.value(NM_VPNC_KEY_XAUTH_PASSWORD"-flags").toInt() & NetworkManager::Setting::NotRequired) { cg.writeEntry("SaveUserPassword", "2"); } cg.writeEntry("Username", data.value(NM_VPNC_KEY_XAUTH_USER)); cg.writeEntry("EnableISPConnect", "0"); cg.writeEntry("ISPConnectType", "0"); cg.writeEntry("ISPConnect", ""); cg.writeEntry("ISPCommand", ""); cg.writeEntry("EnableBackup", "0"); cg.writeEntry("BackupServer", ""); cg.writeEntry("CertStore", "0"); cg.writeEntry("CertName", ""); cg.writeEntry("CertPath", ""); cg.writeEntry("CertSubjectName", ""); cg.writeEntry("CertSerialHash", ""); cg.writeEntry("DHGroup", data.value(NM_VPNC_KEY_DHGROUP)); cg.writeEntry("ForceKeepAlives", "0"); cg.writeEntry("NTDomain", data.value(NM_VPNC_KEY_DOMAIN)); cg.writeEntry("EnableMSLogon", "0"); cg.writeEntry("MSLogonType", "0"); cg.writeEntry("TunnelingMode", "0"); cg.writeEntry("TcpTunnelingPort", "10000"); cg.writeEntry("PeerTimeout", data.value(NM_VPNC_KEY_DPD_IDLE_TIMEOUT)); cg.writeEntry("EnableLocalLAN", "1"); cg.writeEntry("SendCertChain", "0"); cg.writeEntry("VerifyCertDN", ""); cg.writeEntry("EnableSplitDNS", "1"); cg.writeEntry("SPPhonebook", ""); if (data.value(NM_VPNC_KEY_SINGLE_DES) == "yes") { cg.writeEntry("SingleDES", "1"); } if (data.value(NM_VPNC_KEY_NAT_TRAVERSAL_MODE) == NM_VPNC_NATT_MODE_CISCO) { cg.writeEntry("EnableNat", "1"); } if (data.value(NM_VPNC_KEY_NAT_TRAVERSAL_MODE) == NM_VPNC_NATT_MODE_NATT) { cg.writeEntry("EnableNat", "1"); cg.writeEntry("X-NM-Use-NAT-T", "1"); } if (data.value(NM_VPNC_KEY_NAT_TRAVERSAL_MODE) == NM_VPNC_NATT_MODE_NATT_ALWAYS) { cg.writeEntry("EnableNat", "1"); cg.writeEntry("X-NM-Force-NAT-T", "1"); } // Export X-NM-Routes NetworkManager::Ipv4Setting::Ptr ipv4Setting = connection->setting(NetworkManager::Setting::Ipv4).dynamicCast(); if (!ipv4Setting->routes().isEmpty()) { QString routes; - Q_FOREACH (const NetworkManager::IpRoute &route, ipv4Setting->routes()) { + for (const NetworkManager::IpRoute &route : ipv4Setting->routes()) { routes += route.ip().toString() + QLatin1Char('/') + QString::number(route.prefixLength()) + QLatin1Char(' '); } cg.writeEntry("X-NM-Routes", routes.trimmed()); } cg.sync(); mError = VpncUiPlugin::NoError; return true; } #include "vpnc.moc"