NeoMutt  2021-02-05-89-gabe350
Teaching an old dog new tricks
DOXYGEN
mutt_attach.c
Go to the documentation of this file.
1 
30 #include "config.h"
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <stdbool.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <sys/stat.h>
37 #include <sys/wait.h>
38 #include <unistd.h>
39 #include "mutt/lib.h"
40 #include "config/lib.h"
41 #include "email/lib.h"
42 #include "core/lib.h"
43 #include "gui/lib.h"
44 #include "mutt_attach.h"
45 #include "ncrypt/lib.h"
46 #include "pager/lib.h"
47 #include "send/lib.h"
48 #include "context.h"
49 #include "copy.h"
50 #include "handler.h"
51 #include "mailcap.h"
52 #include "mutt_globals.h"
53 #include "muttlib.h"
54 #include "mx.h"
55 #include "options.h"
56 #include "protos.h"
57 #include "rfc3676.h"
58 #include "state.h"
59 #ifdef USE_IMAP
60 #include "imap/lib.h"
61 #endif
62 
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 }
112 
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 }
245 
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 }
328 
335 void mutt_check_lookup_list(struct Body *b, char *type, size_t len)
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 }
368 
382 static int wait_interactive_filter(pid_t pid)
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 }
414 int mutt_view_attachment(FILE *fp, struct Body *a, enum ViewAttachMode mode,
415  struct Email *e, struct AttachCtx *actx, struct MuttWindow *win)
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 }
697 
707 int mutt_pipe_attachment(FILE *fp, struct Body *b, const char *path, char *outfile)
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 }
846 
853 static FILE *save_attachment_open(const char *path, enum SaveAttach opt)
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 }
862 
873 int mutt_save_attachment(FILE *fp, struct Body *m, const char *path,
874  enum SaveAttach opt, struct Email *e)
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 }
993 
1004 int mutt_decode_save_attachment(FILE *fp, struct Body *m, const char *path,
1005  int displaying, enum SaveAttach opt)
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 }
1089 
1103 int mutt_print_attachment(FILE *fp, struct Body *a)
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 }
1253 
1258 void mutt_add_temp_attachment(const char *filename)
1259 {
1260  mutt_list_insert_tail(&TempAttachmentsList, mutt_str_dup(filename));
1261 }
1262 
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 }
rfc3676.h
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
AttachCtx
A set of attachments.
Definition: attach.h:49
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
lib.h
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
handler.h
MuttWindow
A division of the screen.
Definition: mutt_window.h:115
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
mailcap.h
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_globals.h
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
options.h
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
copy.h
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
SaveAttach
SaveAttach
Options for saving attachments.
Definition: mutt_attach.h:54
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
lib.h
mutt_sig_unblock_system
void mutt_sig_unblock_system(bool restore)
Restore previously blocked signals.
Definition: signal.c:207
protos.h
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
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.
Definition: mutt_attach.c:414
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
mutt_print_attachment
int mutt_print_attachment(FILE *fp, struct Body *a)
Print out an attachment.
Definition: mutt_attach.c:1103
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
lib.h
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
muttlib.h
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_check_lookup_list
void mutt_check_lookup_list(struct Body *b, char *type, size_t len)
Update the mime type.
Definition: mutt_attach.c:335
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
lib.h
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_compose_attachment
int mutt_compose_attachment(struct Body *a)
Create an attachment.
Definition: mutt_attach.c:119
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
lib.h
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
lib.h
mutt_edit_attachment
int mutt_edit_attachment(struct Body *a)
Edit an attachment.
Definition: mutt_attach.c:259
lib.h
lib.h
ViewAttachMode
ViewAttachMode
Options for mutt_view_attachment()
Definition: mutt_attach.h:40
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
mutt_unlink_temp_attachments
void mutt_unlink_temp_attachments(void)
Delete all temporary attachments.
Definition: mutt_attach.c:1266
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
context.h
Pager::fp
FILE * fp
Source stream.
Definition: lib.h:69
mutt_get_tmp_attachment
int mutt_get_tmp_attachment(struct Body *a)
Get a temporary copy of an attachment.
Definition: mutt_attach.c: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
mx.h
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.h
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
lib.h
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_attach.h
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