[Gpa-commits] r920 - trunk/src

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Sat Dec 13 23:34:57 CET 2008


Author: moritzs
Date: 2008-12-13 23:34:51 +0100 (Sat, 13 Dec 2008)
New Revision: 920

Added:
   trunk/src/cardman.c
   trunk/src/cardman.h
   trunk/src/gpacardreloadop.c
   trunk/src/gpacardreloadop.h
   trunk/src/gpagenkeycardop.c
   trunk/src/gpagenkeycardop.h
Modified:
   trunk/src/ChangeLog
   trunk/src/Makefile.am
   trunk/src/clipboard.c
   trunk/src/fileman.c
   trunk/src/gpa.c
   trunk/src/gpa.h
   trunk/src/gpagenkeyadvop.c
   trunk/src/gpgmeedit.c
   trunk/src/gpgmeedit.h
   trunk/src/icons.c
   trunk/src/icons.h
   trunk/src/keygendlg.c
   trunk/src/keygendlg.h
   trunk/src/keyring.c
   trunk/src/server.c
Log:
2008-12-13  Moritz  <moritz at gnu.org>

	* gpacardreloadop.c, gpacardreloadop.h, gpagenkeycardop.c,
	gpagenkeycardop.h, cardman.c, cardman.h: New files.

	* Makefile.am (gpa_SOURCES): Added: cardman.c, cardman.h,
	gpacardreloadop.c, gpacardreloadop.h, gpagenkeycardop.c,
	gpagenkeycardop.h.

	* server.c (cmd_start_cardmanager): New function.
	(register_commands): Register START_CARDMANAGER command.

	* gpagenkeyadvop.c
	(gpa_gen_key_advanced_operation_idle_cb): Pass new argument '0' to
	gpa_key_gen_run_dialog.

	* gpgmeedit.c: New enum: CardState.
	(card_edit_list_fnc_action, card_edit_list_fnc_transit)
	(gpa_gpgme_card_edit_list_parms_release)
	(gpa_gpgme_card_edit_list_start): New functions. The rest of
	included card related code is probably not working and therefore
	disabled.
	* gpgmeedit.h: Declare gpa_gpgme_card_edit_list_start.

	* gpa.c: Include "cardman.h".
	(gpa_args_t): Add member to struct: start_card_manager.
	(option_entries): Add new entry for the card manager.
	(quit_if_no_window): Call gpa_card_manager_is_open().
	(gpa_open_cardmanager): New function.
	(main): Check value of args.start_card_manager before preparing to
	start keyring editor; if args.start_card_manager is true, call
	gpa_open_cardmanager().
	* gpa.h: Declare gpa_open_cardmanager().
	(gpa_windows_menu_action_entries): Added entry for card manager.

	* keygendlg.c (_GPAKeyGenDialog): New member in struct: forcard.
	(response_cb): Only check validity of the given passphrases if we
	are not generating a key on a smartcard.
	(gpa_key_gen_run_dialog): New parameter: forcard; initialize
	forcard member in dialog struct. Adjust GUI construction for the
	forcard==TRUE case, which means that we are generating a key on a
	smartcard. For comboKeysize use gtk_combo_box_new_text() instead
	of gtk_combo_box_entry_new_text(), since it doesn't make much
	sense in my opinion to be able to choose arbitrarty key sizes.
	* keygendlg.h: Adjust to new gpa_key_gen_run_dialog API by adding
	forcard parameter.

	* icons.h: Define GPA_STOCK_CARDMAN.
	* icons.c: Add new icon for card manager. At the moment this is a
	placeholder (floppy) icon.

	* keyring.c: Add menuitem/toolitem
	actions for card manager.
	* fileman.c: Likewise.
	* clipboard.c: Likewise.



Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog	2008-12-10 18:22:34 UTC (rev 919)
+++ trunk/src/ChangeLog	2008-12-13 22:34:51 UTC (rev 920)
@@ -1,3 +1,59 @@
+2008-12-13  Moritz  <moritz at gnu.org>
+
+	* gpacardreloadop.c, gpacardreloadop.h, gpagenkeycardop.c,
+	gpagenkeycardop.h, cardman.c, cardman.h: New files.
+
+	* Makefile.am (gpa_SOURCES): Added: cardman.c, cardman.h,
+	gpacardreloadop.c, gpacardreloadop.h, gpagenkeycardop.c,
+	gpagenkeycardop.h.
+
+	* server.c (cmd_start_cardmanager): New function.
+	(register_commands): Register START_CARDMANAGER command.
+
+	* gpagenkeyadvop.c
+	(gpa_gen_key_advanced_operation_idle_cb): Pass new argument '0' to
+	gpa_key_gen_run_dialog.
+
+	* gpgmeedit.c: New enum: CardState.
+	(card_edit_list_fnc_action, card_edit_list_fnc_transit)
+	(gpa_gpgme_card_edit_list_parms_release)
+	(gpa_gpgme_card_edit_list_start): New functions. The rest of
+	included card related code is probably not working and therefore
+	disabled.
+	* gpgmeedit.h: Declare gpa_gpgme_card_edit_list_start.
+
+	* gpa.c: Include "cardman.h".
+	(gpa_args_t): Add member to struct: start_card_manager.
+	(option_entries): Add new entry for the card manager.
+	(quit_if_no_window): Call gpa_card_manager_is_open().
+	(gpa_open_cardmanager): New function.
+	(main): Check value of args.start_card_manager before preparing to
+	start keyring editor; if args.start_card_manager is true, call
+	gpa_open_cardmanager().
+	* gpa.h: Declare gpa_open_cardmanager().
+	(gpa_windows_menu_action_entries): Added entry for card manager.
+
+	* keygendlg.c (_GPAKeyGenDialog): New member in struct: forcard.
+	(response_cb): Only check validity of the given passphrases if we
+	are not generating a key on a smartcard.
+	(gpa_key_gen_run_dialog): New parameter: forcard; initialize
+	forcard member in dialog struct. Adjust GUI construction for the
+	forcard==TRUE case, which means that we are generating a key on a
+	smartcard. For comboKeysize use gtk_combo_box_new_text() instead
+	of gtk_combo_box_entry_new_text(), since it doesn't make much
+	sense in my opinion to be able to choose arbitrarty key sizes.
+	* keygendlg.h: Adjust to new gpa_key_gen_run_dialog API by adding
+	forcard parameter.
+
+	* icons.h: Define GPA_STOCK_CARDMAN.
+	* icons.c: Add new icon for card manager. At the moment this is a
+	placeholder (floppy) icon.
+
+	* keyring.c: Add menuitem/toolitem
+	actions for card manager.
+	* fileman.c: Likewise.
+	* clipboard.c: Likewise.
+
 2008-12-10  Marcus Brinkmann  <marcus at g10code.de>
 
 	* gpaimportfileop.c (gpa_import_file_operation_get_source): Fix

Modified: trunk/src/Makefile.am
===================================================================
--- trunk/src/Makefile.am	2008-12-10 18:22:34 UTC (rev 919)
+++ trunk/src/Makefile.am	2008-12-13 22:34:51 UTC (rev 920)
@@ -53,6 +53,7 @@
 	      icons.c icons.h \
 	      gpawidgets.c gpawidgets.h \
 	      fileman.c fileman.h \
+	      cardman.c cardman.h \
 	      clipboard.h clipboard.c \
 	      filesigndlg.c filesigndlg.h \
 	      encryptdlg.c encryptdlg.h \
@@ -113,6 +114,8 @@
 	      gpagenkeyop.h gpagenkeyop.c \
 	      gpagenkeyadvop.h gpagenkeyadvop.c \
 	      gpagenkeysimpleop.h gpagenkeysimpleop.c \
+	      gpacardreloadop.h gpacardreloadop.c \
+	      gpagenkeycardop.h gpagenkeycardop.c \
 	      gpabackupop.h gpabackupop.c \
 	      gpakeyselector.h gpakeyselector.c \
 	      server.c \

Added: trunk/src/cardman.c
===================================================================
--- trunk/src/cardman.c	2008-12-10 18:22:34 UTC (rev 919)
+++ trunk/src/cardman.c	2008-12-13 22:34:51 UTC (rev 920)
@@ -0,0 +1,538 @@
+/* cardman.c  -  The GNU Privacy Assistant: card manager.
+   Copyright (C) 2000, 2001 G-N-U GmbH.
+   Copyright (C) 2007, 2008 g10 Code GmbH
+
+   This file is part of GPA.
+
+   GPA 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.
+
+   GPA 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/>.  */
+
+/* The card manager window.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <time.h>
+
+#include <gdk/gdkkeysyms.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+
+#include "gpa.h"   
+#include "gpapastrings.h"
+
+#include "gtktools.h"
+#include "gpawidgets.h"
+#include "siglist.h"
+#include "helpmenu.h"
+#include "icons.h"
+#include "cardman.h"
+
+#include "gpacardreloadop.h"
+#include "gpagenkeycardop.h"
+
+
+/* Object and class definition.  */
+struct _GpaCardManager
+{
+  GtkWindow parent;
+
+  GtkWidget *window;
+  GtkWidget *entrySerialno;
+  GtkWidget *entryVersion;
+  GtkWidget *entryManufacturer;
+  GtkWidget *entryLogin;
+  GtkWidget *entryLanguage;
+  GtkWidget *entryPubkeyUrl;
+  GtkWidget *entryFirstName;
+  GtkWidget *entryLastName;
+  GtkWidget *entryKeySig;
+  GtkWidget *entryKeyEnc;
+  GtkWidget *entryKeyAuth;
+#if 0
+  GtkWidget *comboSex;
+  GList *selection_sensitive_actions; /* ? */
+#endif
+};
+
+struct _GpaCardManagerClass 
+{
+  GtkWindowClass parent_class;
+};
+
+/* There is only one instance of the card manager class.  Use a global
+   variable to keep track of it.  */
+static GpaCardManager *instance;
+
+/* We also need to save the parent class. */
+static GObjectClass *parent_class;
+
+#if 0
+/* FIXME: I guess we should use a more intelligent handling for widget
+   sensitivity similar to that in fileman.c. -mo */
+/* Definition of the sensitivity function type.  */
+typedef gboolean (*sensitivity_func_t)(gpointer);
+#endif
+
+/* Local prototypes */
+static GObject *gpa_card_manager_constructor (GType type,
+					      guint n_construct_properties,
+					      GObjectConstructParam *construct_properties);
+
+
+
+/*
+ * GtkWidget boilerplate.
+ */
+static void
+gpa_card_manager_finalize (GObject *object)
+{  
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+static void
+gpa_card_manager_init (GpaCardManager *cardman)
+{
+}
+
+static void
+gpa_card_manager_class_init (GpaCardManagerClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  
+  parent_class = g_type_class_peek_parent (klass);
+  
+  object_class->constructor = gpa_card_manager_constructor;
+  object_class->finalize = gpa_card_manager_finalize;
+}
+
+GType
+gpa_card_manager_get_type (void)
+{
+  static GType cardman_type = 0;
+  
+  if (!cardman_type)
+    {
+      static const GTypeInfo cardman_info =
+	{
+	  sizeof (GpaCardManagerClass),
+	  (GBaseInitFunc) NULL,
+	  (GBaseFinalizeFunc) NULL,
+	  (GClassInitFunc) gpa_card_manager_class_init,
+	  NULL,           /* class_finalize */
+	  NULL,           /* class_data */
+	  sizeof (GpaCardManager),
+	  0,              /* n_preallocs */
+	  (GInstanceInitFunc) gpa_card_manager_init,
+	};
+      
+      cardman_type = g_type_register_static (GTK_TYPE_WINDOW,
+					     "GpaCardManager",
+					     &cardman_info, 0);
+    }
+  
+  return cardman_type;
+}
+
+
+
+static void
+register_reload_operation (GpaCardManager *cardman, GpaCardReloadOperation *op)
+{
+  /* FIXME: is this correct? -mo */
+  g_signal_connect (G_OBJECT (op), "completed",
+		    G_CALLBACK (g_object_unref), cardman);
+}
+
+/* This is the callback used by the GpaCardReloadOp object. It's
+   called for each data item during a reload operation and updates the
+   according widgets. */
+static void
+card_reload_cb (void *opaque, const char *identifier, int idx, const void *value)
+{
+  GpaCardManager *cardman = opaque;
+  const char *string = value;
+
+  if (strcmp (identifier, "serial") == 0 && idx == 0)
+    gtk_entry_set_text (GTK_ENTRY (cardman->entrySerialno), string);
+  else if (strcmp (identifier, "login") == 0 && idx == 0)
+    gtk_entry_set_text (GTK_ENTRY (cardman->entryLogin), string);
+  else if (strcmp (identifier, "name") == 0 && idx == 0)
+    gtk_entry_set_text (GTK_ENTRY (cardman->entryFirstName), string);
+  else if (strcmp (identifier, "name") == 0 && idx == 1)
+    gtk_entry_set_text (GTK_ENTRY (cardman->entryLastName), string);
+  else if (strcmp (identifier, "lang") == 0 && idx == 0)
+    gtk_entry_set_text (GTK_ENTRY (cardman->entryLanguage), string);
+  else if (strcmp (identifier, "url") == 0 && idx == 0)
+    gtk_entry_set_text (GTK_ENTRY (cardman->entryPubkeyUrl), string);
+  else if (strcmp (identifier, "vendor") == 0 && idx == 1)
+    gtk_entry_set_text (GTK_ENTRY (cardman->entryManufacturer), string);
+  else if (strcmp (identifier, "version") == 0 && idx == 0)
+    gtk_entry_set_text (GTK_ENTRY (cardman->entryVersion), string);
+  else if (strcmp (identifier, "fpr") == 0 && idx == 0)
+    gtk_entry_set_text (GTK_ENTRY (cardman->entryKeySig), string);
+  else if (strcmp (identifier, "fpr") == 0 && idx == 1)
+    gtk_entry_set_text (GTK_ENTRY (cardman->entryKeyEnc), string);
+  else if (strcmp (identifier, "fpr") == 0 && idx == 2)
+    gtk_entry_set_text (GTK_ENTRY (cardman->entryKeyAuth), string);
+}
+
+/* This function is called when the user triggers a card-reload. */
+static void
+card_reload (GtkAction *action, gpointer param)
+{
+  GpaCardManager *cardman = param;
+  GpaCardReloadOperation *op;
+
+  op = gpa_card_reload_operation_new (cardman->window, card_reload_cb, cardman);
+  register_reload_operation (cardman, GPA_CARD_RELOAD_OPERATION (op));
+}
+
+#if 0
+/* This function is called when the user triggers a card-reload. */
+static void
+card_edit (GtkAction *action, gpointer param)
+{
+  GpaCardManager *cardman = param;
+  gpg_error_t err;
+
+  fprintf (stderr, "CARD_EDIT\n");
+  //err = gpa_gpgme_card_edit_modify_start (CTX, "123");
+}
+#endif
+
+/* This function is called when the user triggers a key-generation. */
+static void
+card_genkey (GtkAction *action, gpointer param)
+{
+  GpaCardManager *cardman = param;
+  GpaGenKeyCardOperation *op;
+
+  op = gpa_gen_key_card_operation_new (cardman->window);
+  register_reload_operation (cardman, GPA_GEN_KEY_OPERATION (op));
+}
+
+/* Construct the card manager menu and toolbar widgets and return
+   them. */
+static void
+cardman_action_new (GpaCardManager *cardman, GtkWidget **menubar,
+		    GtkWidget **toolbar)
+{
+  static const GtkActionEntry entries[] =
+    {
+      /* Toplevel.  */
+      { "File", NULL, N_("_File"), NULL },
+      { "Card", NULL, N_("_Card"), NULL },
+
+      /* File menu.  */
+      { "FileQuit", GTK_STOCK_QUIT, NULL, NULL,
+	N_("Quit the program"), G_CALLBACK (gtk_main_quit) },
+
+      /* Card menu.  */
+      { "CardReload", GTK_STOCK_REFRESH, NULL, NULL,
+	N_("Reload card information"), G_CALLBACK (card_reload) },
+#if 0
+      /* FIXME: not yet implemented. */
+      { "CardEdit", GTK_STOCK_EDIT, NULL, NULL,
+	N_("Edit card information"), G_CALLBACK (card_edit) },
+#endif
+      { "CardGenkey", GTK_STOCK_NEW, "Generate new key...", NULL,
+	N_("Generate new key on card"), G_CALLBACK (card_genkey) },
+    };
+
+  static const char *ui_description =
+    "<ui>"
+    "  <menubar name='MainMenu'>"
+    "    <menu action='File'>"
+    "      <menuitem action='FileQuit'/>"
+    "    </menu>"
+    "    <menu action='Card'>"
+    "      <menuitem action='CardReload'/>"
+#if 0
+    "      <menuitem action='CardEdit'/>"
+#endif
+    "      <menuitem action='CardGenkey'/>"
+    "    </menu>"
+    "    <menu action='Windows'>"
+    "      <menuitem action='WindowsKeyringEditor'/>"
+    "      <menuitem action='WindowsFileManager'/>"
+    "      <menuitem action='WindowsClipboard'/>"
+    "      <menuitem action='WindowsCardManager'/>"
+    "    </menu>"
+    "    <menu action='Help'>"
+#if 0
+    "      <menuitem action='HelpContents'/>"
+#endif
+    "      <menuitem action='HelpAbout'/>"
+    "    </menu>"
+    "  </menubar>"
+    "  <toolbar name='ToolBar'>"
+    "    <toolitem action='CardReload'/>"
+#if 0
+    "    <toolitem action='CardEdit'/>"
+#endif
+    "    <separator/>"
+    "    <toolitem action='WindowsKeyringEditor'/>"
+    "    <toolitem action='WindowsFileManager'/>"
+    "    <toolitem action='WindowsClipboard'/>"
+#if 0
+    "    <toolitem action='HelpContents'/>"
+#endif
+    "  </toolbar>"
+    "</ui>";
+
+  GtkAccelGroup *accel_group;
+  GtkActionGroup *action_group;
+  GtkAction *action;
+  GtkUIManager *ui_manager;
+  GError *error;
+
+  action_group = gtk_action_group_new ("MenuActions");
+  gtk_action_group_add_actions (action_group, entries, G_N_ELEMENTS (entries),
+				cardman);
+  gtk_action_group_add_actions (action_group, gpa_help_menu_action_entries,
+				G_N_ELEMENTS (gpa_help_menu_action_entries),
+				cardman);
+  gtk_action_group_add_actions (action_group, gpa_windows_menu_action_entries,
+				G_N_ELEMENTS (gpa_windows_menu_action_entries),
+				cardman);
+  gtk_action_group_add_actions
+    (action_group, gpa_preferences_menu_action_entries,
+     G_N_ELEMENTS (gpa_preferences_menu_action_entries), cardman);
+  ui_manager = gtk_ui_manager_new ();
+  gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
+  accel_group = gtk_ui_manager_get_accel_group (ui_manager);
+  gtk_window_add_accel_group (GTK_WINDOW (cardman), accel_group);
+  if (! gtk_ui_manager_add_ui_from_string (ui_manager, ui_description,
+					   -1, &error))
+    {
+      g_message ("building cardman menus failed: %s", error->message);
+      g_error_free (error);
+      exit (EXIT_FAILURE);
+    }
+
+  /* Fixup the icon theme labels which are too long for the toolbar.  */
+  action = gtk_action_group_get_action (action_group, "WindowsKeyringEditor");
+  g_object_set (action, "short_label", _("Keyring"), NULL);
+  action = gtk_action_group_get_action (action_group, "WindowsFileManager");
+  g_object_set (action, "short_label", _("Files"), NULL);
+
+  *menubar = gtk_ui_manager_get_widget (ui_manager, "/MainMenu");
+  *toolbar = gtk_ui_manager_get_widget (ui_manager, "/ToolBar");
+  gpa_toolbar_set_homogeneous (GTK_TOOLBAR (*toolbar), FALSE);
+}
+
+
+
+/* Callback for the destroy signal.  */
+static void
+card_manager_closed (GtkWidget *widget, gpointer param)
+{
+  instance = NULL;
+}
+
+/* This function constructs the container holding the card "form". It
+   updates CARDMAN with new references to the entry widgets, etc.  */
+static GtkWidget *
+construct_card_widget (GpaCardManager *cardman)
+{
+  GtkWidget *table;
+  int rowidx = 0;
+
+  table = gtk_table_new (4, 2, FALSE);
+  gtk_container_set_border_width (GTK_CONTAINER (table), 5);
+
+#define ADD_TABLE_ROW(label, widget) \
+  { \
+    GtkWidget *tmp_label = gtk_label_new (_(label)); \
+    gtk_table_attach (GTK_TABLE (table), tmp_label, 0, 1, rowidx, rowidx + 1, GTK_FILL, GTK_SHRINK, 0, 0); \
+    gtk_table_attach (GTK_TABLE (table), widget, 1, 2, rowidx, rowidx + 1, GTK_FILL, GTK_SHRINK, 0, 0); \
+    rowidx++; \
+  }
+  
+  cardman->entrySerialno = gtk_entry_new ();
+  gtk_editable_set_editable (GTK_EDITABLE (cardman->entrySerialno), FALSE);
+  ADD_TABLE_ROW ("Serial Number: ", cardman->entrySerialno);
+
+  cardman->entryVersion = gtk_entry_new ();
+  gtk_editable_set_editable (GTK_EDITABLE (cardman->entryVersion), FALSE);
+  ADD_TABLE_ROW ("Version: ", cardman->entryVersion);
+
+  cardman->entryManufacturer = gtk_entry_new ();
+  gtk_editable_set_editable (GTK_EDITABLE (cardman->entryManufacturer), FALSE);
+  ADD_TABLE_ROW ("Manufacturer: ", cardman->entryManufacturer);
+
+  cardman->entryFirstName = gtk_entry_new ();
+  gtk_editable_set_editable (GTK_EDITABLE (cardman->entryFirstName), FALSE);
+  ADD_TABLE_ROW ("First Name: ", cardman->entryFirstName);
+
+  cardman->entryLastName = gtk_entry_new ();
+  gtk_editable_set_editable (GTK_EDITABLE (cardman->entryLastName), FALSE);
+  ADD_TABLE_ROW ("Last Name: ", cardman->entryLastName);
+
+#if 0
+  cardman->comboSex = gtk_combo_box_new_text ();
+  gtk_combo_box_append_text (GTK_COMBO_BOX (cardman->comboSex), _("Unspecified"));
+  gtk_combo_box_append_text (GTK_COMBO_BOX (cardman->comboSex), _("Female"));
+  gtk_combo_box_append_text (GTK_COMBO_BOX (cardman->comboSex), _("Male"));
+  gtk_combo_box_set_active (GTK_COMBO_BOX (cardman->comboSex), 0);
+  ADD_TABLE_ROW ("Sex: ", cardman->comboSex);
+#endif
+
+  cardman->entryLanguage = gtk_entry_new ();
+  gtk_editable_set_editable (GTK_EDITABLE (cardman->entryLanguage), FALSE);
+  ADD_TABLE_ROW ("Language: ", cardman->entryLanguage);
+
+  cardman->entryLogin = gtk_entry_new ();
+  gtk_editable_set_editable (GTK_EDITABLE (cardman->entryLogin), FALSE);
+  ADD_TABLE_ROW ("Login data: ", cardman->entryLogin);
+
+  cardman->entryPubkeyUrl = gtk_entry_new ();
+  gtk_editable_set_editable (GTK_EDITABLE (cardman->entryPubkeyUrl), FALSE);
+  ADD_TABLE_ROW ("Public key URL: ", cardman->entryPubkeyUrl);
+
+  cardman->entryKeySig = gtk_entry_new ();
+  gtk_editable_set_editable (GTK_EDITABLE (cardman->entryKeySig), FALSE);
+  gtk_entry_set_width_chars (GTK_ENTRY (cardman->entryKeySig), 42);
+  ADD_TABLE_ROW ("Signature Key: ", cardman->entryKeySig);
+
+  cardman->entryKeyEnc = gtk_entry_new ();
+  gtk_editable_set_editable (GTK_EDITABLE (cardman->entryKeyEnc), FALSE);
+  gtk_entry_set_width_chars (GTK_ENTRY (cardman->entryKeyEnc), 42);
+  ADD_TABLE_ROW ("Encryption Key: ", cardman->entryKeyEnc);
+
+  cardman->entryKeyAuth = gtk_entry_new ();
+  gtk_editable_set_editable (GTK_EDITABLE (cardman->entryKeyAuth), FALSE);
+  gtk_entry_set_width_chars (GTK_ENTRY (cardman->entryKeyAuth), 42);
+  ADD_TABLE_ROW ("Authentication Key: ", cardman->entryKeyAuth);
+
+  return table;
+}
+
+/* Construct a new class object of GpaCardManager.  */
+static GObject*
+gpa_card_manager_constructor (GType type,
+			      guint n_construct_properties,
+			      GObjectConstructParam *construct_properties)
+{
+  GObject *object;
+  GpaCardManager *cardman;
+  GtkWidget *vbox;
+  GtkWidget *hbox;
+  GtkWidget *label;
+  GtkWidget *icon;
+  gchar *markup;
+  GtkWidget *menubar;
+  GtkWidget *card_widget;
+  GtkWidget *toolbar;
+
+  /* Invoke parent's constructor.  */
+  object = parent_class->constructor (type,
+				      n_construct_properties,
+				      construct_properties);
+  cardman = GPA_CARD_MANAGER (object);
+
+  cardman->entryLogin = NULL;
+
+  cardman->entrySerialno = NULL;
+  cardman->entryVersion = NULL;
+  cardman->entryManufacturer = NULL;
+  cardman->entryLogin = NULL;
+  cardman->entryLanguage = NULL;
+  cardman->entryPubkeyUrl = NULL;
+  cardman->entryFirstName = NULL;
+  cardman->entryLastName = NULL;
+  cardman->entryKeySig = NULL;
+  cardman->entryKeyEnc = NULL;
+  cardman->entryKeyAuth = NULL;
+
+  /* Initialize.  */
+  gtk_window_set_title (GTK_WINDOW (cardman),
+			_("GNU Privacy Assistant - Card Manager"));
+  gtk_window_set_default_size (GTK_WINDOW (cardman), 640, 480);
+  /* Realize the window so that we can create pixmaps without warnings.  */
+  gtk_widget_realize (GTK_WIDGET (cardman));
+
+  /* Use a vbox to show the menu, toolbar and the file container.  */
+  vbox = gtk_vbox_new (FALSE, 0);
+
+  /* Get the menu and the toolbar.  */
+  cardman_action_new (cardman, &menubar, &toolbar);
+  gtk_box_pack_start (GTK_BOX (vbox), menubar, FALSE, TRUE, 0);
+  gtk_box_pack_start (GTK_BOX (vbox), toolbar, FALSE, TRUE, 0);
+
+
+  /* Add a fancy label that tells us: This is the file manager.  */
+  hbox = gtk_hbox_new (FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
+  
+  icon = gtk_image_new_from_stock ("gtk-directory", GTK_ICON_SIZE_DND);
+  gtk_box_pack_start (GTK_BOX (hbox), 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_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+
+  card_widget = construct_card_widget (cardman);
+  gtk_box_pack_start (GTK_BOX (vbox), card_widget, TRUE, TRUE, 0);
+
+  gtk_container_add (GTK_CONTAINER (cardman), vbox);
+
+  g_signal_connect (object, "destroy",
+                    G_CALLBACK (card_manager_closed), object);
+
+  return object;
+}
+
+static GpaCardManager *
+gpa_cardman_new (void)
+{
+  GpaCardManager *cardman;
+
+  cardman = g_object_new (GPA_CARD_MANAGER_TYPE, NULL);  
+
+#if 0
+  /* ? */
+  update_selection_sensitive_actions (cardman);
+#endif
+
+  return cardman;
+}
+
+/* API */
+
+GtkWidget *
+gpa_card_manager_get_instance (void)
+{
+  if (!instance)
+    instance = gpa_cardman_new ();
+  return GTK_WIDGET (instance);
+}
+
+gboolean gpa_card_manager_is_open (void)
+{
+  return (instance != NULL);
+}
+
+/* EOF */

Added: trunk/src/cardman.h
===================================================================
--- trunk/src/cardman.h	2008-12-10 18:22:34 UTC (rev 919)
+++ trunk/src/cardman.h	2008-12-13 22:34:51 UTC (rev 920)
@@ -0,0 +1,59 @@
+/* cardman.h  -  The GNU Privacy Assistant: card manager.
+ *	Copyright (C) 2000 G-N-U GmbH.
+ *      Copyright (C) 2007, 2008 g10 Code GmbH
+ *
+ * This file is part of GPA
+ *
+ * GPA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GPA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef CARDMAN_H
+#define CARDMAN_H
+
+#include <gtk/gtk.h>
+
+/* Declare the Object. */
+typedef struct _GpaCardManager GpaCardManager;
+typedef struct _GpaCardManagerClass GpaCardManagerClass;
+
+GType gpa_card_manager_get_type (void) G_GNUC_CONST;
+
+#define GPA_CARD_MANAGER_TYPE	  (gpa_card_manager_get_type ())
+
+#define GPA_CARD_MANAGER(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GPA_CARD_MANAGER_TYPE, GpaCardManager))
+
+#define GPA_CARD_MANAGER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass),  \
+                            GPA_CARD_MANAGER_TYPE, GpaCardManagerClass))
+
+#define GPA_IS_CARD_MANAGER(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GPA_CARD_MANAGER_TYPE))
+
+#define GPA_IS_CARD_MANAGER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), GPA_CARD_MANAGER_TYPE))
+
+#define GPA_CARD_MANAGER_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj),    \
+                              GPA_CARD_MANAGER_TYPE, GpaCardManagerClass))
+
+/*  Our own API.  */
+
+GtkWidget *gpa_card_manager_get_instance (void);
+
+gboolean gpa_card_manager_is_open (void);
+
+#endif /*CARDMAN_H*/

Modified: trunk/src/clipboard.c
===================================================================
--- trunk/src/clipboard.c	2008-12-10 18:22:34 UTC (rev 919)
+++ trunk/src/clipboard.c	2008-12-13 22:34:51 UTC (rev 920)
@@ -831,6 +831,7 @@
     "      <menuitem action='WindowsKeyringEditor'/>"
     "      <menuitem action='WindowsFileManager'/>"
     "      <menuitem action='WindowsClipboard'/>"
+    "      <menuitem action='WindowsCardManager'/>"
     "    </menu>"
     "    <menu action='Help'>"
 #if 0
@@ -861,6 +862,7 @@
     "    <separator/>"
     "    <toolitem action='WindowsKeyringEditor'/>"
     "    <toolitem action='WindowsFileManager'/>"
+    "    <toolitem action='WindowsCardManager'/>"
 #if 0
     "    <toolitem action='HelpContents'/>"
 #endif
@@ -903,6 +905,8 @@
   g_object_set (action, "short_label", _("Keyring"), NULL);
   action = gtk_action_group_get_action (action_group, "WindowsFileManager");
   g_object_set (action, "short_label", _("Files"), NULL);
+  action = gtk_action_group_get_action (action_group, "WindowsCardManager");
+  g_object_set (action, "short_label", _("Card"), NULL);
 
   /* Take care of sensitiveness of widgets.  */
   action = gtk_action_group_get_action (action_group, "EditCut");

Modified: trunk/src/fileman.c
===================================================================
--- trunk/src/fileman.c	2008-12-10 18:22:34 UTC (rev 919)
+++ trunk/src/fileman.c	2008-12-13 22:34:51 UTC (rev 920)
@@ -566,6 +566,7 @@
     "      <menuitem action='WindowsKeyringEditor'/>"
     "      <menuitem action='WindowsFileManager'/>"
     "      <menuitem action='WindowsClipboard'/>"
+    "      <menuitem action='WindowsCardManager'/>"
     "    </menu>"
     "    <menu action='Help'>"
 #if 0
@@ -587,6 +588,7 @@
     "    <separator/>"
     "    <toolitem action='WindowsKeyringEditor'/>"
     "    <toolitem action='WindowsClipboard'/>"
+    "    <toolitem action='WindowsCardManager'/>"
 #if 0
     "    <toolitem action='HelpContents'/>"
 #endif
@@ -627,6 +629,8 @@
   /* Fixup the icon theme labels which are too long for the toolbar.  */
   action = gtk_action_group_get_action (action_group, "WindowsKeyringEditor");
   g_object_set (action, "short_label", _("Keyring"), NULL);
+  action = gtk_action_group_get_action (action_group, "WindowsCardManager");
+  g_object_set (action, "short_label", _("Card"), NULL);
 
   /* Take care of sensitiveness of widgets.  */
   action = gtk_action_group_get_action (action_group, "FileSign");

Modified: trunk/src/gpa.c
===================================================================
--- trunk/src/gpa.c	2008-12-10 18:22:34 UTC (rev 919)
+++ trunk/src/gpa.c	2008-12-13 22:34:51 UTC (rev 920)
@@ -35,6 +35,7 @@
 #include "keyring.h"
 #include "fileman.h"
 #include "clipboard.h"
+#include "cardman.h"
 #include "keyserver.h"
 #include "settingsdlg.h"
 #include "confdialog.h"
@@ -61,6 +62,7 @@
   gboolean start_file_manager;
   gboolean start_clipboard;
   gboolean start_settings;
+  gboolean start_card_manager;
   gboolean start_only_server;
   gchar *options_filename;
 } gpa_args_t;
@@ -98,6 +100,8 @@
       N_("Open clipboard"), NULL },
     { "settings", 's', 0, G_OPTION_ARG_NONE, &args.start_settings,
       N_("Open the settings dialog"), NULL },
+    { "card", 'C', 0, G_OPTION_ARG_NONE, &args.start_card_manager,
+      N_("Open the card manager"), NULL },
     { "daemon", 'd', 0, G_OPTION_ARG_NONE, &args.start_only_server,
       N_("Enable the UI server (implies --cms)"), NULL },
     { "options", 'o', 0, G_OPTION_ARG_FILENAME, &args.options_filename,
@@ -161,8 +165,9 @@
 static void
 quit_if_no_window (void)
 {
-  if (! keyringeditor && ! gpa_file_manager_is_open ()
-      && ! gpa_clipboard_is_open () && !args.start_only_server )
+  if (!keyringeditor && !gpa_file_manager_is_open ()
+      && !gpa_clipboard_is_open () && !args.start_only_server
+      && !gpa_card_manager_is_open ())
     gpa_stop_server ();
 }
 
@@ -220,7 +225,19 @@
   gtk_window_present (GTK_WINDOW (gpa_file_manager_get_instance ()));
 }
 
+/* Show the card manager.  */
+void
+gpa_open_cardmanager (GtkAction *action, void *data)
+{
+  /* FIXME: Shouldn't this connect only happen if the instance is
+     created the first time?  Looks like a memory leak to me.  */
+  g_signal_connect (G_OBJECT (gpa_card_manager_get_instance ()), "destroy",
+		    G_CALLBACK (quit_if_no_window), NULL);
+  gtk_widget_show_all (gpa_card_manager_get_instance ());
 
+  gtk_window_present (GTK_WINDOW (gpa_card_manager_get_instance ()));
+}
+
 /* Show the settings dialog.  */
 void
 gpa_open_settings_dialog (GtkAction *action, void *data)
@@ -372,7 +389,8 @@
 
   /* Start the keyring editor by default.  */
   if (!args.start_keyring_editor && !args.start_file_manager
-      && !args.start_clipboard && !args.start_settings)
+      && !args.start_clipboard && !args.start_settings
+      && !args.start_card_manager)
     args.start_keyring_editor = TRUE;
 
   /* Note: We can not use GPGME's engine info, as that returns NULL
@@ -427,6 +445,9 @@
       if (args.start_file_manager || (optind < argc))
 	gpa_open_filemanager (NULL, NULL);
 
+      if (args.start_card_manager)
+	gpa_open_cardmanager (NULL, NULL);
+
       if (args.start_settings)
 	gpa_open_settings_dialog (NULL, NULL);
 

Modified: trunk/src/gpa.h
===================================================================
--- trunk/src/gpa.h	2008-12-10 18:22:34 UTC (rev 919)
+++ trunk/src/gpa.h	2008-12-13 22:34:51 UTC (rev 920)
@@ -60,6 +60,9 @@
 /* Show the filemanager dialog.  */
 void gpa_open_filemanager (GtkAction *action, void *data);
 
+/* Show the cardmanager dialog.  */
+void gpa_open_cardmanager (GtkAction *action, void *data);
+
 /* Show the filemanager dialog.  */
 void gpa_open_clipboard (GtkAction *action, void *data);
 
@@ -73,7 +76,9 @@
       { "WindowsFileManager", GPA_STOCK_FILEMAN, NULL, NULL,
 	N_("Open the file manager"), G_CALLBACK (gpa_open_filemanager) },
       { "WindowsClipboard", GPA_STOCK_CLIPBOARD, NULL, NULL,
-	N_("Open the clipboard"), G_CALLBACK (gpa_open_clipboard) }
+	N_("Open the clipboard"), G_CALLBACK (gpa_open_clipboard) },
+      { "WindowsCardManager", GPA_STOCK_CARDMAN, NULL, NULL,
+	N_("Open the card manager"), G_CALLBACK (gpa_open_cardmanager) }
   };
 
 

Added: trunk/src/gpacardreloadop.c
===================================================================
--- trunk/src/gpacardreloadop.c	2008-12-10 18:22:34 UTC (rev 919)
+++ trunk/src/gpacardreloadop.c	2008-12-13 22:34:51 UTC (rev 920)
@@ -0,0 +1,351 @@
+/* gpacardreloadop.c - The GpaCardReloadOperation object.
+ *	Copyright (C) 2003 Miguel Coca.
+ *	Copyright (C) 2008 g10 Code GmbH.
+ *
+ * This file is part of GPA.
+ *
+ * GPA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GPA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+
+#include <gpgme.h>
+#include "gpa.h"
+#include "i18n.h"
+#include "gtktools.h"
+#include "gpacardreloadop.h"
+
+static GObjectClass *parent_class = NULL;
+
+static void gpa_card_reload_operation_done_cb (GpaContext *context, 
+					       gpg_error_t err,
+					       GpaCardReloadOperation *op);
+
+static void gpa_card_reload_operation_done_error_cb (GpaContext *context, 
+						     gpg_error_t err,
+						     GpaCardReloadOperation *op);
+
+/* We do all the work in the idle loop.  */
+static gboolean gpa_card_reload_operation_idle_cb (gpointer data);
+
+/* GObject boilerplate */
+
+/* Properties of our object.  */
+enum
+{
+  PROP_0,
+  PROP_CARD_RELOAD_CB,
+  PROP_CARD_RELOAD_CB_OPAQUE
+};
+
+static void
+gpa_card_reload_operation_get_property (GObject     *object,
+					guint        prop_id,
+					GValue      *value,
+					GParamSpec  *pspec)
+{
+  GpaCardReloadOperation *op = GPA_CARD_RELOAD_OPERATION (object);
+
+  switch (prop_id)
+    {
+    case PROP_CARD_RELOAD_CB:
+      g_value_set_pointer (value, op->card_reload_cb);
+      break;
+    case PROP_CARD_RELOAD_CB_OPAQUE:
+      g_value_set_pointer (value, op->card_reload_cb_opaque);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gpa_card_reload_operation_set_property (GObject      *object,
+					guint         prop_id,
+					const GValue *value,
+					GParamSpec   *pspec)
+{
+  GpaCardReloadOperation *op = GPA_CARD_RELOAD_OPERATION (object);
+  gpa_card_reload_cb_t cb;
+
+  switch (prop_id)
+    {
+    case PROP_CARD_RELOAD_CB:
+      cb = (gpa_card_reload_cb_t) g_value_get_pointer (value);
+      op->card_reload_cb = cb;
+      break;
+    case PROP_CARD_RELOAD_CB_OPAQUE:
+      op->card_reload_cb_opaque = g_value_get_pointer (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gpa_card_reload_operation_init (GpaCardReloadOperation *op)
+{
+  gpgme_data_t gpgme_output;
+  gpg_error_t err;
+
+  /* Create a new GPGME data handle into which the GPGME output during
+     the card-list operation is written.  */
+  gpgme_output = NULL;
+  err = gpgme_data_new (&gpgme_output);
+  if (err)
+    gpa_gpgme_warning (err);
+
+  op->card_reload_cb = NULL;
+  op->card_reload_cb_opaque = NULL;
+  op->gpgme_output = gpgme_output;
+}
+
+static void
+gpa_card_reload_operation_finalize (GObject *object)
+{
+  /* GpaCardReloadOperation *op = GPA_CARD_RELOAD_OPERATION (object); */
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static GObject*
+gpa_card_reload_operation_constructor (GType type,
+				       guint n_construct_properties,
+				       GObjectConstructParam *construct_properties)
+{
+  GObject *object;
+  GpaCardReloadOperation *op;
+
+  /* Invoke parent's constructor */
+  object = parent_class->constructor (type,
+				      n_construct_properties,
+				      construct_properties);
+  op = GPA_CARD_RELOAD_OPERATION (object);
+
+  /* Connect to the "done" signal */
+  g_signal_connect (G_OBJECT (GPA_OPERATION (op)->context), "done",
+		    G_CALLBACK (gpa_card_reload_operation_done_error_cb), op);
+  g_signal_connect (G_OBJECT (GPA_OPERATION (op)->context), "done",
+		    G_CALLBACK (gpa_card_reload_operation_done_cb), op);
+
+  /* Begin working when we are back into the main loop */
+  g_idle_add (gpa_card_reload_operation_idle_cb, op);
+
+  return object;
+}
+
+static void
+gpa_card_reload_operation_class_init (GpaCardReloadOperationClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  
+  parent_class = g_type_class_peek_parent (klass);
+
+  object_class->constructor = gpa_card_reload_operation_constructor;
+  object_class->finalize = gpa_card_reload_operation_finalize;
+  object_class->set_property = gpa_card_reload_operation_set_property;
+  object_class->get_property = gpa_card_reload_operation_get_property;
+
+  /* Properties */
+  g_object_class_install_property (object_class,
+				   PROP_CARD_RELOAD_CB,
+				   g_param_spec_pointer 
+				   ("card_reload_cb", "card_reload_cb",
+				    "card_reload_cb",
+				    G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY));
+  g_object_class_install_property (object_class,
+				   PROP_CARD_RELOAD_CB_OPAQUE,
+				   g_param_spec_pointer 
+				   ("card_reload_cb_opaque", "card_reload_cb_opaque",
+				    "card_reload_cb_opaque",
+				    G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY));
+}
+
+GType
+gpa_card_reload_operation_get_type (void)
+{
+  static GType operation_type = 0;
+  
+  if (!operation_type)
+    {
+      static const GTypeInfo operation_info =
+      {
+        sizeof (GpaCardReloadOperationClass),
+        (GBaseInitFunc) NULL,
+        (GBaseFinalizeFunc) NULL,
+        (GClassInitFunc) gpa_card_reload_operation_class_init,
+        NULL,           /* class_finalize */
+        NULL,           /* class_data */
+        sizeof (GpaCardReloadOperation),
+        0,              /* n_preallocs */
+        (GInstanceInitFunc) gpa_card_reload_operation_init,
+      };
+      
+      operation_type = g_type_register_static (GPA_OPERATION_TYPE,
+					       "GpaCardReloadOperation",
+					       &operation_info, 0);
+    }
+  
+  return operation_type;
+}
+
+/* API */
+
+GpaCardReloadOperation *
+gpa_card_reload_operation_new (GtkWidget *window, gpa_card_reload_cb_t cb, void *opaque)
+{
+  GpaCardReloadOperation *op;
+  
+  op = g_object_new (GPA_CARD_RELOAD_OPERATION_TYPE,
+		     "window", window,
+		     "card_reload_cb", cb,
+		     "card_reload_cb_opaque", opaque,
+		     NULL);
+
+  return op;
+}
+
+/* Internal */
+
+/* Called during idle loop; triggers the actual GPGME card-list
+   operation.  */
+static gboolean
+gpa_card_reload_operation_idle_cb (gpointer data)
+{
+  GpaCardReloadOperation *op = data;
+  gpg_error_t err;
+
+  err = gpa_gpgme_card_edit_list_start (GPA_OPERATION(op)->context,
+					op->gpgme_output);
+  if (err)
+    g_signal_emit_by_name (GPA_OPERATION (op), "completed", err);
+  
+  return FALSE;
+}
+
+/* Processes the line LINE, calling the callback CB with it's opaque
+   argument for each data item. Modifies LINE. */
+static void
+process_line (char *line, gpa_card_reload_cb_t cb, void *opaque)
+{
+  char *save_ptr = NULL;
+  char *identifier;
+  int idx;
+
+  idx = 0;
+  identifier = strtok_r (line, ":", &save_ptr);
+  if (!identifier)
+    /* FIXME: maybe an assert here? -mo */
+    return;
+
+  while (1)
+    {
+      char *token;
+
+      token = strtok_r (NULL, ":", &save_ptr);
+      if (token)
+	{
+	  (*cb) (opaque, identifier, idx, token);
+	  idx++;
+	}
+      else
+	break;
+    }
+}
+
+/* Processes the GPGME output contained in OUT, calling the callback
+   CB with it's opaque argument OPAQUE for each data item. */
+static void
+process_gpgme_output (gpgme_data_t out, gpa_card_reload_cb_t cb, void *opaque)
+{
+  char *data;
+  size_t data_length;
+  FILE *stream;
+  ssize_t ret;
+  char *line;
+  size_t line_length;
+
+  /* FIXME: this function is NOT portable!!!! -mo */
+
+  data = gpgme_data_release_and_get_mem (out, &data_length);
+  stream = fmemopen (data, data_length, "r");
+  if (!stream)
+    {
+      fprintf (stderr, "Ooops! Fatal error durign fmemopen (%s) occured. How to handle??\n",
+	       strerror (errno));
+      exit (1);
+    }
+
+  while (1)
+    {
+      line = NULL;
+      line_length = 0;
+
+      ret = getline (&line, &line_length, stream);
+      if (ret == -1)
+	{
+	  if (ferror (stream))
+	    {
+	      fprintf (stderr, "Ooops! Fatal error during getline (%s) occured. How to handle??\n",
+		       strerror (errno));
+	      exit (1);
+	    }
+	  else
+	    /* This must be EOF, no? */
+	    break;
+	}
+
+      process_line (line, cb, opaque);
+      free (line);
+    }
+
+  fclose (stream);
+  gpgme_free (data);
+}
+
+static void
+gpa_card_reload_operation_done_cb (GpaContext *context, 
+				   gpg_error_t err,
+				   GpaCardReloadOperation *op)
+{
+  if (!err)
+    {
+      /* Note: this releases op->gpgme_output! */
+      process_gpgme_output (op->gpgme_output,
+			    op->card_reload_cb,
+			    op->card_reload_cb_opaque);
+    }
+  g_signal_emit_by_name (op, "completed", err);
+}
+
+
+static void
+gpa_card_reload_operation_done_error_cb (GpaContext *context, 
+					 gpg_error_t err,
+					 GpaCardReloadOperation *op)
+{
+  switch (gpg_err_code (err))
+    {
+    case GPG_ERR_NO_ERROR:
+    case GPG_ERR_CANCELED:
+      /* Ignore these */
+      break;
+    default:
+      gpa_gpgme_warning (err);
+      break;
+    }
+}

Added: trunk/src/gpacardreloadop.h
===================================================================
--- trunk/src/gpacardreloadop.h	2008-12-10 18:22:34 UTC (rev 919)
+++ trunk/src/gpacardreloadop.h	2008-12-13 22:34:51 UTC (rev 920)
@@ -0,0 +1,74 @@
+/* gpacardreloadop.h - The GpaCardReloadOperation object.
+ *	Copyright (C) 2003 Miguel Coca.
+ *	Copyright (C) 2008 g10 Code GmbH.
+ *
+ * This file is part of GPA.
+ *
+ * GPA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GPA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef GPA_CARD_RELOAD_OP_H
+#define GPA_CARD_RELOAD_OP_H
+
+#include "gpa.h"
+#include <glib.h>
+#include <glib-object.h>
+#include "gpgmeedit.h"
+#include "gpaoperation.h"
+
+/* GObject stuff */
+#define GPA_CARD_RELOAD_OPERATION_TYPE (gpa_card_reload_operation_get_type ())
+#define GPA_CARD_RELOAD_OPERATION(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GPA_CARD_RELOAD_OPERATION_TYPE, GpaCardReloadOperation))
+#define GPA_CARD_RELOAD_OPERATION_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), GPA_CARD_RELOAD_OPERATION_TYPE, GpaCardReloadOperationClass))
+#define GPA_IS_CARD_RELOAD_OPERATION(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GPA_CARD_RELOAD_OPERATION_TYPE))
+#define GPA_IS_CARD_RELOAD_OPERATION_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), GPA_CARD_RELOAD_OPERATION_TYPE))
+#define GPA_CARD_RELOAD_OPERATION_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), GPA_CARD_RELOAD_OPERATION_TYPE, GpaCardReloadOperationClass))
+
+typedef struct _GpaCardReloadOperation GpaCardReloadOperation;
+typedef struct _GpaCardReloadOperationClass GpaCardReloadOperationClass;
+
+/* Type for the callback passed to GpaCardReloadOp object creation,
+   which is used for passing card data items to the caller. */
+typedef void (*gpa_card_reload_cb_t) (void *opaque,
+				      const char *identifier, int idx, const void *value);
+
+struct _GpaCardReloadOperation {
+  GpaOperation parent;
+
+  gpa_card_reload_cb_t card_reload_cb;
+  void *card_reload_cb_opaque;
+  gpgme_data_t gpgme_output;
+};
+
+struct _GpaCardReloadOperationClass {
+  GpaOperationClass parent_class;
+};
+
+GType gpa_card_reload_operation_get_type (void) G_GNUC_CONST;
+
+/* API */					   
+
+/* Create a new GpaCardReloadOperation object. Use CB for passing card
+   data items to the caller. OPAQUE is the opaque argument for CB.  */
+GpaCardReloadOperation *gpa_card_reload_operation_new (GtkWidget *window,
+						       gpa_card_reload_cb_t cb,
+						       void *opaque);
+
+#endif

Modified: trunk/src/gpagenkeyadvop.c
===================================================================
--- trunk/src/gpagenkeyadvop.c	2008-12-10 18:22:34 UTC (rev 919)
+++ trunk/src/gpagenkeyadvop.c	2008-12-13 22:34:51 UTC (rev 920)
@@ -152,7 +152,7 @@
   gpg_error_t err;
   GPAKeyGenParameters *parms;
   
-  parms = gpa_key_gen_run_dialog (GPA_OPERATION (op)->window);
+  parms = gpa_key_gen_run_dialog (GPA_OPERATION (op)->window, 0);
   if (!parms)
     g_signal_emit_by_name (op, "completed", gpg_error (GPG_ERR_CANCELED));
   else

Added: trunk/src/gpagenkeycardop.c
===================================================================
--- trunk/src/gpagenkeycardop.c	2008-12-10 18:22:34 UTC (rev 919)
+++ trunk/src/gpagenkeycardop.c	2008-12-13 22:34:51 UTC (rev 920)
@@ -0,0 +1,209 @@
+/* gpagenkeycardop.c - The GpaGenKeyCardOperation object.
+ *	Copyright (C) 2003 Miguel Coca.
+ *	Copyright (C) 2008 g10 Code GmbH
+ *
+ * This file is part of GPA
+ *
+ * GPA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GPA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+
+#include <gpgme.h>
+#include "gpa.h"
+#include "i18n.h"
+#include "gtktools.h"
+#include "gpagenkeycardop.h"
+#include "keygendlg.h"
+
+static GObjectClass *parent_class = NULL;
+
+static void gpa_gen_key_card_operation_done_cb (GpaContext *context, 
+						    gpg_error_t err,
+						    GpaGenKeyCardOperation *op);
+
+static void gpa_gen_key_card_operation_done_error_cb (GpaContext *context, 
+							  gpg_error_t err,
+							  GpaGenKeyCardOperation *op);
+
+
+static gboolean
+gpa_gen_key_card_operation_idle_cb (gpointer data);
+
+/* GObject boilerplate */
+
+static void
+gpa_gen_key_card_operation_init (GpaGenKeyCardOperation *op)
+{
+  op->progress_dialog = NULL;
+}
+
+static void
+gpa_gen_key_card_operation_finalize (GObject *object)
+{
+  GpaGenKeyCardOperation *op = GPA_GEN_KEY_CARD_OPERATION (object);
+
+  gtk_widget_destroy (op->progress_dialog);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static GObject*
+gpa_gen_key_card_operation_constructor (GType type,
+					    guint n_construct_properties,
+					    GObjectConstructParam *
+					    construct_properties)
+{
+  GObject *object;
+  GpaGenKeyCardOperation *op;
+
+  /* Invoke parent's constructor */
+  object = parent_class->constructor (type,
+				      n_construct_properties,
+				      construct_properties);
+  op = GPA_GEN_KEY_CARD_OPERATION (object);
+
+  /* Create progress dialog */
+  op->progress_dialog = gpa_progress_dialog_new (GPA_OPERATION (op)->window,
+						 GPA_OPERATION (op)->context);
+  gpa_progress_dialog_set_label (GPA_PROGRESS_DIALOG (op->progress_dialog),
+				 _("Generating Key..."));
+
+  /* Connect to the "done" signal */
+  g_signal_connect (G_OBJECT (GPA_OPERATION (op)->context), "done",
+		    G_CALLBACK (gpa_gen_key_card_operation_done_error_cb), op);
+  g_signal_connect (G_OBJECT (GPA_OPERATION (op)->context), "done",
+		    G_CALLBACK (gpa_gen_key_card_operation_done_cb), op);
+
+  /* Begin working when we are back into the main loop */
+  g_idle_add (gpa_gen_key_card_operation_idle_cb, op);
+
+  return object;
+}
+
+static void
+gpa_gen_key_card_operation_class_init (GpaGenKeyCardOperationClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  
+  parent_class = g_type_class_peek_parent (klass);
+
+  object_class->constructor = gpa_gen_key_card_operation_constructor;
+  object_class->finalize = gpa_gen_key_card_operation_finalize;
+}
+
+GType
+gpa_gen_key_card_operation_get_type (void)
+{
+  static GType operation_type = 0;
+  
+  if (!operation_type)
+    {
+      static const GTypeInfo operation_info =
+      {
+        sizeof (GpaGenKeyCardOperationClass),
+        (GBaseInitFunc) NULL,
+        (GBaseFinalizeFunc) NULL,
+        (GClassInitFunc) gpa_gen_key_card_operation_class_init,
+        NULL,           /* class_finalize */
+        NULL,           /* class_data */
+        sizeof (GpaGenKeyCardOperation),
+        0,              /* n_preallocs */
+        (GInstanceInitFunc) gpa_gen_key_card_operation_init,
+      };
+      
+      operation_type = g_type_register_static (GPA_GEN_KEY_OPERATION_TYPE,
+					       "GpaGenKeyCardOperation",
+					       &operation_info, 0);
+    }
+  
+  return operation_type;
+}
+
+/* API */
+
+GpaGenKeyCardOperation* 
+gpa_gen_key_card_operation_new (GtkWidget *window)
+{
+  GpaGenKeyCardOperation *op;
+  
+  op = g_object_new (GPA_GEN_KEY_CARD_OPERATION_TYPE,
+		     "window", window, NULL);
+
+  return op;
+}
+
+/* Internal */
+
+static gboolean
+gpa_gen_key_card_operation_idle_cb (gpointer data)
+{
+  GpaGenKeyCardOperation *op = data;
+  gpg_error_t err;
+  GPAKeyGenParameters *parms;
+  
+  parms = gpa_key_gen_run_dialog (GPA_OPERATION (op)->window, 1);
+#if 0
+  if (!parms)
+    g_signal_emit_by_name (op, "completed", gpg_error (GPG_ERR_CANCELED));
+  else
+    {
+      err = gpa_generate_key_start (GPA_OPERATION (op)->context->ctx, parms);
+      if (err)
+        {
+          gpa_gpgme_warning (err);
+          g_signal_emit_by_name (op, "completed", err);
+        }
+      else
+        gtk_widget_show_all (op->progress_dialog);
+    }
+#else
+  g_signal_emit_by_name (op, "completed", gpg_error (GPG_ERR_CANCELED));
+#endif
+
+  return FALSE;
+}
+
+
+static void
+gpa_gen_key_card_operation_done_cb (GpaContext *context, 
+					gpg_error_t err,
+					GpaGenKeyCardOperation *op)
+{
+  if (! err)
+    {
+      gpgme_genkey_result_t result = gpgme_op_genkey_result (context->ctx);
+      g_signal_emit_by_name (op, "generated_key", result->fpr);
+    }
+  g_signal_emit_by_name (op, "completed", err);
+}
+
+
+static void
+gpa_gen_key_card_operation_done_error_cb (GpaContext *context, 
+					      gpg_error_t err,
+					      GpaGenKeyCardOperation *op)
+{
+  switch (gpg_err_code (err))
+    {
+    case GPG_ERR_NO_ERROR:
+    case GPG_ERR_CANCELED:
+      /* Ignore these */
+      break;
+    default:
+      gpa_gpgme_warning (err);
+      break;
+    }
+}

Added: trunk/src/gpagenkeycardop.h
===================================================================
--- trunk/src/gpagenkeycardop.h	2008-12-10 18:22:34 UTC (rev 919)
+++ trunk/src/gpagenkeycardop.h	2008-12-13 22:34:51 UTC (rev 920)
@@ -0,0 +1,59 @@
+/* gpagenkeycardop.h - The GpaGenKeyCardOperation object.
+ *	Copyright (C) 2003 Miguel Coca.
+ *	Copyright (C) 2008 g10 Code GmbH
+ *
+ * This file is part of GPA
+ *
+ * GPA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GPA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef GPA_GEN_KEY_CARD_OP_H
+#define GPA_GEN_KEY_CARD_OP_H
+
+#include "gpa.h"
+#include <glib.h>
+#include <glib-object.h>
+#include "gpagenkeyop.h"
+#include "gpaprogressdlg.h"
+
+/* GObject stuff */
+#define GPA_GEN_KEY_CARD_OPERATION_TYPE	  (gpa_gen_key_card_operation_get_type ())
+#define GPA_GEN_KEY_CARD_OPERATION(obj)	  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GPA_GEN_KEY_CARD_OPERATION_TYPE, GpaGenKeyCardOperation))
+#define GPA_GEN_KEY_CARD_OPERATION_CLASS(klass)  (G_TYPE_CHECK_CLASS_CAST ((klass), GPA_GEN_KEY_CARD_OPERATION_TYPE, GpaGenKeyCardOperationClass))
+#define GPA_IS_GEN_KEY_CARD_OPERATION(obj)	  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GPA_GEN_KEY_CARD_OPERATION_TYPE))
+#define GPA_IS_GEN_KEY_CARD_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GPA_GEN_KEY_CARD_OPERATION_TYPE))
+#define GPA_GEN_KEY_CARD_OPERATION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GPA_GEN_KEY_CARD_OPERATION_TYPE, GpaGenKeyCardOperationClass))
+
+typedef struct _GpaGenKeyCardOperation GpaGenKeyCardOperation;
+typedef struct _GpaGenKeyCardOperationClass GpaGenKeyCardOperationClass;
+
+struct _GpaGenKeyCardOperation {
+  GpaGenKeyOperation parent;
+
+  GtkWidget *progress_dialog;
+};
+
+struct _GpaGenKeyCardOperationClass {
+  GpaGenKeyOperationClass parent_class;
+
+};
+
+GType gpa_gen_key_card_operation_get_type (void) G_GNUC_CONST;
+
+/* API */
+
+GpaGenKeyCardOperation *gpa_gen_key_card_operation_new (GtkWidget *window);
+
+#endif

Modified: trunk/src/gpgmeedit.c
===================================================================
--- trunk/src/gpgmeedit.c	2008-12-10 18:22:34 UTC (rev 919)
+++ trunk/src/gpgmeedit.c	2008-12-13 22:34:51 UTC (rev 920)
@@ -88,6 +88,7 @@
   char *result = NULL;
 
   /* Ignore these status lines, as they don't require any response */
+  /* FIXME: should GPGME_STATUS_CARDCTRL be included here as well? -mo */
   if (status == GPGME_STATUS_EOF 
       || status == GPGME_STATUS_GOT_IT
       || status == GPGME_STATUS_NEED_PASSPHRASE
@@ -1068,3 +1069,205 @@
 
   return err;
 }
+
+/*
+ * Card related code.
+ */
+
+typedef enum
+  {
+    CARD_START,
+    CARD_COMMAND,
+    CARD_ADMIN_COMMAND,
+    CARD_QUIT,
+    CARD_QUERY_LOGIN,
+    CARD_ERROR
+  } CardState;
+
+/* Implementation of the card-list operation. */
+
+/* Action function for card-list.  */
+static gpg_error_t
+card_edit_list_fnc_action (int state, void *opaque, char **result)
+{
+  switch (state)
+    {
+    case CARD_COMMAND:
+      *result = "list";
+      break;
+    case CARD_QUIT:
+      *result = "quit";
+      break;
+    default:
+      return gpg_error (GPG_ERR_GENERAL);
+    }
+  return 0;
+}
+
+/* Transit function for card-list.  */
+static int
+card_edit_list_fnc_transit (int current_state, gpgme_status_code_t status,
+			    const char *args, void *opaque, gpg_error_t *err)
+{
+  int next_state;
+
+  switch (current_state)
+    {
+    case CARD_START:
+      if (status == GPGME_STATUS_CARDCTRL)
+	/* Consume GPGME_STATUS_CARDCTRL and stay in CARD_START state. */
+	next_state = CARD_START;
+      else if (status == GPGME_STATUS_GET_LINE)
+	next_state = CARD_COMMAND;
+      break;
+    case CARD_COMMAND:
+      next_state = CARD_QUIT;
+      break;
+    default:
+      next_state = CARD_ERROR;
+      *err = gpg_error (GPG_ERR_GENERAL);
+    }
+
+  return next_state;
+}
+
+static void
+gpa_gpgme_card_edit_list_parms_release (GpaContext *ctx, gpg_error_t err,
+					struct edit_parms_s *parms)
+{
+  /* FIXME: is this correct? -mo */
+
+  if (parms->signal_id != 0)
+    g_signal_handler_disconnect (ctx, parms->signal_id);
+  g_free (parms);
+}
+
+/* Triggers card list operation through CTX. OUT is a valid GPGME data
+   handle which is filled during the operation with the list
+   output. */
+gpg_error_t
+gpa_gpgme_card_edit_list_start (GpaContext *ctx, gpgme_data_t out)
+{
+  struct edit_parms_s *parms = g_malloc (sizeof (struct edit_parms_s));
+  gpg_error_t err;
+
+  parms->state = CARD_START;
+  parms->err = 0;
+  parms->action = card_edit_list_fnc_action;
+  parms->transit = card_edit_list_fnc_transit;
+  parms->out = out;
+  parms->opaque = NULL;
+  parms->signal_id = g_signal_connect (G_OBJECT (ctx), "done",
+				       G_CALLBACK (gpa_gpgme_card_edit_list_parms_release),
+				       parms);
+
+  err = gpgme_op_card_edit_start (ctx->ctx, NULL, edit_fnc, parms, out);
+
+  return err;
+}
+
+#if 0				/* DISABLED */
+
+/* Modify. */
+
+static gpg_error_t
+card_edit_modify_fnc_action (int state, void *opaque, char **result)
+{
+  switch (state)
+    {
+    case CARD_START:
+      /* Nothing to do here. (?) */
+      break;
+    case CARD_COMMAND:
+      *result = "admin";
+      break;
+    case CARD_ADMIN_COMMAND:
+      *result = "login";
+      break;
+    case CARD_QUERY_LOGIN:
+      *result = (char *) opaque;
+      break;
+    case CARD_QUIT:
+      *result = "quit";
+      break;
+    default:
+      return gpg_error (GPG_ERR_GENERAL);
+    }
+  return 0;
+}
+
+static int
+card_edit_modify_fnc_transit (int current_state, gpgme_status_code_t status,
+			      const char *args, void *opaque, gpg_error_t *err)
+{
+  int next_state;
+
+  switch (current_state)
+    {
+    case CARD_START:
+      if (status == GPGME_STATUS_CARDCTRL)
+	/* Consume GPGME_STATUS_CARDCTRL and stay in CARD_START state. */
+	next_state = CARD_START;
+      else if (status == GPGME_STATUS_GET_LINE)
+	next_state = CARD_COMMAND;
+      break;
+    case CARD_COMMAND:
+      /* Dummy: */
+      next_state = CARD_ADMIN_COMMAND;
+      break;
+    case CARD_ADMIN_COMMAND:
+      fprintf (stderr, "[in CARD_ADMIN_COMMAND, status = %i\n", status);
+      /* FIXME! check status.  */
+      next_state = CARD_QUERY_LOGIN;
+      break;
+    case CARD_QUERY_LOGIN:
+      next_state = CARD_QUIT;
+      break;
+    default:
+      next_state = CARD_ERROR;
+      *err = gpg_error (GPG_ERR_GENERAL);
+    }
+
+  return next_state;
+}
+
+static void
+gpa_gpgme_card_edit_modify_parms_release (GpaContext *ctx, gpg_error_t err,
+					  struct edit_parms_s *parms)
+{
+  /* FIXME: i don't really understand this. -mo */
+  gpgme_data_release (parms->out);
+  if (parms->signal_id != 0)
+    g_signal_handler_disconnect (ctx, parms->signal_id);
+  g_free (parms->opaque);
+  g_free (parms);
+}
+
+gpg_error_t
+gpa_gpgme_card_edit_modify_start (GpaContext *ctx, const gchar *login)
+{
+  struct edit_parms_s *parms = g_malloc (sizeof (struct edit_parms_s));
+  gpg_error_t err;
+  gpgme_data_t out;
+  char *serialno = NULL;
+
+  err = gpgme_data_new (&out);
+  if (err)
+    return err;
+
+  parms->state = CARD_START;
+  parms->err = 0;
+  parms->action = card_edit_modify_fnc_action;
+  parms->transit = card_edit_modify_fnc_transit;
+  parms->out = out;
+  parms->opaque = g_strdup (login);
+  parms->signal_id = g_signal_connect (G_OBJECT (ctx), "done",
+				       G_CALLBACK (gpa_gpgme_card_edit_modify_parms_release),
+				       parms);
+
+  err = gpgme_op_card_edit_start (ctx->ctx, NULL, edit_fnc, parms, out);
+
+  return err;
+}
+
+#endif	/* DISABLED */

Modified: trunk/src/gpgmeedit.h
===================================================================
--- trunk/src/gpgmeedit.h	2008-12-10 18:22:34 UTC (rev 919)
+++ trunk/src/gpgmeedit.h	2008-12-13 22:34:51 UTC (rev 920)
@@ -46,4 +46,14 @@
  */
 gpg_error_t gpa_gpgme_edit_passwd_start (GpaContext *ctx, gpgme_key_t key);
 
+/* Triggers card list operation through CTX. OUT is a valid GPGME data
+   handle which is filled during the operation with the list
+   output. */
+gpg_error_t gpa_gpgme_card_edit_list_start (GpaContext *ctx, gpgme_data_t out);
+
+#if 0
+gpg_error_t gpa_gpgme_card_edit_genkey_start (GpaContext *ctx, ...);
+gpg_error_t gpa_gpgme_card_edit_modify_start (GpaContext *ctx, const gchar *login);
 #endif
+
+#endif

Modified: trunk/src/icons.c
===================================================================
--- trunk/src/icons.c	2008-12-10 18:22:34 UTC (rev 919)
+++ trunk/src/icons.c	2008-12-13 22:34:51 UTC (rev 920)
@@ -184,6 +184,12 @@
   icon_set = gtk_icon_set_copy (icon_set);
   gtk_icon_factory_add (icon_factory, GPA_STOCK_FILEMAN, icon_set);
 
+  /* Add a fake stock icon for the card manager window.  */
+  /* FIXME: this is a FLOPPY icon. We need a smartcard icon. -mo */
+  icon_set = gtk_icon_factory_lookup_default (GTK_STOCK_FLOPPY);
+  icon_set = gtk_icon_set_copy (icon_set);
+  gtk_icon_factory_add (icon_factory, GPA_STOCK_CARDMAN, icon_set);
+
   gtk_icon_factory_add_default (icon_factory); 
 
   g_object_unref (icon_factory);
@@ -203,7 +209,8 @@
       { GPA_STOCK_DETAILED, N_("_Detailed"), 0, 0, PACKAGE },
       { GPA_STOCK_KEYRING, N_("_Keyring Editor"), 0, 0, PACKAGE },
       { GPA_STOCK_CLIPBOARD, N_("_Clipboard"), 0, 0, PACKAGE },
-      { GPA_STOCK_FILEMAN, N_("_File Manager"), 0, 0, PACKAGE }
+      { GPA_STOCK_FILEMAN, N_("_File Manager"), 0, 0, PACKAGE },
+      { GPA_STOCK_CARDMAN, N_("_Card Manager"), 0, 0, PACKAGE }
     };
 
   register_stock_icons ();

Modified: trunk/src/icons.h
===================================================================
--- trunk/src/icons.h	2008-12-10 18:22:34 UTC (rev 919)
+++ trunk/src/icons.h	2008-12-13 22:34:51 UTC (rev 920)
@@ -39,6 +39,7 @@
 #define GPA_STOCK_KEYRING "gpa-keyringeditor"
 #define GPA_STOCK_FILEMAN "gpa-fileman"
 #define GPA_STOCK_CLIPBOARD "gpa-clipboard"
+#define GPA_STOCK_CARDMAN "gpa-cardman"
 
 /* Toolbar in keyring editor.  */
 #define GPA_STOCK_BRIEF "gpa-brief"

Modified: trunk/src/keygendlg.c
===================================================================
--- trunk/src/keygendlg.c	2008-12-10 18:22:34 UTC (rev 919)
+++ trunk/src/keygendlg.c	2008-12-13 22:34:51 UTC (rev 920)
@@ -34,6 +34,8 @@
 
 struct _GPAKeyGenDialog
 {
+  gboolean forcard;		/* Specifies if this is a dialog for
+				   on-card key generation or not. */
   GtkWidget *window;
   GtkWidget *entryUserID;
   GtkWidget *entryPasswd;
@@ -72,21 +74,21 @@
       gpa_window_error (_("You must enter a User ID."), dialog->window);
       g_signal_stop_emission_by_name (dlg, "response");
     }
-  else if (!g_str_equal (passwd, repeat))
+  else if ((!dialog->forcard) && (!g_str_equal (passwd, repeat)))
     {
       gpa_window_error (_("In \"Passphrase\" and \"Repeat passphrase\",\n"
 			  "you must enter the same passphrase."),
 			dialog->window);
       g_signal_stop_emission_by_name (dlg, "response");
     }
-  else if (strlen (passwd) == 0)
+  else if ((!dialog->forcard) && strlen (passwd) == 0)
     {
       gpa_window_error (_("You did not enter a passphrase.\n"
 			  "It is needed to protect your private key."),
 			dialog->window);
       g_signal_stop_emission_by_name (dlg, "response");
     }
-  else if (strlen (passwd) < 10 || qdchkpwd (passwd) < 0.6)
+  else if ((!dialog->forcard) && (strlen (passwd) < 10 || qdchkpwd (passwd) < 0.6))
     {
       GtkWidget *msgbox;
       
@@ -117,10 +119,12 @@
 
 /* Run the "Generate Key" dialog and if the user presses OK, return
    the values from the dialog in a newly allocated GPAKeyGenParameters
-   struct.  If the user pressed "Cancel", return NULL.  The returned
-   struct has to be deleted with gpa_key_gen_free_parameters.  */
+   struct.  If FORCARD is true, display the dialog suitable for
+   generation keys on the OpenPGP smartcard. If the user pressed
+   "Cancel", return NULL.  The returned struct has to be deleted with
+   gpa_key_gen_free_parameters.  */
 GPAKeyGenParameters *
-gpa_key_gen_run_dialog (GtkWidget *parent)
+gpa_key_gen_run_dialog (GtkWidget *parent, gboolean forcard)
 {
   GtkWidget *windowGenerate;
   GtkWidget *vboxGenerate;
@@ -146,6 +150,8 @@
 
   GPAKeyGenAlgo algo;
 
+  dialog.forcard = forcard;
+
   windowGenerate = gtk_dialog_new_with_buttons
     (_("Generate key"), GTK_WINDOW (parent),
      GTK_DIALOG_MODAL,
@@ -180,9 +186,16 @@
 		    GTK_FILL, GTK_SHRINK, 0, 0);
   comboAlgorithm = gtk_combo_box_new_text ();
 
-  for (algo = GPA_KEYGEN_ALGO_FIRST; algo <= GPA_KEYGEN_ALGO_LAST; algo++)
-    gtk_combo_box_append_text (GTK_COMBO_BOX (comboAlgorithm), 
-				 gpa_algorithm_string (algo));
+  if (forcard)
+    /* The OpenPGP smartcard does only support RSA. */
+    gtk_combo_box_append_text (GTK_COMBO_BOX (comboAlgorithm),
+			       gpa_algorithm_string (GPA_KEYGEN_ALGO_RSA));
+  else
+    {
+      for (algo = GPA_KEYGEN_ALGO_FIRST; algo <= GPA_KEYGEN_ALGO_LAST; algo++)
+	gtk_combo_box_append_text (GTK_COMBO_BOX (comboAlgorithm), 
+				   gpa_algorithm_string (algo));
+    }
   gtk_combo_box_set_active (GTK_COMBO_BOX (comboAlgorithm), 0);
   gtk_label_set_mnemonic_widget (GTK_LABEL (labelAlgorithm), comboAlgorithm);
 			      
@@ -193,12 +206,23 @@
   gtk_misc_set_alignment (GTK_MISC (labelKeysize), 1.0, 0.5);
   gtk_table_attach (GTK_TABLE (table), labelKeysize, 0, 1, 1, 2,
 		    GTK_FILL, GTK_SHRINK, 0, 0);
-  comboKeysize = gtk_combo_box_entry_new_text ();
+  comboKeysize = gtk_combo_box_new_text ();
   dialog.comboKeysize = comboKeysize;
-  gtk_combo_box_append_text (GTK_COMBO_BOX (comboKeysize), _("768"));
-  gtk_combo_box_append_text (GTK_COMBO_BOX (comboKeysize), _("1024"));
-  gtk_combo_box_append_text (GTK_COMBO_BOX (comboKeysize), _("2048"));
-  gtk_combo_box_set_active (GTK_COMBO_BOX (comboKeysize), 1 /* 1024 */);
+
+  if (forcard)
+    {
+      /* The OpenPGP smartcard does only support 1024bit RSA
+	 keys. FIXME: should we really hardcode this? -mo */
+      gtk_combo_box_append_text (GTK_COMBO_BOX (comboKeysize), _("1024"));
+      gtk_combo_box_set_active (GTK_COMBO_BOX (comboKeysize), 0);
+    }
+  else
+    {
+      gtk_combo_box_append_text (GTK_COMBO_BOX (comboKeysize), _("768"));
+      gtk_combo_box_append_text (GTK_COMBO_BOX (comboKeysize), _("1024"));
+      gtk_combo_box_append_text (GTK_COMBO_BOX (comboKeysize), _("2048"));
+      gtk_combo_box_set_active (GTK_COMBO_BOX (comboKeysize), 1 /* 1024 */);
+    }
   gtk_label_set_mnemonic_widget (GTK_LABEL (labelKeysize), comboKeysize);
   gtk_table_attach (GTK_TABLE (table), comboKeysize, 1, 2, 1, 2,
 		    GTK_FILL, GTK_SHRINK, 0, 0);
@@ -232,28 +256,37 @@
   gtk_table_attach (GTK_TABLE (table), entryComment, 1, 2, 4, 5, GTK_FILL,
 		    GTK_SHRINK, 0, 0);
 
-  labelPasswd = gtk_label_new_with_mnemonic (_("_Passphrase: "));
-  gtk_misc_set_alignment (GTK_MISC (labelPasswd), 1.0, 0.5);
-  gtk_table_attach (GTK_TABLE (table), labelPasswd, 0, 1, 5, 6,
-		    GTK_FILL, GTK_SHRINK, 0, 0);
-  entryPasswd = gtk_entry_new ();
-  dialog.entryPasswd = entryPasswd;
-  gtk_entry_set_visibility (GTK_ENTRY (entryPasswd), FALSE);
-  gtk_label_set_mnemonic_widget (GTK_LABEL (labelPasswd), entryPasswd);
-  gtk_table_attach (GTK_TABLE (table), entryPasswd, 1, 2, 5, 6, GTK_FILL,
-		    GTK_SHRINK, 0, 0);
+  if (forcard)
+    {
+      /* This doesn't make sense for the smartcard. */
+      dialog.entryPasswd = NULL;
+      dialog.entryRepeat = NULL;
+    }
+  else
+    {
+      labelPasswd = gtk_label_new_with_mnemonic (_("_Passphrase: "));
+      gtk_misc_set_alignment (GTK_MISC (labelPasswd), 1.0, 0.5);
+      gtk_table_attach (GTK_TABLE (table), labelPasswd, 0, 1, 5, 6,
+			GTK_FILL, GTK_SHRINK, 0, 0);
+      entryPasswd = gtk_entry_new ();
+      dialog.entryPasswd = entryPasswd;
+      gtk_entry_set_visibility (GTK_ENTRY (entryPasswd), FALSE);
+      gtk_label_set_mnemonic_widget (GTK_LABEL (labelPasswd), entryPasswd);
+      gtk_table_attach (GTK_TABLE (table), entryPasswd, 1, 2, 5, 6, GTK_FILL,
+			GTK_SHRINK, 0, 0);
 
-  labelRepeat = gtk_label_new_with_mnemonic (_("_Repeat passphrase: "));
-  gtk_misc_set_alignment (GTK_MISC (labelRepeat), 1.0, 0.5);
-  gtk_table_attach (GTK_TABLE (table), labelRepeat, 0, 1, 6, 7,
-		    GTK_FILL, GTK_SHRINK, 0, 0);
-  entryRepeat = gtk_entry_new ();
-  dialog.entryRepeat = entryRepeat;
-  gtk_entry_set_visibility (GTK_ENTRY (entryRepeat), FALSE);
-  gtk_label_set_mnemonic_widget (GTK_LABEL (labelRepeat), entryRepeat);
+      labelRepeat = gtk_label_new_with_mnemonic (_("_Repeat passphrase: "));
+      gtk_misc_set_alignment (GTK_MISC (labelRepeat), 1.0, 0.5);
+      gtk_table_attach (GTK_TABLE (table), labelRepeat, 0, 1, 6, 7,
+			GTK_FILL, GTK_SHRINK, 0, 0);
+      entryRepeat = gtk_entry_new ();
+      dialog.entryRepeat = entryRepeat;
+      gtk_entry_set_visibility (GTK_ENTRY (entryRepeat), FALSE);
+      gtk_label_set_mnemonic_widget (GTK_LABEL (labelRepeat), entryRepeat);
 
-  gtk_table_attach (GTK_TABLE (table), entryRepeat, 1, 2, 6, 7,
-		    GTK_FILL, GTK_SHRINK, 0, 0);
+      gtk_table_attach (GTK_TABLE (table), entryRepeat, 1, 2, 6, 7,
+			GTK_FILL, GTK_SHRINK, 0, 0);
+    }
 
   frameExpire = gpa_expiry_frame_new (NULL);
   dialog.frameExpire = frameExpire;
@@ -274,9 +307,13 @@
 	= XSTRDUP_OR_NULL(gtk_entry_get_text (GTK_ENTRY (entryEmail)));
       params->comment
 	= XSTRDUP_OR_NULL (gtk_entry_get_text (GTK_ENTRY(entryComment)));
-      params->password
-	= XSTRDUP_OR_NULL (gtk_entry_get_text (GTK_ENTRY(entryPasswd)));
 
+      if (forcard)
+	params->password = NULL;
+      else
+	params->password
+	  = XSTRDUP_OR_NULL (gtk_entry_get_text (GTK_ENTRY(entryPasswd)));
+
       temp = gtk_combo_box_get_active_text (GTK_COMBO_BOX (comboAlgorithm));
       params->algo = gpa_algorithm_from_string (temp);
       temp = gtk_combo_box_get_active_text (GTK_COMBO_BOX (comboKeysize));

Modified: trunk/src/keygendlg.h
===================================================================
--- trunk/src/keygendlg.h	2008-12-10 18:22:34 UTC (rev 919)
+++ trunk/src/keygendlg.h	2008-12-13 22:34:51 UTC (rev 920)
@@ -1,5 +1,6 @@
 /* keygendlg.h  -  The GNU Privacy Assistant
  *	Copyright (C) 2000, 2001 G-N-U GmbH.
+ *	Copyright (C) 2008 g10 Code GmbH
  *
  * This file is part of GPA
  *
@@ -24,7 +25,6 @@
 #include <gtk/gtk.h>
 #include "gpgmetools.h"
 
-GPAKeyGenParameters * gpa_key_gen_run_dialog (GtkWidget * parent);
+GPAKeyGenParameters * gpa_key_gen_run_dialog (GtkWidget * parent, gboolean forcard);
 
-
 #endif /* KEYSIGNDLG_H */

Modified: trunk/src/keyring.c
===================================================================
--- trunk/src/keyring.c	2008-12-10 18:22:34 UTC (rev 919)
+++ trunk/src/keyring.c	2008-12-13 22:34:51 UTC (rev 920)
@@ -977,6 +977,7 @@
     "      <menuitem action='WindowsKeyringEditor'/>"
     "      <menuitem action='WindowsFileManager'/>"
     "      <menuitem action='WindowsClipboard'/>"
+    "      <menuitem action='WindowsCardManager'/>"
     "    </menu>"
     "    <menu action='Server'>"
     "      <menuitem action='ServerRetrieve'/>"
@@ -1005,6 +1006,7 @@
     "    <separator/>"
     "    <toolitem action='WindowsFileManager'/>"
     "    <toolitem action='WindowsClipboard'/>"
+    "    <toolitem action='WindowsCardManager'/>"
 #if 0
     "    <toolitem action='HelpContents'/>"
 #endif
@@ -1076,6 +1078,8 @@
   g_object_set (action, "short_label", _("Import"), NULL);
   action = gtk_action_group_get_action (action_group, "WindowsFileManager");
   g_object_set (action, "short_label", _("Files"), NULL);
+  action = gtk_action_group_get_action (action_group, "WindowsCardManager");
+  g_object_set (action, "short_label", _("Card"), NULL);
 
   /* Take care of sensitiveness of widgets.  */
   action = gtk_action_group_get_action (action_group, "EditCopy");

Modified: trunk/src/server.c
===================================================================
--- trunk/src/server.c	2008-12-10 18:22:34 UTC (rev 919)
+++ trunk/src/server.c	2008-12-13 22:34:51 UTC (rev 920)
@@ -1151,7 +1151,20 @@
   return assuan_process_done (ctx, 0);
 }
 
+/* START_CARDMANAGER
 
+   Pop up the card manager window.  The client expects that the key
+   manager is brought into the foregound and that this command
+   immediatley returns.
+*/
+static int
+cmd_start_cardmanager (assuan_context_t ctx, char *line)
+{
+  gpa_open_cardmanager (NULL, NULL);
+
+  return assuan_process_done (ctx, 0);
+}
+
 
 /* START_CONFDIALOG
 
@@ -1650,6 +1663,7 @@
     { "VERIFY", cmd_verify },
     { "START_KEYMANAGER", cmd_start_keymanager },
     { "START_CONFDIALOG", cmd_start_confdialog },
+    { "START_CARDMANAGER", cmd_start_cardmanager },
     { "GETINFO", cmd_getinfo },
     { "FILE", cmd_file },
     { "ENCRYPT_FILES", cmd_encrypt_files },



More information about the Gpa-commits mailing list