[gnome-control-center/wip/networking2: 9/36] network: break out the details dialog
- From: Dan Winship <danw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-control-center/wip/networking2: 9/36] network: break out the details dialog
- Date: Wed, 9 Jan 2013 15:38:23 +0000 (UTC)
commit 881122688832e4aed71abd90ad1e6254ffb47121
Author: Matthias Clasen <mclasen redhat com>
Date: Tue Dec 11 00:20:35 2012 -0500
network: break out the details dialog
This code is fairly independent of the rest, and we don't want
net-device-wifi.c to become too massive and unmaintainable.
The code in connection-editor/ is fairly similar to
nm-connection-editor, with some simplification because we
currently only edit wireless connections.
The code in wireless-security/ is almost a straight copy
of the same code in nm-connection-editor, with some changes
to the .ui files to make them fit better in the new design.
configure.ac | 2 +
panels/network/Makefile.am | 7 +-
panels/network/connection-editor/Makefile.am | 44 +
panels/network/connection-editor/ce-page-details.c | 249 +++++
panels/network/connection-editor/ce-page-details.h | 66 ++
panels/network/connection-editor/ce-page-ip4.c | 901 +++++++++++++++++
panels/network/connection-editor/ce-page-ip4.h | 72 ++
panels/network/connection-editor/ce-page-ip6.c | 862 ++++++++++++++++
panels/network/connection-editor/ce-page-ip6.h | 72 ++
panels/network/connection-editor/ce-page-reset.c | 75 ++
panels/network/connection-editor/ce-page-reset.h | 61 ++
.../network/connection-editor/ce-page-security.c | 480 +++++++++
.../network/connection-editor/ce-page-security.h | 66 ++
panels/network/connection-editor/ce-page-wifi.c | 221 +++++
panels/network/connection-editor/ce-page-wifi.h | 63 ++
panels/network/connection-editor/ce-page.c | 454 +++++++++
panels/network/connection-editor/ce-page.h | 106 ++
.../connection-editor.gresource.xml | 12 +
.../network/connection-editor/connection-editor.ui | 140 +++
panels/network/connection-editor/details-page.ui | 402 ++++++++
panels/network/connection-editor/ip4-page.ui | 221 +++++
panels/network/connection-editor/ip6-page.ui | 221 +++++
.../connection-editor/net-connection-editor.c | 420 ++++++++
.../connection-editor/net-connection-editor.h | 83 ++
panels/network/connection-editor/reset-page.ui | 80 ++
panels/network/connection-editor/security-page.ui | 61 ++
panels/network/connection-editor/wifi-page.ui | 140 +++
panels/network/net-device-wifi.c | 145 +---
panels/network/network-wifi.ui | 1039 ++++++++++++++++++--
panels/network/wireless-security/Makefile.am | 55 +
panels/network/wireless-security/eap-method-fast.c | 443 +++++++++
panels/network/wireless-security/eap-method-fast.h | 36 +
.../network/wireless-security/eap-method-fast.ui | 203 ++++
panels/network/wireless-security/eap-method-leap.c | 183 ++++
panels/network/wireless-security/eap-method-leap.h | 35 +
.../network/wireless-security/eap-method-leap.ui | 107 ++
panels/network/wireless-security/eap-method-peap.c | 414 ++++++++
panels/network/wireless-security/eap-method-peap.h | 36 +
.../network/wireless-security/eap-method-peap.ui | 202 ++++
.../network/wireless-security/eap-method-simple.c | 305 ++++++
.../network/wireless-security/eap-method-simple.h | 47 +
.../network/wireless-security/eap-method-simple.ui | 143 +++
panels/network/wireless-security/eap-method-tls.c | 481 +++++++++
panels/network/wireless-security/eap-method-tls.h | 36 +
panels/network/wireless-security/eap-method-tls.ui | 198 ++++
panels/network/wireless-security/eap-method-ttls.c | 391 ++++++++
panels/network/wireless-security/eap-method-ttls.h | 36 +
.../network/wireless-security/eap-method-ttls.ui | 149 +++
panels/network/wireless-security/eap-method.c | 660 +++++++++++++
panels/network/wireless-security/eap-method.h | 128 +++
panels/network/wireless-security/helpers.c | 51 +
panels/network/wireless-security/helpers.h | 40 +
.../network/wireless-security/nag-user-dialog.ui | 191 ++++
.../network/wireless-security/wireless-security.c | 554 +++++++++++
.../wireless-security.gresource.xml | 17 +
.../network/wireless-security/wireless-security.h | 147 +++
panels/network/wireless-security/ws-dynamic-wep.c | 143 +++
panels/network/wireless-security/ws-dynamic-wep.h | 35 +
panels/network/wireless-security/ws-dynamic-wep.ui | 94 ++
panels/network/wireless-security/ws-leap.c | 192 ++++
panels/network/wireless-security/ws-leap.h | 33 +
panels/network/wireless-security/ws-leap.ui | 108 ++
panels/network/wireless-security/ws-wep-key.c | 349 +++++++
panels/network/wireless-security/ws-wep-key.h | 36 +
panels/network/wireless-security/ws-wep-key.ui | 196 ++++
panels/network/wireless-security/ws-wpa-eap.c | 139 +++
panels/network/wireless-security/ws-wpa-eap.h | 35 +
panels/network/wireless-security/ws-wpa-eap.ui | 87 ++
panels/network/wireless-security/ws-wpa-psk.c | 200 ++++
panels/network/wireless-security/ws-wpa-psk.h | 31 +
panels/network/wireless-security/ws-wpa-psk.ui | 118 +++
71 files changed, 13651 insertions(+), 198 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index e425426..cbc2851 100644
--- a/configure.ac
+++ b/configure.ac
@@ -489,6 +489,8 @@ panels/printers/gnome-printers-panel.desktop.in
panels/privacy/Makefile
panels/privacy/gnome-privacy-panel.desktop.in
panels/network/Makefile
+panels/network/wireless-security/Makefile
+panels/network/connection-editor/Makefile
panels/network/gnome-network-panel.desktop.in
panels/notifications/Makefile
panels/notifications/gnome-notifications-panel.desktop.in
diff --git a/panels/network/Makefile.am b/panels/network/Makefile.am
index b588a8a..00a0514 100644
--- a/panels/network/Makefile.am
+++ b/panels/network/Makefile.am
@@ -1,10 +1,13 @@
cappletname = network
+SUBDIRS = wireless-security connection-editor
+
INCLUDES = \
$(PANEL_CFLAGS) \
$(NETWORK_PANEL_CFLAGS) \
$(NETWORK_MANAGER_CFLAGS) \
-DGNOMELOCALEDIR="\"$(datadir)/locale\"" \
+ -I$(srcdir)/wireless-security \
$(NULL)
noinst_LTLIBRARIES = libnetwork.la
@@ -43,7 +46,9 @@ libnetwork_la_SOURCES = \
rfkill-glib.h \
rfkill.h
-libnetwork_la_LIBADD = $(PANEL_LIBS) $(NETWORK_PANEL_LIBS) $(NETWORK_MANAGER_LIBS)
+libnetwork_la_LIBADD = $(PANEL_LIBS) $(NETWORK_PANEL_LIBS) $(NETWORK_MANAGER_LIBS) $(builddir)/connection-editor/libconnection-editor.la
+
+libnetwork_la_LDFLAGS = $(PANEL_LDFLAGS)
resource_files = $(shell glib-compile-resources --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/network.gresource.xml)
cc-network-resources.c: network.gresource.xml $(resource_files)
diff --git a/panels/network/connection-editor/Makefile.am b/panels/network/connection-editor/Makefile.am
new file mode 100644
index 0000000..ed0b11a
--- /dev/null
+++ b/panels/network/connection-editor/Makefile.am
@@ -0,0 +1,44 @@
+noinst_LTLIBRARIES = libconnection-editor.la
+
+BUILT_SOURCES = \
+ net-connection-editor-resources.c \
+ net-connection-editor-resources.h
+
+libconnection_editor_la_SOURCES = \
+ $(BUILT_SOURCES) \
+ net-connection-editor.h \
+ net-connection-editor.c \
+ ce-page.h \
+ ce-page.c \
+ ce-page-details.h \
+ ce-page-details.c \
+ ce-page-wifi.h \
+ ce-page-wifi.c \
+ ce-page-ip4.h \
+ ce-page-ip4.c \
+ ce-page-ip6.h \
+ ce-page-ip6.c \
+ ce-page-security.h \
+ ce-page-security.c \
+ ce-page-reset.h \
+ ce-page-reset.c
+
+libconnection_editor_la_CPPFLAGS = \
+ -I$(srcdir)/../wireless-security \
+ $(NETWORK_PANEL_CFLAGS) \
+ $(NETWORK_MANAGER_CFLAGS) \
+ -DGNOMECC_UI_DIR=\""$(uidir)"\"
+
+libconnection_editor_la_LIBADD = \
+ $(builddir)/../wireless-security/libwireless-security.la \
+ $(NETWORK_PANEL_LIBS) \
+ $(NETWORK_MANAGER_LIBS)
+
+resource_files = $(shell glib-compile-resources --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/connection-editor.gresource.xml)
+net-connection-editor-resources.c: connection-editor.gresource.xml $(resource_files)
+ $(AM_V_GEN) glib-compile-resources --target=$@ --sourcedir=$(srcdir) --generate-source --c-name net_connection_editor $<
+net-connection-editor-resources.h: connection-editor.gresource.xml $(resource_files)
+ $(AM_V_GEN) glib-compile-resources --target=$@ --sourcedir=$(srcdir) --generate-header --c-name net_connection_editor $<
+
+EXTRA_DIST = \
+ $(resource_files)
diff --git a/panels/network/connection-editor/ce-page-details.c b/panels/network/connection-editor/ce-page-details.c
new file mode 100644
index 0000000..10b0d75
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-details.c
@@ -0,0 +1,249 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <glib/gi18n.h>
+
+#include <nm-utils.h>
+#include <nm-device-wifi.h>
+
+#include "../panel-common.h"
+#include "ce-page-details.h"
+
+G_DEFINE_TYPE (CEPageDetails, ce_page_details, CE_TYPE_PAGE)
+
+static gchar *
+get_ap_security_string (NMAccessPoint *ap)
+{
+ NM80211ApSecurityFlags wpa_flags, rsn_flags;
+ NM80211ApFlags flags;
+ GString *str;
+
+ flags = nm_access_point_get_flags (ap);
+ wpa_flags = nm_access_point_get_wpa_flags (ap);
+ rsn_flags = nm_access_point_get_rsn_flags (ap);
+
+ str = g_string_new ("");
+ if ((flags & NM_802_11_AP_FLAGS_PRIVACY) &&
+ (wpa_flags == NM_802_11_AP_SEC_NONE) &&
+ (rsn_flags == NM_802_11_AP_SEC_NONE)) {
+ /* TRANSLATORS: this WEP WiFi security */
+ g_string_append_printf (str, "%s, ", _("WEP"));
+ }
+ if (wpa_flags != NM_802_11_AP_SEC_NONE) {
+ /* TRANSLATORS: this WPA WiFi security */
+ g_string_append_printf (str, "%s, ", _("WPA"));
+ }
+ if (rsn_flags != NM_802_11_AP_SEC_NONE) {
+ /* TRANSLATORS: this WPA WiFi security */
+ g_string_append_printf (str, "%s, ", _("WPA2"));
+ }
+ if ((wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) ||
+ (rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) {
+ /* TRANSLATORS: this Enterprise WiFi security */
+ g_string_append_printf (str, "%s, ", _("Enterprise"));
+ }
+ if (str->len > 0)
+ g_string_set_size (str, str->len - 2);
+ else {
+ g_string_append (str, C_("Wifi security", "None"));
+ }
+ return g_string_free (str, FALSE);
+}
+
+static void
+update_last_used (CEPageDetails *page, NMConnection *connection)
+{
+ gchar *last_used = NULL;
+ GDateTime *now = NULL;
+ GDateTime *then = NULL;
+ gint days;
+ GTimeSpan diff;
+ guint64 timestamp;
+ NMSettingConnection *s_con;
+
+ s_con = nm_connection_get_setting_connection (connection);
+ if (s_con == NULL)
+ goto out;
+ timestamp = nm_setting_connection_get_timestamp (s_con);
+ if (timestamp == 0) {
+ last_used = g_strdup (_("never"));
+ goto out;
+ }
+
+ /* calculate the amount of time that has elapsed */
+ now = g_date_time_new_now_utc ();
+ then = g_date_time_new_from_unix_utc (timestamp);
+
+ diff = g_date_time_difference (now, then);
+ days = diff / G_TIME_SPAN_DAY;
+ if (days == 0)
+ last_used = g_strdup (_("today"));
+ else if (days == 1)
+ last_used = g_strdup (_("yesterday"));
+ else
+ last_used = g_strdup_printf (ngettext ("%i day ago", "%i days ago", days), days);
+out:
+ panel_set_device_widget_details (CE_PAGE (page)->builder, "last_used", last_used);
+ if (now != NULL)
+ g_date_time_unref (now);
+ if (then != NULL)
+ g_date_time_unref (then);
+ g_free (last_used);
+}
+
+static void
+all_user_changed (GObject *sw, GParamSpec *pspec, CEPageDetails *page)
+{
+ gboolean all_users;
+ NMSettingConnection *sc;
+
+ sc = nm_connection_get_setting_connection (CE_PAGE (page)->connection);
+ all_users = gtk_switch_get_active (GTK_SWITCH (sw));
+
+ g_object_set (sc, "permissions", NULL, NULL);
+ if (!all_users)
+ nm_setting_connection_add_permission (sc, "user", g_get_user_name (), NULL);
+}
+
+static void
+connect_details_page (CEPageDetails *page)
+{
+ GtkWidget *widget;
+ NMSettingConnection *sc;
+ guint speed;
+ guint strength;
+ NMDeviceState state;
+ NMAccessPoint *active_ap;
+ const gchar *str;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder,
+ "auto_connect_switch"));
+ sc = nm_connection_get_setting_connection (CE_PAGE (page)->connection);
+ g_object_bind_property (sc, "autoconnect",
+ widget, "active",
+ G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+ widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder,
+ "all_user_switch"));
+ gtk_switch_set_active (GTK_SWITCH (widget),
+ nm_setting_connection_get_num_permissions (sc) == 0);
+ g_signal_connect (widget, "notify::active",
+ G_CALLBACK (all_user_changed), page);
+
+ active_ap = nm_device_wifi_get_active_access_point (NM_DEVICE_WIFI (page->device));
+ state = nm_device_get_state (page->device);
+
+ speed = 0;
+ if (page->ap == active_ap && state != NM_DEVICE_STATE_UNAVAILABLE) {
+ speed = nm_device_wifi_get_bitrate (NM_DEVICE_WIFI (page->device)) / 1000;
+ }
+ if (speed > 0)
+ str = g_strdup_printf (_("%d Mb/s"), speed);
+ else
+ str = NULL;
+ panel_set_device_widget_details (CE_PAGE (page)->builder, "speed", str);
+
+ str = nm_device_wifi_get_hw_address (NM_DEVICE_WIFI (page->device));
+ panel_set_device_widget_details (CE_PAGE (page)->builder, "mac", str);
+
+ str = NULL;
+ if (page->ap == active_ap)
+ str = get_ap_security_string (active_ap);
+ panel_set_device_widget_details (CE_PAGE (page)->builder, "security", str);
+
+ strength = 0;
+ if (page->ap != NULL)
+ strength = nm_access_point_get_strength (page->ap);
+
+ if (strength <= 0)
+ str = NULL;
+ else if (strength < 20)
+ str = C_("Signal strength", "None");
+ else if (strength < 40)
+ str = C_("Signal strength", "Weak");
+ else if (strength < 50)
+ str = C_("Signal strength", "Ok");
+ else if (strength < 80)
+ str = C_("Signal strength", "Good");
+ else
+ str = C_("Signal strength", "Excellent");
+ panel_set_device_widget_details (CE_PAGE (page)->builder, "strength", str);
+
+ /* set IP entries */
+ if (page->ap != active_ap)
+ panel_unset_device_widgets (CE_PAGE (page)->builder);
+ else
+ panel_set_device_widgets (CE_PAGE (page)->builder, page->device);
+
+ if (page->ap != active_ap && CE_PAGE (page)->connection)
+ update_last_used (page, CE_PAGE (page)->connection);
+ else
+ panel_set_device_widget_details (CE_PAGE (page)->builder, "last_used", NULL);
+
+}
+
+static gboolean
+validate (CEPage *page,
+ NMConnection *connection,
+ GError **error)
+{
+ return TRUE;
+}
+
+static void
+ce_page_details_init (CEPageDetails *page)
+{
+}
+
+static void
+ce_page_details_class_init (CEPageDetailsClass *class)
+{
+ CEPageClass *page_class= CE_PAGE_CLASS (class);
+
+ page_class->validate = validate;
+}
+
+CEPage *
+ce_page_details_new (NMConnection *connection,
+ NMClient *client,
+ NMRemoteSettings *settings,
+ NMDevice *device,
+ NMAccessPoint *ap)
+{
+ CEPageDetails *page;
+
+ page = CE_PAGE_DETAILS (ce_page_new (CE_TYPE_PAGE_DETAILS,
+ connection,
+ client,
+ settings,
+ "/org/gnome/control-center/network/details-page.ui",
+ _("Details")));
+
+ page->device = device;
+ page->ap = ap;
+
+ connect_details_page (page);
+
+ return CE_PAGE (page);
+}
+
diff --git a/panels/network/connection-editor/ce-page-details.h b/panels/network/connection-editor/ce-page-details.h
new file mode 100644
index 0000000..5cb8f56
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-details.h
@@ -0,0 +1,66 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __CE_PAGE_DETAILS_H
+#define __CE_PAGE_DETAILS_H
+
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+#include "ce-page.h"
+
+G_BEGIN_DECLS
+
+#define CE_TYPE_PAGE_DETAILS (ce_page_details_get_type ())
+#define CE_PAGE_DETAILS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CE_TYPE_PAGE_DETAILS, CEPageDetails))
+#define CE_PAGE_DETAILS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CE_TYPE_PAGE_DETAILS, CEPageDetailsClass))
+#define CE_IS_PAGE_DETAILS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CE_TYPE_PAGE_DETAILS))
+#define CE_IS_PAGE_DETAILS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CE_TYPE_PAGE_DETAILS))
+#define CE_PAGE_DETAILS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CE_TYPE_PAGE_DETAILS, CEPageDetailsClass))
+
+typedef struct _CEPageDetails CEPageDetails;
+typedef struct _CEPageDetailsClass CEPageDetailsClass;
+
+struct _CEPageDetails
+{
+ CEPage parent;
+
+ NMDevice *device;
+ NMAccessPoint *ap;
+};
+
+struct _CEPageDetailsClass
+{
+ CEPageClass parent_class;
+};
+
+GType ce_page_details_get_type (void);
+
+CEPage *ce_page_details_new (NMConnection *connection,
+ NMClient *client,
+ NMRemoteSettings *settings,
+ NMDevice *device,
+ NMAccessPoint *ap);
+
+G_END_DECLS
+
+#endif /* __CE_PAGE_DETAILS_H */
+
diff --git a/panels/network/connection-editor/ce-page-ip4.c b/panels/network/connection-editor/ce-page-ip4.c
new file mode 100644
index 0000000..a0bc368
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-ip4.c
@@ -0,0 +1,901 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <glib-object.h>
+#include <glib/gi18n.h>
+
+#include "ce-page-ip4.h"
+#include <nm-utils.h>
+
+#include "egg-list-box/egg-list-box.h"
+
+G_DEFINE_TYPE (CEPageIP4, ce_page_ip4, CE_TYPE_PAGE)
+
+enum {
+ METHOD_COL_NAME,
+ METHOD_COL_METHOD
+};
+
+enum {
+ IP4_METHOD_AUTO,
+ IP4_METHOD_MANUAL,
+ IP4_METHOD_LINK_LOCAL,
+ IP4_METHOD_SHARED,
+ IP4_METHOD_DISABLED
+};
+
+static void
+method_changed (GtkComboBox *combo, CEPageIP4 *page)
+{
+ gboolean addr_enabled;
+ gboolean dns_enabled;
+ gboolean routes_enabled;
+ guint method;
+
+ method = gtk_combo_box_get_active (combo);
+ switch (method) {
+ case IP4_METHOD_AUTO:
+ addr_enabled = FALSE;
+ dns_enabled = TRUE;
+ routes_enabled = TRUE;
+ break;
+ case IP4_METHOD_MANUAL:
+ addr_enabled = TRUE;
+ dns_enabled = TRUE;
+ routes_enabled = TRUE;
+ break;
+ case IP4_METHOD_LINK_LOCAL:
+ default:
+ addr_enabled = FALSE;
+ dns_enabled = FALSE;
+ routes_enabled = FALSE;
+ break;
+ }
+
+ gtk_widget_set_sensitive (page->address_list, addr_enabled);
+ gtk_widget_set_sensitive (page->dns_list, dns_enabled);
+ gtk_widget_set_sensitive (page->routes_list, routes_enabled);
+ gtk_widget_set_sensitive (page->never_default, routes_enabled);
+
+ ce_page_changed (CE_PAGE (page));
+}
+
+static void
+update_separator (GtkWidget **separator,
+ GtkWidget *child,
+ GtkWidget *before,
+ gpointer user_data)
+{
+ if (before == NULL)
+ return;
+
+ if (*separator == NULL)
+ {
+ *separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
+ gtk_widget_show (*separator);
+ g_object_ref_sink (*separator);
+ }
+}
+
+static void
+remove_row (GtkButton *button, CEPageIP4 *page)
+{
+ GtkWidget *row;
+ GtkWidget *list;
+
+ row = gtk_widget_get_parent (GTK_WIDGET (button));
+ list = gtk_widget_get_parent (row);
+
+ gtk_container_remove (GTK_CONTAINER (list), row);
+
+ ce_page_changed (CE_PAGE (page));
+}
+
+static gint
+sort_first_last (gconstpointer a, gconstpointer b, gpointer data)
+{
+ gboolean afirst, bfirst, alast, blast;
+
+ afirst = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (a), "first"));
+ bfirst = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (b), "first"));
+ alast = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (a), "last"));
+ blast = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (b), "last"));
+
+ if (afirst)
+ return -1;
+ if (bfirst)
+ return 1;
+ if (alast)
+ return 1;
+ if (blast)
+ return -1;
+
+ return 0;
+}
+
+static void
+add_address_row (CEPageIP4 *page,
+ const gchar *address,
+ const gchar *network,
+ const gchar *gateway)
+{
+ GtkWidget *row;
+ GtkWidget *widget;
+ GtkWidget *delete_button;
+ GtkWidget *image;
+
+ row = gtk_grid_new ();
+ widget = gtk_label_new (_("Address"));
+ gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+ gtk_grid_attach (GTK_GRID (row), widget, 1, 1, 1, 1);
+ widget = gtk_label_new (_("Netmask"));
+ gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+ gtk_grid_attach (GTK_GRID (row), widget, 1, 2, 1, 1);
+ widget = gtk_label_new (_("Gateway"));
+ gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+ gtk_grid_attach (GTK_GRID (row), widget, 1, 3, 1, 1);
+ widget = gtk_entry_new ();
+ g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+ g_object_set_data (G_OBJECT (row), "address", widget);
+ gtk_entry_set_text (GTK_ENTRY (widget), address);
+ gtk_widget_set_margin_left (widget, 10);
+ gtk_widget_set_margin_right (widget, 10);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_grid_attach (GTK_GRID (row), widget, 2, 1, 1, 1);
+ widget = gtk_entry_new ();
+ g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+ g_object_set_data (G_OBJECT (row), "network", widget);
+ gtk_entry_set_text (GTK_ENTRY (widget), network);
+ gtk_widget_set_margin_left (widget, 10);
+ gtk_widget_set_margin_right (widget, 10);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_grid_attach (GTK_GRID (row), widget, 2, 2, 1, 1);
+ widget = gtk_entry_new ();
+ g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+ g_object_set_data (G_OBJECT (row), "gateway", widget);
+ gtk_entry_set_text (GTK_ENTRY (widget), gateway);
+ gtk_widget_set_margin_left (widget, 10);
+ gtk_widget_set_margin_right (widget, 10);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_grid_attach (GTK_GRID (row), widget, 2, 3, 1, 1);
+
+ delete_button = gtk_button_new ();
+ g_signal_connect (delete_button, "clicked", G_CALLBACK (remove_row), page);
+ image = gtk_image_new_from_icon_name ("user-trash-symbolic", GTK_ICON_SIZE_MENU);
+ gtk_button_set_image (GTK_BUTTON (delete_button), image);
+ gtk_grid_attach (GTK_GRID (row), delete_button, 3, 2, 1, 1);
+
+ gtk_widget_set_margin_left (row, 10);
+ gtk_widget_set_margin_right (row, 10);
+ gtk_widget_set_margin_top (row, 10);
+ gtk_widget_set_margin_bottom (row, 10);
+ gtk_widget_set_halign (row, GTK_ALIGN_FILL);
+ gtk_widget_show_all (row);
+ gtk_container_add (GTK_CONTAINER (page->address_list), row);
+}
+
+static void
+add_empty_address_row (CEPageIP4 *page)
+{
+ add_address_row (page, "", "", "");
+}
+
+static void
+add_address_section (CEPageIP4 *page)
+{
+ GtkWidget *widget;
+ GtkWidget *frame;
+ GtkWidget *list;
+ GtkWidget *row;
+ GtkWidget *button;
+ GtkWidget *image;
+ gint i;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "address_section"));
+
+ frame = gtk_frame_new (NULL);
+ gtk_container_add (GTK_CONTAINER (widget), frame);
+ page->address_list = list = GTK_WIDGET (egg_list_box_new ());
+ egg_list_box_set_selection_mode (EGG_LIST_BOX (list), GTK_SELECTION_NONE);
+ egg_list_box_set_separator_funcs (EGG_LIST_BOX (list), update_separator, NULL, NULL);
+ egg_list_box_set_sort_func (EGG_LIST_BOX (list), sort_first_last, NULL, NULL);
+ gtk_container_add (GTK_CONTAINER (frame), list);
+ row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ g_object_set_data (G_OBJECT (row), "last", GINT_TO_POINTER (TRUE));
+ button = gtk_button_new ();
+ g_signal_connect_swapped (button, "clicked", G_CALLBACK (add_empty_address_row), page);
+ image = gtk_image_new_from_icon_name ("list-add-symbolic", GTK_ICON_SIZE_MENU);
+ gtk_button_set_image (GTK_BUTTON (button), image);
+ gtk_widget_set_margin_top (button, 10);
+ gtk_widget_set_margin_bottom (button, 10);
+ gtk_widget_set_margin_left (button, 10);
+ gtk_widget_set_margin_right (button, 10);
+ gtk_widget_set_halign (button, GTK_ALIGN_END);
+ gtk_box_pack_start (GTK_BOX (row), button, TRUE, TRUE, 0);
+ gtk_container_add (GTK_CONTAINER (list), row);
+ gtk_widget_show_all (frame);
+
+ for (i = 0; i < nm_setting_ip4_config_get_num_addresses (page->setting); i++) {
+ NMIP4Address *addr;
+ struct in_addr tmp_addr;
+ gchar address[INET_ADDRSTRLEN + 1];
+ gchar network[INET_ADDRSTRLEN + 1];
+ gchar gateway[INET_ADDRSTRLEN + 1];
+
+ addr = nm_setting_ip4_config_get_address (page->setting, i);
+ if (!addr)
+ continue;
+
+ tmp_addr.s_addr = nm_ip4_address_get_address (addr);
+ (void) inet_ntop (AF_INET, &tmp_addr, &address[0], sizeof (address));
+
+ tmp_addr.s_addr = nm_utils_ip4_prefix_to_netmask (nm_ip4_address_get_prefix (addr));
+ (void) inet_ntop (AF_INET, &tmp_addr, &network[0], sizeof (network));
+
+ tmp_addr.s_addr = nm_ip4_address_get_gateway (addr);
+ (void) inet_ntop (AF_INET, &tmp_addr, &gateway[0], sizeof (gateway));
+
+ add_address_row (page, address, network, gateway);
+ }
+ if (nm_setting_ip4_config_get_num_addresses (page->setting) == 0)
+ add_empty_address_row (page);
+}
+
+static void
+add_dns_row (CEPageIP4 *page,
+ const gchar *address)
+{
+ GtkWidget *row;
+ GtkWidget *widget;
+ GtkWidget *delete_button;
+ GtkWidget *image;
+
+ row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ widget = gtk_label_new (_("Address"));
+ gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+ gtk_box_pack_start (GTK_BOX (row), widget, FALSE, FALSE, 0);
+ widget = gtk_entry_new ();
+ g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+ g_object_set_data (G_OBJECT (row), "address", widget);
+ gtk_entry_set_text (GTK_ENTRY (widget), address);
+ gtk_widget_set_margin_left (widget, 10);
+ gtk_widget_set_margin_right (widget, 10);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_box_pack_start (GTK_BOX (row), widget, TRUE, TRUE, 0);
+
+ delete_button = gtk_button_new ();
+ g_signal_connect (delete_button, "clicked", G_CALLBACK (remove_row), page);
+ image = gtk_image_new_from_icon_name ("user-trash-symbolic", GTK_ICON_SIZE_MENU);
+ gtk_button_set_image (GTK_BUTTON (delete_button), image);
+ gtk_box_pack_start (GTK_BOX (row), delete_button, FALSE, FALSE, 0);
+
+ gtk_widget_set_margin_left (row, 10);
+ gtk_widget_set_margin_right (row, 10);
+ gtk_widget_set_margin_top (row, 10);
+ gtk_widget_set_margin_bottom (row, 10);
+ gtk_widget_set_halign (row, GTK_ALIGN_FILL);
+ gtk_widget_show_all (row);
+ gtk_container_add (GTK_CONTAINER (page->dns_list), row);
+}
+
+static void
+add_empty_dns_row (CEPageIP4 *page)
+{
+ add_dns_row (page, "");
+}
+
+static void
+add_dns_section (CEPageIP4 *page)
+{
+ GtkWidget *widget;
+ GtkWidget *frame;
+ GtkWidget *list;
+ GtkWidget *row;
+ GtkWidget *button;
+ GtkWidget *image;
+ gint i;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "dns_section"));
+
+ frame = gtk_frame_new (NULL);
+ gtk_container_add (GTK_CONTAINER (widget), frame);
+ page->dns_list = list = GTK_WIDGET (egg_list_box_new ());
+ egg_list_box_set_selection_mode (EGG_LIST_BOX (list), GTK_SELECTION_NONE);
+ egg_list_box_set_separator_funcs (EGG_LIST_BOX (list), update_separator, NULL, NULL);
+ egg_list_box_set_sort_func (EGG_LIST_BOX (list), sort_first_last, NULL, NULL);
+ gtk_container_add (GTK_CONTAINER (frame), list);
+ row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ g_object_set_data (G_OBJECT (row), "first", GINT_TO_POINTER (TRUE));
+ widget = gtk_label_new (_("Automatic"));
+ gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
+ gtk_widget_set_margin_top (widget, 10);
+ gtk_widget_set_margin_bottom (widget, 10);
+ gtk_widget_set_margin_left (widget, 10);
+ gtk_widget_set_margin_right (widget, 10);
+ gtk_widget_set_halign (widget, GTK_ALIGN_FILL);
+ gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
+ gtk_box_pack_start (GTK_BOX (row), widget, FALSE, FALSE, 0);
+ widget = gtk_switch_new ();
+ page->auto_dns = GTK_SWITCH (widget);
+ gtk_switch_set_active (page->auto_dns, !nm_setting_ip4_config_get_ignore_auto_dns (page->setting));
+ gtk_widget_set_margin_top (widget, 10);
+ gtk_widget_set_margin_bottom (widget, 10);
+ gtk_widget_set_margin_left (widget, 10);
+ gtk_widget_set_margin_right (widget, 10);
+ gtk_widget_set_halign (widget, GTK_ALIGN_END);
+ gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
+ gtk_box_pack_start (GTK_BOX (row), widget, TRUE, TRUE, 0);
+ gtk_container_add (GTK_CONTAINER (list), row);
+
+ row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ g_object_set_data (G_OBJECT (row), "last", GINT_TO_POINTER (TRUE));
+ button = gtk_button_new ();
+ g_signal_connect_swapped (button, "clicked", G_CALLBACK (add_empty_dns_row), page);
+ image = gtk_image_new_from_icon_name ("list-add-symbolic", GTK_ICON_SIZE_MENU);
+ gtk_button_set_image (GTK_BUTTON (button), image);
+ gtk_widget_set_margin_top (button, 10);
+ gtk_widget_set_margin_bottom (button, 10);
+ gtk_widget_set_margin_left (button, 10);
+ gtk_widget_set_margin_right (button, 10);
+ gtk_widget_set_halign (button, GTK_ALIGN_END);
+ gtk_box_pack_start (GTK_BOX (row), button, TRUE, TRUE, 0);
+ gtk_container_add (GTK_CONTAINER (list), row);
+ gtk_widget_show_all (frame);
+
+ for (i = 0; i < nm_setting_ip4_config_get_num_dns (page->setting); i++) {
+ struct in_addr tmp_addr;
+ gchar address[INET_ADDRSTRLEN + 1];
+
+ tmp_addr.s_addr = nm_setting_ip4_config_get_dns (page->setting, i);
+ (void) inet_ntop (AF_INET, &tmp_addr, &address[0], sizeof (address));
+
+ add_dns_row (page, address);
+ }
+ if (nm_setting_ip4_config_get_num_dns (page->setting) == 0)
+ add_empty_dns_row (page);
+}
+
+static void
+add_route_row (CEPageIP4 *page,
+ const gchar *address,
+ const gchar *netmask,
+ const gchar *gateway,
+ gint metric)
+{
+ GtkWidget *row;
+ GtkWidget *widget;
+ GtkWidget *delete_button;
+ GtkWidget *image;
+
+ row = gtk_grid_new ();
+ widget = gtk_label_new (_("Address"));
+ gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+ gtk_grid_attach (GTK_GRID (row), widget, 1, 1, 1, 1);
+ widget = gtk_label_new (_("Netmask"));
+ gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+ gtk_grid_attach (GTK_GRID (row), widget, 1, 2, 1, 1);
+ widget = gtk_label_new (_("Gateway"));
+ gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+ gtk_grid_attach (GTK_GRID (row), widget, 1, 3, 1, 1);
+ widget = gtk_label_new (_("Metric"));
+ gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+ gtk_grid_attach (GTK_GRID (row), widget, 1, 4, 1, 1);
+ widget = gtk_entry_new ();
+ g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+ g_object_set_data (G_OBJECT (row), "address", widget);
+ gtk_entry_set_text (GTK_ENTRY (widget), address);
+ gtk_widget_set_margin_left (widget, 10);
+ gtk_widget_set_margin_right (widget, 10);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_grid_attach (GTK_GRID (row), widget, 2, 1, 1, 1);
+ widget = gtk_entry_new ();
+ g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+ g_object_set_data (G_OBJECT (row), "netmask", widget);
+ gtk_entry_set_text (GTK_ENTRY (widget), netmask);
+ gtk_widget_set_margin_left (widget, 10);
+ gtk_widget_set_margin_right (widget, 10);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_grid_attach (GTK_GRID (row), widget, 2, 2, 1, 1);
+ widget = gtk_entry_new ();
+ g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+ g_object_set_data (G_OBJECT (row), "gateway", widget);
+ gtk_entry_set_text (GTK_ENTRY (widget), gateway);
+ gtk_widget_set_margin_left (widget, 10);
+ gtk_widget_set_margin_right (widget, 10);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_grid_attach (GTK_GRID (row), widget, 2, 3, 1, 1);
+ widget = gtk_entry_new ();
+ g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+ g_object_set_data (G_OBJECT (row), "metric", widget);
+ if (metric > 0) {
+ gchar *s = g_strdup_printf ("%d", metric);
+ gtk_entry_set_text (GTK_ENTRY (widget), s);
+ g_free (s);
+ }
+ gtk_widget_set_margin_left (widget, 10);
+ gtk_widget_set_margin_right (widget, 10);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_grid_attach (GTK_GRID (row), widget, 2, 4, 1, 1);
+
+ delete_button = gtk_button_new ();
+ g_signal_connect (delete_button, "clicked", G_CALLBACK (remove_row), page);
+ image = gtk_image_new_from_icon_name ("user-trash-symbolic", GTK_ICON_SIZE_MENU);
+ gtk_button_set_image (GTK_BUTTON (delete_button), image);
+ gtk_widget_set_halign (delete_button, GTK_ALIGN_CENTER);
+ gtk_widget_set_valign (delete_button, GTK_ALIGN_CENTER);
+ gtk_grid_attach (GTK_GRID (row), delete_button, 3, 1, 1, 4);
+
+ gtk_widget_set_margin_left (row, 10);
+ gtk_widget_set_margin_right (row, 10);
+ gtk_widget_set_margin_top (row, 10);
+ gtk_widget_set_margin_bottom (row, 10);
+ gtk_widget_set_halign (row, GTK_ALIGN_FILL);
+
+ gtk_widget_show_all (row);
+ gtk_container_add (GTK_CONTAINER (page->routes_list), row);
+}
+
+static void
+add_empty_route_row (CEPageIP4 *page)
+{
+ add_route_row (page, "", "", "", 0);
+}
+
+static void
+add_routes_section (CEPageIP4 *page)
+{
+ GtkWidget *widget;
+ GtkWidget *frame;
+ GtkWidget *list;
+ GtkWidget *row;
+ GtkWidget *button;
+ GtkWidget *image;
+ gint i;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "routes_section"));
+
+ frame = gtk_frame_new (NULL);
+ gtk_container_add (GTK_CONTAINER (widget), frame);
+ page->routes_list = list = GTK_WIDGET (egg_list_box_new ());
+ egg_list_box_set_selection_mode (EGG_LIST_BOX (list), GTK_SELECTION_NONE);
+ egg_list_box_set_separator_funcs (EGG_LIST_BOX (list), update_separator, NULL, NULL);
+ egg_list_box_set_sort_func (EGG_LIST_BOX (list), sort_first_last, NULL, NULL);
+ gtk_container_add (GTK_CONTAINER (frame), list);
+ row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ g_object_set_data (G_OBJECT (row), "first", GINT_TO_POINTER (TRUE));
+ widget = gtk_label_new (_("Automatic"));
+ gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
+ gtk_widget_set_margin_top (widget, 10);
+ gtk_widget_set_margin_bottom (widget, 10);
+ gtk_widget_set_margin_left (widget, 10);
+ gtk_widget_set_margin_right (widget, 10);
+ gtk_widget_set_halign (widget, GTK_ALIGN_FILL);
+ gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
+ gtk_box_pack_start (GTK_BOX (row), widget, FALSE, FALSE, 0);
+ widget = gtk_switch_new ();
+ page->auto_routes = GTK_SWITCH (widget);
+ gtk_switch_set_active (GTK_SWITCH (widget), !nm_setting_ip4_config_get_ignore_auto_routes (page->setting));
+ gtk_widget_set_margin_top (widget, 10);
+ gtk_widget_set_margin_bottom (widget, 10);
+ gtk_widget_set_margin_left (widget, 10);
+ gtk_widget_set_margin_right (widget, 10);
+ gtk_widget_set_halign (widget, GTK_ALIGN_END);
+ gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
+ gtk_box_pack_start (GTK_BOX (row), widget, TRUE, TRUE, 0);
+ gtk_container_add (GTK_CONTAINER (list), row);
+ row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ g_object_set_data (G_OBJECT (row), "last", GINT_TO_POINTER (TRUE));
+ button = gtk_button_new ();
+ g_signal_connect_swapped (button, "clicked", G_CALLBACK (add_empty_route_row), page);
+ image = gtk_image_new_from_icon_name ("list-add-symbolic", GTK_ICON_SIZE_MENU);
+ gtk_button_set_image (GTK_BUTTON (button), image);
+ gtk_widget_set_margin_top (button, 10);
+ gtk_widget_set_margin_bottom (button, 10);
+ gtk_widget_set_margin_left (button, 10);
+ gtk_widget_set_margin_right (button, 10);
+ gtk_widget_set_halign (button, GTK_ALIGN_END);
+ gtk_box_pack_start (GTK_BOX (row), button, TRUE, TRUE, 0);
+ gtk_container_add (GTK_CONTAINER (list), row);
+ gtk_widget_show_all (frame);
+
+ for (i = 0; i < nm_setting_ip4_config_get_num_routes (page->setting); i++) {
+ NMIP4Route *route;
+ struct in_addr tmp_addr;
+ gchar address[INET_ADDRSTRLEN + 1];
+ gchar netmask[INET_ADDRSTRLEN + 1];
+ gchar gateway[INET_ADDRSTRLEN + 1];
+ gint metric;
+
+ route = nm_setting_ip4_config_get_route (page->setting, i);
+ if (!route)
+ continue;
+
+ tmp_addr.s_addr = nm_ip4_route_get_dest (route);
+ (void) inet_ntop (AF_INET, &tmp_addr, &address[0], sizeof (address));
+
+ tmp_addr.s_addr = nm_utils_ip4_prefix_to_netmask (nm_ip4_route_get_prefix (route));
+ (void) inet_ntop (AF_INET, &tmp_addr, &netmask[0], sizeof (netmask));
+
+ tmp_addr.s_addr = nm_ip4_route_get_next_hop (route);
+ (void) inet_ntop (AF_INET, &tmp_addr, &gateway[0], sizeof (gateway));
+ metric = nm_ip4_route_get_metric (route);
+ add_route_row (page, address, netmask, gateway, metric);
+ }
+ if (nm_setting_ip4_config_get_num_routes (page->setting) == 0)
+ add_empty_route_row (page);
+}
+
+static void
+free_addr (gpointer addr)
+{
+ g_array_free ((GArray *)addr, TRUE);
+}
+
+static void
+connect_ip4_page (CEPageIP4 *page)
+{
+ GtkWidget *content;
+ const gchar *str_method;
+ gboolean disabled;
+ GtkListStore *store;
+ GtkTreeIter iter;
+ guint method;
+
+ add_address_section (page);
+ add_dns_section (page);
+ add_routes_section (page);
+
+ page->enabled = GTK_SWITCH (gtk_builder_get_object (CE_PAGE (page)->builder, "switch_enable"));
+
+ str_method = nm_setting_ip4_config_get_method (page->setting);
+ disabled = g_strcmp0 (str_method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0;
+ gtk_switch_set_active (page->enabled, !disabled);
+ g_signal_connect_swapped (page->enabled, "notify::active", G_CALLBACK (ce_page_changed), page);
+ content = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "page_content"));
+ g_object_bind_property (page->enabled, "active",
+ content, "sensitive",
+ G_BINDING_SYNC_CREATE);
+
+ page->method = GTK_COMBO_BOX (gtk_builder_get_object (CE_PAGE (page)->builder, "combo_addresses"));
+
+ store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_UINT);
+ gtk_list_store_insert_with_values (store, &iter, -1,
+ METHOD_COL_NAME, _("Automatic (DHCP)"),
+ METHOD_COL_METHOD, IP4_METHOD_AUTO,
+ -1);
+ gtk_list_store_insert_with_values (store, &iter, -1,
+ METHOD_COL_NAME, _("Manual"),
+ METHOD_COL_METHOD, IP4_METHOD_MANUAL,
+ -1);
+ gtk_list_store_insert_with_values (store, &iter, -1,
+ METHOD_COL_NAME, _("Link-Local Only"),
+ METHOD_COL_METHOD, IP4_METHOD_LINK_LOCAL,
+ -1);
+
+ gtk_combo_box_set_model (page->method, GTK_TREE_MODEL (store));
+
+ method = IP4_METHOD_AUTO;
+ if (g_strcmp0 (str_method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL) == 0) {
+ method = IP4_METHOD_LINK_LOCAL;
+ } else if (g_strcmp0 (str_method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0) {
+ method = IP4_METHOD_MANUAL;
+ } else if (g_strcmp0 (str_method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0) {
+ method = IP4_METHOD_SHARED;
+ } else if (g_strcmp0 (str_method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0) {
+ method = IP4_METHOD_DISABLED;
+ }
+
+ page->never_default = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "never_default_check"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (page->never_default),
+ nm_setting_ip4_config_get_never_default (page->setting));
+
+ g_signal_connect (page->method, "changed", G_CALLBACK (method_changed), page);
+ if (method != IP4_METHOD_SHARED && method != IP4_METHOD_DISABLED)
+ gtk_combo_box_set_active (page->method, method);
+}
+
+static gboolean
+parse_netmask (const char *str, guint32 *prefix)
+{
+ struct in_addr tmp_addr;
+ glong tmp_prefix;
+
+ errno = 0;
+
+ /* Is it a prefix? */
+ if (!strchr (str, '.')) {
+ tmp_prefix = strtol (str, NULL, 10);
+ if (!errno && tmp_prefix >= 0 && tmp_prefix <= 32) {
+ *prefix = tmp_prefix;
+ return TRUE;
+ }
+ }
+
+ /* Is it a netmask? */
+ if (inet_pton (AF_INET, str, &tmp_addr) > 0) {
+ *prefix = nm_utils_ip4_netmask_to_prefix (tmp_addr.s_addr);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+ui_to_setting (CEPageIP4 *page)
+{
+ gboolean valid = FALSE;
+ const gchar *method;
+ gboolean ignore_auto_dns;
+ gboolean ignore_auto_routes;
+ gboolean never_default;
+ GPtrArray *addresses = NULL;
+ GArray *dns_servers = NULL;
+ GPtrArray *routes = NULL;
+ GList *children, *l;
+
+ if (!gtk_switch_get_active (page->enabled)) {
+ method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
+ } else {
+ switch (gtk_combo_box_get_active (page->method)) {
+ case IP4_METHOD_MANUAL:
+ method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL;
+ break;
+ case IP4_METHOD_LINK_LOCAL:
+ method = NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL;
+ break;
+ default:
+ case IP4_METHOD_AUTO:
+ method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
+ break;
+ }
+ }
+
+ addresses = g_ptr_array_new_with_free_func (free_addr);
+ children = gtk_container_get_children (GTK_CONTAINER (page->address_list));
+ for (l = children; l; l = l->next) {
+ GtkWidget *row = l->data;
+ GtkEntry *entry;
+ const gchar *text_address;
+ const gchar *text_netmask;
+ const gchar *text_gateway;
+ struct in_addr tmp_addr;
+ struct in_addr tmp_gateway = { 0 };
+ guint32 prefix;
+ guint32 empty_val = 0;
+ GArray *addr;
+
+ entry = GTK_ENTRY (g_object_get_data (G_OBJECT (row), "address"));
+ if (!entry)
+ continue;
+
+ text_address = gtk_entry_get_text (entry);
+ text_netmask = gtk_entry_get_text (GTK_ENTRY (g_object_get_data (G_OBJECT (row), "network")));
+ text_gateway = gtk_entry_get_text (GTK_ENTRY (g_object_get_data (G_OBJECT (row), "gateway")));
+
+ if (!*text_address && !*text_netmask && !*text_gateway) {
+ /* ignore empty rows */
+ continue;
+ }
+
+ if (inet_pton (AF_INET, text_address, &tmp_addr) <= 0) {
+ g_warning ("IPv4 address %s missing or invalid", text_address);
+ goto out;
+ }
+
+
+ if (!parse_netmask (text_netmask, &prefix)) {
+ g_warning ("IPv4 prefix %s is invalid", text_netmask);
+ goto out;
+ }
+
+ if (text_gateway && inet_pton (AF_INET, text_gateway, &tmp_gateway) <= 0) {
+ g_warning ("IPv4 gateway %s is invalid", text_gateway);
+ goto out;
+ }
+
+ addr = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 3);
+ g_array_append_val (addr, tmp_addr.s_addr);
+ g_array_append_val (addr, prefix);
+ if (tmp_gateway.s_addr)
+ g_array_append_val (addr, tmp_gateway.s_addr);
+ else
+ g_array_append_val (addr, empty_val);
+ g_ptr_array_add (addresses, addr);
+ }
+ g_list_free (children);
+
+ if (addresses->len == 0) {
+ g_ptr_array_free (addresses, TRUE);
+ addresses = NULL;
+ }
+
+ dns_servers = g_array_new (FALSE, FALSE, sizeof (guint));
+ children = gtk_container_get_children (GTK_CONTAINER (page->dns_list));
+ for (l = children; l; l = l->next) {
+ GtkWidget *row = l->data;
+ GtkEntry *entry;
+ const gchar *text;
+ struct in_addr tmp_addr;
+
+ entry = GTK_ENTRY (g_object_get_data (G_OBJECT (row), "address"));
+ if (!entry)
+ continue;
+
+ text = gtk_entry_get_text (entry);
+ if (!*text) {
+ /* ignore empty rows */
+ continue;
+ }
+
+ if (inet_pton (AF_INET, text, &tmp_addr) <= 0) {
+ g_warning ("IPv4 dns server %s invalid", text);
+ goto out;
+ }
+
+ g_array_append_val (dns_servers, tmp_addr.s_addr);
+ }
+ g_list_free (children);
+
+
+ routes = g_ptr_array_new_with_free_func (free_addr);
+ children = gtk_container_get_children (GTK_CONTAINER (page->routes_list));
+ for (l = children; l; l = l->next) {
+ GtkWidget *row = l->data;
+ GtkEntry *entry;
+ const gchar *text_address;
+ const gchar *text_netmask;
+ const gchar *text_gateway;
+ const gchar *text_metric;
+ struct in_addr tmp_addr = { 0 };
+ guint32 address, netmask, gateway, metric;
+ GArray *route;
+
+ entry = GTK_ENTRY (g_object_get_data (G_OBJECT (row), "address"));
+ if (!entry)
+ continue;
+
+ text_address = gtk_entry_get_text (entry);
+ text_netmask = gtk_entry_get_text (GTK_ENTRY (g_object_get_data (G_OBJECT (row), "netmask")));
+ text_gateway = gtk_entry_get_text (GTK_ENTRY (g_object_get_data (G_OBJECT (row), "gateway")));
+ text_metric = gtk_entry_get_text (GTK_ENTRY (g_object_get_data (G_OBJECT (row), "metric")));
+
+ if (!*text_address && !*text_netmask && !*text_gateway && !*text_metric) {
+ /* ignore empty rows */
+ continue;
+ }
+
+ if (inet_pton (AF_INET, text_address, &tmp_addr) <= 0) {
+ g_warning ("IPv4 route address %s invalid", text_address);
+ goto out;
+ }
+ address = tmp_addr.s_addr;
+
+ if (!parse_netmask (text_netmask, &netmask)) {
+ g_warning ("IPv4 route netmask %s invalid", text_netmask);
+ goto out;
+ }
+
+ if (inet_pton (AF_INET, text_gateway, &tmp_addr) <= 0) {
+ g_warning ("IPv4 route gateway %s invalid", text_gateway);
+ goto out;
+ }
+ gateway = tmp_addr.s_addr;
+
+ metric = 0;
+ if (*text_metric) {
+ errno = 0;
+ metric = strtoul (text_metric, NULL, 10);
+ if (errno) {
+ g_warning ("IPv4 route metric %s invalid", text_metric);
+ goto out;
+ }
+ }
+
+ route = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 4);
+ g_array_append_val (route, address);
+ g_array_append_val (route, netmask);
+ g_array_append_val (route, gateway);
+ g_array_append_val (route, metric);
+ g_ptr_array_add (routes, route);
+ }
+ g_list_free (children);
+
+ if (routes->len == 0) {
+ g_ptr_array_free (routes, TRUE);
+ routes = NULL;
+ }
+ ignore_auto_dns = !gtk_switch_get_active (page->auto_dns);
+ ignore_auto_routes = !gtk_switch_get_active (page->auto_routes);
+ never_default = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (page->never_default));
+
+ g_object_set (page->setting,
+ NM_SETTING_IP4_CONFIG_METHOD, method,
+ NM_SETTING_IP4_CONFIG_ADDRESSES, addresses,
+ NM_SETTING_IP4_CONFIG_DNS, dns_servers,
+ NM_SETTING_IP4_CONFIG_ROUTES, routes,
+ NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS, ignore_auto_dns,
+ NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES, ignore_auto_routes,
+ NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, never_default,
+ NULL);
+
+ valid = TRUE;
+
+out:
+ if (addresses)
+ g_ptr_array_free (addresses, TRUE);
+
+ if (dns_servers)
+ g_array_free (dns_servers, TRUE);
+
+ if (routes)
+ g_ptr_array_free (routes, TRUE);
+
+ return valid;
+}
+
+static gboolean
+validate (CEPage *page,
+ NMConnection *connection,
+ GError **error)
+{
+ if (!ui_to_setting (CE_PAGE_IP4 (page)))
+ return FALSE;
+
+ return nm_setting_verify (NM_SETTING (CE_PAGE_IP4 (page)->setting), NULL, error);
+}
+
+static void
+ce_page_ip4_init (CEPageIP4 *page)
+{
+}
+
+static void
+ce_page_ip4_class_init (CEPageIP4Class *class)
+{
+ CEPageClass *page_class= CE_PAGE_CLASS (class);
+
+ page_class->validate = validate;
+}
+
+CEPage *
+ce_page_ip4_new (NMConnection *connection,
+ NMClient *client,
+ NMRemoteSettings *settings)
+{
+ CEPageIP4 *page;
+
+ page = CE_PAGE_IP4 (ce_page_new (CE_TYPE_PAGE_IP4,
+ connection,
+ client,
+ settings,
+ "/org/gnome/control-center/network/ip4-page.ui",
+ _("IPv4")));
+
+ page->setting = nm_connection_get_setting_ip4_config (connection);
+
+ connect_ip4_page (page);
+
+ return CE_PAGE (page);
+}
diff --git a/panels/network/connection-editor/ce-page-ip4.h b/panels/network/connection-editor/ce-page-ip4.h
new file mode 100644
index 0000000..ca38d3e
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-ip4.h
@@ -0,0 +1,72 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more ip4.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __CE_PAGE_IP4_H
+#define __CE_PAGE_IP4_H
+
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+#include "ce-page.h"
+
+G_BEGIN_DECLS
+
+#define CE_TYPE_PAGE_IP4 (ce_page_ip4_get_type ())
+#define CE_PAGE_IP4(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CE_TYPE_PAGE_IP4, CEPageIP4))
+#define CE_PAGE_IP4_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CE_TYPE_PAGE_IP4, CEPageIP4Class))
+#define CE_IS_PAGE_IP4(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CE_TYPE_PAGE_IP4))
+#define CE_IS_PAGE_IP4_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CE_TYPE_PAGE_IP4))
+#define CE_PAGE_IP4_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CE_TYPE_PAGE_IP4, CEPageIP4Class))
+
+typedef struct _CEPageIP4 CEPageIP4;
+typedef struct _CEPageIP4Class CEPageIP4Class;
+
+struct _CEPageIP4
+{
+ CEPage parent;
+
+ NMSettingIP4Config *setting;
+
+ GtkSwitch *enabled;
+ GtkComboBox *method;
+ GtkWidget *address_list;
+ GtkSwitch *auto_dns;
+ GtkWidget *dns_list;
+ GtkSwitch *auto_routes;
+ GtkWidget *routes_list;
+ GtkWidget *never_default;
+};
+
+struct _CEPageIP4Class
+{
+ CEPageClass parent_class;
+};
+
+GType ce_page_ip4_get_type (void);
+
+CEPage *ce_page_ip4_new (NMConnection *connection,
+ NMClient *client,
+ NMRemoteSettings *settings);
+
+G_END_DECLS
+
+#endif /* __CE_PAGE_IP4_H */
+
diff --git a/panels/network/connection-editor/ce-page-ip6.c b/panels/network/connection-editor/ce-page-ip6.c
new file mode 100644
index 0000000..9c54430
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-ip6.c
@@ -0,0 +1,862 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <glib-object.h>
+#include <glib/gi18n.h>
+
+#include "ce-page-ip6.h"
+#include <nm-utils.h>
+
+#include "egg-list-box/egg-list-box.h"
+
+G_DEFINE_TYPE (CEPageIP6, ce_page_ip6, CE_TYPE_PAGE)
+
+enum {
+ METHOD_COL_NAME,
+ METHOD_COL_METHOD
+};
+
+enum {
+ IP6_METHOD_AUTO,
+ IP6_METHOD_DHCP,
+ IP6_METHOD_MANUAL,
+ IP6_METHOD_LINK_LOCAL,
+ IP6_METHOD_SHARED,
+ IP6_METHOD_IGNORE
+};
+
+static void
+method_changed (GtkComboBox *combo, CEPageIP6 *page)
+{
+ gboolean addr_enabled;
+ gboolean dns_enabled;
+ gboolean routes_enabled;
+ guint method;
+
+ method = gtk_combo_box_get_active (combo);
+ switch (method) {
+ case IP6_METHOD_AUTO:
+ case IP6_METHOD_DHCP:
+ addr_enabled = FALSE;
+ dns_enabled = TRUE;
+ routes_enabled = TRUE;
+ break;
+ case IP6_METHOD_MANUAL:
+ addr_enabled = TRUE;
+ dns_enabled = TRUE;
+ routes_enabled = TRUE;
+ break;
+ case IP6_METHOD_LINK_LOCAL:
+ default:
+ addr_enabled = FALSE;
+ dns_enabled = FALSE;
+ routes_enabled = FALSE;
+ break;
+ }
+
+ gtk_widget_set_sensitive (page->address_list, addr_enabled);
+ gtk_widget_set_sensitive (page->dns_list, dns_enabled);
+ gtk_widget_set_sensitive (page->routes_list, routes_enabled);
+ gtk_widget_set_sensitive (page->never_default, routes_enabled);
+
+ ce_page_changed (CE_PAGE (page));
+}
+
+static void
+update_separator (GtkWidget **separator,
+ GtkWidget *child,
+ GtkWidget *before,
+ gpointer user_data)
+{
+ if (before == NULL)
+ return;
+
+ if (*separator == NULL)
+ {
+ *separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
+ gtk_widget_show (*separator);
+ g_object_ref_sink (*separator);
+ }
+}
+
+static void
+remove_row (GtkButton *button, CEPageIP6 *page)
+{
+ GtkWidget *row;
+ GtkWidget *list;
+
+ row = gtk_widget_get_parent (GTK_WIDGET (button));
+ list = gtk_widget_get_parent (row);
+
+ gtk_container_remove (GTK_CONTAINER (list), row);
+
+ ce_page_changed (CE_PAGE (page));
+}
+
+static gint
+sort_first_last (gconstpointer a, gconstpointer b, gpointer data)
+{
+ gboolean afirst, bfirst, alast, blast;
+
+ afirst = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (a), "first"));
+ bfirst = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (b), "first"));
+ alast = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (a), "last"));
+ blast = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (b), "last"));
+
+ if (afirst)
+ return -1;
+ if (bfirst)
+ return 1;
+ if (alast)
+ return 1;
+ if (blast)
+ return -1;
+
+ return 0;
+}
+
+static void
+add_address_row (CEPageIP6 *page,
+ const gchar *address,
+ const gchar *network,
+ const gchar *gateway)
+{
+ GtkWidget *row;
+ GtkWidget *widget;
+ GtkWidget *delete_button;
+ GtkWidget *image;
+
+ row = gtk_grid_new ();
+ widget = gtk_label_new (_("Address"));
+ gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+ gtk_grid_attach (GTK_GRID (row), widget, 1, 1, 1, 1);
+ widget = gtk_label_new (_("Prefix"));
+ gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+ gtk_grid_attach (GTK_GRID (row), widget, 1, 2, 1, 1);
+ widget = gtk_label_new (_("Gateway"));
+ gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+ gtk_grid_attach (GTK_GRID (row), widget, 1, 3, 1, 1);
+ widget = gtk_entry_new ();
+ g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+ g_object_set_data (G_OBJECT (row), "address", widget);
+ gtk_entry_set_text (GTK_ENTRY (widget), address);
+ gtk_widget_set_margin_left (widget, 10);
+ gtk_widget_set_margin_right (widget, 10);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_grid_attach (GTK_GRID (row), widget, 2, 1, 1, 1);
+ widget = gtk_entry_new ();
+ g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+ g_object_set_data (G_OBJECT (row), "prefix", widget);
+ gtk_entry_set_text (GTK_ENTRY (widget), network);
+ gtk_widget_set_margin_left (widget, 10);
+ gtk_widget_set_margin_right (widget, 10);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_grid_attach (GTK_GRID (row), widget, 2, 2, 1, 1);
+ widget = gtk_entry_new ();
+ g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+ g_object_set_data (G_OBJECT (row), "gateway", widget);
+ gtk_entry_set_text (GTK_ENTRY (widget), gateway);
+ gtk_widget_set_margin_left (widget, 10);
+ gtk_widget_set_margin_right (widget, 10);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_grid_attach (GTK_GRID (row), widget, 2, 3, 1, 1);
+
+ delete_button = gtk_button_new ();
+ g_signal_connect (delete_button, "clicked", G_CALLBACK (remove_row), page);
+ image = gtk_image_new_from_icon_name ("user-trash-symbolic", GTK_ICON_SIZE_MENU);
+ gtk_button_set_image (GTK_BUTTON (delete_button), image);
+ gtk_grid_attach (GTK_GRID (row), delete_button, 3, 2, 1, 1);
+
+ gtk_widget_set_margin_left (row, 10);
+ gtk_widget_set_margin_right (row, 10);
+ gtk_widget_set_margin_top (row, 10);
+ gtk_widget_set_margin_bottom (row, 10);
+ gtk_widget_set_halign (row, GTK_ALIGN_FILL);
+ gtk_widget_show_all (row);
+ gtk_container_add (GTK_CONTAINER (page->address_list), row);
+}
+
+static void
+add_empty_address_row (CEPageIP6 *page)
+{
+ add_address_row (page, "", "", "");
+}
+
+static void
+add_address_section (CEPageIP6 *page)
+{
+ GtkWidget *widget;
+ GtkWidget *frame;
+ GtkWidget *list;
+ GtkWidget *row;
+ GtkWidget *button;
+ GtkWidget *image;
+ gint i;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "address_section"));
+
+ frame = gtk_frame_new (NULL);
+ gtk_container_add (GTK_CONTAINER (widget), frame);
+ page->address_list = list = GTK_WIDGET (egg_list_box_new ());
+ egg_list_box_set_selection_mode (EGG_LIST_BOX (list), GTK_SELECTION_NONE);
+ egg_list_box_set_separator_funcs (EGG_LIST_BOX (list), update_separator, NULL, NULL);
+ egg_list_box_set_sort_func (EGG_LIST_BOX (list), sort_first_last, NULL, NULL);
+ gtk_container_add (GTK_CONTAINER (frame), list);
+ row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ g_object_set_data (G_OBJECT (row), "last", GINT_TO_POINTER (TRUE));
+ button = gtk_button_new ();
+ g_signal_connect_swapped (button, "clicked", G_CALLBACK (add_empty_address_row), page);
+ image = gtk_image_new_from_icon_name ("list-add-symbolic", GTK_ICON_SIZE_MENU);
+ gtk_button_set_image (GTK_BUTTON (button), image);
+ gtk_widget_set_margin_top (button, 10);
+ gtk_widget_set_margin_bottom (button, 10);
+ gtk_widget_set_margin_left (button, 10);
+ gtk_widget_set_margin_right (button, 10);
+ gtk_widget_set_halign (button, GTK_ALIGN_END);
+ gtk_box_pack_start (GTK_BOX (row), button, TRUE, TRUE, 0);
+ gtk_container_add (GTK_CONTAINER (list), row);
+ gtk_widget_show_all (frame);
+
+ for (i = 0; i < nm_setting_ip6_config_get_num_addresses (page->setting); i++) {
+ NMIP6Address *addr;
+ const struct in6_addr *tmp_addr;
+ gchar address[INET6_ADDRSTRLEN + 1];
+ gchar network[INET6_ADDRSTRLEN + 1];
+ gchar gateway[INET6_ADDRSTRLEN + 1];
+
+ addr = nm_setting_ip6_config_get_address (page->setting, i);
+ if (!addr)
+ continue;
+
+ tmp_addr = nm_ip6_address_get_address (addr);
+ (void) inet_ntop (AF_INET6, tmp_addr, &address[0], sizeof (address));
+
+ snprintf (network, sizeof (network), "%u", nm_ip6_address_get_prefix (addr));
+
+ tmp_addr = nm_ip6_address_get_gateway (addr);
+ if (tmp_addr && !IN6_IS_ADDR_UNSPECIFIED (tmp_addr))
+ (void) inet_ntop (AF_INET6, tmp_addr, &gateway[0], sizeof (gateway));
+ else
+ gateway[0] = '\0';
+
+ add_address_row (page, address, network, gateway);
+ }
+ if (nm_setting_ip6_config_get_num_addresses (page->setting) == 0)
+ add_empty_address_row (page);
+}
+
+static void
+add_dns_row (CEPageIP6 *page,
+ const gchar *address)
+{
+ GtkWidget *row;
+ GtkWidget *widget;
+ GtkWidget *delete_button;
+ GtkWidget *image;
+
+ row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ widget = gtk_label_new (_("Address"));
+ gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+ gtk_box_pack_start (GTK_BOX (row), widget, FALSE, FALSE, 0);
+ widget = gtk_entry_new ();
+ g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+ g_object_set_data (G_OBJECT (row), "address", widget);
+ gtk_entry_set_text (GTK_ENTRY (widget), address);
+ gtk_widget_set_margin_left (widget, 10);
+ gtk_widget_set_margin_right (widget, 10);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_box_pack_start (GTK_BOX (row), widget, TRUE, TRUE, 0);
+
+ delete_button = gtk_button_new ();
+ g_signal_connect (delete_button, "clicked", G_CALLBACK (remove_row), page);
+ image = gtk_image_new_from_icon_name ("user-trash-symbolic", GTK_ICON_SIZE_MENU);
+ gtk_button_set_image (GTK_BUTTON (delete_button), image);
+ gtk_box_pack_start (GTK_BOX (row), delete_button, FALSE, FALSE, 0);
+
+ gtk_widget_set_margin_left (row, 10);
+ gtk_widget_set_margin_right (row, 10);
+ gtk_widget_set_margin_top (row, 10);
+ gtk_widget_set_margin_bottom (row, 10);
+ gtk_widget_set_halign (row, GTK_ALIGN_FILL);
+ gtk_widget_show_all (row);
+ gtk_container_add (GTK_CONTAINER (page->dns_list), row);
+}
+
+static void
+add_empty_dns_row (CEPageIP6 *page)
+{
+ add_dns_row (page, "");
+}
+
+static void
+add_dns_section (CEPageIP6 *page)
+{
+ GtkWidget *widget;
+ GtkWidget *frame;
+ GtkWidget *list;
+ GtkWidget *row;
+ GtkWidget *button;
+ GtkWidget *image;
+ gint i;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "dns_section"));
+
+ frame = gtk_frame_new (NULL);
+ gtk_container_add (GTK_CONTAINER (widget), frame);
+ page->dns_list = list = GTK_WIDGET (egg_list_box_new ());
+ egg_list_box_set_selection_mode (EGG_LIST_BOX (list), GTK_SELECTION_NONE);
+ egg_list_box_set_separator_funcs (EGG_LIST_BOX (list), update_separator, NULL, NULL);
+ egg_list_box_set_sort_func (EGG_LIST_BOX (list), sort_first_last, NULL, NULL);
+ gtk_container_add (GTK_CONTAINER (frame), list);
+ row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ g_object_set_data (G_OBJECT (row), "first", GINT_TO_POINTER (TRUE));
+ widget = gtk_label_new (_("Automatic"));
+ gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
+ gtk_widget_set_margin_top (widget, 10);
+ gtk_widget_set_margin_bottom (widget, 10);
+ gtk_widget_set_margin_left (widget, 10);
+ gtk_widget_set_margin_right (widget, 10);
+ gtk_widget_set_halign (widget, GTK_ALIGN_FILL);
+ gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
+ gtk_box_pack_start (GTK_BOX (row), widget, FALSE, FALSE, 0);
+ widget = gtk_switch_new ();
+ page->auto_dns = GTK_SWITCH (widget);
+ gtk_switch_set_active (page->auto_dns, !nm_setting_ip6_config_get_ignore_auto_dns (page->setting));
+ gtk_widget_set_margin_top (widget, 10);
+ gtk_widget_set_margin_bottom (widget, 10);
+ gtk_widget_set_margin_left (widget, 10);
+ gtk_widget_set_margin_right (widget, 10);
+ gtk_widget_set_halign (widget, GTK_ALIGN_END);
+ gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
+ gtk_box_pack_start (GTK_BOX (row), widget, TRUE, TRUE, 0);
+ gtk_container_add (GTK_CONTAINER (list), row);
+
+ row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ g_object_set_data (G_OBJECT (row), "last", GINT_TO_POINTER (TRUE));
+ button = gtk_button_new ();
+ g_signal_connect_swapped (button, "clicked", G_CALLBACK (add_empty_dns_row), page);
+ image = gtk_image_new_from_icon_name ("list-add-symbolic", GTK_ICON_SIZE_MENU);
+ gtk_button_set_image (GTK_BUTTON (button), image);
+ gtk_widget_set_margin_top (button, 10);
+ gtk_widget_set_margin_bottom (button, 10);
+ gtk_widget_set_margin_left (button, 10);
+ gtk_widget_set_margin_right (button, 10);
+ gtk_widget_set_halign (button, GTK_ALIGN_END);
+ gtk_box_pack_start (GTK_BOX (row), button, TRUE, TRUE, 0);
+ gtk_container_add (GTK_CONTAINER (list), row);
+ gtk_widget_show_all (frame);
+
+ for (i = 0; i < nm_setting_ip6_config_get_num_dns (page->setting); i++) {
+ const struct in6_addr *tmp_addr;
+ gchar address[INET6_ADDRSTRLEN + 1];
+
+ tmp_addr = nm_setting_ip6_config_get_dns (page->setting, i);
+ (void) inet_ntop (AF_INET, tmp_addr, &address[0], sizeof (address));
+
+ add_dns_row (page, address);
+ }
+ if (nm_setting_ip6_config_get_num_dns (page->setting) == 0)
+ add_empty_dns_row (page);
+}
+
+static void
+add_route_row (CEPageIP6 *page,
+ const gchar *address,
+ gint prefix,
+ const gchar *gateway,
+ gint metric)
+{
+ GtkWidget *row;
+ GtkWidget *widget;
+ GtkWidget *delete_button;
+ GtkWidget *image;
+
+ row = gtk_grid_new ();
+ widget = gtk_label_new (_("Address"));
+ gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+ gtk_grid_attach (GTK_GRID (row), widget, 1, 1, 1, 1);
+ widget = gtk_label_new (_("Prefix"));
+ gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+ gtk_grid_attach (GTK_GRID (row), widget, 1, 2, 1, 1);
+ widget = gtk_label_new (_("Gateway"));
+ gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+ gtk_grid_attach (GTK_GRID (row), widget, 1, 3, 1, 1);
+ widget = gtk_label_new (_("Metric"));
+ gtk_misc_set_alignment (GTK_MISC (widget), 1, 0.5);
+ gtk_grid_attach (GTK_GRID (row), widget, 1, 4, 1, 1);
+ widget = gtk_entry_new ();
+ g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+ g_object_set_data (G_OBJECT (row), "address", widget);
+ gtk_entry_set_text (GTK_ENTRY (widget), address);
+ gtk_widget_set_margin_left (widget, 10);
+ gtk_widget_set_margin_right (widget, 10);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_grid_attach (GTK_GRID (row), widget, 2, 1, 1, 1);
+ widget = gtk_entry_new ();
+ g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+ g_object_set_data (G_OBJECT (row), "prefix", widget);
+ if (prefix > 0) {
+ gchar *s = g_strdup_printf ("%d", prefix);
+ gtk_entry_set_text (GTK_ENTRY (widget), s);
+ g_free (s);
+ }
+ gtk_widget_set_margin_left (widget, 10);
+ gtk_widget_set_margin_right (widget, 10);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_grid_attach (GTK_GRID (row), widget, 2, 2, 1, 1);
+ widget = gtk_entry_new ();
+ g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+ g_object_set_data (G_OBJECT (row), "gateway", widget);
+ gtk_entry_set_text (GTK_ENTRY (widget), gateway);
+ gtk_widget_set_margin_left (widget, 10);
+ gtk_widget_set_margin_right (widget, 10);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_grid_attach (GTK_GRID (row), widget, 2, 3, 1, 1);
+ widget = gtk_entry_new ();
+ g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+ g_object_set_data (G_OBJECT (row), "metric", widget);
+ if (metric > 0) {
+ gchar *s = g_strdup_printf ("%d", metric);
+ gtk_entry_set_text (GTK_ENTRY (widget), s);
+ g_free (s);
+ }
+ gtk_widget_set_margin_left (widget, 10);
+ gtk_widget_set_margin_right (widget, 10);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_grid_attach (GTK_GRID (row), widget, 2, 4, 1, 1);
+
+ delete_button = gtk_button_new ();
+ g_signal_connect (delete_button, "clicked", G_CALLBACK (remove_row), page);
+ image = gtk_image_new_from_icon_name ("user-trash-symbolic", GTK_ICON_SIZE_MENU);
+ gtk_button_set_image (GTK_BUTTON (delete_button), image);
+ gtk_widget_set_halign (delete_button, GTK_ALIGN_CENTER);
+ gtk_widget_set_valign (delete_button, GTK_ALIGN_CENTER);
+ gtk_grid_attach (GTK_GRID (row), delete_button, 3, 1, 1, 4);
+
+ gtk_widget_set_margin_left (row, 10);
+ gtk_widget_set_margin_right (row, 10);
+ gtk_widget_set_margin_top (row, 10);
+ gtk_widget_set_margin_bottom (row, 10);
+ gtk_widget_set_halign (row, GTK_ALIGN_FILL);
+
+ gtk_widget_show_all (row);
+ gtk_container_add (GTK_CONTAINER (page->routes_list), row);
+}
+
+static void
+add_empty_route_row (CEPageIP6 *page)
+{
+ add_route_row (page, "", 0, "", 0);
+}
+
+static void
+add_routes_section (CEPageIP6 *page)
+{
+ GtkWidget *widget;
+ GtkWidget *frame;
+ GtkWidget *list;
+ GtkWidget *row;
+ GtkWidget *button;
+ GtkWidget *image;
+ gint i;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "routes_section"));
+
+ frame = gtk_frame_new (NULL);
+ gtk_container_add (GTK_CONTAINER (widget), frame);
+ page->routes_list = list = GTK_WIDGET (egg_list_box_new ());
+ egg_list_box_set_selection_mode (EGG_LIST_BOX (list), GTK_SELECTION_NONE);
+ egg_list_box_set_separator_funcs (EGG_LIST_BOX (list), update_separator, NULL, NULL);
+ egg_list_box_set_sort_func (EGG_LIST_BOX (list), sort_first_last, NULL, NULL);
+ gtk_container_add (GTK_CONTAINER (frame), list);
+ row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ g_object_set_data (G_OBJECT (row), "first", GINT_TO_POINTER (TRUE));
+ widget = gtk_label_new (_("Automatic"));
+ gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
+ gtk_widget_set_margin_top (widget, 10);
+ gtk_widget_set_margin_bottom (widget, 10);
+ gtk_widget_set_margin_left (widget, 10);
+ gtk_widget_set_margin_right (widget, 10);
+ gtk_widget_set_halign (widget, GTK_ALIGN_FILL);
+ gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
+ gtk_box_pack_start (GTK_BOX (row), widget, FALSE, FALSE, 0);
+ widget = gtk_switch_new ();
+ page->auto_routes = GTK_SWITCH (widget);
+ gtk_switch_set_active (GTK_SWITCH (widget), !nm_setting_ip6_config_get_ignore_auto_routes (page->setting));
+ gtk_widget_set_margin_top (widget, 10);
+ gtk_widget_set_margin_bottom (widget, 10);
+ gtk_widget_set_margin_left (widget, 10);
+ gtk_widget_set_margin_right (widget, 10);
+ gtk_widget_set_halign (widget, GTK_ALIGN_END);
+ gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
+ gtk_box_pack_start (GTK_BOX (row), widget, TRUE, TRUE, 0);
+ gtk_container_add (GTK_CONTAINER (list), row);
+ row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ g_object_set_data (G_OBJECT (row), "last", GINT_TO_POINTER (TRUE));
+ button = gtk_button_new ();
+ g_signal_connect_swapped (button, "clicked", G_CALLBACK (add_empty_route_row), page);
+ image = gtk_image_new_from_icon_name ("list-add-symbolic", GTK_ICON_SIZE_MENU);
+ gtk_button_set_image (GTK_BUTTON (button), image);
+ gtk_widget_set_margin_top (button, 10);
+ gtk_widget_set_margin_bottom (button, 10);
+ gtk_widget_set_margin_left (button, 10);
+ gtk_widget_set_margin_right (button, 10);
+ gtk_widget_set_halign (button, GTK_ALIGN_END);
+ gtk_box_pack_start (GTK_BOX (row), button, TRUE, TRUE, 0);
+ gtk_container_add (GTK_CONTAINER (list), row);
+ gtk_widget_show_all (frame);
+
+ for (i = 0; i < nm_setting_ip6_config_get_num_routes (page->setting); i++) {
+ NMIP6Route *route;
+ const struct in6_addr *tmp_addr;
+ gchar address[INET6_ADDRSTRLEN + 1];
+ gchar gateway[INET6_ADDRSTRLEN + 1];
+ gint prefix, metric;
+
+ route = nm_setting_ip6_config_get_route (page->setting, i);
+ if (!route)
+ continue;
+
+ tmp_addr = nm_ip6_route_get_dest (route);
+ (void) inet_ntop (AF_INET6, tmp_addr, &address[0], sizeof (address));
+ prefix = nm_ip6_route_get_prefix (route);
+ tmp_addr = nm_ip6_route_get_next_hop (route);
+ (void) inet_ntop (AF_INET6, tmp_addr, &gateway[0], sizeof (gateway));
+ metric = nm_ip6_route_get_metric (route);
+ add_route_row (page, address, prefix, gateway, metric);
+ }
+ if (nm_setting_ip6_config_get_num_routes (page->setting) == 0)
+ add_empty_route_row (page);
+}
+
+static void
+connect_ip6_page (CEPageIP6 *page)
+{
+ GtkWidget *content;
+ const gchar *str_method;
+ gboolean disabled;
+ GtkListStore *store;
+ GtkTreeIter iter;
+ guint method;
+
+ add_address_section (page);
+ add_dns_section (page);
+ add_routes_section (page);
+
+ page->enabled = GTK_SWITCH (gtk_builder_get_object (CE_PAGE (page)->builder, "switch_enable"));
+
+ str_method = nm_setting_ip6_config_get_method (page->setting);
+ disabled = g_strcmp0 (str_method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0;
+ gtk_switch_set_active (page->enabled, !disabled);
+ g_signal_connect_swapped (page->enabled, "notify::active", G_CALLBACK (ce_page_changed), page);
+ content = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "page_content"));
+ g_object_bind_property (page->enabled, "active",
+ content, "sensitive",
+ G_BINDING_SYNC_CREATE);
+
+ page->method = GTK_COMBO_BOX (gtk_builder_get_object (CE_PAGE (page)->builder, "combo_addresses"));
+
+ store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_UINT);
+ gtk_list_store_insert_with_values (store, &iter, -1,
+ METHOD_COL_NAME, _("Automatic"),
+ METHOD_COL_METHOD, IP6_METHOD_AUTO,
+ -1);
+ gtk_list_store_insert_with_values (store, &iter, -1,
+ METHOD_COL_NAME, _("Automatic, DHCP only"),
+ METHOD_COL_METHOD, IP6_METHOD_DHCP,
+ -1);
+ gtk_list_store_insert_with_values (store, &iter, -1,
+ METHOD_COL_NAME, _("Manual"),
+ METHOD_COL_METHOD, IP6_METHOD_MANUAL,
+ -1);
+ gtk_list_store_insert_with_values (store, &iter, -1,
+ METHOD_COL_NAME, _("Link-Local Only"),
+ METHOD_COL_METHOD, IP6_METHOD_LINK_LOCAL,
+ -1);
+
+ gtk_combo_box_set_model (page->method, GTK_TREE_MODEL (store));
+
+ method = IP6_METHOD_AUTO;
+ if (g_strcmp0 (str_method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0) {
+ method = IP6_METHOD_DHCP;
+ } else if (g_strcmp0 (str_method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0) {
+ method = IP6_METHOD_LINK_LOCAL;
+ } else if (g_strcmp0 (str_method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL) == 0) {
+ method = IP6_METHOD_MANUAL;
+ } else if (g_strcmp0 (str_method, NM_SETTING_IP6_CONFIG_METHOD_SHARED) == 0) {
+ method = IP6_METHOD_SHARED;
+ } else if (g_strcmp0 (str_method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0) {
+ method = IP6_METHOD_IGNORE;
+ }
+
+ page->never_default = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "never_default_check"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (page->never_default),
+ nm_setting_ip6_config_get_never_default (page->setting));
+
+ g_signal_connect (page->method, "changed", G_CALLBACK (method_changed), page);
+ if (method != IP6_METHOD_SHARED && method != IP6_METHOD_IGNORE)
+ gtk_combo_box_set_active (page->method, method);
+}
+
+static gboolean
+ui_to_setting (CEPageIP6 *page)
+{
+ gboolean valid = FALSE;
+ const gchar *method;
+ gboolean ignore_auto_dns;
+ gboolean ignore_auto_routes;
+ gboolean never_default;
+ GList *children, *l;
+
+ if (!gtk_switch_get_active (page->enabled)) {
+ method = NM_SETTING_IP6_CONFIG_METHOD_IGNORE;
+ } else {
+ switch (gtk_combo_box_get_active (page->method)) {
+ case IP6_METHOD_MANUAL:
+ method = NM_SETTING_IP6_CONFIG_METHOD_MANUAL;
+ break;
+ case IP6_METHOD_LINK_LOCAL:
+ method = NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL;
+ break;
+ case IP6_METHOD_DHCP:
+ method = NM_SETTING_IP6_CONFIG_METHOD_DHCP;
+ break;
+ default:
+ case IP6_METHOD_AUTO:
+ method = NM_SETTING_IP6_CONFIG_METHOD_AUTO;
+ break;
+ }
+ }
+
+ nm_setting_ip6_config_clear_addresses (page->setting);
+ children = gtk_container_get_children (GTK_CONTAINER (page->address_list));
+ for (l = children; l; l = l->next) {
+ GtkWidget *row = l->data;
+ GtkEntry *entry;
+ const gchar *text_address;
+ const gchar *text_prefix;
+ const gchar *text_gateway;
+ struct in6_addr tmp_addr;
+ struct in6_addr tmp_gateway;
+ guint32 prefix;
+ gchar *end;
+ NMIP6Address *addr;
+ gboolean have_gateway = FALSE;
+
+ entry = GTK_ENTRY (g_object_get_data (G_OBJECT (row), "address"));
+ if (!entry)
+ continue;
+
+ text_address = gtk_entry_get_text (entry);
+ text_prefix = gtk_entry_get_text (GTK_ENTRY (g_object_get_data (G_OBJECT (row), "prefix")));
+ text_gateway = gtk_entry_get_text (GTK_ENTRY (g_object_get_data (G_OBJECT (row), "gateway")));
+
+ if (!*text_address && !*text_prefix && !*text_gateway) {
+ /* ignore empty rows */
+ continue;
+ }
+
+ if (inet_pton (AF_INET6, text_address, &tmp_addr) <= 0) {
+ g_warning ("IPv6 address %s missing or invalid", text_address);
+ goto out;
+ }
+
+ prefix = strtoul (text_prefix, &end, 10);
+ if (!end || *end || prefix == 0 || prefix > 128) {
+ g_warning ("IPv6 prefix %s is invalid", text_prefix);
+ goto out;
+ }
+
+ if (text_gateway && *text_gateway) {
+ if (inet_pton (AF_INET6, text_gateway, &tmp_gateway) <= 0) {
+ g_warning ("IPv6 gateway %s is invalid", text_gateway);
+ goto out;
+ }
+ if (!IN6_IS_ADDR_UNSPECIFIED (&tmp_gateway))
+ have_gateway = TRUE;
+ }
+
+ addr = nm_ip6_address_new ();
+ nm_ip6_address_set_address (addr, &tmp_addr);
+ nm_ip6_address_set_prefix (addr, prefix);
+ if (have_gateway)
+ nm_ip6_address_set_gateway (addr, &tmp_gateway);
+ nm_setting_ip6_config_add_address (page->setting, addr);
+ }
+ g_list_free (children);
+
+ nm_setting_ip6_config_clear_dns (page->setting);
+ children = gtk_container_get_children (GTK_CONTAINER (page->dns_list));
+ for (l = children; l; l = l->next) {
+ GtkWidget *row = l->data;
+ GtkEntry *entry;
+ const gchar *text;
+ struct in6_addr tmp_addr;
+
+ entry = GTK_ENTRY (g_object_get_data (G_OBJECT (row), "address"));
+ if (!entry)
+ continue;
+
+ text = gtk_entry_get_text (entry);
+ if (!*text) {
+ /* ignore empty rows */
+ continue;
+ }
+
+ if (inet_pton (AF_INET6, text, &tmp_addr) <= 0) {
+ g_warning ("IPv6 dns server %s invalid", text);
+ goto out;
+ }
+
+ nm_setting_ip6_config_add_dns (page->setting, &tmp_addr);
+ }
+ g_list_free (children);
+
+ nm_setting_ip6_config_clear_routes (page->setting);
+ children = gtk_container_get_children (GTK_CONTAINER (page->routes_list));
+ for (l = children; l; l = l->next) {
+ GtkWidget *row = l->data;
+ GtkEntry *entry;
+ const gchar *text_address;
+ const gchar *text_prefix;
+ const gchar *text_gateway;
+ const gchar *text_metric;
+ struct in6_addr dest, gateway;
+ guint32 prefix, metric;
+ gchar *end;
+ NMIP6Route *route;
+
+ entry = GTK_ENTRY (g_object_get_data (G_OBJECT (row), "address"));
+ if (!entry)
+ continue;
+
+ text_address = gtk_entry_get_text (entry);
+ text_prefix = gtk_entry_get_text (GTK_ENTRY (g_object_get_data (G_OBJECT (row), "prefix")));
+ text_gateway = gtk_entry_get_text (GTK_ENTRY (g_object_get_data (G_OBJECT (row), "gateway")));
+ text_metric = gtk_entry_get_text (GTK_ENTRY (g_object_get_data (G_OBJECT (row), "metric")));
+
+ if (!*text_address && !*text_prefix && !*text_gateway && !*text_metric) {
+ /* ignore empty rows */
+ continue;
+ }
+
+ if (inet_pton (AF_INET6, text_address, &dest) <= 0) {
+ g_warning ("IPv6 route address %s invalid", text_address);
+ goto out;
+ }
+
+ prefix = strtoul (text_prefix, &end, 10);
+ if (!end || *end || prefix == 0 || prefix > 128) {
+ g_warning ("IPv6 route prefix %s invalid", text_prefix);
+ goto out;
+ }
+
+ if (inet_pton (AF_INET6, text_gateway, &gateway) <= 0) {
+ g_warning ("IPv6 route gateway %s invalid", text_gateway);
+ goto out;
+ }
+
+ metric = 0;
+ if (*text_metric) {
+ errno = 0;
+ metric = strtoul (text_metric, NULL, 10);
+ if (errno) {
+ g_warning ("IPv6 route metric %s invalid", text_metric);
+ goto out;
+ }
+ }
+
+ route = nm_ip6_route_new ();
+ nm_ip6_route_set_dest (route, &dest);
+ nm_ip6_route_set_prefix (route, prefix);
+ nm_ip6_route_set_next_hop (route, &gateway);
+ nm_ip6_route_set_metric (route, metric);
+ nm_setting_ip6_config_add_route (page->setting, route);
+ nm_ip6_route_unref (route);
+ }
+ g_list_free (children);
+
+ ignore_auto_dns = !gtk_switch_get_active (page->auto_dns);
+ ignore_auto_routes = !gtk_switch_get_active (page->auto_routes);
+ never_default = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (page->never_default));
+
+ g_object_set (page->setting,
+ NM_SETTING_IP6_CONFIG_METHOD, method,
+ NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS, ignore_auto_dns,
+ NM_SETTING_IP6_CONFIG_IGNORE_AUTO_ROUTES, ignore_auto_routes,
+ NM_SETTING_IP6_CONFIG_NEVER_DEFAULT, never_default,
+ NULL);
+
+ valid = TRUE;
+
+out:
+
+ return valid;
+}
+
+static gboolean
+validate (CEPage *page,
+ NMConnection *connection,
+ GError **error)
+{
+ if (!ui_to_setting (CE_PAGE_IP6 (page)))
+ return FALSE;
+
+ return nm_setting_verify (NM_SETTING (CE_PAGE_IP6 (page)->setting), NULL, error);
+}
+
+static void
+ce_page_ip6_init (CEPageIP6 *page)
+{
+}
+
+static void
+ce_page_ip6_class_init (CEPageIP6Class *class)
+{
+ CEPageClass *page_class= CE_PAGE_CLASS (class);
+
+ page_class->validate = validate;
+}
+
+CEPage *
+ce_page_ip6_new (NMConnection *connection,
+ NMClient *client,
+ NMRemoteSettings *settings)
+{
+ CEPageIP6 *page;
+
+ page = CE_PAGE_IP6 (ce_page_new (CE_TYPE_PAGE_IP6,
+ connection,
+ client,
+ settings,
+ "/org/gnome/control-center/network/ip6-page.ui",
+ _("IPv6")));
+
+ page->setting = nm_connection_get_setting_ip6_config (connection);
+
+ connect_ip6_page (page);
+
+ return CE_PAGE (page);
+}
diff --git a/panels/network/connection-editor/ce-page-ip6.h b/panels/network/connection-editor/ce-page-ip6.h
new file mode 100644
index 0000000..71d8821
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-ip6.h
@@ -0,0 +1,72 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more ip6.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __CE_PAGE_IP6_H
+#define __CE_PAGE_IP6_H
+
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+#include "ce-page.h"
+
+G_BEGIN_DECLS
+
+#define CE_TYPE_PAGE_IP6 (ce_page_ip6_get_type ())
+#define CE_PAGE_IP6(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CE_TYPE_PAGE_IP6, CEPageIP6))
+#define CE_PAGE_IP6_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CE_TYPE_PAGE_IP6, CEPageIP6Class))
+#define CE_IS_PAGE_IP6(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CE_TYPE_PAGE_IP6))
+#define CE_IS_PAGE_IP6_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CE_TYPE_PAGE_IP6))
+#define CE_PAGE_IP6_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CE_TYPE_PAGE_IP6, CEPageIP6Class))
+
+typedef struct _CEPageIP6 CEPageIP6;
+typedef struct _CEPageIP6Class CEPageIP6Class;
+
+struct _CEPageIP6
+{
+ CEPage parent;
+
+ NMSettingIP6Config *setting;
+
+ GtkSwitch *enabled;
+ GtkComboBox *method;
+ GtkWidget *address_list;
+ GtkSwitch *auto_dns;
+ GtkWidget *dns_list;
+ GtkSwitch *auto_routes;
+ GtkWidget *routes_list;
+ GtkWidget *never_default;
+};
+
+struct _CEPageIP6Class
+{
+ CEPageClass parent_class;
+};
+
+GType ce_page_ip6_get_type (void);
+
+CEPage *ce_page_ip6_new (NMConnection *connection,
+ NMClient *client,
+ NMRemoteSettings *settings);
+
+G_END_DECLS
+
+#endif /* __CE_PAGE_IP6_H */
+
diff --git a/panels/network/connection-editor/ce-page-reset.c b/panels/network/connection-editor/ce-page-reset.c
new file mode 100644
index 0000000..6112024
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-reset.c
@@ -0,0 +1,75 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <glib/gi18n.h>
+
+#include "ce-page-reset.h"
+
+G_DEFINE_TYPE (CEPageReset, ce_page_reset, CE_TYPE_PAGE)
+
+static void
+connect_reset_page (CEPageReset *page)
+{
+ /* FIXME */
+}
+
+static gboolean
+validate (CEPage *page,
+ NMConnection *connection,
+ GError **error)
+{
+ return TRUE;
+}
+
+static void
+ce_page_reset_init (CEPageReset *page)
+{
+}
+
+static void
+ce_page_reset_class_init (CEPageResetClass *class)
+{
+ CEPageClass *page_class= CE_PAGE_CLASS (class);
+
+ page_class->validate = validate;
+}
+
+CEPage *
+ce_page_reset_new (NMConnection *connection,
+ NMClient *client,
+ NMRemoteSettings *settings)
+{
+ CEPageReset *page;
+
+ page = CE_PAGE_RESET (ce_page_new (CE_TYPE_PAGE_RESET,
+ connection,
+ client,
+ settings,
+ "/org/gnome/control-center/network/reset-page.ui",
+ _("Reset")));
+
+ connect_reset_page (page);
+
+ return CE_PAGE (page);
+}
diff --git a/panels/network/connection-editor/ce-page-reset.h b/panels/network/connection-editor/ce-page-reset.h
new file mode 100644
index 0000000..3e9582a
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-reset.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more reset.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __CE_PAGE_RESET_H
+#define __CE_PAGE_RESET_H
+
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+#include "ce-page.h"
+
+G_BEGIN_DECLS
+
+#define CE_TYPE_PAGE_RESET (ce_page_reset_get_type ())
+#define CE_PAGE_RESET(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CE_TYPE_PAGE_RESET, CEPageReset))
+#define CE_PAGE_RESET_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CE_TYPE_PAGE_RESET, CEPageResetClass))
+#define CE_IS_PAGE_RESET(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CE_TYPE_PAGE_RESET))
+#define CE_IS_PAGE_RESET_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CE_TYPE_PAGE_RESET))
+#define CE_PAGE_RESET_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CE_TYPE_PAGE_RESET, CEPageResetClass))
+
+typedef struct _CEPageReset CEPageReset;
+typedef struct _CEPageResetClass CEPageResetClass;
+
+struct _CEPageReset
+{
+ CEPage parent;
+};
+
+struct _CEPageResetClass
+{
+ CEPageClass parent_class;
+};
+
+GType ce_page_reset_get_type (void);
+
+CEPage *ce_page_reset_new (NMConnection *connection,
+ NMClient *client,
+ NMRemoteSettings *settings);
+
+G_END_DECLS
+
+#endif /* __CE_PAGE_RESET_H */
+
diff --git a/panels/network/connection-editor/ce-page-security.c b/panels/network/connection-editor/ce-page-security.c
new file mode 100644
index 0000000..9b187bf
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-security.c
@@ -0,0 +1,480 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <glib/gi18n.h>
+
+#include <nm-utils.h>
+#include <nm-connection.h>
+
+#include "wireless-security.h"
+#include "ce-page-security.h"
+
+G_DEFINE_TYPE (CEPageSecurity, ce_page_security, CE_TYPE_PAGE)
+
+enum {
+ S_NAME_COLUMN,
+ S_SEC_COLUMN,
+ S_ADHOC_VALID_COLUMN
+};
+
+static gboolean
+find_proto (NMSettingWirelessSecurity *sec, const char *item)
+{
+ guint32 i;
+
+ for (i = 0; i < nm_setting_wireless_security_get_num_protos (sec); i++) {
+ if (!strcmp (item, nm_setting_wireless_security_get_proto (sec, i)))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static NMUtilsSecurityType
+get_default_type_for_security (NMSettingWirelessSecurity *sec)
+{
+ const char *key_mgmt, *auth_alg;
+
+ g_return_val_if_fail (sec != NULL, NMU_SEC_NONE);
+
+ key_mgmt = nm_setting_wireless_security_get_key_mgmt (sec);
+ auth_alg = nm_setting_wireless_security_get_auth_alg (sec);
+
+ /* No IEEE 802.1x */
+ if (!strcmp (key_mgmt, "none"))
+ return NMU_SEC_STATIC_WEP;
+
+ if (!strcmp (key_mgmt, "ieee8021x")) {
+ if (auth_alg && !strcmp (auth_alg, "leap"))
+ return NMU_SEC_LEAP;
+ return NMU_SEC_DYNAMIC_WEP;
+ }
+
+ if ( !strcmp (key_mgmt, "wpa-none")
+ || !strcmp (key_mgmt, "wpa-psk")) {
+ if (find_proto (sec, "rsn"))
+ return NMU_SEC_WPA2_PSK;
+ else if (find_proto (sec, "wpa"))
+ return NMU_SEC_WPA_PSK;
+ else
+ return NMU_SEC_WPA_PSK;
+ }
+
+ if (!strcmp (key_mgmt, "wpa-eap")) {
+ if (find_proto (sec, "rsn"))
+ return NMU_SEC_WPA2_ENTERPRISE;
+ else if (find_proto (sec, "wpa"))
+ return NMU_SEC_WPA_ENTERPRISE;
+ else
+ return NMU_SEC_WPA_ENTERPRISE;
+ }
+
+ return NMU_SEC_INVALID;
+}
+
+static WirelessSecurity *
+security_combo_get_active (CEPageSecurity *page)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ WirelessSecurity *sec = NULL;
+
+ model = gtk_combo_box_get_model (page->security_combo);
+ gtk_combo_box_get_active_iter (page->security_combo, &iter);
+ gtk_tree_model_get (model, &iter, S_SEC_COLUMN, &sec, -1);
+
+ return sec;
+}
+
+static void
+wsec_size_group_clear (GtkSizeGroup *group)
+{
+ GSList *children;
+ GSList *iter;
+
+ g_return_if_fail (group != NULL);
+
+ children = gtk_size_group_get_widgets (group);
+ for (iter = children; iter; iter = g_slist_next (iter))
+ gtk_size_group_remove_widget (group, GTK_WIDGET (iter->data));
+}
+
+static void
+security_combo_changed (GtkComboBox *combo,
+ gpointer user_data)
+{
+ CEPageSecurity *page = CE_PAGE_SECURITY (user_data);
+ GtkWidget *vbox;
+ GList *l, *children;
+ WirelessSecurity *sec;
+
+ wsec_size_group_clear (page->group);
+
+ vbox = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "vbox"));
+ children = gtk_container_get_children (GTK_CONTAINER (vbox));
+ for (l = children; l; l = l->next) {
+ gtk_container_remove (GTK_CONTAINER (vbox), GTK_WIDGET (l->data));
+ }
+
+ sec = security_combo_get_active (page);
+ if (sec) {
+ GtkWidget *sec_widget;
+ GtkWidget *parent;
+
+ sec_widget = wireless_security_get_widget (sec);
+ g_assert (sec_widget);
+ parent = gtk_widget_get_parent (sec_widget);
+ if (parent)
+ gtk_container_remove (GTK_CONTAINER (parent), sec_widget);
+
+ gtk_size_group_add_widget (page->group, page->security_heading);
+ wireless_security_add_to_size_group (sec, page->group);
+
+ gtk_container_add (GTK_CONTAINER (vbox), sec_widget);
+ wireless_security_unref (sec);
+ }
+
+ ce_page_changed (CE_PAGE (page));
+}
+
+static void
+stuff_changed_cb (WirelessSecurity *sec, gpointer user_data)
+{
+ ce_page_changed (CE_PAGE (user_data));
+}
+
+static void
+add_security_item (CEPageSecurity *page,
+ WirelessSecurity *sec,
+ GtkListStore *model,
+ GtkTreeIter *iter,
+ const char *text,
+ gboolean adhoc_valid)
+{
+ wireless_security_set_changed_notify (sec, stuff_changed_cb, page);
+ gtk_list_store_append (model, iter);
+ gtk_list_store_set (model, iter,
+ S_NAME_COLUMN, text,
+ S_SEC_COLUMN, sec,
+ S_ADHOC_VALID_COLUMN, adhoc_valid,
+ -1);
+ wireless_security_unref (sec);
+}
+
+static void
+set_sensitive (GtkCellLayout *cell_layout,
+ GtkCellRenderer *cell,
+ GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ gboolean *adhoc = data;
+ gboolean sensitive = TRUE, adhoc_valid = TRUE;
+
+ gtk_tree_model_get (tree_model, iter, S_ADHOC_VALID_COLUMN, &adhoc_valid, -1);
+ if (*adhoc && !adhoc_valid)
+ sensitive = FALSE;
+
+ g_object_set (cell, "sensitive", sensitive, NULL);
+}
+
+static void
+finish_setup (CEPageSecurity *page)
+{
+ NMConnection *connection = CE_PAGE (page)->connection;
+ NMSettingWireless *sw;
+ NMSettingWirelessSecurity *sws;
+ gboolean is_adhoc = FALSE;
+ GtkListStore *sec_model;
+ GtkTreeIter iter;
+ const gchar *mode;
+ const gchar *security;
+ guint32 dev_caps = 0;
+ NMUtilsSecurityType default_type = NMU_SEC_NONE;
+ int active = -1;
+ int item = 0;
+ GtkComboBox *combo;
+ GtkCellRenderer *renderer;
+
+ sw = nm_connection_get_setting_wireless (connection);
+ g_assert (sw);
+
+ page->group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+
+ page->security_heading = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "heading_sec"));
+ page->security_combo = combo = GTK_COMBO_BOX (gtk_builder_get_object (CE_PAGE (page)->builder, "combo_sec"));
+
+ dev_caps = NM_WIFI_DEVICE_CAP_CIPHER_WEP40
+ | NM_WIFI_DEVICE_CAP_CIPHER_WEP104
+ | NM_WIFI_DEVICE_CAP_CIPHER_TKIP
+ | NM_WIFI_DEVICE_CAP_CIPHER_CCMP
+ | NM_WIFI_DEVICE_CAP_WPA
+ | NM_WIFI_DEVICE_CAP_RSN;
+
+ mode = nm_setting_wireless_get_mode (sw);
+ if (mode && !strcmp (mode, "adhoc"))
+ is_adhoc = TRUE;
+ page->adhoc = is_adhoc;
+
+ sws = nm_connection_get_setting_wireless_security (connection);
+ security = nm_setting_wireless_get_security (sw);
+ if (!security || strcmp (security, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) != 0)
+ sws = NULL;
+ if (sws)
+ default_type = get_default_type_for_security (sws);
+
+ sec_model = gtk_list_store_new (3, G_TYPE_STRING, wireless_security_get_g_type (), G_TYPE_BOOLEAN);
+
+ if (nm_utils_security_valid (NMU_SEC_NONE, dev_caps, FALSE, is_adhoc, 0, 0, 0)) {
+ gtk_list_store_insert_with_values (sec_model, &iter, -1,
+ S_NAME_COLUMN, C_("Wi-Fi/Ethernet security", "None"),
+ S_ADHOC_VALID_COLUMN, TRUE,
+ -1);
+ if (default_type == NMU_SEC_NONE)
+ active = item;
+ item++;
+ }
+
+ if (nm_utils_security_valid (NMU_SEC_STATIC_WEP, dev_caps, FALSE, is_adhoc, 0, 0, 0)) {
+ WirelessSecurityWEPKey *ws_wep;
+ NMWepKeyType wep_type = NM_WEP_KEY_TYPE_KEY;
+
+ if (default_type == NMU_SEC_STATIC_WEP) {
+ sws = nm_connection_get_setting_wireless_security (connection);
+ if (sws)
+ wep_type = nm_setting_wireless_security_get_wep_key_type (sws);
+ if (wep_type == NM_WEP_KEY_TYPE_UNKNOWN)
+ wep_type = NM_WEP_KEY_TYPE_KEY;
+ }
+
+ ws_wep = ws_wep_key_new (connection, NM_WEP_KEY_TYPE_KEY, FALSE, FALSE);
+ if (ws_wep) {
+ add_security_item (page, WIRELESS_SECURITY (ws_wep), sec_model,
+ &iter, _("WEP 40/128-bit Key (Hex or ASCII)"),
+ TRUE);
+ if ((active < 0) && (default_type == NMU_SEC_STATIC_WEP) && (wep_type == NM_WEP_KEY_TYPE_KEY))
+ active = item;
+ item++;
+ }
+
+ ws_wep = ws_wep_key_new (connection, NM_WEP_KEY_TYPE_PASSPHRASE, FALSE, FALSE);
+ if (ws_wep) {
+ add_security_item (page, WIRELESS_SECURITY (ws_wep), sec_model,
+ &iter, _("WEP 128-bit Passphrase"), TRUE);
+ if ((active < 0) && (default_type == NMU_SEC_STATIC_WEP) && (wep_type == NM_WEP_KEY_TYPE_PASSPHRASE))
+ active = item;
+ item++;
+ }
+ }
+
+ if (nm_utils_security_valid (NMU_SEC_LEAP, dev_caps, FALSE, is_adhoc, 0, 0, 0)) {
+ WirelessSecurityLEAP *ws_leap;
+
+ ws_leap = ws_leap_new (connection, FALSE);
+ if (ws_leap) {
+ add_security_item (page, WIRELESS_SECURITY (ws_leap), sec_model,
+ &iter, _("LEAP"), FALSE);
+ if ((active < 0) && (default_type == NMU_SEC_LEAP))
+ active = item;
+ item++;
+ }
+ }
+
+ if (nm_utils_security_valid (NMU_SEC_DYNAMIC_WEP, dev_caps, FALSE, is_adhoc, 0, 0, 0)) {
+ WirelessSecurityDynamicWEP *ws_dynamic_wep;
+
+ ws_dynamic_wep = ws_dynamic_wep_new (connection, TRUE, FALSE);
+ if (ws_dynamic_wep) {
+ add_security_item (page, WIRELESS_SECURITY (ws_dynamic_wep), sec_model,
+ &iter, _("Dynamic WEP (802.1x)"), FALSE);
+ if ((active < 0) && (default_type == NMU_SEC_DYNAMIC_WEP))
+ active = item;
+ item++;
+ }
+ }
+
+ if (nm_utils_security_valid (NMU_SEC_WPA_PSK, dev_caps, FALSE, is_adhoc, 0, 0, 0) ||
+ nm_utils_security_valid (NMU_SEC_WPA2_PSK, dev_caps, FALSE, is_adhoc, 0, 0, 0)) {
+ WirelessSecurityWPAPSK *ws_wpa_psk;
+
+ ws_wpa_psk = ws_wpa_psk_new (connection, FALSE);
+ if (ws_wpa_psk) {
+ add_security_item (page, WIRELESS_SECURITY (ws_wpa_psk), sec_model,
+ &iter, _("WPA & WPA2 Personal"), FALSE);
+ if ((active < 0) && ((default_type == NMU_SEC_WPA_PSK) || (default_type == NMU_SEC_WPA2_PSK)))
+ active = item;
+ item++;
+ }
+ }
+
+ if (nm_utils_security_valid (NMU_SEC_WPA_ENTERPRISE, dev_caps, FALSE, is_adhoc, 0, 0, 0) ||
+ nm_utils_security_valid (NMU_SEC_WPA2_ENTERPRISE, dev_caps, FALSE, is_adhoc, 0, 0, 0)) {
+ WirelessSecurityWPAEAP *ws_wpa_eap;
+
+ ws_wpa_eap = ws_wpa_eap_new (connection, TRUE, FALSE);
+ if (ws_wpa_eap) {
+ add_security_item (page, WIRELESS_SECURITY (ws_wpa_eap), sec_model,
+ &iter, _("WPA & WPA2 Enterprise"), FALSE);
+ if ((active < 0) && ((default_type == NMU_SEC_WPA_ENTERPRISE) || (default_type == NMU_SEC_WPA2_ENTERPRISE)))
+ active = item;
+ item++;
+ }
+ }
+
+ gtk_combo_box_set_model (combo, GTK_TREE_MODEL (sec_model));
+ gtk_cell_layout_clear (GTK_CELL_LAYOUT (combo));
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer, "text", S_NAME_COLUMN, NULL);
+ gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo), renderer, set_sensitive, &page->adhoc, NULL);
+
+ gtk_combo_box_set_active (combo, active < 0 ? 0 : (guint32) active);
+ g_object_unref (G_OBJECT (sec_model));
+
+ page->security_combo = combo;
+
+ security_combo_changed (combo, page);
+ g_signal_connect (combo, "changed",
+ G_CALLBACK (security_combo_changed), page);
+}
+
+static gboolean
+validate (CEPage *page,
+ NMConnection *connection,
+ GError **error)
+{
+ NMSettingWireless *sw;
+ WirelessSecurity *sec;
+ gboolean valid = FALSE;
+ const char *mode;
+
+ sw = nm_connection_get_setting_wireless (connection);
+
+ mode = nm_setting_wireless_get_mode (sw);
+ if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_ADHOC) == 0)
+ CE_PAGE_SECURITY (page)->adhoc = TRUE;
+ else
+ CE_PAGE_SECURITY (page)->adhoc = FALSE;
+
+ sec = security_combo_get_active (CE_PAGE_SECURITY (page));
+ if (sec) {
+ const GByteArray *ssid = nm_setting_wireless_get_ssid (sw);
+
+ if (ssid) {
+ /* FIXME: get failed property and error out of wifi security objects */
+ valid = wireless_security_validate (sec, ssid);
+ if (valid)
+ wireless_security_fill_connection (sec, connection);
+ else
+ g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_UNKNOWN, "Invalid Wi-Fi security");
+ } else {
+ g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_UNKNOWN, "Missing SSID");
+ valid = FALSE;
+ }
+
+ if (CE_PAGE_SECURITY (page)->adhoc) {
+ if (!wireless_security_adhoc_compatible (sec)) {
+ g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_UNKNOWN, "Security not compatible with Ad-Hoc mode");
+ valid = FALSE;
+ }
+ }
+
+ wireless_security_unref (sec);
+ } else {
+ /* No security, unencrypted */
+ g_object_set (sw, NM_SETTING_WIRELESS_SEC, NULL, NULL);
+ nm_connection_remove_setting (connection, NM_TYPE_SETTING_WIRELESS_SECURITY);
+ nm_connection_remove_setting (connection, NM_TYPE_SETTING_802_1X);
+ valid = TRUE;
+ }
+
+ return valid;
+}
+
+static void
+ce_page_security_init (CEPageSecurity *page)
+{
+}
+
+static void
+dispose (GObject *object)
+{
+ CEPageSecurity *page = CE_PAGE_SECURITY (object);
+
+ g_clear_object (&page->group);
+
+ G_OBJECT_CLASS (ce_page_security_parent_class)->dispose (object);
+}
+
+static void
+ce_page_security_class_init (CEPageSecurityClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ CEPageClass *page_class = CE_PAGE_CLASS (class);
+
+ object_class->dispose = dispose;
+ page_class->validate = validate;
+}
+
+CEPage *
+ce_page_security_new (NMConnection *connection,
+ NMClient *client,
+ NMRemoteSettings *settings)
+{
+ CEPageSecurity *page;
+ const gchar *security;
+ NMUtilsSecurityType default_type = NMU_SEC_NONE;
+ NMSettingWirelessSecurity *sws;
+
+ page = CE_PAGE_SECURITY (ce_page_new (CE_TYPE_PAGE_SECURITY,
+ connection,
+ client,
+ settings,
+ "/org/gnome/control-center/network/security-page.ui",
+ _("Security")));
+
+ sws = nm_connection_get_setting_wireless_security (connection);
+ security = nm_setting_wireless_get_security (nm_connection_get_setting_wireless (connection));
+ if (!security || strcmp (security, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) != 0)
+ sws = NULL;
+ if (sws)
+ default_type = get_default_type_for_security (sws);
+
+ if (default_type == NMU_SEC_STATIC_WEP
+ || default_type == NMU_SEC_LEAP
+ || default_type == NMU_SEC_WPA_PSK
+ || default_type == NMU_SEC_WPA2_PSK) {
+ CE_PAGE (page)->security_setting = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME;
+ }
+
+ if (default_type == NMU_SEC_DYNAMIC_WEP
+ || default_type == NMU_SEC_WPA_ENTERPRISE
+ || default_type == NMU_SEC_WPA2_ENTERPRISE) {
+ CE_PAGE (page)->security_setting = NM_SETTING_802_1X_SETTING_NAME;
+ }
+
+ g_signal_connect (page, "initialized", G_CALLBACK (finish_setup), NULL);
+
+ return CE_PAGE (page);
+}
diff --git a/panels/network/connection-editor/ce-page-security.h b/panels/network/connection-editor/ce-page-security.h
new file mode 100644
index 0000000..ab19bb7
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-security.h
@@ -0,0 +1,66 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more security.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __CE_PAGE_SECURITY_H
+#define __CE_PAGE_SECURITY_H
+
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+#include "ce-page.h"
+
+G_BEGIN_DECLS
+
+#define CE_TYPE_PAGE_SECURITY (ce_page_security_get_type ())
+#define CE_PAGE_SECURITY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CE_TYPE_PAGE_SECURITY, CEPageSecurity))
+#define CE_PAGE_SECURITY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CE_TYPE_PAGE_SECURITY, CEPageSecurityClass))
+#define CE_IS_PAGE_SECURITY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CE_TYPE_PAGE_SECURITY))
+#define CE_IS_PAGE_SECURITY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CE_TYPE_PAGE_SECURITY))
+#define CE_PAGE_SECURITY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CE_TYPE_PAGE_SECURITY, CEPageSecurityClass))
+
+typedef struct _CEPageSecurity CEPageSecurity;
+typedef struct _CEPageSecurityClass CEPageSecurityClass;
+
+struct _CEPageSecurity
+{
+ CEPage parent;
+
+ GtkComboBox *security_combo;
+ GtkWidget *security_heading;
+ GtkSizeGroup *group;
+ gboolean adhoc;
+};
+
+struct _CEPageSecurityClass
+{
+ CEPageClass parent_class;
+};
+
+GType ce_page_security_get_type (void);
+
+CEPage *ce_page_security_new (NMConnection *connection,
+ NMClient *client,
+ NMRemoteSettings *settings);
+
+G_END_DECLS
+
+#endif /* __CE_PAGE_SECURITY_H */
+
diff --git a/panels/network/connection-editor/ce-page-wifi.c b/panels/network/connection-editor/ce-page-wifi.c
new file mode 100644
index 0000000..aa5984d
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-wifi.c
@@ -0,0 +1,221 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <glib/gi18n.h>
+
+#include <nm-setting-wireless.h>
+#include <nm-utils.h>
+#include <nm-device-wifi.h>
+
+#include <net/if_arp.h>
+
+#include "ce-page-wifi.h"
+
+G_DEFINE_TYPE (CEPageWifi, ce_page_wifi, CE_TYPE_PAGE)
+
+static void
+connect_wifi_page (CEPageWifi *page)
+{
+ GtkWidget *widget;
+ const GByteArray *ssid;
+ gchar *utf8_ssid;
+ GPtrArray *bssid_array;
+ gchar **bssid_list;
+ const GByteArray *s_bssid;
+ gchar *s_bssid_str;
+ gchar **mac_list;
+ const GByteArray *s_mac;
+ gchar *s_mac_str;
+ gint i;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder,
+ "entry_ssid"));
+
+ ssid = nm_setting_wireless_get_ssid (page->setting);
+ if (ssid)
+ utf8_ssid = nm_utils_ssid_to_utf8 (ssid);
+ else
+ utf8_ssid = g_strdup ("");
+ gtk_entry_set_text (GTK_ENTRY (widget), utf8_ssid);
+ g_free (utf8_ssid);
+
+ g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder,
+ "combo_bssid"));
+
+ bssid_array = g_ptr_array_new ();
+ for (i = 0; i < nm_setting_wireless_get_num_seen_bssids (page->setting); i++) {
+ g_ptr_array_add (bssid_array, g_strdup (nm_setting_wireless_get_seen_bssid (page->setting, i)));
+ }
+ g_ptr_array_add (bssid_array, NULL);
+ bssid_list = (gchar **) g_ptr_array_free (bssid_array, FALSE);
+ s_bssid = nm_setting_wireless_get_bssid (page->setting);
+ s_bssid_str = s_bssid ? nm_utils_hwaddr_ntoa (s_bssid->data, ARPHRD_ETHER) : NULL;
+ ce_page_setup_mac_combo (GTK_COMBO_BOX_TEXT (widget), s_bssid_str, bssid_list);
+ g_free (s_bssid_str);
+ g_strfreev (bssid_list);
+ g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder,
+ "combo_mac"));
+ mac_list = ce_page_get_mac_list (CE_PAGE (page)->client, NM_TYPE_DEVICE_WIFI,
+ NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS);
+ s_mac = nm_setting_wireless_get_mac_address (page->setting);
+ s_mac_str = s_mac ? nm_utils_hwaddr_ntoa (s_mac->data, ARPHRD_ETHER) : NULL;
+ ce_page_setup_mac_combo (GTK_COMBO_BOX_TEXT (widget), s_mac_str, mac_list);
+ g_free (s_mac_str);
+ g_strfreev (mac_list);
+ g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+
+
+ widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder,
+ "entry_cloned_mac"));
+ ce_page_mac_to_entry (nm_setting_wireless_get_cloned_mac_address (page->setting),
+ ARPHRD_ETHER, GTK_ENTRY (widget));
+ g_signal_connect_swapped (widget, "changed", G_CALLBACK (ce_page_changed), page);
+}
+
+static void
+ui_to_setting (CEPageWifi *page)
+{
+ GByteArray *ssid;
+ GByteArray *bssid = NULL;
+ GByteArray *device_mac = NULL;
+ GByteArray *cloned_mac = NULL;
+ GtkWidget *entry;
+ const gchar *utf8_ssid;
+
+ entry = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "entry_ssid"));
+ utf8_ssid = gtk_entry_get_text (GTK_ENTRY (entry));
+ if (!utf8_ssid || !*utf8_ssid)
+ ssid = NULL;
+ else {
+ ssid = g_byte_array_sized_new (strlen (utf8_ssid));
+ g_byte_array_append (ssid, (const guint8*)utf8_ssid, strlen (utf8_ssid));
+ }
+ entry = gtk_bin_get_child (GTK_BIN (gtk_builder_get_object (CE_PAGE (page)->builder, "combo_bssid")));
+ bssid = ce_page_entry_to_mac (GTK_ENTRY (entry), ARPHRD_ETHER, NULL);
+ entry = gtk_bin_get_child (GTK_BIN (gtk_builder_get_object (CE_PAGE (page)->builder, "combo_mac")));
+ device_mac = ce_page_entry_to_mac (GTK_ENTRY (entry), ARPHRD_ETHER, NULL);
+ entry = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "entry_cloned_mac"));
+ cloned_mac = ce_page_entry_to_mac (GTK_ENTRY (entry), ARPHRD_ETHER, NULL);
+
+ g_object_set (page->setting,
+ NM_SETTING_WIRELESS_SSID, ssid,
+ NM_SETTING_WIRELESS_BSSID, bssid,
+ NM_SETTING_WIRELESS_MAC_ADDRESS, device_mac,
+ NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, cloned_mac,
+ NULL);
+
+ if (ssid)
+ g_byte_array_free (ssid, TRUE);
+ if (bssid)
+ g_byte_array_free (bssid, TRUE);
+ if (device_mac)
+ g_byte_array_free (device_mac, TRUE);
+ if (cloned_mac)
+ g_byte_array_free (cloned_mac, TRUE);
+}
+
+static gboolean
+validate (CEPage *page,
+ NMConnection *connection,
+ GError **error)
+{
+ GtkWidget *entry;
+ GByteArray *ignore;
+ gboolean invalid;
+ gboolean success;
+ gchar *security;
+ NMSettingWireless *setting;
+
+ entry = gtk_bin_get_child (GTK_BIN (gtk_builder_get_object (page->builder, "combo_bssid")));
+ ignore = ce_page_entry_to_mac (GTK_ENTRY (entry), ARPHRD_ETHER, &invalid);
+ if (invalid)
+ return FALSE;
+ if (ignore)
+ g_byte_array_free (ignore, TRUE);
+
+ entry = gtk_bin_get_child (GTK_BIN (gtk_builder_get_object (page->builder, "combo_mac")));
+ ignore = ce_page_entry_to_mac (GTK_ENTRY (entry), ARPHRD_ETHER, &invalid);
+ if (invalid)
+ return FALSE;
+ if (ignore)
+ g_byte_array_free (ignore, TRUE);
+
+ entry = GTK_WIDGET (gtk_builder_get_object (page->builder, "entry_cloned_mac"));
+ ignore = ce_page_entry_to_mac (GTK_ENTRY (entry), ARPHRD_ETHER, &invalid);
+ if (invalid)
+ return FALSE;
+ if (ignore)
+ g_byte_array_free (ignore, TRUE);
+
+
+ ui_to_setting (CE_PAGE_WIFI (page));
+
+ /* A hack to not check the wifi security here */
+ setting = CE_PAGE_WIFI (page)->setting;
+ security = g_strdup (nm_setting_wireless_get_security (setting));
+ g_object_set (setting, NM_SETTING_WIRELESS_SEC, NULL, NULL);
+ success = nm_setting_verify (NM_SETTING (setting), NULL, error);
+ g_object_set (setting, NM_SETTING_WIRELESS_SEC, security, NULL);
+ g_free (security);
+
+ return success;
+}
+
+static void
+ce_page_wifi_init (CEPageWifi *page)
+{
+}
+
+static void
+ce_page_wifi_class_init (CEPageWifiClass *class)
+{
+ CEPageClass *page_class= CE_PAGE_CLASS (class);
+
+ page_class->validate = validate;
+}
+
+CEPage *
+ce_page_wifi_new (NMConnection *connection,
+ NMClient *client,
+ NMRemoteSettings *settings)
+{
+ CEPageWifi *page;
+
+ page = CE_PAGE_WIFI (ce_page_new (CE_TYPE_PAGE_WIFI,
+ connection,
+ client,
+ settings,
+ "/org/gnome/control-center/network/wifi-page.ui",
+ _("Identity")));
+
+ page->setting = nm_connection_get_setting_wireless (connection);
+
+ connect_wifi_page (page);
+
+ return CE_PAGE (page);
+}
diff --git a/panels/network/connection-editor/ce-page-wifi.h b/panels/network/connection-editor/ce-page-wifi.h
new file mode 100644
index 0000000..88087e7
--- /dev/null
+++ b/panels/network/connection-editor/ce-page-wifi.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more wifi.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __CE_PAGE_WIFI_H
+#define __CE_PAGE_WIFI_H
+
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+#include "ce-page.h"
+
+G_BEGIN_DECLS
+
+#define CE_TYPE_PAGE_WIFI (ce_page_wifi_get_type ())
+#define CE_PAGE_WIFI(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CE_TYPE_PAGE_WIFI, CEPageWifi))
+#define CE_PAGE_WIFI_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CE_TYPE_PAGE_WIFI, CEPageWifiClass))
+#define CE_IS_PAGE_WIFI(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CE_TYPE_PAGE_WIFI))
+#define CE_IS_PAGE_WIFI_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CE_TYPE_PAGE_WIFI))
+#define CE_PAGE_WIFI_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CE_TYPE_PAGE_WIFI, CEPageWifiClass))
+
+typedef struct _CEPageWifi CEPageWifi;
+typedef struct _CEPageWifiClass CEPageWifiClass;
+
+struct _CEPageWifi
+{
+ CEPage parent;
+
+ NMSettingWireless *setting;
+};
+
+struct _CEPageWifiClass
+{
+ CEPageClass parent_class;
+};
+
+GType ce_page_wifi_get_type (void);
+
+CEPage *ce_page_wifi_new (NMConnection *connection,
+ NMClient *client,
+ NMRemoteSettings *settings);
+
+G_END_DECLS
+
+#endif /* __CE_PAGE_WIFI_H */
+
diff --git a/panels/network/connection-editor/ce-page.c b/panels/network/connection-editor/ce-page.c
new file mode 100644
index 0000000..99b20e7
--- /dev/null
+++ b/panels/network/connection-editor/ce-page.c
@@ -0,0 +1,454 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <net/if_arp.h>
+#include <netinet/ether.h>
+
+#include <nm-utils.h>
+
+#include "ce-page.h"
+
+
+G_DEFINE_ABSTRACT_TYPE (CEPage, ce_page, G_TYPE_OBJECT)
+
+enum {
+ PROP_0,
+ PROP_CONNECTION,
+ PROP_INITIALIZED,
+};
+
+enum {
+ CHANGED,
+ INITIALIZED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+gboolean
+ce_page_validate (CEPage *page, NMConnection *connection, GError **error)
+{
+ g_return_val_if_fail (CE_IS_PAGE (page), FALSE);
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
+
+ if (CE_PAGE_GET_CLASS (page)->validate)
+ return CE_PAGE_GET_CLASS (page)->validate (page, connection, error);
+
+ return TRUE;
+}
+
+static void
+dispose (GObject *object)
+{
+ CEPage *self = CE_PAGE (object);
+
+ g_clear_object (&self->page);
+ g_clear_object (&self->builder);
+ g_clear_object (&self->connection);
+
+ G_OBJECT_CLASS (ce_page_parent_class)->dispose (object);
+}
+
+static void
+finalize (GObject *object)
+{
+ CEPage *self = CE_PAGE (object);
+
+ g_free (self->title);
+
+ G_OBJECT_CLASS (ce_page_parent_class)->finalize (object);
+}
+
+GtkWidget *
+ce_page_get_page (CEPage *self)
+{
+ g_return_val_if_fail (CE_IS_PAGE (self), NULL);
+
+ return self->page;
+}
+
+const char *
+ce_page_get_title (CEPage *self)
+{
+ g_return_val_if_fail (CE_IS_PAGE (self), NULL);
+
+ return self->title;
+}
+
+gboolean
+ce_page_get_initialized (CEPage *self)
+{
+ g_return_val_if_fail (CE_IS_PAGE (self), FALSE);
+
+ return self->initialized;
+}
+
+void
+ce_page_changed (CEPage *self)
+{
+ g_return_if_fail (CE_IS_PAGE (self));
+
+ g_signal_emit (self, signals[CHANGED], 0);
+}
+
+static void
+get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CEPage *self = CE_PAGE (object);
+
+ switch (prop_id) {
+ case PROP_CONNECTION:
+ g_value_set_object (value, self->connection);
+ break;
+ case PROP_INITIALIZED:
+ g_value_set_boolean (value, self->initialized);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CEPage *self = CE_PAGE (object);
+
+ switch (prop_id) {
+ case PROP_CONNECTION:
+ if (self->connection)
+ g_object_unref (self->connection);
+ self->connection = g_value_dup_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+ce_page_init (CEPage *self)
+{
+ self->builder = gtk_builder_new ();
+}
+
+static void
+ce_page_class_init (CEPageClass *page_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (page_class);
+
+ /* virtual methods */
+ object_class->dispose = dispose;
+ object_class->finalize = finalize;
+ object_class->get_property = get_property;
+ object_class->set_property = set_property;
+
+ /* Properties */
+ g_object_class_install_property
+ (object_class, PROP_CONNECTION,
+ g_param_spec_object ("connection",
+ "Connection",
+ "Connection",
+ NM_TYPE_CONNECTION,
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property
+ (object_class, PROP_INITIALIZED,
+ g_param_spec_boolean ("initialized",
+ "Initialized",
+ "Initialized",
+ FALSE,
+ G_PARAM_READABLE));
+
+ signals[CHANGED] =
+ g_signal_new ("changed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (CEPageClass, changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[INITIALIZED] =
+ g_signal_new ("initialized",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (CEPageClass, initialized),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
+}
+
+CEPage *
+ce_page_new (GType type,
+ NMConnection *connection,
+ NMClient *client,
+ NMRemoteSettings *settings,
+ const gchar *ui_resource,
+ const gchar *title)
+{
+ CEPage *page;
+ GError *error = NULL;
+
+ page = CE_PAGE (g_object_new (type,
+ "connection", connection,
+ NULL));
+ page->title = g_strdup (title);
+ page->client = client;
+ page->settings= settings;
+ if (!gtk_builder_add_from_resource (page->builder, ui_resource, &error)) {
+ g_warning ("Couldn't load builder file: %s", error->message);
+ g_error_free (error);
+ g_object_unref (page);
+ return NULL;
+ }
+ page->page = GTK_WIDGET (gtk_builder_get_object (page->builder, "page"));
+ if (!page->page) {
+ g_warning ("Couldn't load page widget from %s", ui_resource);
+ g_object_unref (page);
+ return NULL;
+ }
+
+ g_object_ref_sink (page->page);
+
+ return page;
+}
+
+static void
+emit_initialized (CEPage *page,
+ GError *error)
+{
+ page->initialized = TRUE;
+ g_signal_emit (page, signals[INITIALIZED], 0, error);
+}
+
+void
+ce_page_complete_init (CEPage *page,
+ const gchar *setting_name,
+ GHashTable *secrets,
+ GError *error)
+{
+ GHashTable *setting_hash;
+ GError *update_error = NULL;
+
+ if (error
+ && !dbus_g_error_has_name (error, "org.freedesktop.NetworkManager.Settings.InvalidSetting")
+ && !dbus_g_error_has_name (error, "org.freedesktop.NetworkManager.AgentManager.NoSecrets")) {
+ emit_initialized (page, error);
+ return;
+ } else if (!setting_name || !secrets || !g_hash_table_size (secrets)) {
+ /* Success, no secrets */
+ emit_initialized (page, NULL);
+ return;
+ }
+
+ setting_hash = g_hash_table_lookup (secrets, setting_name);
+ if (!setting_hash) {
+ /* Success, no secrets */
+ emit_initialized (page, NULL);
+ return;
+ }
+
+ if (nm_connection_update_secrets (page->connection,
+ setting_name,
+ secrets,
+ &update_error)) {
+ emit_initialized (page, NULL);
+ return;
+ }
+
+ if (!update_error) {
+ g_set_error_literal (&update_error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_UNKNOWN,
+ "Failed to update connection secrets due to an unknown error.");
+ }
+
+ emit_initialized (page, update_error);
+ g_clear_error (&update_error);
+}
+
+gchar **
+ce_page_get_mac_list (NMClient *client,
+ GType device_type,
+ const gchar *mac_property)
+{
+ const GPtrArray *devices;
+ GPtrArray *macs;
+ int i;
+
+ macs = g_ptr_array_new ();
+ devices = nm_client_get_devices (client);
+ for (i = 0; devices && (i < devices->len); i++) {
+ NMDevice *dev = g_ptr_array_index (devices, i);
+ const char *iface;
+ char *mac, *item;
+
+ if (!G_TYPE_CHECK_INSTANCE_TYPE (dev, device_type))
+ continue;
+
+ g_object_get (G_OBJECT (dev), mac_property, &mac, NULL);
+ iface = nm_device_get_iface (NM_DEVICE (dev));
+ item = g_strdup_printf ("%s (%s)", mac, iface);
+ g_free (mac);
+ g_ptr_array_add (macs, item);
+ }
+
+ g_ptr_array_add (macs, NULL);
+ return (char **)g_ptr_array_free (macs, FALSE);
+}
+
+void
+ce_page_setup_mac_combo (GtkComboBoxText *combo,
+ const gchar *current_mac,
+ gchar **mac_list)
+{
+ gchar **m, *active_mac = NULL;
+ gint current_mac_len;
+ GtkWidget *entry;
+
+ if (current_mac)
+ current_mac_len = strlen (current_mac);
+ else
+ current_mac_len = -1;
+
+ for (m= mac_list; m && *m; m++) {
+ gtk_combo_box_text_append_text (combo, *m);
+ if (current_mac &&
+ g_ascii_strncasecmp (*m, current_mac, current_mac_len) == 0
+ && ((*m)[current_mac_len] == '\0' || (*m)[current_mac_len] == ' '))
+ active_mac = *m;
+ }
+
+ if (current_mac) {
+ if (!active_mac) {
+ gtk_combo_box_text_prepend_text (combo, current_mac);
+ }
+
+ entry = gtk_bin_get_child (GTK_BIN (combo));
+ if (entry)
+ gtk_entry_set_text (GTK_ENTRY (entry), active_mac ? active_mac : current_mac);
+ }
+}
+
+void
+ce_page_mac_to_entry (const GByteArray *mac,
+ gint type,
+ GtkEntry *entry)
+{
+ char *str_addr;
+
+ g_return_if_fail (entry != NULL);
+ g_return_if_fail (GTK_IS_ENTRY (entry));
+
+ if (!mac || !mac->len)
+ return;
+
+ if (mac->len != nm_utils_hwaddr_len (type))
+ return;
+
+ str_addr = nm_utils_hwaddr_ntoa (mac->data, type);
+ gtk_entry_set_text (entry, str_addr);
+ g_free (str_addr);
+}
+
+static gboolean
+utils_ether_addr_valid (const struct ether_addr *test_addr)
+{
+ guint8 invalid_addr1[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+ guint8 invalid_addr2[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ guint8 invalid_addr3[ETH_ALEN] = {0x44, 0x44, 0x44, 0x44, 0x44, 0x44};
+ guint8 invalid_addr4[ETH_ALEN] = {0x00, 0x30, 0xb4, 0x00, 0x00, 0x00}; /* prism54 dummy MAC */
+
+ g_return_val_if_fail (test_addr != NULL, FALSE);
+
+ /* Compare the AP address the card has with invalid ethernet MAC addresses. */
+ if (!memcmp (test_addr->ether_addr_octet, &invalid_addr1, ETH_ALEN))
+ return FALSE;
+
+ if (!memcmp (test_addr->ether_addr_octet, &invalid_addr2, ETH_ALEN))
+ return FALSE;
+
+ if (!memcmp (test_addr->ether_addr_octet, &invalid_addr3, ETH_ALEN))
+ return FALSE;
+ if (!memcmp (test_addr->ether_addr_octet, &invalid_addr4, ETH_ALEN))
+ return FALSE;
+
+ if (test_addr->ether_addr_octet[0] & 1) /* Multicast addresses */
+ return FALSE;
+
+ return TRUE;
+}
+
+GByteArray *
+ce_page_entry_to_mac (GtkEntry *entry,
+ gint type,
+ gboolean *invalid)
+{
+ const char *temp, *sp;
+ char *buf = NULL;
+ GByteArray *mac;
+
+ g_return_val_if_fail (entry != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
+
+ if (invalid)
+ *invalid = FALSE;
+
+ temp = gtk_entry_get_text (entry);
+ if (!temp || !strlen (temp))
+ return NULL;
+
+ sp = strchr (temp, ' ');
+ if (sp)
+ temp = buf = g_strndup (temp, sp - temp);
+
+ mac = nm_utils_hwaddr_atoba (temp, type);
+ g_free (buf);
+ if (!mac) {
+ if (invalid)
+ *invalid = TRUE;
+ return NULL;
+ }
+
+ if (type == ARPHRD_ETHER && !utils_ether_addr_valid ((struct ether_addr *)mac->data)) {
+ g_byte_array_free (mac, TRUE);
+ if (invalid)
+ *invalid = TRUE;
+ return NULL;
+ }
+
+ return mac;
+}
+
+const gchar *
+ce_page_get_security_setting (CEPage *page)
+{
+ return page->security_setting;
+}
diff --git a/panels/network/connection-editor/ce-page.h b/panels/network/connection-editor/ce-page.h
new file mode 100644
index 0000000..7a08380
--- /dev/null
+++ b/panels/network/connection-editor/ce-page.h
@@ -0,0 +1,106 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __CE_PAGE_H
+#define __CE_PAGE_H
+
+#include <glib-object.h>
+
+#include <nm-connection.h>
+#include <nm-client.h>
+#include <nm-remote-settings.h>
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CE_TYPE_PAGE (ce_page_get_type ())
+#define CE_PAGE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CE_TYPE_PAGE, CEPage))
+#define CE_PAGE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CE_TYPE_PAGE, CEPageClass))
+#define CE_IS_PAGE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CE_TYPE_PAGE))
+#define CE_IS_PAGE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CE_TYPE_PAGE))
+#define CE_PAGE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CE_TYPE_PAGE, CEPageClass))
+
+typedef struct _CEPage CEPage;
+typedef struct _CEPageClass CEPageClass;
+
+struct _CEPage
+{
+ GObject parent;
+
+ gboolean initialized;
+ GtkBuilder *builder;
+ GtkWidget *page;
+ gchar *title;
+ const gchar *security_setting;
+
+ NMConnection *connection;
+ NMClient *client;
+ NMRemoteSettings *settings;
+};
+
+struct _CEPageClass
+{
+ GObjectClass parent_class;
+
+ gboolean (*validate) (CEPage *page, NMConnection *connection, GError **error);
+ void (*changed) (CEPage *page);
+ void (*initialized) (CEPage *page, GError *error);
+};
+
+GType ce_page_get_type (void);
+
+GtkWidget *ce_page_get_page (CEPage *page);
+const gchar *ce_page_get_title (CEPage *page);
+const gchar *ce_page_get_security_setting (CEPage *page);
+gboolean ce_page_validate (CEPage *page,
+ NMConnection *connection,
+ GError **error);
+gboolean ce_page_get_initialized (CEPage *page);
+void ce_page_changed (CEPage *page);
+CEPage *ce_page_new (GType type,
+ NMConnection *connection,
+ NMClient *client,
+ NMRemoteSettings *settings,
+ const gchar *ui_resource,
+ const gchar *title);
+void ce_page_complete_init (CEPage *page,
+ const gchar *setting_name,
+ GHashTable *secrets,
+ GError *error);
+
+gchar **ce_page_get_mac_list (NMClient *client,
+ GType device_type,
+ const gchar *mac_property);
+void ce_page_setup_mac_combo (GtkComboBoxText *combo,
+ const gchar *current_mac,
+ gchar **mac_list);
+void ce_page_mac_to_entry (const GByteArray *mac,
+ gint type,
+ GtkEntry *entry);
+GByteArray *ce_page_entry_to_mac (GtkEntry *entry,
+ gint type,
+ gboolean *invalid);
+
+G_END_DECLS
+
+#endif /* __CE_PAGE_H */
+
diff --git a/panels/network/connection-editor/connection-editor.gresource.xml b/panels/network/connection-editor/connection-editor.gresource.xml
new file mode 100644
index 0000000..a15e9bd
--- /dev/null
+++ b/panels/network/connection-editor/connection-editor.gresource.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/network">
+ <file preprocess="xml-stripblanks">connection-editor.ui</file>
+ <file preprocess="xml-stripblanks">details-page.ui</file>
+ <file preprocess="xml-stripblanks">ip4-page.ui</file>
+ <file preprocess="xml-stripblanks">ip6-page.ui</file>
+ <file preprocess="xml-stripblanks">reset-page.ui</file>
+ <file preprocess="xml-stripblanks">security-page.ui</file>
+ <file preprocess="xml-stripblanks">wifi-page.ui</file>
+ </gresource>
+</gresources>
diff --git a/panels/network/connection-editor/connection-editor.ui b/panels/network/connection-editor/connection-editor.ui
new file mode 100644
index 0000000..a8cb2d9
--- /dev/null
+++ b/panels/network/connection-editor/connection-editor.ui
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkListStore" id="details_store">
+ <columns>
+ <!-- column-name name -->
+ <column type="gchararray"/>
+ <!-- column-name page -->
+ <column type="gint"/>
+ </columns>
+ </object>
+ <object class="GtkDialog" id="details_dialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">5</property>
+ <property name="modal">True</property>
+ <property name="default_width">600</property>
+ <property name="default_height">300</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox2">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area2">
+ <property name="can_focus">False</property>
+ <property name="valign">end</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="details_cancel_button">
+ <property name="label">gtk-cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="details_apply_button">
+ <property name="label">gtk-apply</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkScrolledWindow" id="details_sidebar">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="details_page_list">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="model">details_store</property>
+ <property name="headers_visible">False</property>
+ <property name="headers_clickable">False</property>
+ <property name="search_column">0</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="details_page_list_selection"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="details_column">
+ <child>
+ <object class="GtkCellRendererText" id="details_cell">
+ <property name="xpad">10</property>
+ </object>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ <child>
+ <object class="GtkCellRendererText" id="padding_cell">
+ <property name="xpad">20</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkNotebook" id="details_notebook">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="show_tabs">False</property>
+ <property name="show_border">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="0">details_cancel_button</action-widget>
+ <action-widget response="0">details_apply_button</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/panels/network/connection-editor/details-page.ui b/panels/network/connection-editor/details-page.ui
new file mode 100644
index 0000000..02c9eca
--- /dev/null
+++ b/panels/network/connection-editor/details-page.ui
@@ -0,0 +1,402 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkBox" id="page">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox" id="auto_connect_box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label8">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Automatic _Connect</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">auto_connect_switch</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSwitch" id="auto_connect_switch">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="all_users_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Available to all _users</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">all_user_switch</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSwitch" id="all_user_switch">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">start</property>
+ <property name="margin_left">50</property>
+ <property name="margin_right">50</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">10</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="heading_strength">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Signal Strength</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_strength">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="xalign">0</property>
+ <property name="label">Weak</property>
+ <property name="selectable">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="heading_speed">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Link speed</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_speed">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="xalign">0</property>
+ <property name="label">1Mb/sec</property>
+ <property name="selectable">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="heading_security">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Security</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="heading_ipv4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">IPv4 Address</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="heading_ipv6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">IPv6 Address</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="heading_mac">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Hardware Address</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">5</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="heading_route">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Default Route</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">6</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="heading_dns">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="yalign">0</property>
+ <property name="label" translatable="yes">DNS</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">7</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="heading_last_used">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Last used</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">8</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_security">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="xalign">0</property>
+ <property name="label">WPA</property>
+ <property name="selectable">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_ipv4">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="xalign">0</property>
+ <property name="label">127.0.0.1</property>
+ <property name="selectable">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_ipv6">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="xalign">0</property>
+ <property name="label">::1</property>
+ <property name="selectable">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">4</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_mac">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="xalign">0</property>
+ <property name="label">AA:BB:CC:DD:55:66:77:88</property>
+ <property name="selectable">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">5</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_route">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="xalign">0</property>
+ <property name="label">127.0.0.1</property>
+ <property name="selectable">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">6</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_dns">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="label">127.0.0.1</property>
+ <property name="wrap">True</property>
+ <property name="selectable">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">7</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_last_used">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="xalign">0</property>
+ <property name="label">today</property>
+ <property name="selectable">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">8</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/panels/network/connection-editor/ip4-page.ui b/panels/network/connection-editor/ip4-page.ui
new file mode 100644
index 0000000..e5a46ab
--- /dev/null
+++ b/panels/network/connection-editor/ip4-page.ui
@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkScrolledWindow" id="page">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <child>
+ <object class="GtkViewport" id="viewport1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">20</property>
+ <property name="margin_right">20</property>
+ <property name="margin_top">10</property>
+ <property name="margin_bottom">10</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkBox" id="box5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="heading_enable">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">IPv_4</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">switch_enable</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSwitch" id="switch_enable">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="halign">end</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="page_content">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkBox" id="box7">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="heading_addresses">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Addresses</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">combo_addresses</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="combo_addresses">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="hexpand">True</property>
+ <property name="entry_text_column">0</property>
+ <property name="id_column">1</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="address_section">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="heading_dns">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">24</property>
+ <property name="margin_bottom">6</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">DNS</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="dns_section">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="heading_routes">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">24</property>
+ <property name="margin_bottom">6</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Routes</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="routes_section">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="never_default_check">
+ <property name="label" translatable="yes">Use this connection _only for resources on its network</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">7</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/panels/network/connection-editor/ip6-page.ui b/panels/network/connection-editor/ip6-page.ui
new file mode 100644
index 0000000..8ac22e5
--- /dev/null
+++ b/panels/network/connection-editor/ip6-page.ui
@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkScrolledWindow" id="page">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <child>
+ <object class="GtkViewport" id="viewport1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">20</property>
+ <property name="margin_right">20</property>
+ <property name="margin_top">10</property>
+ <property name="margin_bottom">10</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkBox" id="box5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="heading_enable">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">IPv_6</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">switch_enable</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSwitch" id="switch_enable">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="halign">end</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="page_content">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkBox" id="box7">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="heading_addresses">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Addresses</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">combo_addresses</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="combo_addresses">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="hexpand">True</property>
+ <property name="entry_text_column">0</property>
+ <property name="id_column">1</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="address_section">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="heading_dns">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">24</property>
+ <property name="margin_bottom">6</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">DNS</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="dns_section">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="heading_routes">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">24</property>
+ <property name="margin_bottom">6</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Routes</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="routes_section">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="never_default_check">
+ <property name="label" translatable="yes">Use this connection _only for resources on its network</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">7</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/panels/network/connection-editor/net-connection-editor.c b/panels/network/connection-editor/net-connection-editor.c
new file mode 100644
index 0000000..5faafb0
--- /dev/null
+++ b/panels/network/connection-editor/net-connection-editor.c
@@ -0,0 +1,420 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <glib/gi18n.h>
+
+#include <nm-utils.h>
+#include <nm-device-wifi.h>
+
+#include "net-connection-editor.h"
+#include "net-connection-editor-resources.h"
+#include "ce-page-details.h"
+#include "ce-page-wifi.h"
+#include "ce-page-ip4.h"
+#include "ce-page-ip6.h"
+#include "ce-page-security.h"
+#include "ce-page-reset.h"
+
+#include "egg-list-box/egg-list-box.h"
+
+enum {
+ DONE,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (NetConnectionEditor, net_connection_editor, G_TYPE_OBJECT)
+
+static void
+selection_changed (GtkTreeSelection *selection, NetConnectionEditor *editor)
+{
+ GtkWidget *widget;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gint page;
+
+ gtk_tree_selection_get_selected (selection, &model, &iter);
+ gtk_tree_model_get (model, &iter, 1, &page, -1);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (editor->builder,
+ "details_notebook"));
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), page);
+}
+
+static void
+cancel_editing (NetConnectionEditor *editor)
+{
+ gtk_widget_hide (editor->window);
+ g_signal_emit (editor, signals[DONE], 0, FALSE);
+}
+
+static void
+update_connection (NetConnectionEditor *editor)
+{
+ GHashTable *settings;
+
+ settings = nm_connection_to_hash (editor->connection, NM_SETTING_HASH_FLAG_ALL);
+ nm_connection_replace_settings (editor->orig_connection, settings, NULL);
+ g_hash_table_destroy (settings);
+}
+
+static void
+update_complete (NetConnectionEditor *editor, GError *error)
+{
+ gtk_widget_hide (editor->window);
+ g_signal_emit (editor, signals[DONE], 0, !error);
+}
+
+static void
+updated_connection_cb (NMRemoteConnection *connection, GError *error, gpointer data)
+{
+ NetConnectionEditor *editor = data;
+
+ nm_connection_clear_secrets (NM_CONNECTION (connection));
+
+ update_complete (editor, error);
+}
+
+static void
+apply_edits (NetConnectionEditor *editor)
+{
+ update_connection (editor);
+ nm_remote_connection_commit_changes (NM_REMOTE_CONNECTION (editor->orig_connection),
+ updated_connection_cb, editor);
+}
+
+static void
+net_connection_editor_init (NetConnectionEditor *editor)
+{
+ GtkTreeSelection *selection;
+ GError *error = NULL;
+ GtkWidget *button;
+
+ editor->builder = gtk_builder_new ();
+
+ gtk_builder_add_from_resource (editor->builder,
+ "/org/gnome/control-center/network/connection-editor.ui",
+ &error);
+ if (error != NULL) {
+ g_warning ("Could not load ui file: %s", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ /* set up widgets */
+
+ editor->window = GTK_WIDGET (gtk_builder_get_object (editor->builder, "details_dialog"));
+ selection = GTK_TREE_SELECTION (gtk_builder_get_object (editor->builder,
+ "details_page_list_selection"));
+ g_signal_connect (selection, "changed",
+ G_CALLBACK (selection_changed), editor);
+
+ button = GTK_WIDGET (gtk_builder_get_object (editor->builder, "details_cancel_button"));
+ g_signal_connect_swapped (button, "clicked",
+ G_CALLBACK (cancel_editing), editor);
+ g_signal_connect_swapped (editor->window, "delete-event",
+ G_CALLBACK (cancel_editing), editor);
+
+ button = GTK_WIDGET (gtk_builder_get_object (editor->builder, "details_apply_button"));
+ g_signal_connect_swapped (button, "clicked",
+ G_CALLBACK (apply_edits), editor);
+}
+
+static void
+net_connection_editor_finalize (GObject *object)
+{
+ NetConnectionEditor *editor = NET_CONNECTION_EDITOR (object);
+
+ g_clear_object (&editor->connection);
+ g_clear_object (&editor->orig_connection);
+ if (editor->window) {
+ gtk_widget_destroy (editor->window);
+ editor->window = NULL;
+ }
+ g_clear_object (&editor->parent_window);
+ g_clear_object (&editor->builder);
+ g_clear_object (&editor->device);
+ g_clear_object (&editor->settings);
+ g_clear_object (&editor->client);
+ g_clear_object (&editor->ap);
+
+ G_OBJECT_CLASS (net_connection_editor_parent_class)->finalize (object);
+}
+
+static void
+net_connection_editor_class_init (NetConnectionEditorClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ g_resources_register (net_connection_editor_get_resource ());
+
+ object_class->finalize = net_connection_editor_finalize;
+
+ signals[DONE] = g_signal_new ("done",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (NetConnectionEditorClass, done),
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+}
+
+static void
+net_connection_editor_update_title (NetConnectionEditor *editor)
+{
+ NMSettingWireless *sw;
+ const GByteArray *ssid;
+ gchar *id;
+
+ sw = nm_connection_get_setting_wireless (editor->connection);
+ ssid = nm_setting_wireless_get_ssid (sw);
+ id = nm_utils_ssid_to_utf8 (ssid);
+ gtk_window_set_title (GTK_WINDOW (editor->window), id);
+ g_free (id);
+}
+
+static gboolean
+editor_is_initialized (NetConnectionEditor *editor)
+{
+ return editor->initializing_pages == NULL;
+}
+
+static void
+validate (NetConnectionEditor *editor)
+{
+ gboolean valid = FALSE;
+ GSList *l;
+
+ if (!editor_is_initialized (editor))
+ goto done;
+
+ valid = TRUE;
+ for (l = editor->pages; l; l = l->next) {
+ GError *error = NULL;
+
+ if (!ce_page_validate (CE_PAGE (l->data), editor->connection, &error)) {
+ valid = FALSE;
+ if (error) {
+ g_warning ("Invalid setting %s: %s", ce_page_get_title (CE_PAGE (l->data)), error->message);
+ g_error_free (error);
+ } else {
+ g_warning ("Invalid setting %s", ce_page_get_title (CE_PAGE (l->data)));
+ }
+ }
+ }
+
+done:
+ gtk_widget_set_sensitive (GTK_WIDGET (gtk_builder_get_object (editor->builder, "details_apply_button")), valid);
+}
+
+static void
+page_changed (CEPage *page, gpointer user_data)
+{
+ NetConnectionEditor *editor= user_data;
+
+ validate (editor);
+}
+
+static gboolean
+idle_validate (gpointer user_data)
+{
+ validate (NET_CONNECTION_EDITOR (user_data));
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+recheck_initialization (NetConnectionEditor *editor)
+{
+ GtkNotebook *notebook;
+
+ if (!editor_is_initialized (editor))
+ return;
+
+ notebook = GTK_NOTEBOOK (gtk_builder_get_object (editor->builder, "details_notebook"));
+ gtk_notebook_set_current_page (notebook, 0);
+
+ g_idle_add (idle_validate, editor);
+}
+
+static void
+page_initialized (CEPage *page, GError *error, NetConnectionEditor *editor)
+{
+ GtkNotebook *notebook;
+ GtkWidget *widget;
+ gint position;
+ GList *children, *l;
+ gint i;
+
+ notebook = GTK_NOTEBOOK (gtk_builder_get_object (editor->builder, "details_notebook"));
+ widget = ce_page_get_page (page);
+ position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (page), "position"));
+ g_object_set_data (G_OBJECT (widget), "position", GINT_TO_POINTER (position));
+ children = gtk_container_get_children (GTK_CONTAINER (notebook));
+ for (l = children, i = 0; l; l = l->next, i++) {
+ gint pos = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (l->data), "position"));
+ if (pos > position)
+ break;
+ }
+ g_list_free (children);
+ gtk_notebook_insert_page (notebook, widget, NULL, i);
+
+ editor->initializing_pages = g_slist_remove (editor->initializing_pages, page);
+ editor->pages = g_slist_append (editor->pages, page);
+
+ recheck_initialization (editor);
+}
+
+typedef struct {
+ NetConnectionEditor *editor;
+ CEPage *page;
+ const gchar *setting_name;
+ gboolean canceled;
+} GetSecretsInfo;
+
+static void
+get_secrets_cb (NMRemoteConnection *connection,
+ GHashTable *secrets,
+ GError *error,
+ gpointer user_data)
+{
+ GetSecretsInfo *info = user_data;
+
+ if (info->canceled) {
+ g_free (info);
+ return;
+ }
+
+ ce_page_complete_init (info->page, info->setting_name, secrets, error);
+ g_free (info);
+}
+
+static void
+get_secrets_for_page (NetConnectionEditor *editor,
+ CEPage *page,
+ const gchar *setting_name)
+{
+ GetSecretsInfo *info;
+
+ info = g_new0 (GetSecretsInfo, 1);
+ info->editor = editor;
+ info->page = page;
+ info->setting_name = setting_name;
+
+ nm_remote_connection_get_secrets (NM_REMOTE_CONNECTION (editor->orig_connection),
+ setting_name,
+ get_secrets_cb,
+ info);
+}
+
+static void
+add_page (NetConnectionEditor *editor, CEPage *page)
+{
+ GtkListStore *store;
+ GtkTreeIter iter;
+ const gchar *title;
+ gint position;
+
+ store = GTK_LIST_STORE (gtk_builder_get_object (editor->builder,
+ "details_store"));
+ title = ce_page_get_title (page);
+ position = g_slist_length (editor->initializing_pages);
+ g_object_set_data (G_OBJECT (page), "position", GINT_TO_POINTER (position));
+ gtk_list_store_insert_with_values (store, &iter, -1,
+ 0, title,
+ 1, position,
+ -1);
+ editor->initializing_pages = g_slist_append (editor->initializing_pages, page);
+
+ g_signal_connect (page, "changed", G_CALLBACK (page_changed), editor);
+ g_signal_connect (page, "initialized", G_CALLBACK (page_initialized), editor);
+}
+
+static void
+net_connection_editor_set_connection (NetConnectionEditor *editor,
+ NMConnection *connection)
+{
+ GSList *pages, *l;
+
+ editor->connection = nm_connection_duplicate (connection);
+ editor->orig_connection = g_object_ref (connection);
+
+ net_connection_editor_update_title (editor);
+
+ add_page (editor, ce_page_details_new (editor->connection, editor->client, editor->settings, editor->device, editor->ap));
+ add_page (editor, ce_page_wifi_new (editor->connection, editor->client, editor->settings));
+ add_page (editor, ce_page_ip4_new (editor->connection, editor->client, editor->settings));
+ add_page (editor, ce_page_ip6_new (editor->connection, editor->client, editor->settings));
+ add_page (editor, ce_page_security_new (editor->connection, editor->client, editor->settings));
+ add_page (editor, ce_page_reset_new (editor->connection, editor->client, editor->settings));
+
+ pages = g_slist_copy (editor->initializing_pages);
+ for (l = pages; l; l = l->next) {
+ CEPage *page = l->data;
+ const gchar *security_setting;
+
+ security_setting = ce_page_get_security_setting (page);
+ if (!security_setting) {
+ ce_page_complete_init (page, NULL, NULL, NULL);
+ } else {
+ get_secrets_for_page (editor, page, security_setting);
+ }
+ }
+ g_slist_free (pages);
+}
+
+NetConnectionEditor *
+net_connection_editor_new (GtkWindow *parent_window,
+ NMConnection *connection,
+ NMDevice *device,
+ NMAccessPoint *ap,
+ NMClient *client,
+ NMRemoteSettings *settings)
+{
+ NetConnectionEditor *editor;
+
+ editor = g_object_new (NET_TYPE_CONNECTION_EDITOR, NULL);
+
+ if (parent_window) {
+ editor->parent_window = g_object_ref (parent_window);
+ gtk_window_set_transient_for (GTK_WINDOW (editor->window),
+ parent_window);
+ }
+ if (ap)
+ editor->ap = g_object_ref (ap);
+ editor->device = g_object_ref (device);
+ editor->client = g_object_ref (client);
+ editor->settings = g_object_ref (settings);
+
+ net_connection_editor_set_connection (editor, connection);
+
+ return editor;
+}
+
+void
+net_connection_editor_present (NetConnectionEditor *editor)
+{
+ gtk_window_present (GTK_WINDOW (editor->window));
+}
diff --git a/panels/network/connection-editor/net-connection-editor.h b/panels/network/connection-editor/net-connection-editor.h
new file mode 100644
index 0000000..274c2c1
--- /dev/null
+++ b/panels/network/connection-editor/net-connection-editor.h
@@ -0,0 +1,83 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __NET_CONNECTION_EDITOR_H
+#define __NET_CONNECTION_EDITOR_H
+
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+#include <nm-client.h>
+#include <nm-access-point.h>
+#include <nm-remote-settings.h>
+
+G_BEGIN_DECLS
+
+#define NET_TYPE_CONNECTION_EDITOR (net_connection_editor_get_type ())
+#define NET_CONNECTION_EDITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), NET_TYPE_CONNECTION_EDITOR, NetConnectionEditor))
+#define NET_CONNECTION_EDITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), NET_TYPE_CONNECTION_EDITOR, NetConnectionEditorClass))
+#define NET_IS_CONNECTION_EDITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), NET_TYPE_CONNECTION_EDITOR))
+#define NET_IS_CONNECTION_EDITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), NET_TYPE_CONNECTION_EDITOR))
+#define NET_CONNECTION_EDITOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), NET_TYPE_CONNECTION_EDITOR, NetConnectionEditorClass))
+
+typedef struct _NetConnectionEditor NetConnectionEditor;
+typedef struct _NetConnectionEditorClass NetConnectionEditorClass;
+
+struct _NetConnectionEditor
+{
+ GObject parent;
+
+ GtkWidget *parent_window;
+ NMClient *client;
+ NMDevice *device;
+ NMRemoteSettings *settings;
+
+ NMConnection *connection;
+ NMConnection *orig_connection;
+ NMAccessPoint *ap;
+
+ GtkBuilder *builder;
+ GtkWidget *window;
+
+ GSList *initializing_pages;
+ GSList *pages;
+};
+
+struct _NetConnectionEditorClass
+{
+ GObjectClass parent_class;
+
+ void (*done) (NetConnectionEditor *details, gboolean success);
+};
+
+GType net_connection_editor_get_type (void);
+NetConnectionEditor *net_connection_editor_new (GtkWindow *parent_window,
+ NMConnection *connection,
+ NMDevice *device,
+ NMAccessPoint *ap,
+ NMClient *client,
+ NMRemoteSettings *settings);
+void net_connection_editor_present (NetConnectionEditor *details);
+
+G_END_DECLS
+
+#endif /* __NET_CONNECTION_EDITOR_H */
+
diff --git a/panels/network/connection-editor/reset-page.ui b/panels/network/connection-editor/reset-page.ui
new file mode 100644
index 0000000..91ca84b
--- /dev/null
+++ b/panels/network/connection-editor/reset-page.ui
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkGrid" id="page">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">50</property>
+ <property name="margin_right">50</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="row_spacing">10</property>
+ <property name="column_spacing">10</property>
+ <child>
+ <object class="GtkButton" id="button_reset">
+ <property name="label" translatable="yes">_Reset</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="valign">start</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="button_forget">
+ <property name="label" translatable="yes">_Forget</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="valign">start</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_reset">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Reset the settings for this connection to their defaults, but remember as a preferred connection.</property>
+ <property name="wrap">True</property>
+ <property name="max_width_chars">40</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_forget">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Remove all details relating to this network and do not try to automatically connect to it.</property>
+ <property name="wrap">True</property>
+ <property name="max_width_chars">30</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/panels/network/connection-editor/security-page.ui b/panels/network/connection-editor/security-page.ui
new file mode 100644
index 0000000..969b566
--- /dev/null
+++ b/panels/network/connection-editor/security-page.ui
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkGrid" id="page">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">50</property>
+ <property name="margin_right">50</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">10</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="heading_sec">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">S_ecurity</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">combo_sec</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="combo_sec">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="vbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">2</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/panels/network/connection-editor/wifi-page.ui b/panels/network/connection-editor/wifi-page.ui
new file mode 100644
index 0000000..5e46730
--- /dev/null
+++ b/panels/network/connection-editor/wifi-page.ui
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkGrid" id="page">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">50</property>
+ <property name="margin_right">50</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">10</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="heading_ssid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_SSID</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">entry_ssid</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="heading_bssid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_BSSID</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">combo_bssid</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry_ssid">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="invisible_char">â</property>
+ <property name="text" translatable="yes">My Home Network</property>
+ <property name="invisible_char_set">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="heading_mac">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_MAC Address</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">combo_mac</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry_cloned_mac">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="invisible_char">â</property>
+ <property name="invisible_char_set">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="heading_cloned_mac">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Cloned MAC Address</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">entry_cloned_mac</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="combo_bssid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="has_entry">True</property>
+ <property name="entry_text_column">0</property>
+ <property name="id_column">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="combo_mac">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="has_entry">True</property>
+ <property name="entry_text_column">0</property>
+ <property name="id_column">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/panels/network/net-device-wifi.c b/panels/network/net-device-wifi.c
index 6bac72a..98deed2 100644
--- a/panels/network/net-device-wifi.c
+++ b/panels/network/net-device-wifi.c
@@ -41,6 +41,7 @@
#include "egg-list-box/egg-list-box.h"
+#include "connection-editor/net-connection-editor.h"
#include "net-device-wifi.h"
#define NET_DEVICE_WIFI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NET_TYPE_DEVICE_WIFI, NetDeviceWifiPrivate))
@@ -557,20 +558,6 @@ nm_device_wifi_refresh_ui (NetDeviceWifi *device_wifi)
"speed",
str_tmp);
- /* set device state, with status and optionally speed */
- widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->priv->builder, "label_status"));
- if (ap != active_ap) {
- if (ap)
- gtk_label_set_label (GTK_LABEL (widget), _("Not connected"));
- else
- gtk_label_set_label (GTK_LABEL (widget), _("Out of range"));
- gtk_widget_set_tooltip_text (widget, "");
- } else {
- gtk_label_set_label (GTK_LABEL (widget),
- panel_device_state_to_localized_string (nm_device));
- gtk_widget_set_tooltip_text (widget, panel_device_state_reason_to_localized_string (nm_device));
- }
-
/* device MAC */
str = nm_device_wifi_get_hw_address (NM_DEVICE_WIFI (nm_device));
panel_set_device_widget_details (device_wifi->priv->builder,
@@ -607,29 +594,6 @@ nm_device_wifi_refresh_ui (NetDeviceWifi *device_wifi)
"strength",
str);
- widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->priv->builder, "label_device"));
- gtk_label_set_label (GTK_LABEL (widget),
- priv->selected_ssid_title ? priv->selected_ssid_title : net_object_get_title (NET_OBJECT (device_wifi)));
-
- /* only disconnect when connection active */
- if (ap == active_ap) {
- widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->priv->builder,
- "button_disconnect1"));
- gtk_widget_set_sensitive (widget, state == NM_DEVICE_STATE_ACTIVATED);
- gtk_widget_show (widget);
- widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->priv->builder,
- "button_connect1"));
- gtk_widget_hide (widget);
- } else {
- widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->priv->builder,
- "button_disconnect1"));
- gtk_widget_hide (widget);
- widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->priv->builder,
- "button_connect1"));
- gtk_widget_show (widget);
- gtk_widget_set_sensitive (widget, ap != NULL);
- }
-
/* device MAC */
if (ap != active_ap)
str = NULL;
@@ -643,7 +607,7 @@ nm_device_wifi_refresh_ui (NetDeviceWifi *device_wifi)
else
panel_set_device_widgets (priv->builder, nm_device);
- if (ap != active_ap)
+ if (ap != active_ap && connection)
update_last_used (device_wifi, connection);
else
panel_set_device_widget_details (priv->builder, "last_used", NULL);
@@ -1276,27 +1240,6 @@ show_wifi_list (NetDeviceWifi *device_wifi)
}
static void
-edit_connection (GtkButton *button, NetDeviceWifi *device_wifi)
-{
- GtkWidget *dialog;
- NMConnection *connection;
- const gchar *uuid;
- gchar *cmdline;
- GError *error = NULL;
-
- dialog = gtk_widget_get_toplevel (GTK_WIDGET (button));
- connection = g_object_get_data (G_OBJECT (dialog), "connection");
- uuid = nm_connection_get_uuid (connection);
- cmdline = g_strdup_printf ("nm-connection-editor --edit %s", uuid);
- g_debug ("Launching '%s'\n", cmdline);
- if (!g_spawn_command_line_async (cmdline, &error)) {
- g_warning ("Failed to launch nm-connection-editor: %s", error->message);
- g_error_free (error);
- }
- g_free (cmdline);
-}
-
-static void
remote_settings_read_cb (NMRemoteSettings *remote_settings,
NetDeviceWifi *device_wifi)
{
@@ -1723,65 +1666,11 @@ ap_sort (gconstpointer a, gconstpointer b, gpointer data)
}
static void
-close_details (GtkWidget *widget)
-{
- gtk_widget_hide (widget);
- g_object_set_data (G_OBJECT (widget), "connection", NULL);
- g_object_set_data (G_OBJECT (widget), "ap", NULL);
-}
-
-static void
-open_details (NMConnection *connection,
- NMAccessPoint *ap,
- NetDeviceWifi *device_wifi,
- GtkWidget *toplevel)
+editor_done (NetConnectionEditor *editor,
+ gboolean success,
+ NetDeviceWifi *device_wifi)
{
- GtkWidget *dialog;
- GtkWidget *widget;
- NMSettingWireless *sw;
- const GByteArray *ssid;
- gchar *title;
-
- g_assert (connection != NULL);
-
- dialog = GTK_WIDGET (gtk_builder_get_object (device_wifi->priv->builder,
- "details_dialog"));
-
- g_object_set_data (G_OBJECT (dialog), "connection", connection);
- g_object_set_data (G_OBJECT (dialog), "ap", ap);
-
- nm_device_wifi_refresh_ui (device_wifi);
-#if 1
- /* hide unimplemented editing stuff */
- widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->priv->builder,
- "auto_connect_box"));
- gtk_widget_hide (widget);
-
- widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->priv->builder,
- "details_sidebar"));
- gtk_widget_hide (widget);
-
- widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->priv->builder,
- "details_apply_button"));
- gtk_widget_hide (widget);
-#endif
-
- widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->priv->builder,
- "details_cancel_button"));
- gtk_button_set_label (GTK_BUTTON (widget), _("_Close"));
- g_signal_connect_swapped (widget, "clicked",
- G_CALLBACK (close_details), dialog);
- g_signal_connect (dialog, "delete-event",
- G_CALLBACK (close_details), NULL);
-
- sw = nm_connection_get_setting_wireless (connection);
- ssid = nm_setting_wireless_get_ssid (sw);
- title = g_markup_escape_text (nm_utils_escape_ssid (ssid->data, ssid->len), -1);
- gtk_window_set_title (GTK_WINDOW (dialog), title);
- g_free (title);
- gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (toplevel));
-
- gtk_window_present (GTK_WINDOW (dialog));
+ g_object_unref (editor);
}
static void
@@ -1791,6 +1680,10 @@ show_details_for_row (GtkButton *button, NetDeviceWifi *device_wifi)
NMConnection *connection;
NMAccessPoint *ap;
GtkWidget *window;
+ NetConnectionEditor *editor;
+ NMClient *client;
+ NMRemoteSettings *settings;
+ NMDevice *device;
window = gtk_widget_get_toplevel (GTK_WIDGET (button));
@@ -1798,7 +1691,12 @@ show_details_for_row (GtkButton *button, NetDeviceWifi *device_wifi)
connection = NM_CONNECTION (g_object_get_data (G_OBJECT (row), "connection"));
ap = NM_ACCESS_POINT (g_object_get_data (G_OBJECT (row), "ap"));
- open_details (connection, ap, device_wifi, window);
+ device = net_device_get_nm_device (NET_DEVICE (device_wifi));
+ client = net_object_get_client (NET_OBJECT (device_wifi));
+ settings = net_object_get_remote_settings (NET_OBJECT (device_wifi));
+ editor = net_connection_editor_new (GTK_WINDOW (window), connection, device, ap, client, settings);
+ g_signal_connect (editor, "done", G_CALLBACK (editor_done), device_wifi);
+ net_connection_editor_present (editor);
}
static void
@@ -1894,8 +1792,7 @@ open_history (NetDeviceWifi *device_wifi)
const GByteArray *ssid_ap;
ap = NM_ACCESS_POINT (g_ptr_array_index (aps_unique, i));
ssid_ap = nm_access_point_get_ssid (ap);
- if (ssid->len == ssid_ap->len &&
- memcmp (ssid->data, ssid_ap->data, ssid->len) == 0)
+ if (nm_utils_same_ssid (ssid, ssid_ap, TRUE))
break;
ap = NULL;
}
@@ -1971,8 +1868,7 @@ populate_ap_list (NetDeviceWifi *device_wifi)
setting = nm_connection_get_setting_by_name (connection, NM_SETTING_WIRELESS_SETTING_NAME);
ssid = nm_setting_wireless_get_ssid (NM_SETTING_WIRELESS (setting));
- if (ssid->len == ssid_ap->len &&
- memcmp (ssid->data, ssid_ap->data, ssid->len) == 0)
+ if (nm_utils_same_ssid (ssid, ssid_ap, TRUE))
break;
connection = NULL;
}
@@ -2054,11 +1950,6 @@ net_device_wifi_init (NetDeviceWifi *device_wifi)
g_signal_connect (widget, "notify::active",
G_CALLBACK (device_off_toggled), device_wifi);
- widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->priv->builder,
- "button_options1"));
- g_signal_connect (widget, "clicked",
- G_CALLBACK (edit_connection), device_wifi);
-
swin = GTK_WIDGET (gtk_builder_get_object (device_wifi->priv->builder,
"scrolledwindow_list"));
list = GTK_WIDGET (egg_list_box_new ());
diff --git a/panels/network/network-wifi.ui b/panels/network/network-wifi.ui
index 2d80c3c..9e76ac8 100644
--- a/panels/network/network-wifi.ui
+++ b/panels/network/network-wifi.ui
@@ -1,40 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.0 -->
- <object class="GtkListStore" id="details_store">
- <columns>
- <!-- column-name name -->
- <column type="gchararray"/>
- <!-- column-name page -->
- <column type="gint"/>
- </columns>
- <data>
- <row>
- <col id="0" translatable="yes">Details</col>
- <col id="1">0</col>
- </row>
- <row>
- <col id="0" translatable="yes">Identity</col>
- <col id="1">1</col>
- </row>
- <row>
- <col id="0" translatable="yes">IPv4</col>
- <col id="1">2</col>
- </row>
- <row>
- <col id="0" translatable="yes">IPv6</col>
- <col id="1">3</col>
- </row>
- <row>
- <col id="0" translatable="yes">Hardware</col>
- <col id="1">4</col>
- </row>
- <row>
- <col id="0" translatable="yes">Reset</col>
- <col id="1">5</col>
- </row>
- </data>
- </object>
<object class="GtkDialog" id="details_dialog">
<property name="can_focus">False</property>
<property name="border_width">5</property>
@@ -53,25 +19,6 @@
<property name="valign">end</property>
<property name="layout_style">end</property>
<child>
- <object class="GtkButton" id="button_options1">
- <property name="label" translatable="yes">_Settingsâ</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="halign">end</property>
- <property name="valign">end</property>
- <property name="hexpand">True</property>
- <property name="vexpand">True</property>
- <property name="use_underline">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- <property name="secondary">True</property>
- </packing>
- </child>
- <child>
<object class="GtkButton" id="details_cancel_button">
<property name="label">gtk-cancel</property>
<property name="visible">True</property>
@@ -126,18 +73,24 @@
<property name="headers_clickable">False</property>
<property name="search_column">0</property>
<child internal-child="selection">
- <object class="GtkTreeSelection" id="treeview-selection"/>
+ <object class="GtkTreeSelection" id="details_page_list_selection"/>
</child>
<child>
<object class="GtkTreeViewColumn" id="details_column">
<child>
<object class="GtkCellRendererText" id="details_cell">
- <property name="width_chars">50</property>
+ <property name="xpad">10</property>
</object>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
+ <child>
+ <object class="GtkCellRendererText" id="padding_cell">
+ <property name="xpad">20</property>
+ <property name="text"></property>
+ </object>
+ </child>
</object>
</child>
</object>
@@ -154,6 +107,7 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="show_tabs">False</property>
+ <property name="show_border">False</property>
<child>
<object class="GtkBox" id="box8">
<property name="visible">True</property>
@@ -207,6 +161,8 @@
<property name="margin_right">50</property>
<property name="margin_top">12</property>
<property name="margin_bottom">12</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
<property name="row_spacing">10</property>
<property name="column_spacing">6</property>
<child>
@@ -216,7 +172,6 @@
<property name="hexpand">True</property>
<property name="xalign">1</property>
<property name="label" translatable="yes">Signal Strength</property>
- <property name="mnemonic_widget">label_strength2</property>
<style>
<class name="dim-label"/>
</style>
@@ -250,7 +205,6 @@
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="label" translatable="yes">Link speed</property>
- <property name="mnemonic_widget">label_speed2</property>
<style>
<class name="dim-label"/>
</style>
@@ -283,7 +237,6 @@
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="label" translatable="yes">Security</property>
- <property name="mnemonic_widget">label_security2</property>
<style>
<class name="dim-label"/>
</style>
@@ -301,7 +254,6 @@
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="label" translatable="yes">IPv4 Address</property>
- <property name="mnemonic_widget">label_ipv42</property>
<style>
<class name="dim-label"/>
</style>
@@ -319,7 +271,6 @@
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="label" translatable="yes">IPv6 Address</property>
- <property name="mnemonic_widget">label_ipv62</property>
<style>
<class name="dim-label"/>
</style>
@@ -337,7 +288,6 @@
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="label" translatable="yes">Hardware Address</property>
- <property name="mnemonic_widget">label_mac2</property>
<style>
<class name="dim-label"/>
</style>
@@ -355,7 +305,6 @@
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="label" translatable="yes">Default Route</property>
- <property name="mnemonic_widget">label_route2</property>
<style>
<class name="dim-label"/>
</style>
@@ -374,7 +323,6 @@
<property name="xalign">1</property>
<property name="yalign">0</property>
<property name="label" translatable="yes">DNS</property>
- <property name="mnemonic_widget">label_dns2</property>
<style>
<class name="dim-label"/>
</style>
@@ -392,7 +340,6 @@
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="label" translatable="yes">Last used</property>
- <property name="mnemonic_widget">label_last_used2</property>
<style>
<class name="dim-label"/>
</style>
@@ -524,20 +471,213 @@
<object class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label" translatable="yes">page 1</property>
+ <property name="label" translatable="yes">details</property>
</object>
<packing>
<property name="tab_fill">False</property>
</packing>
</child>
<child>
- <placeholder/>
+ <object class="GtkGrid" id="grid3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">50</property>
+ <property name="margin_right">50</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">10</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="heading_ssid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_SSID</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">entry_ssid</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="heading_bssid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_BSSID</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">entry_bssid</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="heading_sec">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">S_ecurity</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">combo_sec</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_password">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">entry_password</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry_ssid">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="invisible_char">â</property>
+ <property name="text" translatable="yes">My Home Network</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry_bssid">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="invisible_char">â</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="combo_sec">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="entry_text_column">0</property>
+ <property name="id_column">1</property>
+ <items>
+ <item translatable="yes">WPA</item>
+ <item translatable="yes">None</item>
+ </items>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry_password">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="visibility">False</property>
+ <property name="invisible_char">â</property>
+ <property name="text" translatable="yes">blablabla</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="show_password_check">
+ <property name="label" translatable="yes">Show P_assword</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="valign">center</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">4</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label9">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="all_user_check">
+ <property name="label" translatable="yes">Make available to other users</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="valign">end</property>
+ <property name="vexpand">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">5</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
</child>
<child type="tab">
<object class="GtkLabel" id="label6">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label" translatable="yes">page 2</property>
+ <property name="label" translatable="yes">identity</property>
</object>
<packing>
<property name="position">1</property>
@@ -545,19 +685,745 @@
</packing>
</child>
<child>
- <placeholder/>
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkViewport" id="viewport1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">10</property>
+ <property name="margin-left">20</property>
+ <property name="margin-right">20</property>
+ <property name="margin-top">10</property>
+ <property name="margin-bottom">10</property>
+ <child>
+ <object class="GtkBox" id="box5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="heading_ipv4_ipv4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">IPv_4</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">switch_ipv4_ipv4</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSwitch" id="switch_ipv4_ipv4">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="halign">end</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box7">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="heading_ipv4_addresses">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Addresses</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">combo_ipv4_addresses</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="combo_ipv4_addresses">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="hexpand">True</property>
+ <property name="entry_text_column">0</property>
+ <property name="id_column">1</property>
+ <items>
+ <item translatable="yes">Manual</item>
+ <item translatable="yes">Automatic (DHCP)</item>
+ <item translatable="yes">Automatic (DHCP) addresses only</item>
+ <item translatable="yes">Link-local only</item>
+ <item translatable="yes">Shared with other computers</item>
+ <item translatable="yes">Disabled</item>
+ </items>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="details_ipv4_address_section">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="label10">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Address
+section
+goes
+here</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="details_ipv4_dns_heading">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">24</property>
+ <property name="margin_bottom">6</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">DNS</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="details_ipv4_dns_section">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="label11">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">DNS
+section
+goes
+here</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="details_ipv4_routes_heading">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">24</property>
+ <property name="margin_bottom">6</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Routes</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="details_ipv4_routes_section">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="label12">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Routes
+section
+goes
+here</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="details_ipv4_auto_routes_check">
+ <property name="label" translatable="yes">_Ignore automatically obtained routes</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="details_ipv4_network_resources_check">
+ <property name="label" translatable="yes">Use this connection _only for resources on its network</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">8</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
</child>
<child type="tab">
<object class="GtkLabel" id="label7">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label" translatable="yes">page 3</property>
+ <property name="label" translatable="yes">ipv4</property>
</object>
<packing>
<property name="position">2</property>
<property name="tab_fill">False</property>
</packing>
</child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkViewport" id="viewport2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkBox" id="box10">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkBox" id="box11">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="heading_ipv6_ipv6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">IPv_6</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">switch_ipv6_ipv6</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSwitch" id="switch_ipv6_ipv6">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="halign">end</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box12">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="heading_ipv6_addresses">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Addresses</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">combo_ipv6_addresses</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="combo_ipv6_addresses">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="hexpand">True</property>
+ <property name="entry_text_column">0</property>
+ <property name="id_column">1</property>
+ <items>
+ <item translatable="yes">Manual</item>
+ <item translatable="yes">Automatic (DHCP)</item>
+ <item translatable="yes">Automatic (DHCP) addresses only</item>
+ <item translatable="yes">Link-local only</item>
+ <item translatable="yes">Shared with other computers</item>
+ <item translatable="yes">Disabled</item>
+ </items>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="details_ipv6_address_section">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="label13">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Address
+section
+goes
+here</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="details_ipv6_dns_heading">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">24</property>
+ <property name="margin_bottom">6</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">DNS</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="details_ipv6_dns_section">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="label14">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">DNS
+section
+goes
+here</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="details_ipv6_routes_heading">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">24</property>
+ <property name="margin_bottom">6</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Routes</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="details_ipv6_routes_section">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="label15">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Routes
+section
+goes
+here</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="details_ipv6_auto_routes_check">
+ <property name="label" translatable="yes">_Ignore automatically obtained routes</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="details_ipv6_network_resources_check">
+ <property name="label" translatable="yes">Use this connection _only for resources on its network</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">8</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">ipv6</property>
+ </object>
+ <packing>
+ <property name="position">3</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="grid4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">50</property>
+ <property name="margin_right">50</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">10</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="heading_hw_mac">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_MAC Address</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">label_hw_mac</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="heading_hw_cloned_mac">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Cloned MAC Address</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">entry_hw_cloned_mac</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_hw_mac">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">00:24:16:31:8G:7A</property>
+ <property name="selectable">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry_hw_cloned_mac">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="invisible_char">â</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">hardware</property>
+ </object>
+ <packing>
+ <property name="position">4</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="grid5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">50</property>
+ <property name="margin_right">50</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="row_spacing">10</property>
+ <property name="column_spacing">10</property>
+ <child>
+ <object class="GtkButton" id="button_reset">
+ <property name="label" translatable="yes">_Reset</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="valign">start</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="button_forget">
+ <property name="label" translatable="yes">_Forget</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="valign">start</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_reset">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Reset the settings for this connection to their defaults, but remember as a preferred connection.</property>
+ <property name="wrap">True</property>
+ <property name="max_width_chars">40</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_forget">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Remove all details relating to this network and do not try to automatically connect to it.</property>
+ <property name="wrap">True</property>
+ <property name="max_width_chars">30</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">reset</property>
+ </object>
+ <packing>
+ <property name="position">5</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
</object>
<packing>
<property name="expand">True</property>
@@ -575,11 +1441,44 @@
</object>
</child>
<action-widgets>
- <action-widget response="0">button_options1</action-widget>
<action-widget response="0">details_cancel_button</action-widget>
<action-widget response="0">details_apply_button</action-widget>
</action-widgets>
</object>
+ <object class="GtkListStore" id="details_store">
+ <columns>
+ <!-- column-name name -->
+ <column type="gchararray"/>
+ <!-- column-name page -->
+ <column type="gint"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">Details</col>
+ <col id="1">0</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Identity</col>
+ <col id="1">1</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">IPv4</col>
+ <col id="1">2</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">IPv6</col>
+ <col id="1">3</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Hardware</col>
+ <col id="1">4</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Reset</col>
+ <col id="1">5</col>
+ </row>
+ </data>
+ </object>
<object class="GtkDialog" id="hotspot-dialog">
<property name="can_focus">False</property>
<property name="border_width">5</property>
diff --git a/panels/network/wireless-security/Makefile.am b/panels/network/wireless-security/Makefile.am
new file mode 100644
index 0000000..9c951a0
--- /dev/null
+++ b/panels/network/wireless-security/Makefile.am
@@ -0,0 +1,55 @@
+noinst_LTLIBRARIES = libwireless-security.la
+
+BUILT_SOURCES = \
+ wireless-security-resources.h \
+ wireless-security-resources.c
+
+libwireless_security_la_SOURCES = \
+ $(BUILT_SOURCES) \
+ wireless-security.h \
+ wireless-security.c \
+ ws-wep-key.h \
+ ws-wep-key.c \
+ ws-wpa-psk.h \
+ ws-wpa-psk.c \
+ ws-leap.h \
+ ws-leap.c \
+ ws-wpa-eap.h \
+ ws-wpa-eap.c \
+ ws-dynamic-wep.h \
+ ws-dynamic-wep.c \
+ eap-method.h \
+ eap-method.c \
+ eap-method-tls.h \
+ eap-method-tls.c \
+ eap-method-leap.h \
+ eap-method-leap.c \
+ eap-method-fast.h \
+ eap-method-fast.c \
+ eap-method-ttls.h \
+ eap-method-ttls.c \
+ eap-method-peap.h \
+ eap-method-peap.c \
+ eap-method-simple.h \
+ eap-method-simple.c \
+ helpers.h \
+ helpers.c
+
+libwireless_security_la_CPPFLAGS = \
+ $(NETWORK_PANEL_CFLAGS) \
+ $(NETWORK_MANAGER_CFLAGS) \
+ -DUIDIR=\""$(uidir)"\"
+
+libwireless_security_la_LIBADD = \
+ $(NETWORK_PANEL_LIBS) \
+ $(NETWORK_MANAGER_LIBS)
+
+resource_files = $(shell glib-compile-resources --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/wireless-security.gresource.xml)
+wireless-security-resources.c: wireless-security.gresource.xml $(resource_files)
+ $(AM_V_GEN) glib-compile-resources --target=$@ --sourcedir=$(srcdir) --generate-source --c-name wireless_security $<
+wireless-security-resources.h: wireless-security.gresource.xml $(resource_files)
+ $(AM_V_GEN) glib-compile-resources --target=$@ --sourcedir=$(srcdir) --generate-header --c-name wireless_security $<
+
+EXTRA_DIST = \
+ $(resource_files)
+
diff --git a/panels/network/wireless-security/eap-method-fast.c b/panels/network/wireless-security/eap-method-fast.c
new file mode 100644
index 0000000..dc042dd
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-fast.c
@@ -0,0 +1,443 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* vim: set ft=c ts=4 sts=4 sw=4 noexpandtab smartindent: */
+
+/* EAP-FAST authentication method (RFC4851)
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2012 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <ctype.h>
+#include <string.h>
+
+#include <nm-setting-connection.h>
+#include <nm-setting-8021x.h>
+
+#include "eap-method.h"
+#include "wireless-security.h"
+
+#define I_NAME_COLUMN 0
+#define I_METHOD_COLUMN 1
+
+struct _EAPMethodFAST {
+ EAPMethod parent;
+
+ GtkSizeGroup *size_group;
+ WirelessSecurity *sec_parent;
+ gboolean is_editor;
+};
+
+static void
+destroy (EAPMethod *parent)
+{
+ EAPMethodFAST *method = (EAPMethodFAST *) parent;
+
+ if (method->size_group)
+ g_object_unref (method->size_group);
+}
+
+static gboolean
+validate (EAPMethod *parent)
+{
+ GtkWidget *widget;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ EAPMethod *eap = NULL;
+ const char *file;
+ gboolean provisioning;
+ gboolean valid = FALSE;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_provision_checkbutton"));
+ g_assert (widget);
+ provisioning = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_file_button"));
+ g_assert (widget);
+ file = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+ if (!provisioning && !file)
+ return FALSE;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_inner_auth_combo"));
+ g_assert (widget);
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+ gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+ g_assert (eap);
+ valid = eap_method_validate (eap);
+ eap_method_unref (eap);
+ return valid;
+}
+
+static void
+add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
+{
+ EAPMethodFAST *method = (EAPMethodFAST *) parent;
+ GtkWidget *widget;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ EAPMethod *eap;
+
+ if (method->size_group)
+ g_object_unref (method->size_group);
+ method->size_group = g_object_ref (group);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_anon_identity_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_file_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_provision_checkbutton"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_inner_auth_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_inner_auth_combo"));
+ g_assert (widget);
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+ gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+ g_assert (eap);
+ eap_method_add_to_size_group (eap, group);
+ eap_method_unref (eap);
+}
+
+static void
+fill_connection (EAPMethod *parent, NMConnection *connection)
+{
+ NMSetting8021x *s_8021x;
+ GtkWidget *widget;
+ const char *text;
+ char *filename;
+ EAPMethod *eap = NULL;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gboolean enabled;
+ int pac_provisioning = 0;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ g_assert (s_8021x);
+
+ nm_setting_802_1x_add_eap_method (s_8021x, "fast");
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_anon_identity_entry"));
+ g_assert (widget);
+ text = gtk_entry_get_text (GTK_ENTRY (widget));
+ if (text && strlen (text))
+ g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, text, NULL);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_file_button"));
+ g_assert (widget);
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+ g_object_set (s_8021x, NM_SETTING_802_1X_PAC_FILE, filename, NULL);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_provision_checkbutton"));
+ enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+
+ if (!enabled)
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "0", NULL);
+ else {
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_provision_combo"));
+ pac_provisioning = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
+
+ switch (pac_provisioning) {
+ case 0: /* Anonymous */
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "1", NULL);
+ break;
+ case 1: /* Authenticated */
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "2", NULL);
+ break;
+ case 2: /* Both - anonymous and authenticated */
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "3", NULL);
+ break;
+ default: /* Should not happen */
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "1", NULL);
+ break;
+ }
+ }
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_inner_auth_combo"));
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+ gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+ g_assert (eap);
+
+ eap_method_fill_connection (eap, connection);
+ eap_method_unref (eap);
+}
+
+static void
+inner_auth_combo_changed_cb (GtkWidget *combo, gpointer user_data)
+{
+ EAPMethod *parent = (EAPMethod *) user_data;
+ EAPMethodFAST *method = (EAPMethodFAST *) parent;
+ GtkWidget *vbox;
+ EAPMethod *eap = NULL;
+ GList *elt, *children;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkWidget *eap_widget;
+
+ vbox = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_inner_auth_vbox"));
+ g_assert (vbox);
+
+ /* Remove any previous wireless security widgets */
+ children = gtk_container_get_children (GTK_CONTAINER (vbox));
+ for (elt = children; elt; elt = g_list_next (elt))
+ gtk_container_remove (GTK_CONTAINER (vbox), GTK_WIDGET (elt->data));
+ g_list_free (children);
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter);
+ gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+ g_assert (eap);
+
+ eap_widget = eap_method_get_widget (eap);
+ g_assert (eap_widget);
+ gtk_widget_unparent (eap_widget);
+
+ if (method->size_group)
+ eap_method_add_to_size_group (eap, method->size_group);
+ gtk_container_add (GTK_CONTAINER (vbox), eap_widget);
+
+ eap_method_unref (eap);
+
+ wireless_security_changed_cb (combo, method->sec_parent);
+}
+
+static GtkWidget *
+inner_auth_combo_init (EAPMethodFAST *method,
+ NMConnection *connection,
+ NMSetting8021x *s_8021x,
+ gboolean secrets_only)
+{
+ EAPMethod *parent = (EAPMethod *) method;
+ GtkWidget *combo;
+ GtkListStore *auth_model;
+ GtkTreeIter iter;
+ EAPMethodSimple *em_gtc;
+ EAPMethodSimple *em_mschap_v2;
+ guint32 active = 0;
+ const char *phase2_auth = NULL;
+
+ auth_model = gtk_list_store_new (2, G_TYPE_STRING, eap_method_get_g_type ());
+
+ if (s_8021x) {
+ if (nm_setting_802_1x_get_phase2_auth (s_8021x))
+ phase2_auth = nm_setting_802_1x_get_phase2_auth (s_8021x);
+ else if (nm_setting_802_1x_get_phase2_autheap (s_8021x))
+ phase2_auth = nm_setting_802_1x_get_phase2_autheap (s_8021x);
+ }
+
+ em_gtc = eap_method_simple_new (method->sec_parent,
+ connection,
+ EAP_METHOD_SIMPLE_TYPE_GTC,
+ TRUE,
+ method->is_editor,
+ secrets_only);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ I_NAME_COLUMN, _("GTC"),
+ I_METHOD_COLUMN, em_gtc,
+ -1);
+ eap_method_unref (EAP_METHOD (em_gtc));
+
+ /* Check for defaulting to GTC */
+ if (phase2_auth && !strcasecmp (phase2_auth, "gtc"))
+ active = 0;
+
+ em_mschap_v2 = eap_method_simple_new (method->sec_parent,
+ connection,
+ EAP_METHOD_SIMPLE_TYPE_MSCHAP_V2,
+ TRUE,
+ method->is_editor, secrets_only);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ I_NAME_COLUMN, _("MSCHAPv2"),
+ I_METHOD_COLUMN, em_mschap_v2,
+ -1);
+ eap_method_unref (EAP_METHOD (em_mschap_v2));
+
+ /* Check for defaulting to MSCHAPv2 */
+ if (phase2_auth && !strcasecmp (phase2_auth, "mschapv2"))
+ active = 1;
+
+ combo = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_inner_auth_combo"));
+ g_assert (combo);
+
+ gtk_combo_box_set_model (GTK_COMBO_BOX (combo), GTK_TREE_MODEL (auth_model));
+ g_object_unref (G_OBJECT (auth_model));
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combo), active);
+
+ g_signal_connect (G_OBJECT (combo), "changed",
+ (GCallback) inner_auth_combo_changed_cb,
+ method);
+ return combo;
+}
+
+static void
+update_secrets (EAPMethod *parent, NMConnection *connection)
+{
+ eap_method_phase2_update_secrets_helper (parent,
+ connection,
+ "eap_fast_inner_auth_combo",
+ I_METHOD_COLUMN);
+}
+
+static void
+pac_toggled_cb (GtkWidget *widget, gpointer user_data)
+{
+ EAPMethod *parent = (EAPMethod *) user_data;
+ EAPMethodFAST *method = (EAPMethodFAST *) parent;
+ gboolean enabled = FALSE;
+ GtkWidget *provision_combo;
+
+ provision_combo = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_provision_combo"));
+ g_return_if_fail (provision_combo);
+
+ enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+
+ gtk_widget_set_sensitive (provision_combo, enabled);
+
+ wireless_security_changed_cb (widget, method->sec_parent);
+}
+
+EAPMethodFAST *
+eap_method_fast_new (WirelessSecurity *ws_parent,
+ NMConnection *connection,
+ gboolean is_editor,
+ gboolean secrets_only)
+{
+ EAPMethod *parent;
+ EAPMethodFAST *method;
+ GtkWidget *widget;
+ GtkFileFilter *filter;
+ NMSetting8021x *s_8021x = NULL;
+ const char *filename;
+ gboolean provisioning_enabled = TRUE;
+
+ parent = eap_method_init (sizeof (EAPMethodFAST),
+ validate,
+ add_to_size_group,
+ fill_connection,
+ update_secrets,
+ destroy,
+ "/org/gnome/control-center/network/eap-method-fast.ui",
+ "eap_fast_notebook",
+ "eap_fast_anon_identity_entry",
+ FALSE);
+ if (!parent)
+ return NULL;
+
+ method = (EAPMethodFAST *) parent;
+ method->sec_parent = ws_parent;
+ method->is_editor = is_editor;
+
+ if (connection)
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_provision_combo"));
+ g_assert (widget);
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
+ if (s_8021x) {
+ const char *fast_prov;
+
+ fast_prov = nm_setting_802_1x_get_phase1_fast_provisioning (s_8021x);
+ if (fast_prov) {
+ if (!strcmp (fast_prov, "0"))
+ provisioning_enabled = FALSE;
+ else if (!strcmp (fast_prov, "1"))
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
+ else if (!strcmp (fast_prov, "2"))
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 1);
+ else if (!strcmp (fast_prov, "3"))
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 2);
+ }
+ }
+ gtk_widget_set_sensitive (widget, provisioning_enabled);
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) wireless_security_changed_cb,
+ ws_parent);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_provision_checkbutton"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), provisioning_enabled);
+ g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (pac_toggled_cb), parent);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_anon_identity_entry"));
+ if (s_8021x && nm_setting_802_1x_get_anonymous_identity (s_8021x))
+ gtk_entry_set_text (GTK_ENTRY (widget), nm_setting_802_1x_get_anonymous_identity (s_8021x));
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) wireless_security_changed_cb,
+ ws_parent);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_file_button"));
+ g_assert (widget);
+ gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (widget), TRUE);
+ gtk_file_chooser_button_set_title (GTK_FILE_CHOOSER_BUTTON (widget),
+ _("Choose a PAC file..."));
+ g_signal_connect (G_OBJECT (widget), "selection-changed",
+ (GCallback) wireless_security_changed_cb,
+ ws_parent);
+
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_add_pattern (filter, "*.pac");
+ gtk_file_filter_set_name (filter, _("PAC files (*.pac)"));
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (widget), filter);
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_add_pattern (filter, "*");
+ gtk_file_filter_set_name (filter, _("All files"));
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (widget), filter);
+
+ if (connection && s_8021x) {
+ filename = nm_setting_802_1x_get_pac_file (s_8021x);
+ if (filename)
+ gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), filename);
+ }
+
+ widget = inner_auth_combo_init (method, connection, s_8021x, secrets_only);
+ inner_auth_combo_changed_cb (widget, (gpointer) method);
+
+ if (secrets_only) {
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_anon_identity_label"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_anon_identity_entry"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_provision_checkbutton"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_provision_combo"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_file_label"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_file_button"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_inner_auth_label"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_inner_auth_combo"));
+ gtk_widget_hide (widget);
+ }
+
+ return method;
+}
+
diff --git a/panels/network/wireless-security/eap-method-fast.h b/panels/network/wireless-security/eap-method-fast.h
new file mode 100644
index 0000000..32b9a4b
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-fast.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* vim: set ft=c ts=4 sts=4 sw=4 noexpandtab smartindent: */
+
+/* EAP-FAST authentication method (RFC4851)
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2012 Red Hat, Inc.
+ */
+
+#ifndef EAP_METHOD_FAST_H
+#define EAP_METHOD_FAST_H
+
+#include "wireless-security.h"
+
+typedef struct _EAPMethodFAST EAPMethodFAST;
+
+EAPMethodFAST *eap_method_fast_new (WirelessSecurity *ws_parent,
+ NMConnection *connection,
+ gboolean is_editor,
+ gboolean secrets_only);
+
+#endif /* EAP_METHOD_FAST_H */
+
diff --git a/panels/network/wireless-security/eap-method-fast.ui b/panels/network/wireless-security/eap-method-fast.ui
new file mode 100644
index 0000000..fdfc7f8
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-fast.ui
@@ -0,0 +1,203 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkNotebook" id="eap_fast_notebook">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="show_tabs">False</property>
+ <property name="show_border">False</property>
+ <child>
+ <object class="GtkTable" id="table13">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="n_rows">5</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="eap_fast_anon_identity_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Anony_mous identity</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_fast_anon_identity_entry</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="eap_fast_anon_identity_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eap_fast_pac_file_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">PAC _file</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_fast_pac_file_button</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFileChooserButton" id="eap_fast_pac_file_button">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="eap_fast_inner_auth_vbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="right_attach">2</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eap_fast_inner_auth_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Inner authentication</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_fast_inner_auth_combo</property>
+ </object>
+ <packing>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="eap_fast_inner_auth_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">model8</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer8"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="eap_fast_pac_provision_checkbutton">
+ <property name="label" translatable="yes">PAC pro_visioning</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0.5</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="eap_fast_pac_provision_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">model9</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer9"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label61">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+ <object class="GtkListStore" id="model8">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes"> </col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="model9">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">Anonymous</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Authenticated</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Both</col>
+ </row>
+ </data>
+ </object>
+</interface>
diff --git a/panels/network/wireless-security/eap-method-leap.c b/panels/network/wireless-security/eap-method-leap.c
new file mode 100644
index 0000000..58d8c54
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-leap.c
@@ -0,0 +1,183 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#include <ctype.h>
+#include <string.h>
+#include <nm-setting-8021x.h>
+
+#include "eap-method.h"
+#include "wireless-security.h"
+#include "helpers.h"
+
+struct _EAPMethodLEAP {
+ EAPMethod parent;
+
+ gboolean new_connection;
+};
+
+static void
+show_toggled_cb (GtkCheckButton *button, EAPMethod *method)
+{
+ GtkWidget *widget;
+ gboolean visible;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (method->builder, "eap_leap_password_entry"));
+ g_assert (widget);
+
+ visible = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+ gtk_entry_set_visibility (GTK_ENTRY (widget), visible);
+}
+
+static gboolean
+validate (EAPMethod *parent)
+{
+ GtkWidget *widget;
+ const char *text;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_leap_username_entry"));
+ g_assert (widget);
+ text = gtk_entry_get_text (GTK_ENTRY (widget));
+ if (!text || !strlen (text))
+ return FALSE;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_leap_password_entry"));
+ g_assert (widget);
+ text = gtk_entry_get_text (GTK_ENTRY (widget));
+ if (!text || !strlen (text))
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
+{
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_leap_username_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_leap_password_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+}
+
+static void
+fill_connection (EAPMethod *parent, NMConnection *connection)
+{
+ EAPMethodLEAP *method = (EAPMethodLEAP *) parent;
+ NMSetting8021x *s_8021x;
+ GtkWidget *widget;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ g_assert (s_8021x);
+
+ nm_setting_802_1x_add_eap_method (s_8021x, "leap");
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_leap_username_entry"));
+ g_assert (widget);
+ g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, gtk_entry_get_text (GTK_ENTRY (widget)), NULL);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_leap_password_entry"));
+ g_assert (widget);
+ g_object_set (s_8021x, NM_SETTING_802_1X_PASSWORD, gtk_entry_get_text (GTK_ENTRY (widget)), NULL);
+
+ /* Default to agent-owned secrets for new connections */
+ if (method->new_connection) {
+ g_object_set (s_8021x,
+ NM_SETTING_802_1X_PASSWORD_FLAGS, NM_SETTING_SECRET_FLAG_AGENT_OWNED,
+ NM_SETTING_802_1X_SYSTEM_CA_CERTS, TRUE,
+ NULL);
+ }
+}
+
+static void
+update_secrets (EAPMethod *parent, NMConnection *connection)
+{
+ helper_fill_secret_entry (connection,
+ parent->builder,
+ "eap_leap_password_entry",
+ NM_TYPE_SETTING_802_1X,
+ (HelperSecretFunc) nm_setting_802_1x_get_password);
+}
+
+EAPMethodLEAP *
+eap_method_leap_new (WirelessSecurity *ws_parent,
+ NMConnection *connection,
+ gboolean secrets_only)
+{
+ EAPMethodLEAP *method;
+ EAPMethod *parent;
+ GtkWidget *widget;
+
+ parent = eap_method_init (sizeof (EAPMethodLEAP),
+ validate,
+ add_to_size_group,
+ fill_connection,
+ update_secrets,
+ NULL,
+ "/org/gnome/control-center/network/eap-method-leap.ui",
+ "eap_leap_notebook",
+ "eap_leap_username_entry",
+ FALSE);
+ if (!parent)
+ return NULL;
+
+ method = (EAPMethodLEAP *) parent;
+ method->new_connection = secrets_only ? FALSE : TRUE;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_leap_username_entry"));
+ g_assert (widget);
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) wireless_security_changed_cb,
+ ws_parent);
+ if (connection) {
+ NMSetting8021x *s_8021x;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ if (s_8021x && nm_setting_802_1x_get_identity (s_8021x))
+ gtk_entry_set_text (GTK_ENTRY (widget), nm_setting_802_1x_get_identity (s_8021x));
+ }
+
+ if (secrets_only)
+ gtk_widget_set_sensitive (widget, FALSE);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_leap_password_entry"));
+ g_assert (widget);
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) wireless_security_changed_cb,
+ ws_parent);
+
+ /* Fill secrets, if any */
+ if (connection)
+ update_secrets (parent, connection);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "show_checkbutton_eapleap"));
+ g_assert (widget);
+ g_signal_connect (G_OBJECT (widget), "toggled",
+ (GCallback) show_toggled_cb,
+ parent);
+
+ return method;
+}
+
diff --git a/panels/network/wireless-security/eap-method-leap.h b/panels/network/wireless-security/eap-method-leap.h
new file mode 100644
index 0000000..e3525ba
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-leap.h
@@ -0,0 +1,35 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#ifndef EAP_METHOD_LEAP_H
+#define EAP_METHOD_LEAP_H
+
+#include "wireless-security.h"
+
+typedef struct _EAPMethodLEAP EAPMethodLEAP;
+
+EAPMethodLEAP *eap_method_leap_new (WirelessSecurity *ws_parent,
+ NMConnection *connection,
+ gboolean secrets_only);
+
+#endif /* EAP_METHOD_LEAP_H */
+
diff --git a/panels/network/wireless-security/eap-method-leap.ui b/panels/network/wireless-security/eap-method-leap.ui
new file mode 100644
index 0000000..8b475fb
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-leap.ui
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkNotebook" id="eap_leap_notebook">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="show_tabs">False</property>
+ <property name="show_border">False</property>
+ <child>
+ <object class="GtkTable" id="table9">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="n_rows">3</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eap_leap_username_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Username</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_leap_username_entry</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eap_leap_password_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_leap_password_entry</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="eap_leap_password_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="visibility">False</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="show_checkbutton_eapleap">
+ <property name="label" translatable="yes">Sho_w password</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="eap_leap_username_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label43">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/panels/network/wireless-security/eap-method-peap.c b/panels/network/wireless-security/eap-method-peap.c
new file mode 100644
index 0000000..2c1387a
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-peap.c
@@ -0,0 +1,414 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <ctype.h>
+#include <string.h>
+
+#include <nm-setting-connection.h>
+#include <nm-setting-8021x.h>
+
+#include "eap-method.h"
+#include "wireless-security.h"
+
+#define I_NAME_COLUMN 0
+#define I_METHOD_COLUMN 1
+
+struct _EAPMethodPEAP {
+ EAPMethod parent;
+
+ GtkSizeGroup *size_group;
+ WirelessSecurity *sec_parent;
+ gboolean is_editor;
+};
+
+static void
+destroy (EAPMethod *parent)
+{
+ EAPMethodPEAP *method = (EAPMethodPEAP *) parent;
+
+ if (method->size_group)
+ g_object_unref (method->size_group);
+}
+
+static gboolean
+validate (EAPMethod *parent)
+{
+ GtkWidget *widget;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ EAPMethod *eap = NULL;
+ gboolean valid = FALSE;
+
+ if (!eap_method_validate_filepicker (parent->builder, "eap_peap_ca_cert_button", TYPE_CA_CERT, NULL, NULL))
+ return FALSE;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_inner_auth_combo"));
+ g_assert (widget);
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+ gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+ g_assert (eap);
+ valid = eap_method_validate (eap);
+ eap_method_unref (eap);
+ return valid;
+}
+
+static void
+add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
+{
+ EAPMethodPEAP *method = (EAPMethodPEAP *) parent;
+ GtkWidget *widget;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ EAPMethod *eap;
+
+ if (method->size_group)
+ g_object_unref (method->size_group);
+ method->size_group = g_object_ref (group);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_anon_identity_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_ca_cert_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_version_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_inner_auth_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_inner_auth_combo"));
+ g_assert (widget);
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+ gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+ g_assert (eap);
+ eap_method_add_to_size_group (eap, group);
+ eap_method_unref (eap);
+}
+
+static void
+fill_connection (EAPMethod *parent, NMConnection *connection)
+{
+ NMSetting8021x *s_8021x;
+ NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ GtkWidget *widget;
+ const char *text;
+ char *filename;
+ EAPMethod *eap = NULL;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ int peapver_active = 0;
+ GError *error = NULL;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ g_assert (s_8021x);
+
+ nm_setting_802_1x_add_eap_method (s_8021x, "peap");
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_anon_identity_entry"));
+ g_assert (widget);
+ text = gtk_entry_get_text (GTK_ENTRY (widget));
+ if (text && strlen (text))
+ g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, text, NULL);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_ca_cert_button"));
+ g_assert (widget);
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+ if (!nm_setting_802_1x_set_ca_cert (s_8021x, filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+ g_warning ("Couldn't read CA certificate '%s': %s", filename, error ? error->message : "(unknown)");
+ g_clear_error (&error);
+ }
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_version_combo"));
+ peapver_active = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
+ switch (peapver_active) {
+ case 1: /* PEAP v0 */
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_PEAPVER, "0", NULL);
+ break;
+ case 2: /* PEAP v1 */
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_PEAPVER, "1", NULL);
+ break;
+ default: /* Automatic */
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_PEAPVER, NULL, NULL);
+ break;
+ }
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_inner_auth_combo"));
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+ gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+ g_assert (eap);
+
+ eap_method_fill_connection (eap, connection);
+ eap_method_unref (eap);
+}
+static void
+inner_auth_combo_changed_cb (GtkWidget *combo, gpointer user_data)
+{
+ EAPMethod *parent = (EAPMethod *) user_data;
+ EAPMethodPEAP *method = (EAPMethodPEAP *) parent;
+ GtkWidget *vbox;
+ EAPMethod *eap = NULL;
+ GList *elt, *children;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkWidget *eap_widget;
+
+ vbox = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_inner_auth_vbox"));
+ g_assert (vbox);
+
+ /* Remove any previous wireless security widgets */
+ children = gtk_container_get_children (GTK_CONTAINER (vbox));
+ for (elt = children; elt; elt = g_list_next (elt))
+ gtk_container_remove (GTK_CONTAINER (vbox), GTK_WIDGET (elt->data));
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter);
+ gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+ g_assert (eap);
+
+ eap_widget = eap_method_get_widget (eap);
+ g_assert (eap_widget);
+ gtk_widget_unparent (eap_widget);
+
+ if (method->size_group)
+ eap_method_add_to_size_group (eap, method->size_group);
+ gtk_container_add (GTK_CONTAINER (vbox), eap_widget);
+
+ eap_method_unref (eap);
+
+ wireless_security_changed_cb (combo, method->sec_parent);
+}
+
+static GtkWidget *
+inner_auth_combo_init (EAPMethodPEAP *method,
+ NMConnection *connection,
+ NMSetting8021x *s_8021x,
+ gboolean secrets_only)
+{
+ EAPMethod *parent = (EAPMethod *) method;
+ GtkWidget *combo;
+ GtkListStore *auth_model;
+ GtkTreeIter iter;
+ EAPMethodSimple *em_mschap_v2;
+ EAPMethodSimple *em_md5;
+ EAPMethodSimple *em_gtc;
+ guint32 active = 0;
+ const char *phase2_auth = NULL;
+
+ auth_model = gtk_list_store_new (2, G_TYPE_STRING, eap_method_get_g_type ());
+
+ if (s_8021x) {
+ if (nm_setting_802_1x_get_phase2_auth (s_8021x))
+ phase2_auth = nm_setting_802_1x_get_phase2_auth (s_8021x);
+ else if (nm_setting_802_1x_get_phase2_autheap (s_8021x))
+ phase2_auth = nm_setting_802_1x_get_phase2_autheap (s_8021x);
+ }
+
+ em_mschap_v2 = eap_method_simple_new (method->sec_parent,
+ connection,
+ EAP_METHOD_SIMPLE_TYPE_MSCHAP_V2,
+ TRUE,
+ method->is_editor,
+ secrets_only);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ I_NAME_COLUMN, _("MSCHAPv2"),
+ I_METHOD_COLUMN, em_mschap_v2,
+ -1);
+ eap_method_unref (EAP_METHOD (em_mschap_v2));
+
+ /* Check for defaulting to MSCHAPv2 */
+ if (phase2_auth && !strcasecmp (phase2_auth, "mschapv2"))
+ active = 0;
+
+ em_md5 = eap_method_simple_new (method->sec_parent,
+ connection,
+ EAP_METHOD_SIMPLE_TYPE_MD5,
+ TRUE,
+ method->is_editor,
+ secrets_only);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ I_NAME_COLUMN, _("MD5"),
+ I_METHOD_COLUMN, em_md5,
+ -1);
+ eap_method_unref (EAP_METHOD (em_md5));
+
+ /* Check for defaulting to MD5 */
+ if (phase2_auth && !strcasecmp (phase2_auth, "md5"))
+ active = 1;
+
+ em_gtc = eap_method_simple_new (method->sec_parent,
+ connection,
+ EAP_METHOD_SIMPLE_TYPE_GTC,
+ TRUE,
+ method->is_editor,
+ secrets_only);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ I_NAME_COLUMN, _("GTC"),
+ I_METHOD_COLUMN, em_gtc,
+ -1);
+ eap_method_unref (EAP_METHOD (em_gtc));
+
+ /* Check for defaulting to GTC */
+ if (phase2_auth && !strcasecmp (phase2_auth, "gtc"))
+ active = 2;
+
+ combo = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_inner_auth_combo"));
+ g_assert (combo);
+
+ gtk_combo_box_set_model (GTK_COMBO_BOX (combo), GTK_TREE_MODEL (auth_model));
+ g_object_unref (G_OBJECT (auth_model));
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combo), active);
+
+ g_signal_connect (G_OBJECT (combo), "changed",
+ (GCallback) inner_auth_combo_changed_cb,
+ method);
+ return combo;
+}
+
+static void
+update_secrets (EAPMethod *parent, NMConnection *connection)
+{
+ eap_method_phase2_update_secrets_helper (parent,
+ connection,
+ "eap_peap_inner_auth_combo",
+ I_METHOD_COLUMN);
+}
+
+EAPMethodPEAP *
+eap_method_peap_new (WirelessSecurity *ws_parent,
+ NMConnection *connection,
+ gboolean is_editor,
+ gboolean secrets_only)
+{
+ EAPMethod *parent;
+ EAPMethodPEAP *method;
+ GtkWidget *widget;
+ GtkFileFilter *filter;
+ NMSetting8021x *s_8021x = NULL;
+ const char *filename;
+
+ parent = eap_method_init (sizeof (EAPMethodPEAP),
+ validate,
+ add_to_size_group,
+ fill_connection,
+ update_secrets,
+ destroy,
+ "/org/gnome/control-center/network/eap-method-peap.ui",
+ "eap_peap_notebook",
+ "eap_peap_anon_identity_entry",
+ FALSE);
+ if (!parent)
+ return NULL;
+
+ eap_method_nag_init (parent, "eap_peap_ca_cert_button", connection);
+
+ method = (EAPMethodPEAP *) parent;
+ method->sec_parent = ws_parent;
+ method->is_editor = is_editor;
+
+ if (connection)
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_ca_cert_button"));
+ g_assert (widget);
+ gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (widget), TRUE);
+ gtk_file_chooser_button_set_title (GTK_FILE_CHOOSER_BUTTON (widget),
+ _("Choose a Certificate Authority certificate..."));
+ g_signal_connect (G_OBJECT (widget), "selection-changed",
+ (GCallback) wireless_security_changed_cb,
+ ws_parent);
+ filter = eap_method_default_file_chooser_filter_new (FALSE);
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (widget), filter);
+ if (connection && s_8021x) {
+ if (nm_setting_802_1x_get_ca_cert_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH) {
+ filename = nm_setting_802_1x_get_ca_cert_path (s_8021x);
+ if (filename)
+ gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), filename);
+ }
+ }
+
+ widget = inner_auth_combo_init (method, connection, s_8021x, secrets_only);
+ inner_auth_combo_changed_cb (widget, (gpointer) method);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_version_combo"));
+ g_assert (widget);
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
+ if (s_8021x) {
+ const char *peapver;
+
+ peapver = nm_setting_802_1x_get_phase1_peapver (s_8021x);
+ if (peapver) {
+ /* Index 0 is "Automatic" */
+ if (!strcmp (peapver, "0"))
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 1);
+ else if (!strcmp (peapver, "1"))
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 2);
+ }
+ }
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) wireless_security_changed_cb,
+ ws_parent);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_anon_identity_entry"));
+ if (s_8021x && nm_setting_802_1x_get_anonymous_identity (s_8021x))
+ gtk_entry_set_text (GTK_ENTRY (widget), nm_setting_802_1x_get_anonymous_identity (s_8021x));
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) wireless_security_changed_cb,
+ ws_parent);
+
+ if (secrets_only) {
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_anon_identity_label"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_anon_identity_entry"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_ca_cert_label"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_ca_cert_button"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_inner_auth_label"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_inner_auth_combo"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_version_label"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_version_combo"));
+ gtk_widget_hide (widget);
+ }
+
+ return method;
+}
+
diff --git a/panels/network/wireless-security/eap-method-peap.h b/panels/network/wireless-security/eap-method-peap.h
new file mode 100644
index 0000000..752306c
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-peap.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#ifndef EAP_METHOD_PEAP_H
+#define EAP_METHOD_PEAP_H
+
+#include "wireless-security.h"
+
+typedef struct _EAPMethodPEAP EAPMethodPEAP;
+
+EAPMethodPEAP *eap_method_peap_new (WirelessSecurity *ws_parent,
+ NMConnection *connection,
+ gboolean is_editor,
+ gboolean secrets_only);
+
+#endif /* EAP_METHOD_PEAP_H */
+
diff --git a/panels/network/wireless-security/eap-method-peap.ui b/panels/network/wireless-security/eap-method-peap.ui
new file mode 100644
index 0000000..4202237
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-peap.ui
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkListStore" id="model8">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes"> </col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="model9">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">Automatic</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Version 0</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Version 1</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkNotebook" id="eap_peap_notebook">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="show_tabs">False</property>
+ <property name="show_border">False</property>
+ <child>
+ <object class="GtkTable" id="table13">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="n_rows">5</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="eap_peap_anon_identity_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Anony_mous identity</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_peap_anon_identity_entry</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="eap_peap_anon_identity_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eap_peap_ca_cert_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">C_A certificate</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_peap_ca_cert_button</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFileChooserButton" id="eap_peap_ca_cert_button">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="eap_peap_inner_auth_vbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="right_attach">2</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eap_peap_inner_auth_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Inner authentication</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_peap_inner_auth_combo</property>
+ </object>
+ <packing>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="eap_peap_inner_auth_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">model8</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer8"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eap_peap_version_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">PEAP _version</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_peap_version_combo</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="eap_peap_version_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">model9</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer9"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label61">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/panels/network/wireless-security/eap-method-simple.c b/panels/network/wireless-security/eap-method-simple.c
new file mode 100644
index 0000000..aa92cde
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-simple.c
@@ -0,0 +1,305 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2011 Red Hat, Inc.
+ */
+
+#include <ctype.h>
+#include <string.h>
+#include <nm-setting-8021x.h>
+#include <nm-setting-connection.h>
+
+#include "eap-method.h"
+#include "wireless-security.h"
+#include "helpers.h"
+
+struct _EAPMethodSimple {
+ EAPMethod parent;
+
+ EAPMethodSimpleType type;
+ gboolean is_editor;
+ gboolean new_connection;
+};
+
+static void
+show_toggled_cb (GtkCheckButton *button, EAPMethod *method)
+{
+ GtkWidget *widget;
+ gboolean visible;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (method->builder, "eap_simple_password_entry"));
+ g_assert (widget);
+
+ visible = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+ gtk_entry_set_visibility (GTK_ENTRY (widget), visible);
+}
+
+static gboolean
+validate (EAPMethod *parent)
+{
+ GtkWidget *widget;
+ const char *text;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_username_entry"));
+ g_assert (widget);
+ text = gtk_entry_get_text (GTK_ENTRY (widget));
+ if (!text || !strlen (text))
+ return FALSE;
+
+ /* Check if the password should always be requested */
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_password_always_ask"));
+ g_assert (widget);
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
+ return TRUE;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_password_entry"));
+ g_assert (widget);
+ text = gtk_entry_get_text (GTK_ENTRY (widget));
+ if (!text || !strlen (text))
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
+{
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_username_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_password_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+}
+
+static void
+fill_connection (EAPMethod *parent, NMConnection *connection)
+{
+ EAPMethodSimple *method = (EAPMethodSimple *) parent;
+ NMSetting8021x *s_8021x;
+ GtkWidget *widget;
+ gboolean not_saved = FALSE;
+ const char *eap = NULL;
+ NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ g_assert (s_8021x);
+
+ /* If this is the main EAP method, clear any existing methods because the
+ * user-selected on will replace it.
+ */
+ if (parent->phase2 == FALSE)
+ nm_setting_802_1x_clear_eap_methods (s_8021x);
+
+ switch (method->type) {
+ case EAP_METHOD_SIMPLE_TYPE_PAP:
+ eap = "pap";
+ break;
+ case EAP_METHOD_SIMPLE_TYPE_MSCHAP:
+ eap = "mschap";
+ break;
+ case EAP_METHOD_SIMPLE_TYPE_MSCHAP_V2:
+ eap = "mschapv2";
+ break;
+ case EAP_METHOD_SIMPLE_TYPE_MD5:
+ eap = "md5";
+ break;
+ case EAP_METHOD_SIMPLE_TYPE_CHAP:
+ eap = "chap";
+ break;
+ case EAP_METHOD_SIMPLE_TYPE_GTC:
+ eap = "gtc";
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ if (parent->phase2)
+ g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, eap, NULL);
+ else
+ nm_setting_802_1x_add_eap_method (s_8021x, eap);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_username_entry"));
+ g_assert (widget);
+ g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, gtk_entry_get_text (GTK_ENTRY (widget)), NULL);
+
+ /* Save the password always ask setting */
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_password_always_ask"));
+ g_assert (widget);
+ not_saved = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+
+ nm_setting_get_secret_flags (NM_SETTING (s_8021x), NM_SETTING_802_1X_PASSWORD, &flags, NULL);
+ flags &= ~(NM_SETTING_SECRET_FLAG_NOT_SAVED);
+ if (not_saved)
+ flags |= NM_SETTING_SECRET_FLAG_NOT_SAVED;
+ nm_setting_set_secret_flags (NM_SETTING (s_8021x), NM_SETTING_802_1X_PASSWORD, flags, NULL);
+
+ /* Fill the connection's password if we're in the applet so that it'll get
+ * back to NM. From the editor though, since the connection isn't going
+ * back to NM in response to a GetSecrets() call, we don't save it if the
+ * user checked "Always Ask".
+ */
+ if (method->is_editor == FALSE || not_saved == FALSE) {
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_password_entry"));
+ g_assert (widget);
+ g_object_set (s_8021x, NM_SETTING_802_1X_PASSWORD, gtk_entry_get_text (GTK_ENTRY (widget)), NULL);
+ }
+
+ /* Default to agent-owned secrets for new connections */
+ if (method->new_connection && (not_saved == FALSE)) {
+ g_object_set (s_8021x,
+ NM_SETTING_802_1X_PASSWORD_FLAGS, NM_SETTING_SECRET_FLAG_AGENT_OWNED,
+ NM_SETTING_802_1X_SYSTEM_CA_CERTS, TRUE,
+ NULL);
+ }
+}
+
+static void
+update_secrets (EAPMethod *parent, NMConnection *connection)
+{
+ helper_fill_secret_entry (connection,
+ parent->builder,
+ "eap_simple_password_entry",
+ NM_TYPE_SETTING_802_1X,
+ (HelperSecretFunc) nm_setting_802_1x_get_password);
+}
+
+static void
+password_always_ask_changed (GtkButton *button, EAPMethodSimple *method)
+{
+ EAPMethod *parent = (EAPMethod *) method;
+ GtkWidget *password_entry;
+ GtkWidget *show_checkbox;
+ gboolean always_ask;
+
+ always_ask = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+
+ password_entry = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_password_entry"));
+ g_assert (password_entry);
+
+ show_checkbox = GTK_WIDGET (gtk_builder_get_object (parent->builder, "show_checkbutton_eapsimple"));
+ g_assert (show_checkbox);
+
+ if (always_ask) {
+ gtk_entry_set_text (GTK_ENTRY (password_entry), "");
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (show_checkbox), FALSE);
+ }
+
+ gtk_widget_set_sensitive (password_entry, !always_ask);
+ gtk_widget_set_sensitive (show_checkbox, !always_ask);
+}
+
+EAPMethodSimple *
+eap_method_simple_new (WirelessSecurity *ws_parent,
+ NMConnection *connection,
+ EAPMethodSimpleType type,
+ gboolean phase2,
+ gboolean is_editor,
+ gboolean secrets_only)
+{
+ EAPMethod *parent;
+ EAPMethodSimple *method;
+ GtkWidget *widget;
+ gboolean not_saved = FALSE;
+ NMSetting8021x *s_8021x = NULL;
+
+ parent = eap_method_init (sizeof (EAPMethodSimple),
+ validate,
+ add_to_size_group,
+ fill_connection,
+ update_secrets,
+ NULL,
+ "/org/gnome/control-center/network/eap-method-simple.ui",
+ "eap_simple_notebook",
+ "eap_simple_username_entry",
+ phase2);
+ if (!parent)
+ return NULL;
+
+ method = (EAPMethodSimple *) parent;
+ method->type = type;
+ method->is_editor = is_editor;
+ method->new_connection = secrets_only ? FALSE : TRUE;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_username_entry"));
+ g_assert (widget);
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) wireless_security_changed_cb,
+ ws_parent);
+ if (connection) {
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ if (s_8021x && nm_setting_802_1x_get_identity (s_8021x))
+ gtk_entry_set_text (GTK_ENTRY (widget), nm_setting_802_1x_get_identity (s_8021x));
+ }
+
+ if (secrets_only)
+ gtk_widget_set_sensitive (widget, FALSE);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_password_entry"));
+ g_assert (widget);
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) wireless_security_changed_cb,
+ ws_parent);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_password_always_ask"));
+ g_assert (widget);
+ g_signal_connect (G_OBJECT (widget), "toggled",
+ (GCallback) wireless_security_changed_cb,
+ ws_parent);
+ if (is_editor) {
+ /* We only desensitize the password entry from the editor, because
+ * from nm-applet if the entry was desensitized, there'd be no way to
+ * get the password back to NetworkManager when NM asked for it. Since
+ * the editor only sets up the initial connection though, it's safe to
+ * do there.
+ */
+ g_signal_connect (G_OBJECT (widget), "toggled",
+ G_CALLBACK (password_always_ask_changed),
+ method);
+ }
+
+ if (secrets_only)
+ gtk_widget_hide (widget);
+
+ if (s_8021x) {
+ NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
+
+ nm_setting_get_secret_flags (NM_SETTING (s_8021x), NM_SETTING_802_1X_PASSWORD, &flags, NULL);
+ not_saved = (flags & NM_SETTING_SECRET_FLAG_NOT_SAVED);
+ }
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), not_saved);
+
+ /* Fill secrets if there's a static (ie, not OTP) password */
+ if (connection && (not_saved == FALSE))
+ update_secrets (EAP_METHOD (method), connection);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "show_checkbutton_eapsimple"));
+ g_assert (widget);
+ g_signal_connect (G_OBJECT (widget), "toggled",
+ (GCallback) show_toggled_cb,
+ method);
+
+ return method;
+}
+
diff --git a/panels/network/wireless-security/eap-method-simple.h b/panels/network/wireless-security/eap-method-simple.h
new file mode 100644
index 0000000..8a955dc
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-simple.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#ifndef EAP_METHOD_SIMPLE_H
+#define EAP_METHOD_SIMPLE_H
+
+#include "wireless-security.h"
+
+typedef enum {
+ EAP_METHOD_SIMPLE_TYPE_PAP = 0,
+ EAP_METHOD_SIMPLE_TYPE_MSCHAP,
+ EAP_METHOD_SIMPLE_TYPE_MSCHAP_V2,
+ EAP_METHOD_SIMPLE_TYPE_MD5,
+ EAP_METHOD_SIMPLE_TYPE_CHAP,
+ EAP_METHOD_SIMPLE_TYPE_GTC
+} EAPMethodSimpleType;
+
+typedef struct _EAPMethodSimple EAPMethodSimple;
+
+EAPMethodSimple *eap_method_simple_new (WirelessSecurity *ws_parent,
+ NMConnection *connection,
+ EAPMethodSimpleType type,
+ gboolean phase2,
+ gboolean is_editor,
+ gboolean secrets_only);
+
+#endif /* EAP_METHOD_SIMPLE_H */
+
diff --git a/panels/network/wireless-security/eap-method-simple.ui b/panels/network/wireless-security/eap-method-simple.ui
new file mode 100644
index 0000000..854c86f
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-simple.ui
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkNotebook" id="eap_simple_notebook">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="show_tabs">False</property>
+ <property name="show_border">False</property>
+ <child>
+ <object class="GtkTable" id="table11">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="n_rows">3</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eap_simple_username_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Username</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_simple_username_entry</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eap_simple_password_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_simple_password_entry</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="eap_simple_password_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="visibility">False</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="eap_simple_username_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkVBox" id="vbox5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkCheckButton" id="eap_password_always_ask">
+ <property name="label" translatable="yes">As_k for this password every time</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0.5</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="show_checkbutton_eapsimple">
+ <property name="label" translatable="yes">Sho_w password</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label53">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/panels/network/wireless-security/eap-method-tls.c b/panels/network/wireless-security/eap-method-tls.c
new file mode 100644
index 0000000..d3ea1d3
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-tls.c
@@ -0,0 +1,481 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <ctype.h>
+#include <string.h>
+
+#include <nm-setting-connection.h>
+#include <nm-setting-8021x.h>
+
+#include "eap-method.h"
+#include "wireless-security.h"
+#include "helpers.h"
+
+struct _EAPMethodTLS {
+ EAPMethod parent;
+
+ gboolean new_connection;
+};
+
+
+static void
+show_toggled_cb (GtkCheckButton *button, EAPMethod *method)
+{
+ GtkWidget *widget;
+ gboolean visible;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (method->builder, "eap_tls_private_key_password_entry"));
+ g_assert (widget);
+
+ visible = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+ gtk_entry_set_visibility (GTK_ENTRY (widget), visible);
+}
+
+static gboolean
+validate (EAPMethod *parent)
+{
+ NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ GtkWidget *widget;
+ const char *password, *identity;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_identity_entry"));
+ g_assert (widget);
+ identity = gtk_entry_get_text (GTK_ENTRY (widget));
+ if (!identity || !strlen (identity))
+ return FALSE;
+
+ if (!eap_method_validate_filepicker (parent->builder, "eap_tls_ca_cert_button", TYPE_CA_CERT, NULL, NULL))
+ return FALSE;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_private_key_password_entry"));
+ g_assert (widget);
+ password = gtk_entry_get_text (GTK_ENTRY (widget));
+ if (!password || !strlen (password))
+ return FALSE;
+
+ if (!eap_method_validate_filepicker (parent->builder,
+ "eap_tls_private_key_button",
+ TYPE_PRIVATE_KEY,
+ password,
+ &format))
+ return FALSE;
+
+ if (format != NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
+ if (!eap_method_validate_filepicker (parent->builder, "eap_tls_user_cert_button", TYPE_CLIENT_CERT, NULL, NULL))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
+{
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_identity_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_user_cert_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_ca_cert_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_private_key_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_private_key_password_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+}
+
+static void
+fill_connection (EAPMethod *parent, NMConnection *connection)
+{
+ EAPMethodTLS *method = (EAPMethodTLS *) parent;
+ NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ NMSetting8021x *s_8021x;
+ GtkWidget *widget;
+ char *ca_filename, *pk_filename, *cc_filename;
+ const char *password = NULL;
+ GError *error = NULL;
+ const char *secret_flag_prop = NULL;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ g_assert (s_8021x);
+
+ if (parent->phase2)
+ g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, "tls", NULL);
+ else
+ nm_setting_802_1x_add_eap_method (s_8021x, "tls");
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_identity_entry"));
+ g_assert (widget);
+ g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, gtk_entry_get_text (GTK_ENTRY (widget)), NULL);
+
+ /* TLS private key */
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_private_key_password_entry"));
+ g_assert (widget);
+ password = gtk_entry_get_text (GTK_ENTRY (widget));
+ g_assert (password);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_private_key_button"));
+ g_assert (widget);
+ pk_filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+ g_assert (pk_filename);
+
+ if (parent->phase2) {
+ if (!nm_setting_802_1x_set_phase2_private_key (s_8021x, pk_filename, password, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+ g_warning ("Couldn't read phase2 private key '%s': %s", pk_filename, error ? error->message : "(unknown)");
+ g_clear_error (&error);
+ }
+ secret_flag_prop = NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS;
+ } else {
+ if (!nm_setting_802_1x_set_private_key (s_8021x, pk_filename, password, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+ g_warning ("Couldn't read private key '%s': %s", pk_filename, error ? error->message : "(unknown)");
+ g_clear_error (&error);
+ }
+ secret_flag_prop = NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD_FLAGS;
+ }
+ g_free (pk_filename);
+
+ /* Default to agent-owned secrets for new connections */
+ if (method->new_connection) {
+ g_object_set (s_8021x,
+ secret_flag_prop, NM_SETTING_SECRET_FLAG_AGENT_OWNED,
+ NM_SETTING_802_1X_SYSTEM_CA_CERTS, TRUE,
+ NULL);
+ }
+
+ /* TLS client certificate */
+ if (format != NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
+ /* If the key is pkcs#12 nm_setting_802_1x_set_private_key() already
+ * set the client certificate for us.
+ */
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_user_cert_button"));
+ g_assert (widget);
+ cc_filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+ g_assert (cc_filename);
+
+ format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ if (parent->phase2) {
+ if (!nm_setting_802_1x_set_phase2_client_cert (s_8021x, cc_filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+ g_warning ("Couldn't read phase2 client certificate '%s': %s", cc_filename, error ? error->message : "(unknown)");
+ g_clear_error (&error);
+ }
+ } else {
+ if (!nm_setting_802_1x_set_client_cert (s_8021x, cc_filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+ g_warning ("Couldn't read client certificate '%s': %s", cc_filename, error ? error->message : "(unknown)");
+ g_clear_error (&error);
+ }
+ }
+ g_free (cc_filename);
+ }
+
+ /* TLS CA certificate */
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_ca_cert_button"));
+ g_assert (widget);
+ ca_filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+
+ format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ if (parent->phase2) {
+ if (!nm_setting_802_1x_set_phase2_ca_cert (s_8021x, ca_filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+ g_warning ("Couldn't read phase2 CA certificate '%s': %s", ca_filename, error ? error->message : "(unknown)");
+ g_clear_error (&error);
+ }
+ } else {
+ if (!nm_setting_802_1x_set_ca_cert (s_8021x, ca_filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+ g_warning ("Couldn't read CA certificate '%s': %s", ca_filename, error ? error->message : "(unknown)");
+ g_clear_error (&error);
+ }
+ }
+}
+
+static void
+private_key_picker_helper (EAPMethod *parent, const char *filename, gboolean changed)
+{
+ NMSetting8021x *setting;
+ NMSetting8021xCKFormat cert_format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ const char *password;
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_private_key_password_entry"));
+ g_assert (widget);
+ password = gtk_entry_get_text (GTK_ENTRY (widget));
+
+ setting = (NMSetting8021x *) nm_setting_802_1x_new ();
+ nm_setting_802_1x_set_private_key (setting, filename, password, NM_SETTING_802_1X_CK_SCHEME_PATH, &cert_format, NULL);
+ g_object_unref (setting);
+
+ /* With PKCS#12, the client cert must be the same as the private key */
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_user_cert_button"));
+ if (cert_format == NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
+ gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (widget));
+ gtk_widget_set_sensitive (widget, FALSE);
+ } else if (changed)
+ gtk_widget_set_sensitive (widget, TRUE);
+
+ /* Warn the user if the private key is unencrypted */
+ if (!eap_method_is_encrypted_private_key (filename)) {
+ GtkWidget *dialog;
+ GtkWidget *toplevel;
+ GtkWindow *parent_window = NULL;
+
+ toplevel = gtk_widget_get_toplevel (parent->ui_widget);
+ if (gtk_widget_is_toplevel (toplevel))
+ parent_window = GTK_WINDOW (toplevel);
+
+ dialog = gtk_message_dialog_new (parent_window,
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_OK,
+ "%s",
+ _("Unencrypted private keys are insecure"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ "%s",
+ _("The selected private key does not appear to be protected by a password. This could allow your security credentials to be compromised. Please select a password-protected private key.\n\n(You can password-protect your private key with openssl)"));
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ }
+}
+
+static void
+private_key_picker_file_set_cb (GtkWidget *chooser, gpointer user_data)
+{
+ EAPMethod *parent = (EAPMethod *) user_data;
+ char *filename;
+
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser));
+ if (filename)
+ private_key_picker_helper (parent, filename, TRUE);
+ g_free (filename);
+}
+
+static void reset_filter (GtkWidget *widget, GParamSpec *spec, gpointer user_data)
+{
+ if (!gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (widget))) {
+ g_signal_handlers_block_by_func (widget, reset_filter, user_data);
+ gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (widget), GTK_FILE_FILTER (user_data));
+ g_signal_handlers_unblock_by_func (widget, reset_filter, user_data);
+ }
+}
+
+typedef const char * (*PathFunc) (NMSetting8021x *setting);
+typedef NMSetting8021xCKScheme (*SchemeFunc) (NMSetting8021x *setting);
+
+static void
+setup_filepicker (GtkBuilder *builder,
+ const char *name,
+ const char *title,
+ WirelessSecurity *ws_parent,
+ EAPMethod *parent,
+ NMSetting8021x *s_8021x,
+ SchemeFunc scheme_func,
+ PathFunc path_func,
+ gboolean privkey,
+ gboolean client_cert)
+{
+ GtkWidget *widget;
+ GtkFileFilter *filter;
+ const char *filename = NULL;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (builder, name));
+ g_assert (widget);
+ gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (widget), TRUE);
+ gtk_file_chooser_button_set_title (GTK_FILE_CHOOSER_BUTTON (widget), title);
+
+ if (s_8021x && path_func && scheme_func) {
+ if (scheme_func (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH) {
+ filename = path_func (s_8021x);
+ if (filename)
+ gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), filename);
+ }
+ }
+
+ /* Connect a special handler for private keys to intercept PKCS#12 key types
+ * and desensitize the user cert button.
+ */
+ if (privkey) {
+ g_signal_connect (G_OBJECT (widget), "selection-changed",
+ (GCallback) private_key_picker_file_set_cb,
+ parent);
+ if (filename)
+ private_key_picker_helper (parent, filename, FALSE);
+ }
+
+ g_signal_connect (G_OBJECT (widget), "selection-changed",
+ (GCallback) wireless_security_changed_cb,
+ ws_parent);
+
+ filter = eap_method_default_file_chooser_filter_new (privkey);
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (widget), filter);
+
+ /* For some reason, GTK+ calls set_current_filter (..., NULL) from
+ * gtkfilechooserdefault.c::show_and_select_files_finished_loading() on our
+ * dialog; so force-reset the filter to what we want it to be whenever
+ * it gets cleared.
+ */
+ if (client_cert)
+ g_signal_connect (G_OBJECT (widget), "notify::filter", (GCallback) reset_filter, filter);
+}
+
+static void
+update_secrets (EAPMethod *parent, NMConnection *connection)
+{
+ NMSetting8021x *s_8021x;
+ HelperSecretFunc password_func;
+ SchemeFunc scheme_func;
+ PathFunc path_func;
+ const char *filename;
+ GtkWidget *widget;
+
+ if (parent->phase2) {
+ password_func = (HelperSecretFunc) nm_setting_802_1x_get_phase2_private_key_password;
+ scheme_func = nm_setting_802_1x_get_phase2_private_key_scheme;
+ path_func = nm_setting_802_1x_get_phase2_private_key_path;
+ } else {
+ password_func = (HelperSecretFunc) nm_setting_802_1x_get_private_key_password;
+ scheme_func = nm_setting_802_1x_get_private_key_scheme;
+ path_func = nm_setting_802_1x_get_private_key_path;
+ }
+
+ helper_fill_secret_entry (connection,
+ parent->builder,
+ "eap_tls_private_key_password_entry",
+ NM_TYPE_SETTING_802_1X,
+ password_func);
+
+ /* Set the private key filepicker button path if we have a private key */
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ if (s_8021x && (scheme_func (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH)) {
+ filename = path_func (s_8021x);
+ if (filename) {
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_private_key_button"));
+ g_assert (widget);
+ gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), filename);
+ }
+ }
+}
+
+EAPMethodTLS *
+eap_method_tls_new (WirelessSecurity *ws_parent,
+ NMConnection *connection,
+ gboolean phase2,
+ gboolean secrets_only)
+{
+ EAPMethodTLS *method;
+ EAPMethod *parent;
+ GtkWidget *widget;
+ NMSetting8021x *s_8021x = NULL;
+
+ parent = eap_method_init (sizeof (EAPMethodTLS),
+ validate,
+ add_to_size_group,
+ fill_connection,
+ update_secrets,
+ NULL,
+ "/org/gnome/control-center/network/eap-method-tls.ui",
+ "eap_tls_notebook",
+ "eap_tls_identity_entry",
+ phase2);
+ if (!parent)
+ return NULL;
+
+ method = (EAPMethodTLS *) parent;
+ method->new_connection = secrets_only ? FALSE : TRUE;
+
+ eap_method_nag_init (parent, "eap_tls_ca_cert_button", connection);
+
+ if (connection)
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_identity_entry"));
+ g_assert (widget);
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) wireless_security_changed_cb,
+ ws_parent);
+ if (s_8021x && nm_setting_802_1x_get_identity (s_8021x))
+ gtk_entry_set_text (GTK_ENTRY (widget), nm_setting_802_1x_get_identity (s_8021x));
+
+ setup_filepicker (parent->builder, "eap_tls_user_cert_button",
+ _("Choose your personal certificate..."),
+ ws_parent, parent, s_8021x,
+ phase2 ? nm_setting_802_1x_get_phase2_client_cert_scheme : nm_setting_802_1x_get_client_cert_scheme,
+ phase2 ? nm_setting_802_1x_get_phase2_client_cert_path : nm_setting_802_1x_get_client_cert_path,
+ FALSE, TRUE);
+ setup_filepicker (parent->builder, "eap_tls_ca_cert_button",
+ _("Choose a Certificate Authority certificate..."),
+ ws_parent, parent, s_8021x,
+ phase2 ? nm_setting_802_1x_get_phase2_ca_cert_scheme : nm_setting_802_1x_get_ca_cert_scheme,
+ phase2 ? nm_setting_802_1x_get_phase2_ca_cert_path : nm_setting_802_1x_get_ca_cert_path,
+ FALSE, FALSE);
+ setup_filepicker (parent->builder, "eap_tls_private_key_button",
+ _("Choose your private key..."),
+ ws_parent, parent, s_8021x,
+ phase2 ? nm_setting_802_1x_get_phase2_private_key_scheme : nm_setting_802_1x_get_private_key_scheme,
+ phase2 ? nm_setting_802_1x_get_phase2_private_key_path : nm_setting_802_1x_get_private_key_path,
+ TRUE, FALSE);
+
+ /* Fill secrets, if any */
+ if (connection)
+ update_secrets (parent, connection);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_private_key_password_entry"));
+ g_assert (widget);
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) wireless_security_changed_cb,
+ ws_parent);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "show_checkbutton_eaptls"));
+ g_assert (widget);
+ g_signal_connect (G_OBJECT (widget), "toggled",
+ (GCallback) show_toggled_cb,
+ parent);
+
+ if (secrets_only) {
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_identity_entry"));
+ gtk_widget_set_sensitive (widget, FALSE);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_user_cert_label"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_user_cert_button"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_private_key_label"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_private_key_button"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_ca_cert_label"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_ca_cert_button"));
+ gtk_widget_hide (widget);
+ }
+
+ return method;
+}
+
diff --git a/panels/network/wireless-security/eap-method-tls.h b/panels/network/wireless-security/eap-method-tls.h
new file mode 100644
index 0000000..147a75f
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-tls.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#ifndef EAP_METHOD_TLS_H
+#define EAP_METHOD_TLS_H
+
+#include "wireless-security.h"
+
+typedef struct _EAPMethodTLS EAPMethodTLS;
+
+EAPMethodTLS *eap_method_tls_new (WirelessSecurity *ws_parent,
+ NMConnection *connection,
+ gboolean phase2,
+ gboolean secrets_only);
+
+#endif /* EAP_METHOD_TLS_H */
+
diff --git a/panels/network/wireless-security/eap-method-tls.ui b/panels/network/wireless-security/eap-method-tls.ui
new file mode 100644
index 0000000..028e73e
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-tls.ui
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkNotebook" id="eap_tls_notebook">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="show_tabs">False</property>
+ <property name="show_border">False</property>
+ <child>
+ <object class="GtkTable" id="table8">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="n_rows">6</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eap_tls_identity_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">I_dentity</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_tls_identity_entry</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="eap_tls_identity_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eap_tls_user_cert_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_User certificate</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_tls_user_cert_button</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eap_tls_ca_cert_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">C_A certificate</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_tls_ca_cert_button</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFileChooserButton" id="eap_tls_ca_cert_button">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eap_tls_private_key_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Private _key</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_tls_private_key_button</property>
+ </object>
+ <packing>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFileChooserButton" id="eap_tls_private_key_button">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eap_tls_private_key_password_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Private key password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_tls_private_key_password_entry</property>
+ </object>
+ <packing>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="eap_tls_private_key_password_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="visibility">False</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="show_checkbutton_eaptls">
+ <property name="label" translatable="yes">Sho_w password</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">5</property>
+ <property name="bottom_attach">6</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFileChooserButton" id="eap_tls_user_cert_button">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label34">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/panels/network/wireless-security/eap-method-ttls.c b/panels/network/wireless-security/eap-method-ttls.c
new file mode 100644
index 0000000..5ad8599
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-ttls.c
@@ -0,0 +1,391 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <ctype.h>
+#include <string.h>
+
+#include <nm-setting-connection.h>
+#include <nm-setting-8021x.h>
+
+#include "eap-method.h"
+#include "wireless-security.h"
+
+#define I_NAME_COLUMN 0
+#define I_METHOD_COLUMN 1
+
+struct _EAPMethodTTLS {
+ EAPMethod parent;
+
+ GtkSizeGroup *size_group;
+ WirelessSecurity *sec_parent;
+ gboolean is_editor;
+};
+
+static void
+destroy (EAPMethod *parent)
+{
+ EAPMethodTTLS *method = (EAPMethodTTLS *) parent;
+
+ if (method->size_group)
+ g_object_unref (method->size_group);
+}
+
+static gboolean
+validate (EAPMethod *parent)
+{
+ GtkWidget *widget;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ EAPMethod *eap = NULL;
+ gboolean valid = FALSE;
+
+ if (!eap_method_validate_filepicker (parent->builder, "eap_ttls_ca_cert_button", TYPE_CA_CERT, NULL, NULL))
+ return FALSE;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_inner_auth_combo"));
+ g_assert (widget);
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+ gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+ g_assert (eap);
+ valid = eap_method_validate (eap);
+ eap_method_unref (eap);
+ return valid;
+}
+
+static void
+add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
+{
+ EAPMethodTTLS *method = (EAPMethodTTLS *) parent;
+ GtkWidget *widget;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ EAPMethod *eap;
+
+ if (method->size_group)
+ g_object_unref (method->size_group);
+ method->size_group = g_object_ref (group);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_anon_identity_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_ca_cert_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_inner_auth_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_inner_auth_combo"));
+ g_assert (widget);
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+ gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+ g_assert (eap);
+ eap_method_add_to_size_group (eap, group);
+ eap_method_unref (eap);
+}
+
+static void
+fill_connection (EAPMethod *parent, NMConnection *connection)
+{
+ NMSetting8021x *s_8021x;
+ NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ GtkWidget *widget;
+ const char *text;
+ char *filename;
+ EAPMethod *eap = NULL;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GError *error = NULL;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ g_assert (s_8021x);
+
+ nm_setting_802_1x_add_eap_method (s_8021x, "ttls");
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_anon_identity_entry"));
+ g_assert (widget);
+ text = gtk_entry_get_text (GTK_ENTRY (widget));
+ if (text && strlen (text))
+ g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, text, NULL);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_ca_cert_button"));
+ g_assert (widget);
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+ if (!nm_setting_802_1x_set_ca_cert (s_8021x, filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+ g_warning ("Couldn't read CA certificate '%s': %s", filename, error ? error->message : "(unknown)");
+ g_clear_error (&error);
+ }
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_inner_auth_combo"));
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+ gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+ g_assert (eap);
+
+ eap_method_fill_connection (eap, connection);
+ eap_method_unref (eap);
+}
+
+static void
+inner_auth_combo_changed_cb (GtkWidget *combo, gpointer user_data)
+{
+ EAPMethod *parent = (EAPMethod *) user_data;
+ EAPMethodTTLS *method = (EAPMethodTTLS *) parent;
+ GtkWidget *vbox;
+ EAPMethod *eap = NULL;
+ GList *elt, *children;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkWidget *eap_widget;
+
+ vbox = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_inner_auth_vbox"));
+ g_assert (vbox);
+
+ /* Remove any previous wireless security widgets */
+ children = gtk_container_get_children (GTK_CONTAINER (vbox));
+ for (elt = children; elt; elt = g_list_next (elt))
+ gtk_container_remove (GTK_CONTAINER (vbox), GTK_WIDGET (elt->data));
+ g_list_free (children);
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter);
+ gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+ g_assert (eap);
+
+ eap_widget = eap_method_get_widget (eap);
+ g_assert (eap_widget);
+ gtk_widget_unparent (eap_widget);
+
+ if (method->size_group)
+ eap_method_add_to_size_group (eap, method->size_group);
+ gtk_container_add (GTK_CONTAINER (vbox), eap_widget);
+
+ eap_method_unref (eap);
+
+ wireless_security_changed_cb (combo, method->sec_parent);
+}
+
+static GtkWidget *
+inner_auth_combo_init (EAPMethodTTLS *method,
+ NMConnection *connection,
+ NMSetting8021x *s_8021x,
+ gboolean secrets_only)
+{
+ EAPMethod *parent = (EAPMethod *) method;
+ GtkWidget *combo;
+ GtkListStore *auth_model;
+ GtkTreeIter iter;
+ EAPMethodSimple *em_pap;
+ EAPMethodSimple *em_mschap;
+ EAPMethodSimple *em_mschap_v2;
+ EAPMethodSimple *em_chap;
+ guint32 active = 0;
+ const char *phase2_auth = NULL;
+
+ auth_model = gtk_list_store_new (2, G_TYPE_STRING, eap_method_get_g_type ());
+
+ if (s_8021x) {
+ if (nm_setting_802_1x_get_phase2_auth (s_8021x))
+ phase2_auth = nm_setting_802_1x_get_phase2_auth (s_8021x);
+ else if (nm_setting_802_1x_get_phase2_autheap (s_8021x))
+ phase2_auth = nm_setting_802_1x_get_phase2_autheap (s_8021x);
+ }
+
+ em_pap = eap_method_simple_new (method->sec_parent,
+ connection,
+ EAP_METHOD_SIMPLE_TYPE_PAP,
+ TRUE,
+ method->is_editor,
+ secrets_only);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ I_NAME_COLUMN, _("PAP"),
+ I_METHOD_COLUMN, em_pap,
+ -1);
+ eap_method_unref (EAP_METHOD (em_pap));
+
+ /* Check for defaulting to PAP */
+ if (phase2_auth && !strcasecmp (phase2_auth, "pap"))
+ active = 0;
+
+ em_mschap = eap_method_simple_new (method->sec_parent,
+ connection,
+ EAP_METHOD_SIMPLE_TYPE_MSCHAP,
+ TRUE,
+ method->is_editor,
+ secrets_only);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ I_NAME_COLUMN, _("MSCHAP"),
+ I_METHOD_COLUMN, em_mschap,
+ -1);
+ eap_method_unref (EAP_METHOD (em_mschap));
+
+ /* Check for defaulting to MSCHAP */
+ if (phase2_auth && !strcasecmp (phase2_auth, "mschap"))
+ active = 1;
+
+ em_mschap_v2 = eap_method_simple_new (method->sec_parent,
+ connection,
+ EAP_METHOD_SIMPLE_TYPE_MSCHAP_V2,
+ TRUE,
+ method->is_editor, secrets_only);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ I_NAME_COLUMN, _("MSCHAPv2"),
+ I_METHOD_COLUMN, em_mschap_v2,
+ -1);
+ eap_method_unref (EAP_METHOD (em_mschap_v2));
+
+ /* Check for defaulting to MSCHAPv2 */
+ if (phase2_auth && !strcasecmp (phase2_auth, "mschapv2"))
+ active = 2;
+
+ em_chap = eap_method_simple_new (method->sec_parent,
+ connection,
+ EAP_METHOD_SIMPLE_TYPE_CHAP,
+ TRUE,
+ method->is_editor,
+ secrets_only);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ I_NAME_COLUMN, _("CHAP"),
+ I_METHOD_COLUMN, em_chap,
+ -1);
+ eap_method_unref (EAP_METHOD (em_chap));
+
+ /* Check for defaulting to CHAP */
+ if (phase2_auth && !strcasecmp (phase2_auth, "chap"))
+ active = 3;
+
+ combo = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_inner_auth_combo"));
+ g_assert (combo);
+
+ gtk_combo_box_set_model (GTK_COMBO_BOX (combo), GTK_TREE_MODEL (auth_model));
+ g_object_unref (G_OBJECT (auth_model));
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combo), active);
+
+ g_signal_connect (G_OBJECT (combo), "changed",
+ (GCallback) inner_auth_combo_changed_cb,
+ method);
+ return combo;
+}
+
+static void
+update_secrets (EAPMethod *parent, NMConnection *connection)
+{
+ eap_method_phase2_update_secrets_helper (parent,
+ connection,
+ "eap_ttls_inner_auth_combo",
+ I_METHOD_COLUMN);
+}
+
+EAPMethodTTLS *
+eap_method_ttls_new (WirelessSecurity *ws_parent,
+ NMConnection *connection,
+ gboolean is_editor,
+ gboolean secrets_only)
+{
+ EAPMethod *parent;
+ EAPMethodTTLS *method;
+ GtkWidget *widget;
+ GtkFileFilter *filter;
+ NMSetting8021x *s_8021x = NULL;
+ const char *filename;
+
+ parent = eap_method_init (sizeof (EAPMethodTTLS),
+ validate,
+ add_to_size_group,
+ fill_connection,
+ update_secrets,
+ destroy,
+ "/org/gnome/control-center/network/eap-method-ttls.ui",
+ "eap_ttls_notebook",
+ "eap_ttls_anon_identity_entry",
+ FALSE);
+ if (!parent)
+ return NULL;
+
+ eap_method_nag_init (parent, "eap_ttls_ca_cert_button", connection);
+
+ method = (EAPMethodTTLS *) parent;
+ method->sec_parent = ws_parent;
+ method->is_editor = is_editor;
+
+ if (connection)
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_ca_cert_button"));
+ g_assert (widget);
+ gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (widget), TRUE);
+ gtk_file_chooser_button_set_title (GTK_FILE_CHOOSER_BUTTON (widget),
+ _("Choose a Certificate Authority certificate..."));
+ g_signal_connect (G_OBJECT (widget), "selection-changed",
+ (GCallback) wireless_security_changed_cb,
+ ws_parent);
+ filter = eap_method_default_file_chooser_filter_new (FALSE);
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (widget), filter);
+ if (connection && s_8021x) {
+ if (nm_setting_802_1x_get_ca_cert_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH) {
+ filename = nm_setting_802_1x_get_ca_cert_path (s_8021x);
+ if (filename)
+ gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), filename);
+ }
+ }
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_anon_identity_entry"));
+ if (s_8021x && nm_setting_802_1x_get_anonymous_identity (s_8021x))
+ gtk_entry_set_text (GTK_ENTRY (widget), nm_setting_802_1x_get_anonymous_identity (s_8021x));
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) wireless_security_changed_cb,
+ ws_parent);
+
+ widget = inner_auth_combo_init (method, connection, s_8021x, secrets_only);
+ inner_auth_combo_changed_cb (widget, (gpointer) method);
+
+ if (secrets_only) {
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_anon_identity_label"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_anon_identity_entry"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_ca_cert_label"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_ca_cert_button"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_inner_auth_label"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_inner_auth_combo"));
+ gtk_widget_hide (widget);
+ }
+
+ return method;
+}
+
diff --git a/panels/network/wireless-security/eap-method-ttls.h b/panels/network/wireless-security/eap-method-ttls.h
new file mode 100644
index 0000000..16467f6
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-ttls.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#ifndef EAP_METHOD_TTLS_H
+#define EAP_METHOD_TTLS_H
+
+#include "wireless-security.h"
+
+typedef struct _EAPMethodTTLS EAPMethodTTLS;
+
+EAPMethodTTLS *eap_method_ttls_new (WirelessSecurity *ws_parent,
+ NMConnection *connection,
+ gboolean is_editor,
+ gboolean secrets_only);
+
+#endif /* EAP_METHOD_TLS_H */
+
diff --git a/panels/network/wireless-security/eap-method-ttls.ui b/panels/network/wireless-security/eap-method-ttls.ui
new file mode 100644
index 0000000..39465cf
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-ttls.ui
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkListStore" id="model6">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes"> </col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkNotebook" id="eap_ttls_notebook">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="show_tabs">False</property>
+ <property name="show_border">False</property>
+ <child>
+ <object class="GtkTable" id="table10">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="n_rows">4</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="eap_ttls_anon_identity_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Anony_mous identity</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_ttls_anon_identity_entry</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="eap_ttls_anon_identity_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eap_ttls_ca_cert_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">C_A certificate</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_ttls_ca_cert_button</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFileChooserButton" id="eap_ttls_ca_cert_button">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eap_ttls_inner_auth_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Inner authentication</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_ttls_inner_auth_combo</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="eap_ttls_inner_auth_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">model6</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer6"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="eap_ttls_inner_auth_vbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="right_attach">2</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label49">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/panels/network/wireless-security/eap-method.c b/panels/network/wireless-security/eap-method.c
new file mode 100644
index 0000000..8ff9778
--- /dev/null
+++ b/panels/network/wireless-security/eap-method.c
@@ -0,0 +1,660 @@
+/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2012 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <nm-setting-connection.h>
+#include <nm-setting-8021x.h>
+#include "eap-method.h"
+#include "nm-utils.h"
+
+GType
+eap_method_get_g_type (void)
+{
+ static GType type_id = 0;
+
+ if (!type_id) {
+ type_id = g_boxed_type_register_static ("EAPMethod",
+ (GBoxedCopyFunc) eap_method_ref,
+ (GBoxedFreeFunc) eap_method_unref);
+ }
+
+ return type_id;
+}
+
+GtkWidget *
+eap_method_get_widget (EAPMethod *method)
+{
+ g_return_val_if_fail (method != NULL, NULL);
+
+ return method->ui_widget;
+}
+
+gboolean
+eap_method_validate (EAPMethod *method)
+{
+ g_return_val_if_fail (method != NULL, FALSE);
+
+ g_assert (method->validate);
+ return (*(method->validate)) (method);
+}
+
+void
+eap_method_add_to_size_group (EAPMethod *method, GtkSizeGroup *group)
+{
+ g_return_if_fail (method != NULL);
+ g_return_if_fail (group != NULL);
+
+ g_assert (method->add_to_size_group);
+ return (*(method->add_to_size_group)) (method, group);
+}
+
+void
+eap_method_fill_connection (EAPMethod *method, NMConnection *connection)
+{
+ g_return_if_fail (method != NULL);
+ g_return_if_fail (connection != NULL);
+
+ g_assert (method->fill_connection);
+ return (*(method->fill_connection)) (method, connection);
+}
+
+void
+eap_method_update_secrets (EAPMethod *method, NMConnection *connection)
+{
+ g_return_if_fail (method != NULL);
+ g_return_if_fail (connection != NULL);
+
+ if (method->update_secrets)
+ method->update_secrets (method, connection);
+}
+
+typedef struct {
+ EAPMethod *method;
+ NMConnection *connection;
+} NagDialogResponseInfo;
+
+static void
+nag_dialog_destroyed (gpointer data, GObject *dialog_ptr)
+{
+ NagDialogResponseInfo *info = (NagDialogResponseInfo *) data;
+
+ memset (info, '\0', sizeof (NagDialogResponseInfo));
+ g_free (info);
+}
+
+static GSettings *
+_get_ca_ignore_settings (const char *uuid)
+{
+ GSettings *settings;
+ char *path = NULL;
+
+ path = g_strdup_printf ("/org/gnome/nm-applet/eap/%s", uuid);
+ settings = g_settings_new_with_path ("org.gnome.nm-applet.eap", path);
+ g_free (path);
+
+ return settings;
+}
+
+static void
+_set_ignore_ca_cert (const char *uuid, gboolean phase2, gboolean ignore)
+{
+ GSettings *settings;
+ const char *key;
+
+ g_return_if_fail (uuid != NULL);
+
+ settings = _get_ca_ignore_settings (uuid);
+ key = phase2 ? "ignore-phase2-ca-cert" : "ignore-ca-cert";
+ g_settings_set_boolean (settings, key, ignore);
+ g_object_unref (settings);
+}
+
+static void
+nag_dialog_response_cb (GtkDialog *nag_dialog,
+ gint response,
+ gpointer user_data)
+{
+ NagDialogResponseInfo *info = (NagDialogResponseInfo *) user_data;
+ EAPMethod *method = (EAPMethod *) info->method;
+ NMConnection *connection = (NMConnection *) info->connection;
+ GtkWidget *widget;
+
+ if (response == GTK_RESPONSE_NO) {
+ /* Grab the value of the "don't bother me" checkbox */
+ widget = GTK_WIDGET (gtk_builder_get_object (method->nag_builder, "ignore_checkbox"));
+ g_assert (widget);
+
+ method->ignore_ca_cert = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+
+ /* And save it */
+ _set_ignore_ca_cert (nm_connection_get_uuid (connection),
+ method->phase2,
+ method->ignore_ca_cert);
+ }
+
+ gtk_widget_hide (GTK_WIDGET (nag_dialog));
+}
+
+static gboolean
+nag_dialog_delete_event_cb (GtkDialog *nag_dialog, GdkEvent *e, gpointer user_data)
+{
+ // FIXME?: By emitting response signal, dismissing nag dialog with upper right "x" icon,
+ // Alt-F4, or Esc would have the same behaviour as clicking "Ignore" button.
+ //g_signal_emit_by_name (nag_dialog, "response", GTK_RESPONSE_NO, user_data);
+ return TRUE; /* do not destroy */
+}
+
+GtkWidget *
+eap_method_nag_user (EAPMethod *method)
+{
+ GtkWidget *widget;
+ char *filename = NULL;
+
+ g_return_val_if_fail (method != NULL, NULL);
+
+ if (!method->nag_dialog || method->ignore_ca_cert)
+ return NULL;
+
+ /* Checkbox should be unchecked each time dialog comes up */
+ widget = GTK_WIDGET (gtk_builder_get_object (method->nag_builder, "ignore_checkbox"));
+ g_assert (widget);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
+
+ /* Nag the user if the CA Cert is blank, since it's a security risk. */
+ widget = GTK_WIDGET (gtk_builder_get_object (method->builder, method->ca_cert_chooser));
+ g_assert (widget);
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+ if (filename != NULL) {
+ g_free (filename);
+ return NULL;
+ }
+
+ gtk_window_present (GTK_WINDOW (method->nag_dialog));
+ return method->nag_dialog;
+}
+
+#define NAG_DIALOG_UI "/org/gnome/control-center/network/nag-user-dialog.ui"
+
+static gboolean
+_get_ignore_ca_cert (const char *uuid, gboolean phase2)
+{
+ GSettings *settings;
+ const char *key;
+ gboolean ignore = FALSE;
+
+ g_return_val_if_fail (uuid != NULL, FALSE);
+
+ settings = _get_ca_ignore_settings (uuid);
+
+ key = phase2 ? "ignore-phase2-ca-cert" : "ignore-ca-cert";
+ ignore = g_settings_get_boolean (settings, key);
+
+ g_object_unref (settings);
+ return ignore;
+}
+
+gboolean
+eap_method_nag_init (EAPMethod *method,
+ const char *ca_cert_chooser,
+ NMConnection *connection)
+{
+ GtkWidget *dialog, *widget;
+ NagDialogResponseInfo *info;
+ GError *error = NULL;
+ char *text;
+
+ g_return_val_if_fail (method != NULL, FALSE);
+ g_return_val_if_fail (ca_cert_chooser != NULL, FALSE);
+
+ method->nag_builder = gtk_builder_new ();
+ if (!gtk_builder_add_from_resource (method->nag_builder, NAG_DIALOG_UI, &error)) {
+ g_warning ("Couldn't load UI builder file " NAG_DIALOG_UI ": %s",
+ error->message);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ method->ca_cert_chooser = g_strdup (ca_cert_chooser);
+ if (connection) {
+ NMSettingConnection *s_con;
+ const char *uuid;
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_assert (s_con);
+ uuid = nm_setting_connection_get_uuid (s_con);
+ g_assert (uuid);
+
+ /* Figure out if the user wants to ignore missing CA cert */
+ method->ignore_ca_cert = _get_ignore_ca_cert (uuid, method->phase2);
+ }
+
+ info = g_malloc0 (sizeof (NagDialogResponseInfo));
+ info->method = method;
+ info->connection = connection;
+
+ dialog = GTK_WIDGET (gtk_builder_get_object (method->nag_builder, "nag_user_dialog"));
+ g_assert (dialog);
+ g_signal_connect (dialog, "response", G_CALLBACK (nag_dialog_response_cb), info);
+ g_signal_connect (dialog, "delete-event", G_CALLBACK (nag_dialog_delete_event_cb), info);
+ g_object_weak_ref (G_OBJECT (dialog), nag_dialog_destroyed, info);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (method->nag_builder, "content_label"));
+ g_assert (widget);
+
+ text = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">%s</span>\n\n%s",
+ _("No Certificate Authority certificate chosen"),
+ _("Not using a Certificate Authority (CA) certificate can result in connections to insecure, rogue Wi-Fi networks. Would you like to choose a Certificate Authority certificate?"));
+ gtk_label_set_markup (GTK_LABEL (widget), text);
+ g_free (text);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (method->nag_builder, "ignore_button"));
+ gtk_button_set_label (GTK_BUTTON (widget), _("Ignore"));
+ g_assert (widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (method->nag_builder, "change_button"));
+ gtk_button_set_label (GTK_BUTTON (widget), _("Choose CA Certificate"));
+ g_assert (widget);
+
+ method->nag_dialog = dialog;
+ return TRUE;
+}
+
+void
+eap_method_phase2_update_secrets_helper (EAPMethod *method,
+ NMConnection *connection,
+ const char *combo_name,
+ guint32 column)
+{
+ GtkWidget *combo;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+
+ g_return_if_fail (method != NULL);
+ g_return_if_fail (connection != NULL);
+ g_return_if_fail (combo_name != NULL);
+
+ combo = GTK_WIDGET (gtk_builder_get_object (method->builder, combo_name));
+ g_assert (combo);
+
+ /* Let each EAP phase2 method try to update its secrets */
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
+ if (gtk_tree_model_get_iter_first (model, &iter)) {
+ do {
+ EAPMethod *eap = NULL;
+
+ gtk_tree_model_get (model, &iter, column, &eap, -1);
+ if (eap) {
+ eap_method_update_secrets (eap, connection);
+ eap_method_unref (eap);
+ }
+ } while (gtk_tree_model_iter_next (model, &iter));
+ }
+}
+
+EAPMethod *
+eap_method_init (gsize obj_size,
+ EMValidateFunc validate,
+ EMAddToSizeGroupFunc add_to_size_group,
+ EMFillConnectionFunc fill_connection,
+ EMUpdateSecretsFunc update_secrets,
+ EMDestroyFunc destroy,
+ const char *ui_resource,
+ const char *ui_widget_name,
+ const char *default_field,
+ gboolean phase2)
+{
+ EAPMethod *method;
+ GError *error = NULL;
+
+ g_return_val_if_fail (obj_size > 0, NULL);
+ g_return_val_if_fail (ui_resource != NULL, NULL);
+ g_return_val_if_fail (ui_widget_name != NULL, NULL);
+
+ method = g_slice_alloc0 (obj_size);
+ g_assert (method);
+
+ method->refcount = 1;
+ method->obj_size = obj_size;
+ method->validate = validate;
+ method->add_to_size_group = add_to_size_group;
+ method->fill_connection = fill_connection;
+ method->update_secrets = update_secrets;
+ method->destroy = destroy;
+ method->default_field = default_field;
+ method->phase2 = phase2;
+
+ method->builder = gtk_builder_new ();
+ if (!gtk_builder_add_from_resource (method->builder, ui_resource, &error)) {
+ g_warning ("Couldn't load UI builder file %s: %s",
+ ui_resource, error->message);
+ eap_method_unref (method);
+ return NULL;
+ }
+
+ method->ui_widget = GTK_WIDGET (gtk_builder_get_object (method->builder, ui_widget_name));
+ if (!method->ui_widget) {
+ g_warning ("Couldn't load UI widget '%s' from UI file %s",
+ ui_widget_name, ui_resource);
+ eap_method_unref (method);
+ return NULL;
+ }
+ g_object_ref_sink (method->ui_widget);
+
+ return method;
+}
+
+
+EAPMethod *
+eap_method_ref (EAPMethod *method)
+{
+ g_return_val_if_fail (method != NULL, NULL);
+ g_return_val_if_fail (method->refcount > 0, NULL);
+
+ method->refcount++;
+ return method;
+}
+
+void
+eap_method_unref (EAPMethod *method)
+{
+ g_return_if_fail (method != NULL);
+ g_return_if_fail (method->refcount > 0);
+
+ method->refcount--;
+ if (method->refcount == 0) {
+ if (method->destroy)
+ method->destroy (method);
+
+ if (method->nag_dialog)
+ gtk_widget_destroy (method->nag_dialog);
+ if (method->nag_builder)
+ g_object_unref (method->nag_builder);
+ g_free (method->ca_cert_chooser);
+ if (method->builder)
+ g_object_unref (method->builder);
+ if (method->ui_widget)
+ g_object_unref (method->ui_widget);
+
+ g_slice_free1 (method->obj_size, method);
+ }
+}
+
+gboolean
+eap_method_validate_filepicker (GtkBuilder *builder,
+ const char *name,
+ guint32 item_type,
+ const char *password,
+ NMSetting8021xCKFormat *out_format)
+{
+ GtkWidget *widget;
+ char *filename;
+ NMSetting8021x *setting;
+ gboolean success = FALSE;
+ GError *error = NULL;
+
+ if (item_type == TYPE_PRIVATE_KEY) {
+ g_return_val_if_fail (password != NULL, FALSE);
+ g_return_val_if_fail (strlen (password), FALSE);
+ }
+
+ widget = GTK_WIDGET (gtk_builder_get_object (builder, name));
+ g_assert (widget);
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+ if (!filename)
+ return (item_type == TYPE_CA_CERT) ? TRUE : FALSE;
+
+ if (!g_file_test (filename, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
+ goto out;
+
+ setting = (NMSetting8021x *) nm_setting_802_1x_new ();
+
+ if (item_type == TYPE_PRIVATE_KEY) {
+ if (!nm_setting_802_1x_set_private_key (setting, filename, password, NM_SETTING_802_1X_CK_SCHEME_PATH, out_format, &error)) {
+ g_warning ("Error: couldn't verify private key: %d %s",
+ error ? error->code : -1, error ? error->message : "(none)");
+ g_clear_error (&error);
+ } else
+ success = TRUE;
+ } else if (item_type == TYPE_CLIENT_CERT) {
+ if (!nm_setting_802_1x_set_client_cert (setting, filename, NM_SETTING_802_1X_CK_SCHEME_PATH, out_format, &error)) {
+ g_warning ("Error: couldn't verify client certificate: %d %s",
+ error ? error->code : -1, error ? error->message : "(none)");
+ g_clear_error (&error);
+ } else
+ success = TRUE;
+ } else if (item_type == TYPE_CA_CERT) {
+ if (!nm_setting_802_1x_set_ca_cert (setting, filename, NM_SETTING_802_1X_CK_SCHEME_PATH, out_format, &error)) {
+ g_warning ("Error: couldn't verify CA certificate: %d %s",
+ error ? error->code : -1, error ? error->message : "(none)");
+ g_clear_error (&error);
+ } else
+ success = TRUE;
+ } else
+ g_warning ("%s: invalid item type %d.", __func__, item_type);
+
+ g_object_unref (setting);
+
+out:
+ g_free (filename);
+ return success;
+}
+
+static const char *
+find_tag (const char *tag, const char *buf, gsize len)
+{
+ gsize i, taglen;
+
+ taglen = strlen (tag);
+ if (len < taglen)
+ return NULL;
+
+ for (i = 0; i < len - taglen + 1; i++) {
+ if (memcmp (buf + i, tag, taglen) == 0)
+ return buf + i;
+ }
+ return NULL;
+}
+
+static const char *pem_rsa_key_begin = "-----BEGIN RSA PRIVATE KEY-----";
+static const char *pem_dsa_key_begin = "-----BEGIN DSA PRIVATE KEY-----";
+static const char *pem_pkcs8_enc_key_begin = "-----BEGIN ENCRYPTED PRIVATE KEY-----";
+static const char *pem_pkcs8_dec_key_begin = "-----BEGIN PRIVATE KEY-----";
+static const char *pem_cert_begin = "-----BEGIN CERTIFICATE-----";
+static const char *proc_type_tag = "Proc-Type: 4,ENCRYPTED";
+static const char *dek_info_tag = "DEK-Info:";
+
+static gboolean
+file_has_extension (const char *filename, const char *extensions[])
+{
+ char *p, *ext;
+ int i = 0;
+ gboolean found = FALSE;
+
+ p = strrchr (filename, '.');
+ if (!p)
+ return FALSE;
+
+ ext = g_ascii_strdown (p, -1);
+ if (ext) {
+ while (extensions[i]) {
+ if (!strcmp (ext, extensions[i++])) {
+ found = TRUE;
+ break;
+ }
+ }
+ }
+ g_free (ext);
+
+ return found;
+}
+
+static gboolean
+pem_file_is_encrypted (const char *buffer, gsize bytes_read)
+{
+ /* Check if the private key is encrypted or not by looking for the
+ * old OpenSSL-style proc-type and dec-info tags.
+ */
+ if (find_tag (proc_type_tag, (const char *) buffer, bytes_read)) {
+ if (find_tag (dek_info_tag, (const char *) buffer, bytes_read))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+file_is_der_or_pem (const char *filename,
+ gboolean privkey,
+ gboolean *out_privkey_encrypted)
+{
+ int fd;
+ unsigned char buffer[8192];
+ ssize_t bytes_read;
+ gboolean success = FALSE;
+
+ fd = open (filename, O_RDONLY);
+ if (fd < 0)
+ return FALSE;
+
+ bytes_read = read (fd, buffer, sizeof (buffer) - 1);
+ if (bytes_read < 400) /* needs to be lower? */
+ goto out;
+ buffer[bytes_read] = '\0';
+
+ /* Check for DER signature */
+ if (bytes_read > 2 && buffer[0] == 0x30 && buffer[1] == 0x82) {
+ success = TRUE;
+ goto out;
+ }
+
+ /* Check for PEM signatures */
+ if (privkey) {
+ if (find_tag (pem_rsa_key_begin, (const char *) buffer, bytes_read)) {
+ success = TRUE;
+ if (out_privkey_encrypted)
+ *out_privkey_encrypted = pem_file_is_encrypted ((const char *) buffer, bytes_read);
+ goto out;
+ }
+
+ if (find_tag (pem_dsa_key_begin, (const char *) buffer, bytes_read)) {
+ success = TRUE;
+ if (out_privkey_encrypted)
+ *out_privkey_encrypted = pem_file_is_encrypted ((const char *) buffer, bytes_read);
+ goto out;
+ }
+
+ if (find_tag (pem_pkcs8_enc_key_begin, (const char *) buffer, bytes_read)) {
+ success = TRUE;
+ if (out_privkey_encrypted)
+ *out_privkey_encrypted = TRUE;
+ goto out;
+ }
+
+ if (find_tag (pem_pkcs8_dec_key_begin, (const char *) buffer, bytes_read)) {
+ success = TRUE;
+ if (out_privkey_encrypted)
+ *out_privkey_encrypted = FALSE;
+ goto out;
+ }
+ } else {
+ if (find_tag (pem_cert_begin, (const char *) buffer, bytes_read)) {
+ success = TRUE;
+ goto out;
+ }
+ }
+
+out:
+ close (fd);
+ return success;
+}
+
+static gboolean
+default_filter_privkey (const GtkFileFilterInfo *filter_info, gpointer user_data)
+{
+ const char *extensions[] = { ".der", ".pem", ".p12", NULL };
+ gboolean require_encrypted = !!user_data;
+ gboolean is_encrypted = TRUE;
+
+ if (!filter_info->filename)
+ return FALSE;
+
+ if (!file_has_extension (filter_info->filename, extensions))
+ return FALSE;
+
+ if ( !file_is_der_or_pem (filter_info->filename, TRUE, &is_encrypted)
+ && !nm_utils_file_is_pkcs12 (filter_info->filename))
+ return FALSE;
+
+ return require_encrypted ? is_encrypted : TRUE;
+}
+
+static gboolean
+default_filter_cert (const GtkFileFilterInfo *filter_info, gpointer user_data)
+{
+ const char *extensions[] = { ".der", ".pem", ".crt", ".cer", NULL };
+
+ if (!filter_info->filename)
+ return FALSE;
+
+ if (!file_has_extension (filter_info->filename, extensions))
+ return FALSE;
+
+ if (!file_is_der_or_pem (filter_info->filename, FALSE, NULL))
+ return FALSE;
+
+ return TRUE;
+}
+
+GtkFileFilter *
+eap_method_default_file_chooser_filter_new (gboolean privkey)
+{
+ GtkFileFilter *filter;
+
+ filter = gtk_file_filter_new ();
+ if (privkey) {
+ gtk_file_filter_add_custom (filter, GTK_FILE_FILTER_FILENAME, default_filter_privkey, NULL, NULL);
+ gtk_file_filter_set_name (filter, _("DER, PEM, or PKCS#12 private keys (*.der, *.pem, *.p12)"));
+ } else {
+ gtk_file_filter_add_custom (filter, GTK_FILE_FILTER_FILENAME, default_filter_cert, NULL, NULL);
+ gtk_file_filter_set_name (filter, _("DER or PEM certificates (*.der, *.pem, *.crt, *.cer)"));
+ }
+ return filter;
+}
+
+gboolean
+eap_method_is_encrypted_private_key (const char *path)
+{
+ GtkFileFilterInfo info = { .filename = path };
+
+ return default_filter_privkey (&info, (gpointer) TRUE);
+}
+
diff --git a/panels/network/wireless-security/eap-method.h b/panels/network/wireless-security/eap-method.h
new file mode 100644
index 0000000..d2933c7
--- /dev/null
+++ b/panels/network/wireless-security/eap-method.h
@@ -0,0 +1,128 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2012 Red Hat, Inc.
+ */
+
+#ifndef EAP_METHOD_H
+#define EAP_METHOD_H
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+#include <nm-connection.h>
+#include <nm-setting-8021x.h>
+
+typedef struct _EAPMethod EAPMethod;
+
+typedef void (*EMAddToSizeGroupFunc) (EAPMethod *method, GtkSizeGroup *group);
+typedef void (*EMFillConnectionFunc) (EAPMethod *method, NMConnection *connection);
+typedef void (*EMUpdateSecretsFunc) (EAPMethod *method, NMConnection *connection);
+typedef void (*EMDestroyFunc) (EAPMethod *method);
+typedef gboolean (*EMValidateFunc) (EAPMethod *method);
+
+struct _EAPMethod {
+ guint32 refcount;
+ gsize obj_size;
+
+ GtkBuilder *builder;
+ GtkWidget *ui_widget;
+
+ GtkBuilder *nag_builder;
+ char *ca_cert_chooser;
+ const char *default_field;
+ GtkWidget *nag_dialog;
+
+ gboolean phase2;
+ gboolean secrets_only;
+ gboolean ignore_ca_cert;
+
+ EMAddToSizeGroupFunc add_to_size_group;
+ EMFillConnectionFunc fill_connection;
+ EMUpdateSecretsFunc update_secrets;
+ EMValidateFunc validate;
+ EMDestroyFunc destroy;
+};
+
+#define EAP_METHOD(x) ((EAPMethod *) x)
+
+
+GtkWidget *eap_method_get_widget (EAPMethod *method);
+
+gboolean eap_method_validate (EAPMethod *method);
+
+void eap_method_add_to_size_group (EAPMethod *method, GtkSizeGroup *group);
+
+void eap_method_fill_connection (EAPMethod *method, NMConnection *connection);
+
+void eap_method_update_secrets (EAPMethod *method, NMConnection *connection);
+
+GtkWidget * eap_method_nag_user (EAPMethod *method);
+
+EAPMethod *eap_method_ref (EAPMethod *method);
+
+void eap_method_unref (EAPMethod *method);
+
+GType eap_method_get_g_type (void);
+
+/* Below for internal use only */
+
+#include "eap-method-tls.h"
+#include "eap-method-leap.h"
+#include "eap-method-fast.h"
+#include "eap-method-ttls.h"
+#include "eap-method-peap.h"
+#include "eap-method-simple.h"
+
+EAPMethod *eap_method_init (gsize obj_size,
+ EMValidateFunc validate,
+ EMAddToSizeGroupFunc add_to_size_group,
+ EMFillConnectionFunc fill_connection,
+ EMUpdateSecretsFunc update_secrets,
+ EMDestroyFunc destroy,
+ const char *ui_resource,
+ const char *ui_widget_name,
+ const char *default_field,
+ gboolean phase2);
+
+GtkFileFilter * eap_method_default_file_chooser_filter_new (gboolean privkey);
+
+gboolean eap_method_is_encrypted_private_key (const char *path);
+
+#define TYPE_CLIENT_CERT 0
+#define TYPE_CA_CERT 1
+#define TYPE_PRIVATE_KEY 2
+
+gboolean eap_method_validate_filepicker (GtkBuilder *builder,
+ const char *name,
+ guint32 item_type,
+ const char *password,
+ NMSetting8021xCKFormat *out_format);
+
+gboolean eap_method_nag_init (EAPMethod *method,
+ const char *ca_cert_chooser,
+ NMConnection *connection);
+
+void eap_method_phase2_update_secrets_helper (EAPMethod *method,
+ NMConnection *connection,
+ const char *combo_name,
+ guint32 column);
+
+#endif /* EAP_METHOD_H */
+
diff --git a/panels/network/wireless-security/helpers.c b/panels/network/wireless-security/helpers.c
new file mode 100644
index 0000000..5d7941d
--- /dev/null
+++ b/panels/network/wireless-security/helpers.c
@@ -0,0 +1,51 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2009 Red Hat, Inc.
+ */
+
+#include "helpers.h"
+
+void
+helper_fill_secret_entry (NMConnection *connection,
+ GtkBuilder *builder,
+ const char *entry_name,
+ GType setting_type,
+ HelperSecretFunc func)
+{
+ GtkWidget *widget;
+ NMSetting *setting;
+ const char *tmp;
+
+ g_return_if_fail (connection != NULL);
+ g_return_if_fail (builder != NULL);
+ g_return_if_fail (entry_name != NULL);
+ g_return_if_fail (func != NULL);
+
+ setting = nm_connection_get_setting (connection, setting_type);
+ if (setting) {
+ tmp = (*func) (setting);
+ if (tmp) {
+ widget = GTK_WIDGET (gtk_builder_get_object (builder, entry_name));
+ g_assert (widget);
+ gtk_entry_set_text (GTK_ENTRY (widget), tmp);
+ }
+ }
+}
+
diff --git a/panels/network/wireless-security/helpers.h b/panels/network/wireless-security/helpers.h
new file mode 100644
index 0000000..75c01ea
--- /dev/null
+++ b/panels/network/wireless-security/helpers.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2009 Red Hat, Inc.
+ */
+
+#ifndef _HELPERS_H_
+#define _HELPERS_H_
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <nm-connection.h>
+#include <nm-setting.h>
+
+typedef const char * (*HelperSecretFunc)(NMSetting *);
+
+void helper_fill_secret_entry (NMConnection *connection,
+ GtkBuilder *builder,
+ const char *entry_name,
+ GType setting_type,
+ HelperSecretFunc func);
+
+#endif /* _HELPERS_H_ */
+
diff --git a/panels/network/wireless-security/nag-user-dialog.ui b/panels/network/wireless-security/nag-user-dialog.ui
new file mode 100644
index 0000000..d821e11
--- /dev/null
+++ b/panels/network/wireless-security/nag-user-dialog.ui
@@ -0,0 +1,191 @@
+<?xml version="1.0"?>
+<interface>
+ <!-- interface-requires gtk+ 2.6 -->
+ <!-- interface-naming-policy toplevel-contextual -->
+ <object class="GtkDialog" id="nag_user_dialog">
+ <property name="border_width">5</property>
+ <property name="modal">True</property>
+ <property name="window_position">center</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="dialog-vbox2">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">14</property>
+ <child>
+ <object class="GtkHBox" id="hbox5">
+ <property name="visible">True</property>
+ <property name="border_width">5</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkImage" id="image4">
+ <property name="visible">True</property>
+ <property name="yalign">0</property>
+ <property name="stock">gtk-dialog-warning</property>
+ <property name="icon-size">6</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="content_vbox">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="content_label">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="label">alert text</property>
+ <property name="use_markup">True</property>
+ <property name="wrap">True</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="ignore_checkbox">
+ <property name="label" translatable="yes">Don't _warn me again</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="dialog-action_area2">
+ <property name="visible">True</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ignore_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <child>
+ <object class="GtkAlignment" id="alignment3">
+ <property name="visible">True</property>
+ <property name="xscale">0</property>
+ <property name="yscale">0</property>
+ <child>
+ <object class="GtkHBox" id="hbox4">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkImage" id="image3">
+ <property name="visible">True</property>
+ <property name="stock">gtk-no</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label57">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">No</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="change_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <child>
+ <object class="GtkAlignment" id="alignment2">
+ <property name="visible">True</property>
+ <property name="xscale">0</property>
+ <property name="yscale">0</property>
+ <child>
+ <object class="GtkHBox" id="hbox3">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="stock">gtk-ok</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label56">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Yes</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-9">ignore_button</action-widget>
+ <action-widget response="-8">change_button</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/panels/network/wireless-security/wireless-security.c b/panels/network/wireless-security/wireless-security.c
new file mode 100644
index 0000000..42093ea
--- /dev/null
+++ b/panels/network/wireless-security/wireless-security.c
@@ -0,0 +1,554 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2012 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+#include <nm-setting-connection.h>
+#include <nm-setting-wired.h>
+#include <nm-setting-wireless.h>
+#include <nm-setting-wireless-security.h>
+#include <nm-setting-8021x.h>
+
+#include "wireless-security.h"
+#include "wireless-security-resources.h"
+#include "eap-method.h"
+
+GType
+wireless_security_get_g_type (void)
+{
+ static GType type_id = 0;
+
+ if (!type_id) {
+ g_resources_register (wireless_security_get_resource ());
+
+ type_id = g_boxed_type_register_static ("WirelessSecurity",
+ (GBoxedCopyFunc) wireless_security_ref,
+ (GBoxedFreeFunc) wireless_security_unref);
+ }
+
+ return type_id;
+}
+
+GtkWidget *
+wireless_security_get_widget (WirelessSecurity *sec)
+{
+ g_return_val_if_fail (sec != NULL, NULL);
+
+ return sec->ui_widget;
+}
+
+void
+wireless_security_set_changed_notify (WirelessSecurity *sec,
+ WSChangedFunc func,
+ gpointer user_data)
+{
+ g_return_if_fail (sec != NULL);
+
+ sec->changed_notify = func;
+ sec->changed_notify_data = user_data;
+}
+
+void
+wireless_security_changed_cb (GtkWidget *ignored, gpointer user_data)
+{
+ WirelessSecurity *sec = WIRELESS_SECURITY (user_data);
+
+ if (sec->changed_notify)
+ (*(sec->changed_notify)) (sec, sec->changed_notify_data);
+}
+
+gboolean
+wireless_security_validate (WirelessSecurity *sec, const GByteArray *ssid)
+{
+ g_return_val_if_fail (sec != NULL, FALSE);
+
+ g_assert (sec->validate);
+ return (*(sec->validate)) (sec, ssid);
+}
+
+void
+wireless_security_add_to_size_group (WirelessSecurity *sec, GtkSizeGroup *group)
+{
+ g_return_if_fail (sec != NULL);
+ g_return_if_fail (group != NULL);
+
+ g_assert (sec->add_to_size_group);
+ return (*(sec->add_to_size_group)) (sec, group);
+}
+
+void
+wireless_security_fill_connection (WirelessSecurity *sec,
+ NMConnection *connection)
+{
+ g_return_if_fail (sec != NULL);
+ g_return_if_fail (connection != NULL);
+
+ g_assert (sec->fill_connection);
+ return (*(sec->fill_connection)) (sec, connection);
+}
+
+void
+wireless_security_update_secrets (WirelessSecurity *sec, NMConnection *connection)
+{
+ g_return_if_fail (sec != NULL);
+ g_return_if_fail (connection != NULL);
+
+ if (sec->update_secrets)
+ sec->update_secrets (sec, connection);
+}
+
+WirelessSecurity *
+wireless_security_ref (WirelessSecurity *sec)
+{
+ g_return_val_if_fail (sec != NULL, NULL);
+ g_return_val_if_fail (sec->refcount > 0, NULL);
+
+ sec->refcount++;
+ return sec;
+}
+
+void
+wireless_security_unref (WirelessSecurity *sec)
+{
+ g_return_if_fail (sec != NULL);
+ g_return_if_fail (sec->refcount > 0);
+
+ sec->refcount--;
+ if (sec->refcount == 0) {
+ if (sec->destroy)
+ sec->destroy (sec);
+
+ if (sec->builder)
+ g_object_unref (sec->builder);
+ if (sec->ui_widget)
+ g_object_unref (sec->ui_widget);
+ g_slice_free1 (sec->obj_size, sec);
+ }
+}
+
+WirelessSecurity *
+wireless_security_init (gsize obj_size,
+ WSValidateFunc validate,
+ WSAddToSizeGroupFunc add_to_size_group,
+ WSFillConnectionFunc fill_connection,
+ WSUpdateSecretsFunc update_secrets,
+ WSDestroyFunc destroy,
+ const char *ui_resource,
+ const char *ui_widget_name,
+ const char *default_field)
+{
+ WirelessSecurity *sec;
+ GError *error = NULL;
+
+ g_return_val_if_fail (obj_size > 0, NULL);
+ g_return_val_if_fail (ui_resource != NULL, NULL);
+ g_return_val_if_fail (ui_widget_name != NULL, NULL);
+
+ sec = g_slice_alloc0 (obj_size);
+ g_assert (sec);
+
+ sec->refcount = 1;
+ sec->obj_size = obj_size;
+
+ sec->validate = validate;
+ sec->add_to_size_group = add_to_size_group;
+ sec->fill_connection = fill_connection;
+ sec->update_secrets = update_secrets;
+ sec->destroy = destroy;
+ sec->default_field = default_field;
+
+ sec->builder = gtk_builder_new ();
+ if (!gtk_builder_add_from_resource (sec->builder, ui_resource, &error)) {
+ g_warning ("Couldn't load UI builder file %s: %s",
+ ui_resource, error->message);
+ g_error_free (error);
+ wireless_security_unref (sec);
+ return NULL;
+ }
+
+ sec->ui_widget = GTK_WIDGET (gtk_builder_get_object (sec->builder, ui_widget_name));
+ if (!sec->ui_widget) {
+ g_warning ("Couldn't load UI widget '%s' from UI file %s",
+ ui_widget_name, ui_resource);
+ wireless_security_unref (sec);
+ return NULL;
+ }
+ g_object_ref_sink (sec->ui_widget);
+
+ sec->adhoc_compatible = TRUE;
+
+ return sec;
+}
+
+GtkWidget *
+wireless_security_nag_user (WirelessSecurity *sec)
+{
+ g_return_val_if_fail (sec != NULL, NULL);
+
+ if (sec->nag_user)
+ return (*(sec->nag_user)) (sec);
+ return NULL;
+}
+
+gboolean
+wireless_security_adhoc_compatible (WirelessSecurity *sec)
+{
+ g_return_val_if_fail (sec != NULL, FALSE);
+
+ return sec->adhoc_compatible;
+}
+
+void
+wireless_security_clear_ciphers (NMConnection *connection)
+{
+ NMSettingWirelessSecurity *s_wireless_sec;
+
+ g_return_if_fail (connection != NULL);
+
+ s_wireless_sec = nm_connection_get_setting_wireless_security (connection);
+ g_assert (s_wireless_sec);
+
+ nm_setting_wireless_security_clear_protos (s_wireless_sec);
+ nm_setting_wireless_security_clear_pairwise (s_wireless_sec);
+ nm_setting_wireless_security_clear_groups (s_wireless_sec);
+}
+
+void
+ws_802_1x_add_to_size_group (WirelessSecurity *sec,
+ GtkSizeGroup *size_group,
+ const char *label_name,
+ const char *combo_name)
+{
+ GtkWidget *widget;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ EAPMethod *eap;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (sec->builder, label_name));
+ g_assert (widget);
+ gtk_size_group_add_widget (size_group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (sec->builder, combo_name));
+ g_assert (widget);
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+ gtk_tree_model_get (model, &iter, AUTH_METHOD_COLUMN, &eap, -1);
+ g_assert (eap);
+ eap_method_add_to_size_group (eap, size_group);
+ eap_method_unref (eap);
+}
+
+gboolean
+ws_802_1x_validate (WirelessSecurity *sec, const char *combo_name)
+{
+ GtkWidget *widget;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ EAPMethod *eap = NULL;
+ gboolean valid = FALSE;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (sec->builder, combo_name));
+ g_assert (widget);
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+ gtk_tree_model_get (model, &iter, AUTH_METHOD_COLUMN, &eap, -1);
+ g_assert (eap);
+ valid = eap_method_validate (eap);
+ eap_method_unref (eap);
+ return valid;
+}
+
+void
+ws_802_1x_auth_combo_changed (GtkWidget *combo,
+ WirelessSecurity *sec,
+ const char *vbox_name,
+ GtkSizeGroup *size_group)
+{
+ GtkWidget *vbox;
+ EAPMethod *eap = NULL;
+ GList *elt, *children;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkWidget *eap_widget;
+ GtkWidget *eap_default_widget = NULL;
+
+ vbox = GTK_WIDGET (gtk_builder_get_object (sec->builder, vbox_name));
+ g_assert (vbox);
+
+ /* Remove any previous wireless security widgets */
+ children = gtk_container_get_children (GTK_CONTAINER (vbox));
+ for (elt = children; elt; elt = g_list_next (elt))
+ gtk_container_remove (GTK_CONTAINER (vbox), GTK_WIDGET (elt->data));
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter);
+ gtk_tree_model_get (model, &iter, AUTH_METHOD_COLUMN, &eap, -1);
+ g_assert (eap);
+
+ eap_widget = eap_method_get_widget (eap);
+ g_assert (eap_widget);
+ gtk_widget_unparent (eap_widget);
+
+ if (size_group)
+ eap_method_add_to_size_group (eap, size_group);
+ gtk_container_add (GTK_CONTAINER (vbox), eap_widget);
+
+ /* Refocus the EAP method's default widget */
+ if (eap->default_field) {
+ eap_default_widget = GTK_WIDGET (gtk_builder_get_object (eap->builder, eap->default_field));
+ if (eap_default_widget)
+ gtk_widget_grab_focus (eap_default_widget);
+ }
+
+ eap_method_unref (eap);
+
+ wireless_security_changed_cb (combo, WIRELESS_SECURITY (sec));
+}
+
+GtkWidget *
+ws_802_1x_auth_combo_init (WirelessSecurity *sec,
+ const char *combo_name,
+ const char *combo_label,
+ GCallback auth_combo_changed_cb,
+ NMConnection *connection,
+ gboolean is_editor,
+ gboolean secrets_only)
+{
+ GtkWidget *combo, *widget;
+ GtkListStore *auth_model;
+ GtkTreeIter iter;
+ EAPMethodSimple *em_md5;
+ EAPMethodTLS *em_tls;
+ EAPMethodLEAP *em_leap;
+ EAPMethodFAST *em_fast;
+ EAPMethodTTLS *em_ttls;
+ EAPMethodPEAP *em_peap;
+ const char *default_method = NULL, *ctype = NULL;
+ int active = -1, item = 0;
+ gboolean wired = FALSE;
+
+ /* Grab the default EAP method out of the security object */
+ if (connection) {
+ NMSettingConnection *s_con;
+ NMSetting8021x *s_8021x;
+
+ s_con = nm_connection_get_setting_connection (connection);
+ if (s_con)
+ ctype = nm_setting_connection_get_connection_type (s_con);
+ if ( (g_strcmp0 (ctype, NM_SETTING_WIRED_SETTING_NAME) == 0)
+ || nm_connection_get_setting_wired (connection))
+ wired = TRUE;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ if (s_8021x && nm_setting_802_1x_get_num_eap_methods (s_8021x))
+ default_method = nm_setting_802_1x_get_eap_method (s_8021x, 0);
+ }
+
+ auth_model = gtk_list_store_new (2, G_TYPE_STRING, eap_method_get_g_type ());
+
+ if (wired) {
+ em_md5 = eap_method_simple_new (sec,
+ connection,
+ EAP_METHOD_SIMPLE_TYPE_MD5,
+ FALSE,
+ is_editor,
+ secrets_only);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ AUTH_NAME_COLUMN, _("MD5"),
+ AUTH_METHOD_COLUMN, em_md5,
+ -1);
+ eap_method_unref (EAP_METHOD (em_md5));
+ if (default_method && (active < 0) && !strcmp (default_method, "md5"))
+ active = item;
+ item++;
+ }
+
+ em_tls = eap_method_tls_new (sec, connection, FALSE, secrets_only);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ AUTH_NAME_COLUMN, _("TLS"),
+ AUTH_METHOD_COLUMN, em_tls,
+ -1);
+ eap_method_unref (EAP_METHOD (em_tls));
+ if (default_method && (active < 0) && !strcmp (default_method, "tls"))
+ active = item;
+ item++;
+
+ if (!wired) {
+ em_leap = eap_method_leap_new (sec, connection, secrets_only);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ AUTH_NAME_COLUMN, _("LEAP"),
+ AUTH_METHOD_COLUMN, em_leap,
+ -1);
+ eap_method_unref (EAP_METHOD (em_leap));
+ if (default_method && (active < 0) && !strcmp (default_method, "leap"))
+ active = item;
+ item++;
+ }
+
+ em_fast = eap_method_fast_new (sec, connection, is_editor, secrets_only);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ AUTH_NAME_COLUMN, _("FAST"),
+ AUTH_METHOD_COLUMN, em_fast,
+ -1);
+ eap_method_unref (EAP_METHOD (em_fast));
+ if (default_method && (active < 0) && !strcmp (default_method, "fast"))
+ active = item;
+ item++;
+
+ em_ttls = eap_method_ttls_new (sec, connection, is_editor, secrets_only);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ AUTH_NAME_COLUMN, _("Tunneled TLS"),
+ AUTH_METHOD_COLUMN, em_ttls,
+ -1);
+ eap_method_unref (EAP_METHOD (em_ttls));
+ if (default_method && (active < 0) && !strcmp (default_method, "ttls"))
+ active = item;
+ item++;
+
+ em_peap = eap_method_peap_new (sec, connection, is_editor, secrets_only);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ AUTH_NAME_COLUMN, _("Protected EAP (PEAP)"),
+ AUTH_METHOD_COLUMN, em_peap,
+ -1);
+ eap_method_unref (EAP_METHOD (em_peap));
+ if (default_method && (active < 0) && !strcmp (default_method, "peap"))
+ active = item;
+ item++;
+
+ combo = GTK_WIDGET (gtk_builder_get_object (sec->builder, combo_name));
+ g_assert (combo);
+
+ gtk_combo_box_set_model (GTK_COMBO_BOX (combo), GTK_TREE_MODEL (auth_model));
+ g_object_unref (G_OBJECT (auth_model));
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combo), active < 0 ? 0 : (guint32) active);
+
+ g_signal_connect (G_OBJECT (combo), "changed", auth_combo_changed_cb, sec);
+
+ if (secrets_only) {
+ gtk_widget_hide (combo);
+ widget = GTK_WIDGET (gtk_builder_get_object (sec->builder, combo_label));
+ gtk_widget_hide (widget);
+ }
+
+ return combo;
+}
+
+void
+ws_802_1x_fill_connection (WirelessSecurity *sec,
+ const char *combo_name,
+ NMConnection *connection)
+{
+ GtkWidget *widget;
+ NMSettingWireless *s_wireless;
+ NMSettingWirelessSecurity *s_wireless_sec;
+ NMSetting8021x *s_8021x;
+ EAPMethod *eap = NULL;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ s_wireless = nm_connection_get_setting_wireless (connection);
+ g_assert (s_wireless);
+
+ g_object_set (s_wireless, NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NULL);
+
+ /* Blow away the old wireless security setting by adding a clear one */
+ s_wireless_sec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+ nm_connection_add_setting (connection, (NMSetting *) s_wireless_sec);
+
+ /* Blow away the old 802.1x setting by adding a clear one */
+ s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
+ nm_connection_add_setting (connection, (NMSetting *) s_8021x);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (sec->builder, combo_name));
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+ gtk_tree_model_get (model, &iter, AUTH_METHOD_COLUMN, &eap, -1);
+ g_assert (eap);
+
+ eap_method_fill_connection (eap, connection);
+ eap_method_unref (eap);
+}
+
+void
+ws_802_1x_update_secrets (WirelessSecurity *sec,
+ const char *combo_name,
+ NMConnection *connection)
+{
+ GtkWidget *widget;
+ EAPMethod *eap = NULL;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ g_return_if_fail (sec != NULL);
+ g_return_if_fail (combo_name != NULL);
+ g_return_if_fail (connection != NULL);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (sec->builder, combo_name));
+ g_return_if_fail (widget != NULL);
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+
+ /* Let each EAP method try to update its secrets */
+ if (gtk_tree_model_get_iter_first (model, &iter)) {
+ do {
+ gtk_tree_model_get (model, &iter, AUTH_METHOD_COLUMN, &eap, -1);
+ if (eap) {
+ eap_method_update_secrets (eap, connection);
+ eap_method_unref (eap);
+ }
+ } while (gtk_tree_model_iter_next (model, &iter));
+ }
+}
+
+GtkWidget *
+ws_802_1x_nag_user (WirelessSecurity *sec,
+ const char *combo_name)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ EAPMethod *eap = NULL;
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (sec->builder, combo_name));
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+ gtk_tree_model_get (model, &iter, AUTH_METHOD_COLUMN, &eap, -1);
+ g_return_val_if_fail (eap != NULL, NULL);
+
+ widget = eap_method_nag_user (eap);
+ eap_method_unref (eap);
+ return widget;
+}
+
diff --git a/panels/network/wireless-security/wireless-security.gresource.xml b/panels/network/wireless-security/wireless-security.gresource.xml
new file mode 100644
index 0000000..76329de
--- /dev/null
+++ b/panels/network/wireless-security/wireless-security.gresource.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/control-center/network">
+ <file preprocess="xml-stripblanks">eap-method-leap.ui</file>
+ <file preprocess="xml-stripblanks">eap-method-fast.ui</file>
+ <file preprocess="xml-stripblanks">eap-method-peap.ui</file>
+ <file preprocess="xml-stripblanks">eap-method-simple.ui</file>
+ <file preprocess="xml-stripblanks">eap-method-tls.ui</file>
+ <file preprocess="xml-stripblanks">eap-method-ttls.ui</file>
+ <file preprocess="xml-stripblanks">nag-user-dialog.ui</file>
+ <file preprocess="xml-stripblanks">ws-dynamic-wep.ui</file>
+ <file preprocess="xml-stripblanks">ws-leap.ui</file>
+ <file preprocess="xml-stripblanks">ws-wep-key.ui</file>
+ <file preprocess="xml-stripblanks">ws-wpa-eap.ui</file>
+ <file preprocess="xml-stripblanks">ws-wpa-psk.ui</file>
+ </gresource>
+</gresources>
diff --git a/panels/network/wireless-security/wireless-security.h b/panels/network/wireless-security/wireless-security.h
new file mode 100644
index 0000000..23a725b
--- /dev/null
+++ b/panels/network/wireless-security/wireless-security.h
@@ -0,0 +1,147 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#ifndef WIRELESS_SECURITY_H
+#define WIRELESS_SECURITY_H
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+#include <nm-connection.h>
+
+typedef struct _WirelessSecurity WirelessSecurity;
+
+typedef void (*WSChangedFunc) (WirelessSecurity *sec, gpointer user_data);
+
+typedef void (*WSAddToSizeGroupFunc) (WirelessSecurity *sec, GtkSizeGroup *group);
+typedef void (*WSFillConnectionFunc) (WirelessSecurity *sec, NMConnection *connection);
+typedef void (*WSUpdateSecretsFunc) (WirelessSecurity *sec, NMConnection *connection);
+typedef void (*WSDestroyFunc) (WirelessSecurity *sec);
+typedef gboolean (*WSValidateFunc) (WirelessSecurity *sec, const GByteArray *ssid);
+typedef GtkWidget * (*WSNagUserFunc) (WirelessSecurity *sec);
+
+struct _WirelessSecurity {
+ guint32 refcount;
+ gsize obj_size;
+ GtkBuilder *builder;
+ GtkWidget *ui_widget;
+ WSChangedFunc changed_notify;
+ gpointer changed_notify_data;
+ const char *default_field;
+ gboolean adhoc_compatible;
+
+ WSAddToSizeGroupFunc add_to_size_group;
+ WSFillConnectionFunc fill_connection;
+ WSUpdateSecretsFunc update_secrets;
+ WSValidateFunc validate;
+ WSNagUserFunc nag_user;
+ WSDestroyFunc destroy;
+};
+
+#define WIRELESS_SECURITY(x) ((WirelessSecurity *) x)
+
+
+GtkWidget *wireless_security_get_widget (WirelessSecurity *sec);
+
+void wireless_security_set_changed_notify (WirelessSecurity *sec,
+ WSChangedFunc func,
+ gpointer user_data);
+
+gboolean wireless_security_validate (WirelessSecurity *sec, const GByteArray *ssid);
+
+void wireless_security_add_to_size_group (WirelessSecurity *sec,
+ GtkSizeGroup *group);
+
+void wireless_security_fill_connection (WirelessSecurity *sec,
+ NMConnection *connection);
+
+void wireless_security_update_secrets (WirelessSecurity *sec,
+ NMConnection *connection);
+
+GtkWidget * wireless_security_nag_user (WirelessSecurity *sec);
+
+gboolean wireless_security_adhoc_compatible (WirelessSecurity *sec);
+
+WirelessSecurity *wireless_security_ref (WirelessSecurity *sec);
+
+void wireless_security_unref (WirelessSecurity *sec);
+
+GType wireless_security_get_g_type (void);
+
+/* Below for internal use only */
+
+#include "ws-wep-key.h"
+#include "ws-wpa-psk.h"
+#include "ws-leap.h"
+#include "ws-wpa-eap.h"
+#include "ws-dynamic-wep.h"
+
+WirelessSecurity *wireless_security_init (gsize obj_size,
+ WSValidateFunc validate,
+ WSAddToSizeGroupFunc add_to_size_group,
+ WSFillConnectionFunc fill_connection,
+ WSUpdateSecretsFunc update_secrets,
+ WSDestroyFunc destroy,
+ const char *ui_resource,
+ const char *ui_widget_name,
+ const char *default_field);
+
+void wireless_security_changed_cb (GtkWidget *entry, gpointer user_data);
+
+void wireless_security_clear_ciphers (NMConnection *connection);
+
+#define AUTH_NAME_COLUMN 0
+#define AUTH_METHOD_COLUMN 1
+
+GtkWidget *ws_802_1x_auth_combo_init (WirelessSecurity *sec,
+ const char *combo_name,
+ const char *combo_label,
+ GCallback auth_combo_changed_cb,
+ NMConnection *connection,
+ gboolean is_editor,
+ gboolean secrets_only);
+
+void ws_802_1x_auth_combo_changed (GtkWidget *combo,
+ WirelessSecurity *sec,
+ const char *vbox_name,
+ GtkSizeGroup *size_group);
+
+gboolean ws_802_1x_validate (WirelessSecurity *sec, const char *combo_name);
+
+void ws_802_1x_add_to_size_group (WirelessSecurity *sec,
+ GtkSizeGroup *size_group,
+ const char *label_name,
+ const char *combo_name);
+
+void ws_802_1x_fill_connection (WirelessSecurity *sec,
+ const char *combo_name,
+ NMConnection *connection);
+
+void ws_802_1x_update_secrets (WirelessSecurity *sec,
+ const char *combo_name,
+ NMConnection *connection);
+
+GtkWidget * ws_802_1x_nag_user (WirelessSecurity *sec,
+ const char *combo_name);
+
+#endif /* WIRELESS_SECURITY_H */
+
diff --git a/panels/network/wireless-security/ws-dynamic-wep.c b/panels/network/wireless-security/ws-dynamic-wep.c
new file mode 100644
index 0000000..481196a
--- /dev/null
+++ b/panels/network/wireless-security/ws-dynamic-wep.c
@@ -0,0 +1,143 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#include <glib/gi18n.h>
+#include <ctype.h>
+#include <string.h>
+#include <nm-setting-wireless.h>
+
+#include "wireless-security.h"
+#include "eap-method.h"
+
+struct _WirelessSecurityDynamicWEP {
+ WirelessSecurity parent;
+
+ GtkSizeGroup *size_group;
+};
+
+static void
+destroy (WirelessSecurity *parent)
+{
+ WirelessSecurityDynamicWEP *sec = (WirelessSecurityDynamicWEP *) parent;
+
+ if (sec->size_group)
+ g_object_unref (sec->size_group);
+}
+
+static gboolean
+validate (WirelessSecurity *parent, const GByteArray *ssid)
+{
+ return ws_802_1x_validate (parent, "dynamic_wep_auth_combo");
+}
+
+static void
+add_to_size_group (WirelessSecurity *parent, GtkSizeGroup *group)
+{
+ WirelessSecurityDynamicWEP *sec = (WirelessSecurityDynamicWEP *) parent;
+
+ if (sec->size_group)
+ g_object_unref (sec->size_group);
+ sec->size_group = g_object_ref (group);
+
+ ws_802_1x_add_to_size_group (parent,
+ sec->size_group,
+ "dynamic_wep_auth_label",
+ "dynamic_wep_auth_combo");
+}
+
+static void
+fill_connection (WirelessSecurity *parent, NMConnection *connection)
+{
+ NMSettingWirelessSecurity *s_wireless_sec;
+
+ ws_802_1x_fill_connection (parent, "dynamic_wep_auth_combo", connection);
+
+ s_wireless_sec = nm_connection_get_setting_wireless_security (connection);
+ g_assert (s_wireless_sec);
+
+ g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", NULL);
+
+ nm_setting_wireless_security_add_pairwise (s_wireless_sec, "wep40");
+ nm_setting_wireless_security_add_pairwise (s_wireless_sec, "wep104");
+ nm_setting_wireless_security_add_group (s_wireless_sec, "wep40");
+ nm_setting_wireless_security_add_group (s_wireless_sec, "wep104");
+}
+
+static void
+auth_combo_changed_cb (GtkWidget *combo, gpointer user_data)
+{
+ WirelessSecurity *parent = WIRELESS_SECURITY (user_data);
+ WirelessSecurityDynamicWEP *sec = (WirelessSecurityDynamicWEP *) parent;
+
+ ws_802_1x_auth_combo_changed (combo,
+ parent,
+ "dynamic_wep_method_vbox",
+ sec->size_group);
+}
+
+static GtkWidget *
+nag_user (WirelessSecurity *parent)
+{
+ return ws_802_1x_nag_user (parent, "dynamic_wep_auth_combo");
+}
+
+static void
+update_secrets (WirelessSecurity *parent, NMConnection *connection)
+{
+ ws_802_1x_update_secrets (parent, "dynamic_wep_auth_combo", connection);
+}
+
+WirelessSecurityDynamicWEP *
+ws_dynamic_wep_new (NMConnection *connection,
+ gboolean is_editor,
+ gboolean secrets_only)
+{
+ WirelessSecurity *parent;
+ GtkWidget *widget;
+
+ parent = wireless_security_init (sizeof (WirelessSecurityDynamicWEP),
+ validate,
+ add_to_size_group,
+ fill_connection,
+ update_secrets,
+ destroy,
+ "/org/gnome/control-center/network/ws-dynamic-wep.ui",
+ "dynamic_wep_notebook",
+ NULL);
+ if (!parent)
+ return NULL;
+
+ parent->nag_user = nag_user;
+ parent->adhoc_compatible = FALSE;
+
+ widget = ws_802_1x_auth_combo_init (parent,
+ "dynamic_wep_auth_combo",
+ "dynamic_wep_auth_label",
+ (GCallback) auth_combo_changed_cb,
+ connection,
+ is_editor,
+ secrets_only);
+ auth_combo_changed_cb (widget, (gpointer) parent);
+
+ return (WirelessSecurityDynamicWEP *) parent;
+}
+
diff --git a/panels/network/wireless-security/ws-dynamic-wep.h b/panels/network/wireless-security/ws-dynamic-wep.h
new file mode 100644
index 0000000..54979f4
--- /dev/null
+++ b/panels/network/wireless-security/ws-dynamic-wep.h
@@ -0,0 +1,35 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#ifndef WS_DYNAMIC_WEP_H
+#define WS_DYNAMIC_WEP_H
+
+#include <nm-connection.h>
+
+typedef struct _WirelessSecurityDynamicWEP WirelessSecurityDynamicWEP;
+
+WirelessSecurityDynamicWEP *ws_dynamic_wep_new (NMConnection *connection,
+ gboolean is_editor,
+ gboolean secrets_only);
+
+#endif /* WS_DYNAMIC_WEP_H */
+
diff --git a/panels/network/wireless-security/ws-dynamic-wep.ui b/panels/network/wireless-security/ws-dynamic-wep.ui
new file mode 100644
index 0000000..d6bc12b
--- /dev/null
+++ b/panels/network/wireless-security/ws-dynamic-wep.ui
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkListStore" id="model7">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes"> </col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkNotebook" id="dynamic_wep_notebook">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="show_tabs">False</property>
+ <property name="show_border">False</property>
+ <child>
+ <object class="GtkTable" id="table12">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="n_rows">3</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <object class="GtkLabel" id="dynamic_wep_auth_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Au_thentication</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">dynamic_wep_auth_combo</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="dynamic_wep_auth_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">model7</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer7"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="dynamic_wep_method_vbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label55">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/panels/network/wireless-security/ws-leap.c b/panels/network/wireless-security/ws-leap.c
new file mode 100644
index 0000000..a2ddb72
--- /dev/null
+++ b/panels/network/wireless-security/ws-leap.c
@@ -0,0 +1,192 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#include <string.h>
+#include <nm-setting-wireless.h>
+
+#include "wireless-security.h"
+#include "helpers.h"
+
+struct _WirelessSecurityLEAP {
+ WirelessSecurity parent;
+ gboolean new_connection;
+};
+
+static void
+show_toggled_cb (GtkCheckButton *button, WirelessSecurity *sec)
+{
+ GtkWidget *widget;
+ gboolean visible;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (sec->builder, "leap_password_entry"));
+ g_assert (widget);
+
+ visible = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+ gtk_entry_set_visibility (GTK_ENTRY (widget), visible);
+}
+
+static gboolean
+validate (WirelessSecurity *parent, const GByteArray *ssid)
+{
+ GtkWidget *entry;
+ const char *text;
+
+ entry = GTK_WIDGET (gtk_builder_get_object (parent->builder, "leap_username_entry"));
+ g_assert (entry);
+ text = gtk_entry_get_text (GTK_ENTRY (entry));
+ if (!text || !strlen (text))
+ return FALSE;
+
+ entry = GTK_WIDGET (gtk_builder_get_object (parent->builder, "leap_password_entry"));
+ g_assert (entry);
+ text = gtk_entry_get_text (GTK_ENTRY (entry));
+ if (!text || !strlen (text))
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+add_to_size_group (WirelessSecurity *parent, GtkSizeGroup *group)
+{
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "leap_username_label"));
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "leap_password_label"));
+ gtk_size_group_add_widget (group, widget);
+}
+
+static void
+fill_connection (WirelessSecurity *parent, NMConnection *connection)
+{
+ WirelessSecurityLEAP *sec = (WirelessSecurityLEAP *) parent;
+ NMSettingWireless *s_wireless;
+ NMSettingWirelessSecurity *s_wireless_sec;
+ GtkWidget *widget;
+ const char *leap_password = NULL, *leap_username = NULL;
+
+ s_wireless = nm_connection_get_setting_wireless (connection);
+ g_assert (s_wireless);
+
+ g_object_set (s_wireless, NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NULL);
+
+ /* Blow away the old security setting by adding a clear one */
+ s_wireless_sec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+ nm_connection_add_setting (connection, (NMSetting *) s_wireless_sec);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "leap_username_entry"));
+ leap_username = gtk_entry_get_text (GTK_ENTRY (widget));
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "leap_password_entry"));
+ leap_password = gtk_entry_get_text (GTK_ENTRY (widget));
+
+ g_object_set (s_wireless_sec,
+ NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x",
+ NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "leap",
+ NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, leap_username,
+ NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD, leap_password,
+ NULL);
+
+ /* Default to agent-owned secrets for new connections */
+ if (sec->new_connection) {
+ g_object_set (s_wireless_sec,
+ NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS, NM_SETTING_SECRET_FLAG_AGENT_OWNED,
+ NULL);
+ }
+}
+
+static void
+update_secrets (WirelessSecurity *parent, NMConnection *connection)
+{
+ helper_fill_secret_entry (connection,
+ parent->builder,
+ "leap_password_entry",
+ NM_TYPE_SETTING_WIRELESS_SECURITY,
+ (HelperSecretFunc) nm_setting_wireless_security_get_leap_password);
+}
+
+WirelessSecurityLEAP *
+ws_leap_new (NMConnection *connection, gboolean secrets_only)
+{
+ WirelessSecurity *parent;
+ WirelessSecurityLEAP *sec;
+ GtkWidget *widget;
+ NMSettingWirelessSecurity *wsec = NULL;
+
+ parent = wireless_security_init (sizeof (WirelessSecurityLEAP),
+ validate,
+ add_to_size_group,
+ fill_connection,
+ update_secrets,
+ NULL,
+ "/org/gnome/control-center/network/ws-leap.ui",
+ "leap_notebook",
+ "leap_username_entry");
+ if (!parent)
+ return NULL;
+
+ if (connection) {
+ wsec = nm_connection_get_setting_wireless_security (connection);
+ if (wsec) {
+ const char *auth_alg;
+
+ /* Ignore if wireless security doesn't specify LEAP */
+ auth_alg = nm_setting_wireless_security_get_auth_alg (wsec);
+ if (!auth_alg || strcmp (auth_alg, "leap"))
+ wsec = NULL;
+ }
+ }
+
+ parent->adhoc_compatible = FALSE;
+ sec = (WirelessSecurityLEAP *) parent;
+ sec->new_connection = secrets_only ? FALSE : TRUE;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "leap_password_entry"));
+ g_assert (widget);
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) wireless_security_changed_cb,
+ sec);
+ if (wsec)
+ update_secrets (WIRELESS_SECURITY (sec), connection);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "leap_username_entry"));
+ g_assert (widget);
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) wireless_security_changed_cb,
+ sec);
+ if (wsec)
+ gtk_entry_set_text (GTK_ENTRY (widget), nm_setting_wireless_security_get_leap_username (wsec));
+
+ if (secrets_only)
+ gtk_widget_hide (widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "show_checkbutton_leap"));
+ g_assert (widget);
+ g_signal_connect (G_OBJECT (widget), "toggled",
+ (GCallback) show_toggled_cb,
+ sec);
+
+ return sec;
+}
+
diff --git a/panels/network/wireless-security/ws-leap.h b/panels/network/wireless-security/ws-leap.h
new file mode 100644
index 0000000..6f1d705
--- /dev/null
+++ b/panels/network/wireless-security/ws-leap.h
@@ -0,0 +1,33 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#ifndef WS_LEAP_H
+#define WS_LEAP_H
+
+#include <nm-connection.h>
+
+typedef struct _WirelessSecurityLEAP WirelessSecurityLEAP;
+
+WirelessSecurityLEAP * ws_leap_new (NMConnection *connection, gboolean secrets_only);
+
+#endif /* WS_LEAP_H */
+
diff --git a/panels/network/wireless-security/ws-leap.ui b/panels/network/wireless-security/ws-leap.ui
new file mode 100644
index 0000000..76bca3a
--- /dev/null
+++ b/panels/network/wireless-security/ws-leap.ui
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkNotebook" id="leap_notebook">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="show_tabs">False</property>
+ <property name="show_border">False</property>
+ <child>
+ <object class="GtkTable" id="table5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="n_rows">3</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <object class="GtkLabel" id="leap_username_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Username</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">leap_username_entry</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="leap_password_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">leap_password_entry</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="leap_password_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="visibility">False</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="show_checkbutton_leap">
+ <property name="label" translatable="yes">Sho_w password</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="leap_username_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="GtkLabel1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/panels/network/wireless-security/ws-wep-key.c b/panels/network/wireless-security/ws-wep-key.c
new file mode 100644
index 0000000..6de18dc
--- /dev/null
+++ b/panels/network/wireless-security/ws-wep-key.c
@@ -0,0 +1,349 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#include <ctype.h>
+#include <string.h>
+
+#include <nm-setting-wireless.h>
+#include <nm-setting-wireless-security.h>
+
+#include "wireless-security.h"
+
+struct _WirelessSecurityWEPKey {
+ WirelessSecurity parent;
+
+ NMWepKeyType type;
+ char keys[4][65];
+ guint8 cur_index;
+};
+
+static void
+show_toggled_cb (GtkCheckButton *button, WirelessSecurity *sec)
+{
+ GtkWidget *widget;
+ gboolean visible;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (sec->builder, "wep_key_entry"));
+ g_assert (widget);
+
+ visible = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+ gtk_entry_set_visibility (GTK_ENTRY (widget), visible);
+}
+
+static void
+key_index_combo_changed_cb (GtkWidget *combo, WirelessSecurity *parent)
+{
+ WirelessSecurityWEPKey *sec = (WirelessSecurityWEPKey *) parent;
+ GtkWidget *entry;
+ const char *key;
+ int key_index;
+
+ /* Save WEP key for old key index */
+ entry = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wep_key_entry"));
+ key = gtk_entry_get_text (GTK_ENTRY (entry));
+ if (key)
+ strcpy (sec->keys[sec->cur_index], key);
+ else
+ memset (sec->keys[sec->cur_index], 0, sizeof (sec->keys[sec->cur_index]));
+
+ key_index = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
+ g_return_if_fail (key_index <= 3);
+ g_return_if_fail (key_index >= 0);
+
+ /* Populate entry with key from new index */
+ gtk_entry_set_text (GTK_ENTRY (entry), sec->keys[key_index]);
+ sec->cur_index = key_index;
+
+ wireless_security_changed_cb (combo, parent);
+}
+
+static void
+destroy (WirelessSecurity *parent)
+{
+ WirelessSecurityWEPKey *sec = (WirelessSecurityWEPKey *) parent;
+ int i;
+
+ for (i = 0; i < 4; i++)
+ memset (sec->keys[i], 0, sizeof (sec->keys[i]));
+}
+
+static gboolean
+validate (WirelessSecurity *parent, const GByteArray *ssid)
+{
+ WirelessSecurityWEPKey *sec = (WirelessSecurityWEPKey *) parent;
+ GtkWidget *entry;
+ const char *key;
+ int i;
+
+ entry = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wep_key_entry"));
+ g_assert (entry);
+
+ key = gtk_entry_get_text (GTK_ENTRY (entry));
+ if (!key)
+ return FALSE;
+
+ if (sec->type == NM_WEP_KEY_TYPE_KEY) {
+ if ((strlen (key) == 10) || (strlen (key) == 26)) {
+ for (i = 0; i < strlen (key); i++) {
+ if (!isxdigit (key[i]))
+ return FALSE;
+ }
+ } else if ((strlen (key) == 5) || (strlen (key) == 13)) {
+ for (i = 0; i < strlen (key); i++) {
+ if (!isascii (key[i]))
+ return FALSE;
+ }
+ } else {
+ return FALSE;
+ }
+ } else if (sec->type == NM_WEP_KEY_TYPE_PASSPHRASE) {
+ if (!strlen (key) || (strlen (key) > 64))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+add_to_size_group (WirelessSecurity *parent, GtkSizeGroup *group)
+{
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "auth_method_label"));
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wep_key_label"));
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "key_index_label"));
+ gtk_size_group_add_widget (group, widget);
+}
+
+static void
+fill_connection (WirelessSecurity *parent, NMConnection *connection)
+{
+ WirelessSecurityWEPKey *sec = (WirelessSecurityWEPKey *) parent;
+ NMSettingWireless *s_wireless;
+ NMSettingWirelessSecurity *s_wsec;
+ GtkWidget *widget;
+ gint auth_alg;
+ const char *key;
+ int i;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "auth_method_combo"));
+ auth_alg = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wep_key_entry"));
+ key = gtk_entry_get_text (GTK_ENTRY (widget));
+ strcpy (sec->keys[sec->cur_index], key);
+
+ s_wireless = nm_connection_get_setting_wireless (connection);
+ g_assert (s_wireless);
+
+ g_object_set (s_wireless, NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NULL);
+
+ /* Blow away the old security setting by adding a clear one */
+ s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+ nm_connection_add_setting (connection, (NMSetting *) s_wsec);
+
+ g_object_set (s_wsec,
+ NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none",
+ NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX, sec->cur_index,
+ NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, (auth_alg == 1) ? "shared" : "open",
+ NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, sec->type,
+ NULL);
+
+ for (i = 0; i < 4; i++) {
+ if (strlen (sec->keys[i]))
+ nm_setting_wireless_security_set_wep_key (s_wsec, i, sec->keys[i]);
+ }
+}
+
+static void
+wep_entry_filter_cb (GtkEntry * entry,
+ const gchar *text,
+ gint length,
+ gint * position,
+ gpointer data)
+{
+ WirelessSecurityWEPKey *sec = (WirelessSecurityWEPKey *) data;
+ GtkEditable *editable = GTK_EDITABLE (entry);
+ int i, count = 0;
+ gchar *result;
+
+ result = g_malloc0 (length + 1);
+
+ if (sec->type == NM_WEP_KEY_TYPE_KEY) {
+ for (i = 0; i < length; i++) {
+ if (isxdigit(text[i]) || isascii(text[i]))
+ result[count++] = text[i];
+ }
+ } else if (sec->type == NM_WEP_KEY_TYPE_PASSPHRASE) {
+ for (i = 0; i < length; i++)
+ result[count++] = text[i];
+ }
+
+ if (count > 0) {
+ g_signal_handlers_block_by_func (G_OBJECT (editable),
+ G_CALLBACK (wep_entry_filter_cb),
+ data);
+ gtk_editable_insert_text (editable, result, count, position);
+ g_signal_handlers_unblock_by_func (G_OBJECT (editable),
+ G_CALLBACK (wep_entry_filter_cb),
+ data);
+ }
+
+ g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
+ g_free (result);
+}
+
+static void
+update_secrets (WirelessSecurity *parent, NMConnection *connection)
+{
+ WirelessSecurityWEPKey *sec = (WirelessSecurityWEPKey *) parent;
+ NMSettingWirelessSecurity *s_wsec;
+ GtkWidget *widget;
+ const char *tmp;
+ int i;
+
+ s_wsec = nm_connection_get_setting_wireless_security (connection);
+ for (i = 0; s_wsec && i < 4; i++) {
+ tmp = nm_setting_wireless_security_get_wep_key (s_wsec, i);
+ if (tmp)
+ strcpy (sec->keys[i], tmp);
+ }
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wep_key_entry"));
+ if (strlen (sec->keys[sec->cur_index]))
+ gtk_entry_set_text (GTK_ENTRY (widget), sec->keys[sec->cur_index]);
+}
+
+WirelessSecurityWEPKey *
+ws_wep_key_new (NMConnection *connection,
+ NMWepKeyType type,
+ gboolean adhoc_create,
+ gboolean secrets_only)
+{
+ WirelessSecurity *parent;
+ WirelessSecurityWEPKey *sec;
+ GtkWidget *widget;
+ NMSettingWirelessSecurity *s_wsec = NULL;
+ guint8 default_key_idx = 0;
+ gboolean is_adhoc = adhoc_create;
+ gboolean is_shared_key = FALSE;
+
+ parent = wireless_security_init (sizeof (WirelessSecurityWEPKey),
+ validate,
+ add_to_size_group,
+ fill_connection,
+ update_secrets,
+ destroy,
+ "/org/gnome/control-center/network/ws-wep-key.ui",
+ "wep_key_notebook",
+ "wep_key_entry");
+ if (!parent)
+ return NULL;
+
+ sec = (WirelessSecurityWEPKey *) parent;
+ sec->type = type;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wep_key_entry"));
+ g_assert (widget);
+ gtk_entry_set_width_chars (GTK_ENTRY (widget), 28);
+
+ if (connection) {
+ NMSettingWireless *s_wireless;
+ const char *mode, *auth_alg;
+
+ s_wireless = nm_connection_get_setting_wireless (connection);
+ mode = s_wireless ? nm_setting_wireless_get_mode (s_wireless) : NULL;
+ if (mode && !strcmp (mode, "adhoc"))
+ is_adhoc = TRUE;
+
+ s_wsec = nm_connection_get_setting_wireless_security (connection);
+ if (s_wsec) {
+ auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec);
+ if (auth_alg && !strcmp (auth_alg, "shared"))
+ is_shared_key = TRUE;
+ }
+ }
+
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) wireless_security_changed_cb,
+ sec);
+ g_signal_connect (G_OBJECT (widget), "insert-text",
+ (GCallback) wep_entry_filter_cb,
+ sec);
+ if (sec->type == NM_WEP_KEY_TYPE_KEY)
+ gtk_entry_set_max_length (GTK_ENTRY (widget), 26);
+ else if (sec->type == NM_WEP_KEY_TYPE_PASSPHRASE)
+ gtk_entry_set_max_length (GTK_ENTRY (widget), 64);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "key_index_combo"));
+ if (connection && s_wsec)
+ default_key_idx = nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec);
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), default_key_idx);
+ sec->cur_index = default_key_idx;
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) key_index_combo_changed_cb,
+ sec);
+
+ /* Key index is useless with adhoc networks */
+ if (is_adhoc || secrets_only) {
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "key_index_label"));
+ gtk_widget_hide (widget);
+ }
+
+ /* Fill the key entry with the key for that index */
+ if (connection)
+ update_secrets (WIRELESS_SECURITY (sec), connection);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "show_checkbutton_wep"));
+ g_assert (widget);
+ g_signal_connect (G_OBJECT (widget), "toggled",
+ (GCallback) show_toggled_cb,
+ sec);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "auth_method_combo"));
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), is_shared_key ? 1 : 0);
+
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) wireless_security_changed_cb,
+ sec);
+
+ /* Don't show auth method for adhoc (which always uses open-system) or
+ * when in "simple" mode.
+ */
+ if (is_adhoc || secrets_only) {
+ /* Ad-Hoc connections can't use Shared Key auth */
+ if (is_adhoc)
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "auth_method_label"));
+ gtk_widget_hide (widget);
+ }
+
+ return sec;
+}
+
diff --git a/panels/network/wireless-security/ws-wep-key.h b/panels/network/wireless-security/ws-wep-key.h
new file mode 100644
index 0000000..fdd70da
--- /dev/null
+++ b/panels/network/wireless-security/ws-wep-key.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#ifndef WS_WEP_KEY_H
+#define WS_WEP_KEY_H
+
+#include <nm-setting-wireless-security.h>
+
+typedef struct _WirelessSecurityWEPKey WirelessSecurityWEPKey;
+
+WirelessSecurityWEPKey *ws_wep_key_new (NMConnection *connection,
+ NMWepKeyType type,
+ gboolean adhoc_create,
+ gboolean secrets_only);
+
+#endif /* WS_WEP_KEY_H */
+
diff --git a/panels/network/wireless-security/ws-wep-key.ui b/panels/network/wireless-security/ws-wep-key.ui
new file mode 100644
index 0000000..b50aa62
--- /dev/null
+++ b/panels/network/wireless-security/ws-wep-key.ui
@@ -0,0 +1,196 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkListStore" id="model4">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">1 (Default)</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">2</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">3</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">4</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="model3">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">Open System</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Shared Key</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkNotebook" id="wep_key_notebook">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="show_tabs">False</property>
+ <property name="show_border">False</property>
+ <child>
+ <object class="GtkTable" id="table6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="n_rows">4</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="wep_key_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Key</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">wep_key_entry</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="wep_key_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="visibility">False</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label31">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="show_checkbutton_wep">
+ <property name="label" translatable="yes">Sho_w key</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="auth_method_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Au_thentication</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">auth_method_combo</property>
+ </object>
+ <packing>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="auth_method_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">model3</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer3"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="key_index_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">WEP inde_x</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">key_index_combo</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="key_index_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">model4</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer4"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label23">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/panels/network/wireless-security/ws-wpa-eap.c b/panels/network/wireless-security/ws-wpa-eap.c
new file mode 100644
index 0000000..313c483
--- /dev/null
+++ b/panels/network/wireless-security/ws-wpa-eap.c
@@ -0,0 +1,139 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#include <glib/gi18n.h>
+#include <ctype.h>
+#include <string.h>
+#include <nm-setting-wireless.h>
+
+#include "wireless-security.h"
+#include "eap-method.h"
+
+struct _WirelessSecurityWPAEAP {
+ WirelessSecurity parent;
+
+ GtkSizeGroup *size_group;
+};
+
+
+static void
+destroy (WirelessSecurity *parent)
+{
+ WirelessSecurityWPAEAP *sec = (WirelessSecurityWPAEAP *) parent;
+
+ if (sec->size_group)
+ g_object_unref (sec->size_group);
+}
+
+static gboolean
+validate (WirelessSecurity *parent, const GByteArray *ssid)
+{
+ return ws_802_1x_validate (parent, "wpa_eap_auth_combo");
+}
+
+static void
+add_to_size_group (WirelessSecurity *parent, GtkSizeGroup *group)
+{
+ WirelessSecurityWPAEAP *sec = (WirelessSecurityWPAEAP *) parent;
+
+ if (sec->size_group)
+ g_object_unref (sec->size_group);
+ sec->size_group = g_object_ref (group);
+
+ ws_802_1x_add_to_size_group (parent,
+ sec->size_group,
+ "wpa_eap_auth_label",
+ "wpa_eap_auth_combo");
+}
+
+static void
+fill_connection (WirelessSecurity *parent, NMConnection *connection)
+{
+ NMSettingWirelessSecurity *s_wireless_sec;
+
+ ws_802_1x_fill_connection (parent, "wpa_eap_auth_combo", connection);
+
+ s_wireless_sec = nm_connection_get_setting_wireless_security (connection);
+ g_assert (s_wireless_sec);
+
+ g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap", NULL);
+}
+
+static void
+auth_combo_changed_cb (GtkWidget *combo, gpointer user_data)
+{
+ WirelessSecurity *parent = WIRELESS_SECURITY (user_data);
+ WirelessSecurityWPAEAP *sec = (WirelessSecurityWPAEAP *) parent;
+
+ ws_802_1x_auth_combo_changed (combo,
+ parent,
+ "wpa_eap_method_vbox",
+ sec->size_group);
+}
+
+static GtkWidget *
+nag_user (WirelessSecurity *parent)
+{
+ return ws_802_1x_nag_user (parent, "wpa_eap_auth_combo");
+}
+
+static void
+update_secrets (WirelessSecurity *parent, NMConnection *connection)
+{
+ ws_802_1x_update_secrets (parent, "wpa_eap_auth_combo", connection);
+}
+
+WirelessSecurityWPAEAP *
+ws_wpa_eap_new (NMConnection *connection,
+ gboolean is_editor,
+ gboolean secrets_only)
+{
+ WirelessSecurity *parent;
+ GtkWidget *widget;
+
+ parent = wireless_security_init (sizeof (WirelessSecurityWPAEAP),
+ validate,
+ add_to_size_group,
+ fill_connection,
+ update_secrets,
+ destroy,
+ "/org/gnome/control-center/network/ws-wpa-eap.ui",
+ "wpa_eap_notebook",
+ NULL);
+ if (!parent)
+ return NULL;
+
+ parent->nag_user = nag_user;
+ parent->adhoc_compatible = FALSE;
+
+ widget = ws_802_1x_auth_combo_init (parent,
+ "wpa_eap_auth_combo",
+ "wpa_eap_auth_label",
+ (GCallback) auth_combo_changed_cb,
+ connection,
+ is_editor,
+ secrets_only);
+ auth_combo_changed_cb (widget, parent);
+
+ return (WirelessSecurityWPAEAP *) parent;
+}
+
diff --git a/panels/network/wireless-security/ws-wpa-eap.h b/panels/network/wireless-security/ws-wpa-eap.h
new file mode 100644
index 0000000..5c8faea
--- /dev/null
+++ b/panels/network/wireless-security/ws-wpa-eap.h
@@ -0,0 +1,35 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#ifndef WS_WPA_EAP_H
+#define WS_WPA_EAP_H
+
+#include <nm-connection.h>
+
+typedef struct _WirelessSecurityWPAEAP WirelessSecurityWPAEAP;
+
+WirelessSecurityWPAEAP * ws_wpa_eap_new (NMConnection *connection,
+ gboolean is_editor,
+ gboolean secrets_only);
+
+#endif /* WS_WPA_EAP_H */
+
diff --git a/panels/network/wireless-security/ws-wpa-eap.ui b/panels/network/wireless-security/ws-wpa-eap.ui
new file mode 100644
index 0000000..5d71936
--- /dev/null
+++ b/panels/network/wireless-security/ws-wpa-eap.ui
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkListStore" id="model5">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes"> </col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkNotebook" id="wpa_eap_notebook">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="show_tabs">False</property>
+ <property name="show_border">False</property>
+ <child>
+ <object class="GtkTable" id="wpa_eap_table">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="n_rows">2</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="wpa_eap_auth_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Au_thentication</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">wpa_eap_auth_combo</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="wpa_eap_auth_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">model5</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer5"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="wpa_eap_method_vbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="GtkLabel3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/panels/network/wireless-security/ws-wpa-psk.c b/panels/network/wireless-security/ws-wpa-psk.c
new file mode 100644
index 0000000..2075ce4
--- /dev/null
+++ b/panels/network/wireless-security/ws-wpa-psk.c
@@ -0,0 +1,200 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#include <ctype.h>
+#include <string.h>
+#include <nm-setting-wireless.h>
+
+#include "wireless-security.h"
+#include "helpers.h"
+
+#define WPA_PMK_LEN 32
+
+struct _WirelessSecurityWPAPSK {
+ WirelessSecurity parent;
+};
+
+static void
+show_toggled_cb (GtkCheckButton *button, WirelessSecurity *sec)
+{
+ GtkWidget *widget;
+ gboolean visible;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (sec->builder, "wpa_psk_entry"));
+ g_assert (widget);
+
+ visible = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+ gtk_entry_set_visibility (GTK_ENTRY (widget), visible);
+}
+
+static gboolean
+validate (WirelessSecurity *parent, const GByteArray *ssid)
+{
+ GtkWidget *entry;
+ const char *key;
+ guint32 len;
+ int i;
+
+ entry = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wpa_psk_entry"));
+ g_assert (entry);
+
+ key = gtk_entry_get_text (GTK_ENTRY (entry));
+ len = strlen (key);
+ if ((len < 8) || (len > 64))
+ return FALSE;
+
+ if (len == 64) {
+ /* Hex PSK */
+ for (i = 0; i < len; i++) {
+ if (!isxdigit (key[i]))
+ return FALSE;
+ }
+ }
+
+ /* passphrase can be between 8 and 63 characters inclusive */
+
+ return TRUE;
+}
+
+static void
+add_to_size_group (WirelessSecurity *parent, GtkSizeGroup *group)
+{
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wpa_psk_type_label"));
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wpa_psk_label"));
+ gtk_size_group_add_widget (group, widget);
+}
+
+static void
+fill_connection (WirelessSecurity *parent, NMConnection *connection)
+{
+ GtkWidget *widget;
+ const char *key;
+ NMSettingWireless *s_wireless;
+ NMSettingWirelessSecurity *s_wireless_sec;
+ const char *mode;
+ gboolean is_adhoc = FALSE;
+
+ s_wireless = nm_connection_get_setting_wireless (connection);
+ g_assert (s_wireless);
+
+ mode = nm_setting_wireless_get_mode (s_wireless);
+ if (mode && !strcmp (mode, "adhoc"))
+ is_adhoc = TRUE;
+
+ g_object_set (s_wireless, NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NULL);
+
+ /* Blow away the old security setting by adding a clear one */
+ s_wireless_sec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+ nm_connection_add_setting (connection, (NMSetting *) s_wireless_sec);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wpa_psk_entry"));
+ key = gtk_entry_get_text (GTK_ENTRY (widget));
+ g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_PSK, key, NULL);
+
+ wireless_security_clear_ciphers (connection);
+ if (is_adhoc) {
+ /* Ad-Hoc settings as specified by the supplicant */
+ g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-none", NULL);
+ nm_setting_wireless_security_add_proto (s_wireless_sec, "wpa");
+ nm_setting_wireless_security_add_pairwise (s_wireless_sec, "none");
+
+ /* Ad-hoc can only have _one_ group cipher... default to TKIP to be more
+ * compatible for now. Maybe we'll support selecting CCMP later.
+ */
+ nm_setting_wireless_security_add_group (s_wireless_sec, "tkip");
+ } else {
+ g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", NULL);
+
+ /* Just leave ciphers and protocol empty, the supplicant will
+ * figure that out magically based on the AP IEs and card capabilities.
+ */
+ }
+}
+
+static void
+update_secrets (WirelessSecurity *parent, NMConnection *connection)
+{
+ helper_fill_secret_entry (connection,
+ parent->builder,
+ "wpa_psk_entry",
+ NM_TYPE_SETTING_WIRELESS_SECURITY,
+ (HelperSecretFunc) nm_setting_wireless_security_get_psk);
+}
+
+WirelessSecurityWPAPSK *
+ws_wpa_psk_new (NMConnection *connection, gboolean secrets_only)
+{
+ WirelessSecurity *parent;
+ WirelessSecurityWPAPSK *sec;
+ GtkWidget *widget;
+
+ parent = wireless_security_init (sizeof (WirelessSecurityWPAPSK),
+ validate,
+ add_to_size_group,
+ fill_connection,
+ update_secrets,
+ NULL,
+ "/org/gnome/control-center/network/ws-wpa-psk.ui",
+ "wpa_psk_notebook",
+ "wpa_psk_entry");
+ if (!parent)
+ return NULL;
+
+ parent->adhoc_compatible = FALSE;
+ sec = (WirelessSecurityWPAPSK *) parent;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wpa_psk_entry"));
+ g_assert (widget);
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) wireless_security_changed_cb,
+ sec);
+ gtk_entry_set_width_chars (GTK_ENTRY (widget), 28);
+
+ /* Fill secrets, if any */
+ if (connection)
+ update_secrets (WIRELESS_SECURITY (sec), connection);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "show_checkbutton_wpa"));
+ g_assert (widget);
+ g_signal_connect (G_OBJECT (widget), "toggled",
+ (GCallback) show_toggled_cb,
+ sec);
+
+ /* Hide WPA/RSN for now since this can be autodetected by NM and the
+ * supplicant when connecting to the AP.
+ */
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wpa_psk_type_combo"));
+ g_assert (widget);
+ gtk_widget_hide (widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wpa_psk_type_label"));
+ g_assert (widget);
+ gtk_widget_hide (widget);
+
+ return sec;
+}
+
diff --git a/panels/network/wireless-security/ws-wpa-psk.h b/panels/network/wireless-security/ws-wpa-psk.h
new file mode 100644
index 0000000..a89552f
--- /dev/null
+++ b/panels/network/wireless-security/ws-wpa-psk.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * 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) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#ifndef WS_WPA_PSK_H
+#define WS_WPA_PSK_H
+
+typedef struct _WirelessSecurityWPAPSK WirelessSecurityWPAPSK;
+
+WirelessSecurityWPAPSK * ws_wpa_psk_new (NMConnection *connection, gboolean secrets_only);
+
+#endif /* WS_WEP_KEY_H */
+
diff --git a/panels/network/wireless-security/ws-wpa-psk.ui b/panels/network/wireless-security/ws-wpa-psk.ui
new file mode 100644
index 0000000..5bc756a
--- /dev/null
+++ b/panels/network/wireless-security/ws-wpa-psk.ui
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkNotebook" id="wpa_psk_notebook">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="show_tabs">False</property>
+ <property name="show_border">False</property>
+ <child>
+ <object class="GtkTable" id="wpa_psk_table">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="n_rows">3</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="wpa_psk_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">wpa_psk_entry</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="wpa_psk_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="max_length">64</property>
+ <property name="visibility">False</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="wpa_psk_type_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Type</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">wpa_psk_type_combo</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label32">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="show_checkbutton_wpa">
+ <property name="label" translatable="yes">Sho_w password</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0.5</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="wpa_psk_type_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="GtkLabel2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+</interface>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]