[PATCH nm-openconnect] Generate token_mode dropdown list on the fly

Kevin Cernekee cernekee at gmail.com
Sat Jun 8 14:23:26 EDT 2013


Depending on which software token libraries are installed, this could
include stoken options, TOTP options, both, or neither.  Only show the
user the options that are available on his system.
---
 properties/nm-openconnect-dialog.ui |   21 --------
 properties/nm-openconnect.c         |   97 ++++++++++++++++++++++-------------
 2 files changed, 62 insertions(+), 56 deletions(-)


Or pull from:

git://github.com/cernekee/network-manager-openconnect dynamic-dropdown-v1


diff --git a/properties/nm-openconnect-dialog.ui b/properties/nm-openconnect-dialog.ui
index bc38374..13eb129 100644
--- a/properties/nm-openconnect-dialog.ui
+++ b/properties/nm-openconnect-dialog.ui
@@ -614,7 +614,6 @@
                     <child>
                       <object class="GtkComboBox" id="token_mode">
                         <property name="visible">True</property>
-                        <property name="model">token_mode_list</property>
                         <property name="active">0</property>
                         <child>
                           <object class="GtkCellRendererText" id="renderer"/>
@@ -730,24 +729,4 @@
           </packing>
         </child>
       </object>
-      <object class="GtkListStore" id="token_mode_list">
-        <columns>
-          <!-- column-name legible -->
-          <column type="gchararray"/>
-        </columns>
-        <data>
-          <row>
-            <col id="0" translatable="yes">Disabled</col>
-          </row>
-          <row>
-            <col id="0" translatable="yes">RSA SecurID - read from ~/.stokenrc</col>
-          </row>
-          <row>
-            <col id="0" translatable="yes">RSA SecurID - manually entered</col>
-          </row>
-          <row>
-            <col id="0" translatable="yes">TOTP - manually entered</col>
-          </row>
-        </data>
-      </object>
 </interface>
diff --git a/properties/nm-openconnect.c b/properties/nm-openconnect.c
index 7a60937..aea2f11 100644
--- a/properties/nm-openconnect.c
+++ b/properties/nm-openconnect.c
@@ -32,6 +32,7 @@
 #include <arpa/inet.h>
 #include <errno.h>
 #include <stdlib.h>
+#include <glib.h>
 #include <glib/gi18n-lib.h>
 #include <string.h>
 #include <gtk/gtk.h>
@@ -81,6 +82,12 @@ G_DEFINE_TYPE_EXTENDED (OpenconnectPluginUiWidget, openconnect_plugin_ui_widget,
 						G_IMPLEMENT_INTERFACE (NM_TYPE_VPN_PLUGIN_UI_WIDGET_INTERFACE,
 											   openconnect_plugin_ui_widget_interface_init))
 
+struct token_mode_entry {
+	const char *pref_value;
+	const char *label;
+	gboolean token_secret_editable;
+};
+
 #define OPENCONNECT_PLUGIN_UI_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), OPENCONNECT_TYPE_PLUGIN_UI_WIDGET, OpenconnectPluginUiWidgetPrivate))
 
 typedef struct {
@@ -89,6 +96,7 @@ typedef struct {
 	GtkSizeGroup *group;
 	GtkWindowGroup *window_group;
 	gboolean window_added;
+	GArray *token_mode_list;
 } OpenconnectPluginUiWidgetPrivate;
 
 #define COL_AUTH_NAME 0
@@ -374,6 +382,20 @@ stuff_changed_cb (GtkWidget *widget, gpointer user_data)
 	g_signal_emit_by_name (OPENCONNECT_PLUGIN_UI_WIDGET (user_data), "changed");
 }
 
+static void
+append_token_list_option (OpenconnectPluginUiWidgetPrivate *priv,
+				const char *pref_value,
+				const char *label,
+				gboolean token_secret_editable)
+{
+	struct token_mode_entry e = {
+		.pref_value		= pref_value,
+		.label			= label,
+		.token_secret_editable	= token_secret_editable,
+	};
+	g_array_append_val (priv->token_mode_list, e);
+}
+
 static gboolean
 init_token_ui (OpenconnectPluginUiWidget *self,
 				OpenconnectPluginUiWidgetPrivate *priv,
@@ -381,13 +403,22 @@ init_token_ui (OpenconnectPluginUiWidget *self,
 {
 	GtkWidget *widget;
 	GtkTextBuffer *buffer;
+	GtkListStore *token_mode_list_store;
 	const char *value;
+	int i, active_option;
 
-	/*
-	 * don't advertise software token properties if we can't use them anyway
-	 * TODO: Fix up the dialog accordingly if e.g. stoken is present but oath is missing
-	 */
-	if (!openconnect_has_stoken_support () && !openconnect_has_oath_support ())
+	priv->token_mode_list = g_array_new (FALSE, FALSE, sizeof (struct token_mode_entry));
+
+	append_token_list_option (priv, "disabled", _("Disabled"), FALSE);
+	if (openconnect_has_stoken_support ()) {
+		append_token_list_option (priv, "stokenrc", _("RSA SecurID - read from ~/.stokenrc"), FALSE);
+		append_token_list_option (priv, "manual", _("RSA SecurID - manually entered"), TRUE);
+	}
+	if (openconnect_has_oath_support ())
+		append_token_list_option (priv, "totp", _("TOTP - manually entered"), TRUE);
+
+	/* if "Disabled" is the only option, don't bother rendering the rest of the dialog */
+	if (priv->token_mode_list->len == 1)
 		return TRUE;
 
 	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "token_vbox"));
@@ -398,19 +429,24 @@ init_token_ui (OpenconnectPluginUiWidget *self,
 	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "token_mode"));
 	if (!widget)
 		return FALSE;
-	if (s_vpn) {
-		value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENCONNECT_KEY_TOKEN_MODE);
-		if (value) {
-			if (!strcmp (value, "stokenrc"))
-				gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 1);
-			else if (!strcmp (value, "manual"))
-				gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 2);
-			else if (!strcmp (value, "totp"))
-				gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 3);
-			else
-				gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
-		}
+
+	token_mode_list_store = gtk_list_store_new (1, G_TYPE_STRING);
+	value = s_vpn ? nm_setting_vpn_get_data_item (s_vpn, NM_OPENCONNECT_KEY_TOKEN_MODE) : NULL;
+
+	for (i = 0, active_option = 0; i < priv->token_mode_list->len; i++) {
+		struct token_mode_entry *e =
+			&g_array_index (priv->token_mode_list, struct token_mode_entry, i);
+		GtkTreeIter iter;
+
+		gtk_list_store_append (token_mode_list_store, &iter);
+		gtk_list_store_set (token_mode_list_store, &iter, 0, e->label, -1);
+
+		if (value && !strcmp (value, e->pref_value))
+			active_option = i;
 	}
+	gtk_combo_box_set_model (GTK_COMBO_BOX (widget), GTK_TREE_MODEL (token_mode_list_store));
+	gtk_combo_box_set_active (GTK_COMBO_BOX (widget), active_option);
+
 	g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (stuff_changed_cb), self);
 
 	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "token_secret"));
@@ -554,25 +590,13 @@ update_connection (NMVpnPluginUiWidgetInterface *iface,
 
 	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "token_mode"));
 	idx = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
-	str = NULL;
-	switch (idx) {
-	case 0:
-		str = "disabled";
-		break;
-	case 1:
-		str = "stokenrc";
-		break;
-	case 2:
-		str = "manual";
-		token_secret_editable = TRUE;
-		break;
-	case 3:
-		str = "totp";
-		token_secret_editable = TRUE;
-		break;
+
+	if (idx < priv->token_mode_list->len) {
+		struct token_mode_entry *e =
+			&g_array_index (priv->token_mode_list, struct token_mode_entry, idx);
+		nm_setting_vpn_add_data_item (s_vpn, NM_OPENCONNECT_KEY_TOKEN_MODE, e->pref_value);
+		token_secret_editable = e->token_secret_editable;
 	}
-	if (str)
-		nm_setting_vpn_add_data_item (s_vpn, NM_OPENCONNECT_KEY_TOKEN_MODE, str);
 
 	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "token_secret_label"));
 	gtk_widget_set_sensitive (widget, token_secret_editable);
@@ -702,6 +726,9 @@ dispose (GObject *object)
 	if (priv->builder)
 		g_object_unref (priv->builder);
 
+	if (priv->token_mode_list)
+		g_array_free (priv->token_mode_list, TRUE);
+
 	G_OBJECT_CLASS (openconnect_plugin_ui_widget_parent_class)->dispose (object);
 }
 
-- 
1.7.10.4




More information about the openconnect-devel mailing list