NeoMutt  2018-07-16 +952-a2da0a
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, int flag, 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, int flags)
 Open a file to write an attachment to. More...
 
int mutt_save_attachment (FILE *fp, struct Body *m, char *path, int flags, struct Email *e)
 Save an attachment. More...
 
int mutt_decode_save_attachment (FILE *fp, struct Body *m, char *path, int displaying, int flags)
 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[STRING];
70  char tempfile[PATH_MAX];
71  FILE *fpin = NULL, *fpout = NULL;
72  struct stat st;
73 
74  if (a->unlink)
75  return 0;
76 
77  struct Rfc1524MailcapEntry *entry = rfc1524_new_entry();
78  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
79  rfc1524_mailcap_lookup(a, type, entry, 0);
80  rfc1524_expand_filename(entry->nametemplate, a->filename, tempfile, sizeof(tempfile));
81 
82  rfc1524_free_entry(&entry);
83 
84  if (stat(a->filename, &st) == -1)
85  return -1;
86 
87  if ((fpin = fopen(a->filename, "r")) && (fpout = mutt_file_fopen(tempfile, "w")))
88  {
89  mutt_file_copy_stream(fpin, fpout);
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(fpin ? tempfile : a->filename);
98 
99  if (fpin)
100  mutt_file_fclose(&fpin);
101  if (fpout)
102  mutt_file_fclose(&fpout);
103 
104  return a->unlink ? 0 : -1;
105 }
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:47
#define mutt_perror(...)
Definition: logging.h:89
char * nametemplate
Definition: rfc1524.h:45
char * subtype
content-type subtype
Definition: body.h:36
void rfc1524_free_entry(struct Rfc1524MailcapEntry **entry)
Deallocate an struct Rfc1524MailcapEntry.
Definition: rfc1524.c:410
int mutt_file_copy_stream(FILE *fin, FILE *fout)
Copy the contents of one file into another.
Definition: file.c:264
#define PATH_MAX
Definition: mutt.h:46
#define TYPE(X)
Definition: mime.h:82
int rfc1524_expand_filename(char *nametemplate, char *oldfile, char *newfile, size_t nflen)
Expand a new filename from a template or existing filename.
Definition: rfc1524.c:504
A mailcap entry.
Definition: rfc1524.h:37
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:460
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:548
#define STRING
Definition: string2.h:35
int mutt_file_fclose(FILE **f)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
time_t stamp
time stamp of last encoding update.
Definition: body.h:65
int rfc1524_mailcap_lookup(struct Body *a, char *type, struct Rfc1524MailcapEntry *entry, int opt)
Find given type in the list of mailcap files.
Definition: rfc1524.c:437
bool unlink
flag to indicate the file named by "filename" should be unlink()ed before free()ing this structure ...
Definition: body.h:71
struct Rfc1524MailcapEntry * rfc1524_new_entry(void)
Allocate memory for a new rfc1524 entry.
Definition: rfc1524.c:401

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

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

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

251 {
252  char type[STRING];
253  char command[HUGE_STRING];
254  char newfile[PATH_MAX] = "";
255  struct Rfc1524MailcapEntry *entry = rfc1524_new_entry();
256  bool unlink_newfile = false;
257  int rc = 0;
258 
259  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
260  if (rfc1524_mailcap_lookup(a, type, entry, MUTT_EDIT))
261  {
262  if (entry->editcommand)
263  {
264  mutt_str_strfcpy(command, entry->editcommand, sizeof(command));
265  if (rfc1524_expand_filename(entry->nametemplate, a->filename, newfile, sizeof(newfile)))
266  {
267  mutt_debug(1, "oldfile: %s\t newfile: %s\n", a->filename, newfile);
268  if (mutt_file_symlink(a->filename, newfile) == -1)
269  {
270  if (mutt_yesorno(_("Can't match nametemplate, continue?"), MUTT_YES) != MUTT_YES)
271  goto bailout;
272  }
273  else
274  unlink_newfile = true;
275  }
276  else
277  mutt_str_strfcpy(newfile, a->filename, sizeof(newfile));
278 
279  if (rfc1524_expand_command(a, newfile, type, command, sizeof(command)))
280  {
281  /* For now, editing requires a file, no piping */
282  mutt_error(_("Mailcap Edit entry requires %%s"));
283  goto bailout;
284  }
285  else
286  {
287  mutt_endwin();
288  if (mutt_system(command) == -1)
289  {
290  mutt_error(_("Error running \"%s\""), command);
291  goto bailout;
292  }
293  }
294  }
295  }
296  else if (a->type == TYPE_TEXT)
297  {
298  /* On text, default to editor */
300  }
301  else
302  {
303  rfc1524_free_entry(&entry);
304  mutt_error(_("No mailcap edit entry for %s"), type);
305  return 0;
306  }
307 
308  rc = 1;
309 
310 bailout:
311 
312  if (unlink_newfile)
313  unlink(newfile);
314 
315  rfc1524_free_entry(&entry);
316  return rc;
317 }
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:47
#define NONULL(x)
Definition: string2.h:39
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
int mutt_yesorno(const char *msg, int def)
Ask the user a Yes/No question.
Definition: curs_lib.c:330
WHERE char * Editor
Config: External command to use as an email editor.
Definition: globals.h:110
#define _(a)
Definition: message.h:28
int mutt_file_symlink(const char *oldpath, const char *newpath)
Create a symlink.
Definition: file.c:287
Mailcap edit field.
Definition: mutt.h:176
char * nametemplate
Definition: rfc1524.h:45
#define HUGE_STRING
Definition: string2.h:37
char * subtype
content-type subtype
Definition: body.h:36
void rfc1524_free_entry(struct Rfc1524MailcapEntry **entry)
Deallocate an struct Rfc1524MailcapEntry.
Definition: rfc1524.c:410
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:498
#define PATH_MAX
Definition: mutt.h:46
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:742
#define TYPE(X)
Definition: mime.h:82
int rfc1524_expand_filename(char *nametemplate, char *oldfile, char *newfile, size_t nflen)
Expand a new filename from a template or existing filename.
Definition: rfc1524.c:504
A mailcap entry.
Definition: rfc1524.h:37
unsigned int type
content-type primary type
Definition: body.h:67
#define STRING
Definition: string2.h:35
int rfc1524_mailcap_lookup(struct Body *a, char *type, struct Rfc1524MailcapEntry *entry, int opt)
Find given type in the list of mailcap files.
Definition: rfc1524.c:437
#define mutt_error(...)
Definition: logging.h:88
char * editcommand
Definition: rfc1524.h:43
struct Rfc1524MailcapEntry * rfc1524_new_entry(void)
Allocate memory for a new rfc1524 entry.
Definition: rfc1524.c:401
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
int rfc1524_expand_command(struct Body *a, char *filename, char *type, char *command, int clen)
Expand expandos in a command.
Definition: rfc1524.c:72
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

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

326 {
327  struct ListNode *np = NULL;
328  STAILQ_FOREACH(np, &MimeLookupList, entries)
329  {
330  const int i = mutt_str_strlen(np->data) - 1;
331  if ((i > 0 && np->data[i - 1] == '/' && np->data[i] == '*' &&
332  (mutt_str_strncasecmp(type, np->data, i) == 0)) ||
333  (mutt_str_strcasecmp(type, np->data) == 0))
334  {
335  struct Body tmp = { 0 };
336  int n;
337  n = mutt_lookup_mime_type(&tmp, b->filename);
338  if (n != TYPE_OTHER)
339  {
340  snprintf(type, len, "%s/%s",
341  n == TYPE_AUDIO ? "audio" :
342  n == TYPE_APPLICATION ?
343  "application" :
344  n == TYPE_IMAGE ?
345  "image" :
346  n == TYPE_MESSAGE ?
347  "message" :
348  n == TYPE_MODEL ?
349  "model" :
350  n == TYPE_MULTIPART ?
351  "multipart" :
352  n == TYPE_TEXT ? "text" : n == TYPE_VIDEO ? "video" : "other",
353  tmp.subtype);
354  mutt_debug(1, "\"%s\" -> %s\n", b->filename, type);
355  }
356  if (tmp.subtype)
357  FREE(&tmp.subtype);
358  if (tmp.xtype)
359  FREE(&tmp.xtype);
360  }
361  }
362 }
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:47
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:663
The body of an email.
Definition: body.h:33
Type: &#39;video/*&#39;.
Definition: mime.h:39
char * subtype
content-type subtype
Definition: body.h:36
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:653
Type: &#39;text/*&#39;.
Definition: mime.h:38
char * xtype
content-type if x-unknown
Definition: body.h:35
int mutt_lookup_mime_type(struct Body *att, const char *path)
Find the MIME type for an attachment.
Definition: sendlib.c:1068
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
unsigned int type
content-type primary type
Definition: body.h:67
Type: &#39;message/*&#39;.
Definition: mime.h:35
char * data
Definition: list.h:35
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:625
Type: &#39;model/*&#39;.
Definition: mime.h:36
#define FREE(x)
Definition: memory.h:46
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,
int  flag,
struct Email e,
struct AttachCtx actx 
)

View an attachment.

Parameters
fpSource file stream. Can be NULL
aThe message body containing the attachment
flagOption flag for how the attachment should be viewed
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

flag can be one of: MUTT_MAILCAP, MUTT_REGULAR, MUTT_AS_TEXT

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

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

673 {
674  pid_t thepid;
675  int out = -1;
676  int rc = 0;
677 
678  if (outfile && *outfile)
679  {
680  out = mutt_file_open(outfile, O_CREAT | O_EXCL | O_WRONLY);
681  if (out < 0)
682  {
683  mutt_perror("open");
684  return 0;
685  }
686  }
687 
688  mutt_endwin();
689 
690  if (fp)
691  {
692  /* recv case */
693 
694  struct State s = { 0 };
695 
696  /* perform charset conversion on text attachments when piping */
697  s.flags = MUTT_CHARCONV;
698 
699  if (outfile && *outfile)
700  thepid = mutt_create_filter_fd(path, &s.fpout, NULL, NULL, -1, out, -1);
701  else
702  thepid = mutt_create_filter(path, &s.fpout, NULL, NULL);
703 
704  if (thepid < 0)
705  {
706  mutt_perror(_("Can't create filter"));
707  goto bail;
708  }
709 
710  s.fpin = fp;
711  mutt_decode_attachment(b, &s);
713  }
714  else
715  {
716  /* send case */
717 
718  FILE *ofp = NULL;
719 
720  FILE *ifp = fopen(b->filename, "r");
721  if (!ifp)
722  {
723  mutt_perror("fopen");
724  if (outfile && *outfile)
725  {
726  close(out);
727  unlink(outfile);
728  }
729  return 0;
730  }
731 
732  if (outfile && *outfile)
733  thepid = mutt_create_filter_fd(path, &ofp, NULL, NULL, -1, out, -1);
734  else
735  thepid = mutt_create_filter(path, &ofp, NULL, NULL);
736 
737  if (thepid < 0)
738  {
739  mutt_perror(_("Can't create filter"));
740  mutt_file_fclose(&ifp);
741  goto bail;
742  }
743 
744  mutt_file_copy_stream(ifp, ofp);
745  mutt_file_fclose(&ofp);
746  mutt_file_fclose(&ifp);
747  }
748 
749  rc = 1;
750 
751 bail:
752 
753  if (outfile && *outfile)
754  close(out);
755 
756  /* check for error exit from child process */
757  if (mutt_wait_filter(thepid) != 0)
758  rc = 0;
759 
760  if (rc == 0 || WaitKey)
762  return rc;
763 }
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1728
FILE * fp
source stream
Definition: pager.h:68
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:47
#define mutt_perror(...)
Definition: logging.h:89
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:44
#define _(a)
Definition: message.h:28
WHERE bool WaitKey
Config: Prompt to press a key after running external commands.
Definition: globals.h:262
FILE * fpout
Definition: state.h:34
int flags
Definition: state.h:36
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:498
int mutt_file_copy_stream(FILE *fin, FILE *fout)
Copy the contents of one file into another.
Definition: file.c:264
FILE * fpin
Definition: state.h:33
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:531
int mutt_file_fclose(FILE **f)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
int mutt_file_open(const char *path, int flags)
Open a file.
Definition: file.c:498
pid_t mutt_create_filter(const char *s, FILE **in, FILE **out, FILE **err)
Set up filter program.
Definition: filter.c:216
Keep track when processing files.
Definition: state.h:31
pid_t mutt_create_filter_fd(const char *cmd, FILE **in, FILE **out, FILE **err, int fdin, int fdout, int fderr)
Run a command on a pipe (optionally connect stdin/stdout)
Definition: filter.c:64
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,
int  flags 
)
static

Open a file to write an attachment to.

Parameters
pathPath to file to open
flagsFlags, e.g. MUTT_SAVE_APPEND
Return values
ptrFile handle to attachment file

Definition at line 771 of file mutt_attach.c.

772 {
773  if (flags == MUTT_SAVE_APPEND)
774  return fopen(path, "a");
775  if (flags == MUTT_SAVE_OVERWRITE)
776  return fopen(path, "w");
777 
778  return mutt_file_fopen(path, "w");
779 }
Overwrite existing file - mutt_save_attachment()
Definition: mutt.h:182
int flags
Definition: state.h:36
Append to existing file - mutt_save_attachment()
Definition: mutt.h:181
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:548

+ 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,
int  flags,
struct Email e 
)

Save an attachment.

Parameters
fpSource file stream. Can be NULL
mEmail Body
pathWhere to save the attachment
flagsFlags, e.g. MUTT_SAVE_APPEND
eCurrent Email. Can be NULL
Return values
0Success
-1Error

Definition at line 791 of file mutt_attach.c.

792 {
793  if (!m)
794  return -1;
795 
796  if (fp)
797  {
798  /* recv mode */
799 
800  if (e && m->email && m->encoding != ENC_BASE64 && m->encoding != ENC_QUOTED_PRINTABLE &&
802  {
803  /* message type attachments are written to mail folders. */
804 
805  char buf[HUGE_STRING];
806  struct Message *msg = NULL;
807  int chflags = 0;
808  int r = -1;
809 
810  struct Email *en = m->email;
811  en->msgno = e->msgno; /* required for MH/maildir */
812  en->read = true;
813 
814  if (fseeko(fp, m->offset, SEEK_SET) < 0)
815  return -1;
816  if (!fgets(buf, sizeof(buf), fp))
817  return -1;
818  struct Context *ctx = mx_mbox_open(NULL, path, MUTT_APPEND | MUTT_QUIET);
819  if (!ctx)
820  return -1;
821  msg = mx_msg_open_new(ctx->mailbox, en, is_from(buf, NULL, 0, NULL) ? 0 : MUTT_ADD_FROM);
822  if (!msg)
823  {
824  mx_mbox_close(&ctx, NULL);
825  return -1;
826  }
827  if ((ctx->mailbox->magic == MUTT_MBOX) || (ctx->mailbox->magic == MUTT_MMDF))
828  chflags = CH_FROM | CH_UPDATE_LEN;
829  chflags |= (ctx->mailbox->magic == MUTT_MAILDIR ? CH_NOSTATUS : CH_UPDATE);
830  if ((mutt_copy_message_fp(msg->fp, fp, en, 0, chflags) == 0) &&
831  (mx_msg_commit(ctx->mailbox, msg) == 0))
832  {
833  r = 0;
834  }
835  else
836  {
837  r = -1;
838  }
839 
840  mx_msg_close(ctx->mailbox, &msg);
841  mx_mbox_close(&ctx, NULL);
842  return r;
843  }
844  else
845  {
846  /* In recv mode, extract from folder and decode */
847 
848  struct State s = { 0 };
849 
850  s.fpout = save_attachment_open(path, flags);
851  if (!s.fpout)
852  {
853  mutt_perror("fopen");
854  return -1;
855  }
856  fseeko((s.fpin = fp), m->offset, SEEK_SET);
857  mutt_decode_attachment(m, &s);
858 
859  if (mutt_file_fsync_close(&s.fpout) != 0)
860  {
861  mutt_perror("fclose");
862  return -1;
863  }
864  }
865  }
866  else
867  {
868  if (!m->filename)
869  return -1;
870 
871  /* In send mode, just copy file */
872 
873  FILE *ofp = fopen(m->filename, "r");
874  if (!ofp)
875  {
876  mutt_perror("fopen");
877  return -1;
878  }
879 
880  FILE *nfp = save_attachment_open(path, flags);
881  if (!nfp)
882  {
883  mutt_perror("fopen");
884  mutt_file_fclose(&ofp);
885  return -1;
886  }
887 
888  if (mutt_file_copy_stream(ofp, nfp) == -1)
889  {
890  mutt_error(_("Write fault"));
891  mutt_file_fclose(&ofp);
892  mutt_file_fclose(&nfp);
893  return -1;
894  }
895  mutt_file_fclose(&ofp);
896  if (mutt_file_fsync_close(&nfp) != 0)
897  {
898  mutt_error(_("Write fault"));
899  return -1;
900  }
901  }
902 
903  return 0;
904 }
#define MUTT_APPEND
open mailbox for appending messages
Definition: mx.h:50
The "current" mailbox.
Definition: context.h:36
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1728
int mutt_file_fsync_close(FILE **f)
Flush the data, before closing a file (and NULL the pointer)
Definition: file.c:166
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:47
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition: parse.c:1214
The envelope/body of an email.
Definition: email.h:35
#define mutt_perror(...)
Definition: logging.h:89
&#39;Maildir&#39; Mailbox type
Definition: magic.h:40
&#39;mmdf&#39; Mailbox type
Definition: magic.h:38
LOFF_T offset
offset where the actual data begins
Definition: body.h:45
#define CH_FROM
retain the "From " message separator?
Definition: copy.h:51
#define _(a)
Definition: message.h:28
#define CH_NOSTATUS
suppress the status and x-status fields
Definition: copy.h:53
#define CH_UPDATE
update the status and x-status fields?
Definition: copy.h:47
FILE * fpout
Definition: state.h:34
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1187
int flags
Definition: state.h:36
bool read
Definition: email.h:49
struct Context * mx_mbox_open(struct Mailbox *m, const char *path, int flags)
Open a mailbox and parse it.
Definition: mx.c:254
struct Mailbox * mailbox
Definition: context.h:50
enum MailboxType magic
mailbox type
Definition: mailbox.h:99
unsigned int encoding
content-transfer-encoding
Definition: body.h:68
Base-64 encoded text.
Definition: mime.h:52
struct Message * mx_msg_open_new(struct Mailbox *m, struct Email *e, int flags)
Open a new message.
Definition: mx.c:1053
int mutt_copy_message_fp(FILE *fpout, FILE *fpin, struct Email *e, int flags, int chflags)
make a copy of a message from a FILE pointer
Definition: copy.c:584
int mx_mbox_close(struct Context **pctx, int *index_hint)
Save changes and close mailbox.
Definition: mx.c:568
#define HUGE_STRING
Definition: string2.h:37
char * subtype
content-type subtype
Definition: body.h:36
&#39;mbox&#39; Mailbox type
Definition: magic.h:37
A local copy of an email.
Definition: mx.h:81
int mutt_file_copy_stream(FILE *fin, FILE *fout)
Copy the contents of one file into another.
Definition: file.c:264
#define CH_UPDATE_LEN
update Lines: and Content-Length:
Definition: copy.h:57
#define MUTT_QUIET
do not print any messages
Definition: mx.h:52
FILE * fpin
Definition: state.h:33
unsigned int type
content-type primary type
Definition: body.h:67
static FILE * save_attachment_open(char *path, int flags)
Open a file to write an attachment to.
Definition: mutt_attach.c:771
int mutt_file_fclose(FILE **f)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
#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:1166
Quoted-printable text.
Definition: mime.h:51
FILE * fp
pointer to the message data
Definition: mx.h:83
Keep track when processing files.
Definition: state.h:31
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
#define MUTT_ADD_FROM
add a From_ line
Definition: mx.h:64
struct Email * email
header information for message/rfc822
Definition: body.h:59
int msgno
number displayed to the user
Definition: email.h:88

+ 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,
int  flags 
)

Decode, then save an attachment.

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

Definition at line 916 of file mutt_attach.c.

917 {
918  struct State s = { 0 };
919  unsigned int saved_encoding = 0;
920  struct Body *saved_parts = NULL;
921  struct Email *saved_hdr = NULL;
922  int rc = 0;
923 
924  s.flags = displaying;
925 
926  if (flags == MUTT_SAVE_APPEND)
927  s.fpout = fopen(path, "a");
928  else if (flags == MUTT_SAVE_OVERWRITE)
929  s.fpout = fopen(path, "w");
930  else
931  s.fpout = mutt_file_fopen(path, "w");
932 
933  if (!s.fpout)
934  {
935  mutt_perror("fopen");
936  return -1;
937  }
938 
939  if (!fp)
940  {
941  /* When called from the compose menu, the attachment isn't parsed,
942  * so we need to do it here. */
943  struct stat st;
944 
945  if (stat(m->filename, &st) == -1)
946  {
947  mutt_perror("stat");
949  return -1;
950  }
951 
952  s.fpin = fopen(m->filename, "r");
953  if (!s.fpin)
954  {
955  mutt_perror("fopen");
956  return -1;
957  }
958 
959  saved_encoding = m->encoding;
960  if (!is_multipart(m))
961  m->encoding = ENC_8BIT;
962 
963  m->length = st.st_size;
964  m->offset = 0;
965  saved_parts = m->parts;
966  saved_hdr = m->email;
967  mutt_parse_part(s.fpin, m);
968 
969  if (m->noconv || is_multipart(m))
970  s.flags |= MUTT_CHARCONV;
971  }
972  else
973  {
974  s.fpin = fp;
975  s.flags |= MUTT_CHARCONV;
976  }
977 
978  mutt_body_handler(m, &s);
979 
980  if (mutt_file_fsync_close(&s.fpout) != 0)
981  {
982  mutt_perror("fclose");
983  rc = -1;
984  }
985  if (!fp)
986  {
987  m->length = 0;
988  m->encoding = saved_encoding;
989  if (saved_parts)
990  {
991  mutt_email_free(&m->email);
992  m->parts = saved_parts;
993  m->email = saved_hdr;
994  }
996  }
997 
998  return rc;
999 }
int mutt_file_fsync_close(FILE **f)
Flush the data, before closing a file (and NULL the pointer)
Definition: file.c:166
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:47
The envelope/body of an email.
Definition: email.h:35
#define mutt_perror(...)
Definition: logging.h:89
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:44
Overwrite existing file - mutt_save_attachment()
Definition: mutt.h:182
bool noconv
don&#39;t do character set conversion
Definition: body.h:77
LOFF_T offset
offset where the actual data begins
Definition: body.h:45
8-bit text
Definition: mime.h:50
The body of an email.
Definition: body.h:33
FILE * fpout
Definition: state.h:34
int flags
Definition: state.h:36
unsigned int encoding
content-transfer-encoding
Definition: body.h:68
LOFF_T length
length (in bytes) of attachment
Definition: body.h:46
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:58
Append to existing file - mutt_save_attachment()
Definition: mutt.h:181
FILE * fpin
Definition: state.h:33
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:548
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1229
int mutt_file_fclose(FILE **f)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
char * path
Definition: email.h:93
Keep track when processing files.
Definition: state.h:31
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1502
struct Email * email
header information for message/rfc822
Definition: body.h:59
#define is_multipart(x)
Definition: mime.h:77

+ 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 Context|Header 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 1014 of file mutt_attach.c.

1015 {
1016  char newfile[PATH_MAX] = "";
1017  char type[STRING];
1018  pid_t thepid;
1019  FILE *ifp = NULL, *fpout = NULL;
1020  bool unlink_newfile = false;
1021 
1022  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
1023 
1024  if (rfc1524_mailcap_lookup(a, type, NULL, MUTT_PRINT))
1025  {
1026  char command[HUGE_STRING];
1027  int piped = false;
1028 
1029  mutt_debug(2, "Using mailcap...\n");
1030 
1031  struct Rfc1524MailcapEntry *entry = rfc1524_new_entry();
1032  rfc1524_mailcap_lookup(a, type, entry, MUTT_PRINT);
1033  if (rfc1524_expand_filename(entry->nametemplate, a->filename, newfile, sizeof(newfile)))
1034  {
1035  if (!fp)
1036  {
1037  if (mutt_file_symlink(a->filename, newfile) == -1)
1038  {
1039  if (mutt_yesorno(_("Can't match nametemplate, continue?"), MUTT_YES) != MUTT_YES)
1040  {
1041  rfc1524_free_entry(&entry);
1042  return 0;
1043  }
1044  mutt_str_strfcpy(newfile, a->filename, sizeof(newfile));
1045  }
1046  else
1047  unlink_newfile = true;
1048  }
1049  }
1050 
1051  /* in recv mode, save file to newfile first */
1052  if (fp && (mutt_save_attachment(fp, a, newfile, 0, NULL) != 0))
1053  return 0;
1054 
1055  mutt_str_strfcpy(command, entry->printcommand, sizeof(command));
1056  piped = rfc1524_expand_command(a, newfile, type, command, sizeof(command));
1057 
1058  mutt_endwin();
1059 
1060  /* interactive program */
1061  if (piped)
1062  {
1063  ifp = fopen(newfile, "r");
1064  if (!ifp)
1065  {
1066  mutt_perror("fopen");
1067  rfc1524_free_entry(&entry);
1068  return 0;
1069  }
1070 
1071  thepid = mutt_create_filter(command, &fpout, NULL, NULL);
1072  if (thepid < 0)
1073  {
1074  mutt_perror(_("Can't create filter"));
1075  rfc1524_free_entry(&entry);
1076  mutt_file_fclose(&ifp);
1077  return 0;
1078  }
1079  mutt_file_copy_stream(ifp, fpout);
1080  mutt_file_fclose(&fpout);
1081  mutt_file_fclose(&ifp);
1082  if (mutt_wait_filter(thepid) || WaitKey)
1084  }
1085  else
1086  {
1087  int rc = mutt_system(command);
1088  if (rc == -1)
1089  mutt_debug(1, "Error running \"%s\"!", command);
1090 
1091  if ((rc != 0) || WaitKey)
1093  }
1094 
1095  if (fp)
1096  mutt_file_unlink(newfile);
1097  else if (unlink_newfile)
1098  unlink(newfile);
1099 
1100  rfc1524_free_entry(&entry);
1101  return 1;
1102  }
1103 
1104  if ((mutt_str_strcasecmp("text/plain", type) == 0) ||
1105  (mutt_str_strcasecmp("application/postscript", type) == 0))
1106  {
1107  return mutt_pipe_attachment(fp, a, NONULL(PrintCommand), NULL);
1108  }
1109  else if (mutt_can_decode(a))
1110  {
1111  /* decode and print */
1112 
1113  int rc = 0;
1114 
1115  ifp = NULL;
1116  fpout = NULL;
1117 
1118  mutt_mktemp(newfile, sizeof(newfile));
1119  if (mutt_decode_save_attachment(fp, a, newfile, MUTT_PRINTING, 0) == 0)
1120  {
1121  mutt_debug(2, "successfully decoded %s type attachment to %s\n", type, newfile);
1122 
1123  ifp = fopen(newfile, "r");
1124  if (!ifp)
1125  {
1126  mutt_perror("fopen");
1127  goto bail0;
1128  }
1129 
1130  mutt_debug(2, "successfully opened %s read-only\n", newfile);
1131 
1132  mutt_endwin();
1133  thepid = mutt_create_filter(NONULL(PrintCommand), &fpout, NULL, NULL);
1134  if (thepid < 0)
1135  {
1136  mutt_perror(_("Can't create filter"));
1137  goto bail0;
1138  }
1139 
1140  mutt_debug(2, "Filter created.\n");
1141 
1142  mutt_file_copy_stream(ifp, fpout);
1143 
1144  mutt_file_fclose(&fpout);
1145  mutt_file_fclose(&ifp);
1146 
1147  if (mutt_wait_filter(thepid) != 0 || WaitKey)
1149  rc = 1;
1150  }
1151  bail0:
1152  mutt_file_fclose(&ifp);
1153  mutt_file_fclose(&fpout);
1154  mutt_file_unlink(newfile);
1155  return rc;
1156  }
1157  else
1158  {
1159  mutt_error(_("I don't know how to print that"));
1160  return 0;
1161  }
1162 }
int mutt_save_attachment(FILE *fp, struct Body *m, char *path, int flags, struct Email *e)
Save an attachment.
Definition: mutt_attach.c:791
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:47
#define NONULL(x)
Definition: string2.h:39
#define mutt_perror(...)
Definition: logging.h:89
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
int mutt_yesorno(const char *msg, int def)
Ask the user a Yes/No question.
Definition: curs_lib.c:330
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:192
#define _(a)
Definition: message.h:28
WHERE bool WaitKey
Config: Prompt to press a key after running external commands.
Definition: globals.h:262
int mutt_file_symlink(const char *oldpath, const char *newpath)
Create a symlink.
Definition: file.c:287
#define MUTT_PRINTING
are we printing? - MUTT_DISPLAY "light"
Definition: state.h:45
char * nametemplate
Definition: rfc1524.h:45
#define HUGE_STRING
Definition: string2.h:37
char * subtype
content-type subtype
Definition: body.h:36
WHERE char * PrintCommand
Config: External command to print a message.
Definition: globals.h:139
void rfc1524_free_entry(struct Rfc1524MailcapEntry **entry)
Deallocate an struct Rfc1524MailcapEntry.
Definition: rfc1524.c:410
#define mutt_mktemp(a, b)
Definition: muttlib.h:71
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:498
int mutt_file_copy_stream(FILE *fin, FILE *fout)
Copy the contents of one file into another.
Definition: file.c:264
#define PATH_MAX
Definition: mutt.h:46
int mutt_decode_save_attachment(FILE *fp, struct Body *m, char *path, int displaying, int flags)
Decode, then save an attachment.
Definition: mutt_attach.c:916
bool mutt_can_decode(struct Body *a)
Will decoding the attachment produce any output.
Definition: handler.c:1687
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:742
#define TYPE(X)
Definition: mime.h:82
int rfc1524_expand_filename(char *nametemplate, char *oldfile, char *newfile, size_t nflen)
Expand a new filename from a template or existing filename.
Definition: rfc1524.c:504
Mailcap print field.
Definition: mutt.h:178
A mailcap entry.
Definition: rfc1524.h:37
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:531
#define STRING
Definition: string2.h:35
int mutt_file_fclose(FILE **f)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
int rfc1524_mailcap_lookup(struct Body *a, char *type, struct Rfc1524MailcapEntry *entry, int opt)
Find given type in the list of mailcap files.
Definition: rfc1524.c:437
#define mutt_error(...)
Definition: logging.h:88
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:625
struct Rfc1524MailcapEntry * rfc1524_new_entry(void)
Allocate memory for a new rfc1524 entry.
Definition: rfc1524.c:401
char * printcommand
Definition: rfc1524.h:44
pid_t mutt_create_filter(const char *s, FILE **in, FILE **out, FILE **err)
Set up filter program.
Definition: filter.c:216
#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 rfc1524_expand_command(struct Body *a, char *filename, char *type, char *command, int clen)
Expand expandos in a command.
Definition: rfc1524.c:72
int mutt_pipe_attachment(FILE *fp, struct Body *b, const char *path, char *outfile)
Pipe an attachment to a command.
Definition: mutt_attach.c:672
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:50

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

1169 {
1170  mutt_list_insert_tail(&TempAttachmentsList, mutt_str_strdup(filename));
1171 }
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:384

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

1177 {
1178  struct ListNode *np = NULL;
1179 
1180  STAILQ_FOREACH(np, &TempAttachmentsList, entries)
1181  {
1182  mutt_file_chmod_add(np->data, S_IWUSR);
1183  mutt_file_unlink(np->data);
1184  }
1185 
1186  mutt_list_free(&TempAttachmentsList);
1187 }
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:192
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:971
#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: