NeoMutt  2018-07-16 +1360-3df4a2
Teaching an old dog new tricks
DOXYGEN
mutt_attach.c File Reference

Handling of email attachments. More...

#include "config.h"
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "mutt/mutt.h"
#include "config/lib.h"
#include "email/lib.h"
#include "mutt.h"
#include "mutt_attach.h"
#include "context.h"
#include "copy.h"
#include "curs_lib.h"
#include "filter.h"
#include "globals.h"
#include "handler.h"
#include "mailbox.h"
#include "muttlib.h"
#include "mx.h"
#include "ncrypt/ncrypt.h"
#include "options.h"
#include "pager.h"
#include "protos.h"
#include "rfc1524.h"
#include "sendlib.h"
#include "state.h"
+ Include dependency graph for mutt_attach.c:

Go to the source code of this file.

Functions

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

Detailed Description

Handling of email attachments.

Authors
  • Michael R. Elkins
  • Thomas Roessler

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file mutt_attach.c.

Function Documentation

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  char tempfile[PATH_MAX];
71  struct stat st;
72 
73  if (a->unlink)
74  return 0;
75 
76  struct Rfc1524MailcapEntry *entry = rfc1524_new_entry();
77  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
79  rfc1524_expand_filename(entry->nametemplate, a->filename, tempfile, sizeof(tempfile));
80 
81  rfc1524_free_entry(&entry);
82 
83  if (stat(a->filename, &st) == -1)
84  return -1;
85 
86  FILE *fp_in = NULL, *fp_out = NULL;
87  if ((fp_in = fopen(a->filename, "r")) && (fp_out = mutt_file_fopen(tempfile, "w")))
88  {
89  mutt_file_copy_stream(fp_in, fp_out);
90  mutt_str_replace(&a->filename, tempfile);
91  a->unlink = true;
92 
93  if (a->stamp >= st.st_mtime)
95  }
96  else
97  mutt_perror(fp_in ? tempfile : a->filename);
98 
99  mutt_file_fclose(&fp_in);
100  mutt_file_fclose(&fp_out);
101 
102  return a->unlink ? 0 : -1;
103 }
void mutt_stamp_attachment(struct Body *a)
Timestamp an Attachment.
Definition: sendlib.c:1391
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:48
#define mutt_perror(...)
Definition: logging.h:89
bool rfc1524_mailcap_lookup(struct Body *a, char *type, struct Rfc1524MailcapEntry *entry, enum MailcapLookup opt)
Find given type in the list of mailcap files.
Definition: rfc1524.c:437
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
char * nametemplate
Definition: rfc1524.h:45
char * subtype
content-type subtype
Definition: body.h:37
void rfc1524_free_entry(struct Rfc1524MailcapEntry **entry)
Deallocate an struct Rfc1524MailcapEntry.
Definition: rfc1524.c:409
#define PATH_MAX
Definition: mutt.h:48
A mailcap entry.
Definition: rfc1524.h:37
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:459
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:546
#define TYPE(body)
Definition: mime.h:83
No flags set.
Definition: rfc1524.h:57
time_t stamp
time stamp of last encoding update.
Definition: body.h:66
bool unlink
flag to indicate the file named by "filename" should be unlink()ed before free()ing this structure ...
Definition: body.h:74
struct Rfc1524MailcapEntry * rfc1524_new_entry(void)
Allocate memory for a new rfc1524 entry.
Definition: rfc1524.c:400
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:263
int rfc1524_expand_filename(const char *nametemplate, const char *oldfile, char *newfile, size_t nflen)
Expand a new filename from a template or existing filename.
Definition: rfc1524.c:503

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int mutt_compose_attachment ( struct Body a)

Create an attachment.

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

Definition at line 111 of file mutt_attach.c.

112 {
113  char type[256];
114  char cmd[STR_COMMAND];
115  char newfile[PATH_MAX] = "";
116  struct Rfc1524MailcapEntry *entry = rfc1524_new_entry();
117  bool unlink_newfile = false;
118  int rc = 0;
119 
120  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
121  if (rfc1524_mailcap_lookup(a, type, entry, MUTT_MC_COMPOSE))
122  {
123  if (entry->composecommand || entry->composetypecommand)
124  {
125  if (entry->composetypecommand)
126  mutt_str_strfcpy(cmd, entry->composetypecommand, sizeof(cmd));
127  else
128  mutt_str_strfcpy(cmd, entry->composecommand, sizeof(cmd));
129  if (rfc1524_expand_filename(entry->nametemplate, a->filename, newfile, sizeof(newfile)))
130  {
131  mutt_debug(LL_DEBUG1, "oldfile: %s\t newfile: %s\n", a->filename, newfile);
132  if (mutt_file_symlink(a->filename, newfile) == -1)
133  {
134  if (mutt_yesorno(_("Can't match nametemplate, continue?"), MUTT_YES) != MUTT_YES)
135  goto bailout;
136  }
137  else
138  unlink_newfile = true;
139  }
140  else
141  mutt_str_strfcpy(newfile, a->filename, sizeof(newfile));
142 
143  if (rfc1524_expand_command(a, newfile, type, cmd, sizeof(cmd)))
144  {
145  /* For now, editing requires a file, no piping */
146  mutt_error(_("Mailcap compose entry requires %%s"));
147  }
148  else
149  {
150  int r;
151 
152  mutt_endwin();
153  r = mutt_system(cmd);
154  if (r == -1)
155  mutt_error(_("Error running \"%s\""), cmd);
156 
157  if ((r != -1) && entry->composetypecommand)
158  {
159  struct Body *b = NULL;
160  char tempfile[PATH_MAX];
161 
162  FILE *fp = mutt_file_fopen(a->filename, "r");
163  if (!fp)
164  {
165  mutt_perror(_("Failure to open file to parse headers"));
166  goto bailout;
167  }
168 
169  b = mutt_read_mime_header(fp, 0);
170  if (b)
171  {
172  if (!TAILQ_EMPTY(&b->parameter))
173  {
175  a->parameter = b->parameter;
176  TAILQ_INIT(&b->parameter);
177  }
178  if (b->description)
179  {
180  FREE(&a->description);
181  a->description = b->description;
182  b->description = NULL;
183  }
184  if (b->form_name)
185  {
186  FREE(&a->form_name);
187  a->form_name = b->form_name;
188  b->form_name = NULL;
189  }
190 
191  /* Remove headers by copying out data to another file, then
192  * copying the file back */
193  fseeko(fp, b->offset, SEEK_SET);
194  mutt_body_free(&b);
195  mutt_mktemp(tempfile, sizeof(tempfile));
196  FILE *fp_tmp = mutt_file_fopen(tempfile, "w");
197  if (!fp_tmp)
198  {
199  mutt_perror(_("Failure to open file to strip headers"));
200  mutt_file_fclose(&fp);
201  goto bailout;
202  }
203  mutt_file_copy_stream(fp, fp_tmp);
204  mutt_file_fclose(&fp);
205  mutt_file_fclose(&fp_tmp);
207  if (mutt_file_rename(tempfile, a->filename) != 0)
208  {
209  mutt_perror(_("Failure to rename file"));
210  goto bailout;
211  }
212  }
213  }
214  }
215  }
216  }
217  else
218  {
219  rfc1524_free_entry(&entry);
220  mutt_message(_("No mailcap compose entry for %s, creating empty file"), type);
221  return 1;
222  }
223 
224  rc = 1;
225 
226 bailout:
227 
228  if (unlink_newfile)
229  unlink(newfile);
230 
231  rfc1524_free_entry(&entry);
232  return rc;
233 }
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:48
#define mutt_perror(...)
Definition: logging.h:89
bool rfc1524_mailcap_lookup(struct Body *a, char *type, struct Rfc1524MailcapEntry *entry, enum MailcapLookup opt)
Find given type in the list of mailcap files.
Definition: rfc1524.c:437
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
#define mutt_message(...)
Definition: logging.h:87
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:191
LOFF_T offset
offset where the actual data begins
Definition: body.h:46
#define _(a)
Definition: message.h:28
Mailcap compose field.
Definition: rfc1524.h:59
int mutt_file_symlink(const char *oldpath, const char *newpath)
Create a symlink.
Definition: file.c:286
char * form_name
Content-Disposition form-data name param.
Definition: body.h:41
The body of an email.
Definition: body.h:34
int mutt_file_rename(const char *oldfile, const char *newfile)
Rename a file.
Definition: file.c:1238
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:330
#define TAILQ_INIT(head)
Definition: queue.h:759
char * nametemplate
Definition: rfc1524.h:45
char * subtype
content-type subtype
Definition: body.h:37
void rfc1524_free_entry(struct Rfc1524MailcapEntry **entry)
Deallocate an struct Rfc1524MailcapEntry.
Definition: rfc1524.c:409
void mutt_param_free(struct ParameterList *p)
Free a ParameterList.
Definition: parameter.c:59
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:72
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:497
#define PATH_MAX
Definition: mutt.h:48
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:741
A mailcap entry.
Definition: rfc1524.h:37
char * description
content-description
Definition: body.h:40
char * composetypecommand
Definition: rfc1524.h:42
char * composecommand
Definition: rfc1524.h:41
#define STR_COMMAND
Enough space for a long command line.
Definition: string2.h:34
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:546
#define TYPE(body)
Definition: mime.h:83
void mutt_body_free(struct Body **p)
Free a Body.
Definition: body.c:57
Log at debug level 1.
Definition: logging.h:56
int rfc1524_expand_command(struct Body *a, const char *filename, const char *type, char *command, int clen)
Expand expandos in a command.
Definition: rfc1524.c:72
#define mutt_error(...)
Definition: logging.h:88
bool unlink
flag to indicate the file named by "filename" should be unlink()ed before free()ing this structure ...
Definition: body.h:74
struct Rfc1524MailcapEntry * rfc1524_new_entry(void)
Allocate memory for a new rfc1524 entry.
Definition: rfc1524.c:400
#define FREE(x)
Definition: memory.h:40
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:263
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
#define TAILQ_EMPTY(head)
Definition: queue.h:715
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:50
struct Body * mutt_read_mime_header(FILE *fp, bool digest)
Parse a MIME header.
Definition: parse.c:1159
int rfc1524_expand_filename(const char *nametemplate, const char *oldfile, char *newfile, size_t nflen)
Expand a new filename from a template or existing filename.
Definition: rfc1524.c:503

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int mutt_edit_attachment ( struct Body a)

Edit an attachment.

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

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

Returning 0 is useful to tell the calling menu to redraw

Definition at line 248 of file mutt_attach.c.

249 {
250  char type[256];
251  char cmd[STR_COMMAND];
252  char newfile[PATH_MAX] = "";
253  struct Rfc1524MailcapEntry *entry = rfc1524_new_entry();
254  bool unlink_newfile = false;
255  int rc = 0;
256 
257  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
258  if (rfc1524_mailcap_lookup(a, type, entry, MUTT_MC_EDIT))
259  {
260  if (entry->editcommand)
261  {
262  mutt_str_strfcpy(cmd, entry->editcommand, sizeof(cmd));
263  if (rfc1524_expand_filename(entry->nametemplate, a->filename, newfile, sizeof(newfile)))
264  {
265  mutt_debug(LL_DEBUG1, "oldfile: %s\t newfile: %s\n", a->filename, newfile);
266  if (mutt_file_symlink(a->filename, newfile) == -1)
267  {
268  if (mutt_yesorno(_("Can't match nametemplate, continue?"), MUTT_YES) != MUTT_YES)
269  goto bailout;
270  }
271  else
272  unlink_newfile = true;
273  }
274  else
275  mutt_str_strfcpy(newfile, a->filename, sizeof(newfile));
276 
277  if (rfc1524_expand_command(a, newfile, type, cmd, sizeof(cmd)))
278  {
279  /* For now, editing requires a file, no piping */
280  mutt_error(_("Mailcap Edit entry requires %%s"));
281  goto bailout;
282  }
283  else
284  {
285  mutt_endwin();
286  if (mutt_system(cmd) == -1)
287  {
288  mutt_error(_("Error running \"%s\""), cmd);
289  goto bailout;
290  }
291  }
292  }
293  }
294  else if (a->type == TYPE_TEXT)
295  {
296  /* On text, default to editor */
298  }
299  else
300  {
301  rfc1524_free_entry(&entry);
302  mutt_error(_("No mailcap edit entry for %s"), type);
303  return 0;
304  }
305 
306  rc = 1;
307 
308 bailout:
309 
310  if (unlink_newfile)
311  unlink(newfile);
312 
313  rfc1524_free_entry(&entry);
314  return rc;
315 }
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:48
#define NONULL(x)
Definition: string2.h:36
bool rfc1524_mailcap_lookup(struct Body *a, char *type, struct Rfc1524MailcapEntry *entry, enum MailcapLookup opt)
Find given type in the list of mailcap files.
Definition: rfc1524.c:437
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
#define _(a)
Definition: message.h:28
int mutt_file_symlink(const char *oldpath, const char *newpath)
Create a symlink.
Definition: file.c:286
Mailcap edit field.
Definition: rfc1524.h:58
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:330
char * nametemplate
Definition: rfc1524.h:45
char * subtype
content-type subtype
Definition: body.h:37
void rfc1524_free_entry(struct Rfc1524MailcapEntry **entry)
Deallocate an struct Rfc1524MailcapEntry.
Definition: rfc1524.c:409
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:497
#define PATH_MAX
Definition: mutt.h:48
Type: &#39;text/*&#39;.
Definition: mime.h:38
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:741
A mailcap entry.
Definition: rfc1524.h:37
unsigned int type
content-type primary type
Definition: body.h:70
#define STR_COMMAND
Enough space for a long command line.
Definition: string2.h:34
#define TYPE(body)
Definition: mime.h:83
Log at debug level 1.
Definition: logging.h:56
int rfc1524_expand_command(struct Body *a, const char *filename, const char *type, char *command, int clen)
Expand expandos in a command.
Definition: rfc1524.c:72
#define mutt_error(...)
Definition: logging.h:88
WHERE char * C_Editor
Config: External command to use as an email editor.
Definition: globals.h:112
char * editcommand
Definition: rfc1524.h:43
struct Rfc1524MailcapEntry * rfc1524_new_entry(void)
Allocate memory for a new rfc1524 entry.
Definition: rfc1524.c:400
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
void mutt_edit_file(const char *editor, const char *file)
Let the user edit a file.
Definition: curs_lib.c:308
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:50
int rfc1524_expand_filename(const char *nametemplate, const char *oldfile, char *newfile, size_t nflen)
Expand a new filename from a template or existing filename.
Definition: rfc1524.c:503

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

