]> granicus.if.org Git - mutt/commitdiff
Add edit-content-type helper and warning for decrypted attachments. (closes #3728)
authorKevin McCarthy <kevin@8t8.us>
Fri, 11 Aug 2017 01:18:28 +0000 (18:18 -0700)
committerKevin McCarthy <kevin@8t8.us>
Fri, 11 Aug 2017 01:18:28 +0000 (18:18 -0700)
Regenerating the actx index will overwrite any changes made to a
decrypted attachment.  Change the mutt_edit_content_type() function to
return 1 when a structural change is made.  Add a warning message when
that is the case and a decrypted message was edited, so the user is
not surprised.

Note: mutt_edit_content_type() appeared to regenerate multipart
subparts every time, leading to a memory leak.  I believe this was an
oversite, and it should have regenerated only when there were no
subparts, so have "fixed" this.

commands.c
protos.h
recvattach.c

index 2cfa9addeaa0e8852d5c2f667a3e4f13ee02538a..d1bf5d53d4fe0264b432b51eacf636147ae34113 100644 (file)
@@ -878,7 +878,13 @@ void mutt_version (void)
   mutt_message ("Mutt %s (%s)", MUTT_VERSION, ReleaseDate);
 }
 
-void mutt_edit_content_type (HEADER *h, BODY *b, FILE *fp)
+/*
+ * Returns:
+ *   1 when a structural change is made.
+ *     recvattach requires this to know when to regenerate the actx.
+ *   0 otherwise.
+ */
+int mutt_edit_content_type (HEADER *h, BODY *b, FILE *fp)
 {
   char buf[LONG_STRING];
   char obuf[LONG_STRING];
@@ -890,6 +896,7 @@ void mutt_edit_content_type (HEADER *h, BODY *b, FILE *fp)
 
   short charset_changed = 0;
   short type_changed = 0;
+  short structure_changed = 0;
   
   cp = mutt_get_parameter ("charset", b->parameter);
   strfcpy (charset, NONULL (cp), sizeof (charset));
@@ -911,7 +918,7 @@ void mutt_edit_content_type (HEADER *h, BODY *b, FILE *fp)
   
   if (mutt_get_field ("Content-Type: ", buf, sizeof (buf), 0) != 0 ||
       buf[0] == 0)
-    return;
+    return 0;
   
   /* clean up previous junk */
   mutt_free_parameter (&b->parameter);
@@ -952,15 +959,22 @@ void mutt_edit_content_type (HEADER *h, BODY *b, FILE *fp)
   b->force_charset |= charset_changed ? 1 : 0;
 
   if (!is_multipart (b) && b->parts)
+  {
+    structure_changed = 1;
     mutt_free_body (&b->parts);
+  }
   if (!mutt_is_message_type (b->type, b->subtype) && b->hdr)
   {
+    structure_changed = 1;
     b->hdr->content = NULL;
     mutt_free_header (&b->hdr);
   }
 
-  if (fp && (is_multipart (b) || mutt_is_message_type (b->type, b->subtype)))
+  if (fp && !b->parts && (is_multipart (b) || mutt_is_message_type (b->type, b->subtype)))
+  {
+    structure_changed = 1;
     mutt_parse_part (fp, b);
+  }
   
   if (WithCrypto && h)
   {
@@ -969,6 +983,8 @@ void mutt_edit_content_type (HEADER *h, BODY *b, FILE *fp)
 
     h->security |= crypt_query (b);
   }
+
+  return structure_changed;
 }
 
 
index 4f371684174f36fa4bd5d36256b250752c73d36c..63d11c626e5e31fb7b6dd448ec5308e1b8e913dd 100644 (file)
--- a/protos.h
+++ b/protos.h
@@ -181,7 +181,7 @@ void mutt_decode_base64 (STATE *s, long len, int istext, iconv_t cd);
 void mutt_default_save (char *, size_t, HEADER *);
 void mutt_display_address (ENVELOPE *);
 void mutt_display_sanitize (char *);
-void mutt_edit_content_type (HEADER *, BODY *, FILE *);
+int mutt_edit_content_type (HEADER *, BODY *, FILE *);
 void mutt_edit_file (const char *, const char *);
 void mutt_edit_headers (const char *, const char *, HEADER *, char *, size_t);
 char **mutt_envlist (void);
index acfafc26427d30099ad613a2ab855750633ee489..07c4ba8c29a7799c7aca80aad1d47b8b79af736d 100644 (file)
@@ -831,12 +831,31 @@ static int recvattach_pgp_check_traditional (ATTACH_CONTEXT *actx, MUTTMENU *men
   return rv;
 }
 
+static void recvattach_edit_content_type (ATTACH_CONTEXT *actx, MUTTMENU *menu, HEADER *hdr)
+{
+  int i;
+
+  if (mutt_edit_content_type (hdr, CURATTACH->content, CURATTACH->fp) == 1)
+  {
+    /* The mutt_update_recvattach_menu() will overwrite any changes
+     * made to a decrypted CURATTACH->content, so warn the user. */
+    if (CURATTACH->decrypted)
+    {
+      mutt_message _("Structural changes to decrypted attachments are not supported");
+      mutt_sleep (1);
+    }
+    /* Editing the content type can rewrite the body structure. */
+    for (i = 0; i < actx->idxlen; i++)
+      actx->idx[i]->content = NULL;
+    mutt_actx_free_entries (actx);
+    mutt_update_recvattach_menu (actx, menu, 1);
+  }
+}
+
 int
 mutt_attach_display_loop (MUTTMENU *menu, int op, HEADER *hdr,
                          ATTACH_CONTEXT *actx, int recv)
 {
-  int i;
-
   do
   {
     switch (op)
@@ -873,15 +892,12 @@ mutt_attach_display_loop (MUTTMENU *menu, int op, HEADER *hdr,
       case OP_EDIT_TYPE:
        /* when we edit the content-type, we should redisplay the attachment
           immediately */
-       mutt_edit_content_type (hdr, CURATTACH->content, CURATTACH->fp);
         if (recv)
-        {
-          /* Editing the content type can rewrite the body structure. */
-          for (i = 0; i < actx->idxlen; i++)
-            actx->idx[i]->content = NULL;
-          mutt_actx_free_entries (actx);
-          mutt_update_recvattach_menu (actx, menu, 1);
-        }
+          recvattach_edit_content_type (actx, menu, hdr);
+        else
+          mutt_edit_content_type (hdr, CURATTACH->content, CURATTACH->fp);
+
+        menu->redraw |= REDRAW_INDEX;
         op = OP_VIEW_ATTACH;
        break;
       /* functions which are passed through from the pager */
@@ -1096,7 +1112,6 @@ void mutt_view_attachments (HEADER *hdr)
   MUTTMENU *menu;
   BODY *cur = NULL;
   MESSAGE *msg;
-  FILE *fp;
   ATTACH_CONTEXT *actx;
   int flags = 0;
   int op = OP_NULL;
@@ -1322,12 +1337,8 @@ void mutt_view_attachments (HEADER *hdr)
        break;
 
       case OP_EDIT_TYPE:
-       mutt_edit_content_type (hdr, CURATTACH->content, fp);
-        /* Editing the content type can rewrite the body structure. */
-        for (i = 0; i < actx->idxlen; i++)
-          actx->idx[i]->content = NULL;
-        mutt_actx_free_entries (actx);
-        mutt_update_recvattach_menu (actx, menu, 1);
+        recvattach_edit_content_type (actx, menu, hdr);
+        menu->redraw |= REDRAW_INDEX;
        break;
 
       case OP_EXIT: