enable decryption of ascii-armored gpg messages
authorPaul Mangan <paul@claws-mail.org>
Sat, 13 Oct 2001 07:11:42 +0000 (07:11 +0000)
committerPaul Mangan <paul@claws-mail.org>
Sat, 13 Oct 2001 07:11:42 +0000 (07:11 +0000)
AUTHORS
ChangeLog.claws
configure.in
src/Makefile.am
src/messageview.c
src/mimeview.c
src/pgptext.c [new file with mode: 0644]
src/pgptext.h [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
index 510c2fc..a729532 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -84,3 +84,4 @@ contributors (beside the above; based on Changelog)
        wwp
        Jeroen Versteeg
        Ravemax
+       Jens Jahnke
index 1c2f6d8..cc1115d 100644 (file)
@@ -1,3 +1,11 @@
+2001-10-13 [paul]      0.6.3claws13
+
+       * src/pgptext.[ch] **NEW FILES**
+       * src/Makefile.am, src/messageview.c, src/mimeview.c
+               decrypt ascii-armored gpg text embedded in
+               the message body.
+               Submitted by Jens Jahnke <jan0sch@gmx.net>
+
 2001-10-13 [christoph] 0.6.3claws12
 
        * README.claws
index 88ac4cc..5ab2174 100644 (file)
@@ -8,7 +8,7 @@ MINOR_VERSION=6
 MICRO_VERSION=3
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=claws12
+EXTRA_VERSION=claws13
 VERSION=$MAJOR_VERSION.$MINOR_VERSION.$MICRO_VERSION$EXTRA_VERSION
 
 dnl
index 0e1e0f4..eff1460 100644 (file)
@@ -97,6 +97,7 @@ sylpheed_SOURCES = \
        procmime.c procmime.h \
        rfc2015.c rfc2015.h \
        passphrase.c passphrase.h \
+       pgptext.c pgptext.h \
        select-keys.c select-keys.h \
        sigstatus.c sigstatus.h \
        simple-gettext.c \
index a16be14..f5e3ada 100644 (file)
@@ -47,6 +47,7 @@
 #include "account.h"
 #include "alertpanel.h"
 #include "send.h"
+#include "pgptext.h"
 
 static void messageview_change_view_type(MessageView   *messageview,
                                         MessageType     type);
@@ -379,6 +380,26 @@ void messageview_show(MessageView *messageview, MsgInfo *msginfo)
                    rfc2015_is_encrypted(mimeinfo)) {
                        MSG_SET_TMP_FLAGS(msginfo->flags, MSG_ENCRYPTED);
                }
+               if (!MSG_IS_ENCRYPTED(msginfo->flags) &&
+                   pgptext_is_encrypted(mimeinfo, msginfo)) {
+                       MSG_SET_TMP_FLAGS(msginfo->flags, MSG_ENCRYPTED);
+                       /* To avoid trouble with the rfc2015 stuff we go for encryption 
+                        * right here. */
+                       if (MSG_IS_ENCRYPTED(msginfo->flags) &&
+                           !msginfo->plaintext_file  &&
+                           !msginfo->decryption_failed) {
+                               /* This is an encrypted message but it has not yet
+                                * been decrypted and there was no unsuccessful
+                                * decryption attempt */
+                               pgptext_decrypt_message(msginfo, mimeinfo, fp);
+                               if (msginfo->plaintext_file &&
+                                   !msginfo->decryption_failed) {
+                                       fclose(fp);
+                                       continue;
+                               }
+                       }
+               }
+               
                if (MSG_IS_ENCRYPTED(msginfo->flags) &&
                    !msginfo->plaintext_file  &&
                    !msginfo->decryption_failed) {
index dae4b64..bfe3d78 100644 (file)
@@ -51,6 +51,7 @@
 #include "gtkutils.h"
 #include "prefs_common.h"
 #include "rfc2015.h"
+#include "pgptext.h"
 
 typedef enum
 {
@@ -225,6 +226,8 @@ static gboolean mimeview_is_signed(MimeView *mimeview)
        do {
                if (rfc2015_has_signature(partinfo))
                        return TRUE;
+               if (pgptext_has_signature(partinfo))
+                       return TRUE;
         } while ((partinfo = partinfo->parent) != NULL);
 
        debug_print("mimeview_is_signed: FALSE\n" );
diff --git a/src/pgptext.c b/src/pgptext.c
new file mode 100644 (file)
index 0000000..f1001fb
--- /dev/null
@@ -0,0 +1,369 @@
+/*
+ * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 2001 Jens Jahnke <jan0sch@gmx.net>
+ *
+ * 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 Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#if USE_GPGME
+
+#include "defs.h"
+
+#include <glib.h>
+#include <stdio.h>
+#include <string.h>
+#include <locale.h>
+#include <ctype.h>
+
+#include <gpgme.h>
+
+#include "intl.h"
+#include "procmime.h"
+#include "procheader.h"
+#include "base64.h"
+#include "uuencode.h"
+#include "unmime.h"
+#include "codeconv.h"
+#include "utils.h"
+#include "prefs_common.h"
+#include "passphrase.h"
+#include "select-keys.h"
+#include "sigstatus.h"
+#include "rfc2015.h"
+
+#include "pgptext.h"
+
+#define DIM(v)     (sizeof(v)/sizeof((v)[0]))
+
+static char *content_names[] = {
+    "Content-Type",
+    "Content-Disposition",
+    "Content-Transfer-Encoding",
+    NULL
+};
+
+static char *mime_version_name[] = {
+    "Mime-Version",
+    NULL
+};
+
+
+struct passphrase_cb_info_s {
+    GpgmeCtx c;
+    int did_it;
+};
+
+static const char *
+passphrase_cb (void *opaque, const char *desc, void *r_hd)
+{
+    struct passphrase_cb_info_s *info = opaque;
+    GpgmeCtx ctx = info ? info->c : NULL;
+    const char *pass;
+
+    if (!desc) {
+        /* FIXME: cleanup by looking at *r_hd */
+        return NULL;
+    }
+
+    gpgmegtk_set_passphrase_grab (prefs_common.passphrase_grab);
+    g_message ("%% requesting passphrase for `%s': ", desc );
+    pass = gpgmegtk_passphrase_mbox (desc);
+    if (!pass) {
+        g_message ("%% cancel passphrase entry");
+        gpgme_cancel (ctx);
+    }
+    else
+        g_message ("%% sending passphrase");
+
+    return pass;
+}
+
+static GpgmeData
+pgptext_decrypt (MimeInfo *partinfo, FILE *fp)
+{
+    GpgmeCtx ctx = NULL;
+    GpgmeError err;
+    GpgmeData cipher = NULL, plain = NULL;
+    struct passphrase_cb_info_s info;
+
+    memset (&info, 0, sizeof info);
+
+    err = gpgme_new (&ctx);
+    if (err) {
+        g_message ("gpgme_new failed: %s", gpgme_strerror (err));
+        goto leave;
+    }
+
+    err = gpgme_data_new_from_filepart (&cipher, NULL, fp,
+                                       partinfo->fpos, partinfo->size);
+    if (err) {
+        g_message ("gpgme_data_new_from_filepart failed: %s",
+                   gpgme_strerror (err));
+        goto leave;
+    }
+
+    err = gpgme_data_new (&plain);
+    if (err) {
+        g_message ("gpgme_new failed: %s", gpgme_strerror (err));
+        goto leave;
+    }
+
+    if (!getenv("GPG_AGENT_INFO")) {
+        info.c = ctx;
+        gpgme_set_passphrase_cb (ctx, passphrase_cb, &info);
+    } 
+
+    err = gpgme_op_decrypt (ctx, cipher, plain);
+
+leave:
+    gpgme_data_release (cipher);
+    if (err) {
+        g_warning ("** decryption failed: %s", gpgme_strerror (err));
+        gpgme_data_release (plain);
+        plain = NULL;
+    }
+    else
+        g_message ("** decryption succeeded");
+
+    gpgme_release (ctx);
+    return plain;
+}
+
+static int
+headerp(char *p, char **names)
+{
+    int i, c;
+    char *p2;
+
+    p2 = strchr(p, ':');
+    if(!p2 || p == p2) {
+        return 0;
+    }
+    if(p2[-1] == ' ' || p2[-1] == '\t') {
+        return 0;
+    }
+
+    if(!names[0])
+        return 1;  
+
+    c = *p2;
+    *p2 = 0;
+    for(i = 0 ; names[i] != NULL; i++) {
+        if(!name_cmp (names[i], p))
+            break;
+    }
+    *p2 = c;
+
+    return names[i] != NULL;
+}
+
+MimeInfo * pgptext_find_signature (MimeInfo *mimeinfo)
+{
+}
+
+gboolean pgptext_has_signature (MimeInfo *mimeinfo)
+{
+       /*
+        * check for the following strings:
+        *   -----BEGIN PGP SIGNED MESSAGE-----
+        *   ----- ????
+        *   -----BEGIN PGP SIGNATURE-----
+        *   -----END PGP SIGNATURE-----
+        */
+       
+       return 0;
+}
+
+void pgptext_check_signature (MimeInfo *mimeinfo, FILE *fp)
+{
+}
+
+int pgptext_is_encrypted (MimeInfo *mimeinfo, MsgInfo *msginfo)
+{
+       FILE *fp;
+       gchar *file, *tmpchk;
+       gchar buf[BUFFSIZE];
+       gboolean has_begin_pgp_msg = FALSE;
+       gboolean has_end_pgp_msg = FALSE;
+       gchar *check_begin_pgp_msg = "-----BEGIN PGP MESSAGE-----\n";
+       gchar *check_end_pgp_msg = "-----END PGP MESSAGE-----\n";
+       
+       g_return_if_fail(msginfo != NULL);
+       
+       if (!mimeinfo)
+               return 0;
+       
+       if ((fp = procmsg_open_message(msginfo)) == NULL) return;
+       mimeinfo = procmime_scan_mime_header(fp);
+       fclose(fp);
+       if (!mimeinfo) return;
+
+       file = procmsg_get_message_file_path(msginfo);
+       g_return_if_fail(file != NULL);
+
+       if (mimeinfo->mime_type != MIME_TEXT) {
+               if ((fp = fopen(file, "r")) == NULL) {
+                       FILE_OP_ERROR(file, "fopen");
+                       return;
+               }
+               /* skip headers */
+               if (mimeinfo->mime_type == MIME_MULTIPART) {
+                       if (fseek(fp, mimeinfo->fpos, SEEK_SET) < 0)
+                       perror("fseek");
+                       while (fgets(buf, sizeof(buf), fp) != NULL)
+                               if (buf[0] == '\r' || buf[0] == '\n') break;
+               }
+               /* now check for a pgptext encrypted message */
+               while (fgets(buf, sizeof(buf), fp) != NULL) {
+                       tmpchk = g_strnfill(sizeof(buf), '\n');
+                       memmove(tmpchk, &buf, sizeof(buf));
+                       
+                       if (strstr(tmpchk, check_begin_pgp_msg) != NULL)
+                               has_begin_pgp_msg = TRUE;
+                       if (strstr(tmpchk, check_end_pgp_msg) != NULL)
+                               has_end_pgp_msg = TRUE;
+                       
+                       g_free(tmpchk);
+               }
+               fclose(fp);
+       } else {
+               if ((fp = fopen(file, "r")) == NULL) {
+                       FILE_OP_ERROR(file, "fopen");
+                       return;
+               }
+               /* skip headers */
+               if (fseek(fp, mimeinfo->fpos, SEEK_SET) < 0)
+               perror("fseek");
+               while (fgets(buf, sizeof(buf), fp) != NULL)
+                       if (buf[0] == '\r' || buf[0] == '\n') break;
+               
+               /* now check for a pgptext encrypted message */
+               while (fgets(buf, sizeof(buf), fp) != NULL) {
+                       tmpchk = g_strnfill(sizeof(buf), '\n');
+                       memmove(tmpchk, &buf, sizeof(buf));
+                       
+                       if (strstr(tmpchk, check_begin_pgp_msg) != NULL)
+                               has_begin_pgp_msg = TRUE;
+                       if (strstr(tmpchk, check_end_pgp_msg) != NULL)
+                               has_end_pgp_msg = TRUE;
+                       
+                       g_free(tmpchk);
+               }
+               fclose(fp);
+       }
+       
+       g_free(file);   
+       
+       /* do we have a proper message? */
+       if (has_begin_pgp_msg && has_end_pgp_msg)
+               return 1;
+       else
+               return 0;
+}
+
+void pgptext_decrypt_message (MsgInfo *msginfo, MimeInfo *mimeinfo, FILE *fp)
+{
+    static int id;
+    MimeInfo *partinfo;
+    int n, found;
+    int ver_okay=0;
+    char *fname;
+    GpgmeData plain;
+    FILE *dstfp;
+    size_t nread;
+    char buf[BUFFSIZE];
+    GpgmeError err;
+
+    g_return_if_fail (mimeinfo->mime_type == MIME_TEXT);
+
+    g_message ("** text/plain with pgptext encountered");
+
+    partinfo = procmime_scan_message(msginfo);
+               
+    /* skip headers */
+    if (fseek(fp, partinfo->fpos, SEEK_SET) < 0)
+        perror("fseek");
+    while (fgets(buf, sizeof(buf), fp) != NULL) {
+                               partinfo->fpos = partinfo->fpos + strlen(buf);
+        if (buf[0] == '\r' || buf[0] == '\n') break;
+               }
+    /* get size */
+    while (fgets(buf, sizeof(buf), fp) != NULL)
+                               partinfo->size = partinfo->size + strlen(buf);
+               
+    plain = pgptext_decrypt (partinfo, fp);
+    if (!plain) {
+        msginfo->decryption_failed = 1;
+        return;
+    }
+    
+    fname = g_strdup_printf("%s%cplaintext.%08x",
+                           get_mime_tmp_dir(), G_DIR_SEPARATOR, ++id);
+
+    if ((dstfp = fopen(fname, "w")) == NULL) {
+        FILE_OP_ERROR(fname, "fopen");
+        g_free(fname);
+        msginfo->decryption_failed = 1;
+        return;
+    }
+
+    /* write the orginal header to the new file */
+    if (fseek(fp, mimeinfo->fpos, SEEK_SET) < 0)
+        perror("fseek");
+
+    while (fgets(buf, sizeof(buf), fp)) {
+        if (headerp (buf, content_names))
+            continue;
+        if (buf[0] == '\r' || buf[0] == '\n')
+            break;
+        fputs (buf, dstfp);
+    }
+               
+    err = gpgme_data_rewind (plain);
+    if (err)
+        g_message ("** gpgme_data_rewind failed: %s", gpgme_strerror (err));
+
+               /* insert blank line to avoid some trouble... */
+               fputs ("\n", dstfp);
+               
+    while (!(err = gpgme_data_read (plain, buf, sizeof(buf), &nread))) {
+        fwrite (buf, nread, 1, dstfp);
+    }
+
+    if (err != GPGME_EOF) {
+        g_warning ("** gpgme_data_read failed: %s", gpgme_strerror (err));
+    }
+
+    fclose (dstfp);
+
+    msginfo->plaintext_file = fname;
+    msginfo->decryption_failed = 0;
+
+}
+
+int pgptext_encrypt (const char *file, GSList *recp_list)
+{
+}
+
+int pgptext_sign (const char *file, PrefsAccount *ac)
+{
+}
+
+#endif /* USE_GPGME */
+
diff --git a/src/pgptext.h b/src/pgptext.h
new file mode 100644 (file)
index 0000000..75fb123
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 2001 Jens Jahnke <jan0sch@gmx.net>
+ *
+ * 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 Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __RFC2015_H__
+#define __RFC2015_H__
+
+#include <glib.h>
+#include <stdio.h>
+
+#include "procmime.h"
+#include "prefs_account.h"
+
+/*
+void pgptext_disable_all (void);
+void pgptext_secure_remove (const char *fname);
+MimeInfo * pgptext_find_signature (MimeInfo *mimeinfo);
+*/
+gboolean pgptext_has_signature (MimeInfo *mimeinfo);
+void pgptext_check_signature (MimeInfo *mimeinfo, FILE *fp);
+int pgptext_is_encrypted (MimeInfo *mimeinfo, MsgInfo *msginfo);
+void pgptext_decrypt_message (MsgInfo *msginfo, MimeInfo *mimeinfo, FILE *fp);
+int pgptext_encrypt (const char *file, GSList *recp_list);
+int pgptext_sign (const char *file, PrefsAccount *ac);
+
+#endif /* __RFC2015_H__ */