New source files implementing the CamelCipherContext class for gnupg.
authorJeffrey Stedfast <fejj@ximian.com>
Fri, 21 Jun 2002 19:11:57 +0000 (19:11 +0000)
committerJeffrey Stedfast <fejj@src.gnome.org>
Fri, 21 Jun 2002 19:11:57 +0000 (19:11 +0000)
2002-06-21  Jeffrey Stedfast  <fejj@ximian.com>

* camel-gpg-context.[c,h]: New source files implementing the
CamelCipherContext class for gnupg.

* camel-pgp-context.c (camel_pgp_context_new): Return a
CamelCipherContext.

* camel-pgp-mime.c (camel_pgp_mime_part_decrypt): Take a
CamelCipherContext argument rather than a CamelPgpContext since we
now have a CamelGpgContext also.
(camel_pgp_mime_part_encrypt): Same.
(camel_pgp_mime_part_verify): Same.
(camel_pgp_mime_part_sign): Same.

camel/ChangeLog
camel/Makefile.am
camel/camel-gpg-context.c [new file with mode: 0644]
camel/camel-gpg-context.h [new file with mode: 0644]
camel/camel-pgp-context.c
camel/camel-pgp-context.h
camel/camel-pgp-mime.c
camel/camel-pgp-mime.h
camel/camel.h

index 0341caf..b50345b 100644 (file)
@@ -1,3 +1,18 @@
+2002-06-21  Jeffrey Stedfast  <fejj@ximian.com>
+
+       * camel-gpg-context.[c,h]: New source files implementing the
+       CamelCipherContext class for gnupg.
+
+       * camel-pgp-context.c (camel_pgp_context_new): Return a
+       CamelCipherContext.
+
+       * camel-pgp-mime.c (camel_pgp_mime_part_decrypt): Take a
+       CamelCipherContext argument rather than a CamelPgpContext since we
+       now have a CamelGpgContext also.
+       (camel_pgp_mime_part_encrypt): Same.
+       (camel_pgp_mime_part_verify): Same.
+       (camel_pgp_mime_part_sign): Same.
+
 2002-06-20  Jeffrey Stedfast  <fejj@ximian.com>
 
        * camel-digest-folder.c: Updated to support searching as well as
index 000b66c..2c5d774 100644 (file)
@@ -40,6 +40,7 @@ libcamel_la_SOURCES =                                 \
        camel-folder-summary.c                  \
        camel-folder-thread.c                   \
        camel-folder.c                          \
+       camel-gpg-context.c                     \
        camel-html-parser.c                     \
        camel-http-stream.c                     \
        camel-index.c                           \
@@ -140,6 +141,7 @@ libcamelinclude_HEADERS =                   \
        camel-folder-summary.h                  \
        camel-folder-thread.h                   \
        camel-folder.h                          \
+       camel-gpg-context.h                     \
        camel-http-stream.h                     \
        camel-index.h                           \
        camel-internet-address.h                \
diff --git a/camel/camel-gpg-context.c b/camel/camel-gpg-context.c
new file mode 100644 (file)
index 0000000..3276437
--- /dev/null
@@ -0,0 +1,1179 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ *  Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ *  Copyright 2002 Ximian, Inc. (www.ximian.com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <termios.h>
+#include <signal.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include "camel-gpg-context.h"
+#include "camel-stream-fs.h"
+#include "camel-operation.h"
+
+static void camel_gpg_context_class_init (CamelGpgContextClass *klass);
+static void camel_gpg_context_init       (CamelGpgContext *obj);
+static void camel_gpg_context_finalise   (CamelObject *obj);
+
+static int                  gpg_sign (CamelCipherContext *ctx, const char *userid, CamelCipherHash hash,
+                                     CamelStream *istream, CamelStream *ostream, CamelException *ex);
+static int                  gpg_clearsign (CamelCipherContext *context, const char *userid,
+                                          CamelCipherHash hash, CamelStream *istream,
+                                          CamelStream *ostream, CamelException *ex);
+static CamelCipherValidity *gpg_verify (CamelCipherContext *context, CamelCipherHash hash,
+                                       CamelStream *istream, CamelStream *sigstream,
+                                       CamelException *ex);
+static int                  gpg_encrypt (CamelCipherContext *context, gboolean sign, const char *userid,
+                                        GPtrArray *recipients, CamelStream *istream, CamelStream *ostream,
+                                        CamelException *ex);
+static int                  gpg_decrypt (CamelCipherContext *context, CamelStream *istream,
+                                        CamelStream *ostream, CamelException *ex);
+
+static const char *gpg_hash_to_id (CamelCipherContext *context, CamelCipherHash hash);
+static CamelCipherHash gpg_id_to_hash (CamelCipherContext *context, const char *id);
+
+
+static CamelCipherContextClass *parent_class = NULL;
+
+
+CamelType
+camel_gpg_context_get_type (void)
+{
+       static CamelType type = CAMEL_INVALID_TYPE;
+       
+       if (type == CAMEL_INVALID_TYPE) {
+               type = camel_type_register (camel_cipher_context_get_type (),
+                                           "CamelGpgContext",
+                                           sizeof (CamelGpgContext),
+                                           sizeof (CamelGpgContextClass),
+                                           (CamelObjectClassInitFunc) camel_gpg_context_class_init,
+                                           NULL,
+                                           (CamelObjectInitFunc) camel_gpg_context_init,
+                                           (CamelObjectFinalizeFunc) camel_gpg_context_finalise);
+       }
+       
+       return type;
+}
+
+static void
+camel_gpg_context_class_init (CamelGpgContextClass *klass)
+{
+       CamelCipherContextClass *cipher_class = CAMEL_CIPHER_CONTEXT_CLASS (klass);
+       
+       parent_class = CAMEL_CIPHER_CONTEXT_CLASS (camel_type_get_global_classfuncs (camel_cipher_context_get_type ()));
+       
+       cipher_class->sign = gpg_sign;
+       cipher_class->clearsign = gpg_clearsign;
+       cipher_class->verify = gpg_verify;
+       cipher_class->encrypt = gpg_encrypt;
+       cipher_class->decrypt = gpg_decrypt;
+       cipher_class->hash_to_id = gpg_hash_to_id;
+       cipher_class->id_to_hash = gpg_id_to_hash;
+}
+
+static void
+camel_gpg_context_init (CamelGpgContext *context)
+{
+       CamelCipherContext *cipher = (CamelCipherContext *) context;
+       
+       context->path = NULL;
+       context->always_trust = FALSE;
+       
+       cipher->sign_protocol = "application/pgp-signature";
+       cipher->encrypt_protocol = "application/pgp-encrypted";
+}
+
+static void
+camel_gpg_context_finalise (CamelObject *object)
+{
+       CamelGpgContext *ctx = (CamelGpgContext *) object;
+       
+       g_free (ctx->path);
+}
+
+
+static const char *
+gpg_hash_to_id (CamelCipherContext *context, CamelCipherHash hash)
+{
+       switch (hash) {
+       case CAMEL_CIPHER_HASH_MD2:
+               return "pgp-md2";
+       case CAMEL_CIPHER_HASH_MD5:
+               return "pgp-md5";
+       case CAMEL_CIPHER_HASH_SHA1:
+       case CAMEL_CIPHER_HASH_DEFAULT:
+               return "pgp-sha1";
+       case CAMEL_CIPHER_HASH_RIPEMD160:
+               return "pgp-ripemd160";
+       }
+       
+       return NULL;
+}
+
+static CamelCipherHash
+gpg_id_to_hash (CamelCipherContext *context, const char *id)
+{
+       if (!strcmp (id, "pgp-md2"))
+               return CAMEL_CIPHER_HASH_MD2;
+       else if (!strcmp (id, "pgp-md5"))
+               return CAMEL_CIPHER_HASH_MD5;
+       else if (!strcmp (id, "pgp-sha1"))
+               return CAMEL_CIPHER_HASH_SHA1;
+       else if (!strcmp (id, "pgp-ripemd160"))
+               return CAMEL_CIPHER_HASH_RIPEMD160;
+       
+       return CAMEL_CIPHER_HASH_DEFAULT;
+}
+
+
+enum _GpgCtxMode {
+       GPG_CTX_MODE_SIGN,
+       GPG_CTX_MODE_VERIFY,
+       GPG_CTX_MODE_ENCRYPT,
+       GPG_CTX_MODE_DECRYPT,
+};
+
+struct _GpgCtx {
+       enum _GpgCtxMode mode;
+       CamelSession *session;
+       GHashTable *userid_hint;
+       gboolean complete;
+       pid_t pid;
+       
+       char *path;
+       char *userid;
+       char *sigfile;
+       GPtrArray *recipients;
+       CamelCipherHash hash;
+       gboolean always_trust;
+       gboolean armor;
+       
+       int stdin;
+       int stdout;
+       int stderr;
+       int status_fd;
+       int passwd_fd;  /* only needed for sign/decrypt */
+       
+       FILE *status_fp;
+       
+       gboolean need_passwd;
+       char *passwd;
+       
+       CamelStream *istream;
+       CamelStream *ostream;
+       
+       GByteArray *diagnostics;
+};
+
+static struct _GpgCtx *
+gpg_ctx_new (CamelSession *session, const char *path)
+{
+       struct _GpgCtx *gpg;
+       
+       gpg = g_new (struct _GpgCtx, 1);
+       gpg->mode = GPG_CTX_MODE_SIGN;
+       gpg->session = session;
+       camel_object_ref (CAMEL_OBJECT (session));
+       gpg->userid_hint = g_hash_table_new (g_str_hash, g_str_equal);
+       gpg->complete = FALSE;
+       gpg->pid = (pid_t) -1;
+       
+       gpg->path = g_strdup (path);
+       gpg->userid = NULL;
+       gpg->sigfile = NULL;
+       gpg->recipients = NULL;
+       gpg->hash = CAMEL_CIPHER_HASH_DEFAULT;
+       gpg->always_trust = FALSE;
+       gpg->armor = FALSE;
+       
+       gpg->stdin = -1;
+       gpg->stdout = -1;
+       gpg->stderr = -1;
+       gpg->status_fd = -1;
+       gpg->passwd_fd = -1;
+       
+       gpg->status_fp = NULL;
+       
+       gpg->need_passwd = FALSE;
+       gpg->passwd = NULL;
+       
+       gpg->istream = NULL;
+       gpg->ostream = NULL;
+       
+       gpg->diagnostics = g_byte_array_new ();
+       
+       return gpg;
+}
+
+static void
+gpg_ctx_set_mode (struct _GpgCtx *gpg, enum _GpgCtxMode mode)
+{
+       gpg->mode = mode;
+       gpg->need_passwd = mode == GPG_CTX_MODE_SIGN || mode == GPG_CTX_MODE_DECRYPT;
+}
+
+static void
+gpg_ctx_set_hash (struct _GpgCtx *gpg, CamelCipherHash hash)
+{
+       gpg->hash = hash;
+}
+
+static void
+gpg_ctx_set_always_trust (struct _GpgCtx *gpg, gboolean trust)
+{
+       gpg->always_trust = trust;
+}
+
+static void
+gpg_ctx_set_userid (struct _GpgCtx *gpg, const char *userid)
+{
+       g_free (gpg->userid);
+       gpg->userid = g_strdup (userid);
+}
+
+static void
+gpg_ctx_add_recipient (struct _GpgCtx *gpg, const char *keyid)
+{
+       if (gpg->mode != GPG_CTX_MODE_ENCRYPT)
+               return;
+       
+       if (!gpg->recipients)
+               gpg->recipients = g_ptr_array_new ();
+       
+       g_ptr_array_add (gpg->recipients, g_strdup (keyid));
+}
+
+static void
+gpg_ctx_set_sigfile (struct _GpgCtx *gpg, const char *sigfile)
+{
+       g_free (gpg->sigfile);
+       gpg->sigfile = g_strdup (sigfile);
+}
+
+static void
+gpg_ctx_set_armor (struct _GpgCtx *gpg, gboolean armor)
+{
+       gpg->armor = armor;
+}
+
+static void
+gpg_ctx_set_istream (struct _GpgCtx *gpg, CamelStream *istream)
+{
+       camel_object_ref (CAMEL_OBJECT (istream));
+       if (gpg->istream)
+               camel_object_unref (CAMEL_OBJECT (gpg->istream));
+       gpg->istream = istream;
+}
+
+static void
+gpg_ctx_set_ostream (struct _GpgCtx *gpg, CamelStream *ostream)
+{
+       camel_object_ref (CAMEL_OBJECT (ostream));
+       if (gpg->ostream)
+               camel_object_unref (CAMEL_OBJECT (gpg->ostream));
+       gpg->istream = ostream;
+}
+
+static char *
+gpg_ctx_get_diagnostics (struct _GpgCtx *gpg)
+{
+       return g_strndup (gpg->diagnostics->data, gpg->diagnostics->len);
+}
+
+static void
+userid_hint_free (gpointer key, gpointer value, gpointer user_data)
+{
+       g_free (key);
+       g_free (value);
+}
+
+static void
+gpg_ctx_free (struct _GpgCtx *gpg)
+{
+       int i;
+       
+       if (gpg->session)
+               camel_object_unref (CAMEL_OBJECT (gpg->session));
+       
+       g_hash_table_foreach (gpg->userid_hint, userid_hint_free, NULL);
+       g_hash_table_destroy (gpg->userid_hint);
+       
+       g_free (gpg->path);
+       
+       g_free (gpg->userid);
+       
+       g_free (gpg->sigfile);
+       
+       if (gpg->recipients) {
+               for (i = 0; i < gpg->recipients->len; i++)
+                       g_free (gpg->recipients->pdata[i]);
+       
+               g_ptr_array_free (gpg->recipients, TRUE);
+       }
+       
+       if (gpg->stdin != -1)
+               close (gpg->stdin);
+       if (gpg->stdout != -1)
+               close (gpg->stdout);
+       if (gpg->stderr != -1)
+               close (gpg->stderr);
+       if (gpg->status_fd != -1 && gpg->status_fp == NULL)
+               close (gpg->status_fd);
+       if (gpg->passwd_fd != -1)
+               close (gpg->passwd_fd);
+       
+       if (gpg->status_fp != NULL)
+               fclose (gpg->status_fp);
+       
+       if (gpg->passwd)
+               g_free (gpg->passwd);
+       
+       if (gpg->istream)
+               camel_object_unref (CAMEL_OBJECT (gpg->istream));
+       
+       if (gpg->ostream)
+               camel_object_unref (CAMEL_OBJECT (gpg->ostream));
+       
+       g_byte_array_free (gpg->diagnostics, TRUE);
+       
+       g_free (gpg);
+}
+
+static const char *
+gpg_hash_str (CamelCipherHash hash)
+{
+       switch (hash) {
+       case CAMEL_CIPHER_HASH_MD2:
+               return "MD2";
+       case CAMEL_CIPHER_HASH_MD5:
+               return "MD5";
+       case CAMEL_CIPHER_HASH_SHA1:
+               return "SHA1";
+       case CAMEL_CIPHER_HASH_RIPEMD160:
+               return "RIPEMD160";
+       default:
+               return NULL;
+       }
+}
+
+static GPtrArray *
+gpg_ctx_get_argv (struct _GpgCtx *gpg, int status_fd, char **sfd, int passwd_fd, char **pfd)
+{
+       const char *hash_str;
+       GPtrArray *argv;
+       char *buf;
+       int i;
+       
+       argv = g_ptr_array_new ();
+       g_ptr_array_add (argv, "gpg");
+       
+       g_ptr_array_add (argv, "--verbose");
+       g_ptr_array_add (argv, "--no-secmem-warning");
+       g_ptr_array_add (argv, "--no-greeting");
+       g_ptr_array_add (argv, "--batch");
+       g_ptr_array_add (argv, "--yes");
+       
+       *sfd = buf = g_strdup_printf ("%d", status_fd);
+       g_ptr_array_add (argv, "--status-fd");
+       g_ptr_array_add (argv, buf);
+       
+       switch (gpg->mode) {
+       case GPG_CTX_MODE_SIGN:
+               g_ptr_array_add (argv, "--sign");
+               g_ptr_array_add (argv, "-b");
+               if (gpg->armor)
+                       g_ptr_array_add (argv, "--armor");
+               hash_str = gpg_hash_str (gpg->hash);
+               if (hash_str) {
+                       g_ptr_array_add (argv, "--digest-algo");
+                       g_ptr_array_add (argv, (char *) hash_str);
+               }
+               if (gpg->userid) {
+                       g_ptr_array_add (argv, "-u");
+                       g_ptr_array_add (argv, (char *) gpg->userid);
+               }
+               g_ptr_array_add (argv, "--output");
+               g_ptr_array_add (argv, "-");
+               break;
+       case GPG_CTX_MODE_VERIFY:
+               if (!camel_session_is_online (gpg->session))
+                       g_ptr_array_add (argv, "--no-auto-key-retrieve");
+               g_ptr_array_add (argv, "--no-tty");
+               g_ptr_array_add (argv, "--verify");
+               if (gpg->sigfile)
+                       g_ptr_array_add (argv, gpg->sigfile);
+               g_ptr_array_add (argv, "-");
+               break;
+       case GPG_CTX_MODE_ENCRYPT:
+               g_ptr_array_add (argv,  "--encrypt");
+               if (gpg->armor)
+                       g_ptr_array_add (argv, "--armor");
+               if (gpg->always_trust)
+                       g_ptr_array_add (argv, "--always-trust");
+               if (gpg->userid) {
+                       g_ptr_array_add (argv, "-u");
+                       g_ptr_array_add (argv, (char *) gpg->userid);
+               }
+               if (gpg->recipients) {
+                       for (i = 0; i < gpg->recipients->len; i++) {
+                               g_ptr_array_add (argv, "-r");
+                               g_ptr_array_add (argv, gpg->recipients->pdata[i]);
+                       }
+               }
+               g_ptr_array_add (argv, "--output");
+               g_ptr_array_add (argv, "-");
+               break;
+       case GPG_CTX_MODE_DECRYPT:
+               g_ptr_array_add (argv,  "--decrypt");
+               g_ptr_array_add (argv, "--output");
+               g_ptr_array_add (argv, "-");
+               break;
+       }
+       
+       if (gpg->need_passwd && passwd_fd != -1) {
+               *pfd = buf = g_strdup_printf ("%d", passwd_fd);
+               g_ptr_array_add (argv, "--passphrase-fd");
+               g_ptr_array_add (argv, buf);
+       }
+       
+       g_ptr_array_add (argv, NULL);
+       
+       return argv;
+}
+
+static int
+gpg_ctx_op_start (struct _GpgCtx *gpg)
+{
+       char *status_fd = NULL, *passwd_fd = NULL;
+       int i, maxfd, fds[10];
+       GPtrArray *argv;
+       
+       for (i = 0; i < 10; i++)
+               fds[i] = -1;
+       
+       maxfd = gpg->need_passwd ? 10 : 8;
+       for (i = 0; i < maxfd; i += 2) {
+               if (pipe (fds + i) == -1)
+                       goto exception;
+       }
+       
+       argv = gpg_ctx_get_argv (gpg, fds[6], &status_fd, fds[9], &passwd_fd);
+       
+       if (!(gpg->pid = fork ())) {
+               /* child process */
+               
+               if ((dup2 (fds[0], STDIN_FILENO) < 0 ) ||
+                   (dup2 (fds[3], STDOUT_FILENO) < 0 ) ||
+                   (dup2 (fds[5], STDERR_FILENO) < 0 )) {
+                       _exit (255);
+               }
+               
+               /* Dissociate from camel's controlling terminal so
+                * that gpg won't be able to read from it.
+                */
+               setsid ();
+               
+               maxfd = sysconf (_SC_OPEN_MAX);
+               if (maxfd > 0) {
+                       /* Loop over all fds. */
+                       for (i = 0; i < maxfd; i++) {
+                               if ((i != STDIN_FILENO) &&
+                                   (i != STDOUT_FILENO) &&
+                                   (i != STDERR_FILENO) &&
+                                   (i != fds[7]) &&  /* status fd */
+                                   (i != fds[8]))    /* passwd fd */
+                                       close (i);
+                       }
+               }
+               
+               /* run gpg */
+               execvp (gpg->path, (char **) argv->pdata);
+               _exit (255);
+       } else if (gpg->pid < 0) {
+               g_ptr_array_free (argv, TRUE);
+               g_free (status_fd);
+               g_free (passwd_fd);
+               goto exception;
+       }
+       
+       g_ptr_array_free (argv, TRUE);
+       g_free (status_fd);
+       g_free (passwd_fd);
+       
+       /* Parent */
+       close (fds[0]);
+       gpg->stdin = fds[1];
+       gpg->stdout = fds[2];
+       close (fds[3]);
+       gpg->stderr = fds[4];
+       close (fds[5]);
+       gpg->status_fd = fds[6];
+       close (fds[7]);
+       if (gpg->need_passwd) {
+               close (fds[8]);
+               gpg->passwd_fd = fds[9];
+               fcntl (gpg->passwd_fd, F_SETFL, O_NONBLOCK);
+       }
+       
+       fcntl (gpg->stdin, F_SETFL, O_NONBLOCK);
+       fcntl (gpg->stdout, F_SETFL, O_NONBLOCK);
+       fcntl (gpg->stderr, F_SETFL, O_NONBLOCK);
+       
+       return 0;
+       
+ exception:
+       
+       for (i = 0; i < 10; i++) {
+               if (fds[i] != -1)
+                       close (fds[i]);
+       }
+       
+       return -1;
+}
+
+static const char *
+next_token (const char *in, char **token)
+{
+       const char *start, *inptr = in;
+       
+       while (*inptr == ' ')
+               inptr++;
+       
+       if (*inptr == '\0' || *inptr == '\n') {
+               if (token)
+                       *token = NULL;
+               return inptr;
+       }
+       
+       start = inptr;
+       while (*inptr && *inptr != ' ' && *inptr != '\n')
+               inptr++;
+       
+       if (token)
+               *token = g_strndup (start, inptr - start);
+       
+       return inptr;
+}
+
+static int
+gpg_ctx_parse_status (struct _GpgCtx *gpg, const char *status, CamelException *ex)
+{
+       if (strncmp (status, "[GNUPG:] ", 9) != 0)
+               return -1;
+       
+       status += 9;
+       
+       if (!strncmp (status, "USERID_HINT ", 12)) {
+               char *hint, *user;
+               
+               status += 12;
+               status = next_token (status, &hint);
+               if (!hint) {
+                       camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
+                                            _("Failed to parse gpg userid hint."));
+                       return -1;
+               }
+               
+               if (g_hash_table_lookup (gpg->userid_hint, hint)) {
+                       /* we already have this userid hint... */
+                       g_free (hint);
+                       return 0;
+               }
+               
+               user = g_strdup (status);
+               g_strstrip (user);
+               
+               g_hash_table_insert (gpg->userid_hint, hint, user);
+       } else if (!strncmp (status, "NEED_PASSPHRASE ", 16)) {
+               char *prompt, *userid;
+               const char *name;
+               
+               status += 16;
+               
+               status = next_token (status, &userid);
+               if (!userid) {
+                       camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
+                                            _("Failed to parse gpg passphrase request."));
+                       return -1;
+               }
+               
+               name = g_hash_table_lookup (gpg->userid_hint, userid);
+               if (!name)
+                       name = userid;
+               
+               prompt = g_strdup_printf (_("You need a passphrase to unlock the key for\n"
+                                           "user: \"%s\""), name);
+               
+               gpg->passwd = camel_session_get_password (gpg->session, prompt, TRUE, NULL, userid, ex);
+               g_free (prompt);
+               g_free (userid);
+               
+               if (gpg->passwd == NULL) {
+                       if (!camel_exception_is_set (ex))
+                               camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Cancelled."));
+                       return -1;
+               }
+       } else if (!strncmp (status, "GOOD_PASSPHRASE ", 16)) {
+               g_free (gpg->passwd);
+               gpg->passwd = NULL;
+               gpg->need_passwd = FALSE;
+       } else if (!strncmp (status, "BAD_PASSPHRASE ", 15)) {
+               g_free (gpg->passwd);
+               gpg->passwd = NULL;
+               gpg->need_passwd = TRUE;
+       } else if (!strncmp (status, "UNEXPECTED ", 11)) {
+               /* this is an error */
+               return -1;
+       } else {
+               /* check to see if we are complete */
+               switch (gpg->mode) {
+               case GPG_CTX_MODE_SIGN:
+                       if (!strncmp (status, "SIG_CREATED ", 12))
+                               gpg->complete = TRUE;
+                       break;
+               case GPG_CTX_MODE_VERIFY:
+                       if (!strncmp (status, "TRUST_", 6))
+                               gpg->complete = TRUE;
+                       break;
+               case GPG_CTX_MODE_ENCRYPT:
+                       if (!strncmp (status, "END_ENCRYPTION", 14))
+                               gpg->complete = TRUE;
+                       break;
+               case GPG_CTX_MODE_DECRYPT:
+                       if (!strncmp (status, "END_DECRYPTION", 14))
+                               gpg->complete = TRUE;
+                       break;
+               }
+       }
+       
+       return 0;
+}
+
+static int
+gpg_ctx_op_step (struct _GpgCtx *gpg, CamelException *ex)
+{
+       struct timeval timeout;
+       fd_set rdset, wrset;
+       const char *mode;
+       int maxfd = 0;
+       int ret;
+       
+       do {
+               FD_ZERO (&rdset);
+               FD_SET (gpg->stdout, &rdset);
+               FD_SET (gpg->stderr, &rdset);
+               FD_SET (gpg->status_fd, &rdset);
+               
+               maxfd = MAX (gpg->stdout, gpg->stderr);
+               maxfd = MAX (maxfd, gpg->status_fd);
+               
+               FD_ZERO (&wrset);
+               FD_SET (gpg->stdin, &wrset);
+               maxfd = MAX (maxfd, gpg->stdin);
+               if (gpg->passwd_fd != -1) {
+                       FD_SET (gpg->passwd_fd, &wrset);
+                       maxfd = MAX (maxfd, gpg->passwd_fd);
+               }
+               
+               timeout.tv_sec = 10; /* timeout in seconds */
+               timeout.tv_usec = 0;
+               
+               if ((ret = select (maxfd + 1, &rdset, &wrset, NULL, &timeout)) == 0)
+                       return 0;
+               
+               if (ret < 0) {
+                       if (errno == EINTR)
+                               continue;
+                       
+                       return -1;
+               }
+               
+               if (FD_ISSET (gpg->status_fd, &rdset)) {
+                       /* read the status message and decide what to do... */
+                       char buffer[4096];
+                       FILE *fp;
+                       
+                       if (gpg->status_fp == NULL) {
+                               gpg->status_fp = fdopen (gpg->status_fd, "r");
+                               if (gpg->status_fp == NULL)
+                                       goto exception;
+                       }
+                       
+                       fp = gpg->status_fp;
+                       
+                       fgets (buffer, sizeof (buffer), fp);
+                       return gpg_ctx_parse_status (gpg, buffer, ex);
+               }
+               
+               if (FD_ISSET (gpg->stdout, &rdset) && gpg->ostream) {
+                       char buffer[4096];
+                       ssize_t nread;
+                       
+                       nread = read (gpg->stdout, buffer, sizeof (buffer));
+                       if (nread > 0)
+                               ret = camel_stream_write (gpg->ostream, buffer, (size_t) nread);
+                       
+                       if (ret == -1)
+                               goto exception;
+                       
+                       return 0;
+               }
+               
+               if (FD_ISSET (gpg->stderr, &rdset)) {
+                       char buffer[4096];
+                       ssize_t nread;
+                       
+                       nread = read (gpg->stdout, buffer, sizeof (buffer));
+                       if (nread > 0)
+                               g_byte_array_append (gpg->diagnostics, buffer, nread);
+                       
+                       return 0;
+               }
+               
+               if (gpg->passwd_fd != -1 && gpg->need_passwd && gpg->passwd && FD_ISSET (gpg->passwd_fd, &wrset)) {
+                       ssize_t w, nwritten = 0;
+                       size_t n;
+                       
+                       /* send the passphrase to gpg */
+                       n = strlen (gpg->passwd);
+                       do {
+                               do {
+                                       w = write (gpg->passwd_fd, gpg->passwd + nwritten, n - nwritten);
+                               } while (w == -1 && (errno == EINTR || errno == EAGAIN));
+                               
+                               if (w > 0)
+                                       nwritten += w;
+                       } while (nwritten < n && w != -1);
+                       
+                       if (ret == -1)
+                               goto exception;
+                       
+                       return 0;
+               }
+               
+               if (FD_ISSET (gpg->stdin, &wrset) && gpg->istream && !camel_stream_eos (gpg->istream)) {
+                       CamelStream *stream;
+                       
+                       /* write our stream to gpg's stdin */
+                       stream = camel_stream_fs_new_with_fd (gpg->stdin);
+                       ret = camel_stream_write_to_stream (gpg->istream, stream);
+                       if (ret != -1)
+                               ret = camel_stream_flush (stream);
+                       CAMEL_STREAM_FS (stream)->fd = -1;
+                       camel_object_unref (CAMEL_OBJECT (stream));
+                       
+                       if (ret == -1)
+                               goto exception;
+                       
+                       return 0;
+               }
+       } while (1);
+       
+       return 0;
+       
+ exception:
+       
+       switch (gpg->mode) {
+       case GPG_CTX_MODE_SIGN:
+               mode = "sign";
+               break;
+       case GPG_CTX_MODE_VERIFY:
+               mode = "verify";
+               break;
+       case GPG_CTX_MODE_ENCRYPT:
+               mode = "encrypt";
+               break;
+       case GPG_CTX_MODE_DECRYPT:
+               mode = "decrypt";
+               break;
+       default:
+               g_assert_not_reached ();
+               mode = NULL;
+               break;
+       }
+       
+       camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
+                             _("Failed to GPG %s message: %s\n"),
+                             mode, g_strerror (errno));
+       
+       return -1;
+}
+
+static gboolean
+gpg_ctx_op_complete (struct _GpgCtx *gpg)
+{
+       return gpg->complete;
+}
+
+static void
+gpg_ctx_op_cancel (struct _GpgCtx *gpg)
+{
+       pid_t retval;
+       int status;
+       
+       kill (gpg->pid, SIGTERM);
+       sleep (1);
+       retval = waitpid (gpg->pid, &status, WNOHANG);
+       if (retval == 0) {
+               /* no more mr nice guy... */
+               kill (gpg->pid, SIGKILL);
+               sleep (1);
+               waitpid (gpg->pid, &status, WNOHANG);
+       }
+}
+
+static int
+gpg_ctx_op_wait (struct _GpgCtx *gpg)
+{
+       sigset_t mask, omask;
+       pid_t retval;
+       int status;
+       
+       sigemptyset (&mask);
+       sigaddset (&mask, SIGALRM);
+       sigprocmask (SIG_BLOCK, &mask, &omask);
+       alarm (1);
+       retval = waitpid (gpg->pid, &status, 0);
+       alarm (0);
+       sigprocmask (SIG_SETMASK, &omask, NULL);
+       
+       if (retval == (pid_t) -1 && errno == EINTR) {
+               /* The child is hanging: send a friendly reminder. */
+               kill (gpg->pid, SIGTERM);
+               sleep (1);
+               retval = waitpid (gpg->pid, &status, WNOHANG);
+               if (retval == (pid_t) 0) {
+                       /* Still hanging; use brute force. */
+                       kill (gpg->pid, SIGKILL);
+                       sleep (1);
+                       retval = waitpid (gpg->pid, &status, WNOHANG);
+               }
+       }
+       
+       if (retval != (pid_t) -1 && WIFEXITED (status))
+               return WEXITSTATUS (status);
+       else
+               return -1;
+}
+
+
+
+static int
+gpg_sign (CamelCipherContext *context, const char *userid, CamelCipherHash hash,
+         CamelStream *istream, CamelStream *ostream, CamelException *ex)
+{
+       CamelGpgContext *ctx = (CamelGpgContext *) context;
+       struct _GpgCtx *gpg;
+       
+       gpg = gpg_ctx_new (context->session, ctx->path);
+       gpg_ctx_set_mode (gpg, GPG_CTX_MODE_SIGN);
+       gpg_ctx_set_hash (gpg, hash);
+       gpg_ctx_set_armor (gpg, TRUE);
+       gpg_ctx_set_userid (gpg, userid);
+       gpg_ctx_set_istream (gpg, istream);
+       gpg_ctx_set_ostream (gpg, ostream);
+       
+       if (gpg_ctx_op_start (gpg) == -1) {
+               camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
+                                    _("Failed to execute gpg."));
+               gpg_ctx_free (gpg);
+               
+               return -1;
+       }
+       
+       while (!gpg_ctx_op_complete (gpg)) {
+               if (camel_operation_cancel_check (NULL)) {
+                       camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL,
+                                            _("Cancelled."));
+                       gpg_ctx_op_cancel (gpg);
+                       gpg_ctx_free (gpg);
+                       
+                       return -1;
+               }
+               
+               if (gpg_ctx_op_step (gpg, ex) == -1) {
+                       gpg_ctx_op_cancel (gpg);
+                       gpg_ctx_free (gpg);
+                       
+                       return -1;
+               }
+       }
+       
+       if (gpg_ctx_op_wait (gpg) != 0) {
+               char *diagnostics;
+               
+               diagnostics = gpg_ctx_get_diagnostics (gpg);
+               camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, diagnostics);
+               g_free (diagnostics);
+       }
+       gpg_ctx_free (gpg);
+       
+       return 0;
+}
+
+
+static int
+gpg_clearsign (CamelCipherContext *context, const char *userid,
+              CamelCipherHash hash, CamelStream *istream,
+              CamelStream *ostream, CamelException *ex)
+{
+       return -1;
+}
+
+
+static char *
+swrite (CamelStream *istream)
+{
+       CamelStream *ostream;
+       char *template;
+       int fd, ret;
+       
+       template = g_strdup ("/tmp/evolution-pgp.XXXXXX");
+       fd = mkstemp (template);
+       if (fd == -1) {
+               g_free (template);
+               return NULL;
+       }
+       
+       ostream = camel_stream_fs_new_with_fd (fd);
+       ret = camel_stream_write_to_stream (istream, ostream);
+       if (ret != -1) {
+               ret = camel_stream_flush (ostream);
+               if (ret != -1)
+                       ret = camel_stream_close (ostream);
+       }
+       camel_object_unref (CAMEL_OBJECT (ostream));
+       
+       if (ret == -1) {
+               unlink (template);
+               g_free (template);
+               return NULL;
+       }
+       
+       return template;
+}
+
+static CamelCipherValidity *
+gpg_verify (CamelCipherContext *context, CamelCipherHash hash,
+           CamelStream *istream, CamelStream *sigstream,
+           CamelException *ex)
+{
+       CamelGpgContext *ctx = (CamelGpgContext *) context;
+       CamelCipherValidity *validity;
+       char *diagnostics = NULL;
+       struct _GpgCtx *gpg;
+       char *sigfile = NULL;
+       gboolean valid;
+       
+       if (sigstream != NULL) {
+               /* We are going to verify a detached signature so save
+                  the signature to a temp file. */
+               sigfile = swrite (sigstream);
+               if (sigfile == NULL) {
+                       camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
+                                             _("Cannot verify this message: couldn't create temp file: %s"),
+                                             g_strerror (errno));
+                       return NULL;
+               }
+       }
+       
+       gpg = gpg_ctx_new (context->session, ctx->path);
+       gpg_ctx_set_mode (gpg, GPG_CTX_MODE_VERIFY);
+       gpg_ctx_set_hash (gpg, hash);
+       gpg_ctx_set_sigfile (gpg, sigfile);
+       gpg_ctx_set_istream (gpg, istream);
+       
+       if (gpg_ctx_op_start (gpg) == -1) {
+               camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
+                                    _("Failed to execute gpg."));
+               gpg_ctx_free (gpg);
+               goto exception;
+       }
+       
+       while (!gpg_ctx_op_complete (gpg)) {
+               if (camel_operation_cancel_check (NULL)) {
+                       camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL,
+                                            _("Cancelled."));
+                       gpg_ctx_op_cancel (gpg);
+                       goto exception;
+               }
+               
+               if (gpg_ctx_op_step (gpg, ex) == -1) {
+                       gpg_ctx_op_cancel (gpg);
+                       goto exception;
+               }
+       }
+       
+       diagnostics = gpg_ctx_get_diagnostics (gpg);
+       
+       valid = gpg_ctx_op_wait (gpg) == 0;
+       gpg_ctx_free (gpg);
+       
+       validity = camel_cipher_validity_new ();
+       camel_cipher_validity_set_valid (validity, valid);
+       camel_cipher_validity_set_description (validity, diagnostics);
+       g_free (diagnostics);
+       
+       if (sigfile) {
+               unlink (sigfile);
+               g_free (sigfile);
+       }
+       
+       return validity;
+       
+ exception:
+       
+       gpg_ctx_free (gpg);
+               
+       if (sigfile) {
+               unlink (sigfile);
+               g_free (sigfile);
+       }
+       
+       return NULL;
+}
+
+
+static int
+gpg_encrypt (CamelCipherContext *context, gboolean sign, const char *userid,
+            GPtrArray *recipients, CamelStream *istream, CamelStream *ostream,
+            CamelException *ex)
+{
+       CamelGpgContext *ctx = (CamelGpgContext *) context;
+       struct _GpgCtx *gpg;
+       int i;
+       
+       gpg = gpg_ctx_new (context->session, ctx->path);
+       gpg_ctx_set_mode (gpg, GPG_CTX_MODE_ENCRYPT);
+       gpg_ctx_set_armor (gpg, TRUE);
+       gpg_ctx_set_userid (gpg, userid);
+       gpg_ctx_set_istream (gpg, istream);
+       gpg_ctx_set_ostream (gpg, ostream);
+       gpg_ctx_set_always_trust (gpg, TRUE);
+       
+       for (i = 0; i < recipients->len; i++) {
+               gpg_ctx_add_recipient (gpg, recipients->pdata[i]);
+       }
+       
+       if (gpg_ctx_op_start (gpg) == -1) {
+               camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
+                                    _("Failed to execute gpg."));
+               gpg_ctx_free (gpg);
+               
+               return -1;
+       }
+       
+       while (!gpg_ctx_op_complete (gpg)) {
+               if (camel_operation_cancel_check (NULL)) {
+                       camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL,
+                                            _("Cancelled."));
+                       gpg_ctx_op_cancel (gpg);
+                       gpg_ctx_free (gpg);
+                       
+                       return -1;
+               }
+               
+               if (gpg_ctx_op_step (gpg, ex) == -1) {
+                       gpg_ctx_op_cancel (gpg);
+                       gpg_ctx_free (gpg);
+                       
+                       return -1;
+               }
+       }
+       
+       if (gpg_ctx_op_wait (gpg) != 0) {
+               char *diagnostics;
+               
+               diagnostics = gpg_ctx_get_diagnostics (gpg);
+               camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, diagnostics);
+               g_free (diagnostics);
+       }
+       
+       gpg_ctx_free (gpg);
+       
+       return 0;
+}
+
+
+static int
+gpg_decrypt (CamelCipherContext *context, CamelStream *istream,
+            CamelStream *ostream, CamelException *ex)
+{
+       CamelGpgContext *ctx = (CamelGpgContext *) context;
+       struct _GpgCtx *gpg;
+       
+       gpg = gpg_ctx_new (context->session, ctx->path);
+       gpg_ctx_set_mode (gpg, GPG_CTX_MODE_DECRYPT);
+       gpg_ctx_set_istream (gpg, istream);
+       gpg_ctx_set_ostream (gpg, ostream);
+       
+       if (gpg_ctx_op_start (gpg) == -1) {
+               camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
+                                    _("Failed to execute gpg."));
+               gpg_ctx_free (gpg);
+               
+               return -1;
+       }
+       
+       while (!gpg_ctx_op_complete (gpg)) {
+               if (camel_operation_cancel_check (NULL)) {
+                       camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL,
+                                            _("Cancelled."));
+                       gpg_ctx_op_cancel (gpg);
+                       gpg_ctx_free (gpg);
+                       
+                       return -1;
+               }
+               
+               if (gpg_ctx_op_step (gpg, ex) == -1) {
+                       gpg_ctx_op_cancel (gpg);
+                       gpg_ctx_free (gpg);
+                       
+                       return -1;
+               }
+       }
+       
+       if (gpg_ctx_op_wait (gpg) != 0) {
+               char *diagnostics;
+               
+               diagnostics = gpg_ctx_get_diagnostics (gpg);
+               camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, diagnostics);
+               g_free (diagnostics);
+       }
+       
+       gpg_ctx_free (gpg);
+       
+       return 0;
+}
diff --git a/camel/camel-gpg-context.h b/camel/camel-gpg-context.h
new file mode 100644 (file)
index 0000000..263e76f
--- /dev/null
@@ -0,0 +1,68 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ *  Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ *  Copyright 2002 Ximian, Inc. (www.ximian.com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef __CAMEL_GPG_CONTEXT_H__
+#define __CAMEL_GPG_CONTEXT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus */
+
+#include <camel/camel-cipher-context.h>
+
+#define CAMEL_GPG_CONTEXT_TYPE     (camel_gpg_context_get_type ())
+#define CAMEL_GPG_CONTEXT(obj)     (CAMEL_CHECK_CAST((obj), CAMEL_GPG_CONTEXT_TYPE, CamelGpgContext))
+#define CAMEL_GPG_CONTEXT_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_GPG_CONTEXT_TYPE, CamelGpgContextClass))
+#define CAMEL_IS_GPG_CONTEXT(o)    (CAMEL_CHECK_TYPE((o), CAMEL_GPG_CONTEXT_TYPE))
+
+typedef struct _CamelGpgContext CamelGpgContext;
+typedef struct _CamelGpgContextClass CamelGpgContextClass;
+
+struct _CamelGpgContext {
+       CamelCipherContext parent_object;
+       
+       char *path;
+       
+       gboolean always_trust;
+};
+
+struct _CamelGpgContextClass {
+       CamelCipherContextClass parent_class;
+       
+};
+
+
+CamelType camel_gpg_context_get_type (void);
+
+CamelCipherContext *camel_gpg_context_new (CamelSession *session, const char *path);
+
+void camel_gpg_context_set_always_trust (CamelGpgContext *ctx, gboolean trust);
+gboolean camel_gpg_context_get_always_trust (CamelGpgContext *ctx);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __CAMEL_GPG_CONTEXT_H__ */
+
index 0b5916b..eb315c3 100644 (file)
@@ -155,7 +155,7 @@ camel_pgp_context_get_type (void)
  *
  * Return value: the new CamelPgpContext
  **/
-CamelPgpContext *
+CamelCipherContext *
 camel_pgp_context_new (CamelSession *session, CamelPgpType type, const char *path)
 {
        CamelPgpContext *context;
@@ -172,7 +172,7 @@ camel_pgp_context_new (CamelSession *session, CamelPgpType type, const char *pat
        context->priv->type = type;
        context->priv->path = g_strdup (path);
        
-       return context;
+       return (CamelCipherContext *) context;
 }
 
 
index 0eaa3ec..36d91f7 100644 (file)
@@ -60,19 +60,8 @@ typedef struct _CamelPgpContextClass {
 
 CamelType         camel_pgp_context_get_type (void);
 
-CamelPgpContext  *camel_pgp_context_new (CamelSession *session, CamelPgpType type,
-                                        const char *path);
-
-/* PGP routines */
-#define camel_pgp_sign(c, u, h, i, o, e) camel_cipher_sign (CAMEL_CIPHER_CONTEXT (c), u, h, i, o, e)
-
-#define camel_pgp_clearsign(c, u, h, i, o, e) camel_cipher_clearsign (CAMEL_CIPHER_CONTEXT (c), u, h, i, o, e)
-
-#define camel_pgp_verify(c, i, s, e) camel_cipher_verify (CAMEL_CIPHER_CONTEXT (c), CAMEL_CIPHER_HASH_DEFAULT, i, s, e)
-
-#define camel_pgp_encrypt(c, s, u, r, i, o, e) camel_cipher_encrypt (CAMEL_CIPHER_CONTEXT (c), s, u, r, i, o, e)
-
-#define camel_pgp_decrypt(c, i, o, e) camel_cipher_decrypt (CAMEL_CIPHER_CONTEXT (c), i, o, e)
+CamelCipherContext  *camel_pgp_context_new (CamelSession *session, CamelPgpType type,
+                                           const char *path);
 
 #ifdef __cplusplus
 }
index b0e3ab3..c297194 100644 (file)
@@ -240,7 +240,7 @@ pgp_mime_part_sign_prepare_part (CamelMimePart *mime_part, GSList **encodings)
 
 /**
  * camel_pgp_mime_part_sign:
- * @context: PGP Context
+ * @cipher: PGP Cipher Context
  * @mime_part: a MIME part that will be replaced by a pgp signed part
  * @userid: userid to sign with
  * @hash: one of CAMEL_PGP_HASH_TYPE_MD5 or CAMEL_PGP_HASH_TYPE_SHA1
@@ -251,7 +251,7 @@ pgp_mime_part_sign_prepare_part (CamelMimePart *mime_part, GSList **encodings)
  * @ex will be set and #part will remain untouched.
  **/
 void
-camel_pgp_mime_part_sign (CamelPgpContext *context, CamelMimePart **mime_part, const char *userid,
+camel_pgp_mime_part_sign (CamelCipherContext *cipher, CamelMimePart **mime_part, const char *userid,
                          CamelCipherHash hash, CamelException *ex)
 {
        CamelMimePart *part, *signed_part;
@@ -327,7 +327,7 @@ camel_pgp_mime_part_sign (CamelPgpContext *context, CamelMimePart **mime_part, c
        }
        
        /* get the signature */
-       if (camel_pgp_sign (context, userid, hash, stream, sigstream, ex) == -1) {
+       if (camel_cipher_sign (cipher, userid, hash, stream, sigstream, ex) == -1) {
                GSList *list;
                
                camel_object_unref (CAMEL_OBJECT (stream));
@@ -381,14 +381,14 @@ camel_pgp_mime_part_sign (CamelPgpContext *context, CamelMimePart **mime_part, c
 
 /**
  * camel_pgp_mime_part_verify:
- * @context: PGP Context
+ * @cipher: PGP Cipher Context
  * @mime_part: a multipart/signed MIME Part
  * @ex: exception
  *
  * Returns a CamelCipherValidity on success or NULL on fail.
  **/
 CamelCipherValidity *
-camel_pgp_mime_part_verify (CamelPgpContext *context, CamelMimePart *mime_part, CamelException *ex)
+camel_pgp_mime_part_verify (CamelCipherContext *cipher, CamelMimePart *mime_part, CamelException *ex)
 {
        CamelDataWrapper *wrapper;
        CamelMultipart *multipart;
@@ -437,7 +437,7 @@ camel_pgp_mime_part_verify (CamelPgpContext *context, CamelMimePart *mime_part,
        camel_stream_reset (sigstream);
        
        /* verify */
-       valid = camel_pgp_verify (context, stream, sigstream, ex);
+       valid = camel_cipher_verify (cipher, CAMEL_CIPHER_HASH_DEFAULT, stream, sigstream, ex);
        
        d(printf ("attempted to verify data:\n----- BEGIN SIGNED PART -----\n%.*s----- END SIGNED PART -----\n",
                  CAMEL_STREAM_MEM (stream)->buffer->len, CAMEL_STREAM_MEM (stream)->buffer->data));
@@ -451,7 +451,7 @@ camel_pgp_mime_part_verify (CamelPgpContext *context, CamelMimePart *mime_part,
 
 /**
  * camel_pgp_mime_part_encrypt:
- * @context: PGP Context
+ * @cipher: PGP Cipher Context
  * @mime_part: a MIME part that will be replaced by a pgp encrypted part
  * @recipients: list of recipient PGP Key IDs
  * @ex: exception which will be set if there are any errors.
@@ -461,7 +461,7 @@ camel_pgp_mime_part_verify (CamelPgpContext *context, CamelMimePart *mime_part,
  * #ex will be set and #part will remain untouched.
  **/
 void
-camel_pgp_mime_part_encrypt (CamelPgpContext *context, CamelMimePart **mime_part,
+camel_pgp_mime_part_encrypt (CamelCipherContext *cipher, CamelMimePart **mime_part,
                             GPtrArray *recipients, CamelException *ex)
 {
        CamelMultipart *multipart;
@@ -490,7 +490,7 @@ camel_pgp_mime_part_encrypt (CamelPgpContext *context, CamelMimePart **mime_part
        
        /* pgp encrypt */
        ciphertext = camel_stream_mem_new ();
-       if (camel_pgp_encrypt (context, FALSE, NULL, recipients, stream, ciphertext, ex) == -1) {
+       if (camel_cipher_encrypt (cipher, FALSE, NULL, recipients, stream, ciphertext, ex) == -1) {
                camel_object_unref (CAMEL_OBJECT (stream));
                camel_object_unref (CAMEL_OBJECT (ciphertext));
                return;
@@ -540,14 +540,14 @@ camel_pgp_mime_part_encrypt (CamelPgpContext *context, CamelMimePart **mime_part
 
 /**
  * camel_pgp_mime_part_decrypt:
- * @context: PGP Context
+ * @cipher: PGP Cipher Context
  * @mime_part: a multipart/encrypted MIME Part
  * @ex: exception
  *
  * Returns the decrypted MIME Part on success or NULL on fail.
  **/
 CamelMimePart *
-camel_pgp_mime_part_decrypt (CamelPgpContext *context, CamelMimePart *mime_part, CamelException *ex)
+camel_pgp_mime_part_decrypt (CamelCipherContext *cipher, CamelMimePart *mime_part, CamelException *ex)
 {
        CamelDataWrapper *wrapper;
        CamelMultipart *multipart;
@@ -580,7 +580,7 @@ camel_pgp_mime_part_decrypt (CamelPgpContext *context, CamelMimePart *mime_part,
        
        /* get the cleartext */
        stream = camel_stream_mem_new ();
-       if (camel_pgp_decrypt (context, ciphertext, stream, ex) == -1) {
+       if (camel_cipher_decrypt (cipher, ciphertext, stream, ex) == -1) {
                camel_object_unref (CAMEL_OBJECT (ciphertext));
                camel_object_unref (CAMEL_OBJECT (stream));
                return NULL;
index 7f79289..e5dec18 100644 (file)
@@ -38,22 +38,22 @@ extern "C" {
 gboolean camel_pgp_mime_is_rfc2015_signed (CamelMimePart *part);
 gboolean camel_pgp_mime_is_rfc2015_encrypted (CamelMimePart *part);
 
-void camel_pgp_mime_part_sign (CamelPgpContext *context,
+void camel_pgp_mime_part_sign (CamelCipherContext *cipher,
                               CamelMimePart **mime_part,
                               const char *userid,
                               CamelCipherHash hash,
                               CamelException *ex);
 
-CamelCipherValidity *camel_pgp_mime_part_verify (CamelPgpContext *context,
+CamelCipherValidity *camel_pgp_mime_part_verify (CamelCipherContext *cipher,
                                                 CamelMimePart *mime_part,
                                                 CamelException *ex);
 
-void camel_pgp_mime_part_encrypt (CamelPgpContext *context,
+void camel_pgp_mime_part_encrypt (CamelCipherContext *cipher,
                                  CamelMimePart **mime_part,
                                  GPtrArray *recipients,
                                  CamelException *ex);
 
-CamelMimePart *camel_pgp_mime_part_decrypt (CamelPgpContext *context,
+CamelMimePart *camel_pgp_mime_part_decrypt (CamelCipherContext *cipher,
                                            CamelMimePart *mime_part,
                                            CamelException *ex);
 
index 722b619..1deebd1 100644 (file)
@@ -30,7 +30,7 @@
 #ifdef __cplusplus
 extern "C" {
 #pragma }
-#endif /* __cplusplus }*/
+#endif /* __cplusplus */
 
 #include <camel/camel-cipher-context.h>
 #include <camel/camel-cms-context.h>
@@ -59,6 +59,7 @@ extern "C" {
 #include <camel/camel-movemail.h>
 #include <camel/camel-multipart.h>
 #include <camel/camel-pgp-context.h>
+#include <camel/camel-gpg-context.h>
 #include <camel/camel-pgp-mime.h>
 #include <camel/camel-provider.h>
 #include <camel/camel-seekable-stream.h>