NeoMutt  2021-02-05-329-g9e03b7
Teaching an old dog new tricks
DOXYGEN
mutt_attach.h File Reference

Handling of email attachments. More...

#include <stdbool.h>
#include <stdio.h>
+ Include dependency graph for mutt_attach.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Enumerations

enum  ViewAttachMode { MUTT_VA_REGULAR = 1, MUTT_VA_MAILCAP, MUTT_VA_AS_TEXT, MUTT_VA_PAGER }
 Options for mutt_view_attachment() More...
 
enum  SaveAttach { MUTT_SAVE_NO_FLAGS = 0, MUTT_SAVE_APPEND, MUTT_SAVE_OVERWRITE }
 Options for saving attachments. More...
 

Functions

int attach_tag (struct Menu *menu, int sel, int act)
 Tag an attachment - Implements Menu::tag() More...
 
int mutt_attach_display_loop (struct ConfigSubset *sub, struct Menu *menu, int op, struct Email *e, struct AttachCtx *actx, bool recv)
 Event loop for the Attachment menu. More...
 
void mutt_save_attachment_list (struct AttachCtx *actx, FILE *fp, bool tag, struct Body *top, struct Email *e, struct Menu *menu)
 Save a list of attachments. More...
 
void mutt_pipe_attachment_list (struct AttachCtx *actx, FILE *fp, bool tag, struct Body *top, bool filter)
 Pipe a list of attachments to a command. More...
 
void mutt_print_attachment_list (struct AttachCtx *actx, FILE *fp, bool tag, struct Body *top)
 Print a list of Attachments. 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...
 
void mutt_check_lookup_list (struct Body *b, char *type, size_t len)
 Update the mime type. More...
 
int mutt_compose_attachment (struct Body *a)
 Create 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_edit_attachment (struct Body *a)
 Edit an attachment. More...
 
int mutt_get_tmp_attachment (struct Body *a)
 Get a temporary copy of an attachment. More...
 
int mutt_pipe_attachment (FILE *fp, struct Body *b, const char *path, char *outfile)
 Pipe an attachment to a command. More...
 
int mutt_print_attachment (FILE *fp, struct Body *a)
 Print out an attachment. More...
 
int mutt_save_attachment (FILE *fp, struct Body *m, const char *path, enum SaveAttach opt, struct Email *e)
 Save 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

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.h.

Enumeration Type Documentation

◆ ViewAttachMode

Options for mutt_view_attachment()

Enumerator
MUTT_VA_REGULAR 

View using default method.

MUTT_VA_MAILCAP 

Force viewing using mailcap entry.

MUTT_VA_AS_TEXT 

Force viewing as text.

MUTT_VA_PAGER 

View attachment in pager using copiousoutput mailcap.

Definition at line 41 of file mutt_attach.h.

42 {
43  MUTT_VA_REGULAR = 1,
47 };
Force viewing as text.
Definition: mutt_attach.h:45
View using default method.
Definition: mutt_attach.h:43
View attachment in pager using copiousoutput mailcap.
Definition: mutt_attach.h:46
Force viewing using mailcap entry.
Definition: mutt_attach.h:44

◆ SaveAttach

enum SaveAttach

Options for saving attachments.

See also
mutt_save_attachment(), mutt_decode_save_attachment(), save_attachment_open(), mutt_check_overwrite()
Enumerator
MUTT_SAVE_NO_FLAGS 

No flags set.

MUTT_SAVE_APPEND 

Append to existing file.

MUTT_SAVE_OVERWRITE 

Overwrite existing file.

Definition at line 55 of file mutt_attach.h.

56 {
57  MUTT_SAVE_NO_FLAGS = 0,
60 };
No flags set.
Definition: mutt_attach.h:57
Overwrite existing file.
Definition: mutt_attach.h:59
Append to existing file.
Definition: mutt_attach.h:58

Function Documentation

◆ attach_tag()

int attach_tag ( struct Menu menu,
int  sel,
int  act 
)

Tag an attachment - Implements Menu::tag()

Definition at line 478 of file recvattach.c.

479 {
480  struct AttachCtx *actx = menu->mdata;
481  struct Body *cur = actx->idx[actx->v2r[sel]]->body;
482  bool ot = cur->tagged;
483 
484  cur->tagged = ((act >= 0) ? act : !cur->tagged);
485  return cur->tagged - ot;
486 }
The body of an email.
Definition: body.h:34
bool tagged
This attachment is tagged.
Definition: body.h:70
void * mdata
Private data.
Definition: lib.h:129
short * v2r
Mapping from virtual to real attachment.
Definition: attach.h:58
A set of attachments.
Definition: attach.h:49
struct AttachPtr ** idx
Array of attachments.
Definition: attach.h:54
struct Body * body
Attachment.
Definition: attach.h:36
+ Here is the caller graph for this function:

◆ mutt_attach_display_loop()

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

Event loop for the Attachment menu.

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

Definition at line 1334 of file recvattach.c.

1336 {
1337  do
1338  {
1339  switch (op)
1340  {
1341  case OP_DISPLAY_HEADERS:
1342  bool_str_toggle(NeoMutt->sub, "weed", NULL);
1343  /* fallthrough */
1344 
1345  case OP_VIEW_ATTACH:
1346  {
1347  struct AttachPtr *cur_att = current_attachment(actx, menu);
1348  op = mutt_view_attachment(cur_att->fp, cur_att->body, MUTT_VA_REGULAR,
1349  e, actx, menu->win_index);
1350  break;
1351  }
1352 
1353  case OP_NEXT_ENTRY:
1354  case OP_MAIN_NEXT_UNDELETED: /* hack */
1355  {
1356  const int index = menu_get_index(menu) + 1;
1357  if (index < menu->max)
1358  {
1359  menu_set_index(menu, index);
1360  op = OP_VIEW_ATTACH;
1361  }
1362  else
1363  op = OP_NULL;
1364  break;
1365  }
1366 
1367  case OP_PREV_ENTRY:
1368  case OP_MAIN_PREV_UNDELETED: /* hack */
1369  {
1370  const int index = menu_get_index(menu) - 1;
1371  if (index >= 0)
1372  {
1373  menu_set_index(menu, index);
1374  op = OP_VIEW_ATTACH;
1375  }
1376  else
1377  op = OP_NULL;
1378  break;
1379  }
1380 
1381  case OP_EDIT_TYPE:
1382  {
1383  struct AttachPtr *cur_att = current_attachment(actx, menu);
1384  /* when we edit the content-type, we should redisplay the attachment
1385  * immediately */
1386  mutt_edit_content_type(e, cur_att->body, cur_att->fp);
1387  if (recv)
1388  recvattach_edit_content_type(sub, actx, menu, e);
1389  else
1390  mutt_edit_content_type(e, cur_att->body, cur_att->fp);
1391 
1393  op = OP_VIEW_ATTACH;
1394  break;
1395  }
1396  /* functions which are passed through from the pager */
1397  case OP_CHECK_TRADITIONAL:
1399  {
1400  op = OP_NULL;
1401  break;
1402  }
1403  /* fallthrough */
1404  case OP_ATTACH_COLLAPSE:
1405  if (recv)
1406  return op;
1407  /* fallthrough */
1408  default:
1409  op = OP_NULL;
1410  }
1411  } while (op != OP_NULL);
1412 
1413  return op;
1414 }
An email to which things will be attached.
Definition: attach.h:34
#define WithCrypto
Definition: lib.h:113
View using default method.
Definition: mutt_attach.h:43
Container for Accounts, Notifications.
Definition: neomutt.h:36
int bool_str_toggle(struct ConfigSubset *sub, const char *name, struct Buffer *err)
Toggle the value of a bool.
Definition: bool.c:213
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:87
static struct AttachPtr * current_attachment(struct AttachCtx *actx, struct Menu *menu)
Get the current attachment.
Definition: recvattach.c:87
static void recvattach_edit_content_type(struct ConfigSubset *sub, struct AttachCtx *actx, struct Menu *menu, struct Email *e)
Edit the content type of an attachment.
Definition: recvattach.c:1302
FILE * fp
Used in the recvattach menu.
Definition: attach.h:37
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
Definition: email.h:39
#define PGP_TRADITIONAL_CHECKED
Email has a traditional (inline) signature.
Definition: lib.h:89
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
bool mutt_edit_content_type(struct Email *e, struct Body *b, FILE *fp)
Edit the content type of an attachment.
Definition: commands.c:1396
struct MuttWindow * win_index
Definition: lib.h:66
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
struct Body * body
Attachment.
Definition: attach.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_save_attachment_list()

void mutt_save_attachment_list ( struct AttachCtx actx,
FILE *  fp,
bool  tag,
struct Body top,
struct Email e,
struct Menu menu 
)

Save a list of attachments.

Parameters
actxAttachment context
fpFile handle for the attachment (OPTIONAL)
tagIf true, only save the tagged attachments
topFirst Attachment
eEmail
menuMenu listing attachments

Definition at line 747 of file recvattach.c.

749 {
750  char *directory = NULL;
751  int rc = 1;
752  int last = menu_get_index(menu);
753  FILE *fp_out = NULL;
754  int saved_attachments = 0;
755 
756  struct Buffer *buf = mutt_buffer_pool_get();
757  struct Buffer *tfile = mutt_buffer_pool_get();
758 
759  const bool c_attach_split = cs_subset_bool(NeoMutt->sub, "attach_split");
760  const char *const c_attach_sep = cs_subset_string(NeoMutt->sub, "attach_sep");
761  const bool c_attach_save_without_prompting =
762  cs_subset_bool(NeoMutt->sub, "attach_save_without_prompting");
763 
764  for (int i = 0; !tag || (i < actx->idxlen); i++)
765  {
766  if (tag)
767  {
768  fp = actx->idx[i]->fp;
769  top = actx->idx[i]->body;
770  }
771  if (!tag || top->tagged)
772  {
773  if (!c_attach_split)
774  {
775  if (mutt_buffer_is_empty(buf))
776  {
777  enum SaveAttach opt = MUTT_SAVE_NO_FLAGS;
778 
780  prepend_savedir(buf);
781 
782  if ((mutt_buffer_get_field(_("Save to file: "), buf, MUTT_FILE | MUTT_CLEAR,
783  false, NULL, NULL, NULL) != 0) ||
785  {
786  goto cleanup;
787  }
789  if (mutt_check_overwrite(top->filename, mutt_buffer_string(buf), tfile, &opt, NULL))
790  goto cleanup;
791  rc = save_attachment_flowed_helper(fp, top, mutt_buffer_string(tfile), opt, e);
792  if ((rc == 0) && c_attach_sep && (fp_out = fopen(mutt_buffer_string(tfile), "a")))
793  {
794  fprintf(fp_out, "%s", c_attach_sep);
795  mutt_file_fclose(&fp_out);
796  }
797  }
798  else
799  {
801  MUTT_SAVE_APPEND, e);
802  if ((rc == 0) && c_attach_sep && (fp_out = fopen(mutt_buffer_string(tfile), "a")))
803  {
804  fprintf(fp_out, "%s", c_attach_sep);
805  mutt_file_fclose(&fp_out);
806  }
807  }
808  }
809  else
810  {
811  if (tag && menu && top->aptr)
812  {
813  menu_set_index(menu, top->aptr->num);
814  menu_check_recenter(menu);
816 
817  menu_redraw(menu);
818  }
819  if (c_attach_save_without_prompting)
820  {
821  // Save each file, with no prompting, using the configured 'AttachSaveDir'
822  rc = save_without_prompting(fp, top, e);
823  if (rc == 0)
824  saved_attachments++;
825  }
826  else
827  {
828  // Save each file, prompting the user for the location each time.
829  if (query_save_attachment(fp, top, e, &directory) == -1)
830  break;
831  }
832  }
833  }
834  if (!tag)
835  break;
836  }
837 
838  FREE(&directory);
839 
840  if (tag && menu)
841  {
842  menu_set_index(menu, last);
843  menu_check_recenter(menu);
845  }
846 
847  if (rc == 0)
848  {
849  if (!c_attach_split)
850  saved_attachments = 1;
851 
852  if (!c_attach_split || c_attach_save_without_prompting)
853  {
854  mutt_message(ngettext("Attachment saved", "%d attachments saved", saved_attachments),
855  saved_attachments);
856  }
857  }
858 
859 cleanup:
861  mutt_buffer_pool_release(&tfile);
862 }
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
#define NONULL(x)
Definition: string2.h:37
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:71
#define MUTT_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:58
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
const char * mutt_path_basename(const char *f)
Find the last component for a pathname.
Definition: path.c:329
int mutt_buffer_get_field(const char *field, struct Buffer *buf, CompletionFlags complete, bool multiple, struct Mailbox *m, char ***files, int *numfiles)
Ask the user for a string.
Definition: curs_lib.c:255
#define mutt_message(...)
Definition: logging.h:83
No flags set.
Definition: mutt_attach.h:57
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
static void prepend_savedir(struct Buffer *buf)
Add $attach_save_dir to the beginning of a path.
Definition: recvattach.c:492
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
short idxlen
Number of attachmentes.
Definition: attach.h:55
static int query_save_attachment(FILE *fp, struct Body *body, struct Email *e, char **directory)
Ask the user if we should save the attachment.
Definition: recvattach.c:598
Container for Accounts, Notifications.
Definition: neomutt.h:36
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
bool tagged
This attachment is tagged.
Definition: body.h:70
static int save_without_prompting(FILE *fp, struct Body *body, struct Email *e)
Save the attachment, without prompting each time.
Definition: recvattach.c:697
int num
Attachment index number.
Definition: attach.h:41
struct AttachPtr * aptr
Menu information, used in recvattach.c.
Definition: body.h:57
FILE * fp
Used in the recvattach menu.
Definition: attach.h:37
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:295
#define MUTT_FILE
Do file completion.
Definition: mutt.h:54
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
int mutt_check_overwrite(const char *attname, const char *path, struct Buffer *fname, enum SaveAttach *opt, char **directory)
Ask the user if overwriting is necessary.
Definition: muttlib.c:624
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:321
static int save_attachment_flowed_helper(FILE *fp, struct Body *b, const char *path, enum SaveAttach flags, struct Email *e)
Helper for unstuffing attachments.
Definition: recvattach.c:551
Append to existing file.
Definition: mutt_attach.h:58
#define FREE(x)
Definition: memory.h:40
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
struct AttachPtr ** idx
Array of attachments.
Definition: attach.h:54
SaveAttach
Options for saving attachments.
Definition: mutt_attach.h:55
struct Body * body
Attachment.
Definition: attach.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_pipe_attachment_list()

void mutt_pipe_attachment_list ( struct AttachCtx actx,
FILE *  fp,
bool  tag,
struct Body top,
bool  filter 
)

Pipe a list of attachments to a command.

Parameters
actxAttachment context
fpFile handle to the attachment (OPTIONAL)
tagIf true, only save the tagged attachments
topFirst Attachment
filterIs this command a filter?

Definition at line 1042 of file recvattach.c.

1044 {
1045  struct State state = { 0 };
1046  struct Buffer *buf = NULL;
1047 
1048  if (fp)
1049  filter = false; /* sanity check: we can't filter in the recv case yet */
1050 
1051  buf = mutt_buffer_pool_get();
1052  /* perform charset conversion on text attachments when piping */
1053  state.flags = MUTT_CHARCONV;
1054 
1055  if (mutt_buffer_get_field((filter ? _("Filter through: ") : _("Pipe to: ")),
1056  buf, MUTT_CMD, false, NULL, NULL, NULL) != 0)
1057  {
1058  goto cleanup;
1059  }
1060 
1061  if (mutt_buffer_len(buf) == 0)
1062  goto cleanup;
1063 
1065 
1066  const bool c_attach_split = cs_subset_bool(NeoMutt->sub, "attach_split");
1067  if (!filter && !c_attach_split)
1068  {
1069  mutt_endwin();
1070  pid_t pid = filter_create(mutt_buffer_string(buf), &state.fp_out, NULL, NULL);
1071  pipe_attachment_list(mutt_buffer_string(buf), actx, fp, tag, top, filter, &state);
1072  mutt_file_fclose(&state.fp_out);
1073  const bool c_wait_key = cs_subset_bool(NeoMutt->sub, "wait_key");
1074  if ((filter_wait(pid) != 0) || c_wait_key)
1076  }
1077  else
1078  pipe_attachment_list(mutt_buffer_string(buf), actx, fp, tag, top, filter, &state);
1079 
1080 cleanup:
1082 }
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:71
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:206
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:36
int mutt_buffer_get_field(const char *field, struct Buffer *buf, CompletionFlags complete, bool multiple, struct Mailbox *m, char ***files, int *numfiles)
Ask the user for a string.
Definition: curs_lib.c:255
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
FILE * fp_out
File to write to.
Definition: state.h:47
Container for Accounts, Notifications.
Definition: neomutt.h:36
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
#define MUTT_CMD
Do completion on previous word.
Definition: mutt.h:56
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:568
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:356
static void pipe_attachment_list(const char *command, struct AttachCtx *actx, FILE *fp, bool tag, struct Body *top, bool filter, struct State *state)
Pipe a list of attachments to a command.
Definition: recvattach.c:1010
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:601
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:321
Keep track when processing files.
Definition: state.h:44
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_print_attachment_list()

void mutt_print_attachment_list ( struct AttachCtx actx,
FILE *  fp,
bool  tag,
struct Body top 
)

Print a list of Attachments.

Parameters
actxAttachment context
fpFile handle to the attachment (OPTIONAL)
tagApply to all tagged Attachments
topFirst Attachment

Definition at line 1201 of file recvattach.c.

1202 {
1203  char prompt[128];
1204  struct State state = { 0 };
1205  int tagmsgcount = 0;
1206 
1207  if (tag)
1208  for (int i = 0; i < actx->idxlen; i++)
1209  if (actx->idx[i]->body->tagged)
1210  tagmsgcount++;
1211 
1212  snprintf(prompt, sizeof(prompt),
1213  /* L10N: Although we now the precise number of tagged messages, we
1214  do not show it to the user. So feel free to use a "generic
1215  plural" as plural translation if your language has one. */
1216  tag ? ngettext("Print tagged attachment?", "Print %d tagged attachments?", tagmsgcount) :
1217  _("Print attachment?"),
1218  tagmsgcount);
1219  const enum QuadOption c_print = cs_subset_quad(NeoMutt->sub, "print");
1220  if (query_quadoption(c_print, prompt) != MUTT_YES)
1221  return;
1222 
1223  const bool c_attach_split = cs_subset_bool(NeoMutt->sub, "attach_split");
1224  if (c_attach_split)
1225  {
1226  print_attachment_list(actx, fp, tag, top, &state);
1227  }
1228  else
1229  {
1230  if (!can_print(actx, top, tag))
1231  return;
1232  mutt_endwin();
1233  const char *const c_print_command =
1234  cs_subset_string(NeoMutt->sub, "print_command");
1235  pid_t pid = filter_create(NONULL(c_print_command), &state.fp_out, NULL, NULL);
1236  print_attachment_list(actx, fp, tag, top, &state);
1237  mutt_file_fclose(&state.fp_out);
1238  const bool c_wait_key = cs_subset_bool(NeoMutt->sub, "wait_key");
1239  if ((filter_wait(pid) != 0) || c_wait_key)
1241  }
1242 }
#define NONULL(x)
Definition: string2.h:37
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:71
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:206
static void print_attachment_list(struct AttachCtx *actx, FILE *fp, bool tag, struct Body *top, struct State *state)
Print a list of Attachments.
Definition: recvattach.c:1131
#define _(a)
Definition: message.h:28
short idxlen
Number of attachmentes.
Definition: attach.h:55
FILE * fp_out
File to write to.
Definition: state.h:47
Container for Accounts, Notifications.
Definition: neomutt.h:36
QuadOption
Possible values for a quad-option.
Definition: quad.h:35
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
bool tagged
This attachment is tagged.
Definition: body.h:70
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:568
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:295
static bool can_print(struct AttachCtx *actx, struct Body *top, bool tag)
Do we know how to print this attachment type?
Definition: recvattach.c:1091
enum QuadOption cs_subset_quad(const struct ConfigSubset *sub, const char *name)
Get a quad-value config item by name.
Definition: helpers.c:204
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:601
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: curs_lib.c:513
Keep track when processing files.
Definition: state.h:44
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
struct AttachPtr ** idx
Array of attachments.
Definition: attach.h:54
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
struct Body * body
Attachment.
Definition: attach.h:36
+ 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
0The 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  const bool c_wait_key = cs_subset_bool(NeoMutt->sub, "wait_key");
515  if (use_pager || use_pipe)
516  {
517  if (use_pager && ((fd_pager = mutt_file_open(mutt_buffer_string(pagerfile),
518  O_CREAT | O_EXCL | O_WRONLY)) == -1))
519  {
520  mutt_perror("open");
521  goto return_error;
522  }
523  unlink_pagerfile = true;
524 
525  if (use_pipe && ((fd_temp = open(mutt_buffer_string(tmpfile), 0)) == -1))
526  {
527  if (fd_pager != -1)
528  close(fd_pager);
529  mutt_perror("open");
530  goto return_error;
531  }
532  unlink_pagerfile = true;
533 
534  pid = filter_create_fd(mutt_buffer_string(cmd), NULL, NULL, NULL,
535  use_pipe ? fd_temp : -1, use_pager ? fd_pager : -1, -1);
536 
537  if (pid == -1)
538  {
539  if (fd_pager != -1)
540  close(fd_pager);
541 
542  if (fd_temp != -1)
543  close(fd_temp);
544 
545  mutt_error(_("Can't create filter"));
546  goto return_error;
547  }
548 
549  if (use_pager)
550  {
551  if (a->description)
552  {
553  snprintf(desc, sizeof(desc), _("---Command: %-20.20s Description: %s"),
555  }
556  else
557  {
558  snprintf(desc, sizeof(desc), _("---Command: %-30.30s Attachment: %s"),
559  mutt_buffer_string(cmd), type);
560  }
561  filter_wait(pid);
562  }
563  else
564  {
565  if (wait_interactive_filter(pid) || (entry->needsterminal && c_wait_key))
567  }
568 
569  if (fd_temp != -1)
570  close(fd_temp);
571  if (fd_pager != -1)
572  close(fd_pager);
573  }
574  else
575  {
576  /* interactive cmd */
577  int rv = mutt_system(mutt_buffer_string(cmd));
578  if (rv == -1)
579  mutt_debug(LL_DEBUG1, "Error running \"%s\"", cmd->data);
580 
581  if ((rv != 0) || (entry->needsterminal && c_wait_key))
583  }
584  }
585  else
586  {
587  /* Don't use mailcap; the attachment is viewed in the pager */
588 
589  if (mode == MUTT_VA_AS_TEXT)
590  {
591  /* just let me see the raw data */
592  if (fp)
593  {
594  /* Viewing from a received message.
595  *
596  * Don't use mutt_save_attachment() because we want to perform charset
597  * conversion since this will be displayed by the internal pager. */
598  struct State decode_state = { 0 };
599 
600  decode_state.fp_out = mutt_file_fopen(mutt_buffer_string(pagerfile), "w");
601  if (!decode_state.fp_out)
602  {
603  mutt_debug(LL_DEBUG1, "mutt_file_fopen(%s) errno=%d %s\n",
604  mutt_buffer_string(pagerfile), errno, strerror(errno));
605  mutt_perror(mutt_buffer_string(pagerfile));
606  goto return_error;
607  }
608  decode_state.fp_in = fp;
609  decode_state.flags = MUTT_CHARCONV;
610  mutt_decode_attachment(a, &decode_state);
611  if (mutt_file_fclose(&decode_state.fp_out) == EOF)
612  {
613  mutt_debug(LL_DEBUG1, "fclose(%s) errno=%d %s\n",
614  mutt_buffer_string(pagerfile), errno, strerror(errno));
615  }
616  }
617  else
618  {
619  /* in compose mode, just copy the file. we can't use
620  * mutt_decode_attachment() since it assumes the content-encoding has
621  * already been applied */
622  if (mutt_save_attachment(fp, a, mutt_buffer_string(pagerfile), MUTT_SAVE_NO_FLAGS, NULL))
623  goto return_error;
624  unlink_pagerfile = true;
625  }
627  }
628  else
629  {
630  /* Use built-in handler */
631  OptViewAttach = true; /* disable the "use 'v' to view this part"
632  * message in case of error */
633  if (mutt_decode_save_attachment(fp, a, mutt_buffer_string(pagerfile),
635  {
636  OptViewAttach = false;
637  goto return_error;
638  }
639  unlink_pagerfile = true;
640  OptViewAttach = false;
641  }
642 
643  if (a->description)
644  mutt_str_copy(desc, a->description, sizeof(desc));
645  else if (a->filename)
646  snprintf(desc, sizeof(desc), _("---Attachment: %s: %s"), a->filename, type);
647  else
648  snprintf(desc, sizeof(desc), _("---Attachment: %s"), type);
649  }
650 
651  /* We only reach this point if there have been no errors */
652 
653  if (use_pager)
654  {
655  struct PagerData pdata = { 0 };
656  struct PagerView pview = { &pdata };
657 
658  pdata.actx = actx;
659  pdata.body = a;
660  pdata.email = e;
661  pdata.fname = mutt_buffer_string(pagerfile);
662  pdata.fp = fp;
663  pdata.ctx = Context;
664 
665  pview.banner = desc;
666  pview.flags = MUTT_PAGER_ATTACHMENT |
667  (is_message ? MUTT_PAGER_MESSAGE : MUTT_PAGER_NO_FLAGS) |
668  ((use_mailcap && entry->xneomuttnowrap) ? MUTT_PAGER_NOWRAP :
670  pview.mode = PAGER_MODE_ATTACH;
671 
672  rc = mutt_do_pager(&pview);
673 
674  mutt_buffer_reset(pagerfile);
675  unlink_pagerfile = false;
676  }
677  else
678  rc = 0;
679 
680 return_error:
681 
682  if (!entry || !entry->xneomuttkeep)
683  {
684  if (fp && !mutt_buffer_is_empty(tmpfile))
685  {
686  /* add temporary file to TempAttachmentsList to be deleted on timeout hook */
688  }
689  else if (unlink_tempfile)
690  {
691  unlink(mutt_buffer_string(tmpfile));
692  }
693  }
694 
695  mailcap_entry_free(&entry);
696 
697  if (unlink_pagerfile)
699 
700  mutt_buffer_pool_release(&tmpfile);
701  mutt_buffer_pool_release(&pagerfile);
703  mutt_envlist_unset("COLUMNS");
704 
705  return rc;
706 }
bool xneomuttkeep
do not remove the file on command exit
Definition: mailcap.h:47
A mailcap entry.
Definition: mailcap.h:35
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1860
struct MailcapEntry * mailcap_entry_new(void)
Allocate memory for a new rfc1524 entry.
Definition: mailcap.c:435
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:71
#define WithCrypto
Definition: lib.h:113
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition: parse.c:1385
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:36
Mailcap autoview field.
Definition: mailcap.h:60
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:75
No flags set.
Definition: mutt_attach.h:57
struct Body * body
Current attachment.
Definition: lib.h:139
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
String manipulation buffer.
Definition: buffer.h:33
paged view into some data
Definition: lib.h:148
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define _(a)
Definition: message.h:28
FILE * fp_out
File to write to.
Definition: state.h:47
Force viewing as text.
Definition: mutt_attach.h:45
No flags set.
Definition: mailcap.h:56
WHERE struct Context * Context
Definition: mutt_globals.h:40
int mutt_do_pager(struct PagerView *pview)
Display some page-able text to the user (help or attachment)
Definition: do_pager.c:82
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:884
View using default method.
Definition: mutt_attach.h:43
Container for Accounts, Notifications.
Definition: neomutt.h:36
FILE * fp_in
File to read from.
Definition: state.h:46
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:473
int mailcap_expand_command(struct Body *a, const char *filename, const char *type, struct Buffer *command)
Expand expandos in a command.
Definition: mailcap.c:67
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:543
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
struct Email * email
Current message.
Definition: lib.h:138
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:134
Data to be displayed by PagerView.
Definition: lib.h:135
bool copiousoutput
needs pager, basically
Definition: mailcap.h:46
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
#define MUTT_PAGER_MESSAGE
Definition: lib.h:62
static int wait_interactive_filter(pid_t pid)
Wait after an interactive filter.
Definition: mutt_attach.c:381
void mutt_add_temp_attachment(const char *filename)
Add file to list of temporary attachments.
Definition: mutt_attach.c:1272
int mutt_file_open(const char *path, uint32_t flags)
Open a file.
Definition: file.c:522
char * command
Definition: mailcap.h:37
char * subtype
content-type subtype
Definition: body.h:37
enum PagerMode mode
Pager mode.
Definition: lib.h:151
void mutt_file_sanitize_filename(char *path, bool slash)
Replace unsafe characters in a filename.
Definition: file.c:618
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:58
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:122
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:568
bool mutt_envlist_unset(const char *name)
Unset an environment variable.
Definition: envlist.c:132
#define MUTT_PAGER_ATTACHMENT
Attachments may exist.
Definition: lib.h:58
void mailcap_entry_free(struct MailcapEntry **ptr)
Deallocate an struct MailcapEntry.
Definition: mailcap.c:444
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:1014
char * data
Pointer to data.
Definition: buffer.h:35
struct Context * ctx
Current Mailbox context.
Definition: lib.h:137
void mutt_rfc3676_space_unstuff_attachment(struct Body *b, const char *filename)
Unstuff attachments.
Definition: rfc3676.c:515
PagerFlags flags
Additional settings to tweak pager&#39;s function.
Definition: lib.h:152
char * description
content-description
Definition: body.h:40
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
Definition: email.h:39
View attachment in pager using copiousoutput mailcap.
Definition: mutt_attach.h:46
Force viewing using mailcap entry.
Definition: mutt_attach.h:44
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
struct AttachCtx * actx
Attachment information.
Definition: lib.h:141
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:601
char * nametemplate
Definition: mailcap.h:43
#define TYPE(body)
Definition: mime.h:89
Log at debug level 1.
Definition: logging.h:40
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
FILE * fp
Source stream.
Definition: lib.h:140
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
#define mutt_error(...)
Definition: logging.h:84
bool mutt_needs_mailcap(struct Body *m)
Does this type need a mailcap entry do display.
Definition: muttlib.c:405
MailcapLookup
Mailcap actions.
Definition: mailcap.h:54
Pager is invoked via 2nd path. A user-selected attachment (mime part or a nested email) will be shown...
Definition: lib.h:124
void mutt_adv_mktemp(struct Buffer *buf)
Create a temporary file.
Definition: muttlib.c:82
#define FREE(x)
Definition: memory.h:40
Keep track when processing files.
Definition: state.h:44
WHERE bool OptViewAttach
(pseudo) signals that we are viewing attachments
Definition: options.h:55
bool mutt_envlist_set(const char *name, const char *value, bool overwrite)
Set an environment variable.
Definition: envlist.c:85
#define MUTT_PAGER_NOWRAP
Format for term width, ignore $wrap.
Definition: lib.h:59
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
const char * fname
Name of the file to read.
Definition: lib.h:142
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
#define MUTT_PAGER_NO_FLAGS
No flags are set.
Definition: lib.h:46
const char * banner
Title to display in status bar.
Definition: lib.h:153
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
struct Email * email
header information for message/rfc822
Definition: body.h:55
bool needsterminal
endwin() and system
Definition: mailcap.h:45
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:51
bool xneomuttnowrap
do not wrap the output in the pager
Definition: mailcap.h:48
+ 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 334 of file mutt_attach.c.

335 {
336  struct ListNode *np = NULL;
337  STAILQ_FOREACH(np, &MimeLookupList, entries)
338  {
339  const int i = mutt_str_len(np->data) - 1;
340  if (((i > 0) && (np->data[i - 1] == '/') && (np->data[i] == '*') &&
341  mutt_istrn_equal(type, np->data, i)) ||
342  mutt_istr_equal(type, np->data))
343  {
344  struct Body tmp = { 0 };
345  enum ContentType n;
346  if ((n = mutt_lookup_mime_type(&tmp, b->filename)) != TYPE_OTHER ||
347  (n = mutt_lookup_mime_type(&tmp, b->description)) != TYPE_OTHER)
348  {
349  snprintf(type, len, "%s/%s",
350  (n == TYPE_AUDIO) ? "audio" :
351  (n == TYPE_APPLICATION) ? "application" :
352  (n == TYPE_IMAGE) ? "image" :
353  (n == TYPE_MESSAGE) ? "message" :
354  (n == TYPE_MODEL) ? "model" :
355  (n == TYPE_MULTIPART) ? "multipart" :
356  (n == TYPE_TEXT) ? "text" :
357  (n == TYPE_VIDEO) ? "video" :
358  "other",
359  tmp.subtype);
360  mutt_debug(LL_DEBUG1, "\"%s\" -> %s\n", b->filename, type);
361  }
362  FREE(&tmp.subtype);
363  FREE(&tmp.xtype);
364  }
365  }
366 }
Unknown Content-Type.
Definition: mime.h:31
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
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
Type: &#39;audio/*&#39;.
Definition: mime.h:32
The body of an email.
Definition: body.h:34
Type: &#39;video/*&#39;.
Definition: mime.h:39
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
char * subtype
content-type subtype
Definition: body.h:37
Type: &#39;text/*&#39;.
Definition: mime.h:38
char * xtype
content-type if x-unknown
Definition: body.h:36
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
char * description
content-description
Definition: body.h:40
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
Type: &#39;message/*&#39;.
Definition: mime.h:35
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:631
char * data
String.
Definition: list.h:36
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
Log at debug level 1.
Definition: logging.h:40
enum ContentType mutt_lookup_mime_type(struct Body *att, const char *path)
Find the MIME type for an attachment.
Definition: sendlib.c:564
Type: &#39;model/*&#39;.
Definition: mime.h:36
#define FREE(x)
Definition: memory.h:40
Type: &#39;image/*&#39;.
Definition: mime.h:34
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
A List node for strings.
Definition: list.h:34
Type: &#39;application/*&#39;.
Definition: mime.h:33
ContentType
Content-Type.
Definition: mime.h:29
+ 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
1Require full screen redraw
0Otherwise

Definition at line 117 of file mutt_attach.c.

118 {
119  char type[256];
120  struct MailcapEntry *entry = mailcap_entry_new();
121  bool unlink_newfile = false;
122  int rc = 0;
123  struct Buffer *cmd = mutt_buffer_pool_get();
124  struct Buffer *newfile = mutt_buffer_pool_get();
125  struct Buffer *tmpfile = mutt_buffer_pool_get();
126 
127  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
128  if (mailcap_lookup(a, type, sizeof(type), entry, MUTT_MC_COMPOSE))
129  {
130  if (entry->composecommand || entry->composetypecommand)
131  {
132  if (entry->composetypecommand)
134  else
135  mutt_buffer_strcpy(cmd, entry->composecommand);
136 
137  mailcap_expand_filename(entry->nametemplate, a->filename, newfile);
138  mutt_debug(LL_DEBUG1, "oldfile: %s newfile: %s\n", a->filename,
139  mutt_buffer_string(newfile));
140  if (mutt_file_symlink(a->filename, mutt_buffer_string(newfile)) == -1)
141  {
142  if (mutt_yesorno(_("Can't match 'nametemplate', continue?"), MUTT_YES) != MUTT_YES)
143  goto bailout;
144  mutt_buffer_strcpy(newfile, a->filename);
145  }
146  else
147  unlink_newfile = true;
148 
149  if (mailcap_expand_command(a, mutt_buffer_string(newfile), type, cmd))
150  {
151  /* For now, editing requires a file, no piping */
152  mutt_error(_("Mailcap compose entry requires %%s"));
153  }
154  else
155  {
156  int r;
157 
158  mutt_endwin();
160  if (r == -1)
161  mutt_error(_("Error running \"%s\""), mutt_buffer_string(cmd));
162 
163  if ((r != -1) && entry->composetypecommand)
164  {
165  struct Body *b = NULL;
166 
167  FILE *fp = mutt_file_fopen(a->filename, "r");
168  if (!fp)
169  {
170  mutt_perror(_("Failure to open file to parse headers"));
171  goto bailout;
172  }
173 
174  b = mutt_read_mime_header(fp, 0);
175  if (b)
176  {
177  if (!TAILQ_EMPTY(&b->parameter))
178  {
180  a->parameter = b->parameter;
181  TAILQ_INIT(&b->parameter);
182  }
183  if (b->description)
184  {
185  FREE(&a->description);
186  a->description = b->description;
187  b->description = NULL;
188  }
189  if (b->form_name)
190  {
191  FREE(&a->form_name);
192  a->form_name = b->form_name;
193  b->form_name = NULL;
194  }
195 
196  /* Remove headers by copying out data to another file, then
197  * copying the file back */
198  fseeko(fp, b->offset, SEEK_SET);
199  mutt_body_free(&b);
200  mutt_buffer_mktemp(tmpfile);
201  FILE *fp_tmp = mutt_file_fopen(mutt_buffer_string(tmpfile), "w");
202  if (!fp_tmp)
203  {
204  mutt_perror(_("Failure to open file to strip headers"));
205  mutt_file_fclose(&fp);
206  goto bailout;
207  }
208  mutt_file_copy_stream(fp, fp_tmp);
209  mutt_file_fclose(&fp);
210  mutt_file_fclose(&fp_tmp);
212  if (mutt_file_rename(mutt_buffer_string(tmpfile), a->filename) != 0)
213  {
214  mutt_perror(_("Failure to rename file"));
215  goto bailout;
216  }
217  }
218  }
219  }
220  }
221  }
222  else
223  {
224  mutt_message(_("No mailcap compose entry for %s, creating empty file"), type);
225  rc = 1;
226  goto bailout;
227  }
228 
229  rc = 1;
230 
231 bailout:
232 
233  if (unlink_newfile)
234  unlink(mutt_buffer_string(newfile));
235 
237  mutt_buffer_pool_release(&newfile);
238  mutt_buffer_pool_release(&tmpfile);
239 
240  mailcap_entry_free(&entry);
241  return rc;
242 }
A mailcap entry.
Definition: mailcap.h:35
struct MailcapEntry * mailcap_entry_new(void)
Allocate memory for a new rfc1524 entry.
Definition: mailcap.c:435
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
#define mutt_message(...)
Definition: logging.h:83
int mutt_file_rename(const char *oldfile, const char *newfile)
Rename a file.
Definition: file.c:1350
char * composetypecommand
Definition: mailcap.h:40
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
String manipulation buffer.
Definition: buffer.h:33
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
#define _(a)
Definition: message.h:28
char * form_name
Content-Disposition form-data name param.
Definition: body.h:41
The body of an email.
Definition: body.h:34
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:473
int mailcap_expand_command(struct Body *a, const char *filename, const char *type, struct Buffer *command)
Expand expandos in a command.
Definition: mailcap.c:67
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:543
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
Mailcap compose field.
Definition: mailcap.h:58
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:375
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
#define TAILQ_INIT(head)
Definition: queue.h:758
void mutt_param_free(struct ParameterList *pl)
Free a ParameterList.
Definition: parameter.c:61
char * subtype
content-type subtype
Definition: body.h:37
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:568
void mailcap_entry_free(struct MailcapEntry **ptr)
Deallocate an struct MailcapEntry.
Definition: mailcap.c:444
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
char * description
content-description
Definition: body.h:40
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
char * nametemplate
Definition: mailcap.h:43
#define TYPE(body)
Definition: mime.h:89
Log at debug level 1.
Definition: logging.h:40
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:271
#define mutt_error(...)
Definition: logging.h:84
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
char * composecommand
Definition: mailcap.h:39
#define FREE(x)
Definition: memory.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
#define TAILQ_EMPTY(head)
Definition: queue.h:714
int mutt_file_symlink(const char *oldpath, const char *newpath)
Create a symlink.
Definition: file.c:299
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:51
struct Body * mutt_read_mime_header(FILE *fp, bool digest)
Parse a MIME header.
Definition: parse.c:1286
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
+ 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 1014 of file mutt_attach.c.

1016 {
1017  struct State s = { 0 };
1018  unsigned int saved_encoding = 0;
1019  struct Body *saved_parts = NULL;
1020  struct Email *e_saved = NULL;
1021  int rc = 0;
1022 
1023  s.flags = displaying;
1024 
1025  if (opt == MUTT_SAVE_APPEND)
1026  s.fp_out = fopen(path, "a");
1027  else if (opt == MUTT_SAVE_OVERWRITE)
1028  s.fp_out = fopen(path, "w");
1029  else
1030  s.fp_out = mutt_file_fopen(path, "w");
1031 
1032  if (!s.fp_out)
1033  {
1034  mutt_perror("fopen");
1035  return -1;
1036  }
1037 
1038  if (!fp)
1039  {
1040  /* When called from the compose menu, the attachment isn't parsed,
1041  * so we need to do it here. */
1042  struct stat st;
1043 
1044  if (stat(m->filename, &st) == -1)
1045  {
1046  mutt_perror("stat");
1048  return -1;
1049  }
1050 
1051  s.fp_in = fopen(m->filename, "r");
1052  if (!s.fp_in)
1053  {
1054  mutt_perror("fopen");
1055  return -1;
1056  }
1057 
1058  saved_encoding = m->encoding;
1059  if (!is_multipart(m))
1060  m->encoding = ENC_8BIT;
1061 
1062  m->length = st.st_size;
1063  m->offset = 0;
1064  saved_parts = m->parts;
1065  e_saved = m->email;
1066  mutt_parse_part(s.fp_in, m);
1067 
1068  if (m->noconv || is_multipart(m))
1069  s.flags |= MUTT_CHARCONV;
1070  }
1071  else
1072  {
1073  s.fp_in = fp;
1074  s.flags |= MUTT_CHARCONV;
1075  }
1076 
1077  mutt_body_handler(m, &s);
1078 
1079  if (mutt_file_fsync_close(&s.fp_out) != 0)
1080  {
1081  mutt_perror("fclose");
1082  rc = -1;
1083  }
1084  if (!fp)
1085  {
1086  m->length = 0;
1087  m->encoding = saved_encoding;
1088  if (saved_parts)
1089  {
1090  email_free(&m->email);
1091  m->parts = saved_parts;
1092  m->email = e_saved;
1093  }
1094  mutt_file_fclose(&s.fp_in);
1095  }
1096 
1097  return rc;
1098 }
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
The envelope/body of an email.
Definition: email.h:37
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:44
#define mutt_perror(...)
Definition: logging.h:85
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:36
#define is_multipart(body)
Definition: mime.h:82
int mutt_file_fsync_close(FILE **fp)
Flush the data, before closing a file (and NULL the pointer)
Definition: file.c:169
bool noconv
Don&#39;t do character set conversion.
Definition: body.h:73
Overwrite existing file.
Definition: mutt_attach.h:59
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
8-bit text
Definition: mime.h:50
FILE * fp_out
File to write to.
Definition: state.h:47
FILE * fp_in
File to read from.
Definition: state.h:46
The body of an email.
Definition: body.h:34
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1676
char * path
Path of Email (for local Mailboxes)
Definition: email.h:92
Append to existing file.
Definition: mutt_attach.h:58
Keep track when processing files.
Definition: state.h:44
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1603
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
struct Email * email
header information for message/rfc822
Definition: body.h:55
+ 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
1Editor found
0Editor not found

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 257 of file mutt_attach.c.

258 {
259  char type[256];
260  struct MailcapEntry *entry = mailcap_entry_new();
261  bool unlink_newfile = false;
262  int rc = 0;
263  struct Buffer *cmd = mutt_buffer_pool_get();
264  struct Buffer *newfile = mutt_buffer_pool_get();
265 
266  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
267  if (mailcap_lookup(a, type, sizeof(type), entry, MUTT_MC_EDIT))
268  {
269  if (entry->editcommand)
270  {
271  mutt_buffer_strcpy(cmd, entry->editcommand);
272  mailcap_expand_filename(entry->nametemplate, a->filename, newfile);
273  mutt_debug(LL_DEBUG1, "oldfile: %s newfile: %s\n", a->filename,
274  mutt_buffer_string(newfile));
275  if (mutt_file_symlink(a->filename, mutt_buffer_string(newfile)) == -1)
276  {
277  if (mutt_yesorno(_("Can't match 'nametemplate', continue?"), MUTT_YES) != MUTT_YES)
278  goto bailout;
279  mutt_buffer_strcpy(newfile, a->filename);
280  }
281  else
282  unlink_newfile = true;
283 
284  if (mailcap_expand_command(a, mutt_buffer_string(newfile), type, cmd))
285  {
286  /* For now, editing requires a file, no piping */
287  mutt_error(_("Mailcap Edit entry requires %%s"));
288  goto bailout;
289  }
290  else
291  {
292  mutt_endwin();
293  if (mutt_system(mutt_buffer_string(cmd)) == -1)
294  {
295  mutt_error(_("Error running \"%s\""), mutt_buffer_string(cmd));
296  goto bailout;
297  }
298  }
299  }
300  }
301  else if (a->type == TYPE_TEXT)
302  {
303  /* On text, default to editor */
304  const char *const c_editor = cs_subset_string(NeoMutt->sub, "editor");
305  mutt_edit_file(NONULL(c_editor), a->filename);
306  }
307  else
308  {
309  mutt_error(_("No mailcap edit entry for %s"), type);
310  rc = 0;
311  goto bailout;
312  }
313 
314  rc = 1;
315 
316 bailout:
317 
318  if (unlink_newfile)
319  unlink(mutt_buffer_string(newfile));
320 
322  mutt_buffer_pool_release(&newfile);
323 
324  mailcap_entry_free(&entry);
325  return rc;
326 }
A mailcap entry.
Definition: mailcap.h:35
struct MailcapEntry * mailcap_entry_new(void)
Allocate memory for a new rfc1524 entry.
Definition: mailcap.c:435
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
#define NONULL(x)
Definition: string2.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
Container for Accounts, Notifications.
Definition: neomutt.h:36
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:473
int mailcap_expand_command(struct Body *a, const char *filename, const char *type, struct Buffer *command)
Expand expandos in a command.
Definition: mailcap.c:67
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:543
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:375
char * editcommand
Definition: mailcap.h:41
char * subtype
content-type subtype
Definition: body.h:37
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:568
void mailcap_entry_free(struct MailcapEntry **ptr)
Deallocate an struct MailcapEntry.
Definition: mailcap.c:444
Type: &#39;text/*&#39;.
Definition: mime.h:38
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:295
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
char * nametemplate
Definition: mailcap.h:43
#define TYPE(body)
Definition: mime.h:89
Log at debug level 1.
Definition: logging.h:40
#define mutt_error(...)
Definition: logging.h:84
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
Mailcap edit field.
Definition: mailcap.h:57
int mutt_file_symlink(const char *oldpath, const char *newpath)
Create a symlink.
Definition: file.c:299
void mutt_edit_file(const char *editor, const char *file)
Let the user edit a file.
Definition: curs_lib.c:351
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:51
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ 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 67 of file mutt_attach.c.

68 {
69  char type[256];
70  struct stat st;
71 
72  if (a->unlink)
73  return 0;
74 
75  struct Buffer *tmpfile = mutt_buffer_pool_get();
76  struct MailcapEntry *entry = mailcap_entry_new();
77  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
78  mailcap_lookup(a, type, sizeof(type), entry, MUTT_MC_NO_FLAGS);
79  mailcap_expand_filename(entry->nametemplate, a->filename, tmpfile);
80 
81  mailcap_entry_free(&entry);
82 
83  if (stat(a->filename, &st) == -1)
84  {
85  mutt_buffer_pool_release(&tmpfile);
86  return -1;
87  }
88 
89  FILE *fp_in = NULL, *fp_out = NULL;
90  if ((fp_in = fopen(a->filename, "r")) &&
91  (fp_out = mutt_file_fopen(mutt_buffer_string(tmpfile), "w")))
92  {
93  mutt_file_copy_stream(fp_in, fp_out);
95  a->unlink = true;
96 
97  if (a->stamp >= st.st_mtime)
99  }
100  else
101  mutt_perror(fp_in ? mutt_buffer_string(tmpfile) : a->filename);
102 
103  mutt_file_fclose(&fp_in);
104  mutt_file_fclose(&fp_out);
105 
106  mutt_buffer_pool_release(&tmpfile);
107 
108  return a->unlink ? 0 : -1;
109 }
A mailcap entry.
Definition: mailcap.h:35
struct MailcapEntry * mailcap_entry_new(void)
Allocate memory for a new rfc1524 entry.
Definition: mailcap.c:435
void mutt_stamp_attachment(struct Body *a)
Timestamp an Attachment.
Definition: sendlib.c:892
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
No flags set.
Definition: mailcap.h:56
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:473
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:543
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
char * subtype
content-type subtype
Definition: body.h:37
void mailcap_entry_free(struct MailcapEntry **ptr)
Deallocate an struct MailcapEntry.
Definition: mailcap.c:444
char * nametemplate
Definition: mailcap.h:43
#define TYPE(body)
Definition: mime.h:89
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:271
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:446
time_t stamp
Time stamp of last encoding update.
Definition: body.h:61
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
+ 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 717 of file mutt_attach.c.

718 {
719  pid_t pid = 0;
720  int out = -1, rc = 0;
721  bool is_flowed = false;
722  bool unlink_unstuff = false;
723  FILE *fp_filter = NULL, *fp_unstuff = NULL, *fp_in = NULL;
724  struct Buffer *unstuff_tempfile = NULL;
725 
726  if (outfile && *outfile)
727  {
728  out = mutt_file_open(outfile, O_CREAT | O_EXCL | O_WRONLY);
729  if (out < 0)
730  {
731  mutt_perror("open");
732  return 0;
733  }
734  }
735 
737  {
738  is_flowed = true;
739  unstuff_tempfile = mutt_buffer_pool_get();
740  mutt_buffer_mktemp(unstuff_tempfile);
741  }
742 
743  mutt_endwin();
744 
745  if (outfile && *outfile)
746  pid = filter_create_fd(path, &fp_filter, NULL, NULL, -1, out, -1);
747  else
748  pid = filter_create(path, &fp_filter, NULL, NULL);
749  if (pid < 0)
750  {
751  mutt_perror(_("Can't create filter"));
752  goto bail;
753  }
754 
755  /* recv case */
756  if (fp)
757  {
758  struct State s = { 0 };
759 
760  /* perform charset conversion on text attachments when piping */
761  s.flags = MUTT_CHARCONV;
762 
763  if (is_flowed)
764  {
765  fp_unstuff = mutt_file_fopen(mutt_buffer_string(unstuff_tempfile), "w");
766  if (fp_unstuff == NULL)
767  {
768  mutt_perror("mutt_file_fopen");
769  goto bail;
770  }
771  unlink_unstuff = true;
772 
773  s.fp_in = fp;
774  s.fp_out = fp_unstuff;
775  mutt_decode_attachment(b, &s);
776  mutt_file_fclose(&fp_unstuff);
777 
779 
780  fp_unstuff = mutt_file_fopen(mutt_buffer_string(unstuff_tempfile), "r");
781  if (fp_unstuff == NULL)
782  {
783  mutt_perror("mutt_file_fopen");
784  goto bail;
785  }
786  mutt_file_copy_stream(fp_unstuff, fp_filter);
787  mutt_file_fclose(&fp_unstuff);
788  }
789  else
790  {
791  s.fp_in = fp;
792  s.fp_out = fp_filter;
793  mutt_decode_attachment(b, &s);
794  }
795  }
796 
797  /* send case */
798  else
799  {
800  const char *infile = NULL;
801 
802  if (is_flowed)
803  {
804  if (mutt_save_attachment(fp, b, mutt_buffer_string(unstuff_tempfile),
805  MUTT_SAVE_NO_FLAGS, NULL) == -1)
806  {
807  goto bail;
808  }
809  unlink_unstuff = true;
811  infile = mutt_buffer_string(unstuff_tempfile);
812  }
813  else
814  infile = b->filename;
815 
816  fp_in = fopen(infile, "r");
817  if (!fp_in)
818  {
819  mutt_perror("fopen");
820  goto bail;
821  }
822 
823  mutt_file_copy_stream(fp_in, fp_filter);
824  mutt_file_fclose(&fp_in);
825  }
826 
827  mutt_file_fclose(&fp_filter);
828  rc = 1;
829 
830 bail:
831  if (outfile && *outfile)
832  {
833  close(out);
834  if (rc == 0)
835  unlink(outfile);
836  else if (is_flowed)
838  }
839 
840  mutt_file_fclose(&fp_unstuff);
841  mutt_file_fclose(&fp_filter);
842  mutt_file_fclose(&fp_in);
843 
844  if (unlink_unstuff)
845  mutt_file_unlink(mutt_buffer_string(unstuff_tempfile));
846  mutt_buffer_pool_release(&unstuff_tempfile);
847 
848  /* check for error exit from child process */
849  if ((pid > 0) && (filter_wait(pid) != 0))
850  rc = 0;
851 
852  const bool c_wait_key = cs_subset_bool(NeoMutt->sub, "wait_key");
853  if ((rc == 0) || c_wait_key)
855  return rc;
856 }
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1860
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:71
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:206
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
bool mutt_rfc3676_is_format_flowed(struct Body *b)
Is the Email "format-flowed"?
Definition: rfc3676.c:391
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:36
No flags set.
Definition: mutt_attach.h:57
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
FILE * fp_out
File to write to.
Definition: state.h:47
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:884
Container for Accounts, Notifications.
Definition: neomutt.h:36
FILE * fp_in
File to read from.
Definition: state.h:46
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
int mutt_file_open(const char *path, uint32_t flags)
Open a file.
Definition: file.c:522
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:568
void mutt_rfc3676_space_unstuff_attachment(struct Body *b, const char *filename)
Unstuff attachments.
Definition: rfc3676.c:515
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:601
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:271
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
Keep track when processing files.
Definition: state.h:44
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
void mutt_rfc3676_space_stuff_attachment(struct Body *b, const char *filename)
Stuff attachments.
Definition: rfc3676.c:536
+ 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 1113 of file mutt_attach.c.

1114 {
1115  char type[256];
1116  pid_t pid;
1117  FILE *fp_in = NULL, *fp_out = NULL;
1118  bool unlink_newfile = false;
1119  struct Buffer *newfile = mutt_buffer_pool_get();
1120  struct Buffer *cmd = mutt_buffer_pool_get();
1121 
1122  int rc = 0;
1123 
1124  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
1125 
1126  if (mailcap_lookup(a, type, sizeof(type), NULL, MUTT_MC_PRINT))
1127  {
1128  int piped = false;
1129 
1130  mutt_debug(LL_DEBUG2, "Using mailcap\n");
1131 
1132  struct MailcapEntry *entry = mailcap_entry_new();
1133  mailcap_lookup(a, type, sizeof(type), entry, MUTT_MC_PRINT);
1134  mailcap_expand_filename(entry->nametemplate, a->filename, newfile);
1135 
1136  if (mutt_save_attachment(fp, a, mutt_buffer_string(newfile),
1137  MUTT_SAVE_NO_FLAGS, NULL) == -1)
1138  {
1139  goto mailcap_cleanup;
1140  }
1141  unlink_newfile = 1;
1142 
1144 
1145  mutt_buffer_strcpy(cmd, entry->printcommand);
1146  piped = mailcap_expand_command(a, mutt_buffer_string(newfile), type, cmd);
1147 
1148  mutt_endwin();
1149 
1150  const bool c_wait_key = cs_subset_bool(NeoMutt->sub, "wait_key");
1151  /* interactive program */
1152  if (piped)
1153  {
1154  fp_in = fopen(mutt_buffer_string(newfile), "r");
1155  if (!fp_in)
1156  {
1157  mutt_perror("fopen");
1158  mailcap_entry_free(&entry);
1159  goto mailcap_cleanup;
1160  }
1161 
1162  pid = filter_create(mutt_buffer_string(cmd), &fp_out, NULL, NULL);
1163  if (pid < 0)
1164  {
1165  mutt_perror(_("Can't create filter"));
1166  mailcap_entry_free(&entry);
1167  mutt_file_fclose(&fp_in);
1168  goto mailcap_cleanup;
1169  }
1170  mutt_file_copy_stream(fp_in, fp_out);
1171  mutt_file_fclose(&fp_out);
1172  mutt_file_fclose(&fp_in);
1173  if (filter_wait(pid) || c_wait_key)
1175  }
1176  else
1177  {
1178  int rc2 = mutt_system(mutt_buffer_string(cmd));
1179  if (rc2 == -1)
1180  mutt_debug(LL_DEBUG1, "Error running \"%s\"", cmd->data);
1181 
1182  if ((rc2 != 0) || c_wait_key)
1184  }
1185 
1186  rc = 1;
1187 
1188  mailcap_cleanup:
1189  if (unlink_newfile)
1191 
1192  mailcap_entry_free(&entry);
1193  goto out;
1194  }
1195 
1196  const char *const c_print_command =
1197  cs_subset_string(NeoMutt->sub, "print_command");
1198  if (mutt_istr_equal("text/plain", type) ||
1199  mutt_istr_equal("application/postscript", type))
1200  {
1201  rc = (mutt_pipe_attachment(fp, a, NONULL(c_print_command), NULL));
1202  goto out;
1203  }
1204  else if (mutt_can_decode(a))
1205  {
1206  /* decode and print */
1207 
1208  fp_in = NULL;
1209  fp_out = NULL;
1210 
1211  mutt_buffer_mktemp(newfile);
1212  if (mutt_decode_save_attachment(fp, a, mutt_buffer_string(newfile),
1214  {
1215  unlink_newfile = true;
1216  mutt_debug(LL_DEBUG2, "successfully decoded %s type attachment to %s\n",
1217  type, mutt_buffer_string(newfile));
1218 
1219  fp_in = fopen(mutt_buffer_string(newfile), "r");
1220  if (!fp_in)
1221  {
1222  mutt_perror("fopen");
1223  goto decode_cleanup;
1224  }
1225 
1226  mutt_debug(LL_DEBUG2, "successfully opened %s read-only\n",
1227  mutt_buffer_string(newfile));
1228 
1229  mutt_endwin();
1230  pid = filter_create(NONULL(c_print_command), &fp_out, NULL, NULL);
1231  if (pid < 0)
1232  {
1233  mutt_perror(_("Can't create filter"));
1234  goto decode_cleanup;
1235  }
1236 
1237  mutt_debug(LL_DEBUG2, "Filter created\n");
1238 
1239  mutt_file_copy_stream(fp_in, fp_out);
1240 
1241  mutt_file_fclose(&fp_out);
1242  mutt_file_fclose(&fp_in);
1243 
1244  const bool c_wait_key = cs_subset_bool(NeoMutt->sub, "wait_key");
1245  if ((filter_wait(pid) != 0) || c_wait_key)
1247  rc = 1;
1248  }
1249  decode_cleanup:
1250  mutt_file_fclose(&fp_in);
1251  mutt_file_fclose(&fp_out);
1252  if (unlink_newfile)
1254  }
1255  else
1256  {
1257  mutt_error(_("I don't know how to print that"));
1258  rc = 0;
1259  }
1260 
1261 out:
1262  mutt_buffer_pool_release(&newfile);
1264 
1265  return rc;
1266 }
A mailcap entry.
Definition: mailcap.h:35
struct MailcapEntry * mailcap_entry_new(void)
Allocate memory for a new rfc1524 entry.
Definition: mailcap.c:435
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
#define NONULL(x)
Definition: string2.h:37
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:71
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:206
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
No flags set.
Definition: mutt_attach.h:57
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
FILE * fp_out
File to write to.
Definition: state.h:47
#define MUTT_PRINTING
Are we printing? - MUTT_DISPLAY "light".
Definition: state.h:37
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:884
Container for Accounts, Notifications.
Definition: neomutt.h:36
FILE * fp_in
File to read from.
Definition: state.h:46
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:473
int mailcap_expand_command(struct Body *a, const char *filename, const char *type, struct Buffer *command)
Expand expandos in a command.
Definition: mailcap.c:67
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:543
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
Log at debug level 2.
Definition: logging.h:41
Mailcap print field.
Definition: mailcap.h:59
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
char * subtype
content-type subtype
Definition: body.h:37
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:568
void mailcap_entry_free(struct MailcapEntry **ptr)
Deallocate an struct MailcapEntry.
Definition: mailcap.c:444
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:1014
bool mutt_can_decode(struct Body *a)
Will decoding the attachment produce any output.
Definition: handler.c:1820
char * data
Pointer to data.
Definition: buffer.h:35
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:295
void mutt_rfc3676_space_unstuff_attachment(struct Body *b, const char *filename)
Unstuff attachments.
Definition: rfc3676.c:515
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
char * printcommand
Definition: mailcap.h:42
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:601
char * nametemplate
Definition: mailcap.h:43
#define TYPE(body)
Definition: mime.h:89
Log at debug level 1.
Definition: logging.h:40
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:271
#define mutt_error(...)
Definition: logging.h:84
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
int mutt_pipe_attachment(FILE *fp, struct Body *b, const char *path, char *outfile)
Pipe an attachment to a command.
Definition: mutt_attach.c:717
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:51
+ 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 884 of file mutt_attach.c.

886 {
887  if (!m)
888  return -1;
889 
890  if (fp)
891  {
892  /* recv mode */
893 
894  if (e && m->email && (m->encoding != ENC_BASE64) &&
896  {
897  /* message type attachments are written to mail folders. */
898 
899  char buf[8192];
900  struct Message *msg = NULL;
901  CopyHeaderFlags chflags = CH_NO_FLAGS;
902  int rc = -1;
903 
904  struct Email *e_new = m->email;
905  e_new->msgno = e->msgno; /* required for MH/maildir */
906  e_new->read = true;
907 
908  if (fseeko(fp, m->offset, SEEK_SET) < 0)
909  return -1;
910  if (!fgets(buf, sizeof(buf), fp))
911  return -1;
912  struct Mailbox *m_att = mx_path_resolve(path);
913  if (!mx_mbox_open(m_att, MUTT_APPEND | MUTT_QUIET))
914  {
915  mailbox_free(&m_att);
916  return -1;
917  }
918  msg = mx_msg_open_new(m_att, e_new,
919  is_from(buf, NULL, 0, NULL) ? MUTT_MSG_NO_FLAGS : MUTT_ADD_FROM);
920  if (!msg)
921  {
922  mx_mbox_close(m_att);
923  return -1;
924  }
925  if ((m_att->type == MUTT_MBOX) || (m_att->type == MUTT_MMDF))
926  chflags = CH_FROM | CH_UPDATE_LEN;
927  chflags |= ((m_att->type == MUTT_MAILDIR) ? CH_NOSTATUS : CH_UPDATE);
928  if ((mutt_copy_message_fp(msg->fp, fp, e_new, MUTT_CM_NO_FLAGS, chflags, 0) == 0) &&
929  (mx_msg_commit(m_att, msg) == 0))
930  {
931  rc = 0;
932  }
933  else
934  {
935  rc = -1;
936  }
937 
938  mx_msg_close(m_att, &msg);
939  mx_mbox_close(m_att);
940  return rc;
941  }
942  else
943  {
944  /* In recv mode, extract from folder and decode */
945 
946  struct State s = { 0 };
947 
948  s.fp_out = save_attachment_open(path, opt);
949  if (!s.fp_out)
950  {
951  mutt_perror("fopen");
952  return -1;
953  }
954  fseeko((s.fp_in = fp), m->offset, SEEK_SET);
955  mutt_decode_attachment(m, &s);
956 
957  if (mutt_file_fsync_close(&s.fp_out) != 0)
958  {
959  mutt_perror("fclose");
960  return -1;
961  }
962  }
963  }
964  else
965  {
966  if (!m->filename)
967  return -1;
968 
969  /* In send mode, just copy file */
970 
971  FILE *fp_old = fopen(m->filename, "r");
972  if (!fp_old)
973  {
974  mutt_perror("fopen");
975  return -1;
976  }
977 
978  FILE *fp_new = save_attachment_open(path, opt);
979  if (!fp_new)
980  {
981  mutt_perror("fopen");
982  mutt_file_fclose(&fp_old);
983  return -1;
984  }
985 
986  if (mutt_file_copy_stream(fp_old, fp_new) == -1)
987  {
988  mutt_error(_("Write fault"));
989  mutt_file_fclose(&fp_old);
990  mutt_file_fclose(&fp_new);
991  return -1;
992  }
993  mutt_file_fclose(&fp_old);
994  if (mutt_file_fsync_close(&fp_new) != 0)
995  {
996  mutt_error(_("Write fault"));
997  return -1;
998  }
999  }
1000 
1001  return 0;
1002 }
#define MUTT_MSG_NO_FLAGS
No flags are set.
Definition: mx.h:41
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1860
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
bool mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:303
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition: parse.c:1385
The envelope/body of an email.
Definition: email.h:37
#define mutt_perror(...)
Definition: logging.h:85
int mutt_file_fsync_close(FILE **fp)
Flush the data, before closing a file (and NULL the pointer)
Definition: file.c:169
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
#define CH_FROM
Retain the "From " message separator?
Definition: copy.h:56
#define _(a)
Definition: message.h:28
#define CH_NOSTATUS
Suppress the status and x-status fields.
Definition: copy.h:58
FILE * fp_out
File to write to.
Definition: state.h:47
#define CH_UPDATE
Update the status and x-status fields?
Definition: copy.h:52
#define MUTT_APPEND
Open mailbox for appending messages.
Definition: mxapi.h:62
enum MxStatus mx_mbox_close(struct Mailbox *m)
Save changes and close mailbox.
Definition: mx.c:609
#define MUTT_CM_NO_FLAGS
No flags are set.
Definition: copy.h:35
FILE * fp_in
File to read from.
Definition: state.h:46
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1185
bool read
Email is read.
Definition: email.h:51
struct Message * mx_msg_open_new(struct Mailbox *m, const struct Email *e, MsgOpenFlags flags)
Open a new message.
Definition: mx.c:1053
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:71
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
Base-64 encoded text.
Definition: mime.h:52
&#39;Maildir&#39; Mailbox type
Definition: mailbox.h:51
char * subtype
content-type subtype
Definition: body.h:37
A local copy of an email.
Definition: mxapi.h:41
A mailbox.
Definition: mailbox.h:81
#define CH_NO_FLAGS
No flags are set.
Definition: copy.h:51
&#39;mmdf&#39; Mailbox type
Definition: mailbox.h:49
#define CH_UPDATE_LEN
Update Lines: and Content-Length:
Definition: copy.h:62
#define MUTT_QUIET
Do not print any messages.
Definition: mxapi.h:64
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
&#39;mbox&#39; Mailbox type
Definition: mailbox.h:48
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:271
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition: copy.h:50
#define mutt_error(...)
Definition: logging.h:84
int mx_msg_commit(struct Mailbox *m, struct Message *msg)
Commit a message to a folder - Wrapper for MxOps::msg_commit()
Definition: mx.c:1164
Quoted-printable text.
Definition: mime.h:51
FILE * fp
pointer to the message data
Definition: mxapi.h:43
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition: mx.c:1667
Keep track when processing files.
Definition: state.h:44
static FILE * save_attachment_open(const char *path, enum SaveAttach opt)
Open a file to write an attachment to.
Definition: mutt_attach.c:864
bool is_from(const char *s, char *path, size_t pathlen, time_t *tp)
Is a string a &#39;From&#39; header line?
Definition: from.c:48
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:623
#define MUTT_ADD_FROM
add a From_ line
Definition: mx.h:42
struct Email * email
header information for message/rfc822
Definition: body.h:55
int msgno
Number displayed to the user.
Definition: email.h:87
+ 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 1272 of file mutt_attach.c.

1273 {
1274  mutt_list_insert_tail(&TempAttachmentsList, mutt_str_dup(filename));
1275 }
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:64
+ 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 1280 of file mutt_attach.c.

1281 {
1282  struct ListNode *np = NULL;
1283 
1284  STAILQ_FOREACH(np, &TempAttachmentsList, entries)
1285  {
1286  mutt_file_chmod_add(np->data, S_IWUSR);
1287  mutt_file_unlink(np->data);
1288  }
1289 
1290  mutt_list_free(&TempAttachmentsList);
1291 }
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
char * data
String.
Definition: list.h:36
int mutt_file_chmod_add(const char *path, mode_t mode)
Add permissions to a file.
Definition: file.c:1070
A List node for strings.
Definition: list.h:34
+ Here is the call graph for this function:
+ Here is the caller graph for this function: