[Gpa-commits] r894 - trunk/src
scm-commit@wald.intevation.org
scm-commit at wald.intevation.org
Fri May 9 06:45:26 CEST 2008
Author: marcus
Date: 2008-05-09 06:45:25 +0200 (Fri, 09 May 2008)
New Revision: 894
Added:
trunk/src/gpastreamdecryptop.c
trunk/src/gpastreamdecryptop.h
trunk/src/gpastreamverifyop.c
trunk/src/gpastreamverifyop.h
Modified:
trunk/src/ChangeLog
trunk/src/Makefile.am
trunk/src/server.c
Log:
2008-05-09 Marcus Brinkmann <marcus at g10code.de>
* Makefile.am (gpa_SOURCES): Add gpastreamverifyop.h,
gpastreamverifyop.c, gpastreamdecryptop.h and gpastreamdecryptop.c.
* gpastreamverifyop.h, gpastreamverifyop.c: New files.
* gpastreamdecryptop.h, gpastreamdecryptop.c: New files.
* server.c: Include "gpastreamverifyop.h" and "gpastreamdecryptop.h".
(my_devnull_write_cb): New function.
(my_devnull_data_cbs): New struct.
(finish_io_streams, cmd_encrypt, cmd_sign, cmd_decrypt)
(cmd_verify,reset_notify): Reset CTRL->input_fd and CTRL->output_fd.
(cont_verify, cmd_verify): Finish implementation.
(cont_decrypt, cmd_decrypt): Finish implementation.
Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog 2008-05-08 16:47:48 UTC (rev 893)
+++ trunk/src/ChangeLog 2008-05-09 04:45:25 UTC (rev 894)
@@ -1,3 +1,17 @@
+2008-05-09 Marcus Brinkmann <marcus at g10code.de>
+
+ * Makefile.am (gpa_SOURCES): Add gpastreamverifyop.h,
+ gpastreamverifyop.c, gpastreamdecryptop.h and gpastreamdecryptop.c.
+ * gpastreamverifyop.h, gpastreamverifyop.c: New files.
+ * gpastreamdecryptop.h, gpastreamdecryptop.c: New files.
+ * server.c: Include "gpastreamverifyop.h" and "gpastreamdecryptop.h".
+ (my_devnull_write_cb): New function.
+ (my_devnull_data_cbs): New struct.
+ (finish_io_streams, cmd_encrypt, cmd_sign, cmd_decrypt)
+ (cmd_verify,reset_notify): Reset CTRL->input_fd and CTRL->output_fd.
+ (cont_verify, cmd_verify): Finish implementation.
+ (cont_decrypt, cmd_decrypt): Finish implementation.
+
2008-05-08 Werner Koch <wk at g10code.com>
* gpgmetools.c (gpa_switch_to_gpg2): New.
Modified: trunk/src/Makefile.am
===================================================================
--- trunk/src/Makefile.am 2008-05-08 16:47:48 UTC (rev 893)
+++ trunk/src/Makefile.am 2008-05-09 04:45:25 UTC (rev 894)
@@ -89,6 +89,8 @@
gpastreamop.h gpastreamop.c \
gpastreamencryptop.h gpastreamencryptop.c \
gpastreamsignop.h gpastreamsignop.c \
+ gpastreamverifyop.h gpastreamverifyop.c \
+ gpastreamdecryptop.h gpastreamdecryptop.c \
gpafileop.h gpafileop.c \
gpafiledecryptop.h gpafiledecryptop.c \
gpafileencryptop.h gpafileencryptop.c \
Added: trunk/src/gpastreamdecryptop.c
===================================================================
--- trunk/src/gpastreamdecryptop.c 2008-05-08 16:47:48 UTC (rev 893)
+++ trunk/src/gpastreamdecryptop.c 2008-05-09 04:45:25 UTC (rev 894)
@@ -0,0 +1,459 @@
+/* gpastreamsignop.c - The GpaStreamSignOperation object.
+ 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/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <glib.h>
+
+#include "gpgmetools.h"
+#include "gtktools.h"
+#include "verifydlg.h"
+#include "gpastreamdecryptop.h"
+
+
+struct _GpaStreamDecryptOperation
+{
+ GpaStreamOperation parent;
+
+ GtkWidget *dialog;
+
+ gboolean no_verify;
+
+ gpgme_protocol_t selected_protocol;
+};
+
+
+struct _GpaStreamDecryptOperationClass
+{
+ GpaStreamOperationClass parent_class;
+};
+
+
+
+/* Indentifiers for our properties. */
+enum
+ {
+ PROP_0,
+ PROP_NO_VERIFY,
+ PROP_PROTOCOL
+ };
+
+
+static gboolean idle_cb (gpointer data);
+static void response_cb (GtkDialog *dialog, gint response, gpointer user_data);
+static void done_error_cb (GpaContext *context, gpg_error_t err,
+ GpaStreamDecryptOperation *op);
+static void done_cb (GpaContext *context, gpg_error_t err,
+ GpaStreamDecryptOperation *op);
+
+static GObjectClass *parent_class;
+
+
+
+static void
+gpa_stream_decrypt_operation_get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ GpaStreamDecryptOperation *op = GPA_STREAM_DECRYPT_OPERATION (object);
+
+ switch (prop_id)
+ {
+ case PROP_NO_VERIFY:
+ g_value_set_boolean (value, op->no_verify);
+ break;
+ case PROP_PROTOCOL:
+ g_value_set_int (value, op->selected_protocol);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+static void
+gpa_stream_decrypt_operation_set_property (GObject *object, guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GpaStreamDecryptOperation *op = GPA_STREAM_DECRYPT_OPERATION (object);
+
+ switch (prop_id)
+ {
+ case PROP_NO_VERIFY:
+ op->no_verify = g_value_get_boolean (value);
+ break;
+ case PROP_PROTOCOL:
+ op->selected_protocol = g_value_get_int (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+static void
+gpa_stream_decrypt_operation_finalize (GObject *object)
+{
+ GpaStreamDecryptOperation *op = GPA_STREAM_DECRYPT_OPERATION (object);
+
+ if (op->dialog)
+ gtk_widget_destroy (op->dialog);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+static void
+gpa_stream_decrypt_operation_init (GpaStreamDecryptOperation *op)
+{
+ op->dialog = NULL;
+}
+
+
+static GObject*
+gpa_stream_decrypt_operation_ctor (GType type, guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *object;
+ GpaStreamDecryptOperation *op;
+
+ object = parent_class->constructor (type, n_construct_properties,
+ construct_properties);
+ op = GPA_STREAM_DECRYPT_OPERATION (object);
+
+ /* Start with the first file after going back into the main loop */
+ g_idle_add (idle_cb, op);
+
+ /* We connect the done signal to two handles. The error handler is
+ called first. */
+ g_signal_connect (G_OBJECT (GPA_OPERATION (op)->context), "done",
+ G_CALLBACK (done_error_cb), op);
+ g_signal_connect (G_OBJECT (GPA_OPERATION (op)->context), "done",
+ G_CALLBACK (done_cb), op);
+
+ gtk_window_set_title
+ (GTK_WINDOW (GPA_STREAM_OPERATION (op)->progress_dialog),
+ _("Decrypting message ..."));
+
+ if (! op->no_verify)
+ {
+ op->dialog = gpa_file_verify_dialog_new (GPA_OPERATION (op)->window);
+ g_signal_connect (G_OBJECT (op->dialog), "response",
+ G_CALLBACK (response_cb), op);
+ }
+
+ return object;
+}
+
+
+static void
+gpa_stream_decrypt_operation_class_init (GpaStreamDecryptOperationClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->constructor = gpa_stream_decrypt_operation_ctor;
+ object_class->finalize = gpa_stream_decrypt_operation_finalize;
+ object_class->set_property = gpa_stream_decrypt_operation_set_property;
+ object_class->get_property = gpa_stream_decrypt_operation_get_property;
+
+ g_object_class_install_property (object_class, PROP_NO_VERIFY,
+ g_param_spec_boolean
+ ("no-verify", "No Verify",
+ "Flag requesting no verify operation.",
+ FALSE,
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property
+ (object_class, PROP_PROTOCOL,
+ g_param_spec_int
+ ("protocol", "Protocol",
+ "The gpgme protocol currently selected.",
+ GPGME_PROTOCOL_OpenPGP, GPGME_PROTOCOL_UNKNOWN, GPGME_PROTOCOL_UNKNOWN,
+ G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY));
+
+}
+
+
+GType
+gpa_stream_decrypt_operation_get_type (void)
+{
+ static GType stream_decrypt_operation_type = 0;
+
+ if (! stream_decrypt_operation_type)
+ {
+ static const GTypeInfo stream_decrypt_operation_info =
+ {
+ sizeof (GpaStreamDecryptOperationClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) gpa_stream_decrypt_operation_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (GpaStreamDecryptOperation),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) gpa_stream_decrypt_operation_init,
+ };
+
+ stream_decrypt_operation_type = g_type_register_static
+ (GPA_STREAM_OPERATION_TYPE, "GpaStreamDecryptOperation",
+ &stream_decrypt_operation_info, 0);
+ }
+
+ return stream_decrypt_operation_type;
+}
+
+
+/* The decrypt status dialog has returned. */
+static void
+response_cb (GtkDialog *dialog, int response, void *user_data)
+{
+ GpaStreamDecryptOperation *op = user_data;
+
+ gtk_widget_hide (GTK_WIDGET (dialog));
+
+ g_signal_emit_by_name (GPA_OPERATION (op), "completed", 0);
+}
+
+
+/* Show an error message. */
+static void
+done_error_cb (GpaContext *context, gpg_error_t err,
+ GpaStreamDecryptOperation *op)
+{
+ switch (gpg_err_code (err))
+ {
+ case GPG_ERR_NO_ERROR:
+ case GPG_ERR_CANCELED:
+ /* Ignore these */
+ break;
+ default:
+ gpa_gpgme_warning (err);
+ break;
+ }
+}
+
+
+/* Percent-Escape special characters. */
+static gchar *
+my_percent_escape (const gchar *src)
+{
+ gchar *esc_str;
+ int new_len = 3 * strlen (src) + 1;
+ gchar *dst;
+
+ esc_str = g_malloc (new_len);
+
+ dst = esc_str;
+ while (*src)
+ {
+ if (*src == '%')
+ {
+ *(dst++) = '%';
+ *(dst++) = '2';
+ *(dst++) = '5';
+ }
+ else if (*src == ':')
+ {
+ /* The colon is used as field separator. */
+ *(dst++) = '%';
+ *(dst++) = '3';
+ *(dst++) = 'a';
+ }
+ else if (*src == ',')
+ {
+ /* The comma is used as list separator. */
+ *(dst++) = '%';
+ *(dst++) = '2';
+ *(dst++) = 'c';
+ }
+ else
+ *(dst++) = *(src);
+ src++;
+ }
+ *dst = '\0';
+ return esc_str;
+}
+
+
+/* Operation is ready. Tell the server. */
+static void
+done_cb (GpaContext *context, gpg_error_t err, GpaStreamDecryptOperation *op)
+{
+ gtk_widget_hide (GPA_STREAM_OPERATION (op)->progress_dialog);
+
+ if (! err && ! op->no_verify)
+ {
+ gpgme_verify_result_t res;
+ gpgme_signature_t sig;
+
+ res = gpgme_op_verify_result (GPA_OPERATION (op)->context->ctx);
+ sig = res->signatures;
+
+ while (sig)
+ {
+ gpgme_key_t key = NULL;
+ char *keydesc = NULL;
+ char *sigsum;
+ char *sigdesc;
+ char *sigdesc_esc;
+ const char *sigstatus;
+
+ if (sig->summary & GPGME_SIGSUM_VALID)
+ sigsum = "green";
+ else if (sig->summary & GPGME_SIGSUM_GREEN)
+ sigsum = "yellow";
+ else if (sig->summary & GPGME_SIGSUM_KEY_MISSING)
+ sigsum = "none";
+ else
+ sigsum = "red";
+
+ sigstatus = gpg_strerror (sig->status);
+
+ if (sig->fpr)
+ {
+ gpgme_get_key (GPA_OPERATION (op)->context->ctx,
+ sig->fpr, &key, 0);
+ if (key)
+ keydesc = gpa_gpgme_key_get_userid (key->uids);
+ }
+
+ if (sig->summary & GPGME_SIGSUM_RED)
+ {
+ if (keydesc)
+ sigdesc = g_strdup_printf (_("Bad signature by %s: %s"),
+ keydesc, sigstatus);
+ else if (sig->fpr)
+ sigdesc = g_strdup_printf (_("Bad signature by unknown key "
+ "%s: %s"), sig->fpr, sigstatus);
+ else
+ sigdesc = g_strdup_printf (_("Bad signature by unknown key: "
+ "%s"), sigstatus);
+ }
+ else if (sig->summary & GPGME_SIGSUM_VALID)
+ {
+ if (keydesc)
+ sigdesc = g_strdup_printf (_("Good signature by %s: %s"),
+ keydesc, sigstatus);
+ else if (sig->fpr)
+ sigdesc = g_strdup_printf (_("Good signature by unknown key "
+ "%s: %s"), sig->fpr, sigstatus);
+ else
+ sigdesc = g_strdup_printf (_("Good signature by unknown key: "
+ "%s"), sigstatus);
+ }
+ else
+ {
+ if (keydesc)
+ sigdesc = g_strdup_printf (_("Invalid signature by %s: %s"),
+ keydesc, sigstatus);
+ else if (sig->fpr)
+ sigdesc = g_strdup_printf (_("Invalid signature by unknown key "
+ "%s: %s"), sig->fpr, sigstatus);
+ else
+ sigdesc = g_strdup_printf (_("Invalid signature by unknown "
+ "key: %s"), sigstatus);
+ }
+
+ sigdesc_esc = my_percent_escape (sigdesc);
+
+ /* FIXME: Error handling. */
+ err = gpa_operation_write_status (GPA_OPERATION (op), "SIGSTATUS",
+ sigsum, sigdesc_esc, NULL);
+
+ g_free (sigdesc);
+ g_free (sigdesc_esc);
+
+ if (key)
+ gpgme_key_unref (key);
+ if (keydesc)
+ g_free (keydesc);
+
+ sig = sig->next;
+ }
+
+ if (res->signatures)
+ {
+ /* Add the file to the result dialog. */
+ gpa_file_verify_dialog_add_file
+ (GPA_FILE_VERIFY_DIALOG (op->dialog),
+ _("Document"), NULL, NULL, res->signatures);
+ gtk_widget_show_all (op->dialog);
+
+ /* We will complete later in response callback. */
+ return;
+ }
+ }
+
+ g_signal_emit_by_name (GPA_OPERATION (op), "completed", err);
+}
+
+
+static gboolean
+idle_cb (gpointer data)
+{
+ GpaStreamDecryptOperation *op = data;
+ GpaStreamOperation *sop = GPA_STREAM_OPERATION (op);
+ gpgme_error_t err;
+
+ gpgme_set_protocol (GPA_OPERATION (op)->context->ctx, op->selected_protocol);
+
+ if (op->no_verify)
+ err = gpgme_op_decrypt_start (GPA_OPERATION (op)->context->ctx,
+ sop->input_stream, sop->output_stream);
+ else
+ err = gpgme_op_decrypt_verify_start (GPA_OPERATION (op)->context->ctx,
+ sop->input_stream, sop->output_stream);
+
+ if (err)
+ {
+ gpa_gpgme_warning (err);
+ g_signal_emit_by_name (GPA_OPERATION (op), "completed", err);
+ }
+
+ gtk_widget_show_all (GPA_STREAM_OPERATION (op)->progress_dialog);
+
+ return FALSE;
+}
+
+
+/* Public API. */
+
+/* FIXME: Doc. */
+GpaStreamDecryptOperation *
+gpa_stream_decrypt_operation_new (GtkWidget *window,
+ gpgme_data_t input_stream,
+ gpgme_data_t output_stream,
+ gboolean no_verify, gpgme_protocol_t protocol)
+{
+ GpaStreamDecryptOperation *op;
+
+ op = g_object_new (GPA_STREAM_DECRYPT_OPERATION_TYPE,
+ "window", window,
+ "input_stream", input_stream,
+ "output_stream", output_stream,
+ "no-verify", no_verify,
+ "protocol", (int) protocol,
+ NULL);
+
+ return op;
+}
Added: trunk/src/gpastreamdecryptop.h
===================================================================
--- trunk/src/gpastreamdecryptop.h 2008-05-08 16:47:48 UTC (rev 893)
+++ trunk/src/gpastreamdecryptop.h 2008-05-09 04:45:25 UTC (rev 894)
@@ -0,0 +1,65 @@
+/* gpastreamdecryptop.h - The GpaStreamDecryptOperation object.
+ 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 GPA_STREAM_DECRYPT_OP_H
+#define GPA_STREAM_DECRYPT_OP_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "gpastreamop.h"
+
+/* GObject stuff. */
+#define GPA_STREAM_DECRYPT_OPERATION_TYPE \
+ (gpa_stream_decrypt_operation_get_type ())
+
+#define GPA_STREAM_DECRYPT_OPERATION(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), GPA_STREAM_DECRYPT_OPERATION_TYPE, \
+ GpaStreamDecryptOperation))
+
+#define GPA_STREAM_DECRYPT_OPERATION_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), GPA_STREAM_DECRYPT_OPERATION_TYPE, \
+ GpaStreamDecryptOperationClass))
+
+#define GPA_IS_STREAM_DECRYPT_OPERATION(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GPA_STREAM_DECRYPT_OPERATION_TYPE))
+
+#define GPA_IS_STREAM_DECRYPT_OPERATION_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), GPA_STREAM_DECRYPT_OPERATION_TYPE))
+
+#define GPA_STREAM_DECRYPT_OPERATION_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), GPA_STREAM_DECRYPT_OPERATION_TYPE, \
+ GpaStreamDecryptOperationClass))
+
+typedef struct _GpaStreamDecryptOperation GpaStreamDecryptOperation;
+typedef struct _GpaStreamDecryptOperationClass GpaStreamDecryptOperationClass;
+
+GType gpa_stream_decrypt_operation_get_type (void) G_GNUC_CONST;
+
+
+/* Public API. */
+
+/* Creates a new decrypt operation. */
+GpaStreamDecryptOperation *
+gpa_stream_decrypt_operation_new (GtkWidget *window,
+ gpgme_data_t input_stream,
+ gpgme_data_t output_stream,
+ gboolean no_verify,
+ gpgme_protocol_t protocol);
+
+#endif /* GPA_STREAM_DECRYPT_OP_H */
Added: trunk/src/gpastreamverifyop.c
===================================================================
--- trunk/src/gpastreamverifyop.c 2008-05-08 16:47:48 UTC (rev 893)
+++ trunk/src/gpastreamverifyop.c 2008-05-09 04:45:25 UTC (rev 894)
@@ -0,0 +1,463 @@
+/* gpastreamsignop.c - The GpaStreamSignOperation object.
+ 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/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <glib.h>
+
+#include "gpgmetools.h"
+#include "gtktools.h"
+#include "verifydlg.h"
+#include "gpastreamverifyop.h"
+
+
+struct _GpaStreamVerifyOperation
+{
+ GpaStreamOperation parent;
+
+ GtkWidget *dialog;
+
+ gboolean silent;
+
+ gpgme_protocol_t selected_protocol;
+};
+
+
+struct _GpaStreamVerifyOperationClass
+{
+ GpaStreamOperationClass parent_class;
+};
+
+
+
+/* Indentifiers for our properties. */
+enum
+ {
+ PROP_0,
+ PROP_SILENT,
+ PROP_PROTOCOL
+ };
+
+
+static gboolean idle_cb (gpointer data);
+static void response_cb (GtkDialog *dialog, gint response, gpointer user_data);
+static void done_error_cb (GpaContext *context, gpg_error_t err,
+ GpaStreamVerifyOperation *op);
+static void done_cb (GpaContext *context, gpg_error_t err,
+ GpaStreamVerifyOperation *op);
+
+static GObjectClass *parent_class;
+
+
+
+static void
+gpa_stream_verify_operation_get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ GpaStreamVerifyOperation *op = GPA_STREAM_VERIFY_OPERATION (object);
+
+ switch (prop_id)
+ {
+ case PROP_SILENT:
+ g_value_set_boolean (value, op->silent);
+ break;
+ case PROP_PROTOCOL:
+ g_value_set_int (value, op->selected_protocol);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+static void
+gpa_stream_verify_operation_set_property (GObject *object, guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GpaStreamVerifyOperation *op = GPA_STREAM_VERIFY_OPERATION (object);
+
+ switch (prop_id)
+ {
+ case PROP_SILENT:
+ op->silent = g_value_get_boolean (value);
+ break;
+ case PROP_PROTOCOL:
+ op->selected_protocol = g_value_get_int (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+static void
+gpa_stream_verify_operation_finalize (GObject *object)
+{
+ GpaStreamVerifyOperation *op = GPA_STREAM_VERIFY_OPERATION (object);
+
+ if (op->dialog)
+ gtk_widget_destroy (op->dialog);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+static void
+gpa_stream_verify_operation_init (GpaStreamVerifyOperation *op)
+{
+ op->dialog = NULL;
+}
+
+
+static GObject*
+gpa_stream_verify_operation_ctor (GType type, guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *object;
+ GpaStreamVerifyOperation *op;
+
+ object = parent_class->constructor (type, n_construct_properties,
+ construct_properties);
+ op = GPA_STREAM_VERIFY_OPERATION (object);
+
+ /* Start with the first file after going back into the main loop */
+ g_idle_add (idle_cb, op);
+
+ /* We connect the done signal to two handles. The error handler is
+ called first. */
+ g_signal_connect (G_OBJECT (GPA_OPERATION (op)->context), "done",
+ G_CALLBACK (done_error_cb), op);
+ g_signal_connect (G_OBJECT (GPA_OPERATION (op)->context), "done",
+ G_CALLBACK (done_cb), op);
+
+ /* FIXME: Implement silent option. */
+ gtk_window_set_title
+ (GTK_WINDOW (GPA_STREAM_OPERATION (op)->progress_dialog),
+ _("Verifying message ..."));
+
+ if (op->silent)
+ gtk_widget_hide (GPA_STREAM_OPERATION (op)->progress_dialog);
+ else
+ {
+ op->dialog = gpa_file_verify_dialog_new (GPA_OPERATION (op)->window);
+ g_signal_connect (G_OBJECT (op->dialog), "response",
+ G_CALLBACK (response_cb), op);
+ }
+
+ return object;
+}
+
+
+static void
+gpa_stream_verify_operation_class_init (GpaStreamVerifyOperationClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->constructor = gpa_stream_verify_operation_ctor;
+ object_class->finalize = gpa_stream_verify_operation_finalize;
+ object_class->set_property = gpa_stream_verify_operation_set_property;
+ object_class->get_property = gpa_stream_verify_operation_get_property;
+
+ g_object_class_install_property (object_class, PROP_SILENT,
+ g_param_spec_boolean
+ ("silent", "Silent",
+ "Flag requesting silent operation.", FALSE,
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property
+ (object_class, PROP_PROTOCOL,
+ g_param_spec_int
+ ("protocol", "Protocol",
+ "The gpgme protocol currently selected.",
+ GPGME_PROTOCOL_OpenPGP, GPGME_PROTOCOL_UNKNOWN, GPGME_PROTOCOL_UNKNOWN,
+ G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY));
+
+}
+
+
+GType
+gpa_stream_verify_operation_get_type (void)
+{
+ static GType stream_verify_operation_type = 0;
+
+ if (! stream_verify_operation_type)
+ {
+ static const GTypeInfo stream_verify_operation_info =
+ {
+ sizeof (GpaStreamVerifyOperationClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) gpa_stream_verify_operation_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (GpaStreamVerifyOperation),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) gpa_stream_verify_operation_init,
+ };
+
+ stream_verify_operation_type = g_type_register_static
+ (GPA_STREAM_OPERATION_TYPE, "GpaStreamVerifyOperation",
+ &stream_verify_operation_info, 0);
+ }
+
+ return stream_verify_operation_type;
+}
+
+
+/* The verify status dialog has returned. */
+static void
+response_cb (GtkDialog *dialog, int response, void *user_data)
+{
+ GpaStreamVerifyOperation *op = user_data;
+
+ gtk_widget_hide (GTK_WIDGET (dialog));
+
+ g_signal_emit_by_name (GPA_OPERATION (op), "completed", 0);
+}
+
+
+/* Show an error message. */
+static void
+done_error_cb (GpaContext *context, gpg_error_t err,
+ GpaStreamVerifyOperation *op)
+{
+ switch (gpg_err_code (err))
+ {
+ case GPG_ERR_NO_ERROR:
+ case GPG_ERR_CANCELED:
+ /* Ignore these */
+ break;
+ default:
+ gpa_gpgme_warning (err);
+ break;
+ }
+}
+
+
+/* Percent-Escape special characters. */
+static gchar *
+my_percent_escape (const gchar *src)
+{
+ gchar *esc_str;
+ int new_len = 3 * strlen (src) + 1;
+ gchar *dst;
+
+ esc_str = g_malloc (new_len);
+
+ dst = esc_str;
+ while (*src)
+ {
+ if (*src == '%')
+ {
+ *(dst++) = '%';
+ *(dst++) = '2';
+ *(dst++) = '5';
+ }
+ else if (*src == ':')
+ {
+ /* The colon is used as field separator. */
+ *(dst++) = '%';
+ *(dst++) = '3';
+ *(dst++) = 'a';
+ }
+ else if (*src == ',')
+ {
+ /* The comma is used as list separator. */
+ *(dst++) = '%';
+ *(dst++) = '2';
+ *(dst++) = 'c';
+ }
+ else
+ *(dst++) = *(src);
+ src++;
+ }
+ *dst = '\0';
+ return esc_str;
+}
+
+
+/* Operation is ready. Tell the server. */
+static void
+done_cb (GpaContext *context, gpg_error_t err, GpaStreamVerifyOperation *op)
+{
+ if (! op->silent)
+ gtk_widget_hide (GPA_STREAM_OPERATION (op)->progress_dialog);
+
+ if (! err)
+ {
+ gpgme_verify_result_t res;
+ gpgme_signature_t sig;
+
+ res = gpgme_op_verify_result (GPA_OPERATION (op)->context->ctx);
+ sig = res->signatures;
+
+ while (sig)
+ {
+ gpgme_key_t key = NULL;
+ char *keydesc = NULL;
+ char *sigsum;
+ char *sigdesc;
+ char *sigdesc_esc;
+ const char *sigstatus;
+
+ if (sig->summary & GPGME_SIGSUM_VALID)
+ sigsum = "green";
+ else if (sig->summary & GPGME_SIGSUM_GREEN)
+ sigsum = "yellow";
+ else if (sig->summary & GPGME_SIGSUM_KEY_MISSING)
+ sigsum = "none";
+ else
+ sigsum = "red";
+
+ sigstatus = gpg_strerror (sig->status);
+
+ if (sig->fpr)
+ {
+ gpgme_get_key (GPA_OPERATION (op)->context->ctx,
+ sig->fpr, &key, 0);
+ if (key)
+ keydesc = gpa_gpgme_key_get_userid (key->uids);
+ }
+
+ if (sig->summary & GPGME_SIGSUM_RED)
+ {
+ if (keydesc)
+ sigdesc = g_strdup_printf (_("Bad signature by %s: %s"),
+ keydesc, sigstatus);
+ else if (sig->fpr)
+ sigdesc = g_strdup_printf (_("Bad signature by unknown key "
+ "%s: %s"), sig->fpr, sigstatus);
+ else
+ sigdesc = g_strdup_printf (_("Bad signature by unknown key: "
+ "%s"), sigstatus);
+ }
+ else if (sig->summary & GPGME_SIGSUM_VALID)
+ {
+ if (keydesc)
+ sigdesc = g_strdup_printf (_("Good signature by %s: %s"),
+ keydesc, sigstatus);
+ else if (sig->fpr)
+ sigdesc = g_strdup_printf (_("Good signature by unknown key "
+ "%s: %s"), sig->fpr, sigstatus);
+ else
+ sigdesc = g_strdup_printf (_("Good signature by unknown key: "
+ "%s"), sigstatus);
+ }
+ else
+ {
+ if (keydesc)
+ sigdesc = g_strdup_printf (_("Invalid signature by %s: %s"),
+ keydesc, sigstatus);
+ else if (sig->fpr)
+ sigdesc = g_strdup_printf (_("Invalid signature by unknown key "
+ "%s: %s"), sig->fpr, sigstatus);
+ else
+ sigdesc = g_strdup_printf (_("Invalid signature by unknown "
+ "key: %s"), sigstatus);
+ }
+
+ sigdesc_esc = my_percent_escape (sigdesc);
+
+ /* FIXME: Error handling. */
+ err = gpa_operation_write_status (GPA_OPERATION (op), "SIGSTATUS",
+ sigsum, sigdesc_esc, NULL);
+
+ g_free (sigdesc);
+ g_free (sigdesc_esc);
+
+ if (key)
+ gpgme_key_unref (key);
+ if (keydesc)
+ g_free (keydesc);
+
+ sig = sig->next;
+ }
+ }
+
+ if (err || op->silent)
+ g_signal_emit_by_name (GPA_OPERATION (op), "completed", err);
+ else
+ {
+ gpgme_verify_result_t result;
+
+ result = gpgme_op_verify_result (GPA_OPERATION (op)->context->ctx);
+ /* Add the file to the result dialog. */
+ gpa_file_verify_dialog_add_file (GPA_FILE_VERIFY_DIALOG (op->dialog),
+ _("Document"), NULL, NULL,
+ result->signatures);
+
+ gtk_widget_show_all (op->dialog);
+ }
+}
+
+
+static gboolean
+idle_cb (gpointer data)
+{
+ GpaStreamVerifyOperation *op = data;
+ GpaStreamOperation *sop = GPA_STREAM_OPERATION (op);
+ gpgme_error_t err;
+
+ gpgme_set_protocol (GPA_OPERATION (op)->context->ctx, op->selected_protocol);
+
+ err = gpgme_op_verify_start (GPA_OPERATION (op)->context->ctx,
+ sop->input_stream, sop->message_stream,
+ sop->output_stream);
+ if (err)
+ {
+ gpa_gpgme_warning (err);
+ g_signal_emit_by_name (GPA_OPERATION (op), "completed", err);
+ }
+ else if (! op->silent)
+ {
+ gtk_widget_show_all (GPA_STREAM_OPERATION (op)->progress_dialog);
+ }
+
+ return FALSE;
+}
+
+
+/* Public API. */
+
+/* FIXME: Doc. */
+GpaStreamVerifyOperation *
+gpa_stream_verify_operation_new (GtkWidget *window,
+ gpgme_data_t input_stream,
+ gpgme_data_t message_stream,
+ gpgme_data_t output_stream,
+ gboolean silent, gpgme_protocol_t protocol)
+{
+ GpaStreamVerifyOperation *op;
+
+ op = g_object_new (GPA_STREAM_VERIFY_OPERATION_TYPE,
+ "window", window,
+ "input_stream", input_stream,
+ "message_stream", message_stream,
+ "output_stream", output_stream,
+ "silent", silent,
+ "protocol", (int) protocol,
+ NULL);
+
+ return op;
+}
Added: trunk/src/gpastreamverifyop.h
===================================================================
--- trunk/src/gpastreamverifyop.h 2008-05-08 16:47:48 UTC (rev 893)
+++ trunk/src/gpastreamverifyop.h 2008-05-09 04:45:25 UTC (rev 894)
@@ -0,0 +1,66 @@
+/* gpastreamverifyop.h - The GpaStreamVerifyOperation object.
+ 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 GPA_STREAM_VERIFY_OP_H
+#define GPA_STREAM_VERIFY_OP_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "gpastreamop.h"
+
+/* GObject stuff. */
+#define GPA_STREAM_VERIFY_OPERATION_TYPE \
+ (gpa_stream_verify_operation_get_type ())
+
+#define GPA_STREAM_VERIFY_OPERATION(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), GPA_STREAM_VERIFY_OPERATION_TYPE, \
+ GpaStreamVerifyOperation))
+
+#define GPA_STREAM_VERIFY_OPERATION_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), GPA_STREAM_VERIFY_OPERATION_TYPE, \
+ GpaStreamVerifyOperationClass))
+
+#define GPA_IS_STREAM_VERIFY_OPERATION(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GPA_STREAM_VERIFY_OPERATION_TYPE))
+
+#define GPA_IS_STREAM_VERIFY_OPERATION_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), GPA_STREAM_VERIFY_OPERATION_TYPE))
+
+#define GPA_STREAM_VERIFY_OPERATION_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), GPA_STREAM_VERIFY_OPERATION_TYPE, \
+ GpaStreamVerifyOperationClass))
+
+typedef struct _GpaStreamVerifyOperation GpaStreamVerifyOperation;
+typedef struct _GpaStreamVerifyOperationClass GpaStreamVerifyOperationClass;
+
+GType gpa_stream_verify_operation_get_type (void) G_GNUC_CONST;
+
+
+/* Public API. */
+
+/* Creates a new verify operation. */
+GpaStreamVerifyOperation *
+gpa_stream_verify_operation_new (GtkWidget *window,
+ gpgme_data_t input_stream,
+ gpgme_data_t message_stream,
+ gpgme_data_t output_stream,
+ gboolean silent,
+ gpgme_protocol_t protocol);
+
+#endif /* GPA_STREAM_VERIFY_OP_H */
Modified: trunk/src/server.c
===================================================================
--- trunk/src/server.c 2008-05-08 16:47:48 UTC (rev 893)
+++ trunk/src/server.c 2008-05-09 04:45:25 UTC (rev 894)
@@ -1,24 +1,25 @@
/* server.c - The UI server part of GPA.
- * 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/>.
- */
+ Copyright (C) 2007, 2008 g10 Code GmbH
-#include <config.h>
+ 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/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
@@ -28,6 +29,7 @@
# include <sys/socket.h>
# include <sys/un.h>
#endif /*HAVE_W32_SYSTEM*/
+
#include <gpgme.h>
#include <glib.h>
#include <assuan.h>
@@ -36,9 +38,10 @@
#include "i18n.h"
#include "gpastreamencryptop.h"
#include "gpastreamsignop.h"
+#include "gpastreamdecryptop.h"
+#include "gpastreamverifyop.h"
-
#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. */
@@ -242,6 +245,7 @@
NULL
};
+
static ssize_t
my_gpgme_message_read_cb (void *opaque, void *buffer, size_t size)
{
@@ -280,6 +284,21 @@
};
+static ssize_t
+my_devnull_write_cb (void *opaque, const void *buffer, size_t size)
+{
+ return size;
+}
+
+
+static struct gpgme_data_cbs my_devnull_data_cbs =
+ {
+ NULL,
+ my_devnull_write_cb,
+ NULL,
+ NULL
+ };
+
/* Release the recipients stored in the connection context. */
static void
@@ -375,6 +394,12 @@
g_io_channel_shutdown (ctrl->message_channel, 0, NULL);
ctrl->message_channel = NULL;
}
+
+ close_message_fd (ctrl);
+ assuan_close_input_fd (ctx);
+ assuan_close_output_fd (ctx);
+ ctrl->input_fd = -1;
+ ctrl->output_fd = -1;
}
@@ -461,22 +486,22 @@
g_io_channel_set_buffered (ctrl->message_channel, FALSE);
}
- if (ctrl->input_fd != -1 && r_input_data)
+ if (ctrl->input_channel)
{
err = gpgme_data_new_from_cbs (r_input_data, &my_gpgme_data_cbs, ctrl);
if (err)
goto leave;
}
- if (ctrl->output_fd != -1 && r_output_data)
+ if (ctrl->output_channel)
{
err = gpgme_data_new_from_cbs (r_output_data, &my_gpgme_data_cbs, ctrl);
if (err)
goto leave;
}
- if (ctrl->message_fd != -1 && r_message_data)
+ if (ctrl->message_channel)
{
err = gpgme_data_new_from_cbs (r_message_data,
- &my_gpgme_message_cbs, ctrl);
+ &my_gpgme_message_cbs, ctrl);
if (err)
goto leave;
}
@@ -646,6 +671,8 @@
close_message_fd (ctrl);
assuan_close_input_fd (ctx);
assuan_close_output_fd (ctx);
+ ctrl->input_fd = -1;
+ ctrl->output_fd = -1;
return assuan_process_done (ctx, err);
}
@@ -835,6 +862,8 @@
close_message_fd (ctrl);
assuan_close_input_fd (ctx);
assuan_close_output_fd (ctx);
+ ctrl->input_fd = -1;
+ ctrl->output_fd = -1;
return assuan_process_done (ctx, err);
}
@@ -850,11 +879,6 @@
gpg_strerror (err), gpg_strsource (err));
finish_io_streams (ctx, NULL, NULL, NULL);
- if (!err)
- {
- xfree (ctrl->sender);
- ctrl->sender = NULL;
- }
assuan_process_done (ctx, err);
}
@@ -866,8 +890,7 @@
If the option --no-verify is given, the server should not try to
verify a signature, in case the input data is an OpenPGP combined
- message.
-*/
+ message. */
static int
cmd_decrypt (assuan_context_t ctx, char *line)
{
@@ -875,7 +898,7 @@
gpg_error_t err;
gpgme_protocol_t protocol = 0;
int no_verify;
- GpaStreamSignOperation *op; /* Fixme: use GpaStreamDecryptOperatio!!!*/
+ GpaStreamDecryptOperation *op;
gpgme_data_t input_data = NULL;
gpgme_data_t output_data = NULL;
@@ -883,7 +906,7 @@
if (err)
goto leave;
- no_verify= has_option (line, "--no-verify");
+ no_verify = has_option (line, "--no-verify");
line = skip_options (line);
if (*line)
@@ -901,9 +924,8 @@
ctrl->cont_cmd = cont_decrypt;
-#warning FIXME: Use decrypt.
- op = gpa_stream_sign_operation_new (NULL, input_data, output_data,
- ctrl->sender, protocol, 1);
+ op = gpa_stream_decrypt_operation_new (NULL, input_data, output_data,
+ no_verify, protocol);
input_data = output_data = NULL;
g_signal_connect_swapped (G_OBJECT (op), "completed",
@@ -920,6 +942,8 @@
close_message_fd (ctrl);
assuan_close_input_fd (ctx);
assuan_close_output_fd (ctx);
+ ctrl->input_fd = -1;
+ ctrl->output_fd = -1;
return assuan_process_done (ctx, err);
}
@@ -936,11 +960,6 @@
gpg_strerror (err), gpg_strsource (err));
finish_io_streams (ctx, NULL, NULL, NULL);
- if (!err)
- {
- xfree (ctrl->sender);
- ctrl->sender = NULL;
- }
assuan_process_done (ctx, err);
}
@@ -987,8 +1006,7 @@
The signature is not valid.
The DISPLAYSTRING is a percent-and-plus-encoded string with a short
- human readable description of the status.
-*/
+ human readable description of the status. */
static int
cmd_verify (assuan_context_t ctx, char *line)
{
@@ -996,10 +1014,11 @@
gpg_error_t err;
gpgme_protocol_t protocol = 0;
int silent;
- GpaStreamSignOperation *op; /* Fixme: use GpaStreamDecryptOperatio!!!*/
+ GpaStreamVerifyOperation *op;
gpgme_data_t input_data = NULL;
gpgme_data_t output_data = NULL;
gpgme_data_t message_data = NULL;
+ enum { VERIFY_DETACH, VERIFY_OPAQUE, VERIFY_OPAQUE_WITH_OUTPUT } op_mode;
err = parse_protocol_option (ctx, line, 1, &protocol);
if (err)
@@ -1014,19 +1033,19 @@
goto leave;
}
- /* Note: We can't use translate_io_streams becuase that returns an
+ /* Note: We can't use translate_io_streams because that returns an
error if one is not opened but that is not an error here. */
ctrl->input_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
ctrl->output_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
if (ctrl->message_fd != -1 && ctrl->input_fd != -1
&& ctrl->output_fd == -1)
- ; /* Mode = detached. */
+ op_mode = VERIFY_DETACH;
else if (ctrl->message_fd == -1 && ctrl->input_fd != -1
&& ctrl->output_fd == -1)
- ; /* Mode = opaque. */
+ op_mode = VERIFY_OPAQUE;
else if (ctrl->message_fd == -1 && ctrl->input_fd != -1
&& ctrl->output_fd != -1)
- ; /* Mode = opaque with output. */
+ op_mode = VERIFY_OPAQUE_WITH_OUTPUT;
else
{
err = set_error (GPG_ERR_CONFLICT, "invalid verify mode");
@@ -1034,14 +1053,15 @@
}
err = prepare_io_streams (ctx, &input_data, &output_data, &message_data);
+ if (! err && op_mode == VERIFY_OPAQUE)
+ err = gpgme_data_new_from_cbs (&output_data, &my_devnull_data_cbs, ctrl);
if (err)
goto leave;
- ctrl->cont_cmd = cont_decrypt;
+ ctrl->cont_cmd = cont_verify;
-#warning FIXME: Use verify.
- op = gpa_stream_sign_operation_new (NULL, input_data, output_data,
- ctrl->sender, protocol, 1);
+ op = gpa_stream_verify_operation_new (NULL, input_data, message_data,
+ output_data, silent, protocol);
input_data = output_data = message_data = NULL;
g_signal_connect_swapped (G_OBJECT (op), "completed",
@@ -1058,6 +1078,8 @@
close_message_fd (ctrl);
assuan_close_input_fd (ctx);
assuan_close_output_fd (ctx);
+ ctrl->input_fd = -1;
+ ctrl->output_fd = -1;
return assuan_process_done (ctx, err);
}
@@ -1125,6 +1147,8 @@
close_message_fd (ctrl);
assuan_close_input_fd (ctx);
assuan_close_output_fd (ctx);
+ ctrl->input_fd = -1;
+ ctrl->output_fd = -1;
if (ctrl->gpa_op)
{
g_object_unref (ctrl->gpa_op);
More information about the Gpa-commits
mailing list