NeoMutt  2025-12-11-980-ge38c27
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
recvattach.c File Reference

Attachment code. More...

#include "config.h"
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "mutt/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "gui/lib.h"
#include "recvattach.h"
#include "browser/lib.h"
#include "editor/lib.h"
#include "history/lib.h"
#include "hooks/lib.h"
#include "menu/lib.h"
#include "ncrypt/lib.h"
#include "question/lib.h"
#include "send/lib.h"
#include "attach.h"
#include "external.h"
#include "mutt_attach.h"
#include "muttlib.h"
#include <libintl.h>
+ Include dependency graph for recvattach.c:

Go to the source code of this file.

Functions

struct AttachPtrcurrent_attachment (struct AttachCtx *actx, struct Menu *menu)
 Get the current attachment.
 
static void mutt_update_v2r (struct AttachCtx *actx)
 Update the virtual list of attachments.
 
void mutt_update_tree (struct AttachCtx *actx)
 Refresh the list of attachments.
 
static void prepend_savedir (struct Buffer *buf)
 Add $attach_save_dir to the beginning of a path.
 
static bool has_a_message (struct Body *b)
 Determine if the Body has a message (to save)
 
static int save_attachment_flowed_helper (FILE *fp, struct Body *b, const char *path, enum SaveAttach flags, struct Email *e)
 Helper for unstuffing attachments.
 
static int query_save_attachment (FILE *fp, struct Body *b, struct Email *e, char **directory)
 Ask the user if we should save the attachment.
 
static int save_without_prompting (FILE *fp, struct Body *b, struct Email *e)
 Save the attachment, without prompting each time.
 
void mutt_save_attachment_list (struct AttachPtrArray *aa, struct Email *e, struct Menu *menu)
 Save a list of selected attachments.
 
static void query_pipe_attachment (const char *command, FILE *fp, struct Body *b, bool filter)
 Ask the user if we should pipe the attachment.
 
static void pipe_attachment (FILE *fp, struct Body *b, struct State *state)
 Pipe the attachment to a command.
 
static void pipe_attachment_list (const char *command, struct AttachPtrArray *aa, bool filter, struct State *state)
 Pipe a list of attachments to a command.
 
void mutt_pipe_attachment_list (struct AttachPtrArray *aa, bool filter)
 Pipe selected attachments to a command.
 
static bool can_print (struct AttachPtrArray *aa)
 Do we know how to print this attachment type?
 
static void print_attachment_list (struct AttachPtrArray *aa, struct State *state)
 Print a list of Attachments.
 
void mutt_print_attachment_list (struct AttachPtrArray *aa)
 Print selected attachments.
 
void recvattach_edit_content_type (struct AttachCtx *actx, struct Menu *menu, struct Email *e)
 Edit the content type of an attachment.
 
int mutt_attach_display_loop (struct ConfigSubset *sub, struct Menu *menu, int op, struct Email *e, struct AttachCtx *actx, bool recv)
 Event loop for the Attachment menu.
 
void mutt_generate_recvattach_list (struct AttachCtx *actx, struct Email *e, struct Body *b, FILE *fp, int parent_type, int level, bool decrypted)
 Create a list of attachments.
 
void mutt_attach_init (struct AttachCtx *actx)
 Create a new Attachment context.
 
void mutt_update_recvattach_menu (struct AttachCtx *actx, struct Menu *menu, bool init)
 Update the Attachment Menu.
 

Detailed Description

Attachment code.

Authors
  • Anton Rieger
  • Richard Russon
  • Reis Radomil
  • David Harrigan
  • Pietro Cerutti
  • David Purton
  • Dennis Schön
  • Rayford Shireman

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, see http://www.gnu.org/licenses/.

Definition in file recvattach.c.

Function Documentation

◆ current_attachment()

struct AttachPtr * current_attachment ( struct AttachCtx * actx,
struct Menu * menu )

Get the current attachment.

Parameters
actxAttachment context
menuMenu
Return values
ptrCurrent Attachment

Definition at line 71 of file recvattach.c.

72{
73 const int virt = menu_get_index(menu);
74 const int index = actx->v2r[virt];
75
76 return actx->idx[index];
77}
int menu_get_index(struct Menu *menu)
Get the current selection in the Menu.
Definition menu.c:153
struct AttachPtr ** idx
Array of attachments.
Definition attach.h:69
short * v2r
Mapping from virtual to real attachment.
Definition attach.h:73
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_update_v2r()

static void mutt_update_v2r ( struct AttachCtx * actx)
static

Update the virtual list of attachments.

Parameters
actxAttachment context

Update the record of the number of attachments and the status of the tree.

Definition at line 85 of file recvattach.c.

86{
87 int vindex;
88 int rindex;
89 int curlevel;
90
91 vindex = 0;
92 rindex = 0;
93
94 while (rindex < actx->idxlen)
95 {
96 actx->v2r[vindex++] = rindex;
97 if (actx->idx[rindex]->collapsed)
98 {
99 curlevel = actx->idx[rindex]->level;
100 do
101 {
102 rindex++;
103 } while ((rindex < actx->idxlen) && (actx->idx[rindex]->level > curlevel));
104 }
105 else
106 {
107 rindex++;
108 }
109 }
110
111 actx->vcount = vindex;
112}
short vcount
The number of virtual attachments.
Definition attach.h:74
bool collapsed
Group is collapsed.
Definition attach.h:45
int level
Nesting depth of attachment.
Definition attach.h:41
+ Here is the caller graph for this function:

◆ mutt_update_tree()

void mutt_update_tree ( struct AttachCtx * actx)

Refresh the list of attachments.

Parameters
actxAttachment context

Definition at line 118 of file recvattach.c.

119{
120 char buf[256] = { 0 };
121 char *s = NULL;
122
123 mutt_update_v2r(actx);
124
125 for (int vindex = 0; vindex < actx->vcount; vindex++)
126 {
127 const int rindex = actx->v2r[vindex];
128 actx->idx[rindex]->num = vindex;
129 if ((2 * (actx->idx[rindex]->level + 2)) < sizeof(buf))
130 {
131 if (actx->idx[rindex]->level)
132 {
133 s = buf + 2 * (actx->idx[rindex]->level - 1);
134 *s++ = (actx->idx[rindex]->body->next) ? MUTT_TREE_LTEE : MUTT_TREE_LLCORNER;
135 *s++ = MUTT_TREE_HLINE;
136 *s++ = MUTT_TREE_RARROW;
137 }
138 else
139 {
140 s = buf;
141 }
142 *s = '\0';
143 }
144
145 if (actx->idx[rindex]->tree)
146 {
147 if (!mutt_str_equal(actx->idx[rindex]->tree, buf))
148 mutt_str_replace(&actx->idx[rindex]->tree, buf);
149 }
150 else
151 {
152 actx->idx[rindex]->tree = mutt_str_dup(buf);
153 }
154
155 if (((2 * (actx->idx[rindex]->level + 2)) < sizeof(buf)) &&
156 actx->idx[rindex]->level)
157 {
158 s = buf + 2 * (actx->idx[rindex]->level - 1);
159 *s++ = (actx->idx[rindex]->body->next) ? MUTT_TREE_VLINE : MUTT_TREE_SPACE;
160 *s++ = MUTT_TREE_SPACE;
161 }
162 }
163}
@ MUTT_TREE_LLCORNER
Lower left corner.
Definition thread.h:57
@ MUTT_TREE_RARROW
Right arrow.
Definition thread.h:63
@ MUTT_TREE_LTEE
Left T-piece.
Definition thread.h:59
@ MUTT_TREE_VLINE
Vertical line.
Definition thread.h:61
@ MUTT_TREE_HLINE
Horizontal line.
Definition thread.h:60
@ MUTT_TREE_SPACE
Blank space.
Definition thread.h:62
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:666
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition string.c:284
static void mutt_update_v2r(struct AttachCtx *actx)
Update the virtual list of attachments.
Definition recvattach.c:85
struct Body * body
Attachment.
Definition attach.h:37
char * tree
Tree characters to display.
Definition attach.h:40
int num
Attachment index number.
Definition attach.h:42
struct Body * next
next attachment in the list
Definition body.h:72
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ prepend_savedir()

static void prepend_savedir ( struct Buffer * buf)
static

Add $attach_save_dir to the beginning of a path.

Parameters
bufBuffer for the result

Definition at line 169 of file recvattach.c.

170{
171 if (buf_is_empty(buf) || (buf_at(buf, 0) == '/'))
172 return;
173
174 struct Buffer *tmp = buf_pool_get();
175 const char *const c_attach_save_dir = cs_subset_path(NeoMutt->sub, "attach_save_dir");
176 if (c_attach_save_dir)
177 {
178 buf_addstr(tmp, c_attach_save_dir);
179 if (tmp->dptr[-1] != '/')
180 buf_addch(tmp, '/');
181 }
182 else
183 {
184 buf_addstr(tmp, "./");
185 }
186
187 buf_addstr(tmp, buf_string(buf));
188 buf_copy(buf, tmp);
189 buf_pool_release(&tmp);
190}
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:298
char buf_at(const struct Buffer *buf, size_t offset)
Return the character at the given offset.
Definition buffer.c:674
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition buffer.c:248
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition buffer.c:233
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition buffer.c:607
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition helpers.c:168
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
String manipulation buffer.
Definition buffer.h:36
char * dptr
Current read/write position.
Definition buffer.h:38
Container for Accounts, Notifications.
Definition neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ has_a_message()

static bool has_a_message ( struct Body * b)
static

Determine if the Body has a message (to save)

Parameters
[in]bBody of the message
Return values
trueSuitable for saving

Definition at line 197 of file recvattach.c.

198{
199 return (b->email && (b->encoding != ENC_BASE64) && (b->encoding != ENC_QUOTED_PRINTABLE) &&
201}
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition parse.c:1620
@ ENC_BASE64
Base-64 encoded text.
Definition mime.h:52
@ ENC_QUOTED_PRINTABLE
Quoted-printable text.
Definition mime.h:51
struct Email * email
header information for message/rfc822
Definition body.h:74
char * subtype
content-type subtype
Definition body.h:61
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition body.h:41
unsigned int type
content-type primary type, ContentType
Definition body.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ save_attachment_flowed_helper()

static int save_attachment_flowed_helper ( FILE * fp,
struct Body * b,
const char * path,
enum SaveAttach flags,
struct Email * e )
static

Helper for unstuffing attachments.

Parameters
fpAttachment to work on
bBody of email
pathPath to save the attachment
flagsFlags, e.g. MUTT_SAVE_APPEND
eEmail
Return values
0Success
-1Failure

This is a proxy between the mutt_save_attachment_list() calls and mutt_save_attachment(). It (currently) exists solely to unstuff format=flowed text attachments.

Direct modification of mutt_save_attachment() wasn't easily possible because: 1) other callers of mutt_save_attachment() should not have unstuffing performed, such as replying/forwarding attachments. 2) the attachment saving can append to a file, making the unstuffing inside difficult with current functions. 3) we can't unstuff before-hand because decoding hasn't occurred.

So, I apologize for this horrific proxy, but it was the most straightforward method.

Definition at line 228 of file recvattach.c.

230{
231 int rc = -1;
232
234 {
235 struct Body b_fake = { 0 };
236
237 struct Buffer *tempfile = buf_pool_get();
238 buf_mktemp(tempfile);
239
240 rc = mutt_save_attachment(fp, b, buf_string(tempfile), MUTT_SAVE_NONE, e);
241 if (rc != 0)
242 goto cleanup;
243
245
246 /* Now "really" save it. Send mode does this without touching anything,
247 * so force send-mode. */
248 memset(&b_fake, 0, sizeof(struct Body));
249 b_fake.filename = tempfile->data;
250 rc = mutt_save_attachment(NULL, &b_fake, path, flags, e);
251
252 mutt_file_unlink(buf_string(tempfile));
253
254 cleanup:
255 buf_pool_release(&tempfile);
256 }
257 else
258 {
259 rc = mutt_save_attachment(fp, b, path, flags, e);
260 }
261
262 return rc;
263}
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition file.c:156
int mutt_save_attachment(FILE *fp, struct Body *b, const char *path, enum SaveAttach opt, struct Email *e)
Save an attachment.
@ MUTT_SAVE_NONE
Overwrite existing file (the default)
Definition mutt_attach.h:59
void mutt_rfc3676_space_unstuff_attachment(struct Body *b, const char *filename)
Unstuff attachments.
Definition rfc3676.c:524
bool mutt_rfc3676_is_format_flowed(struct Body *b)
Is the Email "format-flowed"?
Definition rfc3676.c:400
The body of an email.
Definition body.h:36
char * filename
When sending a message, this is the file to which this structure refers.
Definition body.h:59
char * data
Pointer to data.
Definition buffer.h:37
#define buf_mktemp(buf)
Definition tmp.h:33
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ query_save_attachment()

static int query_save_attachment ( FILE * fp,
struct Body * b,
struct Email * e,
char ** directory )
static

Ask the user if we should save the attachment.

Parameters
[in]fpFile handle to the attachment (OPTIONAL)
[in]bAttachment
[in]eEmail
[out]directoryWhere the attachment was saved
Return values
0Success
-1Failure

Definition at line 274 of file recvattach.c.

275{
276 char *prompt = NULL;
277 enum SaveAttach opt = MUTT_SAVE_NONE;
278 int rc = -1;
279
280 struct Buffer *buf = buf_pool_get();
281 struct Buffer *tfile = buf_pool_get();
282
283 if (b->filename)
284 {
285 if (directory && *directory)
286 {
287 buf_concat_path(buf, *directory, mutt_path_basename(b->filename));
288 }
289 else
290 {
291 buf_strcpy(buf, b->filename);
292 }
293 }
294 else if (has_a_message(b))
295 {
296 mutt_default_save(buf, b->email);
297 }
298
299 prepend_savedir(buf);
300
301 prompt = _("Save to file: ");
302 while (prompt)
303 {
304 struct FileCompletionData cdata = { false, NULL, NULL, NULL, NULL };
305 if ((mw_get_field(prompt, buf, MUTT_COMP_CLEAR, HC_FILE, &CompleteFileOps, &cdata) != 0) ||
306 buf_is_empty(buf))
307 {
308 goto cleanup;
309 }
310
311 prompt = NULL;
312 expand_path(buf, false);
313
314 bool is_message = (fp && has_a_message(b));
315
316 if (is_message)
317 {
318 struct stat st = { 0 };
319
320 /* check to make sure that this file is really the one the user wants */
321 rc = mutt_save_confirm(buf_string(buf), &st);
322 if (rc == 1)
323 {
324 prompt = _("Save to file: ");
325 continue;
326 }
327 else if (rc == -1)
328 {
329 goto cleanup;
330 }
331 buf_copy(tfile, buf);
332 }
333 else
334 {
335 rc = mutt_check_overwrite(b->filename, buf_string(buf), tfile, &opt, directory);
336 if (rc == -1)
337 {
338 goto cleanup;
339 }
340 else if (rc == 1)
341 {
342 prompt = _("Save to file: ");
343 continue;
344 }
345 }
346
347 mutt_message(_("Saving..."));
348 if (save_attachment_flowed_helper(fp, b, buf_string(tfile), opt,
349 (e || !is_message) ? e : b->email) == 0)
350 {
351 // This uses ngettext to avoid duplication of messages
352 int num = 1;
353 mutt_message(ngettext("Attachment saved", "%d attachments saved", num), num);
354 rc = 0;
355 goto cleanup;
356 }
357 else
358 {
359 prompt = _("Save to file: ");
360 continue;
361 }
362 }
363
364cleanup:
365 buf_pool_release(&buf);
366 buf_pool_release(&tfile);
367 return rc;
368}
const struct CompleteOps CompleteFileOps
Auto-Completion of Files.
Definition complete.c:152
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:401
size_t buf_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition buffer.c:515
@ MUTT_COMP_CLEAR
Clear input if printable character is pressed.
Definition wdata.h:47
int mw_get_field(const char *prompt, struct Buffer *buf, CompletionFlags complete, enum HistoryClass hclass, const struct CompleteOps *comp_api, void *cdata)
Ask the user for a string -.
Definition window.c:502
#define mutt_message(...)
Definition logging2.h:93
@ HC_FILE
Files.
Definition lib.h:59
void mutt_default_save(struct Buffer *path, struct Email *e)
Find the default save path for an email.
Definition exec.c:218
#define _(a)
Definition message.h:28
const char * mutt_path_basename(const char *path)
Find the last component for a pathname.
Definition path.c:282
SaveAttach
Options for saving attachments.
Definition mutt_attach.h:58
void expand_path(struct Buffer *buf, bool regex)
Create the canonical path.
Definition muttlib.c:122
int mutt_check_overwrite(const char *attname, const char *path, struct Buffer *fname, enum SaveAttach *opt, char **directory)
Ask the user if overwriting is necessary.
Definition muttlib.c:524
int mutt_save_confirm(const char *s, struct stat *st)
Ask the user to save.
Definition muttlib.c:690
static int save_attachment_flowed_helper(FILE *fp, struct Body *b, const char *path, enum SaveAttach flags, struct Email *e)
Helper for unstuffing attachments.
Definition recvattach.c:228
static void prepend_savedir(struct Buffer *buf)
Add $attach_save_dir to the beginning of a path.
Definition recvattach.c:169
static bool has_a_message(struct Body *b)
Determine if the Body has a message (to save)
Definition recvattach.c:197
Input for the file completion function.
Definition curs_lib.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ save_without_prompting()

static int save_without_prompting ( FILE * fp,
struct Body * b,
struct Email * e )
static

Save the attachment, without prompting each time.

Parameters
[in]fpFile handle to the attachment (OPTIONAL)
[in]bAttachment
[in]eEmail
Return values
0Success
-1Failure

Definition at line 378 of file recvattach.c.

379{
380 enum SaveAttach opt = MUTT_SAVE_NONE;
381 int rc = -1;
382 struct Buffer *buf = buf_pool_get();
383 struct Buffer *tfile = buf_pool_get();
384
385 if (b->filename)
386 {
387 buf_strcpy(buf, b->filename);
388 }
389 else if (has_a_message(b))
390 {
391 mutt_default_save(buf, b->email);
392 }
393
394 prepend_savedir(buf);
395 expand_path(buf, false);
396
397 bool is_message = (fp && has_a_message(b));
398
399 if (is_message)
400 {
401 buf_copy(tfile, buf);
402 }
403 else
404 {
405 rc = mutt_check_overwrite(b->filename, buf_string(buf), tfile, &opt, NULL);
406 if (rc == -1) // abort or cancel
407 goto cleanup;
408 }
409
410 rc = save_attachment_flowed_helper(fp, b, buf_string(tfile), opt,
411 (e || !is_message) ? e : b->email);
412
413cleanup:
414 buf_pool_release(&buf);
415 buf_pool_release(&tfile);
416 return rc;
417}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_save_attachment_list()

void mutt_save_attachment_list ( struct AttachPtrArray * aa,
struct Email * e,
struct Menu * menu )

Save a list of selected attachments.

Parameters
aaSelected attachments
eParent email
menuMenu listing attachments

Definition at line 425 of file recvattach.c.

426{
427 char *directory = NULL;
428 int rc = 1;
429 int last = menu ? menu_get_index(menu) : 0;
430 FILE *fp_out = NULL;
431 int saved_attachments = 0;
432
433 struct Buffer *buf = buf_pool_get();
434 struct Buffer *tfile = buf_pool_get();
435
436 const bool c_attach_split = cs_subset_bool(NeoMutt->sub, "attach_split");
437 const char *const c_attach_sep = cs_subset_string(NeoMutt->sub, "attach_sep");
438 const bool c_attach_save_without_prompting = cs_subset_bool(NeoMutt->sub, "attach_save_without_prompting");
439
440 struct AttachPtr **app = NULL;
441 ARRAY_FOREACH(app, aa)
442 {
443 FILE *fp = (*app)->fp;
444 struct Body *b = (*app)->body;
445
446 /* Iterate through attachments.
447 * Behavior depends on attach_split: if true, save each to its own file;
448 * if false, concatenate all into one file with optional separator. */
449 if (c_attach_split)
450 {
451 if (menu)
452 {
453 menu_set_index(menu, (*app)->num);
455 menu_redraw(menu);
456 }
457 if (c_attach_save_without_prompting)
458 {
459 // Save each file, with no prompting, using the configured 'AttachSaveDir'
460 rc = save_without_prompting(fp, b, e);
461 if (rc == 0)
462 saved_attachments++;
463 }
464 else
465 {
466 // Save each file, prompting the user for the location each time.
467 if (query_save_attachment(fp, b, e, &directory) == -1)
468 break;
469 }
470 }
471 else
472 {
473 enum SaveAttach opt = MUTT_SAVE_NONE;
474
475 if (buf_is_empty(buf))
476 {
478 prepend_savedir(buf);
479
480 struct FileCompletionData cdata = { false, NULL, NULL, NULL, NULL };
481 if ((mw_get_field(_("Save to file: "), buf, MUTT_COMP_CLEAR, HC_FILE,
482 &CompleteFileOps, &cdata) != 0) ||
483 buf_is_empty(buf))
484 {
485 goto cleanup;
486 }
487 expand_path(buf, false);
488 if (mutt_check_overwrite(b->filename, buf_string(buf), tfile, &opt, NULL))
489 goto cleanup;
490 }
491 else
492 {
493 opt = MUTT_SAVE_APPEND;
494 }
495
496 rc = save_attachment_flowed_helper(fp, b, buf_string(tfile), opt, e);
497 if ((rc == 0) && c_attach_sep && (fp_out = mutt_file_fopen(buf_string(tfile), "a")))
498 {
499 fprintf(fp_out, "%s", c_attach_sep);
500 mutt_file_fclose(&fp_out);
501 }
502 }
503 }
504
505 FREE(&directory);
506
507 if ((ARRAY_SIZE(aa) > 1) && menu)
508 {
509 menu_set_index(menu, last);
511 }
512
513 if (rc == 0)
514 {
515 if (!c_attach_split)
516 saved_attachments = 1;
517
518 if (!c_attach_split || c_attach_save_without_prompting)
519 {
520 mutt_message(ngettext("Attachment saved", "%d attachments saved", saved_attachments),
521 saved_attachments);
522 }
523 }
524
525cleanup:
526 buf_pool_release(&buf);
527 buf_pool_release(&tfile);
528}
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:223
#define ARRAY_SIZE(head)
The number of elements stored.
Definition array.h:87
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
int menu_redraw(struct Menu *menu)
Redraw the parts of the screen that have been flagged to be redrawn.
Definition draw.c:486
#define mutt_file_fclose(FP)
Definition file.h:144
#define mutt_file_fopen(PATH, MODE)
Definition file.h:143
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
void menu_queue_redraw(struct Menu *menu, MenuRedrawFlags redraw)
Queue a request for a redraw.
Definition menu.c:177
@ MENU_REDRAW_MOTION
Redraw after moving the menu list.
Definition lib.h:62
MenuRedrawFlags menu_set_index(struct Menu *menu, int index)
Set the current selection in the Menu.
Definition menu.c:167
@ MUTT_SAVE_APPEND
Append to existing file.
Definition mutt_attach.h:60
static int save_without_prompting(FILE *fp, struct Body *b, struct Email *e)
Save the attachment, without prompting each time.
Definition recvattach.c:378
static int query_save_attachment(FILE *fp, struct Body *b, struct Email *e, char **directory)
Ask the user if we should save the attachment.
Definition recvattach.c:274
#define NONULL(x)
Definition string2.h:44
An email to which things will be attached.
Definition attach.h:36
FILE * fp
Used in the recvattach menu.
Definition attach.h:38
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ query_pipe_attachment()

static void query_pipe_attachment ( const char * command,
FILE * fp,
struct Body * b,
bool filter )
static

Ask the user if we should pipe the attachment.

Parameters
commandCommand to pipe the attachment to
fpFile handle to the attachment (OPTIONAL)
bAttachment
filterIs this command a filter?

Definition at line 537 of file recvattach.c.

538{
539 struct Buffer *tfile = buf_pool_get();
540
541 if (filter)
542 {
543 char warning[PATH_MAX + 256] = { 0 };
544 snprintf(warning, sizeof(warning),
545 _("WARNING! You are about to overwrite %s, continue?"), b->filename);
546 if (query_yesorno(warning, MUTT_NO) != MUTT_YES)
547 {
548 msgwin_clear_text(NULL);
549 buf_pool_release(&tfile);
550 return;
551 }
552 buf_mktemp(tfile);
553 }
554
555 if (mutt_pipe_attachment(fp, b, command, buf_string(tfile)))
556 {
557 if (filter)
558 {
562 mutt_message(_("Attachment filtered"));
563 }
564 }
565 else
566 {
567 if (filter && !buf_is_empty(tfile))
569 }
570 buf_pool_release(&tfile);
571}
int mutt_file_rename(const char *oldfile, const char *newfile)
Rename a file.
Definition file.c:1258
void msgwin_clear_text(struct MuttWindow *win)
Clear the text in the Message Window.
Definition msgwin.c:556
#define PATH_MAX
Definition mutt.h:49
int mutt_pipe_attachment(FILE *fp, struct Body *b, const char *path, const char *outfile)
Pipe an attachment to a command.
@ MUTT_NO
User answered 'No', or assume 'No'.
Definition quad.h:38
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition quad.h:39
enum QuadOption query_yesorno(const char *prompt, enum QuadOption def)
Ask the user a Yes/No question.
Definition question.c:329
void mutt_update_encoding(struct Body *b, struct ConfigSubset *sub)
Update the encoding type.
Definition sendlib.c:424
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pipe_attachment()

static void pipe_attachment ( FILE * fp,
struct Body * b,
struct State * state )
static

Pipe the attachment to a command.

Parameters
fpFile handle to the attachment (OPTIONAL)
bAttachment
stateFile state for decoding the attachment

Definition at line 579 of file recvattach.c.

580{
581 if (!state || !state->fp_out)
582 return;
583
584 FILE *fp_in = NULL;
585 FILE *fp_unstuff = NULL;
586 bool is_flowed = false, unlink_unstuff = false;
587 struct Buffer *unstuff_tempfile = NULL;
588
590 {
591 is_flowed = true;
592 unstuff_tempfile = buf_pool_get();
593 buf_mktemp(unstuff_tempfile);
594 }
595
596 if (fp)
597 {
598 state->fp_in = fp;
599
600 if (is_flowed)
601 {
602 fp_unstuff = mutt_file_fopen(buf_string(unstuff_tempfile), "w");
603 if (!fp_unstuff)
604 {
605 mutt_perror("mutt_file_fopen");
606 goto bail;
607 }
608 unlink_unstuff = true;
609
610 FILE *filter_fp = state->fp_out;
611 state->fp_out = fp_unstuff;
612 mutt_decode_attachment(b, state);
613 mutt_file_fclose(&fp_unstuff);
614 state->fp_out = filter_fp;
615
616 fp_unstuff = mutt_file_fopen(buf_string(unstuff_tempfile), "r");
617 if (!fp_unstuff)
618 {
619 mutt_perror("mutt_file_fopen");
620 goto bail;
621 }
622 mutt_file_copy_stream(fp_unstuff, filter_fp);
623 mutt_file_fclose(&fp_unstuff);
624 }
625 else
626 {
627 mutt_decode_attachment(b, state);
628 }
629 }
630 else
631 {
632 const char *infile = NULL;
633
634 if (is_flowed)
635 {
636 if (mutt_save_attachment(fp, b, buf_string(unstuff_tempfile), 0, NULL) == -1)
637 goto bail;
638 unlink_unstuff = true;
640 infile = buf_string(unstuff_tempfile);
641 }
642 else
643 {
644 infile = b->filename;
645 }
646
647 fp_in = mutt_file_fopen(infile, "r");
648 if (!fp_in)
649 {
650 mutt_perror("fopen");
651 goto bail;
652 }
653 mutt_file_copy_stream(fp_in, state->fp_out);
654 mutt_file_fclose(&fp_in);
655 }
656
657 const char *const c_attach_sep = cs_subset_string(NeoMutt->sub, "attach_sep");
658 if (c_attach_sep)
659 state_puts(state, c_attach_sep);
660
661bail:
662 mutt_file_fclose(&fp_unstuff);
663 mutt_file_fclose(&fp_in);
664
665 if (unlink_unstuff)
666 mutt_file_unlink(buf_string(unstuff_tempfile));
667 buf_pool_release(&unstuff_tempfile);
668}
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition file.c:224
#define mutt_perror(...)
Definition logging2.h:95
void mutt_decode_attachment(const struct Body *b, struct State *state)
Decode an email's attachment.
Definition handler.c:1943
#define state_puts(STATE, STR)
Definition state.h:64
FILE * fp_out
File to write to.
Definition state.h:56
FILE * fp_in
File to read from.
Definition state.h:55
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pipe_attachment_list()

static void pipe_attachment_list ( const char * command,
struct AttachPtrArray * aa,
bool filter,
struct State * state )
static

Pipe a list of attachments to a command.

Parameters
commandCommand to pipe the attachments to
aaSelected attachments
filterIs this command a filter?
stateFile state for decoding the attachments

Definition at line 677 of file recvattach.c.

679{
680 const bool c_attach_split = cs_subset_bool(NeoMutt->sub, "attach_split");
681 struct AttachPtr **app = NULL;
682 ARRAY_FOREACH(app, aa)
683 {
684 FILE *fp = (*app)->fp;
685 struct Body *b = (*app)->body;
686
687 if (!filter && !c_attach_split)
688 pipe_attachment(fp, b, state);
689 else
690 query_pipe_attachment(command, fp, b, filter);
691 }
692}
static void query_pipe_attachment(const char *command, FILE *fp, struct Body *b, bool filter)
Ask the user if we should pipe the attachment.
Definition recvattach.c:537
static void pipe_attachment(FILE *fp, struct Body *b, struct State *state)
Pipe the attachment to a command.
Definition recvattach.c:579
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_pipe_attachment_list()

void mutt_pipe_attachment_list ( struct AttachPtrArray * aa,
bool filter )

Pipe selected attachments to a command.

Parameters
aaSelected attachments
filterIs this command a filter?

Definition at line 699 of file recvattach.c.

700{
701 struct State state = { 0 };
702 struct Buffer *buf = NULL;
703
704 if (ARRAY_EMPTY(aa))
705 return;
706
707 struct AttachPtr **first = ARRAY_GET(aa, 0);
708 if (first && (*first)->fp)
709 filter = false; /* sanity check: we can't filter in the recv case yet */
710
711 buf = buf_pool_get();
712 /* perform charset conversion on text attachments when piping */
713 state.flags = STATE_CHARCONV;
714
715 if (mw_get_field((filter ? _("Filter through: ") : _("Pipe to: ")), buf,
717 {
718 goto cleanup;
719 }
720
721 if (buf_is_empty(buf))
722 goto cleanup;
723
724 expand_path(buf, false);
725
726 const bool c_attach_split = cs_subset_bool(NeoMutt->sub, "attach_split");
727 if (!filter && !c_attach_split)
728 {
729 mutt_endwin();
730 pid_t pid = filter_create(buf_string(buf), &state.fp_out, NULL, NULL,
731 NeoMutt->env);
732 pipe_attachment_list(buf_string(buf), aa, filter, &state);
733 mutt_file_fclose(&state.fp_out);
734 const bool c_wait_key = cs_subset_bool(NeoMutt->sub, "wait_key");
735 if ((filter_wait(pid) != 0) || c_wait_key)
737 }
738 else
739 {
740 pipe_attachment_list(buf_string(buf), aa, filter, &state);
741 }
742
743cleanup:
744 buf_pool_release(&buf);
745}
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition array.h:74
#define ARRAY_GET(head, idx)
Return the element at index.
Definition array.h:109
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition curs_lib.c:174
void mutt_endwin(void)
Shutdown curses.
Definition curs_lib.c:152
@ MUTT_COMP_NONE
No flags are set.
Definition wdata.h:46
@ HC_EXT_COMMAND
External commands.
Definition lib.h:56
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition filter.c:231
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err, char **envlist)
Set up filter program.
Definition filter.c:220
@ STATE_CHARCONV
Do character set conversions.
Definition state.h:41
static void pipe_attachment_list(const char *command, struct AttachPtrArray *aa, bool filter, struct State *state)
Pipe a list of attachments to a command.
Definition recvattach.c:677
char ** env
Private copy of the environment variables.
Definition neomutt.h:57
Keep track when processing files.
Definition state.h:54
StateFlags flags
Flags, e.g. STATE_DISPLAY.
Definition state.h:58
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ can_print()

static bool can_print ( struct AttachPtrArray * aa)
static

Do we know how to print this attachment type?

Parameters
aaSelected attachments
Return values
true(all) the Attachment(s) are printable

Definition at line 752 of file recvattach.c.

753{
754 char type[256] = { 0 };
755
756 struct AttachPtr **app = NULL;
757 ARRAY_FOREACH(app, aa)
758 {
759 struct Body *b = (*app)->body;
760 snprintf(type, sizeof(type), "%s/%s", BODY_TYPE(b), b->subtype);
761 if (!mailcap_lookup(b, type, sizeof(type), NULL, MUTT_MC_PRINT))
762 {
763 if (!mutt_istr_equal("text/plain", b->subtype) &&
764 !mutt_istr_equal("application/postscript", b->subtype))
765 {
766 if (!mutt_can_decode(b))
767 {
768 /* L10N: s gets replaced by a MIME type, e.g. "text/plain" or
769 application/octet-stream. */
770 mutt_error(_("I don't know how to print %s attachments"), type);
771 return false;
772 }
773 }
774 }
775 }
776 return true;
777}
#define mutt_error(...)
Definition logging2.h:94
bool mutt_can_decode(struct Body *b)
Will decoding the attachment produce any output.
Definition handler.c:1903
bool mailcap_lookup(struct Body *b, char *type, size_t typelen, struct MailcapEntry *entry, enum MailcapLookup opt)
Find given type in the list of mailcap files.
Definition mailcap.c:484
@ MUTT_MC_PRINT
Mailcap print field.
Definition mailcap.h:60
#define BODY_TYPE(body)
Get the type name of a body part.
Definition mime.h:93
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition string.c:678
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ print_attachment_list()

static void print_attachment_list ( struct AttachPtrArray * aa,
struct State * state )
static

Print a list of Attachments.

Parameters
aaSelected attachments
stateFile state for decoding the attachments

Definition at line 784 of file recvattach.c.

785{
786 char type[256] = { 0 };
787
788 const bool c_attach_split = cs_subset_bool(NeoMutt->sub, "attach_split");
789 const char *const c_attach_sep = cs_subset_string(NeoMutt->sub, "attach_sep");
790
791 struct AttachPtr **app = NULL;
792 ARRAY_FOREACH(app, aa)
793 {
794 FILE *fp = (*app)->fp;
795 struct Body *b = (*app)->body;
796
797 snprintf(type, sizeof(type), "%s/%s", BODY_TYPE(b), b->subtype);
798 if (!c_attach_split && !mailcap_lookup(b, type, sizeof(type), NULL, MUTT_MC_PRINT))
799 {
800 if (mutt_istr_equal("text/plain", b->subtype) ||
801 mutt_istr_equal("application/postscript", b->subtype))
802 {
803 pipe_attachment(fp, b, state);
804 }
805 else if (mutt_can_decode(b))
806 {
807 /* decode and print */
808
809 FILE *fp_in = NULL;
810 struct Buffer *newfile = buf_pool_get();
811
812 buf_mktemp(newfile);
813 if (mutt_decode_save_attachment(fp, b, buf_string(newfile),
815 {
816 if (!state->fp_out)
817 {
818 mutt_error("BUG in print_attachment_list(). Please report this. ");
820 buf_pool_release(&newfile);
821 return;
822 }
823
824 fp_in = mutt_file_fopen(buf_string(newfile), "r");
825 if (fp_in)
826 {
827 mutt_file_copy_stream(fp_in, state->fp_out);
828 mutt_file_fclose(&fp_in);
829 if (c_attach_sep)
830 state_puts(state, c_attach_sep);
831 }
832 }
834 buf_pool_release(&newfile);
835 }
836 }
837 else
838 {
840 }
841 }
842}
@ STATE_PRINTING
Are we printing? - STATE_DISPLAY "light".
Definition state.h:42
int mutt_decode_save_attachment(FILE *fp, struct Body *b, const char *path, StateFlags flags, enum SaveAttach opt)
Decode, then save an attachment.
int mutt_print_attachment(FILE *fp, struct Body *b)
Print out an attachment.
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_print_attachment_list()

void mutt_print_attachment_list ( struct AttachPtrArray * aa)

Print selected attachments.

Parameters
aaSelected attachments

Definition at line 848 of file recvattach.c.

849{
850 char prompt[128] = { 0 };
851 struct State state = { 0 };
852 const int count = ARRAY_SIZE(aa);
853
854 if (count == 0)
855 return;
856
857 snprintf(prompt, sizeof(prompt),
858 ngettext("Print attachment?", "Print %d attachments?", count), count);
859 if (query_quadoption(prompt, NeoMutt->sub, "print") != MUTT_YES)
860 return;
861
862 const bool c_attach_split = cs_subset_bool(NeoMutt->sub, "attach_split");
863 if (c_attach_split)
864 {
865 print_attachment_list(aa, &state);
866 }
867 else
868 {
869 if (!can_print(aa))
870 return;
871 mutt_endwin();
872 const char *const c_print_command = cs_subset_string(NeoMutt->sub, "print_command");
873 pid_t pid = filter_create(NONULL(c_print_command), &state.fp_out, NULL,
874 NULL, NeoMutt->env);
875 print_attachment_list(aa, &state);
876 mutt_file_fclose(&state.fp_out);
877 const bool c_wait_key = cs_subset_bool(NeoMutt->sub, "wait_key");
878 if ((filter_wait(pid) != 0) || c_wait_key)
880 }
881}
enum QuadOption query_quadoption(const char *prompt, struct ConfigSubset *sub, const char *name)
Ask the user a quad-question.
Definition question.c:384
static void print_attachment_list(struct AttachPtrArray *aa, struct State *state)
Print a list of Attachments.
Definition recvattach.c:784
static bool can_print(struct AttachPtrArray *aa)
Do we know how to print this attachment type?
Definition recvattach.c:752
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ recvattach_edit_content_type()

void recvattach_edit_content_type ( struct AttachCtx * actx,
struct Menu * menu,
struct Email * e )

Edit the content type of an attachment.

Parameters
actxAttachment context
menuMenu listing Attachments
eEmail

Definition at line 889 of file recvattach.c.

890{
891 struct AttachPtr *cur_att = current_attachment(actx, menu);
892 if (!mutt_edit_content_type(e, cur_att->body, cur_att->fp))
893 return;
894
895 /* The mutt_update_recvattach_menu() will overwrite any changes
896 * made to a decrypted cur_att->body, so warn the user. */
897 if (cur_att->decrypted)
898 {
899 mutt_message(_("Structural changes to decrypted attachments are not supported"));
900 mutt_sleep(1);
901 }
902 /* Editing the content type can rewrite the body structure. */
903 for (int i = 0; i < actx->idxlen; i++)
904 actx->idx[i]->body = NULL;
906 mutt_update_recvattach_menu(actx, menu, true);
907}
void mutt_actx_entries_free(struct AttachCtx *actx)
Free entries in an Attachment Context.
Definition attach.c:162
bool mutt_edit_content_type(struct Email *e, struct Body *b, FILE *fp)
Edit the content type of an attachment.
Definition external.c:1073
void mutt_sleep(short s)
Sleep for a while.
Definition muttlib.c:787
void mutt_update_recvattach_menu(struct AttachCtx *actx, struct Menu *menu, bool init)
Update the Attachment Menu.
struct AttachPtr * current_attachment(struct AttachCtx *actx, struct Menu *menu)
Get the current attachment.
Definition recvattach.c:71
short idxlen
Number of attachmentes.
Definition attach.h:70
bool decrypted
Not part of message as stored in the email->body.
Definition attach.h:44
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_attach_display_loop()

int mutt_attach_display_loop ( struct ConfigSubset * sub,
struct Menu * menu,
int op,
struct Email * e,
struct AttachCtx * actx,
bool recv )

Event loop for the Attachment menu.

Parameters
subConfig Subset
menuMenu listing Attachments
opOperation, e.g. OP_ATTACH_VIEW
eEmail
actxAttachment context
recvtrue if these are received attachments (rather than in compose)
Return values
numOperation performed

Definition at line 919 of file recvattach.c.

921{
922 do
923 {
924 switch (op)
925 {
926 case OP_DISPLAY_HEADERS:
927 bool_str_toggle(NeoMutt->sub, "weed", NULL);
929
930 case OP_ATTACH_VIEW:
931 {
932 struct AttachPtr *cur_att = current_attachment(actx, menu);
933 if (!cur_att->fp)
934 {
935 if (cur_att->body->type == TYPE_MULTIPART)
936 {
937 struct Body *b = cur_att->body->parts;
938 while (b && b->parts)
939 b = b->parts;
940 if (b)
941 cur_att = b->aptr;
942 }
943 }
944 op = mutt_view_attachment(cur_att->fp, cur_att->body, MUTT_VA_REGULAR,
945 e, actx, menu->win);
946 break;
947 }
948
949 case OP_NEXT_ENTRY:
950 case OP_MAIN_NEXT_UNDELETED: /* hack */
951 {
952 const int index = menu_get_index(menu) + 1;
953 if (index < menu->max)
954 {
955 menu_set_index(menu, index);
956 op = OP_ATTACH_VIEW;
957 }
958 else
959 {
960 op = OP_NULL;
961 }
962 break;
963 }
964
965 case OP_PREV_ENTRY:
966 case OP_MAIN_PREV_UNDELETED: /* hack */
967 {
968 const int index = menu_get_index(menu) - 1;
969 if (index >= 0)
970 {
971 menu_set_index(menu, index);
972 op = OP_ATTACH_VIEW;
973 }
974 else
975 {
976 op = OP_NULL;
977 }
978 break;
979 }
980
981 case OP_ATTACH_EDIT_TYPE:
982 {
983 struct AttachPtr *cur_att = current_attachment(actx, menu);
984 /* when we edit the content-type, we should redisplay the attachment
985 * immediately */
986 mutt_edit_content_type(e, cur_att->body, cur_att->fp);
987 if (recv)
988 recvattach_edit_content_type(actx, menu, e);
989 else
990 mutt_edit_content_type(e, cur_att->body, cur_att->fp);
991
993 op = OP_ATTACH_VIEW;
994 break;
995 }
996 /* functions which are passed through from the pager */
997 case OP_PIPE:
998 {
999 struct AttachPtr *cur_att = current_attachment(actx, menu);
1000 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
1001 ARRAY_ADD(&aa, cur_att);
1002 mutt_pipe_attachment_list(&aa, false);
1003 ARRAY_FREE(&aa);
1004 op = OP_ATTACH_VIEW;
1005 break;
1006 }
1007 case OP_ATTACH_PRINT:
1008 {
1009 struct AttachPtr *cur_att = current_attachment(actx, menu);
1010 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
1011 ARRAY_ADD(&aa, cur_att);
1013 ARRAY_FREE(&aa);
1014 op = OP_ATTACH_VIEW;
1015 break;
1016 }
1017 case OP_ATTACH_SAVE:
1018 {
1019 struct AttachPtr *cur_att = current_attachment(actx, menu);
1020 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
1021 ARRAY_ADD(&aa, cur_att);
1022 mutt_save_attachment_list(&aa, e, NULL);
1023 ARRAY_FREE(&aa);
1024 op = OP_ATTACH_VIEW;
1025 break;
1026 }
1027 case OP_CHECK_TRADITIONAL:
1029 {
1030 op = OP_NULL;
1031 break;
1032 }
1034
1035 case OP_ATTACH_COLLAPSE:
1036 if (recv)
1037 return op;
1039
1040 default:
1041 op = OP_NULL;
1042 }
1043 } while (op != OP_NULL);
1044
1045 return op;
1046}
#define ARRAY_ADD(head, elem)
Add an element at the end of the array.
Definition array.h:157
#define ARRAY_FREE(head)
Release all memory.
Definition array.h:209
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition array.h:58
int bool_str_toggle(struct ConfigSubset *sub, const char *name, struct Buffer *err)
Toggle the value of a bool.
Definition bool.c:231
@ MENU_REDRAW_INDEX
Redraw the index.
Definition lib.h:61
@ TYPE_MULTIPART
Type: 'multipart/*'.
Definition mime.h:37
#define FALLTHROUGH
Definition lib.h:117
int mutt_view_attachment(FILE *fp, struct Body *b, enum ViewAttachMode mode, struct Email *e, struct AttachCtx *actx, struct MuttWindow *win)
View an attachment.
@ MUTT_VA_REGULAR
View using default method.
Definition mutt_attach.h:45
#define PGP_TRADITIONAL_CHECKED
Email has a traditional (inline) signature.
Definition lib.h:108
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition lib.h:106
#define WithCrypto
Definition lib.h:132
void mutt_save_attachment_list(struct AttachPtrArray *aa, struct Email *e, struct Menu *menu)
Save a list of selected attachments.
Definition recvattach.c:425
void mutt_pipe_attachment_list(struct AttachPtrArray *aa, bool filter)
Pipe selected attachments to a command.
Definition recvattach.c:699
void mutt_print_attachment_list(struct AttachPtrArray *aa)
Print selected attachments.
Definition recvattach.c:848
void recvattach_edit_content_type(struct AttachCtx *actx, struct Menu *menu, struct Email *e)
Edit the content type of an attachment.
Definition recvattach.c:889
struct Body * parts
parts of a multipart or message/rfc822
Definition body.h:73
struct AttachPtr * aptr
Menu information, used in recvattach.c.
Definition body.h:75
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition email.h:43
struct MuttWindow * win
Window holding the Menu.
Definition lib.h:94
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_generate_recvattach_list()

void mutt_generate_recvattach_list ( struct AttachCtx * actx,
struct Email * e,
struct Body * b,
FILE * fp,
int parent_type,
int level,
bool decrypted )

Create a list of attachments.

Parameters
actxAttachment context
eEmail
bBody of email
fpFile to read from
parent_typeType, e.g. TYPE_MULTIPART
levelAttachment depth
decryptedTrue if attachment has been decrypted

Definition at line 1058 of file recvattach.c.

1061{
1062 struct Body *bp = NULL;
1063 struct Body *new_body = NULL;
1064 FILE *fp_new = NULL;
1066
1067 for (bp = b; bp; bp = bp->next)
1068 {
1069 bool need_secured = false;
1070 bool secured = false;
1071
1073 {
1074 need_secured = true;
1075
1076 if (type & SEC_ENCRYPT)
1077 {
1079 goto decrypt_failed;
1080
1081 if (e->env)
1083 }
1084
1085 secured = (crypt_smime_decrypt_mime(fp, &fp_new, bp, &new_body) == 0);
1086 /* If the decrypt/verify-opaque doesn't generate mime output, an empty
1087 * text/plain type will still be returned by mutt_read_mime_header().
1088 * We can't distinguish an actual part from a failure, so only use a
1089 * text/plain that results from a single top-level part. */
1090 if (secured && (new_body->type == TYPE_TEXT) &&
1091 mutt_istr_equal("plain", new_body->subtype) && ((b != bp) || bp->next))
1092 {
1093 mutt_body_free(&new_body);
1094 mutt_file_fclose(&fp_new);
1095 goto decrypt_failed;
1096 }
1097
1098 if (secured && (type & SEC_ENCRYPT))
1099 e->security |= SMIME_ENCRYPT;
1100 }
1101
1102 if (((WithCrypto & APPLICATION_PGP) != 0) &&
1104 {
1105 need_secured = true;
1106
1108 goto decrypt_failed;
1109
1110 secured = (crypt_pgp_decrypt_mime(fp, &fp_new, bp, &new_body) == 0);
1111
1112 if (secured)
1113 e->security |= PGP_ENCRYPT;
1114 }
1115
1116 if (need_secured && secured)
1117 {
1118 mutt_actx_add_fp(actx, fp_new);
1119 mutt_actx_add_body(actx, new_body);
1120 mutt_generate_recvattach_list(actx, e, new_body, fp_new, parent_type, level, 1);
1121 continue;
1122 }
1123
1124 decrypt_failed:
1125 /* Fall through and show the original parts if decryption fails */
1126 if (need_secured && !secured)
1127 mutt_error(_("Can't decrypt encrypted message"));
1128
1129 struct AttachPtr *ap = mutt_aptr_new();
1130 mutt_actx_add_attach(actx, ap);
1131
1132 ap->body = bp;
1133 ap->fp = fp;
1134 bp->aptr = ap;
1136 ap->level = level;
1137 ap->decrypted = decrypted;
1138
1139 if (mutt_is_message_type(bp->type, bp->subtype))
1140 {
1141 mutt_generate_recvattach_list(actx, bp->email, bp->parts, fp, bp->type,
1142 level + 1, decrypted);
1143 e->security |= bp->email->security;
1144 }
1145 else
1146 {
1147 mutt_generate_recvattach_list(actx, e, bp->parts, fp, bp->type, level + 1, decrypted);
1148 }
1149 }
1150}
void mutt_actx_add_attach(struct AttachCtx *actx, struct AttachPtr *attach)
Add an Attachment to an Attachment Context.
Definition attach.c:65
void mutt_actx_add_fp(struct AttachCtx *actx, FILE *fp_new)
Save a File handle to the Attachment Context.
Definition attach.c:121
struct AttachPtr * mutt_aptr_new(void)
Create a new Attachment Pointer.
Definition attach.c:40
void mutt_actx_add_body(struct AttachCtx *actx, struct Body *b)
Add an email body to an Attachment Context.
Definition attach.c:142
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition crypt.c:610
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition crypt.c:131
SecurityFlags mutt_is_multipart_encrypted(struct Body *b)
Does the message have encrypted parts?
Definition crypt.c:444
SecurityFlags mutt_is_malformed_multipart_pgp_encrypted(struct Body *b)
Check for malformed layout.
Definition crypt.c:505
int crypt_pgp_decrypt_mime(FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **b_dec)
Wrapper for CryptModuleSpecs::decrypt_mime()
Definition cryptglue.c:237
void crypt_smime_getkeys(struct Envelope *env)
Wrapper for CryptModuleSpecs::smime_getkeys()
Definition cryptglue.c:538
int crypt_smime_decrypt_mime(FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **b_dec)
Wrapper for CryptModuleSpecs::decrypt_mime()
Definition cryptglue.c:510
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition body.c:58
@ TYPE_TEXT
Type: 'text/*'.
Definition mime.h:38
uint16_t SecurityFlags
Definition lib.h:104
@ SEC_ENCRYPT
Email is encrypted.
Definition lib.h:92
#define PGP_ENCRYPT
Email is PGP encrypted.
Definition lib.h:112
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition lib.h:107
#define SMIME_ENCRYPT
Email is S/MIME encrypted.
Definition lib.h:118
void mutt_generate_recvattach_list(struct AttachCtx *actx, struct Email *e, struct Body *b, FILE *fp, int parent_type, int level, bool decrypted)
Create a list of attachments.
int parent_type
Type of parent attachment, e.g. TYPE_MULTIPART.
Definition attach.h:39
struct Envelope * env
Envelope information.
Definition email.h:68
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_attach_init()

void mutt_attach_init ( struct AttachCtx * actx)

Create a new Attachment context.

Parameters
actxAttachment context

Definition at line 1156 of file recvattach.c.

1157{
1158 /* Collapse the attachments if '$digest_collapse' is set AND if...
1159 * the outer container is of type 'multipart/digest' */
1160 bool digest = mutt_istr_equal(actx->email->body->subtype, "digest");
1161
1162 const bool c_digest_collapse = cs_subset_bool(NeoMutt->sub, "digest_collapse");
1163 for (int i = 0; i < actx->idxlen; i++)
1164 {
1165 actx->idx[i]->body->tagged = false;
1166
1167 /* OR an inner container is of type 'multipart/digest' */
1168 actx->idx[i]->collapsed = (c_digest_collapse &&
1169 (digest ||
1170 ((actx->idx[i]->body->type == TYPE_MULTIPART) &&
1171 mutt_istr_equal(actx->idx[i]->body->subtype, "digest"))));
1172 }
1173}
struct Email * email
Used by recvattach for updating.
Definition attach.h:66
bool tagged
This attachment is tagged.
Definition body.h:90
struct Body * body
List of MIME parts.
Definition email.h:69
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_update_recvattach_menu()

void mutt_update_recvattach_menu ( struct AttachCtx * actx,
struct Menu * menu,
bool init )

Update the Attachment Menu.

Parameters
actxAttachment context
menuMenu listing Attachments
initIf true, create a new Attachments context

Definition at line 1181 of file recvattach.c.

1182{
1183 if (init)
1184 {
1185 mutt_generate_recvattach_list(actx, actx->email, actx->email->body,
1186 actx->fp_root, -1, 0, 0);
1187 mutt_attach_init(actx);
1188 }
1189
1190 mutt_update_tree(actx);
1191
1192 menu->max = actx->vcount;
1193
1194 const int index = menu_get_index(menu);
1195 if (index >= menu->max)
1196 menu_set_index(menu, menu->max - 1);
1198}
void mutt_attach_init(struct AttachCtx *actx)
Create a new Attachment context.
void mutt_update_tree(struct AttachCtx *actx)
Refresh the list of attachments.
Definition recvattach.c:118
FILE * fp_root
Used by recvattach for updating.
Definition attach.h:67
int max
Number of entries in the menu.
Definition lib.h:88
+ Here is the call graph for this function:
+ Here is the caller graph for this function: