NeoMutt  2021-02-05-666-ge300cd
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

◆ 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 1373 of file recvattach.c.

1375 {
1376  do
1377  {
1378  switch (op)
1379  {
1380  case OP_DISPLAY_HEADERS:
1381  bool_str_toggle(NeoMutt->sub, "weed", NULL);
1382  /* fallthrough */
1383 
1384  case OP_VIEW_ATTACH:
1385  {
1386  struct AttachPtr *cur_att = current_attachment(actx, menu);
1387  op = mutt_view_attachment(cur_att->fp, cur_att->body, MUTT_VA_REGULAR,
1388  e, actx, menu->win);
1389  break;
1390  }
1391 
1392  case OP_NEXT_ENTRY:
1393  case OP_MAIN_NEXT_UNDELETED: /* hack */
1394  {
1395  const int index = menu_get_index(menu) + 1;
1396  if (index < menu->max)
1397  {
1398  menu_set_index(menu, index);
1399  op = OP_VIEW_ATTACH;
1400  }
1401  else
1402  op = OP_NULL;
1403  break;
1404  }
1405 
1406  case OP_PREV_ENTRY:
1407  case OP_MAIN_PREV_UNDELETED: /* hack */
1408  {
1409  const int index = menu_get_index(menu) - 1;
1410  if (index >= 0)
1411  {
1412  menu_set_index(menu, index);
1413  op = OP_VIEW_ATTACH;
1414  }
1415  else
1416  op = OP_NULL;
1417  break;
1418  }
1419 
1420  case OP_EDIT_TYPE:
1421  {
1422  struct AttachPtr *cur_att = current_attachment(actx, menu);
1423  /* when we edit the content-type, we should redisplay the attachment
1424  * immediately */
1425  mutt_edit_content_type(e, cur_att->body, cur_att->fp);
1426  if (recv)
1427  recvattach_edit_content_type(sub, actx, menu, e);
1428  else
1429  mutt_edit_content_type(e, cur_att->body, cur_att->fp);
1430 
1432  op = OP_VIEW_ATTACH;
1433  break;
1434  }
1435  /* functions which are passed through from the pager */
1436  case OP_CHECK_TRADITIONAL:
1438  {
1439  op = OP_NULL;
1440  break;
1441  }
1442  /* fallthrough */
1443  case OP_ATTACH_COLLAPSE:
1444  if (recv)
1445  return op;
1446  /* fallthrough */
1447  default:
1448  op = OP_NULL;
1449  }
1450  } while (op != OP_NULL);
1451 
1452  return op;
1453 }
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
struct MuttWindow * win
Window holding the Menu.
Definition: lib.h:76
int bool_str_toggle(struct ConfigSubset *sub, const char *name, struct Buffer *err)
Toggle the value of a bool.
Definition: bool.c:214
#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:128
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:1341
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:1433
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:415
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 788 of file recvattach.c.

790 {
791  char *directory = NULL;
792  int rc = 1;
793  int last = menu_get_index(menu);
794  FILE *fp_out = NULL;
795  int saved_attachments = 0;
796 
797  struct Buffer *buf = mutt_buffer_pool_get();
798  struct Buffer *tfile = mutt_buffer_pool_get();
799 
800  const bool c_attach_split = cs_subset_bool(NeoMutt->sub, "attach_split");
801  const char *const c_attach_sep = cs_subset_string(NeoMutt->sub, "attach_sep");
802  const bool c_attach_save_without_prompting =
803  cs_subset_bool(NeoMutt->sub, "attach_save_without_prompting");
804 
805  for (int i = 0; !tag || (i < actx->idxlen); i++)
806  {
807  if (tag)
808  {
809  fp = actx->idx[i]->fp;
810  top = actx->idx[i]->body;
811  }
812  if (!tag || top->tagged)
813  {
814  if (!c_attach_split)
815  {
816  if (mutt_buffer_is_empty(buf))
817  {
818  enum SaveAttach opt = MUTT_SAVE_NO_FLAGS;
819 
821  prepend_savedir(buf);
822 
823  if ((mutt_buffer_get_field(_("Save to file: "), buf, MUTT_FILE | MUTT_CLEAR,
824  false, NULL, NULL, NULL) != 0) ||
826  {
827  goto cleanup;
828  }
830  if (mutt_check_overwrite(top->filename, mutt_buffer_string(buf), tfile, &opt, NULL))
831  goto cleanup;
832  rc = save_attachment_flowed_helper(fp, top, mutt_buffer_string(tfile), opt, e);
833  if ((rc == 0) && c_attach_sep && (fp_out = fopen(mutt_buffer_string(tfile), "a")))
834  {
835  fprintf(fp_out, "%s", c_attach_sep);
836  mutt_file_fclose(&fp_out);
837  }
838  }
839  else
840  {
842  MUTT_SAVE_APPEND, e);
843  if ((rc == 0) && c_attach_sep && (fp_out = fopen(mutt_buffer_string(tfile), "a")))
844  {
845  fprintf(fp_out, "%s", c_attach_sep);
846  mutt_file_fclose(&fp_out);
847  }
848  }
849  }
850  else
851  {
852  if (tag && menu && top->aptr)
853  {
854  menu_set_index(menu, top->aptr->num);
856 
857  menu_redraw(menu);
858  }
859  if (c_attach_save_without_prompting)
860  {
861  // Save each file, with no prompting, using the configured 'AttachSaveDir'
862  rc = save_without_prompting(fp, top, e);
863  if (rc == 0)
864  saved_attachments++;
865  }
866  else
867  {
868  // Save each file, prompting the user for the location each time.
869  if (query_save_attachment(fp, top, e, &directory) == -1)
870  break;
871  }
872  }
873  }
874  if (!tag)
875  break;
876  }
877 
878  FREE(&directory);
879 
880  if (tag && menu)
881  {
882  menu_set_index(menu, last);
884  }
885 
886  if (rc == 0)
887  {
888  if (!c_attach_split)
889  saved_attachments = 1;
890 
891  if (!c_attach_split || c_attach_save_without_prompting)
892  {
893  mutt_message(ngettext("Attachment saved", "%d attachments saved", saved_attachments),
894  saved_attachments);
895  }
896  }
897 
898 cleanup:
900  mutt_buffer_pool_release(&tfile);
901 }
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:73
#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:268
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:533
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
int menu_redraw(struct Menu *menu)
Redraw the parts of the screen that have been flagged to be redrawn.
Definition: draw.c:546
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:639
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:738
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:317
#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:625
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:322
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:592
Append to existing file.
Definition: mutt_attach.h:58
#define mutt_message(...)
Definition: logging.h:87
#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 1081 of file recvattach.c.

1083 {
1084  struct State state = { 0 };
1085  struct Buffer *buf = NULL;
1086 
1087  if (fp)
1088  filter = false; /* sanity check: we can't filter in the recv case yet */
1089 
1090  buf = mutt_buffer_pool_get();
1091  /* perform charset conversion on text attachments when piping */
1092  state.flags = MUTT_CHARCONV;
1093 
1094  if (mutt_buffer_get_field((filter ? _("Filter through: ") : _("Pipe to: ")),
1095  buf, MUTT_CMD, false, NULL, NULL, NULL) != 0)
1096  {
1097  goto cleanup;
1098  }
1099 
1100  if (mutt_buffer_len(buf) == 0)
1101  goto cleanup;
1102 
1104 
1105  const bool c_attach_split = cs_subset_bool(NeoMutt->sub, "attach_split");
1106  if (!filter && !c_attach_split)
1107  {
1108  mutt_endwin();
1109  pid_t pid = filter_create(mutt_buffer_string(buf), &state.fp_out, NULL, NULL);
1110  pipe_attachment_list(mutt_buffer_string(buf), actx, fp, tag, top, filter, &state);
1111  mutt_file_fclose(&state.fp_out);
1112  const bool c_wait_key = cs_subset_bool(NeoMutt->sub, "wait_key");
1113  if ((filter_wait(pid) != 0) || c_wait_key)
1115  }
1116  else
1117  pipe_attachment_list(mutt_buffer_string(buf), actx, fp, tag, top, filter, &state);
1118 
1119 cleanup:
1121 }
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
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:268
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:422
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:1049
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:455
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:322
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 1240 of file recvattach.c.

1241 {
1242  char prompt[128];
1243  struct State state = { 0 };
1244  int tagmsgcount = 0;
1245 
1246  if (tag)
1247  for (int i = 0; i < actx->idxlen; i++)
1248  if (actx->idx[i]->body->tagged)
1249  tagmsgcount++;
1250 
1251  snprintf(prompt, sizeof(prompt),
1252  /* L10N: Although we now the precise number of tagged messages, we
1253  do not show it to the user. So feel free to use a "generic
1254  plural" as plural translation if your language has one. */
1255  tag ? ngettext("Print tagged attachment?", "Print %d tagged attachments?", tagmsgcount) :
1256  _("Print attachment?"),
1257  tagmsgcount);
1258  const enum QuadOption c_print = cs_subset_quad(NeoMutt->sub, "print");
1259  if (query_quadoption(c_print, prompt) != MUTT_YES)
1260  return;
1261 
1262  const bool c_attach_split = cs_subset_bool(NeoMutt->sub, "attach_split");
1263  if (c_attach_split)
1264  {
1265  print_attachment_list(actx, fp, tag, top, &state);
1266  }
1267  else
1268  {
1269  if (!can_print(actx, top, tag))
1270  return;
1271  mutt_endwin();
1272  const char *const c_print_command =
1273  cs_subset_string(NeoMutt->sub, "print_command");
1274  pid_t pid = filter_create(NONULL(c_print_command), &state.fp_out, NULL, NULL);
1275  print_attachment_list(actx, fp, tag, top, &state);
1276  mutt_file_fclose(&state.fp_out);
1277  const bool c_wait_key = cs_subset_bool(NeoMutt->sub, "wait_key");
1278  if ((filter_wait(pid) != 0) || c_wait_key)
1280  }
1281 }
#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:73
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:1170
#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
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: question.c:347
bool tagged
This attachment is tagged.
Definition: body.h:70
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:422
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
static bool can_print(struct AttachCtx *actx, struct Body *top, bool tag)
Do we know how to print this attachment type?
Definition: recvattach.c:1130
enum QuadOption cs_subset_quad(const struct ConfigSubset *sub, const char *name)
Get a quad-value config item by name.
Definition: helpers.c:218
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:455
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 415 of file mutt_attach.c.

417 {
418  bool use_mailcap = false;
419  bool use_pipe = false;
420  bool use_pager = true;
421  char type[256];
422  char desc[256];
423  char *fname = NULL;
424  struct MailcapEntry *entry = NULL;
425  int rc = -1;
426  bool has_tempfile = false;
427  bool unlink_pagerfile = false;
428 
429  bool is_message = mutt_is_message_type(a->type, a->subtype);
430  if ((WithCrypto != 0) && is_message && a->email &&
432  {
433  return rc;
434  }
435 
436  struct Buffer *tmpfile = mutt_buffer_pool_get();
437  struct Buffer *pagerfile = mutt_buffer_pool_get();
438  struct Buffer *cmd = mutt_buffer_pool_get();
439 
440  use_mailcap = ((mode == MUTT_VA_MAILCAP) ||
441  ((mode == MUTT_VA_REGULAR) && mutt_needs_mailcap(a)) ||
442  (mode == MUTT_VA_PAGER));
443  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
444 
445  char columns[16];
446  snprintf(columns, sizeof(columns), "%d", win->state.cols);
447  mutt_envlist_set("COLUMNS", columns, true);
448 
449  if (use_mailcap)
450  {
451  entry = mailcap_entry_new();
452  enum MailcapLookup mailcap_opt =
454  if (!mailcap_lookup(a, type, sizeof(type), entry, mailcap_opt))
455  {
456  if ((mode == MUTT_VA_REGULAR) || (mode == MUTT_VA_PAGER))
457  {
458  /* fallback to view as text */
459  mailcap_entry_free(&entry);
460  mutt_error(_("No matching mailcap entry found. Viewing as text."));
461  mode = MUTT_VA_AS_TEXT;
462  use_mailcap = false;
463  }
464  else
465  goto return_error;
466  }
467  }
468 
469  if (use_mailcap)
470  {
471  if (!entry->command)
472  {
473  mutt_error(_("MIME type not defined. Can't view attachment."));
474  goto return_error;
475  }
476  mutt_buffer_strcpy(cmd, entry->command);
477 
478  fname = mutt_str_dup(a->filename);
479  /* In send mode(!fp), we allow slashes because those are part of
480  * the tmpfile. The path will be removed in expand_filename */
481  mutt_file_sanitize_filename(fname, fp ? true : false);
482  mailcap_expand_filename(entry->nametemplate, fname, tmpfile);
483  FREE(&fname);
484 
485  if (mutt_save_attachment(fp, a, mutt_buffer_string(tmpfile), 0, NULL) == -1)
486  goto return_error;
487  has_tempfile = true;
488 
490 
491  use_pipe = mailcap_expand_command(a, mutt_buffer_string(tmpfile), type, cmd);
492  use_pager = entry->copiousoutput;
493  }
494 
495  if (use_pager)
496  {
497  if (fp && !use_mailcap && a->filename)
498  {
499  /* recv case */
500  mutt_buffer_strcpy(pagerfile, a->filename);
501  mutt_adv_mktemp(pagerfile);
502  }
503  else
504  mutt_buffer_mktemp(pagerfile);
505  }
506 
507  if (use_mailcap)
508  {
509  pid_t pid = 0;
510  int fd_temp = -1, fd_pager = -1;
511 
512  if (!use_pager)
513  mutt_endwin();
514 
515  const bool c_wait_key = cs_subset_bool(NeoMutt->sub, "wait_key");
516  if (use_pager || use_pipe)
517  {
518  if (use_pager && ((fd_pager = mutt_file_open(mutt_buffer_string(pagerfile),
519  O_CREAT | O_EXCL | O_WRONLY)) == -1))
520  {
521  mutt_perror("open");
522  goto return_error;
523  }
524  unlink_pagerfile = true;
525 
526  if (use_pipe && ((fd_temp = open(mutt_buffer_string(tmpfile), 0)) == -1))
527  {
528  if (fd_pager != -1)
529  close(fd_pager);
530  mutt_perror("open");
531  goto return_error;
532  }
533  unlink_pagerfile = true;
534 
535  pid = filter_create_fd(mutt_buffer_string(cmd), NULL, NULL, NULL,
536  use_pipe ? fd_temp : -1, use_pager ? fd_pager : -1, -1);
537 
538  if (pid == -1)
539  {
540  if (fd_pager != -1)
541  close(fd_pager);
542 
543  if (fd_temp != -1)
544  close(fd_temp);
545 
546  mutt_error(_("Can't create filter"));
547  goto return_error;
548  }
549 
550  if (use_pager)
551  {
552  if (a->description)
553  {
554  snprintf(desc, sizeof(desc), _("---Command: %-20.20s Description: %s"),
556  }
557  else
558  {
559  snprintf(desc, sizeof(desc), _("---Command: %-30.30s Attachment: %s"),
560  mutt_buffer_string(cmd), type);
561  }
562  filter_wait(pid);
563  }
564  else
565  {
566  if (wait_interactive_filter(pid) || (entry->needsterminal && c_wait_key))
568  }
569 
570  if (fd_temp != -1)
571  close(fd_temp);
572  if (fd_pager != -1)
573  close(fd_pager);
574  }
575  else
576  {
577  /* interactive cmd */
578  int rv = mutt_system(mutt_buffer_string(cmd));
579  if (rv == -1)
580  mutt_debug(LL_DEBUG1, "Error running \"%s\"", cmd->data);
581 
582  if ((rv != 0) || (entry->needsterminal && c_wait_key))
584  }
585  }
586  else
587  {
588  /* Don't use mailcap; the attachment is viewed in the pager */
589 
590  if (mode == MUTT_VA_AS_TEXT)
591  {
592  /* just let me see the raw data */
593  if (fp)
594  {
595  /* Viewing from a received message.
596  *
597  * Don't use mutt_save_attachment() because we want to perform charset
598  * conversion since this will be displayed by the internal pager. */
599  struct State decode_state = { 0 };
600 
601  decode_state.fp_out = mutt_file_fopen(mutt_buffer_string(pagerfile), "w");
602  if (!decode_state.fp_out)
603  {
604  mutt_debug(LL_DEBUG1, "mutt_file_fopen(%s) errno=%d %s\n",
605  mutt_buffer_string(pagerfile), errno, strerror(errno));
606  mutt_perror(mutt_buffer_string(pagerfile));
607  goto return_error;
608  }
609  decode_state.fp_in = fp;
610  decode_state.flags = MUTT_CHARCONV;
611  mutt_decode_attachment(a, &decode_state);
612  if (mutt_file_fclose(&decode_state.fp_out) == EOF)
613  {
614  mutt_debug(LL_DEBUG1, "fclose(%s) errno=%d %s\n",
615  mutt_buffer_string(pagerfile), errno, strerror(errno));
616  }
617  }
618  else
619  {
620  /* in compose mode, just copy the file. we can't use
621  * mutt_decode_attachment() since it assumes the content-encoding has
622  * already been applied */
623  if (mutt_save_attachment(fp, a, mutt_buffer_string(pagerfile), MUTT_SAVE_NO_FLAGS, NULL))
624  goto return_error;
625  unlink_pagerfile = true;
626  }
628  }
629  else
630  {
631  /* Use built-in handler */
632  OptViewAttach = true; /* disable the "use 'v' to view this part"
633  * message in case of error */
634  if (mutt_decode_save_attachment(fp, a, mutt_buffer_string(pagerfile),
636  {
637  OptViewAttach = false;
638  goto return_error;
639  }
640  unlink_pagerfile = true;
641  OptViewAttach = false;
642  }
643 
644  if (a->description)
645  mutt_str_copy(desc, a->description, sizeof(desc));
646  else if (a->filename)
647  snprintf(desc, sizeof(desc), _("---Attachment: %s: %s"), a->filename, type);
648  else
649  snprintf(desc, sizeof(desc), _("---Attachment: %s"), type);
650  }
651 
652  /* We only reach this point if there have been no errors */
653 
654  if (use_pager)
655  {
656  struct PagerData pdata = { 0 };
657  struct PagerView pview = { &pdata };
658 
659  pdata.actx = actx;
660  pdata.body = a;
661  pdata.fname = mutt_buffer_string(pagerfile);
662  pdata.fp = fp;
663 
664  pview.banner = desc;
665  pview.flags = MUTT_PAGER_ATTACHMENT |
666  (is_message ? MUTT_PAGER_MESSAGE : MUTT_PAGER_NO_FLAGS) |
667  ((use_mailcap && entry->xneomuttnowrap) ? MUTT_PAGER_NOWRAP :
669  pview.mode = PAGER_MODE_ATTACH;
670 
671  rc = mutt_do_pager(&pview, e);
672 
673  mutt_buffer_reset(pagerfile);
674  unlink_pagerfile = false;
675  }
676  else
677  rc = 0;
678 
679 return_error:
680 
681  if (!entry || !entry->xneomuttkeep)
682  {
683  if ((fp && !mutt_buffer_is_empty(tmpfile)) || has_tempfile)
684  {
685  /* add temporary file to TempAttachmentsList to be deleted on timeout hook */
687  }
688  }
689 
690  mailcap_entry_free(&entry);
691 
692  if (unlink_pagerfile)
694 
695  mutt_buffer_pool_release(&tmpfile);
696  mutt_buffer_pool_release(&pagerfile);
698  mutt_envlist_unset("COLUMNS");
699 
700  return rc;
701 }
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:1861
struct MailcapEntry * mailcap_entry_new(void)
Allocate memory for a new rfc1524 entry.
Definition: mailcap.c:437
#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:73
#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_CHARCONV
Do character set conversions.
Definition: state.h:36
#define mutt_error(...)
Definition: logging.h:88
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:145
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:154
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
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:879
View using default method.
Definition: mutt_attach.h:43
#define mutt_perror(...)
Definition: logging.h:89
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:475
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:545
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
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:135
Data to be displayed by PagerView.
Definition: lib.h:143
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:70
static int wait_interactive_filter(pid_t pid)
Wait after an interactive filter.
Definition: mutt_attach.c:382
void mutt_add_temp_attachment(const char *filename)
Add file to list of temporary attachments.
Definition: mutt_attach.c:1267
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:157
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:60
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:127
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:422
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:66
void mailcap_entry_free(struct MailcapEntry **ptr)
Deallocate an struct MailcapEntry.
Definition: mailcap.c:446
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:1009
int mutt_do_pager(struct PagerView *pview, struct Email *e)
Display some page-able text to the user (help or attachment)
Definition: do_pager.c:120
char * data
Pointer to data.
Definition: buffer.h:35
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:158
char * description
content-description
Definition: body.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
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:147
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:455
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:749
FILE * fp
Source stream.
Definition: lib.h:146
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
bool mutt_needs_mailcap(struct Body *m)
Does this type need a mailcap entry do display.
Definition: muttlib.c:406
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:132
void mutt_adv_mktemp(struct Buffer *buf)
Create a temporary file.
Definition: muttlib.c:83
#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:54
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:67
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
const char * fname
Name of the file to read.
Definition: lib.h:148
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:54
const char * banner
Title to display in status bar.
Definition: lib.h:159
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 335 of file mutt_attach.c.

336 {
337  struct ListNode *np = NULL;
338  STAILQ_FOREACH(np, &MimeLookupList, entries)
339  {
340  const int i = mutt_str_len(np->data) - 1;
341  if (((i > 0) && (np->data[i - 1] == '/') && (np->data[i] == '*') &&
342  mutt_istrn_equal(type, np->data, i)) ||
343  mutt_istr_equal(type, np->data))
344  {
345  struct Body tmp = { 0 };
346  enum ContentType n;
347  if ((n = mutt_lookup_mime_type(&tmp, b->filename)) != TYPE_OTHER ||
348  (n = mutt_lookup_mime_type(&tmp, b->description)) != TYPE_OTHER)
349  {
350  snprintf(type, len, "%s/%s",
351  (n == TYPE_AUDIO) ? "audio" :
352  (n == TYPE_APPLICATION) ? "application" :
353  (n == TYPE_IMAGE) ? "image" :
354  (n == TYPE_MESSAGE) ? "message" :
355  (n == TYPE_MODEL) ? "model" :
356  (n == TYPE_MULTIPART) ? "multipart" :
357  (n == TYPE_TEXT) ? "text" :
358  (n == TYPE_VIDEO) ? "video" :
359  "other",
360  tmp.subtype);
361  mutt_debug(LL_DEBUG1, "\"%s\" -> %s\n", b->filename, type);
362  }
363  FREE(&tmp.subtype);
364  FREE(&tmp.xtype);
365  }
366  }
367 }
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:916
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:352
char * description
content-description
Definition: body.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
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:664
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
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 118 of file mutt_attach.c.

119 {
120  char type[256];
121  struct MailcapEntry *entry = mailcap_entry_new();
122  bool unlink_newfile = false;
123  int rc = 0;
124  struct Buffer *cmd = mutt_buffer_pool_get();
125  struct Buffer *newfile = mutt_buffer_pool_get();
126  struct Buffer *tmpfile = mutt_buffer_pool_get();
127 
128  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
129  if (mailcap_lookup(a, type, sizeof(type), entry, MUTT_MC_COMPOSE))
130  {
131  if (entry->composecommand || entry->composetypecommand)
132  {
133  if (entry->composetypecommand)
135  else
136  mutt_buffer_strcpy(cmd, entry->composecommand);
137 
138  mailcap_expand_filename(entry->nametemplate, a->filename, newfile);
139  mutt_debug(LL_DEBUG1, "oldfile: %s newfile: %s\n", a->filename,
140  mutt_buffer_string(newfile));
141  if (mutt_file_symlink(a->filename, mutt_buffer_string(newfile)) == -1)
142  {
143  if (mutt_yesorno(_("Can't match 'nametemplate', continue?"), MUTT_YES) != MUTT_YES)
144  goto bailout;
145  mutt_buffer_strcpy(newfile, a->filename);
146  }
147  else
148  unlink_newfile = true;
149 
150  if (mailcap_expand_command(a, mutt_buffer_string(newfile), type, cmd))
151  {
152  /* For now, editing requires a file, no piping */
153  mutt_error(_("Mailcap compose entry requires %%s"));
154  }
155  else
156  {
157  int r;
158 
159  mutt_endwin();
161  if (r == -1)
162  mutt_error(_("Error running \"%s\""), mutt_buffer_string(cmd));
163 
164  if ((r != -1) && entry->composetypecommand)
165  {
166  struct Body *b = NULL;
167 
168  FILE *fp = mutt_file_fopen(a->filename, "r");
169  if (!fp)
170  {
171  mutt_perror(_("Failure to open file to parse headers"));
172  goto bailout;
173  }
174 
175  b = mutt_read_mime_header(fp, 0);
176  if (b)
177  {
178  if (!TAILQ_EMPTY(&b->parameter))
179  {
181  a->parameter = b->parameter;
182  TAILQ_INIT(&b->parameter);
183  }
184  if (b->description)
185  {
186  FREE(&a->description);
187  a->description = b->description;
188  b->description = NULL;
189  }
190  if (b->form_name)
191  {
192  FREE(&a->form_name);
193  a->form_name = b->form_name;
194  b->form_name = NULL;
195  }
196 
197  /* Remove headers by copying out data to another file, then
198  * copying the file back */
199  fseeko(fp, b->offset, SEEK_SET);
200  mutt_body_free(&b);
201  mutt_buffer_mktemp(tmpfile);
202  FILE *fp_tmp = mutt_file_fopen(mutt_buffer_string(tmpfile), "w");
203  if (!fp_tmp)
204  {
205  mutt_perror(_("Failure to open file to strip headers"));
206  mutt_file_fclose(&fp);
207  goto bailout;
208  }
209  mutt_file_copy_stream(fp, fp_tmp);
210  mutt_file_fclose(&fp);
211  mutt_file_fclose(&fp_tmp);
213  if (mutt_file_rename(mutt_buffer_string(tmpfile), a->filename) != 0)
214  {
215  mutt_perror(_("Failure to rename file"));
216  goto bailout;
217  }
218  }
219  }
220  }
221  }
222  }
223  else
224  {
225  mutt_message(_("No mailcap compose entry for %s, creating empty file"), type);
226  rc = 1;
227  goto bailout;
228  }
229 
230  rc = 1;
231 
232 bailout:
233 
234  if (unlink_newfile)
235  unlink(mutt_buffer_string(newfile));
236 
238  mutt_buffer_pool_release(&newfile);
239  mutt_buffer_pool_release(&tmpfile);
240 
241  mailcap_entry_free(&entry);
242  return rc;
243 }
A mailcap entry.
Definition: mailcap.h:35
struct MailcapEntry * mailcap_entry_new(void)
Allocate memory for a new rfc1524 entry.
Definition: mailcap.c:437
#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_error(...)
Definition: logging.h:88
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
#define mutt_perror(...)
Definition: logging.h:89
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:475
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:545
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
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:765
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:422
void mailcap_entry_free(struct MailcapEntry **ptr)
Deallocate an struct MailcapEntry.
Definition: mailcap.c:446
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
char * description
content-description
Definition: body.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:180
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
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 mutt_message(...)
Definition: logging.h:87
#define FREE(x)
Definition: memory.h:40
#define TAILQ_EMPTY(head)
Definition: queue.h:721
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 1009 of file mutt_attach.c.

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

259 {
260  char type[256];
261  struct MailcapEntry *entry = mailcap_entry_new();
262  bool unlink_newfile = false;
263  int rc = 0;
264  struct Buffer *cmd = mutt_buffer_pool_get();
265  struct Buffer *newfile = mutt_buffer_pool_get();
266 
267  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
268  if (mailcap_lookup(a, type, sizeof(type), entry, MUTT_MC_EDIT))
269  {
270  if (entry->editcommand)
271  {
272  mutt_buffer_strcpy(cmd, entry->editcommand);
273  mailcap_expand_filename(entry->nametemplate, a->filename, newfile);
274  mutt_debug(LL_DEBUG1, "oldfile: %s newfile: %s\n", a->filename,
275  mutt_buffer_string(newfile));
276  if (mutt_file_symlink(a->filename, mutt_buffer_string(newfile)) == -1)
277  {
278  if (mutt_yesorno(_("Can't match 'nametemplate', continue?"), MUTT_YES) != MUTT_YES)
279  goto bailout;
280  mutt_buffer_strcpy(newfile, a->filename);
281  }
282  else
283  unlink_newfile = true;
284 
285  if (mailcap_expand_command(a, mutt_buffer_string(newfile), type, cmd))
286  {
287  /* For now, editing requires a file, no piping */
288  mutt_error(_("Mailcap Edit entry requires %%s"));
289  goto bailout;
290  }
291  else
292  {
293  mutt_endwin();
294  if (mutt_system(mutt_buffer_string(cmd)) == -1)
295  {
296  mutt_error(_("Error running \"%s\""), mutt_buffer_string(cmd));
297  goto bailout;
298  }
299  }
300  }
301  }
302  else if (a->type == TYPE_TEXT)
303  {
304  /* On text, default to editor */
305  const char *const c_editor = cs_subset_string(NeoMutt->sub, "editor");
306  mutt_edit_file(NONULL(c_editor), a->filename);
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 }
A mailcap entry.
Definition: mailcap.h:35
struct MailcapEntry * mailcap_entry_new(void)
Allocate memory for a new rfc1524 entry.
Definition: mailcap.c:437
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
#define mutt_error(...)
Definition: logging.h:88
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:475
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:545
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
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:422
void mailcap_entry_free(struct MailcapEntry **ptr)
Deallocate an struct MailcapEntry.
Definition: mailcap.c:446
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:317
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:180
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
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:380
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 68 of file mutt_attach.c.

69 {
70  char type[256];
71  struct stat st;
72 
73  if (a->unlink)
74  return 0;
75 
76  struct Buffer *tmpfile = mutt_buffer_pool_get();
77  struct MailcapEntry *entry = mailcap_entry_new();
78  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
79  mailcap_lookup(a, type, sizeof(type), entry, MUTT_MC_NO_FLAGS);
80  mailcap_expand_filename(entry->nametemplate, a->filename, tmpfile);
81 
82  mailcap_entry_free(&entry);
83 
84  if (stat(a->filename, &st) == -1)
85  {
86  mutt_buffer_pool_release(&tmpfile);
87  return -1;
88  }
89 
90  FILE *fp_in = NULL, *fp_out = NULL;
91  if ((fp_in = fopen(a->filename, "r")) &&
92  (fp_out = mutt_file_fopen(mutt_buffer_string(tmpfile), "w")))
93  {
94  mutt_file_copy_stream(fp_in, fp_out);
96  a->unlink = true;
97 
98  if (a->stamp >= st.st_mtime)
100  }
101  else
102  mutt_perror(fp_in ? mutt_buffer_string(tmpfile) : a->filename);
103 
104  mutt_file_fclose(&fp_in);
105  mutt_file_fclose(&fp_out);
106 
107  mutt_buffer_pool_release(&tmpfile);
108 
109  return a->unlink ? 0 : -1;
110 }
A mailcap entry.
Definition: mailcap.h:35
struct MailcapEntry * mailcap_entry_new(void)
Allocate memory for a new rfc1524 entry.
Definition: mailcap.c:437
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
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
#define mutt_perror(...)
Definition: logging.h:89
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:475
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:545
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:446
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 712 of file mutt_attach.c.

713 {
714  pid_t pid = 0;
715  int out = -1, rc = 0;
716  bool is_flowed = false;
717  bool unlink_unstuff = false;
718  FILE *fp_filter = NULL, *fp_unstuff = NULL, *fp_in = NULL;
719  struct Buffer *unstuff_tempfile = NULL;
720 
721  if (outfile && *outfile)
722  {
723  out = mutt_file_open(outfile, O_CREAT | O_EXCL | O_WRONLY);
724  if (out < 0)
725  {
726  mutt_perror("open");
727  return 0;
728  }
729  }
730 
732  {
733  is_flowed = true;
734  unstuff_tempfile = mutt_buffer_pool_get();
735  mutt_buffer_mktemp(unstuff_tempfile);
736  }
737 
738  mutt_endwin();
739 
740  if (outfile && *outfile)
741  pid = filter_create_fd(path, &fp_filter, NULL, NULL, -1, out, -1);
742  else
743  pid = filter_create(path, &fp_filter, NULL, NULL);
744  if (pid < 0)
745  {
746  mutt_perror(_("Can't create filter"));
747  goto bail;
748  }
749 
750  /* recv case */
751  if (fp)
752  {
753  struct State s = { 0 };
754 
755  /* perform charset conversion on text attachments when piping */
756  s.flags = MUTT_CHARCONV;
757 
758  if (is_flowed)
759  {
760  fp_unstuff = mutt_file_fopen(mutt_buffer_string(unstuff_tempfile), "w");
761  if (fp_unstuff == NULL)
762  {
763  mutt_perror("mutt_file_fopen");
764  goto bail;
765  }
766  unlink_unstuff = true;
767 
768  s.fp_in = fp;
769  s.fp_out = fp_unstuff;
770  mutt_decode_attachment(b, &s);
771  mutt_file_fclose(&fp_unstuff);
772 
774 
775  fp_unstuff = mutt_file_fopen(mutt_buffer_string(unstuff_tempfile), "r");
776  if (fp_unstuff == NULL)
777  {
778  mutt_perror("mutt_file_fopen");
779  goto bail;
780  }
781  mutt_file_copy_stream(fp_unstuff, fp_filter);
782  mutt_file_fclose(&fp_unstuff);
783  }
784  else
785  {
786  s.fp_in = fp;
787  s.fp_out = fp_filter;
788  mutt_decode_attachment(b, &s);
789  }
790  }
791 
792  /* send case */
793  else
794  {
795  const char *infile = NULL;
796 
797  if (is_flowed)
798  {
799  if (mutt_save_attachment(fp, b, mutt_buffer_string(unstuff_tempfile),
800  MUTT_SAVE_NO_FLAGS, NULL) == -1)
801  {
802  goto bail;
803  }
804  unlink_unstuff = true;
806  infile = mutt_buffer_string(unstuff_tempfile);
807  }
808  else
809  infile = b->filename;
810 
811  fp_in = fopen(infile, "r");
812  if (!fp_in)
813  {
814  mutt_perror("fopen");
815  goto bail;
816  }
817 
818  mutt_file_copy_stream(fp_in, fp_filter);
819  mutt_file_fclose(&fp_in);
820  }
821 
822  mutt_file_fclose(&fp_filter);
823  rc = 1;
824 
825 bail:
826  if (outfile && *outfile)
827  {
828  close(out);
829  if (rc == 0)
830  unlink(outfile);
831  else if (is_flowed)
833  }
834 
835  mutt_file_fclose(&fp_unstuff);
836  mutt_file_fclose(&fp_filter);
837  mutt_file_fclose(&fp_in);
838 
839  if (unlink_unstuff)
840  mutt_file_unlink(mutt_buffer_string(unstuff_tempfile));
841  mutt_buffer_pool_release(&unstuff_tempfile);
842 
843  /* check for error exit from child process */
844  if ((pid > 0) && (filter_wait(pid) != 0))
845  rc = 0;
846 
847  const bool c_wait_key = cs_subset_bool(NeoMutt->sub, "wait_key");
848  if ((rc == 0) || c_wait_key)
850  return rc;
851 }
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1861
#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:73
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
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:879
#define mutt_perror(...)
Definition: logging.h:89
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:422
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:455
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 1108 of file mutt_attach.c.

1109 {
1110  char type[256];
1111  pid_t pid;
1112  FILE *fp_in = NULL, *fp_out = NULL;
1113  bool unlink_newfile = false;
1114  struct Buffer *newfile = mutt_buffer_pool_get();
1115  struct Buffer *cmd = mutt_buffer_pool_get();
1116 
1117  int rc = 0;
1118 
1119  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
1120 
1121  if (mailcap_lookup(a, type, sizeof(type), NULL, MUTT_MC_PRINT))
1122  {
1123  int piped = false;
1124 
1125  mutt_debug(LL_DEBUG2, "Using mailcap\n");
1126 
1127  struct MailcapEntry *entry = mailcap_entry_new();
1128  mailcap_lookup(a, type, sizeof(type), entry, MUTT_MC_PRINT);
1129  mailcap_expand_filename(entry->nametemplate, a->filename, newfile);
1130 
1131  if (mutt_save_attachment(fp, a, mutt_buffer_string(newfile),
1132  MUTT_SAVE_NO_FLAGS, NULL) == -1)
1133  {
1134  goto mailcap_cleanup;
1135  }
1136  unlink_newfile = 1;
1137 
1139 
1140  mutt_buffer_strcpy(cmd, entry->printcommand);
1141  piped = mailcap_expand_command(a, mutt_buffer_string(newfile), type, cmd);
1142 
1143  mutt_endwin();
1144 
1145  const bool c_wait_key = cs_subset_bool(NeoMutt->sub, "wait_key");
1146  /* interactive program */
1147  if (piped)
1148  {
1149  fp_in = fopen(mutt_buffer_string(newfile), "r");
1150  if (!fp_in)
1151  {
1152  mutt_perror("fopen");
1153  mailcap_entry_free(&entry);
1154  goto mailcap_cleanup;
1155  }
1156 
1157  pid = filter_create(mutt_buffer_string(cmd), &fp_out, NULL, NULL);
1158  if (pid < 0)
1159  {
1160  mutt_perror(_("Can't create filter"));
1161  mailcap_entry_free(&entry);
1162  mutt_file_fclose(&fp_in);
1163  goto mailcap_cleanup;
1164  }
1165  mutt_file_copy_stream(fp_in, fp_out);
1166  mutt_file_fclose(&fp_out);
1167  mutt_file_fclose(&fp_in);
1168  if (filter_wait(pid) || c_wait_key)
1170  }
1171  else
1172  {
1173  int rc2 = mutt_system(mutt_buffer_string(cmd));
1174  if (rc2 == -1)
1175  mutt_debug(LL_DEBUG1, "Error running \"%s\"", cmd->data);
1176 
1177  if ((rc2 != 0) || c_wait_key)
1179  }
1180 
1181  rc = 1;
1182 
1183  mailcap_cleanup:
1184  if (unlink_newfile)
1186 
1187  mailcap_entry_free(&entry);
1188  goto out;
1189  }
1190 
1191  const char *const c_print_command =
1192  cs_subset_string(NeoMutt->sub, "print_command");
1193  if (mutt_istr_equal("text/plain", type) ||
1194  mutt_istr_equal("application/postscript", type))
1195  {
1196  rc = (mutt_pipe_attachment(fp, a, NONULL(c_print_command), NULL));
1197  goto out;
1198  }
1199  else if (mutt_can_decode(a))
1200  {
1201  /* decode and print */
1202 
1203  fp_in = NULL;
1204  fp_out = NULL;
1205 
1206  mutt_buffer_mktemp(newfile);
1207  if (mutt_decode_save_attachment(fp, a, mutt_buffer_string(newfile),
1209  {
1210  unlink_newfile = true;
1211  mutt_debug(LL_DEBUG2, "successfully decoded %s type attachment to %s\n",
1212  type, mutt_buffer_string(newfile));
1213 
1214  fp_in = fopen(mutt_buffer_string(newfile), "r");
1215  if (!fp_in)
1216  {
1217  mutt_perror("fopen");
1218  goto decode_cleanup;
1219  }
1220 
1221  mutt_debug(LL_DEBUG2, "successfully opened %s read-only\n",
1222  mutt_buffer_string(newfile));
1223 
1224  mutt_endwin();
1225  pid = filter_create(NONULL(c_print_command), &fp_out, NULL, NULL);
1226  if (pid < 0)
1227  {
1228  mutt_perror(_("Can't create filter"));
1229  goto decode_cleanup;
1230  }
1231 
1232  mutt_debug(LL_DEBUG2, "Filter created\n");
1233 
1234  mutt_file_copy_stream(fp_in, fp_out);
1235 
1236  mutt_file_fclose(&fp_out);
1237  mutt_file_fclose(&fp_in);
1238 
1239  const bool c_wait_key = cs_subset_bool(NeoMutt->sub, "wait_key");
1240  if ((filter_wait(pid) != 0) || c_wait_key)
1242  rc = 1;
1243  }
1244  decode_cleanup:
1245  mutt_file_fclose(&fp_in);
1246  mutt_file_fclose(&fp_out);
1247  if (unlink_newfile)
1249  }
1250  else
1251  {
1252  mutt_error(_("I don't know how to print that"));
1253  rc = 0;
1254  }
1255 
1256 out:
1257  mutt_buffer_pool_release(&newfile);
1259 
1260  return rc;
1261 }
A mailcap entry.
Definition: mailcap.h:35
struct MailcapEntry * mailcap_entry_new(void)
Allocate memory for a new rfc1524 entry.
Definition: mailcap.c:437
#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:73
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_error(...)
Definition: logging.h:88
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:879
#define mutt_perror(...)
Definition: logging.h:89
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:475
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:545
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:916
char * subtype
content-type subtype
Definition: body.h:37
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:422
void mailcap_entry_free(struct MailcapEntry **ptr)
Deallocate an struct MailcapEntry.
Definition: mailcap.c:446
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:1009
bool mutt_can_decode(struct Body *a)
Will decoding the attachment produce any output.
Definition: handler.c:1821
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:317
void mutt_rfc3676_space_unstuff_attachment(struct Body *b, const char *filename)
Unstuff attachments.
Definition: rfc3676.c:515
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
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:455
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
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:712
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 879 of file mutt_attach.c.

881 {
882  if (!m)
883  return -1;
884 
885  if (fp)
886  {
887  /* recv mode */
888 
889  if (e && m->email && (m->encoding != ENC_BASE64) &&
891  {
892  /* message type attachments are written to mail folders. */
893 
894  char buf[8192];
895  struct Message *msg = NULL;
896  CopyHeaderFlags chflags = CH_NO_FLAGS;
897  int rc = -1;
898 
899  struct Email *e_new = m->email;
900  e_new->msgno = e->msgno; /* required for MH/maildir */
901  e_new->read = true;
902 
903  if (fseeko(fp, m->offset, SEEK_SET) < 0)
904  return -1;
905  if (!fgets(buf, sizeof(buf), fp))
906  return -1;
907  struct Mailbox *m_att = mx_path_resolve(path);
908  if (!mx_mbox_open(m_att, MUTT_APPEND | MUTT_QUIET))
909  {
910  mailbox_free(&m_att);
911  return -1;
912  }
913  msg = mx_msg_open_new(m_att, e_new,
914  is_from(buf, NULL, 0, NULL) ? MUTT_MSG_NO_FLAGS : MUTT_ADD_FROM);
915  if (!msg)
916  {
917  mx_mbox_close(m_att);
918  return -1;
919  }
920  if ((m_att->type == MUTT_MBOX) || (m_att->type == MUTT_MMDF))
921  chflags = CH_FROM | CH_UPDATE_LEN;
922  chflags |= ((m_att->type == MUTT_MAILDIR) ? CH_NOSTATUS : CH_UPDATE);
923  if ((mutt_copy_message_fp(msg->fp, fp, e_new, MUTT_CM_NO_FLAGS, chflags, 0) == 0) &&
924  (mx_msg_commit(m_att, msg) == 0))
925  {
926  rc = 0;
927  }
928  else
929  {
930  rc = -1;
931  }
932 
933  mx_msg_close(m_att, &msg);
934  mx_mbox_close(m_att);
935  return rc;
936  }
937  else
938  {
939  /* In recv mode, extract from folder and decode */
940 
941  struct State s = { 0 };
942 
943  s.fp_out = save_attachment_open(path, opt);
944  if (!s.fp_out)
945  {
946  mutt_perror("fopen");
947  return -1;
948  }
949  fseeko((s.fp_in = fp), m->offset, SEEK_SET);
950  mutt_decode_attachment(m, &s);
951 
952  if (mutt_file_fsync_close(&s.fp_out) != 0)
953  {
954  mutt_perror("fclose");
955  return -1;
956  }
957  }
958  }
959  else
960  {
961  if (!m->filename)
962  return -1;
963 
964  /* In send mode, just copy file */
965 
966  FILE *fp_old = fopen(m->filename, "r");
967  if (!fp_old)
968  {
969  mutt_perror("fopen");
970  return -1;
971  }
972 
973  FILE *fp_new = save_attachment_open(path, opt);
974  if (!fp_new)
975  {
976  mutt_perror("fopen");
977  mutt_file_fclose(&fp_old);
978  return -1;
979  }
980 
981  if (mutt_file_copy_stream(fp_old, fp_new) == -1)
982  {
983  mutt_error(_("Write fault"));
984  mutt_file_fclose(&fp_old);
985  mutt_file_fclose(&fp_new);
986  return -1;
987  }
988  mutt_file_fclose(&fp_old);
989  if (mutt_file_fsync_close(&fp_new) != 0)
990  {
991  mutt_error(_("Write fault"));
992  return -1;
993  }
994  }
995 
996  return 0;
997 }
#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:1861
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:304
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_error(...)
Definition: logging.h:88
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:610
#define MUTT_CM_NO_FLAGS
No flags are set.
Definition: copy.h:35
#define mutt_perror(...)
Definition: logging.h:89
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:1186
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:1054
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:87
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
int mx_msg_commit(struct Mailbox *m, struct Message *msg)
Commit a message to a folder - Wrapper for MxOps::msg_commit()
Definition: mx.c:1165
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:1668
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:859
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:629
#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 1267 of file mutt_attach.c.

1268 {
1269  mutt_list_insert_tail(&TempAttachmentsList, mutt_str_dup(filename));
1270 }
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 1275 of file mutt_attach.c.

1276 {
1277  struct ListNode *np = NULL;
1278 
1279  STAILQ_FOREACH(np, &TempAttachmentsList, entries)
1280  {
1281  mutt_file_chmod_add(np->data, S_IWUSR);
1282  mutt_file_unlink(np->data);
1283  }
1284 
1285  mutt_list_free(&TempAttachmentsList);
1286 }
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:352
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: