[Gpa-commits] r785 - trunk/src
scm-commit@wald.intevation.org
scm-commit at wald.intevation.org
Tue Oct 2 20:18:02 CEST 2007
Author: werner
Date: 2007-10-02 20:18:01 +0200 (Tue, 02 Oct 2007)
New Revision: 785
Added:
trunk/src/gpastreamencryptop.c
trunk/src/gpastreamencryptop.h
trunk/src/gpastreamop.c
trunk/src/gpastreamop.h
trunk/src/utils.c
Modified:
trunk/src/ChangeLog
trunk/src/Makefile.am
trunk/src/encryptdlg.c
trunk/src/gpa.c
trunk/src/gpa.h
trunk/src/gpacontext.c
trunk/src/server.c
Log:
New option --cms to enable the X/509/CMS hack.
Started with the implementation of an encrypt server command.
Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog 2007-09-28 17:50:00 UTC (rev 784)
+++ trunk/src/ChangeLog 2007-10-02 18:18:01 UTC (rev 785)
@@ -1,3 +1,11 @@
+2007-10-02 Werner Koch <wk at g10code.com>
+
+ * utils.c (translate_sys2libc_fd): New.
+
+2007-10-01 Werner Koch <wk at g10code.com>
+
+ * utils.c: New to implement xmalloc and xcalloc.
+
2007-09-28 Werner Koch <wk at g10code.com>
* gpakeyselector.c (gpa_key_selector_next_key): Don't segv is not
Modified: trunk/src/Makefile.am
===================================================================
--- trunk/src/Makefile.am 2007-09-28 17:50:00 UTC (rev 784)
+++ trunk/src/Makefile.am 2007-10-02 18:18:01 UTC (rev 785)
@@ -71,6 +71,8 @@
gpaprogressdlg.h gpaprogressdlg.c \
gparecvkeydlg.h gparecvkeydlg.c \
gpaoperation.h gpaoperation.c \
+ gpastreamop.h gpastreamop.c \
+ gpastreamencryptop.h gpastreamencryptop.c \
gpafileop.h gpafileop.c \
gpafiledecryptop.h gpafiledecryptop.c \
gpafileencryptop.h gpafileencryptop.c \
@@ -96,7 +98,8 @@
gpabackupop.h gpabackupop.c \
gpakeyselector.h gpakeyselector.c \
server.c \
- options.c $(gpa_w32_sources)
+ options.c \
+ utils.c $(gpa_w32_sources)
dndtest_SOURCES = dndtest.c
Modified: trunk/src/encryptdlg.c
===================================================================
--- trunk/src/encryptdlg.c 2007-09-28 17:50:00 UTC (rev 784)
+++ trunk/src/encryptdlg.c 2007-10-02 18:18:01 UTC (rev 785)
@@ -69,6 +69,7 @@
}
}
+
static void
gpa_file_encrypt_dialog_set_property (GObject *object,
guint prop_id,
@@ -89,12 +90,14 @@
}
}
+
static void
gpa_file_encrypt_dialog_finalize (GObject *object)
{
G_OBJECT_CLASS (parent_class)->finalize (object);
}
+
static void
gpa_file_encrypt_dialog_class_init (GpaFileEncryptDialogClass *klass)
{
@@ -115,6 +118,7 @@
G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY));
}
+
static void
gpa_file_encrypt_dialog_init (GpaFileEncryptDialog *dialog)
{
@@ -197,6 +201,7 @@
}
+
GType
gpa_file_encrypt_dialog_get_type (void)
{
Modified: trunk/src/gpa.c
===================================================================
--- trunk/src/gpa.c 2007-09-28 17:50:00 UTC (rev 784)
+++ trunk/src/gpa.c 2007-10-02 18:18:01 UTC (rev 785)
@@ -53,6 +53,7 @@
/* Global variables */
gchar *gpa_exec_dir;
gchar *gnupg_homedir;
+int cms_hack;
#ifdef G_OS_WIN32
#include <windows.h>
@@ -360,6 +361,7 @@
{ "server", no_argument, NULL, 's' },
{ "files", no_argument, NULL, 'f' },
{ "options", required_argument, NULL, 'o' },
+ { "cms", no_argument, NULL, 'x' },
{ NULL, 0, NULL, 0 }
};
@@ -376,6 +378,7 @@
{'f', "files", N_("open filemanager")},
{'s', "server", N_("start only the UI server")},
{'o', "options", N_("read options from file")},
+ {'x', "cms", "enable CMS hack"},
{0, NULL, NULL}
};
@@ -442,6 +445,9 @@
case 's':
args->start_only_server = TRUE;
break;
+ case 'x':
+ cms_hack = 1;
+ break;
default:
exit (EXIT_FAILURE);
}
Modified: trunk/src/gpa.h
===================================================================
--- trunk/src/gpa.h 2007-09-28 17:50:00 UTC (rev 784)
+++ trunk/src/gpa.h 2007-10-02 18:18:01 UTC (rev 785)
@@ -51,6 +51,7 @@
extern GtkWidget *global_windowTip;
extern GList *global_defaultRecipients;
extern gchar *gnupg_homedir;
+extern int cms_hack;
void gpa_open_keyring_editor (void);
void gpa_open_filemanager (void);
@@ -66,7 +67,16 @@
void gpa_show_backend_config (void);
+/*-- utils.c --*/
+/* We are so used to these function thus provide them. */
+void *xmalloc (size_t n);
+void *xcalloc (size_t n, size_t m);
+char *xstrdup (const char *str);
+#define xfree(a) g_free ((a))
+int translate_sys2libc_fd (assuan_fd_t fd, int for_write);
+
+
/*-- Convenience macros. -- */
#define DIM(v) (sizeof(v)/sizeof((v)[0]))
#define DIMof(type,member) DIM(((type *)0)->member)
Modified: trunk/src/gpacontext.c
===================================================================
--- trunk/src/gpacontext.c 2007-09-28 17:50:00 UTC (rev 784)
+++ trunk/src/gpacontext.c 2007-10-02 18:18:01 UTC (rev 785)
@@ -22,6 +22,7 @@
#include <glib.h>
#include <gpgme.h>
+#include "gpa.h"
#include "gpgmetools.h"
#include "gpacontext.h"
@@ -167,7 +168,6 @@
{
gpg_error_t err;
- g_debug ("gpa_context_init: enter");
context->busy = FALSE;
/* The callback queue */
@@ -193,7 +193,8 @@
/* Set the callbacks */
gpgme_set_io_cbs (context->ctx, context->io_cbs);
- gpgme_set_protocol (context->ctx, GPGME_PROTOCOL_CMS);
+ if (cms_hack)
+ gpgme_set_protocol (context->ctx, GPGME_PROTOCOL_CMS);
}
static void
@@ -280,7 +281,6 @@
#ifdef G_OS_WIN32
/* We have to ask GPGME for the GIOChannel to use. The "file
descriptor" may not be a system file descriptor. */
- g_debug ("calling gpgme_get_fdptr (%d)", cb->fd);
channel = gpgme_get_giochannel (cb->fd);
g_assert (channel);
#else
@@ -357,7 +357,6 @@
struct gpa_io_cb_data *cb = g_malloc (sizeof (struct gpa_io_cb_data));
- g_debug ("gpa_context_register callback allocated tag %p", cb);
cb->registered = FALSE;
cb->fd = fd;
cb->dir = dir;
@@ -385,10 +384,8 @@
{
struct gpa_io_cb_data *cb = tag;
- g_debug ("gpa_context_remove callback for tag %p called", cb);
if (cb->registered)
{
- g_debug (" really removed");
g_source_remove (cb->watch);
}
cb->context->cbs = g_list_remove (cb->context->cbs, cb);
@@ -409,25 +406,20 @@
switch (type)
{
case GPGME_EVENT_START:
- g_debug ("gpgme event START");
g_signal_emit (context, signals[START], 0);
break;
case GPGME_EVENT_DONE:
err = type_data;
- g_debug ("gpgme event DONE");
g_signal_emit (context, signals[DONE], 0, *err);
break;
case GPGME_EVENT_NEXT_KEY:
- g_debug ("gpgme event NEXT_KEY");
g_signal_emit (context, signals[NEXT_KEY], 0, type_data);
break;
case GPGME_EVENT_NEXT_TRUSTITEM:
- g_debug ("gpgme event TRUSTITEM");
g_signal_emit (context, signals[NEXT_TRUST_ITEM], 0,
type_data);
break;
default:
- g_debug ("gpgme event no=%d", type);
/* Ignore unsupported event types */
break;
}
Added: trunk/src/gpastreamencryptop.c
===================================================================
--- trunk/src/gpastreamencryptop.c 2007-09-28 17:50:00 UTC (rev 784)
+++ trunk/src/gpastreamencryptop.c 2007-10-02 18:18:01 UTC (rev 785)
@@ -0,0 +1,526 @@
+/* gpastreamdecryptop.c - The GpaOperation object.
+ * Copyright (C) 2007 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 <glib.h>
+
+#include "gpgmetools.h"
+#include "encryptdlg.h"
+#include "gpawidgets.h"
+#include "gpapastrings.h"
+#include "gpastreamencryptop.h"
+
+static void response_cb (GtkDialog *dialog,
+ gint response,
+ gpointer user_data);
+static void done_error_cb (GpaContext *context, gpg_error_t err,
+ GpaStreamEncryptOperation *op);
+static void done_cb (GpaContext *context, gpg_error_t err,
+ GpaStreamEncryptOperation *op);
+
+static GObjectClass *parent_class;
+
+
+/* Helper to be used as a GFunc for free. */
+static void
+free_func (void *p, void *dummy)
+{
+ (void)dummy;
+ g_free (p);
+}
+
+
+
+
+static void
+gpa_stream_encrypt_operation_finalize (GObject *object)
+{
+/* GpaStreamEncryptOperation *op = GPA_STREAM_ENCRYPT_OPERATION (object); */
+
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+static void
+gpa_stream_encrypt_operation_init (GpaStreamEncryptOperation *op)
+{
+ op->encrypt_dialog = NULL;
+}
+
+
+static GObject*
+gpa_stream_encrypt_operation_constructor
+ (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *object;
+ GpaStreamEncryptOperation *op;
+
+ object = parent_class->constructor (type,
+ n_construct_properties,
+ construct_properties);
+ op = GPA_STREAM_ENCRYPT_OPERATION (object);
+
+ /* Create the "Encrypt" dialog */
+ op->encrypt_dialog = gpa_file_encrypt_dialog_new
+ (GPA_OPERATION (op)->window);
+
+ 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
+ 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),
+ _("Encrypting message ..."));
+
+ gtk_widget_show_all (op->encrypt_dialog);
+
+ return object;
+}
+
+
+static void
+gpa_stream_encrypt_operation_class_init (GpaStreamEncryptOperationClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->constructor = gpa_stream_encrypt_operation_constructor;
+ object_class->finalize = gpa_stream_encrypt_operation_finalize;
+}
+
+
+GType
+gpa_stream_encrypt_operation_get_type (void)
+{
+ static GType stream_encrypt_operation_type = 0;
+
+ if (!stream_encrypt_operation_type)
+ {
+ static const GTypeInfo stream_encrypt_operation_info =
+ {
+ sizeof (GpaStreamEncryptOperationClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) gpa_stream_encrypt_operation_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (GpaStreamEncryptOperation),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) gpa_stream_encrypt_operation_init,
+ };
+
+ stream_encrypt_operation_type = g_type_register_static
+ (GPA_STREAM_OPERATION_TYPE, "GpaStreamEncryptOperation",
+ &stream_encrypt_operation_info, 0);
+ }
+
+ return stream_encrypt_operation_type;
+}
+
+
+static gpg_error_t
+start_encryption (GpaStreamEncryptOperation *op, gpgme_key_t *keys)
+{
+ gpg_error_t err;
+
+ /* Start the operation */
+ /* Always trust keys, because any untrusted keys were already confirmed
+ * by the user.
+ */
+/* if (gpa_file_encrypt_dialog_sign */
+/* (GPA_FILE_ENCRYPT_DIALOG (op->encrypt_dialog))) */
+/* { */
+/* /\* Signing was request as well. *\/ */
+/* err = gpgme_op_encrypt_sign_start (GPA_OPERATION (op)->context->ctx, */
+/* op->rset, GPGME_ENCRYPT_ALWAYS_TRUST, */
+/* op->plain, op->cipher); */
+/* } */
+/* else */
+ {
+ /* Plain encryption. */
+ err = gpgme_op_encrypt_start (GPA_OPERATION (op)->context->ctx,
+ keys, GPGME_ENCRYPT_ALWAYS_TRUST,
+ GPA_STREAM_OPERATION (op)->input_stream,
+ GPA_STREAM_OPERATION (op)->output_stream);
+ }
+ if (err)
+ {
+ gpa_gpgme_warning (err);
+ return err;
+ }
+
+ /* Show and update the progress dialog */
+ gtk_widget_show_all (GPA_STREAM_OPERATION (op)->progress_dialog);
+ gpa_progress_dialog_set_label (GPA_PROGRESS_DIALOG
+ (GPA_STREAM_OPERATION (op)->progress_dialog),
+ _("Message encryption"));
+ return 0;
+}
+
+
+
+/*
+ * 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
+ 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.
+ */
+static gpg_error_t
+parse_recipients (GpaStreamEncryptOperation *op, GSList *recipients,
+ gpgme_key_t **r_found, GSList **r_unknown)
+{
+ gpgme_error_t err;
+ GSList *recp;
+ gpgme_ctx_t ctx;
+ size_t n;
+ gpgme_key_t *found;
+ GSList *unknown = NULL;
+ int found_idx;
+ gpgme_key_t key, key2;
+ const char *name;
+
+ *r_found = NULL;
+ *r_unknown = NULL;
+
+ err = gpgme_new (&ctx);
+ if (err)
+ return err;
+
+ for (n=0, recp = recipients; recp; recp = g_slist_next (recp))
+ n++;
+
+ found = xcalloc (n+1, sizeof *found);
+ found_idx = 0;
+ for (recp = recipients; recp; recp = g_slist_next (recp))
+ {
+ name = recp->data;
+ if (!name)
+ continue;
+ key = NULL;
+ err = gpgme_op_keylist_start (ctx, name, 0);
+ if (!err)
+ {
+ err = gpgme_op_keylist_next (ctx, &key);
+ if (!err && !gpgme_op_keylist_next (ctx, &key2))
+ {
+ /* Not found or ambiguous key specification. */
+ gpgme_key_unref (key);
+ gpgme_key_unref (key2);
+ key = key2 = NULL;
+ }
+ }
+ 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)
+ {
+ gpgme_key_ref (key);
+ found[found_idx++] = key;
+ }
+ else if (key)
+ {
+ char *p;
+ const char *warn = (key->revoked? "revoked" :
+ key->expired? "expired" : "disabled");
+
+ n = strlen (name) + 3 + strlen (warn);
+ p = xmalloc (n+1);
+ snprintf (p, n, "%s (%s)", name, warn);
+ unknown = g_slist_append (unknown, p);
+ }
+ else /* Not found or ambiguous. */
+ unknown = g_slist_append (unknown, xstrdup (name));
+
+ gpgme_key_unref (key);
+ }
+ gpgme_release (ctx);
+
+ *r_found = found;
+ *r_unknown = unknown;
+ return 0;
+}
+
+
+/*
+ * The key selection dialog has returned.
+ */
+static void
+response_cb (GtkDialog *dialog, int response, void *user_data)
+{
+ gpg_error_t err;
+ GSList *recipients;
+ GpaStreamEncryptOperation *op = user_data;
+ gpgme_key_t *keys;
+ GSList *unknown_recp;
+
+ gtk_widget_hide (GTK_WIDGET (dialog));
+
+ if (response != GTK_RESPONSE_OK)
+ {
+ /* The dialog was canceled, so we do nothing and complete the
+ * operation */
+ gpa_operation_server_finish (GPA_OPERATION (op),
+ gpg_error (GPG_ERR_CANCELED));
+ g_signal_emit_by_name (GPA_OPERATION (op), "completed");
+ return;
+ }
+
+ recipients = g_slist_append (NULL, xstrdup ("wk at gnupg.org"));
+
+/* gpa_stream_encrypt_dialog_recipients */
+/* (GPA_STREAM_ENCRYPT_DIALOG (op->encrypt_dialog)); */
+
+ err = parse_recipients (op, recipients, &keys, &unknown_recp);
+ if (err)
+ goto leave;
+
+
+ /* Our streams work all in ascii armored mode (Either PGP or PEM) */
+ gpgme_set_armor (GPA_OPERATION (op)->context->ctx, 1);
+ err = start_encryption (op, keys);
+
+ leave:
+ if (keys)
+ {
+ int idx;
+
+ for (idx=0; keys[idx]; idx++)
+ gpgme_key_unref (keys[idx]);
+ xfree (keys);
+ }
+ g_slist_foreach (unknown_recp, free_func, NULL);
+ g_slist_free (unknown_recp);
+ g_slist_foreach (recipients, free_func, NULL);
+ g_slist_free (recipients);
+ if (err)
+ {
+ gpa_operation_server_finish (GPA_OPERATION (op), err);
+ g_signal_emit_by_name (GPA_OPERATION (op), "completed");
+ }
+}
+
+
+
+/*Show an error message. */
+static void
+done_error_cb (GpaContext *context, gpg_error_t err,
+ GpaStreamEncryptOperation *op)
+{
+ switch (gpg_err_code (err))
+ {
+ case GPG_ERR_NO_ERROR:
+ case GPG_ERR_CANCELED:
+ /* Ignore these */
+ break;
+/* case GPG_ERR_BAD_PASSPHRASE: */
+/* gpa_window_error (_("Wrong passphrase!"), GPA_OPERATION (op)->window); */
+/* break; */
+ default:
+ gpa_gpgme_warning (err);
+ break;
+ }
+}
+
+/* Operation is ready. Tell the server. */
+static void
+done_cb (GpaContext *context, gpg_error_t err, GpaStreamEncryptOperation *op)
+{
+
+ gtk_widget_hide (GPA_STREAM_OPERATION (op)->progress_dialog);
+
+ /* Tell the server that we finished and delete ourself. */
+ gpa_operation_server_finish (GPA_OPERATION (op), err);
+ g_signal_emit_by_name (GPA_OPERATION (op), "completed");
+}
+
+
+
+
+/* API */
+
+GpaStreamEncryptOperation*
+gpa_stream_encrypt_operation_new (GtkWidget *window,
+ gpgme_data_t input_stream,
+ gpgme_data_t output_stream,
+ void *server_ctx)
+{
+ GpaStreamEncryptOperation *op;
+
+ op = g_object_new (GPA_STREAM_ENCRYPT_OPERATION_TYPE,
+ "window", window,
+ "input_stream", input_stream,
+ "output_stream", output_stream,
+ "server-ctx", server_ctx,
+ NULL);
+
+ return op;
+}
+
Added: trunk/src/gpastreamencryptop.h
===================================================================
--- trunk/src/gpastreamencryptop.h 2007-09-28 17:50:00 UTC (rev 784)
+++ trunk/src/gpastreamencryptop.h 2007-10-02 18:18:01 UTC (rev 785)
@@ -0,0 +1,85 @@
+/* gpastreamencryptop.h - The GpaStreamEncryptOperation object.
+ * Copyright (C) 2007 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_ENCRYPT_OP_H
+#define GPA_STREAM_ENCRYPT_OP_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include "gpastreamop.h"
+
+/* GObject stuff */
+#define GPA_STREAM_ENCRYPT_OPERATION_TYPE \
+ (gpa_stream_encrypt_operation_get_type ())
+
+#define GPA_STREAM_ENCRYPT_OPERATION(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), GPA_STREAM_ENCRYPT_OPERATION_TYPE,\
+ GpaStreamEncryptOperation))
+
+#define GPA_STREAM_ENCRYPT_OPERATION_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ GPA_STREAM_ENCRYPT_OPERATION_TYPE, \
+ GpaStreamEncryptOperationClass))
+
+#define GPA_IS_STREAM_ENCRYPT_OPERATION(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\
+ GPA_STREAM_ENCRYPT_OPERATION_TYPE))
+
+#define GPA_IS_STREAM_ENCRYPT_OPERATION_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ GPA_STREAM_ENCRYPT_OPERATION_TYPE))
+
+#define GPA_STREAM_ENCRYPT_OPERATION_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ GPA_STREAM_ENCRYPT_OPERATION_TYPE, \
+ GpaStreamEncryptOperationClass))
+
+typedef struct _GpaStreamEncryptOperation GpaStreamEncryptOperation;
+typedef struct _GpaStreamEncryptOperationClass GpaStreamEncryptOperationClass;
+
+
+struct _GpaStreamEncryptOperation
+{
+ GpaStreamOperation parent;
+
+ GtkWidget *encrypt_dialog;
+};
+
+
+struct _GpaStreamEncryptOperationClass
+{
+ GpaStreamOperationClass parent_class;
+};
+
+
+GType gpa_stream_encrypt_operation_get_type (void) G_GNUC_CONST;
+
+/* API */
+
+/* Creates a new encryption operation. */
+GpaStreamEncryptOperation *
+gpa_stream_encrypt_operation_new (GtkWidget *window,
+ gpgme_data_t input_stream,
+ gpgme_data_t output_stream,
+ void *server_ctx);
+
+
+
+#endif /*GPA_STREAM_ENCRYPT_OP_H*/
Added: trunk/src/gpastreamop.c
===================================================================
--- trunk/src/gpastreamop.c 2007-09-28 17:50:00 UTC (rev 784)
+++ trunk/src/gpastreamop.c 2007-10-02 18:18:01 UTC (rev 785)
@@ -0,0 +1,206 @@
+/* gpastreamop.c - The GpaStreamOperation object.
+ * Copyright (C) 2007 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 "i18n.h"
+#include "gtktools.h"
+#include "gpastreamop.h"
+
+/* Signals */
+enum
+{
+ LAST_SIGNAL
+};
+
+/* Properties */
+enum
+{
+ PROP_0,
+ PROP_INPUT_STREAM,
+ PROP_OUTPUT_STREAM,
+ PROP_MESSAGE_STREAM
+};
+
+static GObjectClass *parent_class;
+/* static guint signals[LAST_SIGNAL]; */
+
+
+static void
+gpa_stream_operation_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GpaStreamOperation *op = GPA_STREAM_OPERATION (object);
+
+ switch (prop_id)
+ {
+ case PROP_INPUT_STREAM:
+ g_value_set_pointer (value, op->input_stream);
+ break;
+ case PROP_OUTPUT_STREAM:
+ g_value_set_pointer (value, op->output_stream);
+ break;
+ case PROP_MESSAGE_STREAM:
+ g_value_set_pointer (value, op->message_stream);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+static void
+gpa_stream_operation_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GpaStreamOperation *op = GPA_STREAM_OPERATION (object);
+
+ switch (prop_id)
+ {
+ case PROP_INPUT_STREAM:
+ op->input_stream = (gpgme_data_t)g_value_get_pointer (value);
+ break;
+ case PROP_OUTPUT_STREAM:
+ op->output_stream = (gpgme_data_t)g_value_get_pointer (value);
+ break;
+ case PROP_MESSAGE_STREAM:
+ op->message_stream = (gpgme_data_t)g_value_get_pointer (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+static void
+gpa_stream_operation_finalize (GObject *object)
+{
+ GpaStreamOperation *op = GPA_STREAM_OPERATION (object);
+
+ gpgme_data_release (op->input_stream);
+ gpgme_data_release (op->output_stream);
+ gpgme_data_release (op->output_stream);
+ gtk_widget_destroy (op->progress_dialog);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+static void
+gpa_stream_operation_init (GpaStreamOperation *op)
+{
+ op->input_stream = NULL;
+ op->output_stream = NULL;
+ op->message_stream = NULL;
+
+ op->progress_dialog = NULL;
+}
+
+
+static GObject*
+gpa_stream_operation_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *object;
+ GpaStreamOperation *op;
+
+ object = parent_class->constructor (type,
+ n_construct_properties,
+ construct_properties);
+ op = GPA_STREAM_OPERATION (object);
+
+ op->progress_dialog = gpa_progress_dialog_new (GPA_OPERATION(op)->window,
+ GPA_OPERATION(op)->context);
+
+ return object;
+}
+
+
+static void
+gpa_stream_operation_class_init (GpaStreamOperationClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->constructor = gpa_stream_operation_constructor;
+ object_class->finalize = gpa_stream_operation_finalize;
+ object_class->set_property = gpa_stream_operation_set_property;
+ object_class->get_property = gpa_stream_operation_get_property;
+
+ /* Signals */
+ /* Properties */
+ g_object_class_install_property (object_class,
+ PROP_INPUT_STREAM,
+ g_param_spec_pointer
+ ("input_stream", "Input Stream",
+ "Data read by gpg/gpgsm",
+ G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_OUTPUT_STREAM,
+ g_param_spec_pointer
+ ("output_stream", "Output Stream",
+ "Data written by gpg/gpgsm",
+ G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_INPUT_STREAM,
+ g_param_spec_pointer
+ ("message_stream", "Message Stream",
+ "Message data read by gpg/gpgsm",
+ G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY));
+}
+
+
+GType
+gpa_stream_operation_get_type (void)
+{
+ static GType stream_operation_type = 0;
+
+ if (!stream_operation_type)
+ {
+ static const GTypeInfo stream_operation_info =
+ {
+ sizeof (GpaStreamOperationClass),
+ (GBaseInitFunc)NULL,
+ (GBaseFinalizeFunc)NULL,
+ (GClassInitFunc)gpa_stream_operation_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (GpaStreamOperation),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc)gpa_stream_operation_init,
+ };
+
+ stream_operation_type = g_type_register_static
+ (GPA_OPERATION_TYPE, "GpaStreamOperation",
+ &stream_operation_info, 0);
+ }
+
+ return stream_operation_type;
+}
+
+
+
Added: trunk/src/gpastreamop.h
===================================================================
--- trunk/src/gpastreamop.h 2007-09-28 17:50:00 UTC (rev 784)
+++ trunk/src/gpastreamop.h 2007-10-02 18:18:01 UTC (rev 785)
@@ -0,0 +1,72 @@
+/* gpastreamop.h - The GpaStreamOperation object.
+ * Copyright (C) 2007 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_OP_H
+#define GPA_STREAM_OP_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include "gpa.h"
+#include "gpaoperation.h"
+#include "gpaprogressdlg.h"
+
+/* GObject stuff */
+#define GPA_STREAM_OPERATION_TYPE \
+ (gpa_stream_operation_get_type ())
+#define GPA_STREAM_OPERATION(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), GPA_STREAM_OPERATION_TYPE, GpaStreamOperation))
+#define GPA_STREAM_OPERATION_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((klass), GPA_STREAM_OPERATION_TYPE, \
+ GpaStreamOperationClass))
+#define GPA_IS_STREAM_OPERATION(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), GPA_STREAM_OPERATION_TYPE))
+#define GPA_IS_STREAM_OPERATION_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), GPA_STREAM_OPERATION_TYPE))
+#define GPA_STREAM_OPERATION_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), GPA_STREAM_OPERATION_TYPE, GpaStreamOperationClass))
+
+typedef struct _GpaStreamOperation GpaStreamOperation;
+typedef struct _GpaStreamOperationClass GpaStreamOperationClass;
+
+struct _GpaStreamOperation {
+ GpaOperation parent;
+
+ gpgme_data_t input_stream;
+ gpgme_data_t output_stream;
+ gpgme_data_t message_stream;
+
+ GtkWidget *progress_dialog;
+};
+
+struct _GpaStreamOperationClass {
+ GpaOperationClass parent_class;
+
+};
+
+GType gpa_stream_operation_get_type (void) G_GNUC_CONST;
+
+/*** API ***/
+
+
+
+#endif /*GPA_STREAM_OP_H*/
Modified: trunk/src/server.c
===================================================================
--- trunk/src/server.c 2007-09-28 17:50:00 UTC (rev 784)
+++ trunk/src/server.c 2007-10-02 18:18:01 UTC (rev 785)
@@ -29,23 +29,11 @@
#include <glib.h>
#include <assuan.h>
-#ifdef HAVE_W32_SYSTEM
-# include "w32-afunix.h"
-#else
-# include <sys/socket.h>
-# include <sys/un.h>
-#endif
-
#include "gpa.h"
#include "i18n.h"
-#include "gpafileencryptop.h"
+#include "gpastreamencryptop.h"
-#ifdef HAVE_W32_SYSTEM
-#define myclosesock(a) _w32_close ((a))
-#else
-#define myclosesock(a) close ((a))
-#endif
#define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
@@ -55,12 +43,32 @@
typedef struct conn_ctrl_s *conn_ctrl_t;
struct conn_ctrl_s
{
- /* NULL or continuation function or a command. */
+ /* True if we are currently processing a command. */
+ int in_command;
+
+ /* NULL or continuation function for a command. */
void (*cont_cmd) (assuan_context_t, gpg_error_t);
+
+ /* File descriptors used by the gpgme callbacks. */
+ int input_fd;
+ int output_fd;
+
+ /* Channels used with the gpgme callbacks. */
+ GIOChannel *input_channel;
+ GIOChannel *output_channel;
+
+ /* Gpgme Data objects. */
+ gpgme_data_t input_data;
+ gpgme_data_t output_data;
+
};
+static assuan_sock_nonce_t socket_nonce;
+
+
+
/* Test whether LINE contains thye option NAME. An optional argument
of the option is ignored. For example with NAME being "--protocol"
@@ -109,7 +117,75 @@
+static ssize_t
+my_gpgme_read_cb (void *opaque, void *buffer, size_t size)
+{
+ conn_ctrl_t ctrl = opaque;
+ GIOStatus status;
+ size_t nread;
+ int retval;
+ status = g_io_channel_read_chars (ctrl->input_channel, buffer, size,
+ &nread, NULL);
+ if (status == G_IO_STATUS_AGAIN
+ || (status == G_IO_STATUS_NORMAL && !nread))
+ {
+ errno = EAGAIN;
+ retval = -1;
+ }
+ else if (status == G_IO_STATUS_NORMAL)
+ retval = (int)nread;
+ else if (status == G_IO_STATUS_EOF)
+ retval = 0;
+ else
+ {
+ errno = EIO;
+ retval = 1;
+ }
+
+ return retval;
+}
+
+
+static ssize_t
+my_gpgme_write_cb (void *opaque, const void *buffer, size_t size)
+{
+ conn_ctrl_t ctrl = opaque;
+ GIOStatus status;
+ size_t nwritten;
+ int retval;
+
+ status = g_io_channel_write_chars (ctrl->output_channel, buffer, size,
+ &nwritten, NULL);
+ if (status == G_IO_STATUS_AGAIN)
+ {
+ errno = EAGAIN;
+ retval = -1;
+ }
+ else if (status == G_IO_STATUS_NORMAL)
+ retval = (int)nwritten;
+ else
+ {
+ errno = EIO;
+ retval = 1;
+ }
+
+ return retval;
+}
+
+
+static struct gpgme_data_cbs my_gpgme_data_cbs =
+ {
+ my_gpgme_read_cb,
+ my_gpgme_write_cb,
+ NULL,
+ NULL
+ };
+
+
+
+
+
/* Continuation for cmd_encrypt. */
void
@@ -120,6 +196,18 @@
g_debug ("cont_encrypt called with with ERR=%s <%s>",
gpg_strerror (err), gpg_strsource (err));
+ gpgme_data_release (ctrl->input_data); ctrl->input_data = NULL;
+ gpgme_data_release (ctrl->output_data); ctrl->output_data = NULL;
+ if (ctrl->input_channel)
+ {
+ g_io_channel_shutdown (ctrl->input_channel, 0, NULL);
+ ctrl->input_channel = NULL;
+ }
+ if (ctrl->output_channel)
+ {
+ g_io_channel_shutdown (ctrl->output_channel, 0, NULL);
+ ctrl->output_channel = NULL;
+ }
assuan_process_done (ctx, err);
}
@@ -134,8 +222,9 @@
conn_ctrl_t ctrl = assuan_get_pointer (ctx);
gpg_error_t err;
gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
- int inp_fd, out_fd;
+ GpaStreamEncryptOperation *op;
+
if (has_option (line, "--protocol=OpenPGP"))
; /* This is the default. */
else if (has_option (line, "--protocol=CMS"))
@@ -153,31 +242,75 @@
goto leave;
}
-/* inp_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0); */
-/* if (inp_fd == -1) */
-/* { */
-/* err = set_error (GPG_ERR_ASS_NO_INPUT, NULL); */
-/* goto leave; */
-/* } */
-/* out_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1); */
-/* if (out_fd == -1) */
-/* { */
-/* err = set_error (GPG_ERR_ASS_NO_OUTPUT, NULL); */
-/* goto leave; */
-/* } */
+ ctrl->input_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
+ if (ctrl->input_fd == -1)
+ {
+ err = set_error (GPG_ERR_ASS_NO_INPUT, NULL);
+ goto leave;
+ }
+ ctrl->output_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
+ if (ctrl->output_fd == -1)
+ {
+ err = set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
+ goto leave;
+ }
+#ifdef HAVE_W32_SYSTEM
+ ctrl->input_channel = g_io_channel_win32_new_socket (ctrl->input_fd);
+#else
+ ctrl->input_channel = g_io_channel_unix_new (ctrl->input_fd);
+#endif
+ if (!ctrl->input_channel)
+ {
+ g_debug ("error creating input channel");
+ err = GPG_ERR_EIO;
+ goto leave;
+ }
+ g_io_channel_set_encoding (ctrl->input_channel, NULL, NULL);
+ g_io_channel_set_buffered (ctrl->input_channel, FALSE);
+
+#ifdef HAVE_W32_SYSTEM
+ ctrl->output_channel = g_io_channel_win32_new_socket (ctrl->output_fd);
+#else
+ ctrl->output_channel = g_io_channel_unix_new (ctrl->output_fd);
+#endif
+ if (!ctrl->output_channel)
+ {
+ g_debug ("error creating output channel");
+ err = GPG_ERR_EIO;
+ goto leave;
+ }
+ g_io_channel_set_encoding (ctrl->output_channel, NULL, NULL);
+ g_io_channel_set_buffered (ctrl->output_channel, FALSE);
+
+
+ err = gpgme_data_new_from_cbs (&ctrl->input_data, &my_gpgme_data_cbs, ctrl);
+ if (err)
+ goto leave;
+ err = gpgme_data_new_from_cbs (&ctrl->output_data, &my_gpgme_data_cbs, ctrl);
+ if (err)
+ goto leave;
+
ctrl->cont_cmd = cont_encrypt;
- {
- GList *files = g_list_append (NULL, g_strdup ("test.txt"));
- GpaFileEncryptOperation *op;
-
- op = gpa_file_encrypt_operation_new_for_server (files, ctx);
- g_signal_connect (G_OBJECT (op), "completed",
- G_CALLBACK (g_object_unref), NULL);
- }
+ op = gpa_stream_encrypt_operation_new (NULL, ctrl->input_data,
+ ctrl->output_data, ctx);
+ g_signal_connect (G_OBJECT (op), "completed",
+ G_CALLBACK (g_object_unref), NULL);
return gpg_error (GPG_ERR_UNFINISHED);
leave:
+ gpgme_data_release (ctrl->input_data); ctrl->input_data = NULL;
+ gpgme_data_release (ctrl->output_data); ctrl->output_data = NULL;
+ if (ctrl->input_channel)
+ {
+ g_io_channel_shutdown (ctrl->input_channel, 0, NULL);
+ ctrl->input_channel = NULL;
+ }
+ if (ctrl->output_channel)
+ {
+ g_io_channel_shutdown (ctrl->output_channel, 0, NULL);
+ ctrl->output_channel = NULL;
+ }
assuan_close_input_fd (ctx);
assuan_close_output_fd (ctx);
return assuan_process_done (ctx, err);
@@ -192,6 +325,7 @@
Supported values for WHAT are:
version - Return the version of the program.
+ pid - Return the process id of the server.
*/
static int
cmd_getinfo (assuan_context_t ctx, char *line)
@@ -203,6 +337,13 @@
const char *s = PACKAGE_NAME " " PACKAGE_VERSION;
err = assuan_send_data (ctx, s, strlen (s));
}
+ else if (!strcmp (line, "pid"))
+ {
+ char numbuf[50];
+
+ snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
+ err = assuan_send_data (ctx, numbuf, strlen (numbuf));
+ }
else
err = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
@@ -220,8 +361,10 @@
const char *name;
int (*handler)(assuan_context_t, char *line);
} table[] = {
- { "ENCRYPT", cmd_encrypt },
- { "GETINFO", cmd_getinfo },
+ { "INPUT", NULL },
+ { "OUTPUT", NULL },
+ { "ENCRYPT", cmd_encrypt },
+ { "GETINFO", cmd_getinfo },
{ NULL }
};
int i, rc;
@@ -247,7 +390,7 @@
/* Get an assuan context for the already accepted file descriptor
FD. */
- err = assuan_init_socket_server_ext (&ctx, fd, 2);
+ err = assuan_init_socket_server_ext (&ctx, ASSUAN_INT2FD(fd), 2);
if (err)
{
g_debug ("failed to initialize the new connection: %s",
@@ -279,7 +422,19 @@
if (ctx)
{
conn_ctrl_t ctrl = assuan_get_pointer (ctx);
-
+
+ gpgme_data_release (ctrl->input_data);
+ gpgme_data_release (ctrl->output_data);
+ if (ctrl->input_channel)
+ {
+ g_io_channel_shutdown (ctrl->input_channel, 0, NULL);
+ ctrl->input_channel = NULL;
+ }
+ if (ctrl->output_channel)
+ {
+ g_io_channel_shutdown (ctrl->output_channel, 0, NULL);
+ ctrl->output_channel = NULL;
+ }
assuan_deinit_server (ctx);
g_free (ctrl);
}
@@ -330,9 +485,16 @@
g_debug (" input received while waiting for continuation");
g_usleep (2000000);
}
+ else if (ctrl->in_command)
+ {
+ g_debug (" input received while still processing command");
+ g_usleep (2000000);
+ }
else
{
+ ctrl->in_command++;
err = assuan_process_next (ctx);
+ ctrl->in_command--;
g_debug ("assuan_process_next returned: %s",
err == -1? "EOF": gpg_strerror (err));
if (gpg_err_code (err) == GPG_ERR_EOF || err == -1)
@@ -341,14 +503,19 @@
/* FIXME: what about the socket? */
return FALSE; /* Remove from the watch. */
}
- else if (gpg_err_code (err) == GPG_ERR_UNFINISHED
- && !ctrl->cont_cmd)
+ else if (gpg_err_code (err) == GPG_ERR_UNFINISHED)
{
- /* It is quite possible that some other subsystem
- retruns that erro code. Note the user about this
- curiosity. */
- g_debug ("note: Unfinished error code not emitted by us");
+ if ( !ctrl->cont_cmd)
+ {
+ /* 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");
+ assuan_process_done (ctx, err);
+ }
}
+ else
+ assuan_process_done (ctx, err);
}
}
return TRUE;
@@ -382,6 +549,11 @@
g_debug ("error accepting connection: %s", strerror (errno));
goto leave;
}
+ if (assuan_sock_check_nonce (ASSUAN_INT2FD(fd), &socket_nonce))
+ {
+ g_debug ("new connection at fd %d refused", fd);
+ goto leave;
+ }
g_debug ("new connection at fd %d", fd);
ctx = connection_startup (fd);
@@ -420,7 +592,7 @@
leave:
if (fd != -1)
- myclosesock (fd);
+ assuan_sock_close (ASSUAN_INT2FD (fd));
return TRUE; /* Keep the listen_fd in the event loop. */
}
@@ -432,7 +604,7 @@
{
char *socket_name;
int rc;
- int fd;
+ assuan_fd_t fd;
struct sockaddr_un serv_addr;
socklen_t serv_addr_len = sizeof serv_addr;
GIOChannel *channel;
@@ -447,12 +619,8 @@
}
g_debug ("using server socket `%s'", socket_name);
-#ifdef HAVE_W32_SYSTEM
- fd = _w32_sock_new (AF_UNIX, SOCK_STREAM, 0);
-#else
- fd = socket (AF_UNIX, SOCK_STREAM, 0);
-#endif
- if (fd == -1)
+ fd = assuan_sock_new (AF_UNIX, SOCK_STREAM, 0);
+ if (fd == ASSUAN_INVALID_FD)
{
g_debug ("can't create socket: %s\n", strerror(errno));
g_free (socket_name);
@@ -465,48 +633,42 @@
serv_addr_len = (offsetof (struct sockaddr_un, sun_path)
+ strlen(serv_addr.sun_path) + 1);
-#ifdef HAVE_W32_SYSTEM
- rc = _w32_sock_bind (fd, (struct sockaddr*) &serv_addr, serv_addr_len);
- if (rc == -1 && errno == WSAEADDRINUSE)
- {
- remove (socket_name);
- rc = _w32_sock_bind (fd, (struct sockaddr*) &serv_addr, serv_addr_len);
- }
-#else
- rc = bind (fd, (struct sockaddr*)&serv_addr, serv_addr_len);
+ rc = assuan_sock_bind (fd, (struct sockaddr*) &serv_addr, serv_addr_len);
if (rc == -1 && errno == EADDRINUSE)
{
remove (socket_name);
- rc = bind (fd, (struct sockaddr*)&serv_addr, serv_addr_len);
+ rc = assuan_sock_bind (fd, (struct sockaddr*) &serv_addr, serv_addr_len);
}
-#endif
+ if (rc != -1 && (rc=assuan_sock_get_nonce ((struct sockaddr*) &serv_addr,
+ serv_addr_len, &socket_nonce)))
+ g_debug ("error getting nonce for the socket");
if (rc == -1)
{
g_debug ("error binding socket to `%s': %s\n",
serv_addr.sun_path, strerror (errno) );
- myclosesock (fd);
+ assuan_sock_close (fd);
g_free (socket_name);
return;
}
g_free (socket_name);
socket_name = NULL;
- if (listen (fd, 5) == -1)
+ if (listen (ASSUAN_FD2INT (fd), 5) == -1)
{
g_debug ("listen() failed: %s\n", strerror (errno));
- myclosesock (fd);
+ assuan_sock_close (fd);
return;
}
#ifdef HAVE_W32_SYSTEM
- channel = g_io_channel_win32_new_socket (fd);
+ channel = g_io_channel_win32_new_socket (ASSUAN_FD2INT(fd));
#else
channel = g_io_channel_unix_new (fd);
#endif
if (!channel)
{
g_debug ("error creating a new listening channel\n");
- myclosesock (fd);
+ assuan_sock_close (fd);
return;
}
g_io_channel_set_encoding (channel, NULL, NULL);
@@ -517,7 +679,7 @@
{
g_debug ("error creating watch for listening channel\n");
g_io_channel_shutdown (channel, 0, NULL);
- myclosesock (fd);
+ assuan_sock_close (fd);
return;
}
Added: trunk/src/utils.c
===================================================================
--- trunk/src/utils.c 2007-09-28 17:50:00 UTC (rev 784)
+++ trunk/src/utils.c 2007-10-02 18:18:01 UTC (rev 785)
@@ -0,0 +1,104 @@
+/* utilis.c - Utility functions for GPA.
+ * Copyright (C) 2007 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 <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <glib.h>
+
+#include "gpa.h"
+
+
+/* We want our usual xmalloc function. */
+void *
+xmalloc (size_t n)
+{
+ if (!n)
+ n++;
+ return g_malloc (n);
+}
+
+
+/* We want an xcalloc. The similar g_new0 macro is not correclty
+ implemented as it allows an integer overflow. */
+void *
+xcalloc (size_t n, size_t m)
+{
+ size_t nbytes;
+ void *p;
+
+ nbytes = n * m;
+ if ( m && nbytes / m != n)
+ {
+ errno = ENOMEM;
+ p = NULL;
+ }
+ else
+ p = g_malloc (nbytes);
+ if (p)
+ memset (p, 0, nbytes);
+ else
+ {
+ g_error ("%s: failed to allocate %lu bytes",
+ G_STRLOC, (unsigned long)nbytes);
+ abort (); /* Just in case g_error returns. */
+ }
+
+ return p;
+}
+
+
+char *
+xstrdup (const char *str)
+{
+ char *buf = g_malloc (strlen(str) + 1);
+ strcpy (buf, str);
+ return buf;
+}
+
+
+
+/* This function is a NOP for POSIX systems but required under Windows
+ as the file handles as returned by OS calls (like CreateFile) are
+ different from the libc file descriptors (like open). This function
+ translates system file handles to libc file handles. FOR_WRITE
+ gives the direction of the handle. */
+int
+translate_sys2libc_fd (assuan_fd_t fd, int for_write)
+{
+#ifdef HAVE_W32_SYSTEM
+ int x;
+
+ if (fd == ASSUAN_INVALID_FD)
+ return -1;
+
+ /* Note that _open_osfhandle is currently defined to take and return
+ a long. */
+ x = _open_osfhandle ((long)fd, for_write ? 1 : 0);
+ if (x == -1)
+ g_debug ("failed to translate osfhandle %p\n", (void *) fd);
+ return x;
+#else /*!HAVE_W32_SYSTEM */
+ return fd;
+#endif
+}
More information about the Gpa-commits
mailing list