[Gpa-commits] r827 - trunk/src
scm-commit@wald.intevation.org
scm-commit at wald.intevation.org
Thu Feb 28 19:27:28 CET 2008
Author: werner
Date: 2008-02-28 19:27:27 +0100 (Thu, 28 Feb 2008)
New Revision: 827
Added:
trunk/src/recipientdlg.c
trunk/src/recipientdlg.h
Modified:
trunk/src/ChangeLog
trunk/src/Makefile.am
trunk/src/gpastreamencryptop.c
trunk/src/gpastreamencryptop.h
trunk/src/keyring.c
trunk/src/server.c
Log:
Minor bug fix to the server mode.
Started with a recipients dialog.
Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog 2008-02-20 18:53:28 UTC (rev 826)
+++ trunk/src/ChangeLog 2008-02-28 18:27:27 UTC (rev 827)
@@ -1,3 +1,14 @@
+2008-02-28 Werner Koch <wk at g10code.com>
+
+ * server.c (struct conn_ctrl_s): Add fields is_unfinished and
+ client_died.
+ (not_finished): New. Use that instead of GPG_ERR_UNFINISHED.
+ (gpa_run_server_continuation, receive_cb): Handle dead client with
+ pending continuation.
+
+ * gpastreamencryptop.c: Add recipients property.
+ * recipientdlg.c, recipientdlg.h: New.
+
2008-02-20 Werner Koch <wk at g10code.com>
* server.c (cmd_start_keymanager): New.
Modified: trunk/src/Makefile.am
===================================================================
--- trunk/src/Makefile.am 2008-02-20 18:53:28 UTC (rev 826)
+++ trunk/src/Makefile.am 2008-02-28 18:27:27 UTC (rev 827)
@@ -46,6 +46,7 @@
filesigndlg.c filesigndlg.h \
encryptdlg.c encryptdlg.h \
verifydlg.c verifydlg.h \
+ recipientdlg.c recipientdlg.h \
keyring.c keyring.h \
ownertrustdlg.c ownertrustdlg.h \
keysigndlg.c keysigndlg.h \
Modified: trunk/src/gpastreamencryptop.c
===================================================================
--- trunk/src/gpastreamencryptop.c 2008-02-20 18:53:28 UTC (rev 826)
+++ trunk/src/gpastreamencryptop.c 2008-02-28 18:27:27 UTC (rev 827)
@@ -22,11 +22,21 @@
#include <glib.h>
#include "gpgmetools.h"
-#include "encryptdlg.h"
+#include "recipientdlg.h"
#include "gpawidgets.h"
#include "gpapastrings.h"
#include "gpastreamencryptop.h"
+
+/* Indentifiers for our properties. */
+enum
+ {
+ PROP_0,
+ PROP_RECIPIENTS
+ };
+
+
+
static void response_cb (GtkDialog *dialog,
gint response,
gpointer user_data);
@@ -48,8 +58,44 @@
+static void
+gpa_stream_encrypt_operation_get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ GpaStreamEncryptOperation *op = GPA_STREAM_ENCRYPT_OPERATION (object);
+
+ switch (prop_id)
+ {
+ case PROP_RECIPIENTS:
+ g_value_set_pointer (value, op->recipients);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
static void
+gpa_stream_encrypt_operation_set_property (GObject *object, guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GpaStreamEncryptOperation *op = GPA_STREAM_ENCRYPT_OPERATION (object);
+
+ switch (prop_id)
+ {
+ case PROP_RECIPIENTS:
+ op->recipients = (GSList*)g_value_get_pointer (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+static void
gpa_stream_encrypt_operation_finalize (GObject *object)
{
GpaStreamEncryptOperation *op = GPA_STREAM_ENCRYPT_OPERATION (object);
@@ -69,6 +115,8 @@
gpa_stream_encrypt_operation_init (GpaStreamEncryptOperation *op)
{
op->encrypt_dialog = NULL;
+ op->recipients = NULL;
+ op->selected_protocol = GPGME_PROTOCOL_UNKNOWN;
}
@@ -87,9 +135,10 @@
op = GPA_STREAM_ENCRYPT_OPERATION (object);
/* Create the "Encrypt" dialog */
- op->encrypt_dialog = gpa_file_encrypt_dialog_new
- (GPA_OPERATION (op)->window, FALSE);
+ op->encrypt_dialog = recipient_dlg_new (GPA_OPERATION (op)->window);
+ recipient_dlg_set_recipients (op->encrypt_dialog, op->recipients);
+
g_signal_connect (G_OBJECT (op->encrypt_dialog), "response",
G_CALLBACK (response_cb), op);
/* We connect the done signal to two handles. The error handler is
@@ -118,6 +167,16 @@
object_class->constructor = gpa_stream_encrypt_operation_constructor;
object_class->finalize = gpa_stream_encrypt_operation_finalize;
+ object_class->set_property = gpa_stream_encrypt_operation_set_property;
+ object_class->get_property = gpa_stream_encrypt_operation_get_property;
+
+ g_object_class_install_property
+ (object_class, PROP_RECIPIENTS,
+ g_param_spec_pointer
+ ("recipients", "Recipients",
+ "A list of recipients in rfc-822 mailbox format.",
+ G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY));
+
}
@@ -191,152 +250,14 @@
-/*
- * Setting the recipients for the context.
- */
-
-/* static GtkResponseType */
-/* ignore_key_trust (gpgme_key_t key, GtkWidget *parent) */
-/* { */
-/* GtkWidget *dialog; */
-/* GtkWidget *key_info; */
-/* GtkWidget *vbox; */
-/* GtkWidget *hbox; */
-/* GtkWidget *label; */
-/* GtkWidget *image; */
-/* GtkResponseType response; */
-
-/* dialog = gtk_dialog_new_with_buttons (_("Unknown Key"), GTK_WINDOW(parent), */
-/* GTK_DIALOG_MODAL, */
-/* _("_Yes"), GTK_RESPONSE_YES, */
-/* _("_No"), GTK_RESPONSE_NO, */
-/* NULL); */
-/* gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES); */
-/* gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); */
-
-/* hbox = gtk_hbox_new (FALSE, 6); */
-/* image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, */
-/* GTK_ICON_SIZE_DIALOG); */
-/* gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, TRUE, 0); */
-/* vbox = gtk_vbox_new (FALSE, 6); */
-/* gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0); */
-/* gtk_box_pack_start_defaults (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox); */
-
-/* label = gtk_label_new (_("You are going to encrypt a stream using " */
-/* "the following key:")); */
-/* gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); */
-/* gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 5); */
-/* key_info = gpa_key_info_new (key); */
-/* gtk_box_pack_start (GTK_BOX (vbox), key_info, FALSE, TRUE, 5); */
-/* label = gtk_label_new (_("However, it is not certain that the key belongs " */
-/* "to that person.")); */
-/* gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); */
-/* gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 5); */
-/* label = gtk_label_new (NULL); */
-/* gtk_label_set_markup (GTK_LABEL (label), */
-/* _("Do you <b>really</b> want to use this key?")); */
-/* gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); */
-/* gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 5); */
-
-/* gtk_widget_show_all (dialog); */
-/* response = gtk_dialog_run (GTK_DIALOG (dialog)); */
-
-/* gtk_widget_destroy (dialog); */
-/* return response; */
-/* } */
-
-/* static void */
-/* revoked_key (gpgme_key_t key, GtkWidget *parent) */
-/* { */
-/* GtkWidget *dialog; */
-/* GtkWidget *key_info; */
-/* GtkWidget *vbox; */
-/* GtkWidget *hbox; */
-/* GtkWidget *label; */
-/* GtkWidget *image; */
-
-/* dialog = gtk_dialog_new_with_buttons (_("Revoked Key"), GTK_WINDOW(parent), */
-/* GTK_DIALOG_MODAL, */
-/* _("_Close"), GTK_RESPONSE_CLOSE, */
-/* NULL); */
-/* gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE); */
-/* gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); */
-
-/* hbox = gtk_hbox_new (FALSE, 6); */
-/* image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_ERROR, */
-/* GTK_ICON_SIZE_DIALOG); */
-/* gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, TRUE, 0); */
-/* vbox = gtk_vbox_new (FALSE, 6); */
-/* gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0); */
-/* gtk_box_pack_start_defaults (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox); */
-
-/* label = gtk_label_new (_("The following key has been revoked by it's owner:")); */
-/* gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); */
-/* gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 5); */
-/* key_info = gpa_key_info_new (key); */
-/* gtk_box_pack_start (GTK_BOX (vbox), key_info, FALSE, TRUE, 5); */
-/* label = gtk_label_new (_("And can not be used for encryption.")); */
-/* gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); */
-/* gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 5); */
-
-/* gtk_widget_show_all (dialog); */
-/* gtk_dialog_run (GTK_DIALOG (dialog)); */
-/* gtk_widget_destroy (dialog); */
-/* } */
-
-/* static void */
-/* expired_key (gpgme_key_t key, GtkWidget *parent) */
-/* { */
-/* GtkWidget *dialog; */
-/* GtkWidget *key_info; */
-/* GtkWidget *vbox; */
-/* GtkWidget *hbox; */
-/* GtkWidget *label; */
-/* GtkWidget *image; */
-/* gchar *message; */
-
-/* dialog = gtk_dialog_new_with_buttons (_("Revoked Key"), GTK_WINDOW(parent), */
-/* GTK_DIALOG_MODAL, */
-/* _("_Close"), GTK_RESPONSE_CLOSE, */
-/* NULL); */
-/* gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE); */
-/* gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); */
-
-/* hbox = gtk_hbox_new (FALSE, 6); */
-/* image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_ERROR, */
-/* GTK_ICON_SIZE_DIALOG); */
-/* gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, TRUE, 0); */
-/* vbox = gtk_vbox_new (FALSE, 6); */
-/* gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0); */
-/* gtk_box_pack_start_defaults (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox); */
-
-/* message = g_strdup_printf (_("The following key expired on %s:"), */
-/* gpa_expiry_date_string */
-/* (key->subkeys->expires)); */
-/* label = gtk_label_new (message); */
-/* gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); */
-/* gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 5); */
-/* key_info = gpa_key_info_new (key); */
-/* gtk_box_pack_start (GTK_BOX (vbox), key_info, FALSE, TRUE, 5); */
-/* label = gtk_label_new (_("And can not be used for encryption.")); */
-/* gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); */
-/* gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 5); */
-
-/* gtk_widget_show_all (dialog); */
-/* gtk_dialog_run (GTK_DIALOG (dialog)); */
-/* gtk_widget_destroy (dialog); */
-/* } */
-
-
-/* Given a list of strings, each describing one recipient parse them
+/* Given a list of strings, each describing one recipient, parse them
to detect duplicates, check the validity of each key and ask the
user whether he wants to use an invalid key.
- Try to find a key for each item in array NAMES. Items not found are
- stored as malloced strings in the newly allocated array UNKNOWN.
- Found keys are stored in the newly allocated array FOUND. Both
- arrays are terminated by a NULL entry. Caller needs to release
- FOUND and UNKNOWN.
+ Try to find a key for each item in RECIPIENT. Items not found are
+ stored in the newly allocated list R_UNKNOWN. Found keys are
+ stored in the newly allocated and NULL terminated gpgme_key_t array
+ R_FOUND. Caller needs to release R_FOUND and R_UNKNOWN.
*/
static gpg_error_t
parse_recipients (GpaStreamEncryptOperation *op, GSList *recipients,
@@ -360,6 +281,8 @@
if (err)
return err;
+ /* Fixme: Add rfc-822 mailbox parsing. */
+
for (n=0, recp = recipients; recp; recp = g_slist_next (recp))
n++;
@@ -386,9 +309,26 @@
gpgme_op_keylist_end (ctx);
/* If a usable key has been found, put it into the list of good
- keys. All other keys end up in the list of unknown key. */
- if (key && !key->revoked && !key->disabled && !key->expired)
+ keys. All other keys end up in the list of unknown keys. We
+ select the protocol to use from the frist found key. Fixme:
+ We might want to have a different logic to select the
+ protocol. */
+ if (key
+ && used_proto != GPGME_PROTOCOL_UNKNOWN
+ && used_proto != key->protocol)
{
+ /* We can't use this key becuase it does not match the
+ selected protocol. */
+ char *p;
+ const char *warn = _("wrong protocol");
+
+ n = strlen (name) + 3 + strlen (warn);
+ p = xmalloc (n+1);
+ snprintf (p, n, "%s (%s)", name, warn);
+ unknown = g_slist_append (unknown, p);
+ }
+ else if (key && !key->revoked && !key->disabled && !key->expired)
+ {
gpgme_key_ref (key);
found[found_idx++] = key;
if (used_proto == GPGME_PROTOCOL_UNKNOWN)
@@ -415,11 +355,17 @@
if (err)
;
else if (used_proto == GPGME_PROTOCOL_OpenPGP)
- err = gpa_operation_write_status (GPA_OPERATION (op), "PROTOCOL",
- "OpenPGP", NULL);
+ {
+ op->selected_protocol = used_proto;
+ err = gpa_operation_write_status (GPA_OPERATION (op), "PROTOCOL",
+ "OpenPGP", NULL);
+ }
else if (used_proto == GPGME_PROTOCOL_CMS)
- err = gpa_operation_write_status (GPA_OPERATION (op), "PROTOCOL",
- "CMS", NULL);
+ {
+ op->selected_protocol = used_proto;
+ err = gpa_operation_write_status (GPA_OPERATION (op), "PROTOCOL",
+ "CMS", NULL);
+ }
else
err = 0;
@@ -447,7 +393,7 @@
if (response != GTK_RESPONSE_OK)
{
/* The dialog was canceled, so we do nothing and complete the
- * operation */
+ * operation. */
gpa_operation_server_finish (GPA_OPERATION (op),
gpg_error (GPG_ERR_CANCELED));
g_signal_emit_by_name (GPA_OPERATION (op), "completed");
@@ -463,10 +409,19 @@
if (err)
goto leave;
- /* Our streams work all in ascii armored mode (Either PGP or PEM) */
- if (GPA_STREAM_OPERATION (op)->input_stream)
+ /* Set the output encoding. */
+ if (GPA_STREAM_OPERATION (op)->input_stream
+ && GPA_STREAM_OPERATION (op)->output_stream)
{
- gpgme_set_armor (GPA_OPERATION (op)->context->ctx, 1);
+ if (op->selected_protocol == GPGME_PROTOCOL_CMS)
+ {
+ gpgme_data_set_encoding (GPA_STREAM_OPERATION (op)->output_stream,
+ GPGME_DATA_ENCODING_BASE64);
+ }
+ else
+ {
+ gpgme_set_armor (GPA_OPERATION (op)->context->ctx, 1);
+ }
err = start_encryption (op, keys);
}
else
@@ -537,12 +492,13 @@
/* Start encrypting INPUT_STREAM to OUTPUT_STREAM using SERVER_CTX and
WINDOW. RECIPIENTS gives a list of recipients and the function
- matches them with existing keys and selects appropriate keys. If
- it is not possible to unambigiously select keys and SILENT is not
- given, a key selection dialog offers the user a way to manually
- input keys. INPUT_STREAM and OUTPUT_STREAM may be given as NULL in
- which case the function skips the actual encryption step and just
- verifies the recipients. */
+ matches them with existing keys and selects appropriate keys. The
+ ownership of RECIPIENTS is taken by this function. If it is not
+ possible to unambigiously select keys and SILENT is not given, a
+ key selection dialog offers the user a way to manually select keys.
+ INPUT_STREAM and OUTPUT_STREAM may be given as NULL in which case
+ the function skips the actual encryption step and just verifies the
+ recipients. */
/* FIXME: We need to offer a way to return the actual selected list of
recipients so that repeating this command with that list instantly
starts the decryption. */
@@ -560,10 +516,14 @@
"window", window,
"input_stream", input_stream,
"output_stream", output_stream,
+ "recipients", recipients,
"server-ctx", server_ctx,
NULL);
- if (op)
- op->recipients = recipients;
+ if (!op)
+ {
+ g_slist_foreach (recipients, free_func, NULL);
+ g_slist_free (recipients);
+ }
return op;
}
Modified: trunk/src/gpastreamencryptop.h
===================================================================
--- trunk/src/gpastreamencryptop.h 2008-02-20 18:53:28 UTC (rev 826)
+++ trunk/src/gpastreamencryptop.h 2008-02-28 18:27:27 UTC (rev 827)
@@ -61,6 +61,7 @@
GtkWidget *encrypt_dialog;
GSList *recipients;
+ gpgme_protocol_t selected_protocol;
};
Modified: trunk/src/keyring.c
===================================================================
--- trunk/src/keyring.c 2008-02-20 18:53:28 UTC (rev 826)
+++ trunk/src/keyring.c 2008-02-28 18:27:27 UTC (rev 827)
@@ -1237,7 +1237,7 @@
}
/* Fill the details page of the details notebook with the properties
- of the publix key key */
+ of the public key. */
static void
keyring_details_page_fill_key (GPAKeyringEditor * editor, gpgme_key_t key)
{
Added: trunk/src/recipientdlg.c
===================================================================
--- trunk/src/recipientdlg.c 2008-02-20 18:53:28 UTC (rev 826)
+++ trunk/src/recipientdlg.c 2008-02-28 18:27:27 UTC (rev 827)
@@ -0,0 +1,365 @@
+/* recipientdlg.c - A dialog to select a mail recipient.
+ * 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 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/>.
+ */
+
+#include <config.h>
+
+#include "gpa.h"
+#include "i18n.h"
+
+#include "gtktools.h"
+#include "gpakeyselector.h"
+#include "recipientdlg.h"
+
+
+struct _RecipientDlg
+{
+ GtkDialog parent;
+
+ GtkWidget *clist_keys;
+ GtkWidget *check_sign;
+ GtkWidget *check_armor;
+ GtkWidget *clist_who;
+ GtkWidget *scroller_who;
+};
+
+
+struct _RecipientDlgClass
+{
+ GtkDialogClass parent_class;
+
+};
+
+
+/* The parent class. */
+static GObjectClass *parent_class;
+
+
+/* Indentifiers for our properties. */
+enum
+ {
+ PROP_0,
+ PROP_WINDOW,
+ PROP_FORCE_ARMOR
+ };
+
+
+/* Identifiers for the columns of the RECPLIST. */
+enum
+ {
+ RECPLIST_MAILBOX, /* The rfc822 mailbox to whom a key needs to
+ be associated. */
+ RECPLIST_HAS_PGP, /* A PGP certificate is available. */
+ RECPLIST_HAS_X509, /* An X.509 certificate is available. */
+ RECPLIST_KEYID, /* The key ID of the associated key. */
+
+ RECPLIST_N_COLUMNS
+ };
+
+
+
+/* Create the main list of this dialog. */
+static GtkWidget *
+recplist_window_new (void)
+{
+ GtkListStore *store;
+ GtkWidget *list;
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+
+ /* Create a model and associate a view. */
+ store = gtk_list_store_new (RECPLIST_N_COLUMNS,
+ G_TYPE_STRING,
+ G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN,
+ G_TYPE_STRING);
+ list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
+ gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (list), TRUE);
+
+ /* Define the columns. */
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes
+ (_("Recipient"), renderer, "text", RECPLIST_MAILBOX, NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (list), column);
+
+ renderer = gtk_cell_renderer_toggle_new ();
+ column = gtk_tree_view_column_new_with_attributes
+ (_("PGP"), renderer, "active", RECPLIST_HAS_PGP, NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (list), column);
+
+ renderer = gtk_cell_renderer_toggle_new ();
+ column = gtk_tree_view_column_new_with_attributes
+ (_("X.509"), renderer, "active", RECPLIST_HAS_X509, NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (list), column);
+
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes
+ (_("Key ID"), renderer, "text", RECPLIST_KEYID, NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (list), column);
+
+
+ return list;
+}
+
+
+
+
+static void
+changed_select_row_cb (GtkTreeSelection *treeselection, gpointer user_data)
+{
+/* RecipientDlg *dialog = user_data; */
+
+/* if (gpa_key_selector_has_selection (GPA_KEY_SELECTOR (dialog->clist_keys))) */
+/* { */
+/* gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), */
+/* GTK_RESPONSE_OK, TRUE); */
+/* } */
+/* else */
+/* { */
+/* gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), */
+/* GTK_RESPONSE_OK, FALSE); */
+/* } */
+}
+
+
+
+
+
+/************************************************************
+ ****************** Object Management ********************
+ ************************************************************/
+
+static void
+recipient_dlg_get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ RecipientDlg *dialog = RECIPIENT_DLG (object);
+
+ switch (prop_id)
+ {
+ case PROP_WINDOW:
+ g_value_set_object (value,
+ gtk_window_get_transient_for (GTK_WINDOW (dialog)));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+static void
+recipient_dlg_set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ RecipientDlg *dialog = RECIPIENT_DLG (object);
+
+ switch (prop_id)
+ {
+ case PROP_WINDOW:
+ gtk_window_set_transient_for (GTK_WINDOW (dialog),
+ g_value_get_object (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+static void
+recipient_dlg_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+static void
+recipient_dlg_init (RecipientDlg *dialog)
+{
+
+}
+
+
+static GObject*
+recipient_dlg_constructor (GType type, guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *object;
+ RecipientDlg *dialog;
+ GtkAccelGroup *accelGroup;
+ GtkWidget *vboxEncrypt;
+ GtkWidget *labelKeys;
+ GtkWidget *scrollerKeys;
+ GtkWidget *clistKeys;
+
+ object = parent_class->constructor (type,
+ n_construct_properties,
+ construct_properties);
+ dialog = RECIPIENT_DLG (object);
+
+
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ _("_Cancel"), GTK_RESPONSE_CANCEL, NULL);
+ gtk_window_set_title (GTK_WINDOW (dialog),
+ _("Select keys for recipients"));
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK,
+ FALSE);
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+
+ accelGroup = gtk_accel_group_new ();
+ gtk_window_add_accel_group (GTK_WINDOW (dialog), accelGroup);
+
+ vboxEncrypt = GTK_DIALOG (dialog)->vbox;
+ gtk_container_set_border_width (GTK_CONTAINER (vboxEncrypt), 5);
+
+ labelKeys = gtk_label_new ("");
+ gtk_misc_set_alignment (GTK_MISC (labelKeys), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (vboxEncrypt), labelKeys, FALSE, FALSE, 0);
+
+ scrollerKeys = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollerKeys),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_box_pack_start (GTK_BOX (vboxEncrypt), scrollerKeys, TRUE, TRUE, 0);
+ gtk_widget_set_size_request (scrollerKeys, 400, 200);
+
+ clistKeys = recplist_window_new ();
+ g_signal_connect (G_OBJECT (gtk_tree_view_get_selection
+ (GTK_TREE_VIEW (clistKeys))),
+ "changed", G_CALLBACK (changed_select_row_cb),
+ dialog);
+ dialog->clist_keys = clistKeys;
+ gtk_container_add (GTK_CONTAINER (scrollerKeys), clistKeys);
+ gpa_connect_by_accelerator (GTK_LABEL (labelKeys), clistKeys, accelGroup,
+ _("_Recipient list"));
+
+
+
+ return object;
+}
+
+
+static void
+recipient_dlg_class_init (RecipientDlgClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->constructor = recipient_dlg_constructor;
+ object_class->finalize = recipient_dlg_finalize;
+ object_class->set_property = recipient_dlg_set_property;
+ object_class->get_property = recipient_dlg_get_property;
+
+ g_object_class_install_property
+ (object_class,
+ PROP_WINDOW,
+ g_param_spec_object
+ ("window", "Parent window",
+ "Parent window", GTK_TYPE_WIDGET,
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+}
+
+
+GType
+recipient_dlg_get_type (void)
+{
+ static GType this_type;
+
+ if (!this_type)
+ {
+ static const GTypeInfo this_info =
+ {
+ sizeof (RecipientDlgClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) recipient_dlg_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+
+ sizeof (RecipientDlg),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) recipient_dlg_init,
+ };
+
+ this_type = g_type_register_static (GTK_TYPE_DIALOG,
+ "RecipientDlg",
+ &this_info, 0);
+ }
+
+ return this_type;
+}
+
+
+
+/************************************************************
+ ********************** Public API ************************
+ ************************************************************/
+
+GtkWidget *
+recipient_dlg_new (GtkWidget *parent)
+{
+ RecipientDlg *dialog;
+
+ dialog = g_object_new (RECIPIENT_DLG_TYPE,
+ "window", parent,
+ NULL);
+
+ return GTK_WIDGET(dialog);
+}
+
+
+/* Put the recipients into the list. */
+void
+recipient_dlg_set_recipients (GtkWidget *object, GSList *recipients)
+{
+ RecipientDlg *dialog;
+ GtkListStore *store;
+ GSList *recp;
+ GtkTreeIter iter;
+ const char *name;
+
+ g_return_if_fail (object);
+ dialog = RECIPIENT_DLG (object);
+
+ store = GTK_LIST_STORE (gtk_tree_view_get_model
+ (GTK_TREE_VIEW (dialog->clist_keys)));
+
+ gtk_list_store_clear (store);
+ for (recp = recipients; recp; recp = g_slist_next (recp))
+ {
+ name = recp->data;
+ if (name && *name)
+ {
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ RECPLIST_MAILBOX, name,
+ RECPLIST_HAS_PGP, FALSE,
+ RECPLIST_HAS_X509, (*name == 'f'),
+ RECPLIST_KEYID, "[click to select]",
+ -1);
+ }
+ }
+}
+
+
+
Added: trunk/src/recipientdlg.h
===================================================================
--- trunk/src/recipientdlg.h 2008-02-20 18:53:28 UTC (rev 826)
+++ trunk/src/recipientdlg.h 2008-02-28 18:27:27 UTC (rev 827)
@@ -0,0 +1,68 @@
+/* recipientdlg.h - A dialog to select a mail recipient.
+ * 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 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/>.
+ */
+
+#ifndef RECIPIENTDLG_H
+#define RECIPIENTDLG_H
+
+
+/* Definitions to define the object. */
+#define RECIPIENT_DLG_TYPE \
+ (recipient_dlg_get_type ())
+
+#define RECIPIENT_DLG(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), RECIPIENT_DLG_TYPE,\
+ RecipientDlg))
+
+#define RECIPIENT_DLG_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((klass), RECIPIENT_DLG_TYPE, \
+ RecipientDlgClass))
+
+#define IS_RECIPIENT_DLG(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), RECIPIENT_DLG_TYPE))
+
+#define IS_RECIPIENT_DLG_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((klass), RECIPIENT_DLG_TYPE))
+
+#define RECIPIENT_DLG_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), RECIPIENT_DLG_TYPE, \
+ RecipientDlgClass))
+
+typedef struct _RecipientDlg RecipientDlg;
+typedef struct _RecipientDlgClass RecipientDlgClass;
+
+
+GType recipient_dlg_get_type (void) G_GNUC_CONST;
+
+
+/************************************
+ ************ Public API ************
+ ************************************/
+
+GtkWidget *recipient_dlg_new (GtkWidget *parent);
+void recipient_dlg_set_recipients (GtkWidget *list, GSList *recipients);
+
+
+
+
+#endif /*RECIPIENTDLG_H*/
Modified: trunk/src/server.c
===================================================================
--- trunk/src/server.c 2008-02-20 18:53:28 UTC (rev 826)
+++ trunk/src/server.c 2008-02-28 18:27:27 UTC (rev 827)
@@ -40,7 +40,6 @@
#define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
-
/* The object used to keep track of the a connection's state. */
struct conn_ctrl_s;
typedef struct conn_ctrl_s *conn_ctrl_t;
@@ -52,6 +51,14 @@
/* NULL or continuation function for a command. */
void (*cont_cmd) (assuan_context_t, gpg_error_t);
+ /* Flag indicating that the client died while a continuation was
+ still registyered. */
+ int client_died;
+
+ /* This is a helper to detect that the unfinished erroe code actually
+ comes from our command handler. */
+ int is_unfinished;
+
/* File descriptors used by the gpgme callbacks. */
int input_fd;
int output_fd;
@@ -68,12 +75,23 @@
};
-
+/* The nonce used by the server connection. This nonce is required
+ uner Windows to emulate Unix Domain Sockets. This is managed by
+ libassuan but we need to store the nonce in the application. Under
+ Unix this is just a stub. */
static assuan_sock_nonce_t socket_nonce;
+static int
+not_finished (conn_ctrl_t ctrl)
+{
+ ctrl->is_unfinished = 1;
+ return gpg_error (GPG_ERR_UNFINISHED);
+}
+
+
/* Test whether LINE contains thye option NAME. An optional argument
of the option is ignored. For example with NAME being "--protocol"
this function returns true for "--protocol" as well as for
@@ -229,10 +247,9 @@
Set the recipient for the encryption. <recipient> is an RFC2822
recipient name. This command may or may not check the recipient for
- validity right away; if it does not (as implemented in GPA) all
- recipients are checked at the time of the ENCRYPT command. All
- RECIPIENT commands are cumulative until a RESET or an successful
- ENCRYPT command. */
+ validity right away; if it does not (as here) all recipients are
+ checked at the time of the ENCRYPT command. All RECIPIENT commands
+ are cumulative until a RESET or an successful ENCRYPT command. */
static int
cmd_recipient (assuan_context_t ctx, char *line)
{
@@ -365,8 +382,9 @@
input_data = output_data = NULL;
g_signal_connect (G_OBJECT (op), "completed",
G_CALLBACK (g_object_unref), NULL);
- return gpg_error (GPG_ERR_UNFINISHED);
+ return not_finished (ctrl);
+
leave:
gpgme_data_release (input_data);
gpgme_data_release (output_data);
@@ -390,7 +408,7 @@
/* PREP_ENCRYPT [--protocol=OpenPGP|CMS]
Dummy encryption command used to check whether the given recipients
- are all valid and to tell the cleint the preferred protocol. */
+ are all valid and to tell the client the preferred protocol. */
static int
cmd_prep_encrypt (assuan_context_t ctx, char *line)
{
@@ -421,7 +439,7 @@
copy_recipients (ctrl), 0, ctx);
g_signal_connect (G_OBJECT (op), "completed",
G_CALLBACK (g_object_unref), NULL);
- return gpg_error (GPG_ERR_UNFINISHED);
+ return not_finished (ctrl);
leave:
return assuan_process_done (ctx, err);
@@ -576,7 +594,7 @@
/* input_data = output_data = NULL; */
/* g_signal_connect (G_OBJECT (op), "completed", */
/* G_CALLBACK (g_object_unref), NULL); */
-/* return gpg_error (GPG_ERR_UNFINISHED); */
+/* return not_finished (ctrl); */
leave:
gpgme_data_release (input_data);
@@ -774,6 +792,11 @@
g_debug ("no continuation defined; using default");
assuan_process_done (ctx, err);
}
+ else if (!ctrl->client_died)
+ {
+ g_debug ("not running continuation as client has disconnected");
+ connection_finish (ctx);
+ }
else
{
cont_cmd = ctrl->cont_cmd;
@@ -818,18 +841,22 @@
; /* Ignore. */
else if (gpg_err_code (err) == GPG_ERR_EOF || err == -1)
{
- connection_finish (ctx);
- /* FIXME: what about the socket? */
+ if (ctrl->cont_cmd)
+ ctrl->client_died = 1; /* Need to delay the cleanup. */
+ else
+ connection_finish (ctx);
return FALSE; /* Remove from the watch. */
}
else if (gpg_err_code (err) == GPG_ERR_UNFINISHED)
{
- if ( !ctrl->cont_cmd)
+ if (!ctrl->is_unfinished)
{
/* It is quite possible that some other subsystem
returns that error code. Tell the user about
this curiosity and finish the command. */
g_debug ("note: Unfinished error code not emitted by us");
+ if (ctrl->cont_cmd)
+ g_debug ("OOPS: pending continuation!");
assuan_process_done (ctx, err);
}
}
More information about the Gpa-commits
mailing list