drop mem_alloc and mem_free, use my own hand crafted optmized macros that
[apps/madmutt.git] / pgp.c
diff --git a/pgp.c b/pgp.c
index 995ec13..4603a94 100644 (file)
--- a/pgp.c
+++ b/pgp.c
 # include "config.h"
 #endif
 
+#include <lib-lib/mem.h>
+
 #include "mutt.h"
+#include "enter.h"
+#include "ascii.h"
+#include "handler.h"
 #include "mutt_curses.h"
 #include "pgp.h"
 #include "mime.h"
 #include "copy.h"
+#include "attach.h"
 
 #include "lib/mem.h"
 #include "lib/intl.h"
@@ -99,10 +105,16 @@ void pgp_forget_passphrase (void)
   mutt_message _("PGP passphrase forgotten.");
 }
 
-int pgp_use_gpg_agent (void)
-{
-  return option (OPTUSEGPGAGENT) && getenv ("GPG_TTY")
-    && getenv ("GPG_AGENT_INFO");
+int pgp_use_gpg_agent (void) {
+  char *tty;
+
+  if (!option (OPTUSEGPGAGENT) || !getenv ("GPG_AGENT_INFO"))
+    return 0;
+
+  if ((tty = ttyname(0)))
+    setenv ("GPG_TTY", tty, 0);
+
+  return 1;
 }
 
 char *pgp_keyid (pgp_key_t k)
@@ -151,7 +163,7 @@ static int pgp_copy_checksig (FILE * fpin, FILE * fpout)
       fputs (line, fpout);
       fputc ('\n', fpout);
     }
-    mem_free (&line);
+    p_delete(&line);
   }
   else {
     debug_print (2, ("No pattern.\n"));
@@ -221,17 +233,20 @@ static void pgp_copy_clearsigned (FILE * fpin, STATE * s, char *charset)
 
 /* Support for the Application/PGP Content Type. */
 
-void pgp_application_pgp_handler (BODY * m, STATE * s)
+int pgp_application_pgp_handler (BODY * m, STATE * s)
 {
+  int could_not_decrypt = 0;
   int needpass = -1, pgp_keyblock = 0;
+  int c = 1;
   int clearsign = 0, rv, rc;
   long start_pos = 0;
-  long bytes, last_pos, offset;
+  long bytes;
+  off_t last_pos, offset;
   char buf[HUGE_STRING];
   char outfile[_POSIX_PATH_MAX];
   char tmpfname[_POSIX_PATH_MAX];
   FILE *pgpout = NULL, *pgpin = NULL, *pgperr = NULL;
-  FILE *tmpfp;
+  FILE *tmpfp = NULL;
   pid_t thepid;
 
   short maybe_goodsig = 1;
@@ -243,14 +258,14 @@ void pgp_application_pgp_handler (BODY * m, STATE * s)
 
   rc = 0;                       /* silence false compiler warning if (s->flags & M_DISPLAY) */
 
-  fseek (s->fpin, m->offset, 0);
+  fseeko (s->fpin, m->offset, 0);
   last_pos = m->offset;
 
   for (bytes = m->length; bytes > 0;) {
     if (fgets (buf, sizeof (buf), s->fpin) == NULL)
       break;
 
-    offset = ftell (s->fpin);
+    offset = ftello (s->fpin);
     bytes -= (offset - last_pos);       /* don't rely on str_len(buf) */
     last_pos = offset;
 
@@ -283,12 +298,12 @@ void pgp_application_pgp_handler (BODY * m, STATE * s)
       mutt_mktemp (tmpfname);
       if ((tmpfp = safe_fopen (tmpfname, "w+")) == NULL) {
         mutt_perror (tmpfname);
-        return;
+        return (-1);
       }
 
       fputs (buf, tmpfp);
       while (bytes > 0 && fgets (buf, sizeof (buf) - 1, s->fpin) != NULL) {
-        offset = ftell (s->fpin);
+        offset = ftello (s->fpin);
         bytes -= (offset - last_pos);   /* don't rely on str_len(buf) */
         last_pos = offset;
 
@@ -312,7 +327,7 @@ void pgp_application_pgp_handler (BODY * m, STATE * s)
         mutt_mktemp (outfile);
         if ((pgpout = safe_fopen (outfile, "w+")) == NULL) {
           mutt_perror (tmpfname);
-          return;
+          return (-1);
         }
 
         if ((thepid = pgp_invoke_decode (&pgpin, NULL, &pgperr, -1,
@@ -349,26 +364,39 @@ void pgp_application_pgp_handler (BODY * m, STATE * s)
           if (s->flags & M_DISPLAY) {
             if (rc == 0)
               have_any_sigs = 1;
-/*
- * Sig is bad if
- * gpg_good_sign-pattern did not match || pgp_decode_command returned not 0
- * Sig _is_ correct if
- *  gpg_good_sign="" && pgp_decode_command returned 0
- */
+
+            /*
+             * Sig is bad if
+             * gpg_good_sign-pattern did not match || pgp_decode_command returned not 0
+             * Sig _is_ correct if
+             * gpg_good_sign="" && pgp_decode_command returned 0
+             */
             if (rc == -1 || rv)
               maybe_goodsig = 0;
 
             state_attach_puts (_("[-- End of PGP output --]\n\n"), s);
           }
         }
-      }
 
-      /* treat empty result as sign of failure */
-      if (pgpout !=NULL)
-        if (! ftell(pgpout)) {
+        /* treat empty result as sign of failure */
+        /* TODO: maybe on failure mutt should include the original undecoded text. */
+        if (pgpout) {
+          rewind (pgpout);
+          c = fgetc (pgpout);
+          ungetc (c, pgpout);
+        }
+        if (!clearsign && (!pgpout || c == EOF)) {
+          could_not_decrypt = 1;
+          pgp_void_passphrase ();
+        }
+
+        if (could_not_decrypt && !(s->flags & M_DISPLAY)) {
           mutt_error _("Could not decrypt PGP message");
+          mutt_sleep (1);
+          rc = -1;
           goto out;
         }
+      }
 
       /*
        * Now, copy cleartext to the screen.  NOTE - we expect that PGP
@@ -406,7 +434,10 @@ void pgp_application_pgp_handler (BODY * m, STATE * s)
         state_putc ('\n', s);
         if (needpass) {
           state_attach_puts (_("[-- END PGP MESSAGE --]\n"), s);
-          mutt_message _("PGP message successfully decrypted.");
+          if (could_not_decrypt)
+            mutt_error _("Could not decrypt PGP message.");
+          else
+            mutt_message _("PGP message successfully decrypted.");
         }
         else if (pgp_keyblock)
           state_attach_puts (_("[-- END PGP PUBLIC KEY BLOCK --]\n"), s);
@@ -423,6 +454,8 @@ void pgp_application_pgp_handler (BODY * m, STATE * s)
     }
   }
 
+  rc = 0;
+
 out:
   m->goodsig = (maybe_goodsig && have_any_sigs);
 
@@ -439,8 +472,10 @@ out:
     state_attach_puts (_
                        ("[-- Error: could not find beginning of PGP message! --]\n\n"),
                        s);
-    return;
+    return (-1);
   }
+
+  return (rc);
 }
 
 static int pgp_check_traditional_one_body (FILE * fp, BODY * b,
@@ -538,7 +573,7 @@ int pgp_verify_one (BODY * sigbdy, STATE * s, const char *tempfile)
     return -1;
   }
 
-  fseek (s->fpin, sigbdy->offset, 0);
+  fseeko (s->fpin, sigbdy->offset, 0);
   mutt_copy_bytes (s->fpin, fp, sigbdy->length);
   fclose (fp);
 
@@ -720,7 +755,7 @@ BODY *pgp_decrypt_part (BODY * a, STATE * s, FILE * fpout, BODY * p)
    * the temporary file.
    */
 
-  fseek (s->fpin, a->offset, 0);
+  fseeko (s->fpin, a->offset, 0);
   mutt_copy_bytes (s->fpin, pgptmp, a->length);
   fclose (pgptmp);
 
@@ -771,8 +806,11 @@ BODY *pgp_decrypt_part (BODY * a, STATE * s, FILE * fpout, BODY * p)
   fflush (fpout);
   rewind (fpout);
 
-  if (fgetc (fpout) == EOF)
+  if (fgetc (fpout) == EOF) {
+    mutt_error (_("Decryption failed."));
+    pgp_void_passphrase ();
     return NULL;
+  }
 
   rewind (fpout);
 
@@ -824,12 +862,13 @@ int pgp_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, BODY ** cur)
   return (0);
 }
 
-void pgp_encrypted_handler (BODY * a, STATE * s)
+int pgp_encrypted_handler (BODY * a, STATE * s)
 {
   char tempfile[_POSIX_PATH_MAX];
   FILE *fpout, *fpin;
   BODY *tattach;
   BODY *p = a;
+  int rc = 0;
 
   a = a->parts;
   if (!a || a->type != TYPEAPPLICATION || !a->subtype ||
@@ -839,7 +878,7 @@ void pgp_encrypted_handler (BODY * a, STATE * s)
     if (s->flags & M_DISPLAY)
       state_attach_puts (_("[-- Error: malformed PGP/MIME message! --]\n\n"),
                          s);
-    return;
+    return (-1);
   }
 
   /*
@@ -853,7 +892,7 @@ void pgp_encrypted_handler (BODY * a, STATE * s)
       state_attach_puts (_
                          ("[-- Error: could not create temporary file! --]\n"),
                          s);
-    return;
+    return (-1);
   }
 
   if (s->flags & M_DISPLAY)
@@ -867,7 +906,7 @@ void pgp_encrypted_handler (BODY * a, STATE * s)
 
     fpin = s->fpin;
     s->fpin = fpout;
-    mutt_body_handler (tattach, s);
+    rc = mutt_body_handler (tattach, s);
     s->fpin = fpin;
 
     /* 
@@ -888,11 +927,16 @@ void pgp_encrypted_handler (BODY * a, STATE * s)
     mutt_free_body (&tattach);
     /* clear 'Invoking...' message, since there's no error */
     mutt_message _("PGP message successfully decrypted.");
-  } else
+  } else {
     mutt_error _("Could not decrypt PGP message");
+    pgp_void_passphrase ();
+    rc = -1;
+  }
 
   fclose (fpout);
   mutt_unlink (tempfile);
+
+  return (rc);
 }
 
 /* ----------------------------------------------------------------------------
@@ -1100,7 +1144,7 @@ char *pgp_findKeys (ADDRESS * to, ADDRESS * cc, ADDRESS * bcc)
           k_info = pgp_getkeybystr (keyID, KEYFLAG_CANENCRYPT, PGP_PUBRING);
       }
       else if (r == -1) {
-        mem_free (&keylist);
+        p_delete(&keylist);
         rfc822_free_address (&tmp);
         rfc822_free_address (&addr);
         return NULL;
@@ -1117,7 +1161,7 @@ char *pgp_findKeys (ADDRESS * to, ADDRESS * cc, ADDRESS * bcc)
 
       if ((key = pgp_ask_for_key (buf, q->mailbox,
                                   KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL) {
-        mem_free (&keylist);
+        p_delete(&keylist);
         rfc822_free_address (&tmp);
         rfc822_free_address (&addr);
         return NULL;