NeoMutt  2021-02-05-89-gabe350
Teaching an old dog new tricks
DOXYGEN
mutt_attach.c File Reference
#include "config.h"
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include "mutt/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "gui/lib.h"
#include "mutt_attach.h"
#include "ncrypt/lib.h"
#include "pager/lib.h"
#include "send/lib.h"
#include "context.h"
#include "copy.h"
#include "handler.h"
#include "mailcap.h"
#include "mutt_globals.h"
#include "muttlib.h"
#include "mx.h"
#include "options.h"
#include "protos.h"
#include "rfc3676.h"
#include "state.h"
#include "imap/lib.h"
+ Include dependency graph for mutt_attach.c:

Go to the source code of this file.

Functions

int mutt_get_tmp_attachment (struct Body *a)
 Get a temporary copy of an attachment. More...
 
int mutt_compose_attachment (struct Body *a)
 Create an attachment. More...
 
int mutt_edit_attachment (struct Body *a)
 Edit an attachment. More...
 
void mutt_check_lookup_list (struct Body *b, char *type, size_t len)
 Update the mime type. More...
 
static int wait_interactive_filter (pid_t pid)
 Wait after an interactive filter. More...
 
int mutt_view_attachment (FILE *fp, struct Body *a, enum ViewAttachMode mode, struct Email *e, struct AttachCtx *actx, struct MuttWindow *win)
 View an attachment. More...
 
int mutt_pipe_attachment (FILE *fp, struct Body *b, const char *path, char *outfile)
 Pipe an attachment to a command. More...
 
static FILE * save_attachment_open (const char *path, enum SaveAttach opt)
 Open a file to write an attachment to. More...
 
int mutt_save_attachment (FILE *fp, struct Body *m, const char *path, enum SaveAttach opt, struct Email *e)
 Save an attachment. More...
 
int mutt_decode_save_attachment (FILE *fp, struct Body *m, const char *path, int displaying, enum SaveAttach opt)
 Decode, then save an attachment. More...
 
int mutt_print_attachment (FILE *fp, struct Body *a)
 Print out an attachment. More...
 
void mutt_add_temp_attachment (const char *filename)
 Add file to list of temporary attachments. More...
 
void mutt_unlink_temp_attachments (void)
 Delete all temporary attachments. More...
 

Detailed Description

Handling of email attachments

Authors
  • Michael R. Elkins
  • Thomas Roessler

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 mutt_attach.c.

Function Documentation

◆ mutt_get_tmp_attachment()

int mutt_get_tmp_attachment ( struct Body a)

Get a temporary copy of an attachment.

Parameters
aAttachment to copy
Return values
0Success
-1Error

Definition at line 69 of file mutt_attach.c.

70 {
71  char type[256];
72  struct stat st;
73 
74  if (a->unlink)
75  return 0;
76 
77  struct Buffer *tmpfile = mutt_buffer_pool_get();
78  struct MailcapEntry *entry = mailcap_entry_new();
79  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
80  mailcap_lookup(a, type, sizeof(type), entry, MUTT_MC_NO_FLAGS);
81  mailcap_expand_filename(entry->nametemplate, a->filename, tmpfile);
82 
83  mailcap_entry_free(&entry);
84 
85  if (stat(a->filename, &st) == -1)
86  {
87  mutt_buffer_pool_release(&tmpfile);
88  return -1;
89  }
90 
91  FILE *fp_in = NULL, *fp_out = NULL;
92  if ((fp_in = fopen(a->filename, "r")) &&
93  (fp_out = mutt_file_fopen(mutt_buffer_string(tmpfile), "w")))
94  {
95  mutt_file_copy_stream(fp_in, fp_out);
97  a->unlink = true;
98 
99  if (a->stamp >= st.st_mtime)
101  }
102  else
103  mutt_perror(fp_in ? mutt_buffer_string(tmpfile) : a->filename);
104 
105  mutt_file_fclose(&fp_in);
106  mutt_file_fclose(&fp_out);
107 
108  mutt_buffer_pool_release(&tmpfile);
109 
110  return a->unlink ? 0 : -1;
111 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_compose_attachment()

int mutt_compose_attachment ( struct Body a)

Create an attachment.

Parameters
aBody of email
Return values
1if require full screen redraw
0otherwise

Definition at line 119 of file mutt_attach.c.

120 {
121  char type[256];
122  struct MailcapEntry *entry = mailcap_entry_new();
123  bool unlink_newfile = false;
124  int rc = 0;
125  struct Buffer *cmd = mutt_buffer_pool_get();
126  struct Buffer *newfile = mutt_buffer_pool_get();
127  struct Buffer *tmpfile = mutt_buffer_pool_get();
128 
129  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
130  if (mailcap_lookup(a, type, sizeof(type), entry, MUTT_MC_COMPOSE))
131  {
132  if (entry->composecommand || entry->composetypecommand)
133  {
134  if (entry->composetypecommand)
136  else
137  mutt_buffer_strcpy(cmd, entry->composecommand);
138 
139  mailcap_expand_filename(entry->nametemplate, a->filename, newfile);
140  mutt_debug(LL_DEBUG1, "oldfile: %s newfile: %s\n", a->filename,
141  mutt_buffer_string(newfile));
142  if (mutt_file_symlink(a->filename, mutt_buffer_string(newfile)) == -1)
143  {
144  if (mutt_yesorno(_("Can't match 'nametemplate', continue?"), MUTT_YES) != MUTT_YES)
145  goto bailout;
146  mutt_buffer_strcpy(newfile, a->filename);
147  }
148  else
149  unlink_newfile = true;
150 
151  if (mailcap_expand_command(a, mutt_buffer_string(newfile), type, cmd))
152  {
153  /* For now, editing requires a file, no piping */
154  mutt_error(_("Mailcap compose entry requires %%s"));
155  }
156  else
157  {
158  int r;
159 
160  mutt_endwin();
162  if (r == -1)
163  mutt_error(_("Error running \"%s\""), mutt_buffer_string(cmd));
164 
165  if ((r != -1) && entry->composetypecommand)
166  {
167  struct Body *b = NULL;
168 
169  FILE *fp = mutt_file_fopen(a->filename, "r");
170  if (!fp)
171  {
172  mutt_perror(_("Failure to open file to parse headers"));
173  goto bailout;
174  }
175 
176  b = mutt_read_mime_header(fp, 0);
177  if (b)
178  {
179  if (!TAILQ_EMPTY(&b->parameter))
180  {
182  a->parameter = b->parameter;
183  TAILQ_INIT(&b->parameter);
184  }
185  if (b->description)
186  {
187  FREE(&a->description);
188  a->description = b->description;
189  b->description = NULL;
190  }
191  if (b->form_name)
192  {
193  FREE(&a->form_name);
194  a->form_name = b->form_name;
195  b->form_name = NULL;
196  }
197 
198  /* Remove headers by copying out data to another file, then
199  * copying the file back */
200  fseeko(fp, b->offset, SEEK_SET);
201  mutt_body_free(&b);
202  mutt_buffer_mktemp(tmpfile);
203  FILE *fp_tmp = mutt_file_fopen(mutt_buffer_string(tmpfile), "w");
204  if (!fp_tmp)
205  {
206  mutt_perror(_("Failure to open file to strip headers"));
207  mutt_file_fclose(&fp);
208  goto bailout;
209  }
210  mutt_file_copy_stream(fp, fp_tmp);
211  mutt_file_fclose(&fp);
212  mutt_file_fclose(&fp_tmp);
214  if (mutt_file_rename(mutt_buffer_string(tmpfile), a->filename) != 0)
215  {
216  mutt_perror(_("Failure to rename file"));
217  goto bailout;
218  }
219  }
220  }
221  }
222  }
223  }
224  else
225  {
226  mutt_message(_("No mailcap compose entry for %s, creating empty file"), type);
227  rc = 1;
228  goto bailout;
229  }
230 
231  rc = 1;
232 
233 bailout:
234 
235  if (unlink_newfile)
236  unlink(mutt_buffer_string(newfile));
237 
239  mutt_buffer_pool_release(&newfile);
240  mutt_buffer_pool_release(&tmpfile);
241 
242  mailcap_entry_free(&entry);
243  return rc;
244 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_edit_attachment()

int mutt_edit_attachment ( struct Body a)

Edit an attachment.

Parameters
aEmail containing attachment
Return values
1if editor found
0if not

Currently, this only works for send mode, as it assumes that the Body->filename actually contains the information. I'm not sure we want to deal with editing attachments we've already received, so this should be ok.

Returning 0 is useful to tell the calling menu to redraw

Definition at line 259 of file mutt_attach.c.

260 {
261  char type[256];
262  struct MailcapEntry *entry = mailcap_entry_new();
263  bool unlink_newfile = false;
264  int rc = 0;
265  struct Buffer *cmd = mutt_buffer_pool_get();
266  struct Buffer *newfile = mutt_buffer_pool_get();
267 
268  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
269  if (mailcap_lookup(a, type, sizeof(type), entry, MUTT_MC_EDIT))
270  {
271  if (entry->editcommand)
272  {
273  mutt_buffer_strcpy(cmd, entry->editcommand);
274  mailcap_expand_filename(entry->nametemplate, a->filename, newfile);
275  mutt_debug(LL_DEBUG1, "oldfile: %s newfile: %s\n", a->filename,
276  mutt_buffer_string(newfile));
277  if (mutt_file_symlink(a->filename, mutt_buffer_string(newfile)) == -1)
278  {
279  if (mutt_yesorno(_("Can't match 'nametemplate', continue?"), MUTT_YES) != MUTT_YES)
280  goto bailout;
281  mutt_buffer_strcpy(newfile, a->filename);
282  }
283  else
284  unlink_newfile = true;
285 
286  if (mailcap_expand_command(a, mutt_buffer_string(newfile), type, cmd))
287  {
288  /* For now, editing requires a file, no piping */
289  mutt_error(_("Mailcap Edit entry requires %%s"));
290  goto bailout;
291  }
292  else
293  {
294  mutt_endwin();
295  if (mutt_system(mutt_buffer_string(cmd)) == -1)
296  {
297  mutt_error(_("Error running \"%s\""), mutt_buffer_string(cmd));
298  goto bailout;
299  }
300  }
301  }
302  }
303  else if (a->type == TYPE_TEXT)
304  {
305  /* On text, default to editor */
307  }
308  else
309  {
310  mutt_error(_("No mailcap edit entry for %s"), type);
311  rc = 0;
312  goto bailout;
313  }
314 
315  rc = 1;
316 
317 bailout:
318 
319  if (unlink_newfile)
320  unlink(mutt_buffer_string(newfile));
321 
323  mutt_buffer_pool_release(&newfile);
324 
325  mailcap_entry_free(&entry);
326  return rc;
327 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_check_lookup_list()

void mutt_check_lookup_list ( struct Body b,
char *  type,
size_t  len 
)

Update the mime type.

Parameters
bMessage attachment body
typeBuffer with mime type of attachment in "type/subtype" format
lenBuffer length

Definition at line 335 of file mutt_attach.c.

336 {
337  struct ListNode *np = NULL;
338  STAILQ_FOREACH(np, &MimeLookupList, entries)
339  {
340  const int i = mutt_str_len(np->data) - 1;
341  if (((i > 0) && (np->data[i - 1] == '/') && (np->data[i] == '*') &&
342  mutt_istrn_equal(type, np->data, i)) ||
343  mutt_istr_equal(type, np->data))
344  {
345  struct Body tmp = { 0 };
346  enum ContentType n;
347  if ((n = mutt_lookup_mime_type(&tmp, b->filename)) != TYPE_OTHER ||
348  (n = mutt_lookup_mime_type(&tmp, b->description)) != TYPE_OTHER)
349  {
350  snprintf(type, len, "%s/%s",
351  (n == TYPE_AUDIO) ? "audio" :
352  (n == TYPE_APPLICATION) ? "application" :
353  (n == TYPE_IMAGE) ? "image" :
354  (n == TYPE_MESSAGE) ? "message" :
355  (n == TYPE_MODEL) ? "model" :
356  (n == TYPE_MULTIPART) ? "multipart" :
357  (n == TYPE_TEXT) ? "text" :
358  (n == TYPE_VIDEO) ? "video" :
359  "other",
360  tmp.subtype);
361  mutt_debug(LL_DEBUG1, "\"%s\" -> %s\n", b->filename, type);
362  }
363  FREE(&tmp.subtype);
364  FREE(&tmp.xtype);
365  }
366  }
367 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ wait_interactive_filter()

static int wait_interactive_filter ( pid_t  pid)
static

Wait after an interactive filter.

Parameters
pidProcess id of the process to wait for
Return values
numExit status of the process identified by pid
-1Error

This is used for filters that are actually interactive commands with input piped in: e.g. in mutt_view_attachment(), a mailcap entry without copiousoutput and without a s.

For those cases, we treat it like a blocking system command, and poll IMAP to keep connections open.

Definition at line 382 of file mutt_attach.c.

383 {
384  int rc;
385 
386 #ifdef USE_IMAP
387  rc = imap_wait_keepalive(pid);
388 #else
389  waitpid(pid, &rc, 0);
390 #endif
392  rc = WIFEXITED(rc) ? WEXITSTATUS(rc) : -1;
393 
394  return rc;
395 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_view_attachment()

int mutt_view_attachment ( FILE *  fp,
struct Body a,
enum ViewAttachMode  mode,
struct Email e,
struct AttachCtx actx,
struct MuttWindow win 
)

View an attachment.

Parameters
fpSource file stream. Can be NULL
aThe message body containing the attachment
modeHow the attachment should be viewed, see ViewAttachMode
eCurrent Email. Can be NULL
actxAttachment context
winWindow
Return values
0If the viewer is run and exited successfully
-1Error
numReturn value of mutt_do_pager() when it is used

Display a message attachment using the viewer program configured in mailcap. If there is no mailcap entry for a file type, view the image as text. Viewer processes are opened and waited on synchronously so viewing an attachment this way will block the main neomutt process until the viewer process exits.

Definition at line 414 of file mutt_attach.c.

416 {
417  bool use_mailcap = false;
418  bool use_pipe = false;
419  bool use_pager = true;
420  char type[256];
421  char desc[256];
422  char *fname = NULL;
423  struct MailcapEntry *entry = NULL;
424  int rc = -1;
425  bool unlink_tempfile = false;
426  bool unlink_pagerfile = false;
427 
428  bool is_message = mutt_is_message_type(a->type, a->subtype);
429  if ((WithCrypto != 0) && is_message && a->email &&
431  {
432  return rc;
433  }
434 
435  struct Buffer *tmpfile = mutt_buffer_pool_get();
436  struct Buffer *pagerfile = mutt_buffer_pool_get();
437  struct Buffer *cmd = mutt_buffer_pool_get();
438 
439  use_mailcap = ((mode == MUTT_VA_MAILCAP) ||
440  ((mode == MUTT_VA_REGULAR) && mutt_needs_mailcap(a)) ||
441  (mode == MUTT_VA_PAGER));
442  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
443 
444  char columns[16];
445  snprintf(columns, sizeof(columns), "%d", win->state.cols);
446  mutt_envlist_set("COLUMNS", columns, true);
447 
448  if (use_mailcap)
449  {
450  entry = mailcap_entry_new();
451  enum MailcapLookup mailcap_opt =
453  if (!mailcap_lookup(a, type, sizeof(type), entry, mailcap_opt))
454  {
455  if ((mode == MUTT_VA_REGULAR) || (mode == MUTT_VA_PAGER))
456  {
457  /* fallback to view as text */
458  mailcap_entry_free(&entry);
459  mutt_error(_("No matching mailcap entry found. Viewing as text."));
460  mode = MUTT_VA_AS_TEXT;
461  use_mailcap = false;
462  }
463  else
464  goto return_error;
465  }
466  }
467 
468  if (use_mailcap)
469  {
470  if (!entry->command)
471  {
472  mutt_error(_("MIME type not defined. Can't view attachment."));
473  goto return_error;
474  }
475  mutt_buffer_strcpy(cmd, entry->command);
476 
477  fname = mutt_str_dup(a->filename);
478  /* In send mode(!fp), we allow slashes because those are part of
479  * the tmpfile. The path will be removed in expand_filename */
480  mutt_file_sanitize_filename(fname, fp ? true : false);
481  mailcap_expand_filename(entry->nametemplate, fname, tmpfile);
482  FREE(&fname);
483 
484  if (mutt_save_attachment(fp, a, mutt_buffer_string(tmpfile), 0, NULL) == -1)
485  goto return_error;
486  unlink_tempfile = true;
487 
489 
490  use_pipe = mailcap_expand_command(a, mutt_buffer_string(tmpfile), type, cmd);
491  use_pager = entry->copiousoutput;
492  }
493 
494  if (use_pager)
495  {
496  if (fp && !use_mailcap && a->filename)
497  {
498  /* recv case */
499  mutt_buffer_strcpy(pagerfile, a->filename);
500  mutt_adv_mktemp(pagerfile);
501  }
502  else
503  mutt_buffer_mktemp(pagerfile);
504  }
505 
506  if (use_mailcap)
507  {
508  pid_t pid = 0;
509  int fd_temp = -1, fd_pager = -1;
510 
511  if (!use_pager)
512  mutt_endwin();
513 
514  if (use_pager || use_pipe)
515  {
516  if (use_pager && ((fd_pager = mutt_file_open(mutt_buffer_string(pagerfile),
517  O_CREAT | O_EXCL | O_WRONLY)) == -1))
518  {
519  mutt_perror("open");
520  goto return_error;
521  }
522  unlink_pagerfile = true;
523 
524  if (use_pipe && ((fd_temp = open(mutt_buffer_string(tmpfile), 0)) == -1))
525  {
526  if (fd_pager != -1)
527  close(fd_pager);
528  mutt_perror("open");
529  goto return_error;
530  }
531  unlink_pagerfile = true;
532 
533  pid = filter_create_fd(mutt_buffer_string(cmd), NULL, NULL, NULL,
534  use_pipe ? fd_temp : -1, use_pager ? fd_pager : -1, -1);
535 
536  if (pid == -1)
537  {
538  if (fd_pager != -1)
539  close(fd_pager);
540 
541  if (fd_temp != -1)
542  close(fd_temp);
543 
544  mutt_error(_("Can't create filter"));
545  goto return_error;
546  }
547 
548  if (use_pager)
549  {
550  if (a->description)
551  {
552  snprintf(desc, sizeof(desc), _("---Command: %-20.20s Description: %s"),
554  }
555  else
556  {
557  snprintf(desc, sizeof(desc), _("---Command: %-30.30s Attachment: %s"),
558  mutt_buffer_string(cmd), type);
559  }
560  filter_wait(pid);
561  }
562  else
563  {
564  if (wait_interactive_filter(pid) || (entry->needsterminal && C_WaitKey))
566  }
567 
568  if (fd_temp != -1)
569  close(fd_temp);
570  if (fd_pager != -1)
571  close(fd_pager);
572  }
573  else
574  {
575  /* interactive cmd */
576  int rv = mutt_system(mutt_buffer_string(cmd));
577  if (rv == -1)
578  mutt_debug(LL_DEBUG1, "Error running \"%s\"", cmd->data);
579 
580  if ((rv != 0) || (entry->needsterminal && C_WaitKey))
582  }
583  }
584  else
585  {
586  /* Don't use mailcap; the attachment is viewed in the pager */
587 
588  if (mode == MUTT_VA_AS_TEXT)
589  {
590  /* just let me see the raw data */
591  if (fp)
592  {
593  /* Viewing from a received message.
594  *
595  * Don't use mutt_save_attachment() because we want to perform charset
596  * conversion since this will be displayed by the internal pager. */
597  struct State decode_state = { 0 };
598 
599  decode_state.fp_out = mutt_file_fopen(mutt_buffer_string(pagerfile), "w");
600  if (!decode_state.fp_out)
601  {
602  mutt_debug(LL_DEBUG1, "mutt_file_fopen(%s) errno=%d %s\n",
603  mutt_buffer_string(pagerfile), errno, strerror(errno));
604  mutt_perror(mutt_buffer_string(pagerfile));
605  goto return_error;
606  }
607  decode_state.fp_in = fp;
608  decode_state.flags = MUTT_CHARCONV;
609  mutt_decode_attachment(a, &decode_state);
610  if (mutt_file_fclose(&decode_state.fp_out) == EOF)
611  {
612  mutt_debug(LL_DEBUG1, "fclose(%s) errno=%d %s\n",
613  mutt_buffer_string(pagerfile), errno, strerror(errno));
614  }
615  }
616  else
617  {
618  /* in compose mode, just copy the file. we can't use
619  * mutt_decode_attachment() since it assumes the content-encoding has
620  * already been applied */
621  if (mutt_save_attachment(fp, a, mutt_buffer_string(pagerfile), MUTT_SAVE_NO_FLAGS, NULL))
622  goto return_error;
623  unlink_pagerfile = true;
624  }
626  }
627  else
628  {
629  /* Use built-in handler */
630  OptViewAttach = true; /* disable the "use 'v' to view this part"
631  * message in case of error */
632  if (mutt_decode_save_attachment(fp, a, mutt_buffer_string(pagerfile),
634  {
635  OptViewAttach = false;
636  goto return_error;
637  }
638  unlink_pagerfile = true;
639  OptViewAttach = false;
640  }
641 
642  if (a->description)
643  mutt_str_copy(desc, a->description, sizeof(desc));
644  else if (a->filename)
645  snprintf(desc, sizeof(desc), _("---Attachment: %s: %s"), a->filename, type);
646  else
647  snprintf(desc, sizeof(desc), _("---Attachment: %s"), type);
648  }
649 
650  /* We only reach this point if there have been no errors */
651 
652  if (use_pager)
653  {
654  struct Pager info = { 0 };
655  info.fp = fp;
656  info.body = a;
657  info.ctx = Context;
658  info.actx = actx;
659  info.email = e;
660 
661  rc = mutt_do_pager(desc, mutt_buffer_string(pagerfile),
663  &info);
664  mutt_buffer_reset(pagerfile);
665  unlink_pagerfile = false;
666  }
667  else
668  rc = 0;
669 
670 return_error:
671 
672  if (!entry || !entry->xneomuttkeep)
673  {
674  if (fp && !mutt_buffer_is_empty(tmpfile))
675  {
676  /* add temporary file to TempAttachmentsList to be deleted on timeout hook */
678  }
679  else if (unlink_tempfile)
680  {
681  unlink(mutt_buffer_string(tmpfile));
682  }
683  }
684 
685  mailcap_entry_free(&entry);
686 
687  if (unlink_pagerfile)
689 
690  mutt_buffer_pool_release(&tmpfile);
691  mutt_buffer_pool_release(&pagerfile);
693  mutt_envlist_unset("COLUMNS");
694 
695  return rc;
696 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_pipe_attachment()

int mutt_pipe_attachment ( FILE *  fp,
struct Body b,
const char *  path,
char *  outfile 
)

Pipe an attachment to a command.

Parameters
fpFile to pipe into the command
bAttachment
pathPath to command
outfileFile to save output to
Return values
1Success
0Error

Definition at line 707 of file mutt_attach.c.

708 {
709  pid_t pid = 0;
710  int out = -1, rc = 0;
711  bool is_flowed = false;
712  bool unlink_unstuff = false;
713  FILE *fp_filter = NULL, *fp_unstuff = NULL, *fp_in = NULL;
714  struct Buffer *unstuff_tempfile = NULL;
715 
716  if (outfile && *outfile)
717  {
718  out = mutt_file_open(outfile, O_CREAT | O_EXCL | O_WRONLY);
719  if (out < 0)
720  {
721  mutt_perror("open");
722  return 0;
723  }
724  }
725 
727  {
728  is_flowed = true;
729  unstuff_tempfile = mutt_buffer_pool_get();
730  mutt_buffer_mktemp(unstuff_tempfile);
731  }
732 
733  mutt_endwin();
734 
735  if (outfile && *outfile)
736  pid = filter_create_fd(path, &fp_filter, NULL, NULL, -1, out, -1);
737  else
738  pid = filter_create(path, &fp_filter, NULL, NULL);
739  if (pid < 0)
740  {
741  mutt_perror(_("Can't create filter"));
742  goto bail;
743  }
744 
745  /* recv case */
746  if (fp)
747  {
748  struct State s = { 0 };
749 
750  /* perform charset conversion on text attachments when piping */
751  s.flags = MUTT_CHARCONV;
752 
753  if (is_flowed)
754  {
755  fp_unstuff = mutt_file_fopen(mutt_buffer_string(unstuff_tempfile), "w");
756  if (fp_unstuff == NULL)
757  {
758  mutt_perror("mutt_file_fopen");
759  goto bail;
760  }
761  unlink_unstuff = true;
762 
763  s.fp_in = fp;
764  s.fp_out = fp_unstuff;
765  mutt_decode_attachment(b, &s);
766  mutt_file_fclose(&fp_unstuff);
767 
769 
770  fp_unstuff = mutt_file_fopen(mutt_buffer_string(unstuff_tempfile), "r");
771  if (fp_unstuff == NULL)
772  {
773  mutt_perror("mutt_file_fopen");
774  goto bail;
775  }
776  mutt_file_copy_stream(fp_unstuff, fp_filter);
777  mutt_file_fclose(&fp_unstuff);
778  }
779  else
780  {
781  s.fp_in = fp;
782  s.fp_out = fp_filter;
783  mutt_decode_attachment(b, &s);
784  }
785  }
786 
787  /* send case */
788  else
789  {
790  const char *infile = NULL;
791 
792  if (is_flowed)
793  {
794  if (mutt_save_attachment(fp, b, mutt_buffer_string(unstuff_tempfile),
795  MUTT_SAVE_NO_FLAGS, NULL) == -1)
796  {
797  goto bail;
798  }
799  unlink_unstuff = true;
801  infile = mutt_buffer_string(unstuff_tempfile);
802  }
803  else
804  infile = b->filename;
805 
806  fp_in = fopen(infile, "r");
807  if (!fp_in)
808  {
809  mutt_perror("fopen");
810  goto bail;
811  }
812 
813  mutt_file_copy_stream(fp_in, fp_filter);
815  }
816 
817  mutt_file_fclose(&fp_filter);
818  rc = 1;
819 
820 bail:
821  if (outfile && *outfile)
822  {
823  close(out);
824  if (rc == 0)
825  unlink(outfile);
826  else if (is_flowed)
828  }
829 
830  mutt_file_fclose(&fp_unstuff);
831  mutt_file_fclose(&fp_filter);
833 
834  if (unlink_unstuff)
835  mutt_file_unlink(mutt_buffer_string(unstuff_tempfile));
836  mutt_buffer_pool_release(&unstuff_tempfile);
837 
838  /* check for error exit from child process */
839  if ((pid > 0) && (filter_wait(pid) != 0))
840  rc = 0;
841 
842  if ((rc == 0) || C_WaitKey)
844  return rc;
845 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ save_attachment_open()

static FILE* save_attachment_open ( const char *  path,
enum SaveAttach  opt 
)
static

Open a file to write an attachment to.

Parameters
pathPath to file to open
optSave option, see SaveAttach
Return values
ptrFile handle to attachment file

Definition at line 853 of file mutt_attach.c.

854 {
855  if (opt == MUTT_SAVE_APPEND)
856  return fopen(path, "a");
857  if (opt == MUTT_SAVE_OVERWRITE)
858  return fopen(path, "w");
859 
860  return mutt_file_fopen(path, "w");
861 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_save_attachment()

int mutt_save_attachment ( FILE *  fp,
struct Body m,
const char *  path,
enum SaveAttach  opt,
struct Email e 
)

Save an attachment.

Parameters
fpSource file stream. Can be NULL
mEmail Body
pathWhere to save the attachment
optSave option, see SaveAttach
eCurrent Email. Can be NULL
Return values
0Success
-1Error

Definition at line 873 of file mutt_attach.c.

875 {
876  if (!m)
877  return -1;
878 
879  if (fp)
880  {
881  /* recv mode */
882 
883  if (e && m->email && (m->encoding != ENC_BASE64) &&
885  {
886  /* message type attachments are written to mail folders. */
887 
888  char buf[8192];
889  struct Message *msg = NULL;
890  CopyHeaderFlags chflags = CH_NO_FLAGS;
891  int rc = -1;
892 
893  struct Email *e_new = m->email;
894  e_new->msgno = e->msgno; /* required for MH/maildir */
895  e_new->read = true;
896 
897  if (fseeko(fp, m->offset, SEEK_SET) < 0)
898  return -1;
899  if (!fgets(buf, sizeof(buf), fp))
900  return -1;
901  struct Mailbox *m_att = mx_path_resolve(path);
902  struct Context *ctx = mx_mbox_open(m_att, MUTT_APPEND | MUTT_QUIET);
903  if (!ctx)
904  {
905  mailbox_free(&m_att);
906  return -1;
907  }
908  msg = mx_msg_open_new(ctx->mailbox, e_new,
909  is_from(buf, NULL, 0, NULL) ? MUTT_MSG_NO_FLAGS : MUTT_ADD_FROM);
910  if (!msg)
911  {
912  mx_mbox_close(&ctx);
913  return -1;
914  }
915  if ((ctx->mailbox->type == MUTT_MBOX) || (ctx->mailbox->type == MUTT_MMDF))
916  chflags = CH_FROM | CH_UPDATE_LEN;
917  chflags |= ((ctx->mailbox->type == MUTT_MAILDIR) ? CH_NOSTATUS : CH_UPDATE);
918  if ((mutt_copy_message_fp(msg->fp, fp, e_new, MUTT_CM_NO_FLAGS, chflags, 0) == 0) &&
919  (mx_msg_commit(ctx->mailbox, msg) == 0))
920  {
921  rc = 0;
922  }
923  else
924  {
925  rc = -1;
926  }
927 
928  mx_msg_close(ctx->mailbox, &msg);
929  mx_mbox_close(&ctx);
930  return rc;
931  }
932  else
933  {
934  /* In recv mode, extract from folder and decode */
935 
936  struct State s = { 0 };
937 
938  s.fp_out = save_attachment_open(path, opt);
939  if (!s.fp_out)
940  {
941  mutt_perror("fopen");
942  return -1;
943  }
944  fseeko((s.fp_in = fp), m->offset, SEEK_SET);
945  mutt_decode_attachment(m, &s);
946 
947  if (mutt_file_fsync_close(&s.fp_out) != 0)
948  {
949  mutt_perror("fclose");
950  return -1;
951  }
952  }
953  }
954  else
955  {
956  if (!m->filename)
957  return -1;
958 
959  /* In send mode, just copy file */
960 
961  FILE *fp_old = fopen(m->filename, "r");
962  if (!fp_old)
963  {
964  mutt_perror("fopen");
965  return -1;
966  }
967 
968  FILE *fp_new = save_attachment_open(path, opt);
969  if (!fp_new)
970  {
971  mutt_perror("fopen");
972  mutt_file_fclose(&fp_old);
973  return -1;
974  }
975 
976  if (mutt_file_copy_stream(fp_old, fp_new) == -1)
977  {
978  mutt_error(_("Write fault"));
979  mutt_file_fclose(&fp_old);
980  mutt_file_fclose(&fp_new);
981  return -1;
982  }
983  mutt_file_fclose(&fp_old);
984  if (mutt_file_fsync_close(&fp_new) != 0)
985  {
986  mutt_error(_("Write fault"));
987  return -1;
988  }
989  }
990 
991  return 0;
992 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_decode_save_attachment()

int mutt_decode_save_attachment ( FILE *  fp,
struct Body m,
const char *  path,
int  displaying,
enum SaveAttach  opt 
)

Decode, then save an attachment.

Parameters
fpFile to read from (OPTIONAL)
mAttachment
pathPath to save the Attachment to
displayingFlags, e.g. MUTT_DISPLAY
optSave option, see SaveAttach
Return values
0Success
-1Error

Definition at line 1004 of file mutt_attach.c.

1006 {
1007  struct State s = { 0 };
1008  unsigned int saved_encoding = 0;
1009  struct Body *saved_parts = NULL;
1010  struct Email *e_saved = NULL;
1011  int rc = 0;
1012 
1013  s.flags = displaying;
1014 
1015  if (opt == MUTT_SAVE_APPEND)
1016  s.fp_out = fopen(path, "a");
1017  else if (opt == MUTT_SAVE_OVERWRITE)
1018  s.fp_out = fopen(path, "w");
1019  else
1020  s.fp_out = mutt_file_fopen(path, "w");
1021 
1022  if (!s.fp_out)
1023  {
1024  mutt_perror("fopen");
1025  return -1;
1026  }
1027 
1028  if (!fp)
1029  {
1030  /* When called from the compose menu, the attachment isn't parsed,
1031  * so we need to do it here. */
1032  struct stat st;
1033 
1034  if (stat(m->filename, &st) == -1)
1035  {
1036  mutt_perror("stat");
1038  return -1;
1039  }
1040 
1041  s.fp_in = fopen(m->filename, "r");
1042  if (!s.fp_in)
1043  {
1044  mutt_perror("fopen");
1045  return -1;
1046  }
1047 
1048  saved_encoding = m->encoding;
1049  if (!is_multipart(m))
1050  m->encoding = ENC_8BIT;
1051 
1052  m->length = st.st_size;
1053  m->offset = 0;
1054  saved_parts = m->parts;
1055  e_saved = m->email;
1056  mutt_parse_part(s.fp_in, m);
1057 
1058  if (m->noconv || is_multipart(m))
1059  s.flags |= MUTT_CHARCONV;
1060  }
1061  else
1062  {
1063  s.fp_in = fp;
1064  s.flags |= MUTT_CHARCONV;
1065  }
1066 
1067  mutt_body_handler(m, &s);
1068 
1069  if (mutt_file_fsync_close(&s.fp_out) != 0)
1070  {
1071  mutt_perror("fclose");
1072  rc = -1;
1073  }
1074  if (!fp)
1075  {
1076  m->length = 0;
1077  m->encoding = saved_encoding;
1078  if (saved_parts)
1079  {
1080  email_free(&m->email);
1081  m->parts = saved_parts;
1082  m->email = e_saved;
1083  }
1084  mutt_file_fclose(&s.fp_in);
1085  }
1086 
1087  return rc;
1088 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_print_attachment()

int mutt_print_attachment ( FILE *  fp,
struct Body a 
)

Print out an attachment.

Parameters
fpFile to write to
aAttachment
Return values
1Success
0Error

Ok, the difference between send and receive: recv: Body->filename is a suggested name, and Mailbox|Email points to the attachment in mailbox which is encoded send: Body->filename points to the un-encoded file which contains the attachment

Definition at line 1103 of file mutt_attach.c.

1104 {
1105  char type[256];
1106  pid_t pid;
1107  FILE *fp_in = NULL, *fp_out = NULL;
1108  bool unlink_newfile = false;
1109  struct Buffer *newfile = mutt_buffer_pool_get();
1110  struct Buffer *cmd = mutt_buffer_pool_get();
1111 
1112  int rc = 0;
1113 
1114  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
1115 
1116  if (mailcap_lookup(a, type, sizeof(type), NULL, MUTT_MC_PRINT))
1117  {
1118  int piped = false;
1119 
1120  mutt_debug(LL_DEBUG2, "Using mailcap\n");
1121 
1122  struct MailcapEntry *entry = mailcap_entry_new();
1123  mailcap_lookup(a, type, sizeof(type), entry, MUTT_MC_PRINT);
1124  mailcap_expand_filename(entry->nametemplate, a->filename, newfile);
1125 
1126  if (mutt_save_attachment(fp, a, mutt_buffer_string(newfile),
1127  MUTT_SAVE_NO_FLAGS, NULL) == -1)
1128  {
1129  goto mailcap_cleanup;
1130  }
1131  unlink_newfile = 1;
1132 
1134 
1135  mutt_buffer_strcpy(cmd, entry->printcommand);
1136  piped = mailcap_expand_command(a, mutt_buffer_string(newfile), type, cmd);
1137 
1138  mutt_endwin();
1139 
1140  /* interactive program */
1141  if (piped)
1142  {
1143  fp_in = fopen(mutt_buffer_string(newfile), "r");
1144  if (!fp_in)
1145  {
1146  mutt_perror("fopen");
1147  mailcap_entry_free(&entry);
1148  goto mailcap_cleanup;
1149  }
1150 
1151  pid = filter_create(mutt_buffer_string(cmd), &fp_out, NULL, NULL);
1152  if (pid < 0)
1153  {
1154  mutt_perror(_("Can't create filter"));
1155  mailcap_entry_free(&entry);
1156  mutt_file_fclose(&fp_in);
1157  goto mailcap_cleanup;
1158  }
1159  mutt_file_copy_stream(fp_in, fp_out);
1160  mutt_file_fclose(&fp_out);
1161  mutt_file_fclose(&fp_in);
1162  if (filter_wait(pid) || C_WaitKey)
1164  }
1165  else
1166  {
1167  int rc2 = mutt_system(mutt_buffer_string(cmd));
1168  if (rc2 == -1)
1169  mutt_debug(LL_DEBUG1, "Error running \"%s\"", cmd->data);
1170 
1171  if ((rc2 != 0) || C_WaitKey)
1173  }
1174 
1175  rc = 1;
1176 
1177  mailcap_cleanup:
1178  if (unlink_newfile)
1180 
1181  mailcap_entry_free(&entry);
1182  goto out;
1183  }
1184 
1185  if (mutt_istr_equal("text/plain", type) ||
1186  mutt_istr_equal("application/postscript", type))
1187  {
1188  rc = (mutt_pipe_attachment(fp, a, NONULL(C_PrintCommand), NULL));
1189  goto out;
1190  }
1191  else if (mutt_can_decode(a))
1192  {
1193  /* decode and print */
1194 
1195  fp_in = NULL;
1196  fp_out = NULL;
1197 
1198  mutt_buffer_mktemp(newfile);
1199  if (mutt_decode_save_attachment(fp, a, mutt_buffer_string(newfile),
1201  {
1202  unlink_newfile = true;
1203  mutt_debug(LL_DEBUG2, "successfully decoded %s type attachment to %s\n",
1204  type, mutt_buffer_string(newfile));
1205 
1206  fp_in = fopen(mutt_buffer_string(newfile), "r");
1207  if (!fp_in)
1208  {
1209  mutt_perror("fopen");
1210  goto decode_cleanup;
1211  }
1212 
1213  mutt_debug(LL_DEBUG2, "successfully opened %s read-only\n",
1214  mutt_buffer_string(newfile));
1215 
1216  mutt_endwin();
1217  pid = filter_create(NONULL(C_PrintCommand), &fp_out, NULL, NULL);
1218  if (pid < 0)
1219  {
1220  mutt_perror(_("Can't create filter"));
1221  goto decode_cleanup;
1222  }
1223 
1224  mutt_debug(LL_DEBUG2, "Filter created\n");
1225 
1226  mutt_file_copy_stream(fp_in, fp_out);
1227 
1228  mutt_file_fclose(&fp_out);
1229  mutt_file_fclose(&fp_in);
1230 
1231  if ((filter_wait(pid) != 0) || C_WaitKey)
1233  rc = 1;
1234  }
1235  decode_cleanup:
1236  mutt_file_fclose(&fp_in);
1237  mutt_file_fclose(&fp_out);
1238  if (unlink_newfile)
1240  }
1241  else
1242  {
1243  mutt_error(_("I don't know how to print that"));
1244  rc = 0;
1245  }
1246 
1247 out:
1248  mutt_buffer_pool_release(&newfile);
1250 
1251  return rc;
1252 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_add_temp_attachment()

void mutt_add_temp_attachment ( const char *  filename)

Add file to list of temporary attachments.

Parameters
filenamefilename with full path

Definition at line 1258 of file mutt_attach.c.

1259 {
1260  mutt_list_insert_tail(&TempAttachmentsList, mutt_str_dup(filename));
1261 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_unlink_temp_attachments()

void mutt_unlink_temp_attachments ( void  )

Delete all temporary attachments.

Definition at line 1266 of file mutt_attach.c.

1267 {
1268  struct ListNode *np = NULL;
1269 
1270  STAILQ_FOREACH(np, &TempAttachmentsList, entries)
1271  {
1272  mutt_file_chmod_add(np->data, S_IWUSR);
1273  mutt_file_unlink(np->data);
1274  }
1275 
1276  mutt_list_free(&TempAttachmentsList);
1277 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:
MailcapEntry::composecommand
char * composecommand
Definition: mailcap.h:42
CH_FROM
#define CH_FROM
Retain the "From " message separator?
Definition: copy.h:55
CopyHeaderFlags
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition: copy.h:49
mutt_endwin
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:572
Email::msgno
int msgno
Number displayed to the user.
Definition: email.h:87
mutt_rfc3676_is_format_flowed
bool mutt_rfc3676_is_format_flowed(struct Body *b)
Is the Email "format-flowed"?
Definition: rfc3676.c:387
MailcapEntry::composetypecommand
char * composetypecommand
Definition: mailcap.h:43
ENC_QUOTED_PRINTABLE
@ ENC_QUOTED_PRINTABLE
Quoted-printable text.
Definition: mime.h:51
Body::noconv
bool noconv
Don't do character set conversion.
Definition: body.h:73
MUTT_MSG_NO_FLAGS
#define MUTT_MSG_NO_FLAGS
No flags are set.
Definition: mx.h:64
MUTT_MC_COMPOSE
@ MUTT_MC_COMPOSE
Mailcap compose field.
Definition: mailcap.h:60
MailcapEntry::xneomuttkeep
bool xneomuttkeep
do not remove the file on command exit
Definition: mailcap.h:50
MUTT_MMDF
@ MUTT_MMDF
'mmdf' Mailbox type
Definition: mailbox.h:49
State::fp_in
FILE * fp_in
File to read from.
Definition: state.h:46
TAILQ_INIT
#define TAILQ_INIT(head)
Definition: queue.h:758
mutt_stamp_attachment
void mutt_stamp_attachment(struct Body *a)
Timestamp an Attachment.
Definition: sendlib.c:893
_
#define _(a)
Definition: message.h:28
NONULL
#define NONULL(x)
Definition: string2.h:37
Mailbox
A mailbox.
Definition: mailbox.h:81
save_attachment_open
static FILE * save_attachment_open(const char *path, enum SaveAttach opt)
Open a file to write an attachment to.
Definition: mutt_attach.c:853
mutt_system
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:51
filter_create_fd
pid_t filter_create_fd(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err, int fdin, int fdout, int fderr)
Run a command on a pipe (optionally connect stdin/stdout)
Definition: filter.c:61
MUTT_DISPLAY
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
Pager::actx
struct AttachCtx * actx
Attachment information.
Definition: lib.h:70
ListNode
A List node for strings.
Definition: list.h:34
Buffer
String manipulation buffer.
Definition: buffer.h:33
mutt_rfc3676_space_stuff_attachment
void mutt_rfc3676_space_stuff_attachment(struct Body *b, const char *filename)
Stuff attachments.
Definition: rfc3676.c:532
mutt_file_sanitize_filename
void mutt_file_sanitize_filename(char *path, bool slash)
Replace unsafe characters in a filename.
Definition: file.c:618
MUTT_MC_EDIT
@ MUTT_MC_EDIT
Mailcap edit field.
Definition: mailcap.h:59
Body::offset
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
MailcapEntry::editcommand
char * editcommand
Definition: mailcap.h:44
mailcap_lookup
bool mailcap_lookup(struct Body *a, char *type, size_t typelen, struct MailcapEntry *entry, enum MailcapLookup opt)
Find given type in the list of mailcap files.
Definition: mailcap.c:465
mutt_file_fclose
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
mutt_buffer_is_empty
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
Body
The body of an email.
Definition: body.h:34
SEC_ENCRYPT
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:85
mailcap_expand_command
int mailcap_expand_command(struct Body *a, const char *filename, const char *type, struct Buffer *command)
Expand expandos in a command.
Definition: mailcap.c:69
Pager::email
struct Email * email
Current message.
Definition: lib.h:67
mutt_buffer_mktemp
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
mutt_parse_part
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1659
TAILQ_EMPTY
#define TAILQ_EMPTY(head)
Definition: queue.h:714
TYPE_VIDEO
@ TYPE_VIDEO
Type: 'video/*'.
Definition: mime.h:39
MUTT_YES
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition: quad.h:40
Context
The "current" mailbox.
Definition: context.h:38
mutt_str_dup
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
mutt_file_fopen
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
mutt_file_unlink
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
LL_DEBUG1
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
FREE
#define FREE(x)
Definition: memory.h:40
mutt_perror
#define mutt_perror(...)
Definition: logging.h:85
MUTT_MC_PRINT
@ MUTT_MC_PRINT
Mailcap print field.
Definition: mailcap.h:61
ContentType
ContentType
Content-Type.
Definition: mime.h:29
Email::path
char * path
Path of Email (for local Mailboxes)
Definition: email.h:92
Body::encoding
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
mutt_param_free
void mutt_param_free(struct ParameterList *pl)
Free a ParameterList.
Definition: parameter.c:61
mutt_pipe_attachment
int mutt_pipe_attachment(FILE *fp, struct Body *b, const char *path, char *outfile)
Pipe an attachment to a command.
Definition: mutt_attach.c:707
mutt_buffer_reset
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
mutt_buffer_pool_release
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
mailbox_free
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:71
mutt_decode_save_attachment
int mutt_decode_save_attachment(FILE *fp, struct Body *m, const char *path, int displaying, enum SaveAttach opt)
Decode, then save an attachment.
Definition: mutt_attach.c:1004
Context
WHERE struct Context * Context
Definition: mutt_globals.h:42
mutt_body_free
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
Body::subtype
char * subtype
content-type subtype
Definition: body.h:37
mx_path_resolve
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition: mx.c:1681
mutt_list_insert_tail
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:64
STAILQ_FOREACH
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
mutt_file_chmod_add
int mutt_file_chmod_add(const char *path, mode_t mode)
Add permissions to a file.
Definition: file.c:1067
MUTT_PAGER_MESSAGE
#define MUTT_PAGER_MESSAGE
Definition: lib.h:57
MailcapEntry
A mailcap entry.
Definition: mailcap.h:38
State::fp_out
FILE * fp_out
File to write to.
Definition: state.h:47
TYPE_AUDIO
@ TYPE_AUDIO
Type: 'audio/*'.
Definition: mime.h:32
mutt_istr_equal
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
C_Editor
WHERE char * C_Editor
Config: External command to use as an email editor.
Definition: mutt_globals.h:90
MUTT_MC_AUTOVIEW
@ MUTT_MC_AUTOVIEW
Mailcap autoview field.
Definition: mailcap.h:62
mutt_copy_message_fp
int mutt_copy_message_fp(FILE *fp_out, FILE *fp_in, struct Email *e, CopyMessageFlags cmflags, CopyHeaderFlags chflags, int wraplen)
make a copy of a message from a FILE pointer
Definition: copy.c:616
MailcapEntry::printcommand
char * printcommand
Definition: mailcap.h:45
mutt_sig_unblock_system
void mutt_sig_unblock_system(bool restore)
Restore previously blocked signals.
Definition: signal.c:207
mutt_any_key_to_continue
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:605
filter_create
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:206
mutt_buffer_pool_get
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
imap_wait_keepalive
int imap_wait_keepalive(pid_t pid)
Wait for a process to change state.
Definition: util.c:967
Body::xtype
char * xtype
content-type if x-unknown
Definition: body.h:36
mutt_can_decode
bool mutt_can_decode(struct Body *a)
Will decoding the attachment produce any output.
Definition: handler.c:1805
Body::form_name
char * form_name
Content-Disposition form-data name param.
Definition: body.h:41
mutt_edit_file
void mutt_edit_file(const char *editor, const char *file)
Let the user edit a file.
Definition: curs_lib.c:356
Mailbox::type
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
mx_msg_commit
int mx_msg_commit(struct Mailbox *m, struct Message *msg)
Commit a message to a folder - Wrapper for MxOps::msg_commit()
Definition: mx.c:1183
MailcapEntry::command
char * command
Definition: mailcap.h:40
MailcapEntry::needsterminal
bool needsterminal
endwin() and system
Definition: mailcap.h:48
MUTT_VA_PAGER
@ MUTT_VA_PAGER
View attachment in pager using copiousoutput mailcap.
Definition: mutt_attach.h:45
MUTT_VA_AS_TEXT
@ MUTT_VA_AS_TEXT
Force viewing as text.
Definition: mutt_attach.h:44
mutt_do_pager
int mutt_do_pager(const char *banner, const char *tempfile, PagerFlags do_color, struct Pager *info)
Display some page-able text to the user.
Definition: curs_lib.c:691
MUTT_CHARCONV
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:36
mutt_file_copy_stream
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:271
TYPE
#define TYPE(body)
Definition: mime.h:89
mx_mbox_close
enum MxStatus mx_mbox_close(struct Context **ptr)
Save changes and close mailbox.
Definition: mx.c:632
Body::length
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
mutt_rfc3676_space_unstuff_attachment
void mutt_rfc3676_space_unstuff_attachment(struct Body *b, const char *filename)
Unstuff attachments.
Definition: rfc3676.c:511
ENC_8BIT
@ ENC_8BIT
8-bit text
Definition: mime.h:50
MUTT_CM_NO_FLAGS
#define MUTT_CM_NO_FLAGS
No flags are set.
Definition: copy.h:34
is_from
bool is_from(const char *s, char *path, size_t pathlen, time_t *tp)
Is a string a 'From' header line?
Definition: from.c:48
CH_NO_FLAGS
#define CH_NO_FLAGS
No flags are set.
Definition: copy.h:50
Pager::ctx
struct Context * ctx
Current mailbox.
Definition: lib.h:66
mutt_file_symlink
int mutt_file_symlink(const char *oldpath, const char *newpath)
Create a symlink.
Definition: file.c:299
MUTT_PAGER_NO_FLAGS
#define MUTT_PAGER_NO_FLAGS
No flags are set.
Definition: lib.h:42
mailcap_expand_filename
void mailcap_expand_filename(const char *nametemplate, const char *oldfile, struct Buffer *newfile)
Expand a new filename from a template or existing filename.
Definition: mailcap.c:533
MUTT_MC_NO_FLAGS
@ MUTT_MC_NO_FLAGS
No flags set.
Definition: mailcap.h:58
CH_NOSTATUS
#define CH_NOSTATUS
Suppress the status and x-status fields.
Definition: copy.h:57
Body::description
char * description
content-description
Definition: body.h:40
TYPE_MODEL
@ TYPE_MODEL
Type: 'model/*'.
Definition: mime.h:36
mutt_is_message_type
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition: parse.c:1368
mutt_read_mime_header
struct Body * mutt_read_mime_header(FILE *fp, bool digest)
Parse a MIME header.
Definition: parse.c:1269
Body::parts
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
TYPE_MESSAGE
@ TYPE_MESSAGE
Type: 'message/*'.
Definition: mime.h:35
Context::mailbox
struct Mailbox * mailbox
Definition: context.h:50
MUTT_SAVE_APPEND
@ MUTT_SAVE_APPEND
Append to existing file.
Definition: mutt_attach.h:57
mutt_debug
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
MUTT_PAGER_ATTACHMENT
#define MUTT_PAGER_ATTACHMENT
Attachments may exist.
Definition: lib.h:54
MUTT_ADD_FROM
#define MUTT_ADD_FROM
add a From_ line
Definition: mx.h:65
TYPE_IMAGE
@ TYPE_IMAGE
Type: 'image/*'.
Definition: mime.h:34
CH_UPDATE
#define CH_UPDATE
Update the status and x-status fields?
Definition: copy.h:51
C_PrintCommand
WHERE char * C_PrintCommand
Config: External command to print a message.
Definition: mutt_globals.h:103
Message::fp
FILE * fp
pointer to the message data
Definition: mx.h:96
mutt_envlist_unset
bool mutt_envlist_unset(const char *name)
Unset an environment variable.
Definition: envlist.c:132
MUTT_QUIET
#define MUTT_QUIET
Do not print any messages.
Definition: mx.h:55
mutt_str_len
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:631
mutt_buffer_string
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
Email::security
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition: email.h:39
MailcapEntry::copiousoutput
bool copiousoutput
needs pager, basically
Definition: mailcap.h:49
mutt_str_replace
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:446
filter_wait
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
mutt_adv_mktemp
void mutt_adv_mktemp(struct Buffer *buf)
Create a temporary file.
Definition: muttlib.c:90
WithCrypto
#define WithCrypto
Definition: lib.h:123
MuttWindow::state
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:120
State
Keep track when processing files.
Definition: state.h:44
TYPE_APPLICATION
@ TYPE_APPLICATION
Type: 'application/*'.
Definition: mime.h:33
mailcap_entry_free
void mailcap_entry_free(struct MailcapEntry **ptr)
Deallocate an struct MailcapEntry.
Definition: mailcap.c:436
MUTT_VA_REGULAR
@ MUTT_VA_REGULAR
View using default method.
Definition: mutt_attach.h:42
Body::stamp
time_t stamp
Time stamp of last encoding update.
Definition: body.h:61
is_multipart
#define is_multipart(body)
Definition: mime.h:82
ENC_BASE64
@ ENC_BASE64
Base-64 encoded text.
Definition: mime.h:52
TYPE_TEXT
@ TYPE_TEXT
Type: 'text/*'.
Definition: mime.h:38
MailcapLookup
MailcapLookup
Mailcap actions.
Definition: mailcap.h:56
MUTT_SAVE_NO_FLAGS
@ MUTT_SAVE_NO_FLAGS
No flags set.
Definition: mutt_attach.h:56
mutt_file_open
int mutt_file_open(const char *path, uint32_t flags)
Open a file.
Definition: file.c:522
Body::type
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
mx_mbox_open
struct Context * mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:309
TYPE_OTHER
@ TYPE_OTHER
Unknown Content-Type.
Definition: mime.h:31
mutt_file_rename
int mutt_file_rename(const char *oldfile, const char *newfile)
Rename a file.
Definition: file.c:1347
OptViewAttach
WHERE bool OptViewAttach
(pseudo) signals that we are viewing attachments
Definition: options.h:55
mutt_body_handler
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1595
ListNode::data
char * data
String.
Definition: list.h:36
Pager::fp
FILE * fp
Source stream.
Definition: lib.h:69
email_free
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:43
mutt_istrn_equal
bool mutt_istrn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings ignoring case (to a maximum), safely.
Definition: string.c:621
mutt_needs_mailcap
bool mutt_needs_mailcap(struct Body *m)
Does this type need a mailcap entry do display.
Definition: muttlib.c:405
MUTT_MAILDIR
@ MUTT_MAILDIR
'Maildir' Mailbox type
Definition: mailbox.h:51
Body::email
struct Email * email
header information for message/rfc822
Definition: body.h:55
WindowState::cols
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:57
Body::unlink
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
MUTT_APPEND
#define MUTT_APPEND
Open mailbox for appending messages.
Definition: mx.h:53
Body::parameter
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
MUTT_SAVE_OVERWRITE
@ MUTT_SAVE_OVERWRITE
Overwrite existing file.
Definition: mutt_attach.h:58
Pager
An email being displayed.
Definition: lib.h:64
mutt_decode_attachment
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email's attachment.
Definition: handler.c:1845
mx_msg_close
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1204
State::flags
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
mutt_yesorno
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:380
Buffer::data
char * data
Pointer to data.
Definition: buffer.h:35
wait_interactive_filter
static int wait_interactive_filter(pid_t pid)
Wait after an interactive filter.
Definition: mutt_attach.c:382
TYPE_MULTIPART
@ TYPE_MULTIPART
Type: 'multipart/*'.
Definition: mime.h:37
Email
The envelope/body of an email.
Definition: email.h:37
mutt_envlist_set
bool mutt_envlist_set(const char *name, const char *value, bool overwrite)
Set an environment variable.
Definition: envlist.c:85
mutt_add_temp_attachment
void mutt_add_temp_attachment(const char *filename)
Add file to list of temporary attachments.
Definition: mutt_attach.c:1258
mutt_message
#define mutt_message(...)
Definition: logging.h:83
mx_msg_open_new
struct Message * mx_msg_open_new(struct Mailbox *m, const struct Email *e, MsgOpenFlags flags)
Open a new message.
Definition: mx.c:1072
mutt_lookup_mime_type
enum ContentType mutt_lookup_mime_type(struct Body *att, const char *path)
Find the MIME type for an attachment.
Definition: sendlib.c:565
MUTT_VA_MAILCAP
@ MUTT_VA_MAILCAP
Force viewing using mailcap entry.
Definition: mutt_attach.h:43
mutt_file_fsync_close
int mutt_file_fsync_close(FILE **fp)
Flush the data, before closing a file (and NULL the pointer)
Definition: file.c:169
mutt_list_free
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
MUTT_PRINTING
#define MUTT_PRINTING
Are we printing? - MUTT_DISPLAY "light".
Definition: state.h:37
crypt_valid_passphrase
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:135
CH_UPDATE_LEN
#define CH_UPDATE_LEN
Update Lines: and Content-Length:
Definition: copy.h:61
mutt_save_attachment
int mutt_save_attachment(FILE *fp, struct Body *m, const char *path, enum SaveAttach opt, struct Email *e)
Save an attachment.
Definition: mutt_attach.c:873
Email::read
bool read
Email is read.
Definition: email.h:51
Pager::body
struct Body * body
Current attachment.
Definition: lib.h:68
MUTT_MBOX
@ MUTT_MBOX
'mbox' Mailbox type
Definition: mailbox.h:48
mutt_buffer_strcpy
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
MailcapEntry::nametemplate
char * nametemplate
Definition: mailcap.h:46
LL_DEBUG2
@ LL_DEBUG2
Log at debug level 2.
Definition: logging.h:41
C_WaitKey
WHERE bool C_WaitKey
Config: Prompt to press a key after running external commands.
Definition: mutt_globals.h:169
mailcap_entry_new
struct MailcapEntry * mailcap_entry_new(void)
Allocate memory for a new rfc1524 entry.
Definition: mailcap.c:427
Message
A local copy of an email.
Definition: mx.h:94
Body::filename
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
mutt_error
#define mutt_error(...)
Definition: logging.h:84
mutt_str_copy
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:716