[Gpa-commits] r959 - trunk/src
scm-commit@wald.intevation.org
scm-commit at wald.intevation.org
Wed Mar 4 09:47:51 CET 2009
Author: werner
Date: 2009-03-04 09:47:46 +0100 (Wed, 04 Mar 2009)
New Revision: 959
Added:
trunk/src/membuf.c
trunk/src/membuf.h
Modified:
trunk/src/ChangeLog
trunk/src/Makefile.am
trunk/src/cardman.c
Log:
Add an application selection button.
Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog 2009-03-03 18:25:30 UTC (rev 958)
+++ trunk/src/ChangeLog 2009-03-04 08:47:46 UTC (rev 959)
@@ -1,3 +1,15 @@
+2009-03-04 Werner Koch <wk at g10code.com>
+
+ * cardman.c (struct _GpaCardManager): Add field APP_SELECTOR.
+ (setup_app_selector, setup_app_selector_data_cb): New.
+ (gpa_card_manager_init): Call setup_app_selector.
+ (card_reload): Implement application selection.
+ (update_card_widget): Add arg ERROR_DESCRIPTION and change all
+ callers.
+
+ * membuf.c, membuf.h: New. Taken from GnuPG and modified for use
+ with Glib.
+
2009-03-03 Werner Koch <wk at g10code.com>
* convert.c (gpa_sex_char_to_string): Make strings a salutation.
Modified: trunk/src/Makefile.am
===================================================================
--- trunk/src/Makefile.am 2009-03-03 18:25:30 UTC (rev 958)
+++ trunk/src/Makefile.am 2009-03-04 08:47:46 UTC (rev 959)
@@ -138,6 +138,7 @@
strlist.h strlist.c \
gpg-stuff.h gpg-stuff.c \
convert.c convert.h \
+ membuf.c membuf.h \
utils.c $(gpa_w32_sources) $(gpa_cardman_sources)
dndtest_SOURCES = dndtest.c
Modified: trunk/src/cardman.c
===================================================================
--- trunk/src/cardman.c 2009-03-03 18:25:30 UTC (rev 958)
+++ trunk/src/cardman.c 2009-03-04 08:47:46 UTC (rev 959)
@@ -38,6 +38,7 @@
#include "icons.h"
#include "cardman.h"
#include "convert.h"
+#include "membuf.h"
#include "gpagenkeycardop.h"
@@ -62,11 +63,12 @@
GtkUIManager *ui_manager;
+
+ GtkWidget *app_selector; /* Combo Box to select the application. */
GtkWidget *card_container; /* The container holding the card widget. */
GtkWidget *card_widget; /* The widget to display a card applciation. */
-
/* Labels in the status bar. */
GtkWidget *status_label;
GtkWidget *status_text;
@@ -99,7 +101,7 @@
/* Local prototypes */
static void start_ticker (GpaCardManager *cardman);
-static void update_card_widget (GpaCardManager *cardman);
+static void update_card_widget (GpaCardManager *cardman, const char *err_desc);
static void gpa_card_manager_finalize (GObject *object);
@@ -258,7 +260,11 @@
card_reload (GpaCardManager *cardman)
{
gpg_error_t err;
+ const char *application;
+ char *command_buf = NULL;
const char *command;
+ const char *err_desc = NULL;
+ int auto_app;
if (!cardman->gpgagent)
return; /* No support for GPGME_PROTOCOL_ASSUAN. */
@@ -279,22 +285,80 @@
command; this makes sure that scdaemon initalizes the card if
that has not yet been done. */
command = "SCD SERIALNO";
+ if (cardman->app_selector
+ && (gtk_combo_box_get_active
+ (GTK_COMBO_BOX (cardman->app_selector)) > 0)
+ && (application = gtk_combo_box_get_active_text
+ (GTK_COMBO_BOX (cardman->app_selector))))
+ {
+ command_buf = g_strdup_printf ("%s %s", command, application);
+ command = command_buf;
+ auto_app = 0;
+ }
+ else
+ auto_app = 1;
err = gpgme_op_assuan_transact (cardman->gpgagent,
command,
scd_data_cb, NULL,
scd_inq_cb, NULL,
scd_status_cb, cardman);
if (!err)
- err = gpgme_op_assuan_result (cardman->gpgagent)->err;
+ {
+ err = gpgme_op_assuan_result (cardman->gpgagent)->err;
+ if (!auto_app
+ && gpg_err_source (err) == GPG_ERR_SOURCE_SCD
+ && gpg_err_code (err) == GPG_ERR_CONFLICT)
+ {
+ /* Not in auto select mode and the scdaemon told us
+ about a conflicting use. We now do a restart and try
+ again to display an application selection conflict
+ error only if it is not due to our own connection to
+ the scdaemon. */
+ if (!gpgme_op_assuan_transact (cardman->gpgagent,
+ "SCD RESTART",
+ NULL, NULL, NULL, NULL,
+ NULL, NULL)
+ && !gpgme_op_assuan_result (cardman->gpgagent)->err)
+ {
+ err = gpgme_op_assuan_transact (cardman->gpgagent,
+ command,
+ scd_data_cb, NULL,
+ scd_inq_cb, NULL,
+ scd_status_cb, cardman);
+ if (!err)
+ err = gpgme_op_assuan_result (cardman->gpgagent)->err;
+ }
+ }
+ }
+
if (gpg_err_code (err) == GPG_ERR_CARD_NOT_PRESENT)
;
+ else if (gpg_err_source (err) == GPG_ERR_SOURCE_SCD
+ && gpg_err_code (err) == GPG_ERR_CONFLICT)
+ {
+ err_desc = auto_app
+ ? _("The selected card application is currently not available.")
+ : _("Another process is using a different card application "
+ "than the selected one.\n\n"
+ "You may change the application selection mode to "
+ "\"Auto\" to select the active application.");
+ }
+ else if (!auto_app
+ && gpg_err_source (err) == GPG_ERR_SOURCE_SCD
+ && gpg_err_code (err) == GPG_ERR_NOT_SUPPORTED)
+ {
+ err_desc =
+ _("The selected card application is not available.");
+ }
else if (err)
{
g_debug ("assuan command `%s' failed: %s <%s>\n",
command, gpg_strerror (err), gpg_strsource (err));
+ err_desc = _("Error accessing the card.");
statusbar_update (cardman, _("Error accessing card"));
}
+ g_free (command_buf);
if (!err)
@@ -329,7 +393,7 @@
}
- update_card_widget (cardman);
+ update_card_widget (cardman, err_desc);
update_title (cardman);
update_info_visibility (cardman);
@@ -626,7 +690,7 @@
static void
-update_card_widget (GpaCardManager *cardman)
+update_card_widget (GpaCardManager *cardman, const char *error_description)
{
if (cardman->card_widget)
{
@@ -654,7 +718,13 @@
}
else
{
- cardman->card_widget = gtk_label_new (_("No card found."));
+ if (!error_description)
+ {
+ error_description = cardman->cardtype
+ ? _("This card application is not yet supported.")
+ : _("No card found.");
+ }
+ cardman->card_widget = gtk_label_new (error_description);
}
gtk_scrolled_window_add_with_viewport
@@ -664,11 +734,82 @@
}
+/* Handler for the "changed" signal of the application selector. */
static void
+app_selector_changed_cb (GtkComboBox *cbox, void *opaque)
+{
+ GpaCardManager *cardman = opaque;
+
+ g_object_ref (cardman);
+ g_idle_add (card_reload_idle_cb, cardman);
+}
+
+
+/* Assuan data callback used by setup_app_selector. */
+static gpg_error_t
+setup_app_selector_data_cb (void *opaque, const void *data, size_t datalen)
+{
+ membuf_t *mb = opaque;
+
+ put_membuf (mb, data, datalen);
+
+ return 0;
+}
+
+
+/* Fill the app_selection box with the available applications. */
+static void
+setup_app_selector (GpaCardManager *cardman)
+{
+ gpg_error_t err;
+ membuf_t mb;
+ char *string;
+ char *p, *p0, *p1;
+
+ if (!cardman->gpgagent || !cardman->app_selector)
+ return;
+
+ init_membuf (&mb, 256);
+
+ err = gpgme_op_assuan_transact (cardman->gpgagent,
+ "SCD GETINFO app_list",
+ setup_app_selector_data_cb, &mb,
+ NULL, NULL, NULL, NULL);
+ if (err || gpgme_op_assuan_result (cardman->gpgagent)->err)
+ {
+ g_free (get_membuf (&mb, NULL));
+ return;
+ }
+ /* Make sure the data is a string and get it. */
+ put_membuf (&mb, "", 1);
+ string = get_membuf (&mb, NULL);
+ if (!string)
+ return; /* Out of core. */
+
+ for (p=p0=string; *p; p++)
+ {
+ if (*p == '\n')
+ {
+ *p = 0;
+ p1 = strchr (p0, ':');
+ if (p1)
+ *p1 = 0;
+ gtk_combo_box_append_text
+ (GTK_COMBO_BOX (cardman->app_selector), p0);
+ if (p[1])
+ p0 = p+1;
+ }
+ }
+
+ g_free (string);
+}
+
+
+static void
construct_widgets (GpaCardManager *cardman)
{
GtkWidget *vbox;
- GtkWidget *hbox;
+ GtkWidget *hbox, *hbox1, *hbox2;
GtkWidget *label;
GtkWidget *icon;
gchar *markup;
@@ -691,22 +832,39 @@
gtk_box_pack_start (GTK_BOX (vbox), toolbar, FALSE, TRUE, 0);
/* Add a fancy label that tells us: This is the card manager. */
- hbox = gtk_hbox_new (FALSE, 0);
- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
+ hbox1 = gtk_hbox_new (FALSE, 0);
icon = gtk_image_new_from_stock (GPA_STOCK_CARDMAN, GTK_ICON_SIZE_DND);
- gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox1), icon, FALSE, TRUE, 0);
label = gtk_label_new (NULL);
markup = g_strdup_printf ("<span font_desc=\"16\">%s</span>",
_("Card Manager"));
gtk_label_set_markup (GTK_LABEL (label), markup);
g_free (markup);
- gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 10);
+ gtk_box_pack_start (GTK_BOX (hbox1), label, TRUE, TRUE, 10);
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
- /* Create a container (a scolled windows) which will take the actual
- card widgte. This container is required so that we can easily
+ /* Add a application selection box. */
+ hbox2 = gtk_hbox_new (FALSE, 0);
+ label = gtk_label_new (_("Application selection:"));
+ gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, TRUE, 5);
+ cardman->app_selector = gtk_combo_box_new_text ();
+ gtk_combo_box_append_text (GTK_COMBO_BOX (cardman->app_selector),
+ _("Auto"));
+ gtk_combo_box_set_active (GTK_COMBO_BOX (cardman->app_selector), 0);
+ gtk_box_pack_start (GTK_BOX (hbox2), cardman->app_selector, FALSE, TRUE, 0);
+
+ /* Put Card Manager label and application selector into the same line. */
+ hbox = gtk_hbox_new (FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), hbox1, FALSE, FALSE, 0);
+ gtk_box_pack_end (GTK_BOX (hbox), hbox2, FALSE, FALSE, 0);
+
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
+
+
+ /* Create a container (a scolled window) which will take the actual
+ card widget. This container is required so that we can easily
change to a differet card widget. */
cardman->card_container = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy
@@ -715,7 +873,7 @@
gtk_box_pack_start (GTK_BOX (vbox), cardman->card_container, TRUE, TRUE, 0);
/* Update the container using the current card application. */
- update_card_widget (cardman);
+ update_card_widget (cardman, NULL);
statusbar = statusbar_new (cardman);
gtk_box_pack_start (GTK_BOX (vbox), statusbar, FALSE, FALSE, 0);
@@ -777,6 +935,13 @@
gpgme_release (cardman->gpgagent);
cardman->gpgagent = NULL;
}
+
+ setup_app_selector (cardman);
+ if (cardman->app_selector)
+ g_signal_connect (cardman->app_selector, "changed",
+ G_CALLBACK (app_selector_changed_cb), cardman);
+
+
}
Added: trunk/src/membuf.c
===================================================================
--- trunk/src/membuf.c 2009-03-03 18:25:30 UTC (rev 958)
+++ trunk/src/membuf.c 2009-03-04 08:47:46 UTC (rev 959)
@@ -0,0 +1,104 @@
+/* membuf.c - A simple implementation of a dynamic buffer
+ * Copyright (C) 2001, 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <glib.h>
+
+#include "membuf.h"
+
+
+/* A simple implementation of a dynamic buffer. Use init_membuf() to
+ create a buffer, put_membuf to append bytes and get_membuf to
+ release and return the buffer. Allocation errors are detected but
+ only returned at the final get_membuf(), this helps not to clutter
+ the code with out of core checks. */
+void
+init_membuf (membuf_t *mb, size_t initiallen)
+{
+ if (!initiallen)
+ initiallen = 1024;
+ mb->len = 0;
+ mb->size = initiallen;
+ mb->out_of_core = 0;
+ mb->buf = g_try_malloc (initiallen);
+ if (!mb->buf)
+ mb->out_of_core = errno;
+}
+
+
+void
+put_membuf (membuf_t *mb, const void *buf, size_t len)
+{
+ if (mb->out_of_core)
+ return;
+
+ if (mb->len + len >= mb->size)
+ {
+ char *p;
+
+ mb->size += len + 1024;
+ p = g_try_realloc (mb->buf, mb->size);
+ if (!p)
+ {
+ mb->out_of_core = errno ? errno : ENOMEM;
+ /* Wipe out what we already accumulated. This is required
+ in case we are storing sensitive data here. The membuf
+ API does not provide another way to cleanup after an
+ error. */
+ memset (mb->buf, 0, mb->len);
+ return;
+ }
+ mb->buf = p;
+ }
+ memcpy (mb->buf + mb->len, buf, len);
+ mb->len += len;
+}
+
+
+void
+put_membuf_str (membuf_t *mb, const char *string)
+{
+ put_membuf (mb, string, strlen (string));
+}
+
+
+void *
+get_membuf (membuf_t *mb, size_t *len)
+{
+ char *p;
+
+ if (mb->out_of_core)
+ {
+ g_free (mb->buf);
+ mb->buf = NULL;
+ errno = mb->out_of_core;
+ return NULL;
+ }
+
+ p = mb->buf;
+ if (len)
+ *len = mb->len;
+ mb->buf = NULL;
+ mb->out_of_core = ENOMEM; /* Hack to make sure it won't get reused. */
+ return p;
+}
Added: trunk/src/membuf.h
===================================================================
--- trunk/src/membuf.h 2009-03-03 18:25:30 UTC (rev 958)
+++ trunk/src/membuf.h 2009-03-04 08:47:46 UTC (rev 959)
@@ -0,0 +1,46 @@
+/* membuf.h - A simple implementation of a dynamic buffer
+ * Copyright (C) 2001, 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GPA_MEMBUF_H
+#define GPA_MEMBUF_H
+
+/* The definition of the structure is private, we only need it here,
+ so it can be allocated on the stack. */
+struct private_membuf_s
+{
+ size_t len;
+ size_t size;
+ char *buf;
+ int out_of_core;
+};
+
+typedef struct private_membuf_s membuf_t;
+
+/* Return the current length of the membuf. */
+#define get_membuf_len(a) ((a)->len)
+#define is_membuf_ready(a) ((a)->buf || (a)->out_of_core)
+#define MEMBUF_ZERO { 0, 0, NULL, 0}
+
+void init_membuf (membuf_t *mb, size_t initiallen);
+void put_membuf (membuf_t *mb, const void *buf, size_t len);
+void put_membuf_str (membuf_t *mb, const char *string);
+void *get_membuf (membuf_t *mb, size_t *len);
+
+
+#endif /*GPA_MEMBUF_H*/
More information about the Gpa-commits
mailing list