From 1ad0ec8a31b4e41690689c1e91b0c75e060e46e8 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 26 Jun 2008 17:01:11 +0000 Subject: [PATCH] 2008-06-26 Dan Williams Implement the Advanced... dialog git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3772 4912f4e0-d625-0410-9fb7-b9a5a253dbdc --- vpn-daemons/openvpn/ChangeLog | 4 + vpn-daemons/openvpn/po/POTFILES.in | 1 + vpn-daemons/openvpn/properties/auth-helpers.c | 412 +++++++++++++++++- vpn-daemons/openvpn/properties/auth-helpers.h | 7 + .../properties/nm-openvpn-dialog.glade | 295 +++++++++++++ vpn-daemons/openvpn/properties/nm-openvpn.c | 115 +++++ 6 files changed, 828 insertions(+), 6 deletions(-) diff --git a/vpn-daemons/openvpn/ChangeLog b/vpn-daemons/openvpn/ChangeLog index ea6c2cab9c..1e1c1ac471 100644 --- a/vpn-daemons/openvpn/ChangeLog +++ b/vpn-daemons/openvpn/ChangeLog @@ -1,3 +1,7 @@ +2008-06-26 Dan Williams + + Implement the Advanced... dialog + 2008-06-23 Dan Williams * Convert to new NM VPN UI plugin format diff --git a/vpn-daemons/openvpn/po/POTFILES.in b/vpn-daemons/openvpn/po/POTFILES.in index 2ace195c2c..572edf5e60 100644 --- a/vpn-daemons/openvpn/po/POTFILES.in +++ b/vpn-daemons/openvpn/po/POTFILES.in @@ -3,6 +3,7 @@ auth-dialog/gnome-two-password-dialog.c auth-dialog/main.c nm-openvpn.desktop.in +properties/auth-helpers.c properties/nm-openvpn.c properties/nm-openvpn-dialog.glade src/nm-openvpn-service.c diff --git a/vpn-daemons/openvpn/properties/auth-helpers.c b/vpn-daemons/openvpn/properties/auth-helpers.c index 7eda9b9067..3fa789db8c 100644 --- a/vpn-daemons/openvpn/properties/auth-helpers.c +++ b/vpn-daemons/openvpn/properties/auth-helpers.c @@ -4,6 +4,7 @@ * nm-openvpn.c : GNOME UI dialogs for configuring openvpn VPN connections * * Copyright (C) 2008 Dan Williams, + * Copyright (C) 2008 Tambet Ingo, * * 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 @@ -254,7 +255,7 @@ validate_tls (GladeXML *xml, const char *prefix, GError **error) return FALSE; } - return FALSE; + return TRUE; } gboolean @@ -266,15 +267,14 @@ auth_widget_check_validity (GladeXML *xml, gint contype, GError **error) switch (contype) { case NM_OPENVPN_CONTYPE_TLS: - if (!validate_tls (xml, "tls", error)) - is_valid = FALSE; + is_valid = validate_tls (xml, "tls", error); break; case NM_OPENVPN_CONTYPE_PASSWORD_TLS: - if (!validate_tls (xml, "pw_tls", error)) { - is_valid = FALSE; + is_valid = validate_tls (xml, "pw_tls", error); + if (!is_valid) break; - } + widget = glade_xml_get_widget (xml, "pw_tls_username_entry"); str = gtk_entry_get_text (GTK_ENTRY (widget)); if (!str || !strlen (str)) { @@ -583,3 +583,403 @@ sk_file_chooser_filter_new (void) return filter; } +static void +nm_gvalue_destroy (gpointer data) +{ + GValue *value = (GValue *) data; + + g_value_unset (value); + g_slice_free (GValue, value); +} + +static const char *advanced_keys[] = { + NM_OPENVPN_KEY_PORT, + NM_OPENVPN_KEY_COMP_LZO, + NM_OPENVPN_KEY_TAP_DEV, + NM_OPENVPN_KEY_PROTO_TCP, + NM_OPENVPN_KEY_CIPHER, + NM_OPENVPN_KEY_TA_DIR, + NM_OPENVPN_KEY_TA, + NULL +}; + +static void +copy_values (gpointer key, gpointer data, gpointer user_data) +{ + GHashTable *hash = (GHashTable *) user_data; + GValue *value = (GValue *) data; + const char **i; + + for (i = &advanced_keys[0]; *i; i++) { + if (strcmp ((const char *) key, *i)) + continue; + + if (G_VALUE_HOLDS_STRING (value)) { + g_hash_table_insert (hash, + g_strdup ((const char *) key), + str_to_gvalue (g_value_get_string (value))); + } else if (G_VALUE_HOLDS_INT (value)) { + g_hash_table_insert (hash, + g_strdup ((const char *) key), + int_to_gvalue (g_value_get_int (value))); + } else if (G_VALUE_HOLDS_BOOLEAN (value)) { + g_hash_table_insert (hash, + g_strdup ((const char *) key), + bool_to_gvalue (g_value_get_boolean (value))); + } + } +} + +GHashTable * +advanced_dialog_new_hash_from_connection (NMConnection *connection, + GError **error) +{ + GHashTable *hash; + NMSettingVPNProperties *s_vpn_props; + GValue *value; + + hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, nm_gvalue_destroy); + + s_vpn_props = (NMSettingVPNProperties *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN_PROPERTIES); + if (s_vpn_props && s_vpn_props->data) + g_hash_table_foreach (s_vpn_props->data, copy_values, hash); + + return hash; +} + +static void +port_toggled_cb (GtkWidget *check, gpointer user_data) +{ + GladeXML *xml = (GladeXML *) user_data; + GtkWidget *widget; + + widget = glade_xml_get_widget (xml, "port_spinbutton"); + gtk_widget_set_sensitive (widget, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check))); +} + +static const char * +nm_find_openvpn (void) +{ + static const char *openvpn_binary_paths[] = { + "/usr/sbin/openvpn", + "/sbin/openvpn", + NULL + }; + const char **openvpn_binary = openvpn_binary_paths; + + while (*openvpn_binary != NULL) { + if (g_file_test (*openvpn_binary, G_FILE_TEST_EXISTS)) + break; + openvpn_binary++; + } + + return *openvpn_binary; +} + +#define TLS_CIPHER_COL_NAME 0 +#define TLS_CIPHER_COL_DEFAULT 1 + +static void +populate_cipher_combo (GtkComboBox *box, const char *user_cipher) +{ + GtkListStore *store; + GtkTreeIter iter; + const char *openvpn_binary = NULL; + gchar *cmdline, *tmp, *token; + gboolean user_added = FALSE; + + openvpn_binary = nm_find_openvpn (); + if (!openvpn_binary) + return; + + cmdline = g_strdup_printf("/bin/sh -c \"%s --show-ciphers | /bin/awk '/^[A-Z][A-Z0-9]+-/ { print $1 }'\"", openvpn_binary); + if (!g_spawn_command_line_sync(cmdline, &tmp, NULL, NULL, NULL)) + goto end; + + token = strtok(tmp, "\n"); + + store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT); + gtk_combo_box_set_model (box, GTK_TREE_MODEL (store)); + + /* Add default option which won't pass --cipher to openvpn */ + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + TLS_CIPHER_COL_NAME, _("Default"), + TLS_CIPHER_COL_DEFAULT, TRUE, -1); + + while (token) { + if (strlen (token)) { + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + TLS_CIPHER_COL_NAME, token, + TLS_CIPHER_COL_DEFAULT, FALSE, -1); + if (user_cipher && !strcmp (token, user_cipher)) { + gtk_combo_box_set_active_iter (box, &iter); + user_added = TRUE; + } + } + token = strtok (NULL, "\n"); + } + + /* Add the user-specified cipher if it exists wasn't found by openvpn */ + if (user_cipher && !user_added) { + gtk_list_store_insert (store, &iter, 1); + gtk_list_store_set (store, &iter, + TLS_CIPHER_COL_NAME, user_cipher, + TLS_CIPHER_COL_DEFAULT, FALSE -1); + gtk_combo_box_set_active_iter (box, &iter); + } else if (!user_added) { + gtk_combo_box_set_active (box, 0); + } + + g_object_unref (G_OBJECT (store)); + + end: + g_free(tmp); +} + +static void +tls_auth_toggled_cb (GtkWidget *widget, gpointer user_data) +{ + GladeXML *xml = (GladeXML *) user_data; + gboolean use_auth = FALSE; + + widget = glade_xml_get_widget (xml, "tls_auth_checkbutton"); + use_auth = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)); + + widget = glade_xml_get_widget (xml, "tls_dir_help_label"); + gtk_widget_set_sensitive (widget, use_auth); + widget = glade_xml_get_widget (xml, "direction_label"); + gtk_widget_set_sensitive (widget, use_auth); + widget = glade_xml_get_widget (xml, "tls_auth_label"); + gtk_widget_set_sensitive (widget, use_auth); + widget = glade_xml_get_widget (xml, "tls_auth_chooser"); + gtk_widget_set_sensitive (widget, use_auth); + widget = glade_xml_get_widget (xml, "direction_combo"); + gtk_widget_set_sensitive (widget, use_auth); +} + +#define TA_DIR_COL_NAME 0 +#define TA_DIR_COL_NUM 1 + +GtkWidget * +advanced_dialog_new (GHashTable *hash, int contype) +{ + GladeXML *xml; + GtkWidget *dialog = NULL; + char *glade_file = NULL; + GtkWidget *widget; + GValue *value; + + g_return_val_if_fail (hash != NULL, NULL); + + glade_file = g_strdup_printf ("%s/%s", GLADEDIR, "nm-openvpn-dialog.glade"); + xml = glade_xml_new (glade_file, "openvpn-advanced-dialog", GETTEXT_PACKAGE); + if (xml == NULL) + goto out; + + dialog = glade_xml_get_widget (xml, "openvpn-advanced-dialog"); + if (!dialog) { + g_object_unref (G_OBJECT (xml)); + goto out; + } + gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); + + g_object_set_data_full (G_OBJECT (dialog), "glade-xml", + xml, (GDestroyNotify) g_object_unref); + g_object_set_data (G_OBJECT (dialog), "connection-type", GINT_TO_POINTER (contype)); + + widget = glade_xml_get_widget (xml, "port_checkbutton"); + g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (port_toggled_cb), xml); + + value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_PORT); + if (value && G_VALUE_HOLDS_INT (value)) { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE); + + widget = glade_xml_get_widget (xml, "port_spinbutton"); + gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), + (gdouble) g_value_get_int (value)); + gtk_widget_set_sensitive (widget, TRUE); + } else { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE); + + widget = glade_xml_get_widget (xml, "port_spinbutton"); + gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), 1194.0); + gtk_widget_set_sensitive (widget, FALSE); + } + + value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_COMP_LZO); + if (value && G_VALUE_HOLDS_BOOLEAN (value)) { + widget = glade_xml_get_widget (xml, "lzo_checkbutton"); + if (g_value_get_boolean (value)) + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE); + } + + value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_PROTO_TCP); + if (value && G_VALUE_HOLDS_BOOLEAN (value)) { + widget = glade_xml_get_widget (xml, "tcp_checkbutton"); + if (g_value_get_boolean (value)) + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE); + } + + value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_TAP_DEV); + if (value && G_VALUE_HOLDS_BOOLEAN (value)) { + widget = glade_xml_get_widget (xml, "tap_checkbutton"); + if (g_value_get_boolean (value)) + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE); + } + + if (contype != NM_OPENVPN_CONTYPE_TLS && contype != NM_OPENVPN_CONTYPE_PASSWORD_TLS) { + widget = glade_xml_get_widget (xml, "options_notebook"); + gtk_notebook_remove_page (GTK_NOTEBOOK (widget), 1); + } else { + char *user_cipher = NULL; + GtkListStore *store; + GtkTreeIter iter; + int direction = -1, active = -1; + + widget = glade_xml_get_widget (xml, "cipher_combo"); + value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_CIPHER); + if (value && G_VALUE_HOLDS_STRING (value)) + user_cipher = (char *) g_value_get_string (value); + populate_cipher_combo (GTK_COMBO_BOX (widget), user_cipher); + + widget = glade_xml_get_widget (xml, "tls_auth_checkbutton"); + value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_TA); + if (value && G_VALUE_HOLDS_STRING (value)) { + if (strlen (g_value_get_string (value))) + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE); + } + g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (tls_auth_toggled_cb), xml); + tls_auth_toggled_cb (widget, xml); + + widget = glade_xml_get_widget (xml, "direction_combo"); + value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_TA_DIR); + if (value && G_VALUE_HOLDS_STRING (value)) { + direction = (int) strtol (g_value_get_string (value), NULL, 10); + /* If direction is not 0 or 1, use no direction */ + if (direction != 0 && direction != 1) + direction = -1; + } + + store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT); + + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, TA_DIR_COL_NAME, _("None"), TA_DIR_COL_NUM, -1, -1); + + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, TA_DIR_COL_NAME, "0", TA_DIR_COL_NUM, 0, -1); + if (direction == 0) + active = 1; + + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, TA_DIR_COL_NAME, "1", TA_DIR_COL_NUM, 1, -1); + if (direction == 1) + active = 2; + + gtk_combo_box_set_model (GTK_COMBO_BOX (widget), GTK_TREE_MODEL (store)); + g_object_unref (store); + gtk_combo_box_set_active (GTK_COMBO_BOX (widget), active < 0 ? 0 : active); + + value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_TA); + if (value && G_VALUE_HOLDS_STRING (value)) { + widget = glade_xml_get_widget (xml, "tls_auth_chooser"); + gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), g_value_get_string (value)); + } + } + +out: + g_free (glade_file); + return dialog; +} + +GHashTable * +advanced_dialog_new_hash_from_dialog (GtkWidget *dialog, GError **error) +{ + GHashTable *hash; + GtkWidget *widget; + GladeXML *xml; + int contype = NM_OPENVPN_CONTYPE_INVALID; + + g_return_val_if_fail (dialog != NULL, NULL); + if (error) + g_return_val_if_fail (*error == NULL, NULL); + + xml = g_object_get_data (G_OBJECT (dialog), "glade-xml"); + g_return_val_if_fail (xml != NULL, NULL); + + hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, nm_gvalue_destroy); + + widget = glade_xml_get_widget (xml, "port_checkbutton"); + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) { + int port; + + widget = glade_xml_get_widget (xml, "port_spinbutton"); + port = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (widget)); + g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_PORT), int_to_gvalue (port)); + } + + widget = glade_xml_get_widget (xml, "lzo_checkbutton"); + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) + g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_COMP_LZO), bool_to_gvalue (TRUE)); + + widget = glade_xml_get_widget (xml, "tcp_checkbutton"); + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) + g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_PROTO_TCP), bool_to_gvalue (TRUE)); + + widget = glade_xml_get_widget (xml, "tap_checkbutton"); + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) + g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_TAP_DEV), bool_to_gvalue (TRUE)); + + contype = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), "connection-type")); + if (contype == NM_OPENVPN_CONTYPE_TLS || contype == NM_OPENVPN_CONTYPE_PASSWORD_TLS) { + GtkTreeModel *model; + GtkTreeIter iter; + + widget = glade_xml_get_widget (xml, "cipher_combo"); + model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget)); + if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter)) { + char *cipher = NULL; + gboolean is_default = TRUE; + + gtk_tree_model_get (model, &iter, + TLS_CIPHER_COL_NAME, &cipher, + TLS_CIPHER_COL_DEFAULT, &is_default, -1); + if (!is_default && cipher) { + g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_CIPHER), + str_to_gvalue (cipher)); + } + } + + widget = glade_xml_get_widget (xml, "tls_auth_checkbutton"); + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) { + char *filename; + + widget = glade_xml_get_widget (xml, "tls_auth_chooser"); + filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget)); + if (filename && strlen (filename)) { + g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_TA), + str_to_gvalue (filename)); + } + g_free (filename); + + widget = glade_xml_get_widget (xml, "direction_combo"); + model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget)); + if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter)) { + int direction = -1; + + gtk_tree_model_get (model, &iter, TA_DIR_COL_NUM, &direction, -1); + if (direction >= 0) { + char str_dir[2] = { '0', '\0' }; + + str_dir[0] = (direction == 0) ? '0' : '1'; + g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_TA_DIR), + str_to_gvalue (str_dir)); + } + } + } + } + + return hash; +} + diff --git a/vpn-daemons/openvpn/properties/auth-helpers.h b/vpn-daemons/openvpn/properties/auth-helpers.h index 896d2ab9eb..5f4efe97b0 100644 --- a/vpn-daemons/openvpn/properties/auth-helpers.h +++ b/vpn-daemons/openvpn/properties/auth-helpers.h @@ -29,6 +29,7 @@ #include #include +#include #include typedef void (*ChangedCallback) (GtkWidget *widget, gpointer user_data); @@ -57,4 +58,10 @@ GtkFileFilter *tls_file_chooser_filter_new (void); GtkFileFilter *sk_file_chooser_filter_new (void); +GtkWidget *advanced_dialog_new (GHashTable *hash, int contype); + +GHashTable *advanced_dialog_new_hash_from_connection (NMConnection *connection, GError **error); + +GHashTable *advanced_dialog_new_hash_from_dialog (GtkWidget *dialog, GError **error); + #endif diff --git a/vpn-daemons/openvpn/properties/nm-openvpn-dialog.glade b/vpn-daemons/openvpn/properties/nm-openvpn-dialog.glade index 482c4ba24b..45e5387df9 100644 --- a/vpn-daemons/openvpn/properties/nm-openvpn-dialog.glade +++ b/vpn-daemons/openvpn/properties/nm-openvpn-dialog.glade @@ -656,4 +656,299 @@ + + 5 + GTK_WIN_POS_CENTER_ON_PARENT + True + stock-preferences + GDK_WINDOW_TYPE_HINT_DIALOG + True + False + + + True + 2 + + + True + True + + + True + 12 + 6 + + + True + 6 + + + True + True + Use custom gateway p_ort: + True + 0 + True + + + False + + + + + True + True + 1194 1 65535 1 10 10 + True + + + False + False + 1 + + + + + False + + + + + True + True + Use L_ZO data compression + True + 0 + True + + + False + 1 + + + + + True + True + Use a _TCP connection + True + 0 + True + + + False + 2 + + + + + True + True + Use a TA_P device + True + 0 + True + + + False + 3 + + + + + + + True + General + + + tab + False + + + + + True + 12 + 3 + 2 + 12 + 6 + + + + + + True + 3 + 2 + 12 + 6 + + + True + 0 + Key File: + + + + + True + + + + 1 + 2 + 1 + 2 + + + + + True + + + 1 + 2 + + + + + + + + True + 1 + 0 + + + True + 0 + <i>If key direction is used, it must be the opposite of that used on the VPN peer. For example, if the peer uses '1', this connection must use '0'. If you are unsure what value to use, contact your system administrator.</i> + True + True + + + + + 1 + 2 + 2 + 3 + + + + + + True + 0 + Key Direction: + + + 1 + 2 + + + + + 1 + 2 + 2 + 3 + + + + + True + True + Use additional TLS authentication + 0 + True + + + 2 + 1 + 2 + + + + + True + 0 + Cipher: + + + GTK_EXPAND + + + + + True + + + + 1 + 2 + GTK_EXPAND + + + + + 1 + + + + + True + Certificates (TLS) + + + tab + 1 + False + + + + + False + False + 1 + + + + + True + GTK_BUTTONBOX_END + + + True + True + True + gtk-cancel + True + -6 + + + + + True + True + True + gtk-ok + True + -5 + + + 1 + + + + + False + GTK_PACK_END + + + + + diff --git a/vpn-daemons/openvpn/properties/nm-openvpn.c b/vpn-daemons/openvpn/properties/nm-openvpn.c index 105505bcd5..521c71abe8 100644 --- a/vpn-daemons/openvpn/properties/nm-openvpn.c +++ b/vpn-daemons/openvpn/properties/nm-openvpn.c @@ -82,6 +82,9 @@ typedef struct { GladeXML *xml; GtkWidget *widget; GtkSizeGroup *group; + GtkWindowGroup *window_group; + gboolean window_added; + GHashTable *advanced; } OpenvpnPluginUiWidgetPrivate; @@ -185,6 +188,73 @@ auth_combo_changed_cb (GtkWidget *combo, gpointer user_data) stuff_changed_cb (combo, self); } +static void +advanced_dialog_close_cb (GtkWidget *dialog, gpointer user_data) +{ + OpenvpnPluginUiWidget *self = OPENVPN_PLUGIN_UI_WIDGET (user_data); + OpenvpnPluginUiWidgetPrivate *priv = OPENVPN_PLUGIN_UI_WIDGET_GET_PRIVATE (self); + + gtk_widget_hide (dialog); + /* gtk_widget_destroy() will remove the window from the window group */ + gtk_widget_destroy (dialog); +} + +static void +advanced_dialog_response_cb (GtkWidget *dialog, gint response, gpointer user_data) +{ + OpenvpnPluginUiWidget *self = OPENVPN_PLUGIN_UI_WIDGET (user_data); + OpenvpnPluginUiWidgetPrivate *priv = OPENVPN_PLUGIN_UI_WIDGET_GET_PRIVATE (self); + GError *error = NULL; + + if (priv->advanced) + g_hash_table_destroy (priv->advanced); + priv->advanced = advanced_dialog_new_hash_from_dialog (dialog, &error); + if (!priv->advanced) { + g_message ("%s: error reading advanced settings: %s", __func__, error->message); + g_error_free (error); + } + advanced_dialog_close_cb (dialog, self); + + stuff_changed_cb (NULL, self); +} + +static void +advanced_button_clicked_cb (GtkWidget *button, gpointer user_data) +{ + OpenvpnPluginUiWidget *self = OPENVPN_PLUGIN_UI_WIDGET (user_data); + OpenvpnPluginUiWidgetPrivate *priv = OPENVPN_PLUGIN_UI_WIDGET_GET_PRIVATE (self); + GtkWidget *dialog, *toplevel, *widget; + GtkTreeModel *model; + GtkTreeIter iter; + int contype = NM_OPENVPN_CONTYPE_INVALID; + + toplevel = gtk_widget_get_toplevel (priv->widget); + g_return_if_fail (GTK_WIDGET_TOPLEVEL (toplevel)); + + widget = glade_xml_get_widget (priv->xml, "auth_combo"); + model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget)); + if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter)) + gtk_tree_model_get (model, &iter, COL_AUTH_TYPE, &contype, -1); + + dialog = advanced_dialog_new (priv->advanced, contype); + if (!dialog) { + g_warning ("%s: failed to create the Advanced dialog!", __func__); + return; + } + + gtk_window_group_add_window (priv->window_group, GTK_WINDOW (dialog)); + if (!priv->window_added) { + gtk_window_group_add_window (priv->window_group, GTK_WINDOW (toplevel)); + priv->window_added = TRUE; + } + + gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (toplevel)); + g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (advanced_dialog_response_cb), self); + g_signal_connect (G_OBJECT (dialog), "close", G_CALLBACK (advanced_dialog_close_cb), self); + + gtk_widget_show_all (dialog); +} + static gboolean init_plugin_ui (OpenvpnPluginUiWidget *self, NMConnection *connection, GError **error) { @@ -286,6 +356,9 @@ init_plugin_ui (OpenvpnPluginUiWidget *self, NMConnection *connection, GError ** g_signal_connect (widget, "changed", G_CALLBACK (auth_combo_changed_cb), self); gtk_combo_box_set_active (GTK_COMBO_BOX (widget), active < 0 ? 0 : active); + widget = glade_xml_get_widget (priv->xml, "advanced_button"); + g_signal_connect (G_OBJECT (widget), "clicked", G_CALLBACK (advanced_button_clicked_cb), self); + return TRUE; } @@ -334,6 +407,31 @@ int_to_gvalue (gint i) return value; } +static void +hash_copy_advanced (gpointer key, gpointer data, gpointer user_data) +{ + GHashTable *hash = (GHashTable *) user_data; + GValue *value = (GValue *) data; + const char *i; + + if (G_VALUE_HOLDS_STRING (value)) { + g_hash_table_insert (hash, + g_strdup ((const char *) key), + str_to_gvalue (g_value_get_string (value))); + } else if (G_VALUE_HOLDS_INT (value)) { + g_hash_table_insert (hash, + g_strdup ((const char *) key), + int_to_gvalue (g_value_get_int (value))); + } else if (G_VALUE_HOLDS_BOOLEAN (value)) { + g_hash_table_insert (hash, + g_strdup ((const char *) key), + bool_to_gvalue (g_value_get_boolean (value))); + } else { + g_warning ("%s: unhandled key '%s' of type '%s'", + __func__, (const char *) key, G_VALUE_TYPE_NAME (value)); + } +} + static gboolean update_connection (NMVpnPluginUiWidgetInterface *iface, NMConnection *connection, @@ -388,6 +486,9 @@ update_connection (NMVpnPluginUiWidgetInterface *iface, } } + if (priv->advanced) + g_hash_table_foreach (priv->advanced, hash_copy_advanced, s_vpn_props->data); + nm_connection_add_setting (connection, NM_SETTING (s_vpn_props)); valid = TRUE; @@ -432,11 +533,19 @@ nm_vpn_plugin_ui_widget_interface_new (NMConnection *connection, GError **error) } g_object_ref_sink (priv->widget); + priv->window_group = gtk_window_group_new (); + if (!init_plugin_ui (OPENVPN_PLUGIN_UI_WIDGET (object), connection, error)) { g_object_unref (object); return NULL; } + priv->advanced = advanced_dialog_new_hash_from_connection (connection, error); + if (!priv->advanced) { + g_object_unref (object); + return NULL; + } + return object; } @@ -449,12 +558,18 @@ dispose (GObject *object) if (priv->group) g_object_unref (priv->group); + if (priv->window_group) + g_object_unref (priv->window_group); + if (priv->widget) g_object_unref (priv->widget); if (priv->xml) g_object_unref (priv->xml); + if (priv->advanced) + g_hash_table_destroy (priv->advanced); + G_OBJECT_CLASS (openvpn_plugin_ui_widget_parent_class)->dispose (object); }