324 {
325  struct ListNode *np = NULL;
326  STAILQ_FOREACH(np, &MimeLookupList, entries)
327  {
328  const int i = mutt_str_strlen(np->data) - 1;
329  if (((i > 0) && (np->data[i - 1] == '/') && (np->data[i] == '*') &&
330  (mutt_str_strncasecmp(type, np->data, i) == 0)) ||
331  (mutt_str_strcasecmp(type, np->data) == 0))
332  {
333  struct Body tmp = { 0 };
334  int n;
335  n = mutt_lookup_mime_type(&tmp, b->filename);
336  if (n != TYPE_OTHER)
337  {
338  snprintf(type, len, "%s/%s",
339  n == TYPE_AUDIO ? "audio" :
340  n == TYPE_APPLICATION ?
341  "application" :
342  n == TYPE_IMAGE ?
343  "image" :
344  n == TYPE_MESSAGE ?
345  "message" :
346  n == TYPE_MODEL ?
347  "model" :
348  n == TYPE_MULTIPART ?
349  "multipart" :
350  n == TYPE_TEXT ? "text" : n == TYPE_VIDEO ? "video" : "other",
351  tmp.subtype);
352  mutt_debug(LL_DEBUG1, "\"%s\" -> %s\n", b->filename, type);
353  }
354  if (tmp.subtype)
355  FREE(&tmp.subtype);
356  if (tmp.xtype)
357  FREE(&tmp.xtype);
358  }
359  }
360 }
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:48
Type: &#39;audio/*&#39;.
Definition: mime.h:32
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:662
The body of an email.
Definition: body.h:34
Type: &#39;video/*&#39;.
Definition: mime.h:39
char * subtype
content-type subtype
Definition: body.h:37
int mutt_str_strncasecmp(const char *a, const char *b, size_t l)
Compare two strings ignoring case (to a maximum), safely.
Definition: string.c:652
Type: &#39;text/*&#39;.
Definition: mime.h:38
char * xtype
content-type if x-unknown
Definition: body.h:36
int mutt_lookup_mime_type(struct Body *att, const char *path)
Find the MIME type for an attachment.
Definition: sendlib.c:1069
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
unsigned int type
content-type primary type
Definition: body.h:70
Type: &#39;message/*&#39;.
Definition: mime.h:35
char * data
Definition: list.h:35
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
Log at debug level 1.
Definition: logging.h:56
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:624
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:85
A List node for strings.
Definition: list.h:33
Type: &#39;application/*&#39;.
Definition: mime.h:33

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

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
Return values
0If the viewer is run and exited successfully
-1Error
numReturn value of mutt_do_pager() when it is used

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

Definition at line 379 of file mutt_attach.c.

381 {
382  char tempfile[PATH_MAX] = "";
383  char pagerfile[PATH_MAX] = "";
384  bool use_mailcap = false;
385  bool use_pipe = false;
386  bool use_pager = true;
387  char type[256];
388  char cmd[STR_COMMAND];
389  char desc[256];
390  char *fname = NULL;
391  struct Rfc1524MailcapEntry *entry = NULL;
392  int rc = -1;
393  bool unlink_tempfile = false;
394 
395  bool is_message = mutt_is_message_type(a->type, a->subtype);
396  if ((WithCrypto != 0) && is_message && a->email &&
398  {
399  return rc;
400  }
401  use_mailcap =
402  (mode == MUTT_VA_MAILCAP || (mode == MUTT_VA_REGULAR && mutt_needs_mailcap(a)));
403  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
404 
405  if (use_mailcap)
406  {
407  entry = rfc1524_new_entry();
408  if (!rfc1524_mailcap_lookup(a, type, entry, MUTT_MC_NO_FLAGS))
409  {
410  if (mode == MUTT_VA_REGULAR)
411  {
412  /* fallback to view as text */
413  rfc1524_free_entry(&entry);
414  mutt_error(_("No matching mailcap entry found. Viewing as text."));
415  mode = MUTT_VA_AS_TEXT;
416  use_mailcap = false;
417  }
418  else
419  goto return_error;
420  }
421  }
422 
423  if (use_mailcap)
424  {
425  if (!entry->command)
426  {
427  mutt_error(_("MIME type not defined. Cannot view attachment."));
428  goto return_error;
429  }
430  mutt_str_strfcpy(cmd, entry->command, sizeof(cmd));
431 
432  if (fp)
433  {
434  fname = mutt_str_strdup(a->filename);
435  mutt_file_sanitize_filename(fname, true);
436  }
437  else
438  fname = a->filename;
439 
440  if (rfc1524_expand_filename(entry->nametemplate, fname, tempfile, sizeof(tempfile)))
441  {
442  if (!fp && (mutt_str_strcmp(tempfile, a->filename) != 0))
443  {
444  /* send case: the file is already there */
445  if (mutt_file_symlink(a->filename, tempfile) == -1)
446  {
447  if (mutt_yesorno(_("Can't match nametemplate, continue?"), MUTT_YES) == MUTT_YES)
448  mutt_str_strfcpy(tempfile, a->filename, sizeof(tempfile));
449  else
450  goto return_error;
451  }
452  else
453  unlink_tempfile = true;
454  }
455  }
456  else if (!fp) /* send case */
457  mutt_str_strfcpy(tempfile, a->filename, sizeof(tempfile));
458 
459  if (fp)
460  {
461  /* recv case: we need to save the attachment to a file */
462  FREE(&fname);
463  if (mutt_save_attachment(fp, a, tempfile, MUTT_SAVE_NO_FLAGS, NULL) == -1)
464  goto return_error;
465  mutt_file_chmod(tempfile, S_IRUSR);
466  }
467 
468  use_pipe = rfc1524_expand_command(a, tempfile, type, cmd, sizeof(cmd));
469  use_pager = entry->copiousoutput;
470  }
471 
472  if (use_pager)
473  {
474  if (fp && !use_mailcap && a->filename)
475  {
476  /* recv case */
477  mutt_str_strfcpy(pagerfile, a->filename, sizeof(pagerfile));
478  mutt_adv_mktemp(pagerfile, sizeof(pagerfile));
479  }
480  else
481  mutt_mktemp(pagerfile, sizeof(pagerfile));
482  }
483 
484  if (use_mailcap)
485  {
486  pid_t pid = 0;
487  int tempfd = -1, pagerfd = -1;
488 
489  if (!use_pager)
490  mutt_endwin();
491 
492  if (use_pager || use_pipe)
493  {
494  if (use_pager &&
495  ((pagerfd = mutt_file_open(pagerfile, O_CREAT | O_EXCL | O_WRONLY)) == -1))
496  {
497  mutt_perror("open");
498  goto return_error;
499  }
500  if (use_pipe && ((tempfd = open(tempfile, 0)) == -1))
501  {
502  if (pagerfd != -1)
503  close(pagerfd);
504  mutt_perror("open");
505  goto return_error;
506  }
507 
508  pid = mutt_create_filter_fd(cmd, NULL, NULL, NULL, use_pipe ? tempfd : -1,
509  use_pager ? pagerfd : -1, -1);
510  if (pid == -1)
511  {
512  if (pagerfd != -1)
513  close(pagerfd);
514 
515  if (tempfd != -1)
516  close(tempfd);
517 
518  mutt_error(_("Can't create filter"));
519  goto return_error;
520  }
521 
522  if (use_pager)
523  {
524  if (a->description)
525  {
526  snprintf(desc, sizeof(desc), _("---Command: %-20.20s Description: %s"),
527  cmd, a->description);
528  }
529  else
530  {
531  snprintf(desc, sizeof(desc), _("---Command: %-30.30s Attachment: %s"), cmd, type);
532  }
533  }
534 
535  if ((mutt_wait_filter(pid) || (entry->needsterminal && C_WaitKey)) && !use_pager)
537 
538  if (tempfd != -1)
539  close(tempfd);
540  if (pagerfd != -1)
541  close(pagerfd);
542  }
543  else
544  {
545  /* interactive cmd */
546  int rv = mutt_system(cmd);
547  if (rv == -1)
548  mutt_debug(LL_DEBUG1, "Error running \"%s\"!", cmd);
549 
550  if ((rv != 0) || (entry->needsterminal && C_WaitKey))
552  }
553  }
554  else
555  {
556  /* Don't use mailcap; the attachment is viewed in the pager */
557 
558  if (mode == MUTT_VA_AS_TEXT)
559  {
560  /* just let me see the raw data */
561  if (fp)
562  {
563  /* Viewing from a received message.
564  *
565  * Don't use mutt_save_attachment() because we want to perform charset
566  * conversion since this will be displayed by the internal pager. */
567  struct State decode_state = { 0 };
568 
569  decode_state.fp_out = mutt_file_fopen(pagerfile, "w");
570  if (!decode_state.fp_out)
571  {
572  mutt_debug(LL_DEBUG1, "mutt_file_fopen(%s) errno=%d %s\n", pagerfile,
573  errno, strerror(errno));
574  mutt_perror(pagerfile);
575  goto return_error;
576  }
577  decode_state.fp_in = fp;
578  decode_state.flags = MUTT_CHARCONV;
579  mutt_decode_attachment(a, &decode_state);
580  if (fclose(decode_state.fp_out) == EOF)
581  mutt_debug(LL_DEBUG1, "fclose(%s) errno=%d %s\n", pagerfile, errno,
582  strerror(errno));
583  }
584  else
585  {
586  /* in compose mode, just copy the file. we can't use
587  * mutt_decode_attachment() since it assumes the content-encoding has
588  * already been applied */
589  if (mutt_save_attachment(fp, a, pagerfile, MUTT_SAVE_NO_FLAGS, NULL))
590  goto return_error;
591  }
592  }
593  else
594  {
595  /* Use built-in handler */
596  OptViewAttach = true; /* disable the "use 'v' to view this part"
597  * message in case of error */
599  {
600  OptViewAttach = false;
601  goto return_error;
602  }
603  OptViewAttach = false;
604  }
605 
606  if (a->description)
607  mutt_str_strfcpy(desc, a->description, sizeof(desc));
608  else if (a->filename)
609  snprintf(desc, sizeof(desc), _("---Attachment: %s: %s"), a->filename, type);
610  else
611  snprintf(desc, sizeof(desc), _("---Attachment: %s"), type);
612  }
613 
614  /* We only reach this point if there have been no errors */
615 
616  if (use_pager)
617  {
618  struct Pager info = { 0 };
619  info.fp = fp;
620  info.body = a;
621  info.ctx = Context;
622  info.actx = actx;
623  info.email = e;
624 
625  rc = mutt_do_pager(desc, pagerfile,
626  MUTT_PAGER_ATTACHMENT | (is_message ? MUTT_PAGER_MESSAGE : 0),
627  &info);
628  *pagerfile = '\0';
629  }
630  else
631  rc = 0;
632 
633 return_error:
634 
635  if (!entry || !entry->xneomuttkeep)
636  {
637  if (fp && tempfile[0])
638  {
639  /* add temporary file to TempAttachmentsList to be deleted on timeout hook */
640  mutt_add_temp_attachment(tempfile);
641  }
642  else if (unlink_tempfile)
643  {
644  unlink(tempfile);
645  }
646  }
647 
648  if (entry)
649  rfc1524_free_entry(&entry);
650 
651  if (pagerfile[0])
652  mutt_file_unlink(pagerfile);
653 
654  return rc;
655 }
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1748
void mutt_add_temp_attachment(char *filename)
Add file to list of temporary attachments.
Definition: mutt_attach.c:1166
FILE * fp
source stream
Definition: pager.h:70
#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:48
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition: parse.c:1255
#define mutt_perror(...)
Definition: logging.h:89
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:36
bool rfc1524_mailcap_lookup(struct Body *a, char *type, struct Rfc1524MailcapEntry *entry, enum MailcapLookup opt)
Find given type in the list of mailcap files.
Definition: rfc1524.c:437
#define MUTT_PAGER_MESSAGE
Definition: pager.h:58
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
No flags set.
Definition: mutt_attach.h:54
void mutt_file_sanitize_filename(char *fp, bool slash)
Replace unsafe characters in a filename.
Definition: file.c:576
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:191
bool needsterminal
endwin() and system
Definition: rfc1524.h:47
#define _(a)
Definition: message.h:28
FILE * fp_out
File to write to.
Definition: state.h:47
struct Body * body
current attachment
Definition: pager.h:69
Force viewing as text.
Definition: mutt_attach.h:43
int mutt_file_symlink(const char *oldpath, const char *newpath)
Create a symlink.
Definition: file.c:286
bool xneomuttkeep
do not remove the file on command exit
Definition: rfc1524.h:49
An email being displayed.
Definition: pager.h:65
View using default method.
Definition: mutt_attach.h:41
#define SEC_ENCRYPT
Email is encrypted.
Definition: ncrypt.h:120
FILE * fp_in
File to read from.
Definition: state.h:46
#define MUTT_PAGER_ATTACHMENT
Attachments may exist.
Definition: pager.h:55
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
int crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:144
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:330
char * nametemplate
Definition: rfc1524.h:45
char * subtype
content-type subtype
Definition: body.h:37
struct Context * ctx
current mailbox
Definition: pager.h:67
void rfc1524_free_entry(struct Rfc1524MailcapEntry **entry)
Deallocate an struct Rfc1524MailcapEntry.
Definition: rfc1524.c:409
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:72
WHERE struct Context * Context
Definition: globals.h:41
WHERE bool C_WaitKey
Config: Prompt to press a key after running external commands.
Definition: globals.h:266
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:497
int mutt_file_chmod(const char *path, mode_t mode)
Set permissions of a file.
Definition: file.c:948
#define PATH_MAX
Definition: mutt.h:48
struct AttachCtx * actx
attachment information
Definition: pager.h:71
pid_t mutt_create_filter_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:64
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:741
A mailcap entry.
Definition: rfc1524.h:37
char * description
content-description
Definition: body.h:40
int mutt_save_attachment(FILE *fp, struct Body *m, char *path, enum SaveAttach opt, struct Email *e)
Save an attachment.
Definition: mutt_attach.c:783
SecurityFlags security
bit 0-8: flags, bit 9,10: application.
Definition: email.h:39
Force viewing using mailcap entry.
Definition: mutt_attach.h:42
unsigned int type
content-type primary type
Definition: body.h:70
#define STR_COMMAND
Enough space for a long command line.
Definition: string2.h:34
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:546
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:530
#define TYPE(body)
Definition: mime.h:83
struct Email * email
current message
Definition: pager.h:68
Log at debug level 1.
Definition: logging.h:56
int mutt_do_pager(const char *banner, const char *tempfile, PagerFlags do_color, struct Pager *info)
Display some page-able text to the user.
Definition: curs_lib.c:569
No flags set.
Definition: rfc1524.h:57
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:383
int rfc1524_expand_command(struct Body *a, const char *filename, const char *type, char *command, int clen)
Expand expandos in a command.
Definition: rfc1524.c:72
#define mutt_error(...)
Definition: logging.h:88
bool mutt_needs_mailcap(struct Body *m)
Does this type need a mailcap entry do display.
Definition: muttlib.c:399
int mutt_file_open(const char *path, int flags)
Open a file.
Definition: file.c:496
struct Rfc1524MailcapEntry * rfc1524_new_entry(void)
Allocate memory for a new rfc1524 entry.
Definition: rfc1524.c:400
#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:52
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
int mutt_wait_filter(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:227
struct Email * email
header information for message/rfc822
Definition: body.h:60
#define WithCrypto
Definition: ncrypt.h:155
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:611
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:50
int rfc1524_expand_filename(const char *nametemplate, const char *oldfile, char *newfile, size_t nflen)
Expand a new filename from a template or existing filename.
Definition: rfc1524.c:503
bool copiousoutput
needs pager, basically
Definition: rfc1524.h:48
int mutt_decode_save_attachment(FILE *fp, struct Body *m, char *path, int displaying, enum SaveAttach opt)
Decode, then save an attachment.
Definition: mutt_attach.c:913
void mutt_adv_mktemp(char *buf, size_t buflen)
Advanced mktemp(3)
Definition: muttlib.c:123

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

667 {
668  pid_t pid;
669  int out = -1;
670  int rc = 0;
671 
672  if (outfile && *outfile)
673  {
674  out = mutt_file_open(outfile, O_CREAT | O_EXCL | O_WRONLY);
675  if (out < 0)
676  {
677  mutt_perror("open");
678  return 0;
679  }
680  }
681 
682  mutt_endwin();
683 
684  if (fp)
685  {
686  /* recv case */
687 
688  struct State s = { 0 };
689 
690  /* perform charset conversion on text attachments when piping */
691  s.flags = MUTT_CHARCONV;
692 
693  if (outfile && *outfile)
694  pid = mutt_create_filter_fd(path, &s.fp_out, NULL, NULL, -1, out, -1);
695  else
696  pid = mutt_create_filter(path, &s.fp_out, NULL, NULL);
697 
698  if (pid < 0)
699  {
700  mutt_perror(_("Can't create filter"));
701  goto bail;
702  }
703 
704  s.fp_in = fp;
705  mutt_decode_attachment(b, &s);
707  }
708  else
709  {
710  /* send case */
711  FILE *fp_in = fopen(b->filename, "r");
712  if (!fp_in)
713  {
714  mutt_perror("fopen");
715  if (outfile && *outfile)
716  {
717  close(out);
718  unlink(outfile);
719  }
720  return 0;
721  }
722 
723  FILE *fp_out = NULL;
724  if (outfile && *outfile)
725  pid = mutt_create_filter_fd(path, &fp_out, NULL, NULL, -1, out, -1);
726  else
727  pid = mutt_create_filter(path, &fp_out, NULL, NULL);
728 
729  if (pid < 0)
730  {
731  mutt_perror(_("Can't create filter"));
732  mutt_file_fclose(&fp_in);
733  goto bail;
734  }
735 
736  mutt_file_copy_stream(fp_in, fp_out);
737  mutt_file_fclose(&fp_out);
738  mutt_file_fclose(&fp_in);
739  }
740 
741  rc = 1;
742 
743 bail:
744 
745  if (outfile && *outfile)
746  close(out);
747 
748  /* check for error exit from child process */
749  if (mutt_wait_filter(pid) != 0)
750  rc = 0;
751 
752  if ((rc == 0) || C_WaitKey)
754  return rc;
755 }
pid_t mutt_create_filter(const char *s, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:216
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1748
FILE * fp
source stream
Definition: pager.h:70
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:48
#define mutt_perror(...)
Definition: logging.h:89
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:36
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
#define _(a)
Definition: message.h:28
FILE * fp_out
File to write to.
Definition: state.h:47
FILE * fp_in
File to read from.
Definition: state.h:46
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
WHERE bool C_WaitKey
Config: Prompt to press a key after running external commands.
Definition: globals.h:266
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:497
pid_t mutt_create_filter_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:64
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:530
int mutt_file_open(const char *path, int flags)
Open a file.
Definition: file.c:496
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:263
Keep track when processing files.
Definition: state.h:44
int mutt_wait_filter(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:227

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Open a file to write an attachment to.

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

Definition at line 763 of file mutt_attach.c.

764 {
765  if (opt == MUTT_SAVE_APPEND)
766  return fopen(path, "a");
767  if (opt == MUTT_SAVE_OVERWRITE)
768  return fopen(path, "w");
769 
770  return mutt_file_fopen(path, "w");
771 }
Overwrite existing file.
Definition: mutt_attach.h:56
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:546
Append to existing file.
Definition: mutt_attach.h:55

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int mutt_save_attachment ( FILE *  fp,
struct Body m,
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 783 of file mutt_attach.c.

785 {
786  if (!m)
787  return -1;
788 
789  if (fp)
790  {
791  /* recv mode */
792 
793  if (e && m->email && (m->encoding != ENC_BASE64) &&
795  {
796  /* message type attachments are written to mail folders. */
797 
798  char buf[8192];
799  struct Message *msg = NULL;
800  CopyHeaderFlags chflags = CH_NO_FLAGS;
801  int rc = -1;
802 
803  struct Email *en = m->email;
804  en->msgno = e->msgno; /* required for MH/maildir */
805  en->read = true;
806 
807  if (fseeko(fp, m->offset, SEEK_SET) < 0)
808  return -1;
809  if (!fgets(buf, sizeof(buf), fp))
810  return -1;
811  struct Mailbox *m_att = mx_path_resolve(path);
812  struct Context *ctx = mx_mbox_open(m_att, MUTT_APPEND | MUTT_QUIET);
813  if (!ctx)
814  {
815  mailbox_free(&m_att);
816  return -1;
817  }
818  msg = mx_msg_open_new(ctx->mailbox, en, is_from(buf, NULL, 0, NULL) ? 0 : MUTT_ADD_FROM);
819  if (!msg)
820  {
821  mx_mbox_close(&ctx);
822  return -1;
823  }
824  if ((ctx->mailbox->magic == MUTT_MBOX) || (ctx->mailbox->magic == MUTT_MMDF))
825  chflags = CH_FROM | CH_UPDATE_LEN;
826  chflags |= (ctx->mailbox->magic == MUTT_MAILDIR ? CH_NOSTATUS : CH_UPDATE);
827  if ((mutt_copy_message_fp(msg->fp, fp, en, 0, chflags) == 0) &&
828  (mx_msg_commit(ctx->mailbox, msg) == 0))
829  {
830  rc = 0;
831  }
832  else
833  {
834  rc = -1;
835  }
836 
837  mx_msg_close(ctx->mailbox, &msg);
838  mx_mbox_close(&ctx);
839  return rc;
840  }
841  else
842  {
843  /* In recv mode, extract from folder and decode */
844 
845  struct State s = { 0 };
846 
847  s.fp_out = save_attachment_open(path, opt);
848  if (!s.fp_out)
849  {
850  mutt_perror("fopen");
851  return -1;
852  }
853  fseeko((s.fp_in = fp), m->offset, SEEK_SET);
854  mutt_decode_attachment(m, &s);
855 
856  if (mutt_file_fsync_close(&s.fp_out) != 0)
857  {
858  mutt_perror("fclose");
859  return -1;
860  }
861  }
862  }
863  else
864  {
865  if (!m->filename)
866  return -1;
867 
868  /* In send mode, just copy file */
869 
870  FILE *fp_old = fopen(m->filename, "r");
871  if (!fp_old)
872  {
873  mutt_perror("fopen");
874  return -1;
875  }
876 
877  FILE *fp_new = save_attachment_open(path, opt);
878  if (!fp_new)
879  {
880  mutt_perror("fopen");
881  mutt_file_fclose(&fp_old);
882  return -1;
883  }
884 
885  if (mutt_file_copy_stream(fp_old, fp_new) == -1)
886  {
887  mutt_error(_("Write fault"));
888  mutt_file_fclose(&fp_old);
889  mutt_file_fclose(&fp_new);
890  return -1;
891  }
892  mutt_file_fclose(&fp_old);
893  if (mutt_file_fsync_close(&fp_new) != 0)
894  {
895  mutt_error(_("Write fault"));
896  return -1;
897  }
898  }
899 
900  return 0;
901 }
#define MUTT_APPEND
Open mailbox for appending messages.
Definition: mx.h:52
The "current" mailbox.
Definition: context.h:37
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1748
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:48
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition: parse.c:1255
The envelope/body of an email.
Definition: email.h:37
#define mutt_perror(...)
Definition: logging.h:89
int mx_mbox_close(struct Context **ptr)
Save changes and close mailbox.
Definition: mx.c:529
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
&#39;Maildir&#39; Mailbox type
Definition: magic.h:40
&#39;mmdf&#39; Mailbox type
Definition: magic.h:38
int mutt_copy_message_fp(FILE *fp_out, FILE *fp_in, struct Email *e, CopyMessageFlags cmflags, CopyHeaderFlags chflags)
make a copy of a message from a FILE pointer
Definition: copy.c:590
LOFF_T offset
offset where the actual data begins
Definition: body.h:46
#define CH_FROM
Retain the "From " message separator?
Definition: copy.h:55
#define _(a)
Definition: message.h:28
#define CH_NOSTATUS
Suppress the status and x-status fields.
Definition: copy.h:57
struct Context * mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:246
FILE * fp_out
File to write to.
Definition: state.h:47
#define CH_UPDATE
Update the status and x-status fields?
Definition: copy.h:51
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:1058
bool read
Definition: email.h:51
struct Mailbox * mailbox
Definition: context.h:51
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:103
enum MailboxType magic
mailbox type
Definition: mailbox.h:106
static FILE * save_attachment_open(char *path, enum SaveAttach opt)
Open a file to write an attachment to.
Definition: mutt_attach.c:763
unsigned int encoding
content-transfer-encoding
Definition: body.h:71
struct Message * mx_msg_open_new(struct Mailbox *m, struct Email *e, MsgOpenFlags flags)
Open a new message.
Definition: mx.c:927
Base-64 encoded text.
Definition: mime.h:52
char * subtype
content-type subtype
Definition: body.h:37
&#39;mbox&#39; Mailbox type
Definition: magic.h:37
A local copy of an email.
Definition: mx.h:81
A mailbox.
Definition: mailbox.h:83
#define CH_NO_FLAGS
No flags are set.
Definition: copy.h:50
#define CH_UPDATE_LEN
Update Lines: and Content-Length:
Definition: copy.h:61
#define MUTT_QUIET
Do not print any messages.
Definition: mx.h:54
unsigned int type
content-type primary type
Definition: body.h:70
char path[PATH_MAX]
Definition: mailbox.h:85
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition: copy.h:49
#define mutt_error(...)
Definition: logging.h:88
int mx_msg_commit(struct Mailbox *m, struct Message *msg)
Commit a message to a folder - Wrapper for MxOps::msg_commit()
Definition: mx.c:1037
Quoted-printable text.
Definition: mime.h:51
FILE * fp
pointer to the message data
Definition: mx.h:83
struct Mailbox * mx_path_resolve(const char *path)
XXX.
Definition: mx.c:1506
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:263
Keep track when processing files.
Definition: state.h:44
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:49
int mutt_file_fsync_close(FILE **fp)
Flush the data, before closing a file (and NULL the pointer)
Definition: file.c:165
#define MUTT_ADD_FROM
add a From_ line
Definition: mx.h:64
struct Email * email
header information for message/rfc822
Definition: body.h:60
int msgno
number displayed to the user
Definition: email.h:89

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int mutt_decode_save_attachment ( FILE *  fp,
struct Body m,
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 913 of file mutt_attach.c.

915 {
916  struct State s = { 0 };
917  unsigned int saved_encoding = 0;
918  struct Body *saved_parts = NULL;
919  struct Email *saved_hdr = NULL;
920  int rc = 0;
921 
922  s.flags = displaying;
923 
924  if (opt == MUTT_SAVE_APPEND)
925  s.fp_out = fopen(path, "a");
926  else if (opt == MUTT_SAVE_OVERWRITE)
927  s.fp_out = fopen(path, "w");
928  else
929  s.fp_out = mutt_file_fopen(path, "w");
930 
931  if (!s.fp_out)
932  {
933  mutt_perror("fopen");
934  return -1;
935  }
936 
937  if (!fp)
938  {
939  /* When called from the compose menu, the attachment isn't parsed,
940  * so we need to do it here. */
941  struct stat st;
942 
943  if (stat(m->filename, &st) == -1)
944  {
945  mutt_perror("stat");
947  return -1;
948  }
949 
950  s.fp_in = fopen(m->filename, "r");
951  if (!s.fp_in)
952  {
953  mutt_perror("fopen");
954  return -1;
955  }
956 
957  saved_encoding = m->encoding;
958  if (!is_multipart(m))
959  m->encoding = ENC_8BIT;
960 
961  m->length = st.st_size;
962  m->offset = 0;
963  saved_parts = m->parts;
964  saved_hdr = m->email;
965  mutt_parse_part(s.fp_in, m);
966 
967  if (m->noconv || is_multipart(m))
968  s.flags |= MUTT_CHARCONV;
969  }
970  else
971  {
972  s.fp_in = fp;
973  s.flags |= MUTT_CHARCONV;
974  }
975 
976  mutt_body_handler(m, &s);
977 
978  if (mutt_file_fsync_close(&s.fp_out) != 0)
979  {
980  mutt_perror("fclose");
981  rc = -1;
982  }
983  if (!fp)
984  {
985  m->length = 0;
986  m->encoding = saved_encoding;
987  if (saved_parts)
988  {
989  mutt_email_free(&m->email);
990  m->parts = saved_parts;
991  m->email = saved_hdr;
992  }
994  }
995 
996  return rc;
997 }
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:48
The envelope/body of an email.
Definition: email.h:37
#define mutt_perror(...)
Definition: logging.h:89
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:36
#define is_multipart(body)
Definition: mime.h:77
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
bool noconv
don&#39;t do character set conversion
Definition: body.h:80
Overwrite existing file.
Definition: mutt_attach.h:56
LOFF_T offset
offset where the actual data begins
Definition: body.h:46
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
unsigned int encoding
content-transfer-encoding
Definition: body.h:71
LOFF_T length
length (in bytes) of attachment
Definition: body.h:47
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:59
void mutt_email_free(struct Email **e)
Free an Email.
Definition: email.c:41
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:546
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1270
char * path
Definition: email.h:94
Append to existing file.
Definition: mutt_attach.h:55
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:1524
int mutt_file_fsync_close(FILE **fp)
Flush the data, before closing a file (and NULL the pointer)
Definition: file.c:165
struct Email * email
header information for message/rfc822
Definition: body.h:60

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

1013 {
1014  char newfile[PATH_MAX] = "";
1015  char type[256];
1016  pid_t pid;
1017  FILE *fp_in = NULL, *fp_out = NULL;
1018  bool unlink_newfile = false;
1019 
1020  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
1021 
1022  if (rfc1524_mailcap_lookup(a, type, NULL, MUTT_MC_PRINT))
1023  {
1024  char cmd[STR_COMMAND];
1025  int piped = false;
1026 
1027  mutt_debug(LL_DEBUG2, "Using mailcap...\n");
1028 
1029  struct Rfc1524MailcapEntry *entry = rfc1524_new_entry();
1030  rfc1524_mailcap_lookup(a, type, entry, MUTT_MC_PRINT);
1031  if (rfc1524_expand_filename(entry->nametemplate, a->filename, newfile, sizeof(newfile)))
1032  {
1033  if (!fp)
1034  {
1035  if (mutt_file_symlink(a->filename, newfile) == -1)
1036  {
1037  if (mutt_yesorno(_("Can't match nametemplate, continue?"), MUTT_YES) != MUTT_YES)
1038  {
1039  rfc1524_free_entry(&entry);
1040  return 0;
1041  }
1042  mutt_str_strfcpy(newfile, a->filename, sizeof(newfile));
1043  }
1044  else
1045  unlink_newfile = true;
1046  }
1047  }
1048 
1049  /* in recv mode, save file to newfile first */
1050  if (fp && (mutt_save_attachment(fp, a, newfile, MUTT_SAVE_NO_FLAGS, NULL) != 0))
1051  return 0;
1052 
1053  mutt_str_strfcpy(cmd, entry->printcommand, sizeof(cmd));
1054  piped = rfc1524_expand_command(a, newfile, type, cmd, sizeof(cmd));
1055 
1056  mutt_endwin();
1057 
1058  /* interactive program */
1059  if (piped)
1060  {
1061  fp_in = fopen(newfile, "r");
1062  if (!fp_in)
1063  {
1064  mutt_perror("fopen");
1065  rfc1524_free_entry(&entry);
1066  return 0;
1067  }
1068 
1069  pid = mutt_create_filter(cmd, &fp_out, NULL, NULL);
1070  if (pid < 0)
1071  {
1072  mutt_perror(_("Can't create filter"));
1073  rfc1524_free_entry(&entry);
1074  mutt_file_fclose(&fp_in);
1075  return 0;
1076  }
1077  mutt_file_copy_stream(fp_in, fp_out);
1078  mutt_file_fclose(&fp_out);
1079  mutt_file_fclose(&fp_in);
1080  if (mutt_wait_filter(pid) || C_WaitKey)
1082  }
1083  else
1084  {
1085  int rc = mutt_system(cmd);
1086  if (rc == -1)
1087  mutt_debug(LL_DEBUG1, "Error running \"%s\"!", cmd);
1088 
1089  if ((rc != 0) || C_WaitKey)
1091  }
1092 
1093  if (fp)
1094  mutt_file_unlink(newfile);
1095  else if (unlink_newfile)
1096  unlink(newfile);
1097 
1098  rfc1524_free_entry(&entry);
1099  return 1;
1100  }
1101 
1102  if ((mutt_str_strcasecmp("text/plain", type) == 0) ||
1103  (mutt_str_strcasecmp("application/postscript", type) == 0))
1104  {
1105  return mutt_pipe_attachment(fp, a, NONULL(C_PrintCommand), NULL);
1106  }
1107  else if (mutt_can_decode(a))
1108  {
1109  /* decode and print */
1110 
1111  int rc = 0;
1112 
1113  fp_in = NULL;
1114  fp_out = NULL;
1115 
1116  mutt_mktemp(newfile, sizeof(newfile));
1118  {
1119  mutt_debug(LL_DEBUG2, "successfully decoded %s type attachment to %s\n", type, newfile);
1120 
1121  fp_in = fopen(newfile, "r");
1122  if (!fp_in)
1123  {
1124  mutt_perror("fopen");
1125  goto bail0;
1126  }
1127 
1128  mutt_debug(LL_DEBUG2, "successfully opened %s read-only\n", newfile);
1129 
1130  mutt_endwin();
1131  pid = mutt_create_filter(NONULL(C_PrintCommand), &fp_out, NULL, NULL);
1132  if (pid < 0)
1133  {
1134  mutt_perror(_("Can't create filter"));
1135  goto bail0;
1136  }
1137 
1138  mutt_debug(LL_DEBUG2, "Filter created.\n");
1139 
1140  mutt_file_copy_stream(fp_in, fp_out);
1141 
1142  mutt_file_fclose(&fp_out);
1143  mutt_file_fclose(&fp_in);
1144 
1145  if ((mutt_wait_filter(pid) != 0) || C_WaitKey)
1147  rc = 1;
1148  }
1149  bail0:
1150  mutt_file_fclose(&fp_in);
1151  mutt_file_fclose(&fp_out);
1152  mutt_file_unlink(newfile);
1153  return rc;
1154  }
1155  else
1156  {
1157  mutt_error(_("I don't know how to print that"));
1158  return 0;
1159  }
1160 }
pid_t mutt_create_filter(const char *s, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:216
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:48
#define NONULL(x)
Definition: string2.h:36
#define mutt_perror(...)
Definition: logging.h:89
bool rfc1524_mailcap_lookup(struct Body *a, char *type, struct Rfc1524MailcapEntry *entry, enum MailcapLookup opt)
Find given type in the list of mailcap files.
Definition: rfc1524.c:437
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
No flags set.
Definition: mutt_attach.h:54
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:191
#define _(a)
Definition: message.h:28
int mutt_file_symlink(const char *oldpath, const char *newpath)
Create a symlink.
Definition: file.c:286
#define MUTT_PRINTING
Are we printing? - MUTT_DISPLAY "light".
Definition: state.h:37
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:330
Log at debug level 2.
Definition: logging.h:57
Mailcap print field.
Definition: rfc1524.h:60
char * nametemplate
Definition: rfc1524.h:45
char * subtype
content-type subtype
Definition: body.h:37
void rfc1524_free_entry(struct Rfc1524MailcapEntry **entry)
Deallocate an struct Rfc1524MailcapEntry.
Definition: rfc1524.c:409
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:72
WHERE bool C_WaitKey
Config: Prompt to press a key after running external commands.
Definition: globals.h:266
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:497
#define PATH_MAX
Definition: mutt.h:48
bool mutt_can_decode(struct Body *a)
Will decoding the attachment produce any output.
Definition: handler.c:1707
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:741
A mailcap entry.
Definition: rfc1524.h:37
int mutt_save_attachment(FILE *fp, struct Body *m, char *path, enum SaveAttach opt, struct Email *e)
Save an attachment.
Definition: mutt_attach.c:783
#define STR_COMMAND
Enough space for a long command line.
Definition: string2.h:34
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:530
#define TYPE(body)
Definition: mime.h:83
Log at debug level 1.
Definition: logging.h:56
int rfc1524_expand_command(struct Body *a, const char *filename, const char *type, char *command, int clen)
Expand expandos in a command.
Definition: rfc1524.c:72
#define mutt_error(...)
Definition: logging.h:88
WHERE char * C_PrintCommand
Config: External command to print a message.
Definition: globals.h:142
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:624
struct Rfc1524MailcapEntry * rfc1524_new_entry(void)
Allocate memory for a new rfc1524 entry.
Definition: rfc1524.c:400
char * printcommand
Definition: rfc1524.h:44
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:263
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
int mutt_wait_filter(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:227
int mutt_pipe_attachment(FILE *fp, struct Body *b, const char *path, char *outfile)
Pipe an attachment to a command.
Definition: mutt_attach.c:666
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:50
int rfc1524_expand_filename(const char *nametemplate, const char *oldfile, char *newfile, size_t nflen)
Expand a new filename from a template or existing filename.
Definition: rfc1524.c:503
int mutt_decode_save_attachment(FILE *fp, struct Body *m, char *path, int displaying, enum SaveAttach opt)
Decode, then save an attachment.
Definition: mutt_attach.c:913

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_add_temp_attachment ( char *  filename)

Add file to list of temporary attachments.

Parameters
filenamefilename with full path

Definition at line 1166 of file mutt_attach.c.

1167 {
1168  mutt_list_insert_tail(&TempAttachmentsList, mutt_str_strdup(filename));
1169 }
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:58
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:383

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_unlink_temp_attachments ( void  )

Delete all temporary attachments.

Definition at line 1174 of file mutt_attach.c.

1175 {
1176  struct ListNode *np = NULL;
1177 
1178  STAILQ_FOREACH(np, &TempAttachmentsList, entries)
1179  {
1180  mutt_file_chmod_add(np->data, S_IWUSR);
1181  mutt_file_unlink(np->data);
1182  }
1183 
1184  mutt_list_free(&TempAttachmentsList);
1185 }
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:191
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:105
int mutt_file_chmod_add(const char *path, mode_t mode)
Add permissions to a file.
Definition: file.c:969
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
char * data
Definition: list.h:35
A List node for strings.
Definition: list.h:33

+ Here is the call graph for this function:

+ Here is the caller graph for this function: