Return -1 on error. (gpg_decrypt): Same. (gpg_sign): Again here.
authorJeffrey Stedfast <fejj@ximian.com>
Sat, 22 Jun 2002 23:07:55 +0000 (23:07 +0000)
committerJeffrey Stedfast <fejj@src.gnome.org>
Sat, 22 Jun 2002 23:07:55 +0000 (23:07 +0000)
2002-06-22  Jeffrey Stedfast  <fejj@ximian.com>

* camel-gpg-context.c (gpg_encrypt): Return -1 on error.
(gpg_decrypt): Same.
(gpg_sign): Again here.
(gpg_ctx_op_step): Only attenmpt to read from the status-fd if we
are not already 'complete'.

* camel-pgp-mime.c (camel_pgp_mime_part_encrypt): Flush the
filtered stream.

camel/ChangeLog
camel/camel-gpg-context.c
camel/camel-pgp-mime.c

index b50345b..6560ae5 100644 (file)
@@ -1,3 +1,14 @@
+2002-06-22  Jeffrey Stedfast  <fejj@ximian.com>
+
+       * camel-gpg-context.c (gpg_encrypt): Return -1 on error.
+       (gpg_decrypt): Same.
+       (gpg_sign): Again here.
+       (gpg_ctx_op_step): Only attenmpt to read from the status-fd if we
+       are not already 'complete'.
+
+       * camel-pgp-mime.c (camel_pgp_mime_part_encrypt): Flush the
+       filtered stream.
+
 2002-06-21  Jeffrey Stedfast  <fejj@ximian.com>
 
        * camel-gpg-context.[c,h]: New source files implementing the
index 033d470..e696cd0 100644 (file)
@@ -197,7 +197,6 @@ struct _GpgCtx {
        enum _GpgCtxMode mode;
        CamelSession *session;
        GHashTable *userid_hint;
-       gboolean complete;
        pid_t pid;
        
        char *path;
@@ -205,8 +204,6 @@ struct _GpgCtx {
        char *sigfile;
        GPtrArray *recipients;
        CamelCipherHash hash;
-       gboolean always_trust;
-       gboolean armor;
        
        int stdin;
        int stdout;
@@ -219,13 +216,21 @@ struct _GpgCtx {
        unsigned char *statusptr;
        unsigned int statusleft;
        
-       gboolean need_passwd;
        char *passwd;
        
        CamelStream *istream;
        CamelStream *ostream;
        
        GByteArray *diagnostics;
+       
+       unsigned int complete:1;
+       unsigned int reading:1;
+       unsigned int always_trust:1;
+       unsigned int armor:1;
+       unsigned int need_passwd:1;
+       unsigned int send_passwd:1;
+       
+       unsigned int padding:26;
 };
 
 static struct _GpgCtx *
@@ -239,6 +244,7 @@ gpg_ctx_new (CamelSession *session, const char *path)
        camel_object_ref (CAMEL_OBJECT (session));
        gpg->userid_hint = g_hash_table_new (g_str_hash, g_str_equal);
        gpg->complete = FALSE;
+       gpg->reading = FALSE;
        gpg->pid = (pid_t) -1;
        
        gpg->path = g_strdup (path);
@@ -260,6 +266,7 @@ gpg_ctx_new (CamelSession *session, const char *path)
        gpg->statusleft = 128;
        
        gpg->need_passwd = FALSE;
+       gpg->send_passwd = FALSE;
        gpg->passwd = NULL;
        
        gpg->istream = NULL;
@@ -274,7 +281,7 @@ 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;
+       gpg->need_passwd = gpg->mode == GPG_CTX_MODE_SIGN || GPG_CTX_MODE_DECRYPT;
 }
 
 static void
@@ -336,7 +343,7 @@ 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;
+       gpg->ostream = ostream;
 }
 
 static char *
@@ -440,7 +447,7 @@ gpg_ctx_get_argv (struct _GpgCtx *gpg, int status_fd, char **sfd, int passwd_fd,
        *sfd = buf = g_strdup_printf ("--status-fd=%d", status_fd);
        g_ptr_array_add (argv, buf);
        
-       if (gpg->need_passwd && passwd_fd != -1) {
+       if (passwd_fd != -1) {
                *pfd = buf = g_strdup_printf ("--passphrase-fd=%d", passwd_fd);
                g_ptr_array_add (argv, buf);
        }
@@ -644,7 +651,7 @@ gpg_ctx_parse_status (struct _GpgCtx *gpg, CamelException *ex)
        *inptr++ = '\0';
        status = gpg->statusbuf;
        
-       printf ("status: %s", status);
+       printf ("status: %s\n", status);
        fflush (stdout);
        
        if (strncmp (status, "[GNUPG:] ", 9) != 0)
@@ -702,14 +709,14 @@ gpg_ctx_parse_status (struct _GpgCtx *gpg, CamelException *ex)
                                camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Cancelled."));
                        return -1;
                }
+               
+               gpg->send_passwd = TRUE;
        } 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;
@@ -735,7 +742,8 @@ gpg_ctx_parse_status (struct _GpgCtx *gpg, CamelException *ex)
                        break;
                }
                
-               printf ("okay, that's all folks...\n");
+               if (gpg->complete)
+                       printf ("okay, that's all folks...\n");
        }
        
  recycle:
@@ -775,7 +783,6 @@ gpg_ctx_parse_status (struct _GpgCtx *gpg, CamelException *ex)
        gpg->statusleft -= len;                                           \
 } G_STMT_END
 
-
 static int
 gpg_ctx_op_step (struct _GpgCtx *gpg, CamelException *ex)
 {
@@ -829,7 +836,7 @@ gpg_ctx_op_step (struct _GpgCtx *gpg, CamelException *ex)
           can to all of them. If one fails along the way, return
           -1. */
        
-       if (FD_ISSET (gpg->status_fd, &rdset)) {
+       if (FD_ISSET (gpg->status_fd, &rdset) && !gpg->complete) {
                /* read the status message and decide what to do... */
                char buffer[4096];
                ssize_t nread;
@@ -859,8 +866,16 @@ gpg_ctx_op_step (struct _GpgCtx *gpg, CamelException *ex)
                if (nread == -1)
                        goto exception;
                
-               if (camel_stream_write (gpg->ostream, buffer, (size_t) nread) == -1)
-                       goto exception;
+               if (nread > 0) {
+                       if (camel_stream_write (gpg->ostream, buffer, (size_t) nread) == -1)
+                               goto exception;
+                       
+                       /* make sure we don't exit before reading all the data... */
+                       gpg->reading = TRUE;
+               } else {
+                       /* we've safely read all the output */
+                       gpg->reading = FALSE;
+               }
        }
        
        if (FD_ISSET (gpg->stderr, &rdset)) {
@@ -876,47 +891,67 @@ gpg_ctx_op_step (struct _GpgCtx *gpg, CamelException *ex)
                g_byte_array_append (gpg->diagnostics, buffer, nread);
        }
        
-       if (wrsetp && gpg->passwd_fd != -1 && FD_ISSET (gpg->passwd_fd, &wrset) && gpg->need_passwd) {
-               ssize_t w, nwritten = 0;
-               size_t n;
-               
-               printf ("sending gpg our passphrase...\n");
-               
-               if (!gpg->passwd) {
-                       const char *name, *userid;
-                       char *prompt;
+       if (wrsetp && gpg->passwd_fd != -1 && FD_ISSET (gpg->passwd_fd, &wrset)) {
+               if (gpg->send_passwd) {
+                       ssize_t w, nwritten = 0;
+                       size_t n;
                        
-                       userid = gpg->userid;
-                       if (userid) {
-                               name = g_hash_table_lookup (gpg->userid_hint, gpg->userid);
-                               if (name == NULL)
-                                       name = gpg->userid;
-                       } else {
-                               name = "GnuPG";
-                               userid = "passphrase";
-                       }
+                       printf ("sending gpg our passphrase...\n");
                        
-                       prompt = g_strdup_printf (_("You need a passphrase to unlock the key for\n"
-                                                   "user: \"%s\""), name);
+                       if (!gpg->passwd) {
+                               const char *name, *userid;
+                               char *prompt;
+                               
+                               userid = gpg->userid;
+                               if (userid) {
+                                       name = g_hash_table_lookup (gpg->userid_hint, gpg->userid);
+                                       if (name == NULL)
+                                               name = gpg->userid;
+                                       
+                                       prompt = g_strdup_printf (_("You need a passphrase to unlock the key for\n"
+                                                                   "user: \"%s\""), name);
+                               } else {
+                                       name = "GnuPG";
+                                       userid = "passphrase";
+                                       
+                                       prompt = g_strdup (_("You need a passphrase to unlock your GnuPG key"));
+                               }
+                               
+                               gpg->passwd = camel_session_get_password (gpg->session, prompt, TRUE, NULL,
+                                                                         userid, ex);
+                               g_free (prompt);
+                               
+                               if (gpg->passwd == NULL) {
+                                       camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Cancelled"));
+                                       return -1;
+                               }
+                       }
                        
-                       gpg->passwd = camel_session_get_password (gpg->session, prompt, TRUE, NULL,
-                                                                 userid, ex);
-                       g_free (prompt);
-               }
-               
-               /* send the passphrase to gpg */
-               n = strlen (gpg->passwd);
-               do {
+                       /* send the passphrase to gpg */
+                       n = strlen (gpg->passwd);
                        do {
-                               w = write (gpg->passwd_fd, gpg->passwd + nwritten, n - nwritten);
-                       } while (w == -1 && (errno == EINTR || errno == EAGAIN));
+                               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 (w > 0)
-                               nwritten += w;
-               } while (nwritten < n && w != -1);
-               
-               if (w == -1)
-                       goto exception;
+                       if (w == -1)
+                               goto exception;
+                       
+                       g_free (gpg->passwd);
+                       gpg->passwd = NULL;
+                       gpg->send_passwd = FALSE;
+                       
+                       close (gpg->passwd_fd);
+                       gpg->passwd_fd = -1;
+               } else {
+                       printf ("gpg seems to be expecting a passphrase from us...\n");
+                       printf ("yet we have not received a NEED_PASSPHRASE status message yet?\n");
+                       fflush (stdout);
+               }
        }
        
        if (wrsetp && gpg->stdin != -1 && FD_ISSET (gpg->stdin, &wrset)) {
@@ -948,6 +983,7 @@ gpg_ctx_op_step (struct _GpgCtx *gpg, CamelException *ex)
                }
                
                if (camel_stream_eos (gpg->istream)) {
+                       printf ("closing stdin...");
                        close (gpg->stdin);
                        gpg->stdin = -1;
                }
@@ -996,7 +1032,7 @@ gpg_ctx_op_step (struct _GpgCtx *gpg, CamelException *ex)
 static gboolean
 gpg_ctx_op_complete (struct _GpgCtx *gpg)
 {
-       return gpg->complete;
+       return gpg->complete && !gpg->reading;
 }
 
 static void
@@ -1099,7 +1135,12 @@ gpg_sign (CamelCipherContext *context, const char *userid, CamelCipherHash hash,
                diagnostics = gpg_ctx_get_diagnostics (gpg);
                camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, diagnostics);
                g_free (diagnostics);
+               
+               gpg_ctx_free (gpg);
+               
+               return -1;
        }
+       
        gpg_ctx_free (gpg);
        
        return 0;
@@ -1165,7 +1206,8 @@ gpg_verify (CamelCipherContext *context, CamelCipherHash hash,
                sigfile = swrite (sigstream);
                if (sigfile == NULL) {
                        camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
-                                             _("Cannot verify this message: couldn't create temp file: %s"),
+                                             _("Cannot verify message signature: "
+                                               "could not create temp file: %s"),
                                              g_strerror (errno));
                        return NULL;
                }
@@ -1224,7 +1266,6 @@ gpg_verify (CamelCipherContext *context, CamelCipherHash hash,
        
        diagnostics = gpg_ctx_get_diagnostics (gpg);
        
-       
        gpg_ctx_free (gpg);
                
        if (sigfile) {
@@ -1248,10 +1289,10 @@ gpg_encrypt (CamelCipherContext *context, gboolean sign, const char *userid,
        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_userid (gpg, "fejj@stampede.org");
        gpg_ctx_set_istream (gpg, istream);
        gpg_ctx_set_ostream (gpg, ostream);
-       gpg_ctx_set_always_trust (gpg, TRUE);
+       gpg_ctx_set_always_trust (gpg, ctx->always_trust);
        
        for (i = 0; i < recipients->len; i++) {
                gpg_ctx_add_recipient (gpg, recipients->pdata[i]);
@@ -1289,6 +1330,10 @@ gpg_encrypt (CamelCipherContext *context, gboolean sign, const char *userid,
                diagnostics = gpg_ctx_get_diagnostics (gpg);
                camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, diagnostics);
                g_free (diagnostics);
+               
+               gpg_ctx_free (gpg);
+               
+               return -1;
        }
        
        gpg_ctx_free (gpg);
@@ -1341,6 +1386,10 @@ gpg_decrypt (CamelCipherContext *context, CamelStream *istream,
                diagnostics = gpg_ctx_get_diagnostics (gpg);
                camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, diagnostics);
                g_free (diagnostics);
+               
+               gpg_ctx_free (gpg);
+               
+               return -1;
        }
        
        gpg_ctx_free (gpg);
index c297194..51b3d91 100644 (file)
@@ -485,6 +485,7 @@ camel_pgp_mime_part_encrypt (CamelCipherContext *cipher, CamelMimePart **mime_pa
        camel_stream_filter_add (filtered_stream, CAMEL_MIME_FILTER (crlf_filter));
        camel_object_unref (CAMEL_OBJECT (crlf_filter));
        camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (part), CAMEL_STREAM (filtered_stream));
+       camel_stream_flush (CAMEL_STREAM (filtered_stream));
        camel_object_unref (CAMEL_OBJECT (filtered_stream));
        camel_stream_reset (stream);