NeoMutt  2025-12-11-911-gd8d604
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:155
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, rindex, curlevel;
88
89 vindex = 0;
90 rindex = 0;
91
92 while (rindex < actx->idxlen)
93 {
94 actx->v2r[vindex++] = rindex;
95 if (actx->idx[rindex]->collapsed)
96 {
97 curlevel = actx->idx[rindex]->level;
98 do
99 {
100 rindex++;
101 } while ((rindex < actx->idxlen) && (actx->idx[rindex]->level > curlevel));
102 }
103 else
104 {
105 rindex++;
106 }
107 }
108
109 actx->vcount = vindex;
110}
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 116 of file recvattach.c.

117{
118 char buf[256] = { 0 };
119 char *s = NULL;
120
121 mutt_update_v2r(actx);
122
123 for (int vindex = 0; vindex < actx->vcount; vindex++)
124 {
125 const int rindex = actx->v2r[vindex];
126 actx->idx[rindex]->num = vindex;
127 if ((2 * (actx->idx[rindex]->level + 2)) < sizeof(buf))
128 {
129 if (actx->idx[rindex]->level)
130 {
131 s = buf + 2 * (actx->idx[rindex]->level - 1);
132 *s++ = (actx->idx[rindex]->body->next) ? MUTT_TREE_LTEE : MUTT_TREE_LLCORNER;
133 *s++ = MUTT_TREE_HLINE;
134 *s++ = MUTT_TREE_RARROW;
135 }
136 else
137 {
138 s = buf;
139 }
140 *s = '\0';
141 }
142
143 if (actx->idx[rindex]->tree)
144 {
145 if (!mutt_str_equal(actx->idx[rindex]->tree, buf))
146 mutt_str_replace(&actx->idx[rindex]->tree, buf);
147 }
148 else
149 {
150 actx->idx[rindex]->tree = mutt_str_dup(buf);
151 }
152
153 if (((2 * (actx->idx[rindex]->level + 2)) < sizeof(buf)) &&
154 actx->idx[rindex]->level)
155 {
156 s = buf + 2 * (actx->idx[rindex]->level - 1);
157 *s++ = (actx->idx[rindex]->body->next) ? MUTT_TREE_VLINE : MUTT_TREE_SPACE;
158 *s++ = MUTT_TREE_SPACE;
159 }
160 }
161}
@ 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:665
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 167 of file recvattach.c.

168{
169 if (buf_is_empty(buf) || (buf_at(buf, 0) == '/'))
170 return;
171
172 struct Buffer *tmp = buf_pool_get();
173 const char *const c_attach_save_dir = cs_subset_path(NeoMutt->sub, "attach_save_dir");
174 if (c_attach_save_dir)
175 {
176 buf_addstr(tmp, c_attach_save_dir);
177 if (tmp->dptr[-1] != '/')
178 buf_addch(tmp, '/');
179 }
180 else
181 {
182 buf_addstr(tmp, "./");
183 }
184
185 buf_addstr(tmp, buf_string(buf));
186 buf_copy(buf, tmp);
187 buf_pool_release(&tmp);
188}
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:291
char buf_at(const struct Buffer *buf, size_t offset)
Return the character at the given offset.
Definition buffer.c:668
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition buffer.c:241
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition buffer.c:226
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition buffer.c:601
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 195 of file recvattach.c.

196{
197 return (b->email && (b->encoding != ENC_BASE64) && (b->encoding != ENC_QUOTED_PRINTABLE) &&
199}
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition parse.c:1556
@ 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 226 of file recvattach.c.

228{
229 int rc = -1;
230
232 {
233 struct Body b_fake = { 0 };
234
235 struct Buffer *tempfile = buf_pool_get();
236 buf_mktemp(tempfile);
237
238 rc = mutt_save_attachment(fp, b, buf_string(tempfile), MUTT_SAVE_NONE, e);
239 if (rc != 0)
240 goto cleanup;
241
243
244 /* Now "really" save it. Send mode does this without touching anything,
245 * so force send-mode. */
246 memset(&b_fake, 0, sizeof(struct Body));
247 b_fake.filename = tempfile->data;
248 rc = mutt_save_attachment(NULL, &b_fake, path, flags, e);
249
250 mutt_file_unlink(buf_string(tempfile));
251
252 cleanup:
253 buf_pool_release(&tempfile);
254 }
255 else
256 {
257 rc = mutt_save_attachment(fp, b, path, flags, e);
258 }
259
260 return rc;
261}
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:522
bool mutt_rfc3676_is_format_flowed(struct Body *b)
Is the Email "format-flowed"?
Definition rfc3676.c:398
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 272 of file recvattach.c.

273{
274 char *prompt = NULL;
275 enum SaveAttach opt = MUTT_SAVE_NONE;
276 int rc = -1;
277
278 struct Buffer *buf = buf_pool_get();
279 struct Buffer *tfile = buf_pool_get();
280
281 if (b->filename)
282 {
283 if (directory && *directory)
284 {
285 buf_concat_path(buf, *directory, mutt_path_basename(b->filename));
286 }
287 else
288 {
289 buf_strcpy(buf, b->filename);
290 }
291 }
292 else if (has_a_message(b))
293 {
294 mutt_default_save(buf, b->email);
295 }
296
297 prepend_savedir(buf);
298
299 prompt = _("Save to file: ");
300 while (prompt)
301 {
302 struct FileCompletionData cdata = { false, NULL, NULL, NULL, NULL };
303 if ((mw_get_field(prompt, buf, MUTT_COMP_CLEAR, HC_FILE, &CompleteFileOps, &cdata) != 0) ||
304 buf_is_empty(buf))
305 {
306 goto cleanup;
307 }
308
309 prompt = NULL;
310 expand_path(buf, false);
311
312 bool is_message = (fp && has_a_message(b));
313
314 if (is_message)
315 {
316 struct stat st = { 0 };
317
318 /* check to make sure that this file is really the one the user wants */
319 rc = mutt_save_confirm(buf_string(buf), &st);
320 if (rc == 1)
321 {
322 prompt = _("Save to file: ");
323 continue;
324 }
325 else if (rc == -1)
326 {
327 goto cleanup;
328 }
329 buf_copy(tfile, buf);
330 }
331 else
332 {
333 rc = mutt_check_overwrite(b->filename, buf_string(buf), tfile, &opt, directory);
334 if (rc == -1)
335 {
336 goto cleanup;
337 }
338 else if (rc == 1)
339 {
340 prompt = _("Save to file: ");
341 continue;
342 }
343 }
344
345 mutt_message(_("Saving..."));
346 if (save_attachment_flowed_helper(fp, b, buf_string(tfile), opt,
347 (e || !is_message) ? e : b->email) == 0)
348 {
349 // This uses ngettext to avoid duplication of messages
350 int num = 1;
351 mutt_message(ngettext("Attachment saved", "%d attachments saved", num), num);
352 rc = 0;
353 goto cleanup;
354 }
355 else
356 {
357 prompt = _("Save to file: ");
358 continue;
359 }
360 }
361
362cleanup:
363 buf_pool_release(&buf);
364 buf_pool_release(&tfile);
365 return rc;
366}
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:395
size_t buf_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition buffer.c:509
@ 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:226
static void prepend_savedir(struct Buffer *buf)
Add $attach_save_dir to the beginning of a path.
Definition recvattach.c:167
static bool has_a_message(struct Body *b)
Determine if the Body has a message (to save)
Definition recvattach.c:195
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 376 of file recvattach.c.

377{
378 enum SaveAttach opt = MUTT_SAVE_NONE;
379 int rc = -1;
380 struct Buffer *buf = buf_pool_get();
381 struct Buffer *tfile = buf_pool_get();
382
383 if (b->filename)
384 {
385 buf_strcpy(buf, b->filename);
386 }
387 else if (has_a_message(b))
388 {
389 mutt_default_save(buf, b->email);
390 }
391
392 prepend_savedir(buf);
393 expand_path(buf, false);
394
395 bool is_message = (fp && has_a_message(b));
396
397 if (is_message)
398 {
399 buf_copy(tfile, buf);
400 }
401 else
402 {
403 rc = mutt_check_overwrite(b->filename, buf_string(buf), tfile, &opt, NULL);
404 if (rc == -1) // abort or cancel
405 goto cleanup;
406 }
407
408 rc = save_attachment_flowed_helper(fp, b, buf_string(tfile), opt,
409 (e || !is_message) ? e : b->email);
410
411cleanup:
412 buf_pool_release(&buf);
413 buf_pool_release(&tfile);
414 return rc;
415}
+ 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 423 of file recvattach.c.

424{
425 char *directory = NULL;
426 int rc = 1;
427 int last = menu ? menu_get_index(menu) : 0;
428 FILE *fp_out = NULL;
429 int saved_attachments = 0;
430
431 struct Buffer *buf = buf_pool_get();
432 struct Buffer *tfile = buf_pool_get();
433
434 const bool c_attach_split = cs_subset_bool(NeoMutt->sub, "attach_split");
435 const char *const c_attach_sep = cs_subset_string(NeoMutt->sub, "attach_sep");
436 const bool c_attach_save_without_prompting = cs_subset_bool(NeoMutt->sub, "attach_save_without_prompting");
437
438 struct AttachPtr **app = NULL;
439 ARRAY_FOREACH(app, aa)
440 {
441 FILE *fp = (*app)->fp;
442 struct Body *b = (*app)->body;
443
444 /* Iterate through attachments.
445 * Behavior depends on attach_split: if true, save each to its own file;
446 * if false, concatenate all into one file with optional separator. */
447 if (c_attach_split)
448 {
449 if (menu)
450 {
451 menu_set_index(menu, (*app)->num);
453 menu_redraw(menu);
454 }
455 if (c_attach_save_without_prompting)
456 {
457 // Save each file, with no prompting, using the configured 'AttachSaveDir'
458 rc = save_without_prompting(fp, b, e);
459 if (rc == 0)
460 saved_attachments++;
461 }
462 else
463 {
464 // Save each file, prompting the user for the location each time.
465 if (query_save_attachment(fp, b, e, &directory) == -1)
466 break;
467 }
468 }
469 else
470 {
471 enum SaveAttach opt = MUTT_SAVE_NONE;
472
473 if (buf_is_empty(buf))
474 {
476 prepend_savedir(buf);
477
478 struct FileCompletionData cdata = { false, NULL, NULL, NULL, NULL };
479 if ((mw_get_field(_("Save to file: "), buf, MUTT_COMP_CLEAR, HC_FILE,
480 &CompleteFileOps, &cdata) != 0) ||
481 buf_is_empty(buf))
482 {
483 goto cleanup;
484 }
485 expand_path(buf, false);
486 if (mutt_check_overwrite(b->filename, buf_string(buf), tfile, &opt, NULL))
487 goto cleanup;
488 }
489 else
490 {
491 opt = MUTT_SAVE_APPEND;
492 }
493
494 rc = save_attachment_flowed_helper(fp, b, buf_string(tfile), opt, e);
495 if ((rc == 0) && c_attach_sep && (fp_out = mutt_file_fopen(buf_string(tfile), "a")))
496 {
497 fprintf(fp_out, "%s", c_attach_sep);
498 mutt_file_fclose(&fp_out);
499 }
500 }
501 }
502
503 FREE(&directory);
504
505 if ((ARRAY_SIZE(aa) > 1) && menu)
506 {
507 menu_set_index(menu, last);
509 }
510
511 if (rc == 0)
512 {
513 if (!c_attach_split)
514 saved_attachments = 1;
515
516 if (!c_attach_split || c_attach_save_without_prompting)
517 {
518 mutt_message(ngettext("Attachment saved", "%d attachments saved", saved_attachments),
519 saved_attachments);
520 }
521 }
522
523cleanup:
524 buf_pool_release(&buf);
525 buf_pool_release(&tfile);
526}
#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:499
#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:179
@ 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:169
@ 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:376
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:272
#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 535 of file recvattach.c.

536{
537 struct Buffer *tfile = buf_pool_get();
538
539 if (filter)
540 {
541 char warning[PATH_MAX + 256];
542 snprintf(warning, sizeof(warning),
543 _("WARNING! You are about to overwrite %s, continue?"), b->filename);
544 if (query_yesorno(warning, MUTT_NO) != MUTT_YES)
545 {
546 msgwin_clear_text(NULL);
547 buf_pool_release(&tfile);
548 return;
549 }
550 buf_mktemp(tfile);
551 }
552
553 if (mutt_pipe_attachment(fp, b, command, buf_string(tfile)))
554 {
555 if (filter)
556 {
560 mutt_message(_("Attachment filtered"));
561 }
562 }
563 else
564 {
565 if (filter && !buf_is_empty(tfile))
567 }
568 buf_pool_release(&tfile);
569}
int mutt_file_rename(const char *oldfile, const char *newfile)
Rename a file.
Definition file.c:1257
void msgwin_clear_text(struct MuttWindow *win)
Clear the text in the Message Window.
Definition msgwin.c:554
#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:421
+ 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 577 of file recvattach.c.

578{
579 if (!state || !state->fp_out)
580 return;
581
582 FILE *fp_in = NULL;
583 FILE *fp_unstuff = NULL;
584 bool is_flowed = false, unlink_unstuff = false;
585 struct Buffer *unstuff_tempfile = NULL;
586
588 {
589 is_flowed = true;
590 unstuff_tempfile = buf_pool_get();
591 buf_mktemp(unstuff_tempfile);
592 }
593
594 if (fp)
595 {
596 state->fp_in = fp;
597
598 if (is_flowed)
599 {
600 fp_unstuff = mutt_file_fopen(buf_string(unstuff_tempfile), "w");
601 if (!fp_unstuff)
602 {
603 mutt_perror("mutt_file_fopen");
604 goto bail;
605 }
606 unlink_unstuff = true;
607
608 FILE *filter_fp = state->fp_out;
609 state->fp_out = fp_unstuff;
610 mutt_decode_attachment(b, state);
611 mutt_file_fclose(&fp_unstuff);
612 state->fp_out = filter_fp;
613
614 fp_unstuff = mutt_file_fopen(buf_string(unstuff_tempfile), "r");
615 if (!fp_unstuff)
616 {
617 mutt_perror("mutt_file_fopen");
618 goto bail;
619 }
620 mutt_file_copy_stream(fp_unstuff, filter_fp);
621 mutt_file_fclose(&fp_unstuff);
622 }
623 else
624 {
625 mutt_decode_attachment(b, state);
626 }
627 }
628 else
629 {
630 const char *infile = NULL;
631
632 if (is_flowed)
633 {
634 if (mutt_save_attachment(fp, b, buf_string(unstuff_tempfile), 0, NULL) == -1)
635 goto bail;
636 unlink_unstuff = true;
638 infile = buf_string(unstuff_tempfile);
639 }
640 else
641 {
642 infile = b->filename;
643 }
644
645 fp_in = mutt_file_fopen(infile, "r");
646 if (!fp_in)
647 {
648 mutt_perror("fopen");
649 goto bail;
650 }
651 mutt_file_copy_stream(fp_in, state->fp_out);
652 mutt_file_fclose(&fp_in);
653 }
654
655 const char *const c_attach_sep = cs_subset_string(NeoMutt->sub, "attach_sep");
656 if (c_attach_sep)
657 state_puts(state, c_attach_sep);
658
659bail:
660 mutt_file_fclose(&fp_unstuff);
661 mutt_file_fclose(&fp_in);
662
663 if (unlink_unstuff)
664 mutt_file_unlink(buf_string(unstuff_tempfile));
665 buf_pool_release(&unstuff_tempfile);
666}
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:1938
#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 675 of file recvattach.c.

677{
678 const bool c_attach_split = cs_subset_bool(NeoMutt->sub, "attach_split");
679 struct AttachPtr **app = NULL;
680 ARRAY_FOREACH(app, aa)
681 {
682 FILE *fp = (*app)->fp;
683 struct Body *b = (*app)->body;
684
685 if (!filter && !c_attach_split)
686 pipe_attachment(fp, b, state);
687 else
688 query_pipe_attachment(command, fp, b, filter);
689 }
690}
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:535
static void pipe_attachment(FILE *fp, struct Body *b, struct State *state)
Pipe the attachment to a command.
Definition recvattach.c:577
+ 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 697 of file recvattach.c.

698{
699 struct State state = { 0 };
700 struct Buffer *buf = NULL;
701
702 if (ARRAY_EMPTY(aa))
703 return;
704
705 struct AttachPtr **first = ARRAY_GET(aa, 0);
706 if (first && (*first)->fp)
707 filter = false; /* sanity check: we can't filter in the recv case yet */
708
709 buf = buf_pool_get();
710 /* perform charset conversion on text attachments when piping */
711 state.flags = STATE_CHARCONV;
712
713 if (mw_get_field((filter ? _("Filter through: ") : _("Pipe to: ")), buf,
715 {
716 goto cleanup;
717 }
718
719 if (buf_is_empty(buf))
720 goto cleanup;
721
722 expand_path(buf, false);
723
724 const bool c_attach_split = cs_subset_bool(NeoMutt->sub, "attach_split");
725 if (!filter && !c_attach_split)
726 {
727 mutt_endwin();
728 pid_t pid = filter_create(buf_string(buf), &state.fp_out, NULL, NULL,
729 NeoMutt->env);
730 pipe_attachment_list(buf_string(buf), aa, filter, &state);
731 mutt_file_fclose(&state.fp_out);
732 const bool c_wait_key = cs_subset_bool(NeoMutt->sub, "wait_key");
733 if ((filter_wait(pid) != 0) || c_wait_key)
735 }
736 else
737 {
738 pipe_attachment_list(buf_string(buf), aa, filter, &state);
739 }
740
741cleanup:
742 buf_pool_release(&buf);
743}
#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:175
void mutt_endwin(void)
Shutdown curses.
Definition curs_lib.c:153
@ 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:228
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:217
@ 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:675
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 750 of file recvattach.c.

751{
752 char type[256] = { 0 };
753
754 struct AttachPtr **app = NULL;
755 ARRAY_FOREACH(app, aa)
756 {
757 struct Body *b = (*app)->body;
758 snprintf(type, sizeof(type), "%s/%s", BODY_TYPE(b), b->subtype);
759 if (!mailcap_lookup(b, type, sizeof(type), NULL, MUTT_MC_PRINT))
760 {
761 if (!mutt_istr_equal("text/plain", b->subtype) &&
762 !mutt_istr_equal("application/postscript", b->subtype))
763 {
764 if (!mutt_can_decode(b))
765 {
766 /* L10N: s gets replaced by a MIME type, e.g. "text/plain" or
767 application/octet-stream. */
768 mutt_error(_("I don't know how to print %s attachments"), type);
769 return false;
770 }
771 }
772 }
773 }
774 return true;
775}
#define mutt_error(...)
Definition logging2.h:94
bool mutt_can_decode(struct Body *b)
Will decoding the attachment produce any output.
Definition handler.c:1898
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:677
+ 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 782 of file recvattach.c.

783{
784 char type[256] = { 0 };
785
786 const bool c_attach_split = cs_subset_bool(NeoMutt->sub, "attach_split");
787 const char *const c_attach_sep = cs_subset_string(NeoMutt->sub, "attach_sep");
788
789 struct AttachPtr **app = NULL;
790 ARRAY_FOREACH(app, aa)
791 {
792 FILE *fp = (*app)->fp;
793 struct Body *b = (*app)->body;
794
795 snprintf(type, sizeof(type), "%s/%s", BODY_TYPE(b), b->subtype);
796 if (!c_attach_split && !mailcap_lookup(b, type, sizeof(type), NULL, MUTT_MC_PRINT))
797 {
798 if (mutt_istr_equal("text/plain", b->subtype) ||
799 mutt_istr_equal("application/postscript", b->subtype))
800 {
801 pipe_attachment(fp, b, state);
802 }
803 else if (mutt_can_decode(b))
804 {
805 /* decode and print */
806
807 FILE *fp_in = NULL;
808 struct Buffer *newfile = buf_pool_get();
809
810 buf_mktemp(newfile);
811 if (mutt_decode_save_attachment(fp, b, buf_string(newfile),
813 {
814 if (!state->fp_out)
815 {
816 mutt_error("BUG in print_attachment_list(). Please report this. ");
818 buf_pool_release(&newfile);
819 return;
820 }
821
822 fp_in = mutt_file_fopen(buf_string(newfile), "r");
823 if (fp_in)
824 {
825 mutt_file_copy_stream(fp_in, state->fp_out);
826 mutt_file_fclose(&fp_in);
827 if (c_attach_sep)
828 state_puts(state, c_attach_sep);
829 }
830 }
832 buf_pool_release(&newfile);
833 }
834 }
835 else
836 {
838 }
839 }
840}
@ 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 846 of file recvattach.c.

847{
848 char prompt[128] = { 0 };
849 struct State state = { 0 };
850 const int count = ARRAY_SIZE(aa);
851
852 if (count == 0)
853 return;
854
855 snprintf(prompt, sizeof(prompt),
856 ngettext("Print attachment?", "Print %d attachments?", count), count);
857 if (query_quadoption(prompt, NeoMutt->sub, "print") != MUTT_YES)
858 return;
859
860 const bool c_attach_split = cs_subset_bool(NeoMutt->sub, "attach_split");
861 if (c_attach_split)
862 {
863 print_attachment_list(aa, &state);
864 }
865 else
866 {
867 if (!can_print(aa))
868 return;
869 mutt_endwin();
870 const char *const c_print_command = cs_subset_string(NeoMutt->sub, "print_command");
871 pid_t pid = filter_create(NONULL(c_print_command), &state.fp_out, NULL,
872 NULL, NeoMutt->env);
873 print_attachment_list(aa, &state);
874 mutt_file_fclose(&state.fp_out);
875 const bool c_wait_key = cs_subset_bool(NeoMutt->sub, "wait_key");
876 if ((filter_wait(pid) != 0) || c_wait_key)
878 }
879}
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:782
static bool can_print(struct AttachPtrArray *aa)
Do we know how to print this attachment type?
Definition recvattach.c:750
+ 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 887 of file recvattach.c.

888{
889 struct AttachPtr *cur_att = current_attachment(actx, menu);
890 if (!mutt_edit_content_type(e, cur_att->body, cur_att->fp))
891 return;
892
893 /* The mutt_update_recvattach_menu() will overwrite any changes
894 * made to a decrypted cur_att->body, so warn the user. */
895 if (cur_att->decrypted)
896 {
897 mutt_message(_("Structural changes to decrypted attachments are not supported"));
898 mutt_sleep(1);
899 }
900 /* Editing the content type can rewrite the body structure. */
901 for (int i = 0; i < actx->idxlen; i++)
902 actx->idx[i]->body = NULL;
904 mutt_update_recvattach_menu(actx, menu, true);
905}
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 917 of file recvattach.c.

919{
920 do
921 {
922 switch (op)
923 {
924 case OP_DISPLAY_HEADERS:
925 bool_str_toggle(NeoMutt->sub, "weed", NULL);
927
928 case OP_ATTACH_VIEW:
929 {
930 struct AttachPtr *cur_att = current_attachment(actx, menu);
931 if (!cur_att->fp)
932 {
933 if (cur_att->body->type == TYPE_MULTIPART)
934 {
935 struct Body *b = cur_att->body->parts;
936 while (b && b->parts)
937 b = b->parts;
938 if (b)
939 cur_att = b->aptr;
940 }
941 }
942 op = mutt_view_attachment(cur_att->fp, cur_att->body, MUTT_VA_REGULAR,
943 e, actx, menu->win);
944 break;
945 }
946
947 case OP_NEXT_ENTRY:
948 case OP_MAIN_NEXT_UNDELETED: /* hack */
949 {
950 const int index = menu_get_index(menu) + 1;
951 if (index < menu->max)
952 {
953 menu_set_index(menu, index);
954 op = OP_ATTACH_VIEW;
955 }
956 else
957 {
958 op = OP_NULL;
959 }
960 break;
961 }
962
963 case OP_PREV_ENTRY:
964 case OP_MAIN_PREV_UNDELETED: /* hack */
965 {
966 const int index = menu_get_index(menu) - 1;
967 if (index >= 0)
968 {
969 menu_set_index(menu, index);
970 op = OP_ATTACH_VIEW;
971 }
972 else
973 {
974 op = OP_NULL;
975 }
976 break;
977 }
978
979 case OP_ATTACH_EDIT_TYPE:
980 {
981 struct AttachPtr *cur_att = current_attachment(actx, menu);
982 /* when we edit the content-type, we should redisplay the attachment
983 * immediately */
984 mutt_edit_content_type(e, cur_att->body, cur_att->fp);
985 if (recv)
986 recvattach_edit_content_type(actx, menu, e);
987 else
988 mutt_edit_content_type(e, cur_att->body, cur_att->fp);
989
991 op = OP_ATTACH_VIEW;
992 break;
993 }
994 /* functions which are passed through from the pager */
995 case OP_PIPE:
996 {
997 struct AttachPtr *cur_att = current_attachment(actx, menu);
998 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
999 ARRAY_ADD(&aa, cur_att);
1000 mutt_pipe_attachment_list(&aa, false);
1001 ARRAY_FREE(&aa);
1002 op = OP_ATTACH_VIEW;
1003 break;
1004 }
1005 case OP_ATTACH_PRINT:
1006 {
1007 struct AttachPtr *cur_att = current_attachment(actx, menu);
1008 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
1009 ARRAY_ADD(&aa, cur_att);
1011 ARRAY_FREE(&aa);
1012 op = OP_ATTACH_VIEW;
1013 break;
1014 }
1015 case OP_ATTACH_SAVE:
1016 {
1017 struct AttachPtr *cur_att = current_attachment(actx, menu);
1018 struct AttachPtrArray aa = ARRAY_HEAD_INITIALIZER;
1019 ARRAY_ADD(&aa, cur_att);
1020 mutt_save_attachment_list(&aa, e, NULL);
1021 ARRAY_FREE(&aa);
1022 op = OP_ATTACH_VIEW;
1023 break;
1024 }
1025 case OP_CHECK_TRADITIONAL:
1027 {
1028 op = OP_NULL;
1029 break;
1030 }
1032
1033 case OP_ATTACH_COLLAPSE:
1034 if (recv)
1035 return op;
1037
1038 default:
1039 op = OP_NULL;
1040 }
1041 } while (op != OP_NULL);
1042
1043 return op;
1044}
#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:423
void mutt_pipe_attachment_list(struct AttachPtrArray *aa, bool filter)
Pipe selected attachments to a command.
Definition recvattach.c:697
void mutt_print_attachment_list(struct AttachPtrArray *aa)
Print selected attachments.
Definition recvattach.c:846
void recvattach_edit_content_type(struct AttachCtx *actx, struct Menu *menu, struct Email *e)
Edit the content type of an attachment.
Definition recvattach.c:887
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 1056 of file recvattach.c.

1059{
1060 struct Body *bp = NULL;
1061 struct Body *new_body = NULL;
1062 FILE *fp_new = NULL;
1064
1065 for (bp = b; bp; bp = bp->next)
1066 {
1067 bool need_secured = false;
1068 bool secured = false;
1069
1071 {
1072 need_secured = true;
1073
1074 if (type & SEC_ENCRYPT)
1075 {
1077 goto decrypt_failed;
1078
1079 if (e->env)
1081 }
1082
1083 secured = (crypt_smime_decrypt_mime(fp, &fp_new, bp, &new_body) == 0);
1084 /* If the decrypt/verify-opaque doesn't generate mime output, an empty
1085 * text/plain type will still be returned by mutt_read_mime_header().
1086 * We can't distinguish an actual part from a failure, so only use a
1087 * text/plain that results from a single top-level part. */
1088 if (secured && (new_body->type == TYPE_TEXT) &&
1089 mutt_istr_equal("plain", new_body->subtype) && ((b != bp) || bp->next))
1090 {
1091 mutt_body_free(&new_body);
1092 mutt_file_fclose(&fp_new);
1093 goto decrypt_failed;
1094 }
1095
1096 if (secured && (type & SEC_ENCRYPT))
1097 e->security |= SMIME_ENCRYPT;
1098 }
1099
1100 if (((WithCrypto & APPLICATION_PGP) != 0) &&
1102 {
1103 need_secured = true;
1104
1106 goto decrypt_failed;
1107
1108 secured = (crypt_pgp_decrypt_mime(fp, &fp_new, bp, &new_body) == 0);
1109
1110 if (secured)
1111 e->security |= PGP_ENCRYPT;
1112 }
1113
1114 if (need_secured && secured)
1115 {
1116 mutt_actx_add_fp(actx, fp_new);
1117 mutt_actx_add_body(actx, new_body);
1118 mutt_generate_recvattach_list(actx, e, new_body, fp_new, parent_type, level, 1);
1119 continue;
1120 }
1121
1122 decrypt_failed:
1123 /* Fall through and show the original parts if decryption fails */
1124 if (need_secured && !secured)
1125 mutt_error(_("Can't decrypt encrypted message"));
1126
1127 struct AttachPtr *ap = mutt_aptr_new();
1128 mutt_actx_add_attach(actx, ap);
1129
1130 ap->body = bp;
1131 ap->fp = fp;
1132 bp->aptr = ap;
1134 ap->level = level;
1135 ap->decrypted = decrypted;
1136
1137 if (mutt_is_message_type(bp->type, bp->subtype))
1138 {
1139 mutt_generate_recvattach_list(actx, bp->email, bp->parts, fp, bp->type,
1140 level + 1, decrypted);
1141 e->security |= bp->email->security;
1142 }
1143 else
1144 {
1145 mutt_generate_recvattach_list(actx, e, bp->parts, fp, bp->type, level + 1, decrypted);
1146 }
1147 }
1148}
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:609
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:443
SecurityFlags mutt_is_malformed_multipart_pgp_encrypted(struct Body *b)
Check for malformed layout.
Definition crypt.c:504
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 1154 of file recvattach.c.

1155{
1156 /* Collapse the attachments if '$digest_collapse' is set AND if...
1157 * the outer container is of type 'multipart/digest' */
1158 bool digest = mutt_istr_equal(actx->email->body->subtype, "digest");
1159
1160 const bool c_digest_collapse = cs_subset_bool(NeoMutt->sub, "digest_collapse");
1161 for (int i = 0; i < actx->idxlen; i++)
1162 {
1163 actx->idx[i]->body->tagged = false;
1164
1165 /* OR an inner container is of type 'multipart/digest' */
1166 actx->idx[i]->collapsed = (c_digest_collapse &&
1167 (digest ||
1168 ((actx->idx[i]->body->type == TYPE_MULTIPART) &&
1169 mutt_istr_equal(actx->idx[i]->body->subtype, "digest"))));
1170 }
1171}
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 1179 of file recvattach.c.

1180{
1181 if (init)
1182 {
1183 mutt_generate_recvattach_list(actx, actx->email, actx->email->body,
1184 actx->fp_root, -1, 0, 0);
1185 mutt_attach_init(actx);
1186 }
1187
1188 mutt_update_tree(actx);
1189
1190 menu->max = actx->vcount;
1191
1192 const int index = menu_get_index(menu);
1193 if (index >= menu->max)
1194 menu_set_index(menu, menu->max - 1);
1196}
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:116
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: