[network-manager-openvpn/th/cleanup-bgo790612: 5/11] properties: merge "properties/auth-helpers.c" in "nm-editor-plugin.c"



commit 751f9749a966877c34d3912850a57f59a0c83a5d
Author: Thomas Haller <thaller redhat com>
Date:   Fri Nov 17 14:51:18 2017 +0100

    properties: merge "properties/auth-helpers.c" in "nm-editor-plugin.c"
    
    In the past, the properties plugin contained the non-gtk part and the
    GTK gui. Hence, several GTK related parts were in "properties/auth-helpers.c".
    
    That is no longer the case. The GTK part of the plugin is in
    "properties/nm-openvpn-editor.c".
    
    There is no reason for this split. Moving related code to different
    files doesn't make it simpler but more complicated.
    
    Move the GTK code back to "properties/nm-openvpn-editor.c"
    
    No code was changed, except necessary adjustments.

 Makefile.am                    |    4 +-
 po/POTFILES.in                 |    1 -
 properties/auth-helpers.c      | 2171 ----------------------------------------
 properties/auth-helpers.h      |   57 --
 properties/nm-openvpn-editor.c | 2149 +++++++++++++++++++++++++++++++++++++++-
 5 files changed, 2148 insertions(+), 2234 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index cd6e310..abc5483 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -110,9 +110,7 @@ editor_sources = \
        properties/resources.c \
        properties/resources.h \
        properties/nm-openvpn-editor.c \
-       properties/nm-openvpn-editor.h \
-       properties/auth-helpers.c \
-       properties/auth-helpers.h
+       properties/nm-openvpn-editor.h
 
 properties_cppflags = \
        -DICONDIR=\""$(datadir)/pixmaps"\" \
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 133d9b4..7f0c1b7 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -2,7 +2,6 @@
 # Please keep this file sorted alphabetically.
 appdata/network-manager-openvpn.metainfo.xml.in
 auth-dialog/main.c
-properties/auth-helpers.c
 properties/import-export.c
 properties/nm-openvpn-editor-plugin.c
 properties/nm-openvpn-editor.c
diff --git a/properties/nm-openvpn-editor.c b/properties/nm-openvpn-editor.c
index 81dcdfa..f902ac5 100644
--- a/properties/nm-openvpn-editor.c
+++ b/properties/nm-openvpn-editor.c
@@ -5,8 +5,9 @@
  * nm-openvpn.c : GNOME UI dialogs for configuring openvpn VPN connections
  *
  * Copyright (C) 2005 Tim Niemueller <tim niemueller de>
+ * Copyright (C) 2008 Tambet Ingo, <tambet gmail com>
  * Copyright (C) 2008 - 2010 Dan Williams, <dcbw redhat com>
- * Copyright (C) 2008 - 2011 Red Hat, Inc.
+ * Copyright (C) 2008 - 2017 Red Hat, Inc.
  * Based on work by David Zeuthen, <davidz redhat com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -35,9 +36,2153 @@
 #include <stdlib.h>
 #include <string.h>
 #include <gtk/gtk.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
 
-#include "auth-helpers.h"
 #include "utils.h"
+#include "nm-utils/nm-shared-utils.h"
+
+/*****************************************************************************/
+
+#define BLOCK_HANDLER_ID "block-handler-id"
+
+/*****************************************************************************/
+
+typedef void (*ChangedCallback) (GtkWidget *widget, gpointer user_data);
+
+static GtkFileFilter *sk_file_chooser_filter_new (void);
+
+/*****************************************************************************/
+
+static const char *comp_lzo_values[] = {
+       "adaptive",
+       "yes",
+       "no-by-default",
+};
+
+static const char *
+comp_lzo_values_conf_coerce (const char *value_conf)
+{
+       if (!value_conf || nm_streq (value_conf, "no"))
+               return NULL;
+       if (nm_streq (value_conf, "yes"))
+               return "yes";
+       if (nm_streq (value_conf, "no-by-default"))
+               return "no-by-default";
+       return "adaptive";
+}
+
+static const char *
+comp_lzo_values_conf_to_display (const char *value_conf)
+{
+       if (nm_streq (value_conf, "yes"))
+               return "yes";
+       if (nm_streq (value_conf, "no-by-default"))
+               return "no";
+       if (nm_streq (value_conf, "adaptive"))
+               return "adaptive";
+       g_return_val_if_reached ("adaptive");
+}
+
+/*****************************************************************************/
+
+/* From gnome-control-center/panels/network/connection-editor/ui-helpers.c */
+
+static void
+widget_set_error (GtkWidget *widget)
+{
+       g_return_if_fail (GTK_IS_WIDGET (widget));
+
+       gtk_style_context_add_class (gtk_widget_get_style_context (widget), "error");
+}
+
+static void
+widget_unset_error (GtkWidget *widget)
+{
+       g_return_if_fail (GTK_IS_WIDGET (widget));
+
+       gtk_style_context_remove_class (gtk_widget_get_style_context (widget), "error");
+}
+
+typedef struct {
+       GtkWidget *widget1;
+       GtkWidget *widget2;
+} TlsChooserSignalData;
+
+static void
+tls_cert_changed_cb (NMACertChooser *this, gpointer user_data)
+{
+       NMACertChooser *other = user_data;
+       NMSetting8021xCKScheme scheme;
+       char *this_cert, *other_cert;
+       char *this_key, *other_key;
+
+       other_key = nma_cert_chooser_get_key (other, &scheme);
+       this_key = nma_cert_chooser_get_key (this, &scheme);
+       other_cert = nma_cert_chooser_get_cert (other, &scheme);
+       this_cert = nma_cert_chooser_get_cert (this, &scheme);
+
+       if (   scheme == NM_SETTING_802_1X_CK_SCHEME_PATH
+           && is_pkcs12 (this_cert)) {
+               if (!this_key)
+                       nma_cert_chooser_set_key (this, this_cert, NM_SETTING_802_1X_CK_SCHEME_PATH);
+               if (!other_cert) {
+                       nma_cert_chooser_set_cert (other, this_cert, NM_SETTING_802_1X_CK_SCHEME_PATH);
+                       if (!other_key)
+                               nma_cert_chooser_set_key (other, this_cert, NM_SETTING_802_1X_CK_SCHEME_PATH);
+               }
+       }
+
+       g_free (this_cert);
+       g_free (other_cert);
+       g_free (this_key);
+       g_free (other_key);
+}
+
+static void
+tls_setup (GtkBuilder *builder,
+           NMSettingVpn *s_vpn,
+           const char *prefix,
+           NMACertChooser *ca_chooser,
+           ChangedCallback changed_cb,
+           gpointer user_data)
+{
+       NMACertChooser *cert;
+       const char *value;
+       char *tmp;
+
+       tmp = g_strdup_printf ("%s_user_cert", prefix);
+       cert = NMA_CERT_CHOOSER (gtk_builder_get_object (builder, tmp));
+       g_free (tmp);
+
+       nma_cert_chooser_add_to_size_group (cert, GTK_SIZE_GROUP (gtk_builder_get_object (builder, 
"labels")));
+       g_signal_connect (G_OBJECT (cert), "changed", G_CALLBACK (changed_cb), user_data);
+
+       if (s_vpn) {
+               value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_CERT);
+               if (value && strlen (value))
+                       nma_cert_chooser_set_cert (cert, value, NM_SETTING_802_1X_CK_SCHEME_PATH);
+
+               value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_KEY);
+               if (value && strlen (value))
+                       nma_cert_chooser_set_key (cert, value, NM_SETTING_802_1X_CK_SCHEME_PATH);
+               value = nm_setting_vpn_get_secret (s_vpn, NM_OPENVPN_KEY_CERTPASS);
+               if (value)
+                       nma_cert_chooser_set_key_password (cert, value);
+       }
+
+       nma_cert_chooser_setup_key_password_storage (cert, 0, (NMSetting *) s_vpn,
+                                                    NM_OPENVPN_KEY_CERTPASS, TRUE, FALSE);
+
+       /* Link choosers to the PKCS#12 changer callback */
+       g_signal_connect_object (ca_chooser, "changed", G_CALLBACK (tls_cert_changed_cb), cert, 0);
+       g_signal_connect_object (cert, "changed", G_CALLBACK (tls_cert_changed_cb), ca_chooser, 0);
+}
+
+static void
+pw_setup (GtkBuilder *builder,
+          NMSettingVpn *s_vpn,
+          const char *prefix,
+          ChangedCallback changed_cb,
+          gpointer user_data)
+{
+       GtkWidget *widget;
+       const char *value;
+       char *tmp;
+
+       tmp = g_strdup_printf ("%s_username_entry", prefix);
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, tmp));
+       g_free (tmp);
+
+       if (s_vpn) {
+               value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_USERNAME);
+               if (value && strlen (value))
+                       gtk_entry_set_text (GTK_ENTRY (widget), value);
+       }
+       g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (changed_cb), user_data);
+
+       /* Fill in the user password */
+       tmp = g_strdup_printf ("%s_password_entry", prefix);
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, tmp));
+       g_free (tmp);
+       g_signal_connect (widget, "changed", G_CALLBACK (changed_cb), user_data);
+
+       if (s_vpn) {
+               value = nm_setting_vpn_get_secret (s_vpn, NM_OPENVPN_KEY_PASSWORD);
+               if (value)
+                       gtk_entry_set_text (GTK_ENTRY (widget), value);
+       }
+
+       nma_utils_setup_password_storage (widget, 0, (NMSetting *) s_vpn, NM_OPENVPN_KEY_PASSWORD,
+                                         TRUE, FALSE);
+}
+
+static void
+tls_pw_init_auth_widget (GtkBuilder *builder,
+                         NMSettingVpn *s_vpn,
+                         const char *contype,
+                         const char *prefix,
+                         ChangedCallback changed_cb,
+                         gpointer user_data)
+{
+       NMACertChooser *ca;
+       const char *value;
+       char *tmp;
+       gboolean tls = FALSE, pw = FALSE;
+
+       g_return_if_fail (builder != NULL);
+       g_return_if_fail (changed_cb != NULL);
+       g_return_if_fail (prefix != NULL);
+
+       tmp = g_strdup_printf ("%s_ca_cert", prefix);
+       ca = NMA_CERT_CHOOSER (gtk_builder_get_object (builder, tmp));
+       g_free (tmp);
+       nma_cert_chooser_add_to_size_group (ca, GTK_SIZE_GROUP (gtk_builder_get_object (builder, "labels")));
+
+       /* Three major connection types here: TLS-only, PW-only, and TLS + PW */
+       if (!strcmp (contype, NM_OPENVPN_CONTYPE_TLS) || !strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD_TLS))
+               tls = TRUE;
+       if (!strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD) || !strcmp (contype, 
NM_OPENVPN_CONTYPE_PASSWORD_TLS))
+               pw = TRUE;
+
+       g_signal_connect (ca, "changed", G_CALLBACK (changed_cb), user_data);
+       if (s_vpn) {
+               value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_CA);
+               if (value && strlen (value))
+                       nma_cert_chooser_set_cert (ca, value, NM_SETTING_802_1X_CK_SCHEME_PATH);
+       }
+
+       /* Set up the rest of the options */
+       if (tls)
+               tls_setup (builder, s_vpn, prefix, ca, changed_cb, user_data);
+       if (pw)
+               pw_setup (builder, s_vpn, prefix, changed_cb, user_data);
+}
+
+#define SK_DIR_COL_NAME 0
+#define SK_DIR_COL_NUM  1
+
+static void
+sk_init_auth_widget (GtkBuilder *builder,
+                     NMSettingVpn *s_vpn,
+                     ChangedCallback changed_cb,
+                     gpointer user_data)
+{
+       GtkWidget *widget;
+       const char *value = NULL;
+       GtkListStore *store;
+       GtkTreeIter iter;
+       gint active = -1;
+       gint direction = -1;
+       GtkFileFilter *filter;
+
+       g_return_if_fail (builder != NULL);
+       g_return_if_fail (changed_cb != NULL);
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "sk_key_chooser"));
+       filter = sk_file_chooser_filter_new ();
+       gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (widget), filter);
+       gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (widget), TRUE);
+       gtk_file_chooser_button_set_title (GTK_FILE_CHOOSER_BUTTON (widget),
+                                          _("Choose an OpenVPN static key…"));
+       g_signal_connect (G_OBJECT (widget), "selection-changed", G_CALLBACK (changed_cb), user_data);
+
+       if (s_vpn) {
+               value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_STATIC_KEY);
+               if (value && strlen (value))
+                       gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), value);
+       }
+
+       store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
+
+       if (s_vpn) {
+               value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_STATIC_KEY_DIRECTION);
+               if (value && strlen (value)) {
+                       long int tmp;
+
+                       errno = 0;
+                       tmp = strtol (value, NULL, 10);
+                       if (errno == 0 && (tmp == 0 || tmp == 1))
+                               direction = (guint32) tmp;
+               }
+       }
+
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter, SK_DIR_COL_NAME, _("None"), SK_DIR_COL_NUM, -1, -1);
+
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter, SK_DIR_COL_NAME, "0", SK_DIR_COL_NUM, 0, -1);
+       if (direction == 0)
+               active = 1;
+
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter, SK_DIR_COL_NAME, "1", SK_DIR_COL_NUM, 1, -1);
+       if (direction == 1)
+               active = 2;
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "sk_direction_combo"));
+
+       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);
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "sk_local_address_entry"));
+       g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (changed_cb), user_data);
+       if (s_vpn) {
+               value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_LOCAL_IP);
+               if (value && strlen (value))
+                       gtk_entry_set_text (GTK_ENTRY (widget), value);
+       }
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "sk_remote_address_entry"));
+       g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (changed_cb), user_data);
+       if (s_vpn) {
+               value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_REMOTE_IP);
+               if (value && strlen (value))
+                       gtk_entry_set_text (GTK_ENTRY (widget), value);
+       }
+}
+
+static gboolean
+validate_cert_chooser (GtkBuilder *builder, const char *name, GError **error)
+{
+       NMACertChooser *chooser;
+
+       chooser = NMA_CERT_CHOOSER (gtk_builder_get_object (builder, name));
+       return nma_cert_chooser_validate (chooser, error);
+}
+
+static gboolean
+validate_tls (GtkBuilder *builder, const char *prefix, GError **error)
+{
+       char *tmp;
+       gboolean valid, encrypted = FALSE;
+       NMACertChooser *user_cert;
+       NMSettingSecretFlags pw_flags;
+       gboolean secrets_required = TRUE;
+       NMSetting8021xCKScheme scheme;
+       GError *local = NULL;
+
+       tmp = g_strdup_printf ("%s_ca_cert", prefix);
+       valid = validate_cert_chooser (builder, tmp, &local);
+       g_free (tmp);
+       if (!valid) {
+               g_set_error (error,
+                            NMV_EDITOR_PLUGIN_ERROR,
+                            NMV_EDITOR_PLUGIN_ERROR_INVALID_PROPERTY,
+                            "%s: %s", NM_OPENVPN_KEY_CA, local->message);
+               g_error_free (local);
+               return FALSE;
+       }
+
+       tmp = g_strdup_printf ("%s_user_cert", prefix);
+       user_cert = NMA_CERT_CHOOSER (gtk_builder_get_object (builder, tmp));
+       valid = validate_cert_chooser (builder, tmp, &local);
+       g_free (tmp);
+       if (!valid) {
+               g_set_error (error,
+                            NMV_EDITOR_PLUGIN_ERROR,
+                            NMV_EDITOR_PLUGIN_ERROR_INVALID_PROPERTY,
+                            "%s: %s", NM_OPENVPN_KEY_CERT, local->message);
+               g_error_free (local);
+               return FALSE;
+       }
+
+       /* Encrypted certificates require a password */
+       tmp = nma_cert_chooser_get_cert (user_cert, &scheme);
+       encrypted = is_encrypted (tmp);
+       g_free (tmp);
+
+       pw_flags = nma_cert_chooser_get_key_password_flags (user_cert);
+       if (   pw_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED
+           || pw_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)
+               secrets_required = FALSE;
+
+       if (encrypted && secrets_required) {
+               if (!nma_cert_chooser_get_key_password (user_cert)) {
+                       g_set_error (error,
+                                    NMV_EDITOR_PLUGIN_ERROR,
+                                    NMV_EDITOR_PLUGIN_ERROR_INVALID_PROPERTY,
+                                    NM_OPENVPN_KEY_CERTPASS);
+                       return FALSE;
+               }
+       }
+
+       return TRUE;
+}
+
+static gboolean
+auth_widget_check_validity (GtkBuilder *builder, const char *contype, GError **error)
+{
+       GtkWidget *widget;
+       const char *str;
+       char *filename;
+       GError *local = NULL;
+
+       if (!strcmp (contype, NM_OPENVPN_CONTYPE_TLS)) {
+               if (!validate_tls (builder, "tls", error))
+                       return FALSE;
+       } else if (!strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD_TLS)) {
+               if (!validate_tls (builder, "pw_tls", error))
+                       return FALSE;
+
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "pw_tls_username_entry"));
+               str = gtk_entry_get_text (GTK_ENTRY (widget));
+               if (!str || !*str) {
+                       g_set_error (error,
+                                    NMV_EDITOR_PLUGIN_ERROR,
+                                    NMV_EDITOR_PLUGIN_ERROR_INVALID_PROPERTY,
+                                    NM_OPENVPN_KEY_USERNAME);
+                       return FALSE;
+               }
+       } else if (!strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD)) {
+               if (!validate_cert_chooser (builder, "pw_ca_cert", &local)) {
+                       g_set_error (error,
+                                    NMV_EDITOR_PLUGIN_ERROR,
+                                    NMV_EDITOR_PLUGIN_ERROR_INVALID_PROPERTY,
+                                    "%s: %s", NM_OPENVPN_KEY_CA, local->message);
+                       g_error_free (local);
+                       return FALSE;
+               }
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "pw_username_entry"));
+               str = gtk_entry_get_text (GTK_ENTRY (widget));
+               if (!str || !*str) {
+                       g_set_error (error,
+                                    NMV_EDITOR_PLUGIN_ERROR,
+                                    NMV_EDITOR_PLUGIN_ERROR_INVALID_PROPERTY,
+                                    NM_OPENVPN_KEY_USERNAME);
+                       return FALSE;
+               }
+       } else if (!strcmp (contype, NM_OPENVPN_CONTYPE_STATIC_KEY)) {
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "sk_key_chooser"));
+               filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+               if (!filename || !filename[0]) {
+                       g_free (filename);
+                       g_set_error (error,
+                                    NMV_EDITOR_PLUGIN_ERROR,
+                                    NMV_EDITOR_PLUGIN_ERROR_INVALID_PROPERTY,
+                                    NM_OPENVPN_KEY_STATIC_KEY);
+                       return FALSE;
+               }
+               g_free (filename);
+
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "sk_local_address_entry"));
+               str = gtk_entry_get_text (GTK_ENTRY (widget));
+               if (!str || !*str) {
+                       g_set_error (error,
+                                    NMV_EDITOR_PLUGIN_ERROR,
+                                    NMV_EDITOR_PLUGIN_ERROR_INVALID_PROPERTY,
+                                    NM_OPENVPN_KEY_LOCAL_IP);
+                       return FALSE;
+               }
+
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "sk_remote_address_entry"));
+               str = gtk_entry_get_text (GTK_ENTRY (widget));
+               if (!str || !*str) {
+                       g_set_error (error,
+                                    NMV_EDITOR_PLUGIN_ERROR,
+                                    NMV_EDITOR_PLUGIN_ERROR_INVALID_PROPERTY,
+                                    NM_OPENVPN_KEY_REMOTE_IP);
+                       return FALSE;
+               }
+       } else
+               g_assert_not_reached ();
+
+       return TRUE;
+}
+
+static void
+update_from_cert_chooser (GtkBuilder *builder,
+                          const char *cert_prop,
+                          const char *key_prop,
+                          const char *key_pass_prop,
+                          const char *prefix,
+                          const char *widget_name,
+                          NMSettingVpn *s_vpn)
+{
+       NMSetting8021xCKScheme scheme;
+       NMACertChooser *cert_chooser;
+       NMSettingSecretFlags pw_flags;
+       char *tmp;
+       const char *password;
+
+       g_return_if_fail (builder != NULL);
+       g_return_if_fail (cert_prop != NULL);
+       g_return_if_fail (prefix != NULL);
+       g_return_if_fail (widget_name != NULL);
+       g_return_if_fail (s_vpn != NULL);
+
+       tmp = g_strdup_printf ("%s_%s", prefix, widget_name);
+       cert_chooser = NMA_CERT_CHOOSER (gtk_builder_get_object (builder, tmp));
+       g_free (tmp);
+
+       tmp = nma_cert_chooser_get_cert (cert_chooser, &scheme);
+       if (tmp && strlen (tmp))
+               nm_setting_vpn_add_data_item (s_vpn, cert_prop, tmp);
+       g_free (tmp);
+
+       if (key_prop) {
+               g_return_if_fail (key_pass_prop != NULL);
+
+               tmp = nma_cert_chooser_get_key (cert_chooser, &scheme);
+               if (tmp && strlen (tmp))
+                       nm_setting_vpn_add_data_item (s_vpn, key_prop, tmp);
+               g_free (tmp);
+
+               password = nma_cert_chooser_get_key_password (cert_chooser);
+               if (password && strlen (password))
+                       nm_setting_vpn_add_secret (s_vpn, key_pass_prop, password);
+
+               pw_flags = nma_cert_chooser_get_key_password_flags (cert_chooser);
+               nm_setting_set_secret_flags (NM_SETTING (s_vpn), key_pass_prop, pw_flags, NULL);
+       }
+}
+
+static void
+update_tls (GtkBuilder *builder, const char *prefix, NMSettingVpn *s_vpn)
+{
+       update_from_cert_chooser (builder,
+                                 NM_OPENVPN_KEY_CA,
+                                 NULL,
+                                 NULL,
+                                 prefix, "ca_cert", s_vpn);
+
+       update_from_cert_chooser (builder,
+                                 NM_OPENVPN_KEY_CERT,
+                                 NM_OPENVPN_KEY_KEY,
+                                 NM_OPENVPN_KEY_CERTPASS,
+                                 prefix, "user_cert", s_vpn);
+}
+
+static void
+update_pw (GtkBuilder *builder, const char *prefix, NMSettingVpn *s_vpn)
+{
+       GtkWidget *widget;
+       NMSettingSecretFlags pw_flags;
+       char *tmp;
+       const char *str;
+
+       g_return_if_fail (builder != NULL);
+       g_return_if_fail (prefix != NULL);
+       g_return_if_fail (s_vpn != NULL);
+
+       tmp = g_strdup_printf ("%s_username_entry", prefix);
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, tmp));
+       g_free (tmp);
+
+       str = gtk_entry_get_text (GTK_ENTRY (widget));
+       if (str && strlen (str))
+               nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_USERNAME, str);
+
+       /* Password */
+       tmp = g_strdup_printf ("%s_password_entry", prefix);
+       widget = (GtkWidget *) gtk_builder_get_object (builder, tmp);
+       g_assert (widget);
+       g_free (tmp);
+
+       str = gtk_entry_get_text (GTK_ENTRY (widget));
+       if (str && strlen (str))
+               nm_setting_vpn_add_secret (s_vpn, NM_OPENVPN_KEY_PASSWORD, str);
+
+       /* Update password flags */
+       pw_flags = nma_utils_menu_to_secret_flags (widget);
+       nm_setting_set_secret_flags (NM_SETTING (s_vpn), NM_OPENVPN_KEY_PASSWORD, pw_flags, NULL);
+}
+
+static gboolean
+auth_widget_update_connection (GtkBuilder *builder,
+                               const char *contype,
+                               NMSettingVpn *s_vpn)
+{
+       GtkTreeModel *model;
+       GtkTreeIter iter;
+       GtkWidget *widget;
+       const char *str;
+       char *filename;
+
+       if (!strcmp (contype, NM_OPENVPN_CONTYPE_TLS)) {
+               update_tls (builder, "tls", s_vpn);
+       } else if (!strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD)) {
+               update_from_cert_chooser (builder, NM_OPENVPN_KEY_CA, NULL, NULL,
+                                         "pw", "ca_cert", s_vpn);
+               update_pw (builder, "pw", s_vpn);
+       } else if (!strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD_TLS)) {
+               update_tls (builder, "pw_tls", s_vpn);
+               update_pw (builder, "pw_tls", s_vpn);
+       } else if (!strcmp (contype, NM_OPENVPN_CONTYPE_STATIC_KEY)) {
+               /* Update static key */
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "sk_key_chooser"));
+               filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+               if (filename && strlen (filename))
+                       nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_STATIC_KEY, filename);
+               g_free (filename);
+
+               /* Update direction */
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "sk_direction_combo"));
+               g_assert (widget);
+               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, SK_DIR_COL_NUM, &direction, -1);
+                       if (direction > -1) {
+                               char *tmp = g_strdup_printf ("%d", direction);
+                               nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_STATIC_KEY_DIRECTION, 
tmp);
+                               g_free (tmp);
+                       }
+               }
+
+               /* Update local address */
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "sk_local_address_entry"));
+               g_assert (widget);
+               str = gtk_entry_get_text (GTK_ENTRY (widget));
+               if (str && strlen (str))
+                       nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_LOCAL_IP, str);
+
+               /* Update remote address */
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "sk_remote_address_entry"));
+               g_assert (widget);
+               str = gtk_entry_get_text (GTK_ENTRY (widget));
+               if (str && strlen (str))
+                       nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_REMOTE_IP, str);
+       } else
+               g_assert_not_reached ();
+
+       return TRUE;
+}
+
+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 *sk_key_begin = "-----BEGIN OpenVPN Static key V1-----";
+
+static gboolean
+sk_default_filter (const GtkFileFilterInfo *filter_info, gpointer data)
+{
+       int fd;
+       unsigned char buffer[1024];
+       ssize_t bytes_read;
+       gboolean show = FALSE;
+       char *p;
+       char *ext;
+
+       if (!filter_info->filename)
+               return FALSE;
+
+       p = strrchr (filter_info->filename, '.');
+       if (!p)
+               return FALSE;
+
+       ext = g_ascii_strdown (p, -1);
+       if (!ext)
+               return FALSE;
+       if (!g_str_has_suffix (ext, ".key")) {
+               g_free (ext);
+               return FALSE;
+       }
+       g_free (ext);
+
+       fd = open (filter_info->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 PEM signatures */
+       if (find_tag (sk_key_begin, (const char *) buffer, bytes_read)) {
+               show = TRUE;
+               goto out;
+       }
+
+out:
+       close (fd);
+       return show;
+}
+
+static GtkFileFilter *
+sk_file_chooser_filter_new (void)
+{
+       GtkFileFilter *filter;
+
+       filter = gtk_file_filter_new ();
+       gtk_file_filter_add_custom (filter, GTK_FILE_FILTER_FILENAME, sk_default_filter, NULL, NULL);
+       gtk_file_filter_set_name (filter, _("OpenVPN Static Keys (*.key)"));
+       return filter;
+}
+
+static const char *advanced_keys[] = {
+       NM_OPENVPN_KEY_PORT,
+       NM_OPENVPN_KEY_COMP_LZO,
+       NM_OPENVPN_KEY_MSSFIX,
+       NM_OPENVPN_KEY_FLOAT,
+       NM_OPENVPN_KEY_TUNNEL_MTU,
+       NM_OPENVPN_KEY_FRAGMENT_SIZE,
+       NM_OPENVPN_KEY_TAP_DEV,
+       NM_OPENVPN_KEY_DEV,
+       NM_OPENVPN_KEY_DEV_TYPE,
+       NM_OPENVPN_KEY_PROTO_TCP,
+       NM_OPENVPN_KEY_PROXY_TYPE,
+       NM_OPENVPN_KEY_PROXY_SERVER,
+       NM_OPENVPN_KEY_PROXY_PORT,
+       NM_OPENVPN_KEY_PROXY_RETRY,
+       NM_OPENVPN_KEY_HTTP_PROXY_USERNAME,
+       NM_OPENVPN_KEY_CIPHER,
+       NM_OPENVPN_KEY_KEYSIZE,
+       NM_OPENVPN_KEY_AUTH,
+       NM_OPENVPN_KEY_TA_DIR,
+       NM_OPENVPN_KEY_TA,
+       NM_OPENVPN_KEY_TLS_CRYPT,
+       NM_OPENVPN_KEY_RENEG_SECONDS,
+       NM_OPENVPN_KEY_TLS_REMOTE,
+       NM_OPENVPN_KEY_VERIFY_X509_NAME,
+       NM_OPENVPN_KEY_REMOTE_RANDOM,
+       NM_OPENVPN_KEY_TUN_IPV6,
+       NM_OPENVPN_KEY_REMOTE_CERT_TLS,
+       NM_OPENVPN_KEY_NS_CERT_TYPE,
+       NM_OPENVPN_KEY_PING,
+       NM_OPENVPN_KEY_PING_EXIT,
+       NM_OPENVPN_KEY_PING_RESTART,
+       NM_OPENVPN_KEY_MAX_ROUTES,
+       NM_OPENVPN_KEY_MTU_DISC,
+       NULL
+};
+
+static void
+copy_values (const char *key, const char *value, gpointer user_data)
+{
+       GHashTable *hash = (GHashTable *) user_data;
+       const char **i;
+
+       for (i = &advanced_keys[0]; *i; i++) {
+               if (strcmp (key, *i))
+                       continue;
+
+               g_hash_table_insert (hash, g_strdup (key), g_strdup (value));
+       }
+}
+
+static GHashTable *
+advanced_dialog_new_hash_from_connection (NMConnection *connection,
+                                          GError **error)
+{
+       GHashTable *hash;
+       NMSettingVpn *s_vpn;
+       const char *secret, *flags;
+
+       hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+       s_vpn = nm_connection_get_setting_vpn (connection);
+       nm_setting_vpn_foreach_data_item (s_vpn, copy_values, hash);
+
+       /* HTTP Proxy password is special */
+       secret = nm_setting_vpn_get_secret (s_vpn, NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD);
+       if (secret) {
+               g_hash_table_insert (hash,
+                                    g_strdup (NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD),
+                                    g_strdup (secret));
+       }
+       flags = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD"-flags");
+       if (flags)
+               g_hash_table_insert (hash,
+                                    g_strdup (NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD"-flags"),
+                                    g_strdup (flags));
+
+       return hash;
+}
+
+static void
+checkbox_toggled_update_widget_cb (GtkWidget *check, gpointer user_data)
+{
+       GtkWidget *widget = (GtkWidget*) user_data;
+
+       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 *tmp, **items, **item;
+       gboolean user_added = FALSE;
+       char *argv[3];
+       GError *error = NULL;
+       gboolean success, ignore_lines = TRUE;
+
+       openvpn_binary = nm_find_openvpn ();
+       if (!openvpn_binary)
+               return;
+
+       argv[0] = (char *) openvpn_binary;
+       argv[1] = "--show-ciphers";
+       argv[2] = NULL;
+
+       success = g_spawn_sync ("/", argv, NULL, 0, NULL, NULL, &tmp, NULL, NULL, &error);
+       if (!success) {
+               g_warning ("%s: couldn't determine ciphers: %s", __func__, error->message);
+               g_error_free (error);
+               return;
+       }
+
+       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);
+
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter,
+                           TLS_CIPHER_COL_NAME, "none",
+                           TLS_CIPHER_COL_DEFAULT, FALSE, -1);
+       if (g_strcmp0 (user_cipher, "none") == 0) {
+               gtk_combo_box_set_active_iter (box, &iter);
+               user_added = TRUE;
+       }
+
+       items = g_strsplit (tmp, "\n", 0);
+       g_free (tmp);
+
+       for (item = items; *item; item++) {
+               char *space;
+
+               /* Don't add anything until after the first blank line. Also,
+                * any blank line indicates the start of a comment, ended by
+                * another blank line.
+                */
+               if (!strlen (*item)) {
+                       ignore_lines = !ignore_lines;
+                       continue;
+               }
+
+               if (ignore_lines)
+                       continue;
+
+               space = strchr (*item, ' ');
+               if (space)
+                       *space = '\0';
+
+               if (strcmp (*item, "none") == 0)
+                       continue;
+
+               if (strlen (*item)) {
+                       gtk_list_store_append (store, &iter);
+                       gtk_list_store_set (store, &iter,
+                                           TLS_CIPHER_COL_NAME, *item,
+                                           TLS_CIPHER_COL_DEFAULT, FALSE, -1);
+                       if (!user_added && user_cipher && !g_ascii_strcasecmp (*item, user_cipher)) {
+                               gtk_combo_box_set_active_iter (box, &iter);
+                               user_added = TRUE;
+                       }
+               }
+       }
+
+       /* 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));
+       g_strfreev (items);
+}
+
+#define HMACAUTH_COL_NAME 0
+#define HMACAUTH_COL_VALUE 1
+#define HMACAUTH_COL_DEFAULT 2
+
+static void
+populate_hmacauth_combo (GtkComboBox *box, const char *hmacauth)
+{
+       GtkListStore *store;
+       GtkTreeIter iter;
+       gboolean active_initialized = FALSE;
+       const char **item;
+       static const char *items[] = {
+               NM_OPENVPN_AUTH_NONE,
+               NM_OPENVPN_AUTH_RSA_MD4,
+               NM_OPENVPN_AUTH_MD5,
+               NM_OPENVPN_AUTH_SHA1,
+               NM_OPENVPN_AUTH_SHA224,
+               NM_OPENVPN_AUTH_SHA256,
+               NM_OPENVPN_AUTH_SHA384,
+               NM_OPENVPN_AUTH_SHA512,
+               NM_OPENVPN_AUTH_RIPEMD160,
+               NULL
+       };
+
+       store = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
+       gtk_combo_box_set_model (box, GTK_TREE_MODEL (store));
+
+       /* Add default option which won't pass --auth to openvpn */
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter,
+                           HMACAUTH_COL_NAME, _("Default"),
+                           HMACAUTH_COL_DEFAULT, TRUE, -1);
+
+       /* Add options */
+       for (item = items; *item; item++) {
+               const char *name = NULL;
+
+               if (!strcmp (*item, NM_OPENVPN_AUTH_NONE))
+                       name = _("None");
+               else if (!strcmp (*item, NM_OPENVPN_AUTH_RSA_MD4))
+                       name = _("RSA MD-4");
+               else if (!strcmp (*item, NM_OPENVPN_AUTH_MD5))
+                       name = _("MD-5");
+               else if (!strcmp (*item, NM_OPENVPN_AUTH_SHA1))
+                       name = _("SHA-1");
+               else if (!strcmp (*item, NM_OPENVPN_AUTH_SHA224))
+                       name = _("SHA-224");
+               else if (!strcmp (*item, NM_OPENVPN_AUTH_SHA256))
+                       name = _("SHA-256");
+               else if (!strcmp (*item, NM_OPENVPN_AUTH_SHA384))
+                       name = _("SHA-384");
+               else if (!strcmp (*item, NM_OPENVPN_AUTH_SHA512))
+                       name = _("SHA-512");
+               else if (!strcmp (*item, NM_OPENVPN_AUTH_RIPEMD160))
+                       name = _("RIPEMD-160");
+               else
+                       g_assert_not_reached ();
+
+               gtk_list_store_append (store, &iter);
+               gtk_list_store_set (store, &iter,
+                                   HMACAUTH_COL_NAME, name,
+                                   HMACAUTH_COL_VALUE, *item,
+                                   HMACAUTH_COL_DEFAULT, FALSE, -1);
+               if (hmacauth && !g_ascii_strcasecmp (*item, hmacauth)) {
+                       gtk_combo_box_set_active_iter (box, &iter);
+                       active_initialized = TRUE;
+               }
+       }
+
+       if (!active_initialized)
+               gtk_combo_box_set_active (box, 0);
+
+       g_object_unref (store);
+}
+
+#define TLS_REMOTE_MODE_NONE        "none"
+#define TLS_REMOTE_MODE_SUBJECT     NM_OPENVPN_VERIFY_X509_NAME_TYPE_SUBJECT
+#define TLS_REMOTE_MODE_NAME        NM_OPENVPN_VERIFY_X509_NAME_TYPE_NAME
+#define TLS_REMOTE_MODE_NAME_PREFIX NM_OPENVPN_VERIFY_X509_NAME_TYPE_NAME_PREFIX
+#define TLS_REMOTE_MODE_LEGACY      "legacy"
+
+#define TLS_REMOTE_MODE_COL_NAME 0
+#define TLS_REMOTE_MODE_COL_VALUE 1
+
+static void
+populate_tls_remote_mode_entry_combo (GtkEntry* entry, GtkComboBox *box,
+                                      const char *tls_remote, const char *x509_name)
+{
+       GtkListStore *store;
+       GtkTreeIter iter;
+       const char *subject_name = NULL;
+
+       store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
+       gtk_combo_box_set_model (box, GTK_TREE_MODEL (store));
+
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter,
+                           TLS_REMOTE_MODE_COL_NAME, _("Don’t verify certificate identification"),
+                           TLS_REMOTE_MODE_COL_VALUE, TLS_REMOTE_MODE_NONE,
+                           -1);
+
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter,
+                           TLS_REMOTE_MODE_COL_NAME, _("Verify whole subject exactly"),
+                           TLS_REMOTE_MODE_COL_VALUE, TLS_REMOTE_MODE_SUBJECT,
+                           -1);
+
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter,
+                           TLS_REMOTE_MODE_COL_NAME, _("Verify name exactly"),
+                           TLS_REMOTE_MODE_COL_VALUE, TLS_REMOTE_MODE_NAME,
+                           -1);
+
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter,
+                           TLS_REMOTE_MODE_COL_NAME, _("Verify name by prefix"),
+                           TLS_REMOTE_MODE_COL_VALUE, TLS_REMOTE_MODE_NAME_PREFIX,
+                           -1);
+
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter,
+                           TLS_REMOTE_MODE_COL_NAME, _("Verify subject partially (legacy mode, strongly 
discouraged)"),
+                           TLS_REMOTE_MODE_COL_VALUE, TLS_REMOTE_MODE_LEGACY,
+                           -1);
+
+       if (x509_name && strlen (x509_name)) {
+               if (g_str_has_prefix (x509_name, "name:"))
+                       gtk_combo_box_set_active (box, 2);
+               else if (g_str_has_prefix (x509_name, "name-prefix:"))
+                       gtk_combo_box_set_active (box, 3);
+               else
+                       gtk_combo_box_set_active (box, 1);
+
+               subject_name = strchr (x509_name, ':');
+               if (subject_name)
+                       subject_name++;
+               else
+                       subject_name = x509_name;
+       } else if (tls_remote && strlen (tls_remote)) {
+               gtk_combo_box_set_active (box, 4);
+
+               subject_name = tls_remote;
+       } else {
+               gtk_combo_box_set_active (box, 0);
+
+               subject_name = "";
+       }
+
+       gtk_entry_set_text (entry, subject_name);
+
+    g_object_unref (store);
+}
+
+static void
+tls_remote_changed (GtkWidget *widget, gpointer user_data)
+{
+       GtkBuilder *builder = (GtkBuilder *) user_data;
+       GtkWidget *entry, *combo, *ok_button;
+       GtkTreeIter iter;
+       gboolean entry_enabled = TRUE, entry_has_error = FALSE;
+       gboolean legacy_tls_remote = FALSE;
+
+       entry     = GTK_WIDGET (gtk_builder_get_object (builder, "tls_remote_entry"));
+       combo     = GTK_WIDGET (gtk_builder_get_object (builder, "tls_remote_mode_combo"));
+       ok_button = GTK_WIDGET (gtk_builder_get_object (builder, "ok_button"));
+
+       if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter)) {
+               gs_free char *tls_remote_mode = NULL;
+               GtkTreeModel *combo_model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
+
+               gtk_tree_model_get (combo_model, &iter, TLS_REMOTE_MODE_COL_VALUE, &tls_remote_mode, -1);
+               g_return_if_fail (tls_remote_mode);
+
+               /* If a mode of 'none' is selected, disable the subject entry control.
+                  Otherwise, enable the entry, and set up it's error state based on
+                  whether it is empty or not (it should not be). */
+               if (!strcmp (tls_remote_mode, TLS_REMOTE_MODE_NONE)) {
+                       entry_enabled = FALSE;
+               } else {
+                       const char *subject = gtk_entry_get_text (GTK_ENTRY (entry));
+
+                       entry_enabled = TRUE;
+                       entry_has_error = !subject || !subject[0];
+                       legacy_tls_remote = nm_streq (tls_remote_mode, TLS_REMOTE_MODE_LEGACY);
+               }
+       }
+
+       gtk_widget_set_sensitive (entry, entry_enabled);
+       if(entry_has_error) {
+               widget_set_error (entry);
+               gtk_widget_set_sensitive (ok_button, FALSE);
+       } else {
+               if (legacy_tls_remote) {
+                       /* selecting tls-remote is not an error, but strongly discouraged. I wish
+                        * there would be a warning-class as well. Anyway, mark the widget as
+                        * erroneous, although this doesn't make the connection invalid (which
+                        * is an ugly inconsistency). */
+                       widget_set_error (entry);
+               } else
+                       widget_unset_error (entry);
+               gtk_widget_set_sensitive (ok_button, TRUE);
+       }
+
+}
+
+static void
+remote_tls_cert_toggled_cb (GtkWidget *widget, gpointer user_data)
+{
+       GtkBuilder *builder = (GtkBuilder *) user_data;
+       gboolean use_remote_cert_tls = FALSE;
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_cert_tls_checkbutton"));
+       use_remote_cert_tls = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_cert_tls_label"));
+       gtk_widget_set_sensitive (widget, use_remote_cert_tls);
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_cert_tls_combo"));
+       gtk_widget_set_sensitive (widget, use_remote_cert_tls);
+}
+
+#define REMOTE_CERT_COL_NAME 0
+#define REMOTE_CERT_COL_VALUE 1
+
+static void
+populate_remote_cert_tls_combo (GtkComboBox *box, const char *remote_cert)
+{
+       GtkListStore *store;
+       GtkTreeIter iter;
+
+       store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
+       gtk_combo_box_set_model (box, GTK_TREE_MODEL (store));
+
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter,
+                           REMOTE_CERT_COL_NAME, _("Server"),
+                           REMOTE_CERT_COL_VALUE, NM_OPENVPN_REM_CERT_TLS_SERVER,
+                           -1);
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter,
+                           REMOTE_CERT_COL_NAME, _("Client"),
+                           REMOTE_CERT_COL_VALUE, NM_OPENVPN_REM_CERT_TLS_CLIENT,
+                           -1);
+
+       if (g_strcmp0 (remote_cert, NM_OPENVPN_REM_CERT_TLS_CLIENT) == 0)
+               gtk_combo_box_set_active (box, 1);
+       else
+               gtk_combo_box_set_active (box, 0);
+
+       g_object_unref (store);
+}
+
+#define TLS_AUTH_MODE_NONE  0
+#define TLS_AUTH_MODE_AUTH  1
+#define TLS_AUTH_MODE_CRYPT 2
+
+static void
+tls_auth_toggled_cb (GtkWidget *widget, gpointer user_data)
+{
+       GtkBuilder *builder = (GtkBuilder *) user_data;
+       gint active;
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "tls_auth_mode"));
+       active = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "direction_label"));
+       gtk_widget_set_sensitive (widget, active == TLS_AUTH_MODE_AUTH);
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "direction_combo"));
+       gtk_widget_set_sensitive (widget, active == TLS_AUTH_MODE_AUTH);
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "tls_auth_label"));
+       gtk_widget_set_sensitive (widget, active != TLS_AUTH_MODE_NONE);
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "tls_auth_chooser"));
+       gtk_widget_set_sensitive (widget, active != TLS_AUTH_MODE_NONE);
+}
+
+static void
+ns_cert_type_toggled_cb (GtkWidget *widget, gpointer user_data)
+{
+       GtkBuilder *builder = (GtkBuilder *) user_data;
+       gboolean use_ns_cert_type = FALSE;
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "ns_cert_type_checkbutton"));
+       use_ns_cert_type = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "ns_cert_type_label"));
+       gtk_widget_set_sensitive (widget, use_ns_cert_type);
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "ns_cert_type_combo"));
+       gtk_widget_set_sensitive (widget, use_ns_cert_type);
+}
+
+#define NS_CERT_TYPE_COL_NAME 0
+#define NS_CERT_TYPE_COL_VALUE 1
+
+static void
+populate_ns_cert_type_combo (GtkComboBox *box, const char *type)
+{
+       GtkListStore *store;
+       GtkTreeIter iter;
+
+       store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
+       gtk_combo_box_set_model (box, GTK_TREE_MODEL (store));
+
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter,
+                           NS_CERT_TYPE_COL_NAME, _("Server"),
+                           NS_CERT_TYPE_COL_VALUE, NM_OPENVPN_NS_CERT_TYPE_SERVER,
+                           -1);
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter,
+                           NS_CERT_TYPE_COL_NAME, _("Client"),
+                           NS_CERT_TYPE_COL_VALUE, NM_OPENVPN_NS_CERT_TYPE_CLIENT,
+                           -1);
+
+       if (g_strcmp0 (type, NM_OPENVPN_NS_CERT_TYPE_CLIENT) == 0)
+               gtk_combo_box_set_active (box, 1);
+       else
+               gtk_combo_box_set_active (box, 0);
+
+       g_object_unref (store);
+}
+
+static void
+mtu_disc_toggled_cb (GtkWidget *widget, gpointer user_data)
+{
+       GtkBuilder *builder = (GtkBuilder *) user_data;
+       gboolean use_mtu_disc;
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "mtu_disc_checkbutton"));
+       use_mtu_disc = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "mtu_disc_combo"));
+       gtk_widget_set_sensitive (widget, use_mtu_disc);
+}
+
+#define PROXY_TYPE_NONE  0
+#define PROXY_TYPE_HTTP  1
+#define PROXY_TYPE_SOCKS 2
+
+#define DEVICE_TYPE_IDX_TUN     0
+#define DEVICE_TYPE_IDX_TAP     1
+
+#define PING_EXIT    0
+#define PING_RESTART 1
+
+static void
+proxy_type_changed (GtkComboBox *combo, gpointer user_data)
+{
+       GtkBuilder *builder = GTK_BUILDER (user_data);
+       gboolean sensitive;
+       GtkWidget *widget;
+       guint32 i = 0;
+       int active;
+       const char *widgets[] = {
+               "proxy_desc_label", "proxy_server_label", "proxy_server_entry",
+               "proxy_port_label", "proxy_port_spinbutton", "proxy_retry_checkbutton",
+               "proxy_username_label", "proxy_password_label", "proxy_username_entry",
+               "proxy_password_entry", "show_proxy_password", NULL
+       };
+       const char *user_pass_widgets[] = {
+               "proxy_username_label", "proxy_password_label", "proxy_username_entry",
+               "proxy_password_entry", "show_proxy_password", NULL
+       };
+
+       active = gtk_combo_box_get_active (combo);
+       sensitive = (active > PROXY_TYPE_NONE);
+
+       while (widgets[i]) {
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, widgets[i++]));
+               gtk_widget_set_sensitive (widget, sensitive);
+       }
+
+       /* Additionally user/pass widgets need to be disabled for SOCKS */
+       if (active == PROXY_TYPE_SOCKS) {
+               i = 0;
+               while (user_pass_widgets[i]) {
+                       widget = GTK_WIDGET (gtk_builder_get_object (builder, user_pass_widgets[i++]));
+                       gtk_widget_set_sensitive (widget, FALSE);
+               }
+       }
+
+       /* Proxy options require TCP; but don't reset the TCP checkbutton
+        * to false when the user disables HTTP proxy; leave it checked.
+        */
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "tcp_checkbutton"));
+       if (sensitive == TRUE)
+               gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
+       gtk_widget_set_sensitive (widget, !sensitive);
+}
+
+static void
+show_proxy_password_toggled_cb (GtkCheckButton *button, gpointer user_data)
+{
+       GtkBuilder *builder = (GtkBuilder *) user_data;
+       GtkWidget *widget;
+       gboolean visible;
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "proxy_password_entry"));
+       g_assert (widget);
+
+       visible = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+       gtk_entry_set_visibility (GTK_ENTRY (widget), visible);
+}
+
+static void
+device_name_filter_cb (GtkEntry *entry,
+                       const gchar *text,
+                       gint length,
+                       gint *position,
+                       void *user_data)
+{
+       int i, count = 0;
+       gchar *result = g_new (gchar, length + 1);
+       GtkEditable *editable = GTK_EDITABLE (entry);
+
+       for (i = 0; i < length; i++) {
+               if (text[i] == '/' || g_ascii_isspace (text[i]))
+                       continue;
+               result[count++] = text[i];
+       }
+       result[count] = 0;
+
+       if (count > 0) {
+               g_signal_handlers_block_by_func (G_OBJECT (editable),
+                                                G_CALLBACK (device_name_filter_cb),
+                                                user_data);
+               gtk_editable_insert_text (editable, result, count, position);
+               g_signal_handlers_unblock_by_func (G_OBJECT (editable),
+                                                  G_CALLBACK (device_name_filter_cb),
+                                                  user_data);
+       }
+       g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
+
+       g_free (result);
+}
+
+static gboolean
+device_name_changed_cb (GtkEntry *entry,
+                        gpointer user_data)
+{
+       GtkEditable *editable = GTK_EDITABLE (entry);
+       GtkWidget *ok_button = user_data;
+       gboolean entry_sensitive;
+       char *entry_text;
+
+       entry_sensitive = gtk_widget_get_sensitive (GTK_WIDGET (entry));
+       entry_text = gtk_editable_get_chars (editable, 0, -1);
+
+       /* Change cell's background to red if the value is invalid */
+       if (   entry_sensitive
+           && entry_text[0] != '\0'
+           && !_nm_utils_is_valid_iface_name (entry_text)) {
+               widget_set_error (GTK_WIDGET (editable));
+               gtk_widget_set_sensitive (ok_button, FALSE);
+       } else {
+               widget_unset_error (GTK_WIDGET (editable));
+               gtk_widget_set_sensitive (ok_button, TRUE);
+       }
+
+       g_free (entry_text);
+       return FALSE;
+}
+
+static void
+dev_checkbox_toggled_cb (GtkWidget *check, gpointer user_data)
+{
+       GtkBuilder *builder = (GtkBuilder *) user_data;
+       GtkWidget *combo, *entry, *ok_button;
+
+       combo = GTK_WIDGET (gtk_builder_get_object (builder, "dev_type_combo"));
+       entry = GTK_WIDGET (gtk_builder_get_object (builder, "dev_entry"));
+       ok_button = GTK_WIDGET (gtk_builder_get_object (builder, "ok_button"));
+
+       /* Set values to default ones */
+       if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check))) {
+               gtk_entry_set_text (GTK_ENTRY (entry), "");
+               gtk_combo_box_set_active (GTK_COMBO_BOX (combo), DEVICE_TYPE_IDX_TUN);
+       }
+
+       checkbox_toggled_update_widget_cb (check, combo);
+       checkbox_toggled_update_widget_cb (check, entry);
+       device_name_changed_cb (GTK_ENTRY (entry), ok_button);
+}
+
+static gboolean
+_hash_get_boolean (GHashTable *hash,
+                   const char *key)
+{
+       const char *value;
+
+       nm_assert (hash);
+       nm_assert (key && key[0]);
+
+       value = g_hash_table_lookup (hash, key);
+
+       return nm_streq0 (value, "yes");
+}
+
+static GtkToggleButton *
+_builder_init_toggle_button (GtkBuilder *builder,
+                             const char *widget_name,
+                             gboolean active_state)
+{
+       GtkToggleButton *widget;
+
+       widget = (GtkToggleButton *) gtk_builder_get_object (builder, widget_name);
+       g_return_val_if_fail (GTK_IS_TOGGLE_BUTTON (widget), NULL);
+
+       gtk_toggle_button_set_active (widget, active_state);
+       return widget;
+}
+
+static void
+_builder_init_optional_spinbutton (GtkBuilder *builder,
+                                   const char *checkbutton_name,
+                                   const char *spinbutton_name,
+                                   gboolean active_state,
+                                   gint64 value)
+{
+       GtkWidget *widget;
+       GtkWidget *spin;
+
+       widget = (GtkWidget *) gtk_builder_get_object (builder, checkbutton_name);
+       g_return_if_fail (GTK_IS_TOGGLE_BUTTON (widget));
+
+       spin = (GtkWidget *) gtk_builder_get_object (builder, spinbutton_name);
+       g_return_if_fail (GTK_IS_SPIN_BUTTON (spin));
+
+       g_signal_connect ((GObject *) widget, "toggled", G_CALLBACK (checkbox_toggled_update_widget_cb), 
spin);
+
+       gtk_spin_button_set_value ((GtkSpinButton *) spin, (double) value);
+
+       gtk_widget_set_sensitive (spin, active_state);
+       gtk_toggle_button_set_active ((GtkToggleButton *) widget, active_state);
+}
+
+static void
+ping_exit_restart_checkbox_toggled_cb (GtkWidget *check, gpointer user_data)
+{
+       GtkBuilder *builder = (GtkBuilder *) user_data;
+       GtkWidget *combo, *spin;
+
+       combo = GTK_WIDGET (gtk_builder_get_object (builder, "ping_exit_restart_combo"));
+       spin = GTK_WIDGET (gtk_builder_get_object (builder, "ping_exit_restart_spinbutton"));
+
+       checkbox_toggled_update_widget_cb (check, combo);
+       checkbox_toggled_update_widget_cb (check, spin);
+}
+
+#define TA_DIR_COL_NAME 0
+#define TA_DIR_COL_NUM 1
+
+static GtkWidget *
+advanced_dialog_new (GHashTable *hash, const char *contype)
+{
+       GtkBuilder *builder;
+       GtkWidget *dialog = NULL;
+       GtkWidget *widget, *combo, *spin, *entry, *ok_button;
+       const char *value, *value2;
+       const char *dev, *dev_type, *tap_dev;
+       GtkListStore *store;
+       GtkTreeIter iter;
+       guint i;
+       guint32 active;
+       guint32 pw_flags = NM_SETTING_SECRET_FLAG_NONE;
+       GError *error = NULL;
+
+       g_return_val_if_fail (hash != NULL, NULL);
+
+       builder = gtk_builder_new ();
+
+       gtk_builder_set_translation_domain (builder, GETTEXT_PACKAGE);
+
+       if (!gtk_builder_add_from_resource (builder, 
"/org/freedesktop/network-manager-openvpn/nm-openvpn-dialog.ui", &error)) {
+               g_error_free (error);
+               g_object_unref (G_OBJECT (builder));
+               g_return_val_if_reached (NULL);
+       }
+
+       dialog = GTK_WIDGET (gtk_builder_get_object (builder, "openvpn-advanced-dialog"));
+       if (!dialog) {
+               g_object_unref (G_OBJECT (builder));
+               g_return_val_if_reached (NULL);
+       }
+       gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+
+       g_object_set_data_full (G_OBJECT (dialog), "builder",
+                               builder, (GDestroyNotify) g_object_unref);
+       g_object_set_data (G_OBJECT (dialog), "connection-type", GINT_TO_POINTER (contype));
+
+       ok_button = GTK_WIDGET (gtk_builder_get_object (builder, "ok_button"));
+
+
+       value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_RENEG_SECONDS);
+       _builder_init_optional_spinbutton (builder, "reneg_checkbutton", "reneg_spinbutton", !!value,
+                                          _nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXINT, 0));
+
+
+       /* Proxy support */
+       combo = GTK_WIDGET (gtk_builder_get_object (builder, "proxy_type_combo"));
+
+       store = gtk_list_store_new (1, G_TYPE_STRING);
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter, 0, _("Not required"), -1);
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter, 0, _("HTTP"), -1);
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter, 0, _("SOCKS"), -1);
+
+       value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_PROXY_SERVER);
+       value2 = g_hash_table_lookup (hash, NM_OPENVPN_KEY_PROXY_PORT);
+       if (value && strlen (value) && value2 && strlen (value2)) {
+               long int tmp = 0;
+
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "proxy_server_entry"));
+               gtk_entry_set_text (GTK_ENTRY (widget), value);
+
+               errno = 0;
+               tmp = strtol (value2, NULL, 10);
+               if (errno != 0 || tmp < 0 || tmp > 65535)
+                       tmp = 0;
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "proxy_port_spinbutton"));
+               gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), (gdouble) tmp);
+
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "proxy_retry_checkbutton"));
+               value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_PROXY_RETRY);
+               if (value && !strcmp (value, "yes"))
+                       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
+
+               value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_HTTP_PROXY_USERNAME);
+               if (value && strlen (value)) {
+                       widget = GTK_WIDGET (gtk_builder_get_object (builder, "proxy_username_entry"));
+                       gtk_entry_set_text (GTK_ENTRY (widget), value);
+               }
+
+               value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD);
+               if (value && strlen (value)) {
+                       widget = GTK_WIDGET (gtk_builder_get_object (builder, "proxy_password_entry"));
+                       gtk_entry_set_text (GTK_ENTRY (widget), value);
+               }
+
+               value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD"-flags");
+               if (value && strlen (value)) {
+                       errno = 0;
+                       tmp = strtol (value, NULL, 10);
+                       if (errno != 0 || tmp < 0 || tmp > 65535)
+                               tmp = 0;
+                       pw_flags = (guint32) tmp;
+               }
+       }
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "proxy_password_entry"));
+       nma_utils_setup_password_storage (widget, pw_flags, NULL, NULL,
+                                         TRUE, FALSE);
+
+       value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_PROXY_TYPE);
+       active = PROXY_TYPE_NONE;
+       if (value) {
+               if (!strcmp (value, "http"))
+                       active = PROXY_TYPE_HTTP;
+               else if (!strcmp (value, "socks"))
+                       active = PROXY_TYPE_SOCKS;
+       }
+
+       gtk_combo_box_set_model (GTK_COMBO_BOX (combo), GTK_TREE_MODEL (store));
+       g_object_unref (store);
+       gtk_combo_box_set_active (GTK_COMBO_BOX (combo), active);
+       proxy_type_changed (GTK_COMBO_BOX (combo), builder);
+       g_signal_connect (G_OBJECT (combo), "changed", G_CALLBACK (proxy_type_changed), builder);
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "show_proxy_password"));
+       g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (show_proxy_password_toggled_cb), builder);
+
+
+       value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_PORT);
+       _builder_init_optional_spinbutton (builder, "port_checkbutton", "port_spinbutton", !!value,
+                                          _nm_utils_ascii_str_to_int64 (value, 10, 1, 65535, 1194));
+
+
+       value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_TUNNEL_MTU);
+       _builder_init_optional_spinbutton (builder, "tunmtu_checkbutton", "tunmtu_spinbutton", !!value,
+                                          _nm_utils_ascii_str_to_int64 (value, 10, 1, 65535, 1500));
+
+
+       value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_FRAGMENT_SIZE);
+       _builder_init_optional_spinbutton (builder, "fragment_checkbutton", "fragment_spinbutton", !!value,
+                                          _nm_utils_ascii_str_to_int64 (value, 10, 0, 65535, 1300));
+
+
+       value = comp_lzo_values_conf_coerce (g_hash_table_lookup (hash, NM_OPENVPN_KEY_COMP_LZO));
+       widget = GTK_WIDGET (_builder_init_toggle_button (builder, "lzo_checkbutton", value != NULL));
+       combo = GTK_WIDGET (gtk_builder_get_object (builder, "lzo_combo"));
+       store = gtk_list_store_new (1, G_TYPE_STRING);
+       active = 0;
+       for (i = 0; i < G_N_ELEMENTS (comp_lzo_values); i++) {
+               gtk_list_store_append (store, &iter);
+               gtk_list_store_set (store, &iter,
+                                   0, comp_lzo_values_conf_to_display (comp_lzo_values[i]),
+                                   -1);
+               if (nm_streq (comp_lzo_values[i], value ?: "adaptive"))
+                       active = i;
+       }
+       gtk_combo_box_set_model (GTK_COMBO_BOX (combo), GTK_TREE_MODEL (store));
+       g_object_unref (store);
+       gtk_combo_box_set_active (GTK_COMBO_BOX (combo), active);
+       g_object_bind_property (widget, "active", combo, "sensitive", G_BINDING_SYNC_CREATE);
+
+       _builder_init_toggle_button (builder, "mssfix_checkbutton", _hash_get_boolean (hash, 
NM_OPENVPN_KEY_MSSFIX));
+       _builder_init_toggle_button (builder, "float_checkbutton", _hash_get_boolean (hash, 
NM_OPENVPN_KEY_FLOAT));
+       _builder_init_toggle_button (builder, "tcp_checkbutton", _hash_get_boolean (hash, 
NM_OPENVPN_KEY_PROTO_TCP));
+
+
+       /* Populate device-related widgets */
+       dev =      g_hash_table_lookup (hash, NM_OPENVPN_KEY_DEV);
+       dev_type = g_hash_table_lookup (hash, NM_OPENVPN_KEY_DEV_TYPE);
+       tap_dev =  g_hash_table_lookup (hash, NM_OPENVPN_KEY_TAP_DEV);
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "dev_checkbutton"));
+       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), (dev && *dev) || dev_type || tap_dev);
+       dev_checkbox_toggled_cb (widget, builder);
+       g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (dev_checkbox_toggled_cb), builder);
+       combo = GTK_WIDGET (gtk_builder_get_object (builder, "dev_type_combo"));
+       active = DEVICE_TYPE_IDX_TUN;
+       if (   !g_strcmp0 (dev_type, "tap")
+           || (!dev_type && dev && g_str_has_prefix (dev, "tap"))
+           || (!dev_type && !g_strcmp0 (tap_dev, "yes")))
+               active = DEVICE_TYPE_IDX_TAP;
+
+       store = gtk_list_store_new (1, G_TYPE_STRING);
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter, 0, _("TUN"), -1);
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter, 0, _("TAP"), -1);
+       gtk_combo_box_set_model (GTK_COMBO_BOX (combo), GTK_TREE_MODEL (store));
+       g_object_unref (store);
+       gtk_combo_box_set_active (GTK_COMBO_BOX (combo), active);
+
+       entry = GTK_WIDGET (gtk_builder_get_object (builder, "dev_entry"));
+       gtk_entry_set_max_length (GTK_ENTRY (entry), 15);  /* interface name is max 15 chars */
+       gtk_entry_set_placeholder_text (GTK_ENTRY (entry), _("(automatic)"));
+       g_signal_connect (G_OBJECT (entry), "insert-text", G_CALLBACK (device_name_filter_cb), NULL);
+       g_signal_connect (G_OBJECT (entry), "changed", G_CALLBACK (device_name_changed_cb), ok_button);
+       gtk_entry_set_text (GTK_ENTRY (entry), dev ?: "");
+
+
+       _builder_init_toggle_button (builder, "remote_random_checkbutton", _hash_get_boolean (hash, 
NM_OPENVPN_KEY_REMOTE_RANDOM));
+       _builder_init_toggle_button (builder, "tun_ipv6_checkbutton", _hash_get_boolean (hash, 
NM_OPENVPN_KEY_TUN_IPV6));
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "cipher_combo"));
+       value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_CIPHER);
+       populate_cipher_combo (GTK_COMBO_BOX (widget), value);
+
+
+       value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_KEYSIZE);
+       _builder_init_optional_spinbutton (builder, "keysize_checkbutton", "keysize_spinbutton", !!value,
+                                          _nm_utils_ascii_str_to_int64 (value, 10, 1, 65535, 128));
+
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "hmacauth_combo"));
+       value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_AUTH);
+       populate_hmacauth_combo (GTK_COMBO_BOX (widget), value);
+
+       entry = GTK_WIDGET (gtk_builder_get_object (builder, "tls_remote_entry"));
+       combo = GTK_WIDGET (gtk_builder_get_object (builder, "tls_remote_mode_combo"));
+       populate_tls_remote_mode_entry_combo (GTK_ENTRY (entry), GTK_COMBO_BOX (combo),
+                                             g_hash_table_lookup (hash, NM_OPENVPN_KEY_TLS_REMOTE),
+                                             g_hash_table_lookup (hash, NM_OPENVPN_KEY_VERIFY_X509_NAME));
+       g_signal_connect (G_OBJECT (entry), "changed", G_CALLBACK (tls_remote_changed), builder);
+       g_signal_connect (G_OBJECT (combo), "changed", G_CALLBACK (tls_remote_changed), builder);
+       tls_remote_changed (entry, builder);
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_cert_tls_checkbutton"));
+       value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_REMOTE_CERT_TLS);
+       if (value && strlen (value))
+               gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
+       g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (remote_tls_cert_toggled_cb), builder);
+       remote_tls_cert_toggled_cb (widget, builder);
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_cert_tls_combo"));
+       value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_REMOTE_CERT_TLS);
+       populate_remote_cert_tls_combo (GTK_COMBO_BOX (widget), value);
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "ns_cert_type_checkbutton"));
+       value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_NS_CERT_TYPE);
+       if (value && strlen (value))
+               gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
+       g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (ns_cert_type_toggled_cb), builder);
+       ns_cert_type_toggled_cb (widget, builder);
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "ns_cert_type_combo"));
+       value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_NS_CERT_TYPE);
+       populate_ns_cert_type_combo (GTK_COMBO_BOX (widget), value);
+
+       if (NM_IN_STRSET (contype,
+                         NM_OPENVPN_CONTYPE_TLS,
+                         NM_OPENVPN_CONTYPE_PASSWORD_TLS,
+                         NM_OPENVPN_CONTYPE_PASSWORD)) {
+               int direction = -1;
+
+               /* Initialize direction combo */
+               combo = GTK_WIDGET (gtk_builder_get_object (builder, "direction_combo"));
+               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);
+               gtk_list_store_append (store, &iter);
+               gtk_list_store_set (store, &iter, TA_DIR_COL_NAME, "1", TA_DIR_COL_NUM, 1, -1);
+               gtk_combo_box_set_model (GTK_COMBO_BOX (combo), GTK_TREE_MODEL (store));
+               g_object_unref (store);
+               gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
+
+               combo = GTK_WIDGET (gtk_builder_get_object (builder, "tls_auth_mode"));
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "tls_auth_chooser"));
+               value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_TA);
+               value2 = g_hash_table_lookup (hash, NM_OPENVPN_KEY_TLS_CRYPT);
+               if (value2 && value2[0]) {
+                       gtk_combo_box_set_active (GTK_COMBO_BOX (combo), TLS_AUTH_MODE_CRYPT);
+                       gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), value2);
+               } else if (value && value[0]) {
+                       gtk_combo_box_set_active (GTK_COMBO_BOX (combo), TLS_AUTH_MODE_AUTH);
+                       gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), value);
+                       value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_TA_DIR);
+                       if (value && value[0]) {
+                               direction = (int) strtol (value, NULL, 10);
+                               /* If direction is not 0 or 1, use no direction */
+                               if (direction != 0 && direction != 1)
+                                       direction = -1;
+                       }
+                       widget = GTK_WIDGET (gtk_builder_get_object (builder, "direction_combo"));
+                       gtk_combo_box_set_active (GTK_COMBO_BOX (widget), direction + 1);
+               } else
+                       gtk_combo_box_set_active (GTK_COMBO_BOX (combo), TLS_AUTH_MODE_NONE);
+
+               g_signal_connect (G_OBJECT (combo), "changed", G_CALLBACK (tls_auth_toggled_cb), builder);
+               tls_auth_toggled_cb (combo, builder);
+       } else {
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "options_notebook"));
+               gtk_notebook_remove_page (GTK_NOTEBOOK (widget), 2);
+       }
+
+
+       value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_PING);
+       _builder_init_optional_spinbutton (builder, "ping_checkbutton", "ping_spinbutton", !!value,
+                                          _nm_utils_ascii_str_to_int64 (value, 10, 1, 65535, 30));
+
+
+       /* ping-exit / ping-restart */
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "ping_exit_restart_checkbutton"));
+       spin = GTK_WIDGET (gtk_builder_get_object (builder, "ping_exit_restart_spinbutton"));
+       combo = GTK_WIDGET (gtk_builder_get_object (builder, "ping_exit_restart_combo"));
+       g_signal_connect ((GObject *) widget, "toggled", G_CALLBACK (ping_exit_restart_checkbox_toggled_cb), 
builder);
+
+       value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_PING_EXIT);
+       active = PING_EXIT;
+       if (!value) {
+               value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_PING_RESTART);
+               if (value)
+                       active = PING_RESTART;
+       }
+
+       store = gtk_list_store_new (1, G_TYPE_STRING);
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter, 0, _("ping-exit"), -1);
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter, 0, _("ping-restart"), -1);
+       gtk_combo_box_set_model (GTK_COMBO_BOX (combo), GTK_TREE_MODEL (store));
+       g_object_unref (store);
+       gtk_combo_box_set_active ((GtkComboBox *) combo, active);
+
+       gtk_spin_button_set_value ((GtkSpinButton *) spin,
+                                  (double) _nm_utils_ascii_str_to_int64 (value, 10, 1, 65535, 30));
+       gtk_widget_set_sensitive (combo, !!value);
+       gtk_widget_set_sensitive (spin, !!value);
+       gtk_toggle_button_set_active ((GtkToggleButton *) widget, !!value);
+
+       /* MTU discovery */
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "mtu_disc_checkbutton"));
+       value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_MTU_DISC);
+       if (value && value[0]) {
+               gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
+               combo = GTK_WIDGET (gtk_builder_get_object (builder, "mtu_disc_combo"));
+               if (nm_streq (value, "maybe"))
+                       gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 1);
+               else if (nm_streq (value, "yes"))
+                       gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 2);
+               else
+                       gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
+       }
+       g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (mtu_disc_toggled_cb), builder);
+       mtu_disc_toggled_cb (widget, builder);
+
+       value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_MAX_ROUTES);
+       _builder_init_optional_spinbutton (builder, "max_routes_checkbutton", "max_routes_spinbutton", 
!!value,
+                                          _nm_utils_ascii_str_to_int64 (value, 10, 0, 100000000, 100));
+
+       return dialog;
+}
+
+static GHashTable *
+advanced_dialog_new_hash_from_dialog (GtkWidget *dialog, GError **error)
+{
+       GHashTable *hash;
+       GtkWidget *widget, *entry, *combo;
+       GtkBuilder *builder;
+       const char *contype = NULL;
+       const char *value;
+       int active;
+       int proxy_type = PROXY_TYPE_NONE;
+       GtkTreeModel *model;
+       GtkTreeIter iter;
+
+       g_return_val_if_fail (dialog != NULL, NULL);
+       if (error)
+               g_return_val_if_fail (*error == NULL, NULL);
+
+       builder = g_object_get_data (G_OBJECT (dialog), "builder");
+       g_return_val_if_fail (builder != NULL, NULL);
+
+       hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "reneg_checkbutton"));
+       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
+               int reneg_seconds;
+
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "reneg_spinbutton"));
+               reneg_seconds = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (widget));
+               g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_RENEG_SECONDS), g_strdup_printf ("%d", 
reneg_seconds));
+       }
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "tunmtu_checkbutton"));
+       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
+               int tunmtu_size;
+
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "tunmtu_spinbutton"));
+               tunmtu_size = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (widget));
+               g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_TUNNEL_MTU), g_strdup_printf ("%d", 
tunmtu_size));
+       }
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "fragment_checkbutton"));
+       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
+               int fragment_size;
+
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "fragment_spinbutton"));
+               fragment_size = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (widget));
+               g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_FRAGMENT_SIZE), g_strdup_printf ("%d", 
fragment_size));
+       }
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "port_checkbutton"));
+       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
+               int port;
+
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "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), g_strdup_printf ("%d", port));
+       }
+
+       /* Proxy support */
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "proxy_type_combo"));
+       proxy_type = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
+       if (proxy_type != PROXY_TYPE_NONE) {
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "proxy_server_entry"));
+               value = (char *) gtk_entry_get_text (GTK_ENTRY (widget));
+               if (value && strlen (value)) {
+                       int proxy_port;
+
+                       if (proxy_type == PROXY_TYPE_HTTP)
+                               g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_PROXY_TYPE), g_strdup 
("http"));
+                       else if (proxy_type == PROXY_TYPE_SOCKS)
+                               g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_PROXY_TYPE), g_strdup 
("socks"));
+
+                       g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_PROXY_SERVER), g_strdup (value));
+
+                       widget = GTK_WIDGET (gtk_builder_get_object (builder, "proxy_port_spinbutton"));
+                       proxy_port = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (widget));
+                       if (proxy_port > 0) {
+                               g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_PROXY_PORT),
+                                                    g_strdup_printf ("%d", proxy_port));
+                       }
+
+                       widget = GTK_WIDGET (gtk_builder_get_object (builder, "proxy_retry_checkbutton"));
+                       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
+                               g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_PROXY_RETRY), g_strdup 
("yes"));
+
+                       if (proxy_type == PROXY_TYPE_HTTP) {
+                               guint32 pw_flags;
+
+                               widget = GTK_WIDGET (gtk_builder_get_object (builder, 
"proxy_username_entry"));
+                               value = (char *) gtk_entry_get_text (GTK_ENTRY (widget));
+                               if (value && strlen (value)) {
+                                       g_hash_table_insert (hash,
+                                                            g_strdup (NM_OPENVPN_KEY_HTTP_PROXY_USERNAME),
+                                                            g_strdup (value));
+                               }
+
+                               widget = GTK_WIDGET (gtk_builder_get_object (builder, 
"proxy_password_entry"));
+                               value = (char *) gtk_entry_get_text (GTK_ENTRY (widget));
+                               if (value && strlen (value)) {
+                                       g_hash_table_insert (hash,
+                                                            g_strdup (NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD),
+                                                            g_strdup (value));
+                               }
+
+                               pw_flags = nma_utils_menu_to_secret_flags (widget);
+                               if (pw_flags != NM_SETTING_SECRET_FLAG_NONE) {
+                                       g_hash_table_insert (hash,
+                                                            g_strdup 
(NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD"-flags"),
+                                                            g_strdup_printf ("%d", pw_flags));
+                               }
+                       }
+               }
+       }
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "lzo_checkbutton"));
+       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
+               combo = GTK_WIDGET (gtk_builder_get_object (builder, "lzo_combo"));
+               active = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
+               if (active >= 0 && active < G_N_ELEMENTS (comp_lzo_values))
+                       g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_COMP_LZO), g_strdup 
(comp_lzo_values[active]));
+       }
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "mssfix_checkbutton"));
+       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
+               g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_MSSFIX), g_strdup ("yes"));
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "float_checkbutton"));
+       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
+               g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_FLOAT), g_strdup ("yes"));
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "tcp_checkbutton"));
+       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
+               g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_PROTO_TCP), g_strdup ("yes"));
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "dev_checkbutton"));
+       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
+               int device_type;
+
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "dev_type_combo"));
+               device_type = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
+               g_hash_table_insert (hash,
+                                    g_strdup (NM_OPENVPN_KEY_DEV_TYPE),
+                                    g_strdup (device_type == DEVICE_TYPE_IDX_TUN ? "tun" : "tap"));
+
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "dev_entry"));
+               value = gtk_entry_get_text (GTK_ENTRY (widget));
+               if (value && value[0] != '\0')
+                       g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_DEV), g_strdup (value));
+       }
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_random_checkbutton"));
+       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
+               g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_REMOTE_RANDOM), g_strdup ("yes"));
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "tun_ipv6_checkbutton"));
+       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
+               g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_TUN_IPV6), g_strdup ("yes"));
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "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), g_strdup (cipher));
+               }
+       }
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "keysize_checkbutton"));
+       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
+               int keysize_val;
+
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "keysize_spinbutton"));
+               keysize_val = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (widget));
+               g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_KEYSIZE), g_strdup_printf ("%d", 
keysize_val));
+       }
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "hmacauth_combo"));
+       model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+       if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter)) {
+               char *hmacauth = NULL;
+               gboolean is_default = TRUE;
+
+               gtk_tree_model_get (model, &iter,
+                                   HMACAUTH_COL_VALUE, &hmacauth,
+                                   HMACAUTH_COL_DEFAULT, &is_default, -1);
+               if (!is_default && hmacauth) {
+                       g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_AUTH), g_strdup (hmacauth));
+               }
+       }
+
+       contype = g_object_get_data (G_OBJECT (dialog), "connection-type");
+       if (   !strcmp (contype, NM_OPENVPN_CONTYPE_TLS)
+           || !strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD_TLS)
+           || !strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD)) {
+               char *filename;
+
+               entry = GTK_WIDGET (gtk_builder_get_object (builder, "tls_remote_entry"));
+               value = gtk_entry_get_text (GTK_ENTRY (entry));
+
+               combo = GTK_WIDGET (gtk_builder_get_object (builder, "tls_remote_mode_combo"));
+               model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
+
+               if (value && strlen (value) && gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter)) {
+                       gs_free char *tls_remote_mode = NULL;
+                       gtk_tree_model_get (model, &iter, TLS_REMOTE_MODE_COL_VALUE, &tls_remote_mode, -1);
+
+                       if (!g_strcmp0 (tls_remote_mode, TLS_REMOTE_MODE_NONE)) {
+                               // pass
+                       } else if (!g_strcmp0 (tls_remote_mode, TLS_REMOTE_MODE_LEGACY)) {
+                               g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_TLS_REMOTE), 
g_strdup(value));
+                       } else {
+                               char *x509_name = g_strdup_printf ("%s:%s", tls_remote_mode, value);
+                               g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_VERIFY_X509_NAME), 
x509_name);
+                       }
+               }
+
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_cert_tls_checkbutton"));
+               if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
+                       widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_cert_tls_combo"));
+                       model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+                       if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter)) {
+                               char *remote_cert = NULL;
+
+                               gtk_tree_model_get (model, &iter, REMOTE_CERT_COL_VALUE, &remote_cert, -1);
+                               if (remote_cert)
+                                       g_hash_table_insert (hash,
+                                                            g_strdup (NM_OPENVPN_KEY_REMOTE_CERT_TLS),
+                                                            remote_cert);
+                       }
+               }
+
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "ns_cert_type_checkbutton"));
+               if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
+                       widget = GTK_WIDGET (gtk_builder_get_object (builder, "ns_cert_type_combo"));
+                       model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+                       if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter)) {
+                               char *type = NULL;
+
+                               gtk_tree_model_get (model, &iter, NS_CERT_TYPE_COL_VALUE, &type, -1);
+                               if (type)
+                                       g_hash_table_insert (hash,
+                                                            g_strdup (NM_OPENVPN_KEY_NS_CERT_TYPE),
+                                                            type);
+                       }
+               }
+
+               combo = GTK_WIDGET (gtk_builder_get_object (builder, "tls_auth_mode"));
+               switch (gtk_combo_box_get_active (GTK_COMBO_BOX (combo))) {
+               case TLS_AUTH_MODE_AUTH:
+                       widget = GTK_WIDGET (gtk_builder_get_object (builder, "tls_auth_chooser"));
+                       filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+                       if (filename && filename[0])
+                               g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_TA), g_strdup (filename));
+                       g_free (filename);
+
+                       widget = GTK_WIDGET (gtk_builder_get_object (builder, "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) {
+                                       g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_TA_DIR),
+                                                            g_strdup_printf ("%d", direction));
+                               }
+                       }
+                       break;
+               case TLS_AUTH_MODE_CRYPT:
+                       widget = GTK_WIDGET (gtk_builder_get_object (builder, "tls_auth_chooser"));
+                       filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+                       if (filename && filename[0])
+                               g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_TLS_CRYPT), g_strdup 
(filename));
+                       g_free (filename);
+                       break;
+               case TLS_AUTH_MODE_NONE:
+                       break;
+               }
+       }
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "ping_checkbutton"));
+       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
+               int ping_val;
+
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "ping_spinbutton"));
+               ping_val = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (widget));
+
+               g_hash_table_insert (hash,
+                                    g_strdup (NM_OPENVPN_KEY_PING),
+                                    g_strdup_printf ("%d", ping_val));
+       }
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "ping_exit_restart_checkbutton"));
+       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
+               int ping_exit_type, ping_val;
+
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "ping_exit_restart_combo"));
+               ping_exit_type = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
+
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "ping_exit_restart_spinbutton"));
+               ping_val = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (widget));
+
+               g_hash_table_insert (hash,
+                                    ping_exit_type == PING_EXIT ?
+                                      g_strdup (NM_OPENVPN_KEY_PING_EXIT) :
+                                      g_strdup (NM_OPENVPN_KEY_PING_RESTART),
+                                    g_strdup_printf ("%d", ping_val));
+       }
+
+       /* max routes */
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "max_routes_checkbutton"));
+       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
+               int max_routes;
+
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "max_routes_spinbutton"));
+               max_routes = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (widget));
+               g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_MAX_ROUTES), g_strdup_printf ("%d", 
max_routes));
+       }
+
+       /* MTU discovery */
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "mtu_disc_checkbutton"));
+       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
+               char *val = NULL;
+
+               combo = GTK_WIDGET (gtk_builder_get_object (builder, "mtu_disc_combo"));
+               switch (gtk_combo_box_get_active (GTK_COMBO_BOX (combo))) {
+               case 0:
+                       val = "no";
+                       break;
+               case 1:
+                       val = "maybe";
+                       break;
+               case 2:
+                       val = "yes";
+                       break;
+               }
+               if (val) {
+                       g_hash_table_insert (hash,
+                                            g_strdup (NM_OPENVPN_KEY_MTU_DISC),
+                                            g_strdup (val));
+               }
+       }
+
+       return hash;
+}
 
 /*****************************************************************************/
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]