fix regression. make the hook types be ints.
[apps/madmutt.git] / crypt-gpgme.c
index 84bc377..145a6e0 100644 (file)
 
 #ifdef CRYPT_BACKEND_GPGME
 
+#include <lib-lib/mem.h>
+#include <lib-lib/str.h>
+#include <lib-lib/ascii.h>
+#include <lib-lib/macros.h>
+#include <lib-lib/file.h>
+
+#include <lib-mime/mime.h>
+
 #include "mutt.h"
-#include "mutt_crypt.h"
+#include <lib-crypt/crypt.h>
 #include "mutt_menu.h"
 #include "mutt_curses.h"
-#include "mime.h"
+#include "handler.h"
+#include "enter.h"
 #include "copy.h"
 #include "pager.h"
+#include "recvattach.h"
 #include "sort.h"
 
-#include "lib/mem.h"
-#include "lib/intl.h"
-#include "lib/str.h"
+#include "lib/debug.h"
 
 #include <sys/wait.h>
 #include <string.h>
@@ -112,10 +120,10 @@ static gpgme_key_t signature_key = NULL;
  * General helper functions.
  */
 
-/* return true when S pints to a didgit or letter. */
+/* return true when S points to a didgit or letter. */
 static int digit_or_letter (const unsigned char *s)
 {
-  return ((*s >= '0' && *s < '9')
+  return ((*s >= '0' && *s <= '9')
           || (*s >= 'A' && *s <= 'Z')
           || (*s >= 'a' && *s <= 'z'));
 }
@@ -127,12 +135,10 @@ static void print_utf8 (FILE * fp, const char *buf, size_t len)
 {
   char *tstr;
 
-  tstr = safe_malloc (len + 1);
-  memcpy (tstr, buf, len);
-  tstr[len] = 0;
+  tstr = p_dupstr(buf, len);
   mutt_convert_string (&tstr, "utf-8", Charset, M_ICONV_HOOK_FROM);
   fputs (tstr, fp);
-  FREE (&tstr);
+  p_delete(&tstr);
 }
 
 
@@ -148,7 +154,7 @@ static const char *crypt_keyid (crypt_key_t * k)
 
   if (k->kobj && k->kobj->subkeys) {
     s = k->kobj->subkeys->keyid;
-    if ((!option (OPTPGPLONGIDS)) && (safe_strlen (s) == 16))
+    if ((!option (OPTPGPLONGIDS)) && (m_strlen(s) == 16))
       /* Return only the short keyID.  */
       s += 8;
   }
@@ -207,11 +213,11 @@ static char crypt_flags (int flags)
 }
 
 /* Return a copy of KEY. */
-static crypt_key_t *crypt_copy_key (crypt_key_t * key)
+static crypt_key_t *crypt_copy_key (crypt_key_t *key)
 {
   crypt_key_t *k;
 
-  k = safe_calloc (1, sizeof *k);
+  k = p_new(crypt_key_t, 1);
   k->kobj = key->kobj;
   gpgme_key_ref (key->kobj);
   k->idx = key->idx;
@@ -228,7 +234,7 @@ static void crypt_free_key (crypt_key_t ** keylist)
   while (*keylist) {
     crypt_key_t *k = (*keylist)->next;
 
-    FREE (&k);
+    p_delete(&k);
     *keylist = k;
   }
 }
@@ -282,7 +288,7 @@ static int crypt_id_is_valid (crypt_key_t * key)
 
 /* Return a bit vector describing how well the addresses ADDR and
    U_ADDR match and whether KEY is valid. */
-static int crypt_id_matches_addr (ADDRESS * addr, ADDRESS * u_addr,
+static int crypt_id_matches_addr (address_t * addr, address_t * u_addr,
                                   crypt_key_t * key)
 {
   int rv = 0;
@@ -294,11 +300,11 @@ static int crypt_id_matches_addr (ADDRESS * addr, ADDRESS * u_addr,
     rv |= CRYPT_KV_STRONGID;
 
   if (addr->mailbox && u_addr->mailbox
-      && safe_strcasecmp (addr->mailbox, u_addr->mailbox) == 0)
+      && m_strcasecmp(addr->mailbox, u_addr->mailbox) == 0)
     rv |= CRYPT_KV_ADDR;
 
   if (addr->personal && u_addr->personal
-      && safe_strcasecmp (addr->personal, u_addr->personal) == 0)
+      && m_strcasecmp(addr->personal, u_addr->personal) == 0)
     rv |= CRYPT_KV_STRING;
 
   return rv;
@@ -318,7 +324,7 @@ static gpgme_ctx_t create_gpgme_context (int for_smime)
 
   err = gpgme_new (&ctx);
   if (err) {
-    mutt_error ("error creating gpgme context: %s\n", gpgme_strerror (err));
+    mutt_error (_("error creating gpgme context: %s\n"), gpgme_strerror (err));
     sleep (2);
     mutt_exit (1);
   }
@@ -326,7 +332,7 @@ static gpgme_ctx_t create_gpgme_context (int for_smime)
   if (for_smime) {
     err = gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
     if (err) {
-      mutt_error ("error enabling CMS protocol: %s\n", gpgme_strerror (err));
+      mutt_error (_("error enabling CMS protocol: %s\n"), gpgme_strerror (err));
       sleep (2);
       mutt_exit (1);
     }
@@ -344,7 +350,7 @@ static gpgme_data_t create_gpgme_data (void)
 
   err = gpgme_data_new (&data);
   if (err) {
-    mutt_error ("error creating gpgme data object: %s\n",
+    mutt_error (_("error creating gpgme data object: %s\n"),
                 gpgme_strerror (err));
     sleep (2);
     mutt_exit (1);
@@ -403,7 +409,7 @@ static gpgme_data_t body_to_data_object (BODY * a, int convert)
   }
   unlink (tempfile);
   if (err) {
-    mutt_error ("error allocating data object: %s\n", gpgme_strerror (err));
+    mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err));
     return NULL;
   }
 
@@ -420,7 +426,7 @@ static gpgme_data_t file_to_data_object (FILE * fp, long offset, long length)
 
   err = gpgme_data_new_from_filepart (&data, NULL, fp, offset, length);
   if (err) {
-    mutt_error ("error allocating data object: %s\n", gpgme_strerror (err));
+    mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err));
     return NULL;
   }
 
@@ -437,7 +443,7 @@ static int data_object_to_stream (gpgme_data_t data, FILE * fp)
   err = ((gpgme_data_seek (data, 0, SEEK_SET) == -1)
          ? gpgme_error_from_errno (errno) : 0);
   if (err) {
-    mutt_error ("error rewinding data object: %s\n", gpgme_strerror (err));
+    mutt_error (_("error rewinding data object: %s\n"), gpgme_strerror (err));
     return -1;
   }
 
@@ -455,7 +461,7 @@ static int data_object_to_stream (gpgme_data_t data, FILE * fp)
     }
   }
   if (nread == -1) {
-    mutt_error ("error reading data object: %s\n", strerror (errno));
+    mutt_error (_("error reading data object: %s\n"), strerror (errno));
     return -1;
   }
   return 0;
@@ -497,14 +503,14 @@ static char *data_object_to_tempfile (gpgme_data_t data, FILE ** ret_fp)
   else
     fclose (fp);
   if (nread == -1) {
-    mutt_error ("error reading data object: %s\n", gpgme_strerror (err));
+    mutt_error (_("error reading data object: %s\n"), gpgme_strerror (err));
     unlink (tempfile);
     fclose (fp);
     return NULL;
   }
   if (ret_fp)
     *ret_fp = fp;
-  return safe_strdup (tempfile);
+  return m_strdup(tempfile);
 }
 
 
@@ -549,13 +555,13 @@ static gpgme_key_t *create_recipient_set (const char *keylist,
           err = gpgme_get_key (context, buf, &key, 0);
 
         if (!err) {
-          safe_realloc (&rset, sizeof (*rset) * (rset_n + 1));
+          p_realloc(&rset, rset_n + 1);
           rset[rset_n++] = key;
         }
         else {
-          mutt_error ("error adding recipient `%s': %s\n",
+          mutt_error (_("error adding recipient `%s': %s\n"),
                       buf, gpgme_strerror (err));
-          FREE (&rset);
+          p_delete(&rset);
           return NULL;
         }
       }
@@ -563,7 +569,7 @@ static gpgme_key_t *create_recipient_set (const char *keylist,
   }
 
   /* NULL terminate.  */
-  safe_realloc (&rset, sizeof (*rset) * (rset_n + 1));
+  p_realloc(&rset, rset_n + 1);
   rset[rset_n++] = NULL;
 
   if (context)
@@ -599,7 +605,7 @@ static int set_signer (gpgme_ctx_t ctx, int for_smime)
     gpgme_key_release (key);
     gpgme_key_release (key2);
     gpgme_release (listctx);
-    mutt_error (_("ambiguous specfication of secret key `%s'\n"), signid);
+    mutt_error (_("ambiguous specification of secret key `%s'\n"), signid);
     return -1;
   }
   gpgme_op_keylist_end (listctx);
@@ -650,7 +656,7 @@ static char *encrypt_gpgme_object (gpgme_data_t plaintext, gpgme_key_t * rset,
                             plaintext, ciphertext);
   mutt_need_hard_redraw ();
   if (err) {
-    mutt_error ("error encrypting data: %s\n", gpgme_strerror (err));
+    mutt_error (_("error encrypting data: %s\n"), gpgme_strerror (err));
     gpgme_data_release (ciphertext);
     gpgme_release (ctx);
     return NULL;
@@ -682,8 +688,7 @@ static int get_micalg (gpgme_ctx_t ctx, char *buf, size_t buflen)
   if (result) {
     algorithm_name = gpgme_hash_algo_name (result->signatures->hash_algo);
     if (algorithm_name) {
-      strncpy (buf, algorithm_name, buflen - 1);
-      buf[buflen - 1] = 0;
+      m_strcpy(buf, buflen, algorithm_name);
     }
   }
 
@@ -743,7 +748,7 @@ static BODY *sign_message (BODY * a, int use_smime)
   if (err) {
     gpgme_data_release (signature);
     gpgme_release (ctx);
-    mutt_error ("error signing data: %s\n", gpgme_strerror (err));
+    mutt_error (_("error signing data: %s\n"), gpgme_strerror (err));
     return NULL;
   }
 
@@ -756,7 +761,7 @@ static BODY *sign_message (BODY * a, int use_smime)
 
   t = mutt_new_body ();
   t->type = TYPEMULTIPART;
-  t->subtype = safe_strdup ("signed");
+  t->subtype = m_strdup("signed");
   t->encoding = ENC7BIT;
   t->use_disp = 0;
   t->disposition = DISPINLINE;
@@ -780,15 +785,15 @@ static BODY *sign_message (BODY * a, int use_smime)
   t = t->parts->next;
   t->type = TYPEAPPLICATION;
   if (use_smime) {
-    t->subtype = safe_strdup ("pkcs7-signature");
+    t->subtype = m_strdup("pkcs7-signature");
     mutt_set_parameter ("name", "smime.p7s", &t->parameter);
     t->encoding = ENCBASE64;
     t->use_disp = 1;
     t->disposition = DISPATTACH;
-    t->d_filename = safe_strdup ("smime.p7s");
+    t->d_filename = m_strdup("smime.p7s");
   }
   else {
-    t->subtype = safe_strdup ("pgp-signature");
+    t->subtype = m_strdup("pgp-signature");
     t->use_disp = 0;
     t->disposition = DISPINLINE;
     t->encoding = ENC7BIT;
@@ -831,19 +836,19 @@ BODY *pgp_gpgme_encrypt_message (BODY * a, char *keylist, int sign)
     convert_to_7bit (a);
   plaintext = body_to_data_object (a, 0);
   if (!plaintext) {
-    FREE (&rset);
+    p_delete(&rset);
     return NULL;
   }
 
   outfile = encrypt_gpgme_object (plaintext, rset, 0, sign);
   gpgme_data_release (plaintext);
-  FREE (&rset);
+  p_delete(&rset);
   if (!outfile)
     return NULL;
 
   t = mutt_new_body ();
   t->type = TYPEMULTIPART;
-  t->subtype = safe_strdup ("encrypted");
+  t->subtype = m_strdup("encrypted");
   t->encoding = ENC7BIT;
   t->use_disp = 0;
   t->disposition = DISPINLINE;
@@ -853,18 +858,18 @@ BODY *pgp_gpgme_encrypt_message (BODY * a, char *keylist, int sign)
 
   t->parts = mutt_new_body ();
   t->parts->type = TYPEAPPLICATION;
-  t->parts->subtype = safe_strdup ("pgp-encrypted");
+  t->parts->subtype = m_strdup("pgp-encrypted");
   t->parts->encoding = ENC7BIT;
 
   t->parts->next = mutt_new_body ();
   t->parts->next->type = TYPEAPPLICATION;
-  t->parts->next->subtype = safe_strdup ("octet-stream");
+  t->parts->next->subtype = m_strdup("octet-stream");
   t->parts->next->encoding = ENC7BIT;
   t->parts->next->filename = outfile;
   t->parts->next->use_disp = 1;
   t->parts->next->disposition = DISPINLINE;
   t->parts->next->unlink = 1;   /* delete after sending the message */
-  t->parts->next->d_filename = safe_strdup ("msg.asc"); /* non pgp/mime
+  t->parts->next->d_filename = m_strdup("msg.asc"); /* non pgp/mime
                                                            can save */
 
   return t;
@@ -889,25 +894,25 @@ BODY *smime_gpgme_build_smime_entity (BODY * a, char *keylist)
 
   plaintext = body_to_data_object (a, 0);
   if (!plaintext) {
-    FREE (&rset);
+    p_delete(&rset);
     return NULL;
   }
 
   outfile = encrypt_gpgme_object (plaintext, rset, 1, 0);
   gpgme_data_release (plaintext);
-  FREE (&rset);
+  p_delete(&rset);
   if (!outfile)
     return NULL;
 
   t = mutt_new_body ();
   t->type = TYPEAPPLICATION;
-  t->subtype = safe_strdup ("pkcs7-mime");
+  t->subtype = m_strdup("pkcs7-mime");
   mutt_set_parameter ("name", "smime.p7m", &t->parameter);
   mutt_set_parameter ("smime-type", "enveloped-data", &t->parameter);
   t->encoding = ENCBASE64;      /* The output of OpenSSL SHOULD be binary */
   t->use_disp = 1;
   t->disposition = DISPATTACH;
-  t->d_filename = safe_strdup ("smime.p7m");
+  t->d_filename = m_strdup("smime.p7m");
   t->filename = outfile;
   t->unlink = 1;                /*delete after sending the message */
   t->parts = 0;
@@ -987,7 +992,7 @@ static int show_sig_summary (unsigned long sum,
     gpgme_signature_t sig;
     unsigned int i;
 
-    state_attach_puts (_("A system error occured"), s);
+    state_attach_puts (_("A system error occurred"), s);
 
     /* Try to figure out some more detailed system error information. */
     result = gpgme_op_verify_result (ctx);
@@ -1002,7 +1007,7 @@ static int show_sig_summary (unsigned long sum,
       state_attach_puts (": ", s);
       if (t0)
         state_attach_puts (t0, s);
-      if (t1 && !(t0 && !safe_strcmp (t0, t1))) {
+      if (t1 && !(t0 && !m_strcmp(t0, t1))) {
         if (t0)
           state_attach_puts (",", s);
         state_attach_puts (t1, s);
@@ -1029,10 +1034,10 @@ static void show_fingerprint (gpgme_key_t key, STATE * state)
     return;
   is_pgp = (key->protocol == GPGME_PROTOCOL_OpenPGP);
 
-  buf = safe_malloc (safe_strlen (prefix) + safe_strlen (s) * 4 + 2);
+  buf = xmalloc(m_strlen(prefix) + m_strlen(s) * 4 + 2);
   strcpy (buf, prefix);         /* __STRCPY_CHECKED__ */
-  p = buf + safe_strlen (buf);
-  if (is_pgp && safe_strlen (s) == 40) {     /* PGP v4 style formatted. */
+  p = buf + m_strlen(buf);
+  if (is_pgp && m_strlen(s) == 40) {     /* PGP v4 style formatted. */
     for (i = 0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++) {
       *p++ = s[0];
       *p++ = s[1];
@@ -1059,7 +1064,7 @@ static void show_fingerprint (gpgme_key_t key, STATE * state)
   *p++ = '\n';
   *p = 0;
   state_attach_puts (buf, state);
-  FREE (&buf);
+  p_delete(&buf);
 }
 
 /* Show the valididy of a key used for one signature. */
@@ -1237,7 +1242,7 @@ static int verify_one (BODY * sigbdy, STATE * s,
   err = gpgme_data_new_from_file (&message, tempfile, 1);
   if (err) {
     gpgme_data_release (signature);
-    mutt_error ("error allocating data object: %s\n", gpgme_strerror (err));
+    mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err));
     return -1;
   }
   ctx = create_gpgme_context (is_smime);
@@ -1297,7 +1302,7 @@ static int verify_one (BODY * sigbdy, STATE * s,
             if (notation->value) {
               state_attach_puts (notation->value, s);
               if (!(*notation->value
-                    && (notation->value[safe_strlen (notation->value) - 1] ==
+                    && (notation->value[m_strlen(notation->value) - 1] ==
                         '\n')))
                 state_attach_puts ("\n", s);
             }
@@ -1311,7 +1316,7 @@ static int verify_one (BODY * sigbdy, STATE * s,
   gpgme_release (ctx);
 
   state_attach_puts (_("[-- End signature information --]\n\n"), s);
-  dprint (1, (debugfile, "verify_one: returning %d.\n", badsig));
+  debug_print (1, ("returning %d.\n", badsig));
 
   return badsig ? 1 : anywarn ? 2 : 0;
 }
@@ -1484,7 +1489,7 @@ int pgp_gpgme_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, BODY ** cur)
 
   b = b->parts->next;
 
-  memset (&s, 0, sizeof (s));
+  p_clear(&s, 1);
   s.fpin = fpin;
   mutt_mktemp (tempfile);
   if (!(*fpout = safe_fopen (tempfile, "w+"))) {
@@ -1528,9 +1533,9 @@ int smime_gpgme_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b,
   saved_b_type = b->type;
   saved_b_offset = b->offset;
   saved_b_length = b->length;
-  memset (&s, 0, sizeof (s));
+  p_clear(&s, 1);
   s.fpin = fpin;
-  fseek (s.fpin, b->offset, 0);
+  fseeko (s.fpin, b->offset, 0);
   mutt_mktemp (tempfile);
   if (!(tmpfp = safe_fopen (tempfile, "w+"))) {
     mutt_perror (tempfile);
@@ -1541,11 +1546,11 @@ int smime_gpgme_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b,
   s.fpout = tmpfp;
   mutt_decode_attachment (b, &s);
   fflush (tmpfp);
-  b->length = ftell (s.fpout);
+  b->length = ftello (s.fpout);
   b->offset = 0;
   rewind (tmpfp);
 
-  memset (&s, 0, sizeof (s));
+  p_clear(&s, 1);
   s.fpin = tmpfp;
   s.fpout = 0;
   mutt_mktemp (tempfile);
@@ -1580,9 +1585,9 @@ int smime_gpgme_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b,
     saved_b_type = bb->type;
     saved_b_offset = bb->offset;
     saved_b_length = bb->length;
-    memset (&s, 0, sizeof (s));
+    p_clear(&s, 1);
     s.fpin = *fpout;
-    fseek (s.fpin, bb->offset, 0);
+    fseeko (s.fpin, bb->offset, 0);
     mutt_mktemp (tempfile);
     if (!(tmpfp = safe_fopen (tempfile, "w+"))) {
       mutt_perror (tempfile);
@@ -1593,12 +1598,12 @@ int smime_gpgme_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b,
     s.fpout = tmpfp;
     mutt_decode_attachment (bb, &s);
     fflush (tmpfp);
-    bb->length = ftell (s.fpout);
+    bb->length = ftello (s.fpout);
     bb->offset = 0;
     rewind (tmpfp);
     fclose (*fpout);
 
-    memset (&s, 0, sizeof (s));
+    p_clear(&s, 1);
     s.fpin = tmpfp;
     s.fpout = 0;
     mutt_mktemp (tempfile);
@@ -1655,10 +1660,10 @@ static int pgp_check_traditional_one_body (FILE * fp, BODY * b,
   }
 
   while (fgets (buf, sizeof (buf), tfp)) {
-    if (!safe_strncmp ("-----BEGIN PGP ", buf, 15)) {
-      if (!safe_strcmp ("MESSAGE-----\n", buf + 15))
+    if (!m_strncmp("-----BEGIN PGP ", buf, 15)) {
+      if (!m_strcmp("MESSAGE-----\n", buf + 15))
         enc = 1;
-      else if (!safe_strcmp ("SIGNED MESSAGE-----\n", buf + 15))
+      else if (!m_strcmp("SIGNED MESSAGE-----\n", buf + 15))
         sgn = 1;
     }
   }
@@ -1724,7 +1729,7 @@ static void copy_clearsigned (gpgme_data_t data, STATE * s, char *charset)
   if (!fname)
     return;
   unlink (fname);
-  FREE (&fname);
+  p_delete(&fname);
 
   fc = fgetconv_open (fp, charset, Charset, M_ICONV_HOOK_FROM);
 
@@ -1737,7 +1742,7 @@ static void copy_clearsigned (gpgme_data_t data, STATE * s, char *charset)
       continue;
     }
 
-    if (!safe_strcmp (buf, "-----BEGIN PGP SIGNATURE-----\n"))
+    if (!m_strcmp(buf, "-----BEGIN PGP SIGNATURE-----\n"))
       break;
 
     if (armor_header) {
@@ -1761,16 +1766,17 @@ static void copy_clearsigned (gpgme_data_t data, STATE * s, char *charset)
 
 
 /* Support for classic_application/pgp */
-void pgp_gpgme_application_handler (BODY * m, STATE * s)
+int pgp_gpgme_application_handler (BODY * m, STATE * s)
 {
   int needpass = -1, pgp_keyblock = 0;
   int clearsign = 0;
   long start_pos = 0;
-  long bytes, last_pos, offset;
+  long bytes;
+  off_t last_pos, offset;
   char buf[HUGE_STRING];
   FILE *pgpout = NULL;
 
-  gpgme_error_t err;
+  gpgme_error_t err = 0;
   gpgme_data_t armored_data = NULL;
 
   short maybe_goodsig = 1;
@@ -1778,37 +1784,37 @@ void pgp_gpgme_application_handler (BODY * m, STATE * s)
 
   char body_charset[STRING];    /* Only used for clearsigned messages. */
 
-  dprint (2, (debugfile, "Entering pgp_application_pgp handler\n"));
+  debug_print (2, ("Entering pgp_application_pgp handler\n"));
 
   /* For clearsigned messages we won't be able to get a character set
      but we know that this may only be text thus we assume Latin-1
      here. */
   if (!mutt_get_body_charset (body_charset, sizeof (body_charset), m))
-    strfcpy (body_charset, "iso-8859-1", sizeof body_charset);
+    m_strcpy(body_charset, sizeof(body_charset), "iso-8859-1");
 
-  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);
-    bytes -= (offset - last_pos);       /* don't rely on safe_strlen(buf) */
+    offset = ftello (s->fpin);
+    bytes -= (offset - last_pos);       /* don't rely on m_strlen(buf) */
     last_pos = offset;
 
-    if (!safe_strncmp ("-----BEGIN PGP ", buf, 15)) {
+    if (!m_strncmp("-----BEGIN PGP ", buf, 15)) {
       clearsign = 0;
       start_pos = last_pos;
 
-      if (!safe_strcmp ("MESSAGE-----\n", buf + 15))
+      if (!m_strcmp("MESSAGE-----\n", buf + 15))
         needpass = 1;
-      else if (!safe_strcmp ("SIGNED MESSAGE-----\n", buf + 15)) {
+      else if (!m_strcmp("SIGNED MESSAGE-----\n", buf + 15)) {
         clearsign = 1;
         needpass = 0;
       }
       else if (!option (OPTDONTHANDLEPGPKEYS) &&
-               !safe_strcmp ("PUBLIC KEY BLOCK-----\n", buf + 15)) {
+               !m_strcmp("PUBLIC KEY BLOCK-----\n", buf + 15)) {
         needpass = 0;
         pgp_keyblock = 1;
       }
@@ -1824,18 +1830,18 @@ void pgp_gpgme_application_handler (BODY * m, STATE * s)
 
       /* Copy PGP material to an data container */
       armored_data = create_gpgme_data ();
-      gpgme_data_write (armored_data, buf, safe_strlen (buf));
+      gpgme_data_write (armored_data, buf, m_strlen(buf));
       while (bytes > 0 && fgets (buf, sizeof (buf) - 1, s->fpin) != NULL) {
-        offset = ftell (s->fpin);
-        bytes -= (offset - last_pos);   /* don't rely on safe_strlen(buf) */
+        offset = ftello (s->fpin);
+        bytes -= (offset - last_pos);   /* don't rely on m_strlen(buf) */
         last_pos = offset;
 
-        gpgme_data_write (armored_data, buf, safe_strlen (buf));
+        gpgme_data_write (armored_data, buf, m_strlen(buf));
 
-        if ((needpass && !safe_strcmp ("-----END PGP MESSAGE-----\n", buf))
+        if ((needpass && !m_strcmp("-----END PGP MESSAGE-----\n", buf))
             || (!needpass
-                && (!safe_strcmp ("-----END PGP SIGNATURE-----\n", buf)
-                    || !safe_strcmp ("-----END PGP PUBLIC KEY BLOCK-----\n",
+                && (!m_strcmp("-----END PGP SIGNATURE-----\n", buf)
+                    || !m_strcmp("-----END PGP PUBLIC KEY BLOCK-----\n",
                                      buf))))
           break;
       }
@@ -1916,7 +1922,7 @@ void pgp_gpgme_application_handler (BODY * m, STATE * s)
           }
           else {
             unlink (tmpfname);
-            FREE (&tmpfname);
+            p_delete(&tmpfname);
           }
         }
         gpgme_release (ctx);
@@ -1981,9 +1987,10 @@ void pgp_gpgme_application_handler (BODY * m, STATE * s)
   if (needpass == -1) {
     state_attach_puts (_("[-- Error: could not find beginning"
                          " of PGP message! --]\n\n"), s);
-    return;
+    return (-1);
   }
-  dprint (2, (debugfile, "Leaving pgp_application_pgp handler\n"));
+  debug_print (2, ("Leaving pgp_application_pgp handler\n"));
+  return (err);
 }
 
 /* 
@@ -1991,15 +1998,16 @@ void pgp_gpgme_application_handler (BODY * m, STATE * s)
  */
 
 /* MIME handler for pgp/mime encrypted messages. */
-void pgp_gpgme_encrypted_handler (BODY * a, STATE * s)
+int pgp_gpgme_encrypted_handler (BODY * a, STATE * s)
 {
   char tempfile[_POSIX_PATH_MAX];
   FILE *fpout;
   BODY *tattach;
   BODY *orig_body = a;
   int is_signed;
+  int rc = 0;
 
-  dprint (2, (debugfile, "Entering pgp_encrypted handler\n"));
+  debug_print (2, ("Entering pgp_encrypted handler\n"));
   a = a->parts;
   if (!a || a->type != TYPEAPPLICATION || !a->subtype
       || ascii_strcasecmp ("pgp-encrypted", a->subtype)
@@ -2008,7 +2016,7 @@ void pgp_gpgme_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);
   }
 
   /* Move forward to the application/pgp-encrypted body. */
@@ -2019,7 +2027,7 @@ void pgp_gpgme_encrypted_handler (BODY * a, STATE * s)
     if (s->flags & M_DISPLAY)
       state_attach_puts (_("[-- Error: could not create temporary file! "
                            "--]\n"), s);
-    return;
+    return (-1);
   }
 
   tattach = decrypt_part (a, s, fpout, 0, &is_signed);
@@ -2029,17 +2037,14 @@ void pgp_gpgme_encrypted_handler (BODY * a, STATE * s)
     if (s->flags & M_DISPLAY)
       state_attach_puts (is_signed ?
                          _
-                         ("[-- The following data is PGP/MIME signed and encrypted --]\n\n")
-                         :
-                         _
-                         ("[-- The following data is PGP/MIME encrypted --]\n\n"),
-                         s);
+                         ("[-- The following data is PGP/MIME signed and encrypted --]\n\n") :
+                         _("[-- The following data is PGP/MIME encrypted --]\n\n"), s);
 
     {
       FILE *savefp = s->fpin;
 
       s->fpin = fpout;
-      mutt_body_handler (tattach, s);
+      rc = mutt_body_handler (tattach, s);
       s->fpin = savefp;
     }
 
@@ -2064,19 +2069,20 @@ void pgp_gpgme_encrypted_handler (BODY * a, STATE * s)
 
   fclose (fpout);
   mutt_unlink (tempfile);
-  dprint (2, (debugfile, "Leaving pgp_encrypted handler\n"));
+  debug_print (2, ("Leaving pgp_encrypted handler\n"));
+  return (rc);
 }
 
 /* Support for application/smime */
-void smime_gpgme_application_handler (BODY * a, STATE * s)
+int smime_gpgme_application_handler (BODY * a, STATE * s)
 {
   char tempfile[_POSIX_PATH_MAX];
   FILE *fpout;
   BODY *tattach;
   int is_signed;
+  int rc = 0;
 
-
-  dprint (2, (debugfile, "Entering smime_encrypted handler\n"));
+  debug_print (2, ("Entering smime_encrypted handler\n"));
 
   a->warnsig = 0;
   mutt_mktemp (tempfile);
@@ -2084,7 +2090,7 @@ void smime_gpgme_application_handler (BODY * a, STATE * s)
     if (s->flags & M_DISPLAY)
       state_attach_puts (_("[-- Error: could not create temporary file! "
                            "--]\n"), s);
-    return;
+    return (-1);
   }
 
   tattach = decrypt_part (a, s, fpout, 1, &is_signed);
@@ -2093,17 +2099,14 @@ void smime_gpgme_application_handler (BODY * a, STATE * s)
 
     if (s->flags & M_DISPLAY)
       state_attach_puts (is_signed ?
-                         _("[-- The following data is S/MIME signed --]\n\n")
-                         :
-                         _
-                         ("[-- The following data is S/MIME encrypted --]\n\n"),
-                         s);
+                         _("[-- The following data is S/MIME signed --]\n\n") :
+                         _("[-- The following data is S/MIME encrypted --]\n\n"), s);
 
     {
       FILE *savefp = s->fpin;
 
       s->fpin = fpout;
-      mutt_body_handler (tattach, s);
+      rc = mutt_body_handler (tattach, s);
       s->fpin = savefp;
     }
 
@@ -2133,7 +2136,8 @@ void smime_gpgme_application_handler (BODY * a, STATE * s)
 
   fclose (fpout);
   mutt_unlink (tempfile);
-  dprint (2, (debugfile, "Leaving smime_encrypted handler\n"));
+  debug_print (2, ("Leaving smime_encrypted handler\n"));
+  return (rc);
 }
 
 
@@ -2367,10 +2371,10 @@ static int _crypt_compare_address (const void *a, const void *b)
   crypt_key_t **t = (crypt_key_t **) b;
   int r;
 
-  if ((r = safe_strcasecmp ((*s)->uid, (*t)->uid)))
+  if ((r = m_strcasecmp((*s)->uid, (*t)->uid)))
     return r > 0;
   else
-    return safe_strcasecmp (crypt_keyid (*s), crypt_keyid (*t)) > 0;
+    return m_strcasecmp(crypt_keyid (*s), crypt_keyid (*t)) > 0;
 }
 
 static int crypt_compare_address (const void *a, const void *b)
@@ -2387,10 +2391,10 @@ static int _crypt_compare_keyid (const void *a, const void *b)
   crypt_key_t **t = (crypt_key_t **) b;
   int r;
 
-  if ((r = safe_strcasecmp (crypt_keyid (*s), crypt_keyid (*t))))
+  if ((r = m_strcasecmp(crypt_keyid (*s), crypt_keyid (*t))))
     return r > 0;
   else
-    return safe_strcasecmp ((*s)->uid, (*t)->uid) > 0;
+    return m_strcasecmp((*s)->uid, (*t)->uid) > 0;
 }
 
 static int crypt_compare_keyid (const void *a, const void *b)
@@ -2416,7 +2420,7 @@ static int _crypt_compare_date (const void *a, const void *b)
   if (ts < tt)
     return 0;
 
-  return safe_strcasecmp ((*s)->uid, (*t)->uid) > 0;
+  return m_strcasecmp((*s)->uid, (*t)->uid) > 0;
 }
 
 static int crypt_compare_date (const void *a, const void *b)
@@ -2461,9 +2465,9 @@ static int _crypt_compare_trust (const void *a, const void *b)
   if (ts < tt)
     return 0;
 
-  if ((r = safe_strcasecmp ((*s)->uid, (*t)->uid)))
+  if ((r = m_strcasecmp((*s)->uid, (*t)->uid)))
     return r > 0;
-  return (safe_strcasecmp (crypt_keyid ((*s)), crypt_keyid ((*t)))) > 0;
+  return (m_strcasecmp(crypt_keyid ((*s)), crypt_keyid ((*t)))) > 0;
 }
 
 static int crypt_compare_trust (const void *a, const void *b)
@@ -2479,10 +2483,10 @@ static int print_dn_part (FILE * fp, struct dn_array_s *dn, const char *key)
   int any = 0;
 
   for (; dn->key; dn++) {
-    if (!safe_strcmp (dn->key, key)) {
+    if (!m_strcmp(dn->key, key)) {
       if (any)
         fputs (" + ", fp);
-      print_utf8 (fp, dn->value, safe_strlen (dn->value));
+      print_utf8 (fp, dn->value, m_strlen(dn->value));
       any = 1;
     }
   }
@@ -2505,7 +2509,7 @@ static void print_dn_parts (FILE * fp, struct dn_array_s *dn)
   /* now print the rest without any specific ordering */
   for (; dn->key; dn++) {
     for (i = 0; stdpart[i]; i++) {
-      if (!safe_strcmp (dn->key, stdpart[i]))
+      if (!m_strcmp(dn->key, stdpart[i]))
         break;
     }
     if (!stdpart[i]) {
@@ -2537,10 +2541,8 @@ static const unsigned char *parse_dn_part (struct dn_array_s *array,
   n = s - string;
   if (!n)
     return NULL;                /* empty key */
-  array->key = safe_malloc (n + 1);
+  array->key = p_dupstr(string, n );
   p = (unsigned char *) array->key;
-  memcpy (p, string, n);        /* fixme: trim trailing spaces */
-  p[n] = 0;
   string = s + 1;
 
   if (*string == '#') {         /* hexstring */
@@ -2551,7 +2553,7 @@ static const unsigned char *parse_dn_part (struct dn_array_s *array,
     if (!n || (n & 1))
       return NULL;              /* empty or odd number of digits */
     n /= 2;
-    p = safe_malloc (n + 1);
+    p = xmalloc(n + 1);
     array->value = (char *) p;
     for (s1 = string; n; s1 += 2, n--)
       *p++ = xtoi_2 (s1);
@@ -2581,7 +2583,7 @@ static const unsigned char *parse_dn_part (struct dn_array_s *array,
         n++;
     }
 
-    p = safe_malloc (n + 1);
+    p = xmalloc(n + 1);
     array->value = (char *) p;
     for (s = string; n; s++, n--) {
       if (*s == '\\') {
@@ -2612,7 +2614,7 @@ static struct dn_array_s *parse_dn (const unsigned char *string)
   int i;
 
   arraysize = 7;                /* C,ST,L,O,OU,CN,email */
-  array = safe_malloc ((arraysize + 1) * sizeof *array);
+  array = p_new(struct dn_array_s, arraysize + 1);
   arrayidx = 0;
   while (*string) {
     while (*string == ' ')
@@ -2623,12 +2625,12 @@ static struct dn_array_s *parse_dn (const unsigned char *string)
       struct dn_array_s *a2;
 
       arraysize += 5;
-      a2 = safe_malloc ((arraysize + 1) * sizeof *array);
+      a2 = p_new(struct dn_array_s, arraysize + 1);
       for (i = 0; i < arrayidx; i++) {
         a2[i].key = array[i].key;
         a2[i].value = array[i].value;
       }
-      FREE (&array);
+      p_delete(&array);
       array = a2;
     }
     array[arrayidx].key = NULL;
@@ -2650,10 +2652,10 @@ static struct dn_array_s *parse_dn (const unsigned char *string)
 
 failure:
   for (i = 0; i < arrayidx; i++) {
-    FREE (&array[i].key);
-    FREE (&array[i].value);
+    p_delete(&array[i].key);
+    p_delete(&array[i].value);
   }
-  FREE (&array);
+  p_delete(&array);
   return NULL;
 }
 
@@ -2684,10 +2686,10 @@ static void parse_and_print_user_id (FILE * fp, const char *userid)
     else {
       print_dn_parts (fp, dn);
       for (i = 0; dn[i].key; i++) {
-        FREE (&dn[i].key);
-        FREE (&dn[i].value);
+        p_delete(&dn[i].key);
+        p_delete(&dn[i].value);
       }
-      FREE (&dn);
+      p_delete(&dn);
     }
   }
 }
@@ -2752,13 +2754,14 @@ static void print_key_info (gpgme_key_t key, FILE * fp)
       continue;
 
     s = uid->uid;
-    fprintf (fp, "%s ......: ", idx ? _(" aka") : _("Name"));
+    fputs (idx ? _(" aka ......: ") :_("Name ......: "), fp);
+
     if (uid->invalid) {
       fputs (_("[Invalid]"), fp);
       putc (' ', fp);
     }
     if (is_pgp)
-      print_utf8 (fp, s, safe_strlen (s));
+      print_utf8 (fp, s, m_strlen(s));
     else
       parse_and_print_user_id (fp, s);
     putc ('\n', fp);
@@ -2773,7 +2776,7 @@ static void print_key_info (gpgme_key_t key, FILE * fp)
 #else
     strftime (shortbuf, sizeof shortbuf, "%c", tm);
 #endif
-    fprintf (fp, "Valid From : %s\n", shortbuf);
+    fprintf (fp, _("Valid From : %s\n"), shortbuf);
   }
 
   if (key->subkeys && (key->subkeys->expires > 0)) {
@@ -2785,7 +2788,7 @@ static void print_key_info (gpgme_key_t key, FILE * fp)
 #else
     strftime (shortbuf, sizeof shortbuf, "%c", tm);
 #endif
-    fprintf (fp, "Valid To ..: %s\n", shortbuf);
+    fprintf (fp, _("Valid To ..: %s\n"), shortbuf);
   }
 
   if (key->subkeys)
@@ -2798,29 +2801,29 @@ static void print_key_info (gpgme_key_t key, FILE * fp)
   if (key->subkeys)
     aval = key->subkeys->length;
 
-  fprintf (fp, "Key Type ..: %s, %lu bit %s\n", s2, aval, s);
+  fprintf (fp, _("Key Type ..: %s, %lu bit %s\n"), s2, aval, s);
 
-  fprintf (fp, "Key Usage .: ");
+  fprintf (fp, _("Key Usage .: "));
   delim = "";
 
   if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT)) {
     fprintf (fp, "%s%s", delim, _("encryption"));
-    delim = ", ";
+    delim = _(", ");
   }
   if (key_check_cap (key, KEY_CAP_CAN_SIGN)) {
     fprintf (fp, "%s%s", delim, _("signing"));
-    delim = ", ";
+    delim = _(", ");
   }
   if (key_check_cap (key, KEY_CAP_CAN_CERTIFY)) {
     fprintf (fp, "%s%s", delim, _("certification"));
-    delim = ", ";
+    delim = _(", ");
   }
   putc ('\n', fp);
 
   if (key->subkeys) {
     s = key->subkeys->fpr;
     fputs (_("Fingerprint: "), fp);
-    if (is_pgp && safe_strlen (s) == 40) {
+    if (is_pgp && m_strlen(s) == 40) {
       for (i = 0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++) {
         putc (*s, fp);
         putc (s[1], fp);
@@ -2846,13 +2849,13 @@ static void print_key_info (gpgme_key_t key, FILE * fp)
   if (key->issuer_serial) {
     s = key->issuer_serial;
     if (s)
-      fprintf (fp, "Serial-No .: 0x%s\n", s);
+      fprintf (fp, _("Serial-No .: 0x%s\n"), s);
   }
 
   if (key->issuer_name) {
     s = key->issuer_name;
     if (s) {
-      fprintf (fp, "Issued By .: ");
+      fprintf (fp, _("Issued By .: "));
       parse_and_print_user_id (fp, s);
       putc ('\n', fp);
     }
@@ -2866,9 +2869,9 @@ static void print_key_info (gpgme_key_t key, FILE * fp)
       s = subkey->keyid;
 
       putc ('\n', fp);
-      if (safe_strlen (s) == 16)
+      if (m_strlen(s) == 16)
         s += 8;                 /* display only the short keyID */
-      fprintf (fp, "Subkey ....: 0x%s", s);
+      fprintf (fp, _("Subkey ....: 0x%s"), s);
       if (subkey->revoked) {
         putc (' ', fp);
         fputs (_("[Revoked]"), fp);
@@ -2896,7 +2899,7 @@ static void print_key_info (gpgme_key_t key, FILE * fp)
 #else
         strftime (shortbuf, sizeof shortbuf, "%c", tm);
 #endif
-        fprintf (fp, "Valid From : %s\n", shortbuf);
+        fprintf (fp, _("Valid From : %s\n"), shortbuf);
       }
 
       if (subkey->expires > 0) {
@@ -2908,7 +2911,7 @@ static void print_key_info (gpgme_key_t key, FILE * fp)
 #else
         strftime (shortbuf, sizeof shortbuf, "%c", tm);
 #endif
-        fprintf (fp, "Valid To ..: %s\n", shortbuf);
+        fprintf (fp, _("Valid To ..: %s\n"), shortbuf);
       }
 
       if (subkey)
@@ -2921,22 +2924,22 @@ static void print_key_info (gpgme_key_t key, FILE * fp)
       else
         aval = 0;
 
-      fprintf (fp, "Key Type ..: %s, %lu bit %s\n", "PGP", aval, s);
+      fprintf (fp, _("Key Type ..: %s, %lu bit %s\n"), "PGP", aval, s);
 
-      fprintf (fp, "Key Usage .: ");
+      fprintf (fp, _("Key Usage .: "));
       delim = "";
 
       if (subkey->can_encrypt) {
         fprintf (fp, "%s%s", delim, _("encryption"));
-        delim = ", ";
+        delim = _(", ");
       }
       if (subkey->can_sign) {
         fprintf (fp, "%s%s", delim, _("signing"));
-        delim = ", ";
+        delim = _(", ");
       }
       if (subkey->can_certify) {
         fprintf (fp, "%s%s", delim, _("certification"));
-        delim = ", ";
+        delim = _(", ");
       }
       putc ('\n', fp);
     }
@@ -2960,7 +2963,7 @@ static void verify_key (crypt_key_t * key)
 
   mutt_mktemp (tempfile);
   if (!(fp = safe_fopen (tempfile, "w"))) {
-    mutt_perror _("Can't create temporary file");
+    mutt_perror (_("Can't create temporary file"));
 
     return;
   }
@@ -2979,7 +2982,7 @@ static void verify_key (crypt_key_t * key)
 
   k = key->kobj;
   gpgme_key_ref (k);
-  while ((s = k->chain_id) && k->subkeys && safe_strcmp (s, k->subkeys->fpr)) {
+  while ((s = k->chain_id) && k->subkeys && m_strcmp(s, k->subkeys->fpr)) {
     putc ('\n', fp);
     err = gpgme_op_keylist_start (listctx, s, 0);
     gpgme_key_release (k);
@@ -3034,7 +3037,7 @@ static char *list_to_pattern (LIST * list)
     n++;                        /* delimiter or end of string */
   }
   n++;                          /* make sure to allocate at least one byte */
-  pattern = p = safe_calloc (1, n);
+  pattern = p = p_new(char, n);
   for (l = list; l; l = l->next) {
     s = l->data;
     if (*s) {
@@ -3081,8 +3084,8 @@ static crypt_key_t *get_candidates (LIST * hints, unsigned int app,
 
   err = gpgme_new (&ctx);
   if (err) {
-    mutt_error ("gpgme_new failed: %s", gpgme_strerror (err));
-    FREE (&pattern);
+    mutt_error (_("gpgme_new failed: %s"), gpgme_strerror (err));
+    p_delete(&pattern);
     return NULL;
   }
 
@@ -3105,20 +3108,20 @@ static crypt_key_t *get_candidates (LIST * hints, unsigned int app,
     if (!n)
       goto no_pgphints;
 
-    patarr = safe_calloc (n + 1, sizeof *patarr);
+    patarr = p_new(char *, n + 1);
     for (l = hints, n = 0; l; l = l->next) {
       if (l->data && *l->data)
-        patarr[n++] = safe_strdup (l->data);
+        patarr[n++] = m_strdup(l->data);
     }
     patarr[n] = NULL;
     err = gpgme_op_keylist_ext_start (ctx, (const char **) patarr, secret, 0);
     for (n = 0; patarr[n]; n++)
-      FREE (&patarr[n]);
-    FREE (&patarr);
+      p_delete(&patarr[n]);
+    p_delete(&patarr);
     if (err) {
-      mutt_error ("gpgme_op_keylist_start failed: %s", gpgme_strerror (err));
+      mutt_error (_("gpgme_op_keylist_start failed: %s"), gpgme_strerror (err));
       gpgme_release (ctx);
-      FREE (&pattern);
+      p_delete(&pattern);
       return NULL;
     }
 
@@ -3151,7 +3154,7 @@ static crypt_key_t *get_candidates (LIST * hints, unsigned int app,
 #endif /* DISABLED code */
 
       for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) {
-        k = safe_calloc (1, sizeof *k);
+        k = p_new(crypt_key_t, 1);
         k->kobj = key;
         k->idx = idx;
         k->uid = uid->uid;
@@ -3161,7 +3164,7 @@ static crypt_key_t *get_candidates (LIST * hints, unsigned int app,
       }
     }
     if (gpg_err_code (err) != GPG_ERR_EOF)
-      mutt_error ("gpgme_op_keylist_next failed: %s", gpgme_strerror (err));
+      mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err));
     gpgme_op_keylist_end (ctx);
   no_pgphints:
     ;
@@ -3172,9 +3175,9 @@ static crypt_key_t *get_candidates (LIST * hints, unsigned int app,
     gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
     err = gpgme_op_keylist_start (ctx, pattern, 0);
     if (err) {
-      mutt_error ("gpgme_op_keylist_start failed: %s", gpgme_strerror (err));
+      mutt_error (_("gpgme_op_keylist_start failed: %s"), gpgme_strerror (err));
       gpgme_release (ctx);
-      FREE (&pattern);
+      p_delete(&pattern);
       return NULL;
     }
 
@@ -3187,7 +3190,7 @@ static crypt_key_t *get_candidates (LIST * hints, unsigned int app,
         flags |= KEYFLAG_CANSIGN;
 
       for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) {
-        k = safe_calloc (1, sizeof *k);
+        k = p_new(crypt_key_t, 1);
         k->kobj = key;
         k->idx = idx;
         k->uid = uid->uid;
@@ -3197,12 +3200,12 @@ static crypt_key_t *get_candidates (LIST * hints, unsigned int app,
       }
     }
     if (gpg_err_code (err) != GPG_ERR_EOF)
-      mutt_error ("gpgme_op_keylist_next failed: %s", gpgme_strerror (err));
+      mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err));
     gpgme_op_keylist_end (ctx);
   }
 
   gpgme_release (ctx);
-  FREE (&pattern);
+  p_delete(&pattern);
   return db;
 }
 
@@ -3213,16 +3216,16 @@ static LIST *crypt_add_string_to_hints (LIST * hints, const char *str)
   char *scratch;
   char *t;
 
-  if ((scratch = safe_strdup (str)) == NULL)
+  if ((scratch = m_strdup(str)) == NULL)
     return hints;
 
   for (t = strtok (scratch, " ,.:\"()<>\n"); t;
        t = strtok (NULL, " ,.:\"()<>\n")) {
-    if (safe_strlen (t) > 3)
-      hints = mutt_add_list (hints, t);
+    if (m_strlen(t) > 3)
+      hints = mutt_add_list(hints, t);
   }
 
-  FREE (&scratch);
+  p_delete(&scratch);
   return hints;
 }
 
@@ -3230,7 +3233,7 @@ static LIST *crypt_add_string_to_hints (LIST * hints, const char *str)
    will be set to true on return if the user did override the the
    key's validity. */
 static crypt_key_t *crypt_select_key (crypt_key_t * keys,
-                                      ADDRESS * p, const char *s,
+                                      address_t * p, const char *s,
                                       unsigned int app, int *forced_valid)
 {
   int keymax;
@@ -3256,7 +3259,7 @@ static crypt_key_t *crypt_select_key (crypt_key_t * keys,
 
     if (i == keymax) {
       keymax += 20;
-      safe_realloc (&key_table, sizeof (crypt_key_t *) * keymax);
+      p_realloc(&key_table, keymax);
     }
 
     key_table[i++] = k;
@@ -3414,17 +3417,17 @@ static crypt_key_t *crypt_select_key (crypt_key_t * keys,
   }
 
   mutt_menuDestroy (&menu);
-  FREE (&key_table);
+  p_delete(&key_table);
 
   set_option (OPTNEEDREDRAW);
 
   return k;
 }
 
-static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities,
+static crypt_key_t *crypt_getkeybyaddr (address_t * a, short abilities,
                                         unsigned int app, int *forced_valid)
 {
-  ADDRESS *r, *p;
+  address_t *r, *p;
   LIST *hints = NULL;
 
   int weak = 0;
@@ -3455,16 +3458,13 @@ static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities,
   if (!keys)
     return NULL;
 
-  dprint (5, (debugfile, "crypt_getkeybyaddr: looking for %s <%s>.",
-              a->personal, a->mailbox));
+  debug_print (5, ("looking for %s <%s>.\n", a->personal, a->mailbox));
 
   for (k = keys; k; k = k->next) {
-    dprint (5, (debugfile, "  looking at key: %s `%.15s'\n",
-                crypt_keyid (k), k->uid));
+    debug_print (5, ("  looking at key: %s `%.15s'\n", crypt_keyid (k), k->uid));
 
     if (abilities && !(k->flags & abilities)) {
-      dprint (5, (debugfile, "  insufficient abilities: Has %x, want %x\n",
-                  k->flags, abilities));
+      debug_print (5, ("  insufficient abilities: Has %x, want %x\n", k->flags, abilities));
       continue;
     }
 
@@ -3497,7 +3497,7 @@ static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities,
                    || !(validity & CRYPT_KV_ADDR)))
         this_key_has_weak = 1;
     }
-    rfc822_free_address (&r);
+    address_delete (&r);
 
     if (match) {
       crypt_key_t *tmp;
@@ -3568,19 +3568,18 @@ static crypt_key_t *crypt_getkeybystr (char *p, short abilities,
       continue;
 
     match = 0;
-    dprint (5, (debugfile, "crypt_getkeybystr: matching \"%s\" against "
-                "key %s, \"%s\": ", p, crypt_keyid (k), k->uid));
+    debug_print (5, ("matching \"%s\" against " "key %s, \"%s\":\n", p, crypt_keyid (k), k->uid));
 
-    if (!*p || !safe_strcasecmp (p, crypt_keyid (k))
-        || (!safe_strncasecmp (p, "0x", 2)
-            && !safe_strcasecmp (p + 2, crypt_keyid (k)))
+    if (!*p || !m_strcasecmp(p, crypt_keyid (k))
+        || (!m_strncasecmp(p, "0x", 2)
+            && !m_strcasecmp(p + 2, crypt_keyid (k)))
         || (option (OPTPGPLONGIDS)
-            && !safe_strncasecmp (p, "0x", 2)
-            && !safe_strcasecmp (p + 2, crypt_keyid (k) + 8))
-        || str_isstr (k->uid, p)) {
+            && !m_strncasecmp(p, "0x", 2)
+            && !m_strcasecmp(p + 2, crypt_keyid (k) + 8))
+        || m_stristr(k->uid, p)) {
       crypt_key_t *tmp;
 
-      dprint (5, (debugfile, "match.\n"));
+      debug_print (5, ("match.\n"));
 
       *matches_endp = tmp = crypt_copy_key (k);
       matches_endp = &tmp->next;
@@ -3623,8 +3622,8 @@ static crypt_key_t *crypt_ask_for_key (char *tag,
   if (whatfor) {
 
     for (l = id_defaults; l; l = l->next)
-      if (!safe_strcasecmp (whatfor, l->what)) {
-        strfcpy (resp, NONULL (l->dflt), sizeof (resp));
+      if (!m_strcasecmp(whatfor, l->what)) {
+        m_strcpy(resp, sizeof(resp), NONULL(l->dflt));
         break;
       }
   }
@@ -3637,13 +3636,13 @@ static crypt_key_t *crypt_ask_for_key (char *tag,
 
     if (whatfor) {
       if (l)
-        str_replace (&l->dflt, resp);
+        m_strreplace(&l->dflt, resp);
       else {
-        l = safe_malloc (sizeof (struct crypt_cache));
+        l = p_new(struct crypt_cache, 1);
         l->next = id_defaults;
         id_defaults = l;
-        l->what = safe_strdup (whatfor);
-        l->dflt = safe_strdup (resp);
+        l->what = m_strdup(whatfor);
+        l->dflt = m_strdup(resp);
       }
     }
 
@@ -3657,15 +3656,15 @@ static crypt_key_t *crypt_ask_for_key (char *tag,
 
 /* This routine attempts to find the keyids of the recipients of a
    message.  It returns NULL if any of the keys can not be found.  */
-static char *find_keys (ADDRESS * to, ADDRESS * cc, ADDRESS * bcc,
+static char *find_keys (address_t * to, address_t * cc, address_t * bcc,
                         unsigned int app)
 {
   char *keyID, *keylist = NULL, *t;
   size_t keylist_size = 0;
   size_t keylist_used = 0;
-  ADDRESS *tmp = NULL, *addr = NULL;
-  ADDRESS **last = &tmp;
-  ADDRESS *p, *q;
+  address_t *tmp = NULL, *addr = NULL;
+  address_t **last = &tmp;
+  address_t *p, *q;
   int i;
   crypt_key_t *k_info, *key;
   const char *fqdn = mutt_fqdn (1);
@@ -3689,7 +3688,7 @@ static char *find_keys (ADDRESS * to, ADDRESS * cc, ADDRESS * bcc,
       abort ();
     }
 
-    *last = rfc822_cpy_adr (p);
+    *last = address_list_dup (p);
     while (*last)
       last = &((*last)->next);
   }
@@ -3730,9 +3729,9 @@ static char *find_keys (ADDRESS * to, ADDRESS * cc, ADDRESS * bcc,
         }
       }
       else if (r == -1) {
-        FREE (&keylist);
-        rfc822_free_address (&tmp);
-        rfc822_free_address (&addr);
+        p_delete(&keylist);
+        address_delete (&tmp);
+        address_delete (&addr);
         return NULL;
       }
     }
@@ -3749,9 +3748,9 @@ static char *find_keys (ADDRESS * to, ADDRESS * cc, ADDRESS * bcc,
                                     app,
 #endif
                                     &forced_valid)) == NULL) {
-        FREE (&keylist);
-        rfc822_free_address (&tmp);
-        rfc822_free_address (&addr);
+        p_delete(&keylist);
+        address_delete (&tmp);
+        address_delete (&addr);
         return NULL;
       }
     }
@@ -3768,26 +3767,26 @@ static char *find_keys (ADDRESS * to, ADDRESS * cc, ADDRESS * bcc,
         *r_application &= ~APPLICATION_SMIME;
 #endif
 
-      keylist_size += safe_strlen (s) + 4 + 1;
-      safe_realloc (&keylist, keylist_size);
+      keylist_size += m_strlen(s) + 4 + 1;
+      p_realloc(&keylist, keylist_size);
       sprintf (keylist + keylist_used, "%s0x%s%s",      /* __SPRINTF_CHECKED__ */
                keylist_used ? " " : "", s, forced_valid ? "!" : "");
     }
-    keylist_used = safe_strlen (keylist);
+    keylist_used = m_strlen(keylist);
 
     crypt_free_key (&key);
-    rfc822_free_address (&addr);
+    address_delete (&addr);
   }
-  rfc822_free_address (&tmp);
+  address_delete (&tmp);
   return (keylist);
 }
 
-char *pgp_gpgme_findkeys (ADDRESS * to, ADDRESS * cc, ADDRESS * bcc)
+char *pgp_gpgme_findkeys (address_t * to, address_t * cc, address_t * bcc)
 {
   return find_keys (to, cc, bcc, APPLICATION_PGP);
 }
 
-char *smime_gpgme_findkeys (ADDRESS * to, ADDRESS * cc, ADDRESS * bcc)
+char *smime_gpgme_findkeys (address_t * to, address_t * cc, address_t * bcc)
 {
   return find_keys (to, cc, bcc, APPLICATION_SMIME);
 }
@@ -3830,21 +3829,23 @@ static int gpgme_send_menu (HEADER * msg, int *redraw, int is_smime)
   if (is_smime)
     choice =
       mutt_multi_choice (_
-                         ("S/MIME (e)ncrypt, (s)ign, sign (a)s, (b)oth, (t)oggle or (f)orget it?"),
-                         _("esabtf"));
+                         ("S/MIME (e)ncrypt, (s)ign, sign (a)s, (b)oth, (p)gp or (c)lear?"),
+                         _("esabpfc"));
   else
     choice =
       mutt_multi_choice (_
-                         ("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, (t)oggle or (f)orget it?"),
-                         _("esabtf"));
+                         ("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, s/(m)ime or (c)lear?"),
+                         _("esabmfc"));
 
   switch (choice) {
   case 1:                      /* (e)ncrypt */
     msg->security |= (is_smime ? SMIMEENCRYPT : PGPENCRYPT);
+    msg->security &= ~(is_smime ? SMIMESIGN : PGPSIGN);
     break;
 
   case 2:                      /* (s)ign */
     msg->security |= (is_smime ? SMIMESIGN : PGPSIGN);
+    msg->security &= ~(is_smime ? SMIMEENCRYPT : PGPENCRYPT);
     break;
 
   case 3:                      /* sign (a)s */
@@ -3853,15 +3854,17 @@ static int gpgme_send_menu (HEADER * msg, int *redraw, int is_smime)
                                 is_smime ? APPLICATION_SMIME :
                                 APPLICATION_PGP, NULL))) {
       snprintf (input_signas, sizeof (input_signas), "0x%s", crypt_keyid (p));
-      str_replace (is_smime ? &SmimeDefaultKey : &PgpSignAs,
+      m_strreplace(is_smime ? &SmimeDefaultKey : &PgpSignAs,
                         input_signas);
       crypt_free_key (&p);
 
       msg->security |= (is_smime ? SMIMESIGN : PGPSIGN);
     }
+#if 0
     else {
       msg->security &= (is_smime ? ~SMIMESIGN : ~PGPSIGN);
     }
+#endif
     *redraw = REDRAW_FULL;
     break;
 
@@ -3870,16 +3873,16 @@ static int gpgme_send_menu (HEADER * msg, int *redraw, int is_smime)
       (is_smime ? (SMIMEENCRYPT | SMIMESIGN) : (PGPENCRYPT | PGPSIGN));
     break;
 
-  case 5:                      /* (t)oggle */
+  case 5:                      /* (p)gp or s/(m)ime */
     is_smime = !is_smime;
     break;
 
-  case 6:                      /* (f)orget it */
+  case 6:                      /* (c)lear */
     msg->security = 0;
     break;
   }
 
-  if (choice == 6);
+  if (choice == 6 || choice == 7);
   else if (is_smime) {
     msg->security &= ~APPLICATION_PGP;
     msg->security |= APPLICATION_SMIME;
@@ -3904,7 +3907,7 @@ int smime_gpgme_send_menu (HEADER * msg, int *redraw)
 
 static int verify_sender (HEADER * h, gpgme_protocol_t protocol)
 {
-  ADDRESS *sender = NULL;
+  address_t *sender = NULL;
   unsigned int ret = 1;
 
   if (h->env->from) {
@@ -3923,9 +3926,9 @@ static int verify_sender (HEADER * h, gpgme_protocol_t protocol)
       int sender_length = 0;
       int uid_length = 0;
 
-      sender_length = safe_strlen (sender->mailbox);
+      sender_length = m_strlen(sender->mailbox);
       for (uid = key->uids; uid && ret; uid = uid->next) {
-        uid_length = safe_strlen (uid->email);
+        uid_length = m_strlen(uid->email);
         if (1 && (uid->email[0] == '<')
             && (uid->email[uid_length - 1] == '>')
             && (uid_length == sender_length + 2)