NeoMutt  2018-07-16 +2225-8687db
Teaching an old dog new tricks
DOXYGEN
handler.c File Reference

Decide how to display email content. More...

#include "config.h"
#include <stddef.h>
#include <ctype.h>
#include <iconv.h>
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include "mutt/mutt.h"
#include "email/lib.h"
#include "mutt.h"
#include "handler.h"
#include "copy.h"
#include "enriched.h"
#include "filter.h"
#include "globals.h"
#include "keymap.h"
#include "mutt_attach.h"
#include "mutt_logging.h"
#include "muttlib.h"
#include "ncrypt/ncrypt.h"
#include "opcodes.h"
#include "options.h"
#include "rfc1524.h"
#include "rfc3676.h"
#include "state.h"
#include <libintl.h>

Go to the source code of this file.

Macros

#define BUFI_SIZE   1000
 
#define BUFO_SIZE   2000
 
#define TXT_HTML   1
 
#define TXT_PLAIN   2
 
#define TXT_ENRICHED   3
 

Typedefs

typedef int(* handler_t) (struct Body *b, struct State *s)
 typedef handler_t - Manage a PGP or S/MIME encrypted MIME part More...
 

Functions

static void print_part_line (struct State *s, struct Body *b, int n)
 Print a separator for the Mime part. More...
 
static void convert_to_state (iconv_t cd, char *bufi, size_t *l, struct State *s)
 Convert text and write it to a file. More...
 
static void decode_xbit (struct State *s, long len, bool istext, iconv_t cd)
 Decode xbit-encoded text. More...
 
static int qp_decode_triple (char *s, char *d)
 Decode a quoted-printable triplet. More...
 
static void qp_decode_line (char *dest, char *src, size_t *l, int last)
 Decode a line of quoted-printable text. More...
 
static void decode_quoted (struct State *s, long len, bool istext, iconv_t cd)
 Decode an attachment encoded with quoted-printable. More...
 
static unsigned char decode_byte (char ch)
 Decode a uuencoded byte. More...
 
static void decode_uuencoded (struct State *s, long len, bool istext, iconv_t cd)
 Decode uuencoded text. More...
 
static bool is_mmnoask (const char *buf)
 Metamail compatibility: should the attachment be autoviewed? More...
 
static bool is_autoview (struct Body *b)
 Should email body be filtered by mailcap. More...
 
static int autoview_handler (struct Body *a, struct State *s)
 Handler for autoviewable attachments - Implements handler_t. More...
 
static int text_plain_handler (struct Body *b, struct State *s)
 Handler for plain text - Implements handler_t. More...
 
static int message_handler (struct Body *a, struct State *s)
 Handler for message/rfc822 body parts - Implements handler_t. More...
 
static int external_body_handler (struct Body *b, struct State *s)
 Handler for external-body emails - Implements handler_t. More...
 
static int alternative_handler (struct Body *a, struct State *s)
 Handler for multipart alternative emails - Implements handler_t. More...
 
static int multilingual_handler (struct Body *a, struct State *s)
 Handler for multi-lingual emails - Implements handler_t. More...
 
static int multipart_handler (struct Body *a, struct State *s)
 Handler for multipart emails - Implements handler_t. More...
 
static int run_decode_and_handler (struct Body *b, struct State *s, handler_t handler, bool plaintext)
 Run an appropriate decoder for an email. More...
 
static int valid_pgp_encrypted_handler (struct Body *b, struct State *s)
 Handler for valid pgp-encrypted emails - Implements handler_t. More...
 
static int malformed_pgp_encrypted_handler (struct Body *b, struct State *s)
 Handler for invalid pgp-encrypted emails - Implements handler_t. More...
 
void mutt_decode_base64 (struct State *s, size_t len, bool istext, iconv_t cd)
 Decode base64-encoded text. More...
 
int mutt_body_handler (struct Body *b, struct State *s)
 Handler for the Body of an email. More...
 
bool mutt_can_decode (struct Body *a)
 Will decoding the attachment produce any output. More...
 
void mutt_decode_attachment (struct Body *b, struct State *s)
 Decode an email's attachment. More...
 

Variables

bool C_HonorDisposition
 Config: Don't display MIME parts inline if they have a disposition of 'attachment'. More...
 
bool C_ImplicitAutoview
 Config: Display MIME attachments inline if a 'copiousoutput' mailcap entry exists. More...
 
bool C_IncludeEncrypted
 Config: Whether to include encrypted content when replying. More...
 
bool C_IncludeOnlyfirst
 Config: Only include the first attachment when replying. More...
 
struct SlistC_PreferredLanguages
 Config: Preferred languages for multilingual MIME. More...
 
bool C_ReflowText
 Config: Reformat paragraphs of 'format=flowed' text. More...
 
char * C_ShowMultipartAlternative
 Config: How to display 'multipart/alternative' MIME parts. More...
 

Detailed Description

Decide how to display email content.

Authors
  • Michael R. Elkins

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

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

Definition in file handler.c.

Macro Definition Documentation

#define BUFI_SIZE   1000

Definition at line 72 of file handler.c.

#define BUFO_SIZE   2000

Definition at line 73 of file handler.c.

#define TXT_HTML   1

Definition at line 75 of file handler.c.

#define TXT_PLAIN   2

Definition at line 76 of file handler.c.

#define TXT_ENRICHED   3

Definition at line 77 of file handler.c.

Typedef Documentation

typedef int(* handler_t) (struct Body *b, struct State *s)

typedef handler_t - Manage a PGP or S/MIME encrypted MIME part

Parameters
mBody of the email
sState of text being processed
Return values
0Success
-1Error

Definition at line 86 of file handler.c.

Function Documentation

static void print_part_line ( struct State s,
struct Body b,
int  n 
)
static

Print a separator for the Mime part.

Parameters
sState of text being processed
bBody of the email
nPart number for multipart emails (0 otherwise)

Definition at line 94 of file handler.c.

95 {
96  char length[5];
97  mutt_str_pretty_size(length, sizeof(length), b->length);
99  char *charset = mutt_param_get(&b->parameter, "charset");
100  if (n != 0)
101  {
102  state_printf(s, _("[-- Alternative Type #%d: %s/%s%s%s, Encoding: %s, Size: %s --]\n"),
103  n, TYPE(b), b->subtype, charset ? "; charset=" : "",
104  charset ? charset : "", ENCODING(b->encoding), length);
105  }
106  else
107  {
108  state_printf(s, _("[-- Type: %s/%s%s%s, Encoding: %s, Size: %s --]\n"),
109  TYPE(b), b->subtype, charset ? "; charset=" : "",
110  charset ? charset : "", ENCODING(b->encoding), length);
111  }
112 }
int state_printf(struct State *s, const char *fmt,...)
Write a formatted string to the State.
Definition: state.c:147
#define _(a)
Definition: message.h:28
#define ENCODING(x)
Definition: mime.h:85
unsigned int encoding
content-transfer-encoding
Definition: body.h:66
char * subtype
content-type subtype
Definition: body.h:37
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
void state_mark_attach(struct State *s)
Write a unique marker around content.
Definition: state.c:41
#define TYPE(body)
Definition: mime.h:83
char * mutt_param_get(const struct ParameterList *p, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
void mutt_str_pretty_size(char *buf, size_t buflen, size_t num)
Display an abbreviated size, like 3.4K.
Definition: string.c:1047
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
static void convert_to_state ( iconv_t  cd,
char *  bufi,
size_t *  l,
struct State s 
)
static

Convert text and write it to a file.

Parameters
cdIconv conversion descriptor
bufiBuffer with text to convert
lLength of buffer
sState to write to

Definition at line 121 of file handler.c.

122 {
123  char bufo[BUFO_SIZE];
124  const char *ib = NULL;
125  char *ob = NULL;
126  size_t ibl, obl;
127 
128  if (!bufi)
129  {
130  if (cd != (iconv_t)(-1))
131  {
132  ob = bufo;
133  obl = sizeof(bufo);
134  iconv(cd, NULL, NULL, &ob, &obl);
135  if (ob != bufo)
136  state_prefix_put(bufo, ob - bufo, s);
137  }
138  return;
139  }
140 
141  if (cd == (iconv_t)(-1))
142  {
143  state_prefix_put(bufi, *l, s);
144  *l = 0;
145  return;
146  }
147 
148  ib = bufi;
149  ibl = *l;
150  while (true)
151  {
152  ob = bufo;
153  obl = sizeof(bufo);
154  mutt_ch_iconv(cd, &ib, &ibl, &ob, &obl, 0, "?", NULL);
155  if (ob == bufo)
156  break;
157  state_prefix_put(bufo, ob - bufo, s);
158  }
159  memmove(bufi, ib, ibl);
160  *l = ibl;
161 }
void state_prefix_put(const char *buf, size_t buflen, struct State *s)
Write a prefixed fixed-string to the State.
Definition: state.c:165
size_t mutt_ch_iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft, const char **inrepls, const char *outrepl, int *iconverrno)
Change the encoding of a string.
Definition: charset.c:588
#define BUFO_SIZE
Definition: handler.c:73
static void decode_xbit ( struct State s,
long  len,
bool  istext,
iconv_t  cd 
)
static

Decode xbit-encoded text.

Parameters
sState to work with
lenLength of text to decode
istextMime part is plain text
cdIconv conversion descriptor

Definition at line 170 of file handler.c.

171 {
172  if (!istext)
173  {
174  mutt_file_copy_bytes(s->fp_in, s->fp_out, len);
175  return;
176  }
177 
178  state_set_prefix(s);
179 
180  int c;
181  char bufi[BUFI_SIZE];
182  size_t l = 0;
183  while (((c = fgetc(s->fp_in)) != EOF) && len--)
184  {
185  if ((c == '\r') && len)
186  {
187  const int ch = fgetc(s->fp_in);
188  if (ch == '\n')
189  {
190  c = ch;
191  len--;
192  }
193  else
194  ungetc(ch, s->fp_in);
195  }
196 
197  bufi[l++] = c;
198  if (l == sizeof(bufi))
199  convert_to_state(cd, bufi, &l, s);
200  }
201 
202  convert_to_state(cd, bufi, &l, s);
203  convert_to_state(cd, 0, 0, s);
204 
206 }
#define state_reset_prefix(state)
Definition: state.h:53
int ch
raw key pressed
Definition: mutt_curses.h:110
FILE * fp_out
File to write to.
Definition: state.h:47
FILE * fp_in
File to read from.
Definition: state.h:46
#define BUFI_SIZE
Definition: handler.c:72
int mutt_file_copy_bytes(FILE *fp_in, FILE *fp_out, size_t size)
Copy some content from one file to another.
Definition: file.c:237
#define state_set_prefix(state)
Definition: state.h:52
static void convert_to_state(iconv_t cd, char *bufi, size_t *l, struct State *s)
Convert text and write it to a file.
Definition: handler.c:121
static int qp_decode_triple ( char *  s,
char *  d 
)
static

Decode a quoted-printable triplet.

Parameters
sState to work with
dDecoded character
Return values
0Success
-1Error

Definition at line 215 of file handler.c.

216 {
217  /* soft line break */
218  if ((s[0] == '=') && (s[1] == '\0'))
219  return 1;
220 
221  /* quoted-printable triple */
222  if ((s[0] == '=') && isxdigit((unsigned char) s[1]) && isxdigit((unsigned char) s[2]))
223  {
224  *d = (hexval(s[1]) << 4) | hexval(s[2]);
225  return 0;
226  }
227 
228  /* something else */
229  return -1;
230 }
#define hexval(ch)
Definition: mime.h:75
static void qp_decode_line ( char *  dest,
char *  src,
size_t *  l,
int  last 
)
static

Decode a line of quoted-printable text.

Parameters
destBuffer for result
srcText to decode
lBytes written to buffer
lastLast character of the line

Definition at line 239 of file handler.c.

240 {
241  char *d = NULL, *s = NULL;
242  char c = 0;
243 
244  int kind = -1;
245  bool soft = false;
246 
247  /* decode the line */
248 
249  for (d = dest, s = src; *s;)
250  {
251  switch ((kind = qp_decode_triple(s, &c)))
252  {
253  case 0:
254  *d++ = c;
255  s += 3;
256  break; /* qp triple */
257  case -1:
258  *d++ = *s++;
259  break; /* single character */
260  case 1:
261  soft = true;
262  s++;
263  break; /* soft line break */
264  }
265  }
266 
267  if (!soft && (last == '\n'))
268  {
269  /* neither \r nor \n as part of line-terminating CRLF
270  * may be qp-encoded, so remove \r and \n-terminate;
271  * see RFC2045, sect. 6.7, (1): General 8bit representation */
272  if ((kind == 0) && (c == '\r'))
273  *(d - 1) = '\n';
274  else
275  *d++ = '\n';
276  }
277 
278  *d = '\0';
279  *l = d - dest;
280 }
static int qp_decode_triple(char *s, char *d)
Decode a quoted-printable triplet.
Definition: handler.c:215
static void decode_quoted ( struct State s,
long  len,
bool  istext,
iconv_t  cd 
)
static

Decode an attachment encoded with quoted-printable.

Parameters
sState to work with
lenLength of text to decode
istextMime part is plain text
cdIconv conversion descriptor

Why doesn't this overflow any buffers? First, it's guaranteed that the length of a line grows when you en-code it to quoted-printable. That means that we always can store the result in a buffer of at most the same size.

Now, we don't special-case if the line we read with fgets() isn't terminated. We don't care about this, since 256 > 78, so corrupted input will just be corrupted a bit more. That implies that 256+1 bytes are always sufficient to store the result of qp_decode_line.

Finally, at soft line breaks, some part of a multibyte character may have been left over by convert_to_state(). This shouldn't be more than 6 characters, so 256+7 should be sufficient memory to store the decoded data.

Just to make sure that I didn't make some off-by-one error above, we just use 512 for the target buffer's size.

Definition at line 307 of file handler.c.

308 {
309  char line[256];
310  char decline[512];
311  size_t l = 0;
312  size_t l3;
313 
314  if (istext)
315  state_set_prefix(s);
316 
317  while (len > 0)
318  {
319  /* It's ok to use a fixed size buffer for input, even if the line turns
320  * out to be longer than this. Just process the line in chunks. This
321  * really shouldn't happen according the MIME spec, since Q-P encoded
322  * lines are at most 76 characters, but we should be liberal about what
323  * we accept. */
324  if (!fgets(line, MIN((ssize_t) sizeof(line), len + 1), s->fp_in))
325  break;
326 
327  size_t linelen = strlen(line);
328  len -= linelen;
329 
330  /* inspect the last character we read so we can tell if we got the
331  * entire line. */
332  const int last = (linelen != 0) ? line[linelen - 1] : 0;
333 
334  /* chop trailing whitespace if we got the full line */
335  if (last == '\n')
336  {
337  while ((linelen > 0) && IS_SPACE(line[linelen - 1]))
338  linelen--;
339  line[linelen] = '\0';
340  }
341 
342  /* decode and do character set conversion */
343  qp_decode_line(decline + l, line, &l3, last);
344  l += l3;
345  convert_to_state(cd, decline, &l, s);
346  }
347 
348  convert_to_state(cd, 0, 0, s);
350 }
#define MIN(a, b)
Definition: memory.h:31
#define state_reset_prefix(state)
Definition: state.h:53
FILE * fp_in
File to read from.
Definition: state.h:46
static void qp_decode_line(char *dest, char *src, size_t *l, int last)
Decode a line of quoted-printable text.
Definition: handler.c:239
const char * line
Definition: common.c:36
#define IS_SPACE(ch)
Definition: string2.h:38
#define state_set_prefix(state)
Definition: state.h:52
static void convert_to_state(iconv_t cd, char *bufi, size_t *l, struct State *s)
Convert text and write it to a file.
Definition: handler.c:121
static unsigned char decode_byte ( char  ch)
static

Decode a uuencoded byte.

Parameters
chCharacter to decode
Return values
numDecoded value

Definition at line 357 of file handler.c.

358 {
359  if ((ch < 32) || (ch > 95))
360  return 0;
361  return ch - 32;
362 }
int ch
raw key pressed
Definition: mutt_curses.h:110
static void decode_uuencoded ( struct State s,
long  len,
bool  istext,
iconv_t  cd 
)
static

Decode uuencoded text.

Parameters
sState to work with
lenLength of text to decode
istextMime part is plain text
cdIconv conversion descriptor

Definition at line 371 of file handler.c.

372 {
373  char tmps[128];
374  char *pt = NULL;
375  char bufi[BUFI_SIZE];
376  size_t k = 0;
377 
378  if (istext)
379  state_set_prefix(s);
380 
381  while (len > 0)
382  {
383  if (!fgets(tmps, sizeof(tmps), s->fp_in))
384  return;
385  len -= mutt_str_strlen(tmps);
386  if (mutt_str_startswith(tmps, "begin ", CASE_MATCH))
387  break;
388  }
389  while (len > 0)
390  {
391  if (!fgets(tmps, sizeof(tmps), s->fp_in))
392  return;
393  len -= mutt_str_strlen(tmps);
394  if (mutt_str_startswith(tmps, "end", CASE_MATCH))
395  break;
396  pt = tmps;
397  const unsigned char linelen = decode_byte(*pt);
398  pt++;
399  for (unsigned char c = 0; c < linelen;)
400  {
401  for (char l = 2; l <= 6; l += 2)
402  {
403  char out = decode_byte(*pt) << l;
404  pt++;
405  out |= (decode_byte(*pt) >> (6 - l));
406  bufi[k++] = out;
407  c++;
408  if (c == linelen)
409  break;
410  }
411  convert_to_state(cd, bufi, &k, s);
412  pt++;
413  }
414  }
415 
416  convert_to_state(cd, bufi, &k, s);
417  convert_to_state(cd, 0, 0, s);
418 
420 }
#define state_reset_prefix(state)
Definition: state.h:53
Match case when comparing strings.
Definition: string2.h:67
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:666
static unsigned char decode_byte(char ch)
Decode a uuencoded byte.
Definition: handler.c:357
FILE * fp_in
File to read from.
Definition: state.h:46
#define BUFI_SIZE
Definition: handler.c:72
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
#define state_set_prefix(state)
Definition: state.h:52
static void convert_to_state(iconv_t cd, char *bufi, size_t *l, struct State *s)
Convert text and write it to a file.
Definition: handler.c:121
static bool is_mmnoask ( const char *  buf)
static

Metamail compatibility: should the attachment be autoviewed?

Parameters
bufMime type, e.g. 'text/plain'
Return values
trueMetamail "no ask" is true

Test if the MM_NOASK environment variable should allow autoviewing of the attachment.

Note
If MM_NOASK=1 then the function will automatically return true.

Definition at line 432 of file handler.c.

433 {
434  const char *val = mutt_str_getenv("MM_NOASK");
435  if (!val)
436  return false;
437 
438  char *p = NULL;
439  char tmp[1024];
440  char *q = NULL;
441 
442  if (mutt_str_strcmp(val, "1") == 0)
443  return true;
444 
445  mutt_str_strfcpy(tmp, val, sizeof(tmp));
446  p = tmp;
447 
448  while ((p = strtok(p, ",")))
449  {
450  q = strrchr(p, '/');
451  if (q)
452  {
453  if (q[1] == '*')
454  {
455  if (mutt_str_strncasecmp(buf, p, q - p) == 0)
456  return true;
457  }
458  else
459  {
460  if (mutt_str_strcasecmp(buf, p) == 0)
461  return true;
462  }
463  }
464  else
465  {
466  const size_t plen = mutt_str_startswith(buf, p, CASE_IGNORE);
467  if ((plen != 0) && (buf[plen] == '/'))
468  return true;
469  }
470 
471  p = NULL;
472  }
473 
474  return false;
475 }
static size_t plen
Length of cached packet.
Definition: pgppacket.c:38
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:1084
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:656
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:750
Ignore case when comparing strings.
Definition: string2.h:68
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:628
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
static bool is_autoview ( struct Body b)
static

Should email body be filtered by mailcap.

Parameters
bBody of the email
Return values
1body part should be filtered by a mailcap entry prior to viewing inline
0otherwise

Definition at line 483 of file handler.c.

484 {
485  char type[128];
486  bool is_av = false;
487 
488  snprintf(type, sizeof(type), "%s/%s", TYPE(b), b->subtype);
489 
490  if (C_ImplicitAutoview)
491  {
492  /* $implicit_autoview is essentially the same as "auto_view *" */
493  is_av = true;
494  }
495  else
496  {
497  /* determine if this type is on the user's auto_view list */
498  mutt_check_lookup_list(b, type, sizeof(type));
499  struct ListNode *np = NULL;
500  STAILQ_FOREACH(np, &AutoViewList, entries)
501  {
502  int i = mutt_str_strlen(np->data) - 1;
503  if (((i > 0) && (np->data[i - 1] == '/') && (np->data[i] == '*') &&
504  (mutt_str_strncasecmp(type, np->data, i) == 0)) ||
505  (mutt_str_strcasecmp(type, np->data) == 0))
506  {
507  is_av = true;
508  break;
509  }
510  }
511 
512  if (is_mmnoask(type))
513  is_av = true;
514  }
515 
516  /* determine if there is a mailcap entry suitable for auto_view
517  *
518  * @warning type is altered by this call as a result of 'mime_lookup' support */
519  if (is_av)
520  return rfc1524_mailcap_lookup(b, type, NULL, MUTT_MC_AUTOVIEW);
521 
522  return false;
523 }
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:466
Mailcap autoview field.
Definition: rfc1524.h:61
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:666
static bool is_mmnoask(const char *buf)
Metamail compatibility: should the attachment be autoviewed?
Definition: handler.c:432
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:656
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
#define TYPE(body)
Definition: mime.h:83
char * data
Definition: list.h:35
void mutt_check_lookup_list(struct Body *b, char *type, size_t len)
Update the mime type.
Definition: mutt_attach.c:331
bool C_ImplicitAutoview
Config: Display MIME attachments inline if a &#39;copiousoutput&#39; mailcap entry exists.
Definition: handler.c:65
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:628
A List node for strings.
Definition: list.h:33
static int autoview_handler ( struct Body a,
struct State s 
)
static

Handler for autoviewable attachments - Implements handler_t.

Definition at line 528 of file handler.c.

529 {
530  struct Rfc1524MailcapEntry *entry = rfc1524_new_entry();
531  char buf[1024];
532  char type[256];
533  struct Buffer *cmd = mutt_buffer_pool_get();
534  struct Buffer *tempfile = mutt_buffer_pool_get();
535  char *fname = NULL;
536  FILE *fp_in = NULL;
537  FILE *fp_out = NULL;
538  FILE *fp_err = NULL;
539  pid_t pid;
540  int rc = 0;
541 
542  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
544 
545  fname = mutt_str_strdup(a->filename);
546  mutt_file_sanitize_filename(fname, true);
547  mutt_rfc1524_expand_filename(entry->nametemplate, fname, tempfile);
548  FREE(&fname);
549 
550  if (entry->command)
551  {
552  if ((s->flags & MUTT_REPLYING) && entry->composecommand)
553  mutt_buffer_strcpy(cmd, entry->composecommand);
554  else
555  mutt_buffer_strcpy(cmd, entry->command);
556 
557  /* mutt_rfc1524_expand_command returns 0 if the file is required */
558  bool piped = mutt_rfc1524_expand_command(a, mutt_b2s(tempfile), type, cmd);
559 
560  if (s->flags & MUTT_DISPLAY)
561  {
563  state_printf(s, _("[-- Autoview using %s --]\n"), mutt_b2s(cmd));
564  mutt_message(_("Invoking autoview command: %s"), mutt_b2s(cmd));
565  }
566 
567  fp_in = mutt_file_fopen(mutt_b2s(tempfile), "w+");
568  if (!fp_in)
569  {
570  mutt_perror("fopen");
571  rfc1524_free_entry(&entry);
572  rc = -1;
573  goto cleanup;
574  }
575 
576  mutt_file_copy_bytes(s->fp_in, fp_in, a->length);
577 
578  if (!piped)
579  {
580  mutt_file_fclose(&fp_in);
581  pid = mutt_create_filter(mutt_b2s(cmd), NULL, &fp_out, &fp_err);
582  }
583  else
584  {
585  unlink(mutt_b2s(tempfile));
586  fflush(fp_in);
587  rewind(fp_in);
588  pid = mutt_create_filter_fd(mutt_b2s(cmd), NULL, &fp_out, &fp_err,
589  fileno(fp_in), -1, -1);
590  }
591 
592  if (pid < 0)
593  {
594  mutt_perror(_("Can't create filter"));
595  if (s->flags & MUTT_DISPLAY)
596  {
598  state_printf(s, _("[-- Can't run %s. --]\n"), mutt_b2s(cmd));
599  }
600  rc = -1;
601  goto bail;
602  }
603 
604  if (s->prefix)
605  {
606  while (fgets(buf, sizeof(buf), fp_out))
607  {
608  state_puts(s->prefix, s);
609  state_puts(buf, s);
610  }
611  /* check for data on stderr */
612  if (fgets(buf, sizeof(buf), fp_err))
613  {
614  if (s->flags & MUTT_DISPLAY)
615  {
617  state_printf(s, _("[-- Autoview stderr of %s --]\n"), mutt_b2s(cmd));
618  }
619 
620  state_puts(s->prefix, s);
621  state_puts(buf, s);
622  while (fgets(buf, sizeof(buf), fp_err))
623  {
624  state_puts(s->prefix, s);
625  state_puts(buf, s);
626  }
627  }
628  }
629  else
630  {
631  mutt_file_copy_stream(fp_out, s->fp_out);
632  /* Check for stderr messages */
633  if (fgets(buf, sizeof(buf), fp_err))
634  {
635  if (s->flags & MUTT_DISPLAY)
636  {
638  state_printf(s, _("[-- Autoview stderr of %s --]\n"), mutt_b2s(cmd));
639  }
640 
641  state_puts(buf, s);
642  mutt_file_copy_stream(fp_err, s->fp_out);
643  }
644  }
645 
646  bail:
647  mutt_file_fclose(&fp_out);
648  mutt_file_fclose(&fp_err);
649 
650  mutt_wait_filter(pid);
651  if (piped)
652  mutt_file_fclose(&fp_in);
653  else
654  mutt_file_unlink(mutt_b2s(tempfile));
655 
656  if (s->flags & MUTT_DISPLAY)
658  }
659 
660 cleanup:
661  rfc1524_free_entry(&entry);
662 
664  mutt_buffer_pool_release(&tempfile);
665 
666  return rc;
667 }
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_rfc1524_expand_filename(const char *nametemplate, const char *oldfile, struct Buffer *newfile)
Expand a new filename from a template or existing filename.
Definition: rfc1524.c:519
int state_printf(struct State *s, const char *fmt,...)
Write a formatted string to the State.
Definition: state.c:147
int mutt_rfc1524_expand_command(struct Body *a, const char *filename, const char *type, struct Buffer *command)
Expand expandos in a command.
Definition: rfc1524.c:71
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:75
#define mutt_perror(...)
Definition: logging.h:85
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:466
Mailcap autoview field.
Definition: rfc1524.h:61
#define mutt_message(...)
Definition: logging.h:83
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:86
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:191
String manipulation buffer.
Definition: buffer.h:33
char * prefix
String to add to the beginning of each output line.
Definition: state.h:48
#define _(a)
Definition: message.h:28
Mailcap compose field.
Definition: rfc1524.h:59
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
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:141
char * nametemplate
Definition: rfc1524.h:45
char * subtype
content-type subtype
Definition: body.h:37
void mutt_file_sanitize_filename(char *path, bool slash)
Replace unsafe characters in a filename.
Definition: file.c:614
#define mutt_b2s(buf)
Definition: buffer.h:42
void rfc1524_free_entry(struct Rfc1524MailcapEntry **entry)
Deallocate an struct Rfc1524MailcapEntry.
Definition: rfc1524.c:438
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:314
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
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_file_copy_bytes(FILE *fp_in, FILE *fp_out, size_t size)
Copy some content from one file to another.
Definition: file.c:237
A mailcap entry.
Definition: rfc1524.h:37
void state_mark_attach(struct State *s)
Write a unique marker around content.
Definition: state.c:41
char * composecommand
Definition: rfc1524.h:41
#define TYPE(body)
Definition: mime.h:83
#define state_puts(str, state)
Definition: state.h:54
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:267
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
struct Rfc1524MailcapEntry * rfc1524_new_entry(void)
Allocate memory for a new rfc1524 entry.
Definition: rfc1524.c:429
#define FREE(x)
Definition: memory.h:40
#define MUTT_REPLYING
Are we replying?
Definition: state.h:38
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:584
int mutt_wait_filter(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:227
static int text_plain_handler ( struct Body b,
struct State s 
)
static

Handler for plain text - Implements handler_t.

Return values
0Always

When generating format=flowed ($text_flowed is set) from format=fixed, strip all trailing spaces to improve interoperability; if $text_flowed is unset, simply verbatim copy input.

Definition at line 677 of file handler.c.

678 {
679  char *buf = NULL;
680  size_t sz = 0;
681 
682  while ((buf = mutt_file_read_line(buf, &sz, s->fp_in, NULL, 0)))
683  {
684  if ((mutt_str_strcmp(buf, "-- ") != 0) && C_TextFlowed)
685  {
686  size_t len = mutt_str_strlen(buf);
687  while ((len > 0) && (buf[len - 1] == ' '))
688  buf[--len] = '\0';
689  }
690  if (s->prefix)
691  state_puts(s->prefix, s);
692  state_puts(buf, s);
693  state_putc('\n', s);
694  }
695 
696  FREE(&buf);
697  return 0;
698 }
char * prefix
String to add to the beginning of each output line.
Definition: state.h:48
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, int flags)
Read a line from a file.
Definition: file.c:663
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:666
FILE * fp_in
File to read from.
Definition: state.h:46
WHERE bool C_TextFlowed
Config: Generate &#39;format=flowed&#39; messages.
Definition: globals.h:255
#define state_puts(str, state)
Definition: state.h:54
#define state_putc(str, state)
Definition: state.h:55
#define FREE(x)
Definition: memory.h:40
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
static int message_handler ( struct Body a,
struct State s 
)
static

Handler for message/rfc822 body parts - Implements handler_t.

Definition at line 703 of file handler.c.

704 {
705  struct stat st;
706  struct Body *b = NULL;
707  LOFF_T off_start;
708  int rc = 0;
709 
710  off_start = ftello(s->fp_in);
711  if (off_start < 0)
712  return -1;
713 
714  if ((a->encoding == ENC_BASE64) || (a->encoding == ENC_QUOTED_PRINTABLE) ||
715  (a->encoding == ENC_UUENCODED))
716  {
717  fstat(fileno(s->fp_in), &st);
718  b = mutt_body_new();
719  b->length = (LOFF_T) st.st_size;
721  }
722  else
723  b = a;
724 
725  if (b->parts)
726  {
727  CopyHeaderFlags chflags = CH_DECODE | CH_FROM;
728  if ((s->flags & MUTT_WEED) || ((s->flags & (MUTT_DISPLAY | MUTT_PRINTING)) && C_Weed))
729  chflags |= CH_WEED | CH_REORDER;
730  if (s->prefix)
731  chflags |= CH_PREFIX;
732  if (s->flags & MUTT_DISPLAY)
733  chflags |= CH_DISPLAY;
734 
735  mutt_copy_hdr(s->fp_in, s->fp_out, off_start, b->parts->offset, chflags, s->prefix);
736 
737  if (s->prefix)
738  state_puts(s->prefix, s);
739  state_putc('\n', s);
740 
741  rc = mutt_body_handler(b->parts, s);
742  }
743 
744  if ((a->encoding == ENC_BASE64) || (a->encoding == ENC_QUOTED_PRINTABLE) ||
745  (a->encoding == ENC_UUENCODED))
746  {
747  mutt_body_free(&b);
748  }
749 
750  return rc;
751 }
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
char * prefix
String to add to the beginning of each output line.
Definition: state.h:48
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
#define CH_FROM
Retain the "From " message separator?
Definition: copy.h:55
FILE * fp_out
File to write to.
Definition: state.h:47
#define MUTT_PRINTING
Are we printing? - MUTT_DISPLAY "light".
Definition: state.h:37
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
struct Body * mutt_rfc822_parse_message(FILE *fp, struct Body *parent)
parse a Message/RFC822 body
Definition: parse.c:1443
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
#define CH_WEED
Weed the headers?
Definition: copy.h:52
unsigned int encoding
content-transfer-encoding
Definition: body.h:66
Base-64 encoded text.
Definition: mime.h:52
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
#define CH_REORDER
Re-order output of headers (specified by &#39;hdr_order&#39;)
Definition: copy.h:58
#define CH_DECODE
Do RFC2047 header decoding.
Definition: copy.h:53
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
#define CH_DISPLAY
Display result to user.
Definition: copy.h:69
#define MUTT_WEED
Weed headers even when not in display mode.
Definition: state.h:35
#define state_puts(str, state)
Definition: state.h:54
void mutt_body_free(struct Body **p)
Free a Body.
Definition: body.c:57
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition: copy.h:49
#define state_putc(str, state)
Definition: state.h:55
Quoted-printable text.
Definition: mime.h:51
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1544
#define CH_PREFIX
Quote header using C_IndentString string?
Definition: copy.h:56
int mutt_copy_hdr(FILE *fp_in, FILE *fp_out, LOFF_T off_start, LOFF_T off_end, CopyHeaderFlags chflags, const char *prefix)
Copy header from one file to another.
Definition: copy.c:74
UUEncoded text.
Definition: mime.h:54
bool C_Weed
Config: Filter headers when displaying/forwarding/printing/replying.
Definition: email_globals.c:40
static int external_body_handler ( struct Body b,
struct State s 
)
static

Handler for external-body emails - Implements handler_t.

Definition at line 756 of file handler.c.

757 {
758  const char *str = NULL;
759  char strbuf[1024];
760 
761  const char *access_type = mutt_param_get(&b->parameter, "access-type");
762  if (!access_type)
763  {
764  if (s->flags & MUTT_DISPLAY)
765  {
767  state_puts(_("[-- Error: message/external-body has no access-type "
768  "parameter --]\n"),
769  s);
770  return 0;
771  }
772  else
773  return -1;
774  }
775 
776  const char *expiration = mutt_param_get(&b->parameter, "expiration");
777  time_t expire;
778  if (expiration)
779  expire = mutt_date_parse_date(expiration, NULL);
780  else
781  expire = -1;
782 
783  if (mutt_str_strcasecmp(access_type, "x-mutt-deleted") == 0)
784  {
785  if (s->flags & (MUTT_DISPLAY | MUTT_PRINTING))
786  {
787  char pretty_size[10];
788  char *length = mutt_param_get(&b->parameter, "length");
789  if (length)
790  {
791  long size = strtol(length, NULL, 10);
792  mutt_str_pretty_size(pretty_size, sizeof(pretty_size), size);
793  if (expire != -1)
794  {
795  str = ngettext(
796  /* L10N: If the translation of this string is a multi line string, then
797  each line should start with "[-- " and end with " --]".
798  The first "%s/%s" is a MIME type, e.g. "text/plain". The last %s
799  expands to a date as returned by `mutt_date_parse_date()`.
800 
801  Note: The size argument printed is not the actual number as passed
802  to gettext but the prettified version, e.g. size = 2048 will be
803  printed as 2K. Your language might be sensitive to that: For
804  example although '1K' and '1024' represent the same number your
805  language might inflect the noun 'byte' differently.
806 
807  Sadly, we can't do anything about that at the moment besides
808  passing the precise size in bytes. If you are interested the
809  function responsible for the prettification is
810  mutt_str_pretty_size() in mutt/string.c. */
811  "[-- This %s/%s attachment (size %s byte) has been deleted --]\n"
812  "[-- on %s --]\n",
813  "[-- This %s/%s attachment (size %s bytes) has been deleted --]\n"
814  "[-- on %s --]\n",
815  size);
816  }
817  else
818  {
819  str = ngettext(
820  /* L10N: If the translation of this string is a multi line string, then
821  each line should start with "[-- " and end with " --]".
822  The first "%s/%s" is a MIME type, e.g. "text/plain".
823 
824  Note: The size argument printed is not the actual number as passed
825  to gettext but the prettified version, e.g. size = 2048 will be
826  printed as 2K. Your language might be sensitive to that: For
827  example although '1K' and '1024' represent the same number your
828  language might inflect the noun 'byte' differently.
829 
830  Sadly, we can't do anything about that at the moment besides
831  passing the precise size in bytes. If you are interested the
832  function responsible for the prettification is
833  mutt_str_pretty_size() in mutt/string.c. */
834  "[-- This %s/%s attachment (size %s byte) has been deleted --]\n",
835  "[-- This %s/%s attachment (size %s bytes) has been deleted "
836  "--]\n",
837  size);
838  }
839  }
840  else
841  {
842  pretty_size[0] = '\0';
843  if (expire != -1)
844  {
845  /* L10N: If the translation of this string is a multi line string, then
846  each line should start with "[-- " and end with " --]".
847  The first "%s/%s" is a MIME type, e.g. "text/plain". The last %s
848  expands to a date as returned by `mutt_date_parse_date()`.
849 
850  Caution: Argument three %3$ is also defined but should not be used
851  in this translation! */
852  str = _("[-- This %s/%s attachment has been deleted --]\n[-- on %4$s "
853  "--]\n");
854  }
855  else
856  {
857  /* L10N: If the translation of this string is a multi line string, then
858  each line should start with "[-- " and end with " --]".
859  The first "%s/%s" is a MIME type, e.g. "text/plain". */
860  str = _("[-- This %s/%s attachment has been deleted --]\n");
861  }
862  }
863 
864  snprintf(strbuf, sizeof(strbuf), str, TYPE(b->parts), b->parts->subtype,
865  pretty_size, expiration);
866  state_attach_puts(strbuf, s);
867  if (b->parts->filename)
868  {
870  state_printf(s, _("[-- name: %s --]\n"), b->parts->filename);
871  }
872 
873  CopyHeaderFlags chflags = CH_DECODE;
874  if (C_Weed)
875  chflags |= CH_WEED | CH_REORDER;
876 
877  mutt_copy_hdr(s->fp_in, s->fp_out, ftello(s->fp_in), b->parts->offset, chflags, NULL);
878  }
879  }
880  else if (expiration && (expire < time(NULL)))
881  {
882  if (s->flags & MUTT_DISPLAY)
883  {
884  /* L10N: If the translation of this string is a multi line string, then
885  each line should start with "[-- " and end with " --]".
886  The "%s/%s" is a MIME type, e.g. "text/plain". */
887  snprintf(strbuf, sizeof(strbuf), _("[-- This %s/%s attachment is not included, --]\n[-- and the indicated external source has --]\n[-- expired. --]\n"),
888  TYPE(b->parts), b->parts->subtype);
889  state_attach_puts(strbuf, s);
890 
892  if (C_Weed)
893  chflags |= CH_WEED | CH_REORDER;
894 
895  mutt_copy_hdr(s->fp_in, s->fp_out, ftello(s->fp_in), b->parts->offset, chflags, NULL);
896  }
897  }
898  else
899  {
900  if (s->flags & MUTT_DISPLAY)
901  {
902  /* L10N: If the translation of this string is a multi line string, then
903  each line should start with "[-- " and end with " --]".
904  The "%s/%s" is a MIME type, e.g. "text/plain". The %s after
905  access-type is an access-type as defined by the MIME RFCs, e.g. "FTP",
906  "LOCAL-FILE", "MAIL-SERVER". */
907  snprintf(strbuf, sizeof(strbuf), _("[-- This %s/%s attachment is not included, --]\n[-- and the indicated access-type %s is unsupported --]\n"),
908  TYPE(b->parts), b->parts->subtype, access_type);
909  state_attach_puts(strbuf, s);
910 
912  if (C_Weed)
913  chflags |= CH_WEED | CH_REORDER;
914 
915  mutt_copy_hdr(s->fp_in, s->fp_out, ftello(s->fp_in), b->parts->offset, chflags, NULL);
916  }
917  }
918 
919  return 0;
920 }
int state_printf(struct State *s, const char *fmt,...)
Write a formatted string to the State.
Definition: state.c:147
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
#define _(a)
Definition: message.h:28
FILE * fp_out
File to write to.
Definition: state.h:47
#define MUTT_PRINTING
Are we printing? - MUTT_DISPLAY "light".
Definition: state.h:37
time_t mutt_date_parse_date(const char *s, struct Tz *tz_out)
Parse a date string in RFC822 format.
Definition: date.c:436
void state_attach_puts(const char *t, struct State *s)
Write a string to the state.
Definition: state.c:64
FILE * fp_in
File to read from.
Definition: state.h:46
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
#define CH_WEED
Weed the headers?
Definition: copy.h:52
char * subtype
content-type subtype
Definition: body.h:37
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
#define CH_REORDER
Re-order output of headers (specified by &#39;hdr_order&#39;)
Definition: copy.h:58
#define CH_DECODE
Do RFC2047 header decoding.
Definition: copy.h:53
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
#define CH_DISPLAY
Display result to user.
Definition: copy.h:69
void state_mark_attach(struct State *s)
Write a unique marker around content.
Definition: state.c:41
#define TYPE(body)
Definition: mime.h:83
#define state_puts(str, state)
Definition: state.h:54
char * mutt_param_get(const struct ParameterList *p, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition: copy.h:49
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:628
void mutt_str_pretty_size(char *buf, size_t buflen, size_t num)
Display an abbreviated size, like 3.4K.
Definition: string.c:1047
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
int mutt_copy_hdr(FILE *fp_in, FILE *fp_out, LOFF_T off_start, LOFF_T off_end, CopyHeaderFlags chflags, const char *prefix)
Copy header from one file to another.
Definition: copy.c:74
bool C_Weed
Config: Filter headers when displaying/forwarding/printing/replying.
Definition: email_globals.c:40
static int alternative_handler ( struct Body a,
struct State s 
)
static

Handler for multipart alternative emails - Implements handler_t.

Definition at line 925 of file handler.c.

926 {
927  struct Body *choice = NULL;
928  struct Body *b = NULL;
929  bool mustfree = false;
930  int rc = 0;
931 
932  if ((a->encoding == ENC_BASE64) || (a->encoding == ENC_QUOTED_PRINTABLE) ||
933  (a->encoding == ENC_UUENCODED))
934  {
935  struct stat st;
936  mustfree = true;
937  fstat(fileno(s->fp_in), &st);
938  b = mutt_body_new();
939  b->length = (long) st.st_size;
941  s->fp_in, mutt_param_get(&a->parameter, "boundary"), (long) st.st_size,
942  (mutt_str_strcasecmp("digest", a->subtype) == 0));
943  }
944  else
945  b = a;
946 
947  a = b;
948 
949  /* First, search list of preferred types */
950  struct ListNode *np = NULL;
951  STAILQ_FOREACH(np, &AlternativeOrderList, entries)
952  {
953  int btlen; /* length of basetype */
954  bool wild; /* do we have a wildcard to match all subtypes? */
955 
956  char *c = strchr(np->data, '/');
957  if (c)
958  {
959  wild = ((c[1] == '*') && (c[2] == '\0'));
960  btlen = c - np->data;
961  }
962  else
963  {
964  wild = true;
965  btlen = mutt_str_strlen(np->data);
966  }
967 
968  if (a->parts)
969  b = a->parts;
970  else
971  b = a;
972  while (b)
973  {
974  const char *bt = TYPE(b);
975  if ((mutt_str_strncasecmp(bt, np->data, btlen) == 0) && (bt[btlen] == 0))
976  {
977  /* the basetype matches */
978  if (wild || (mutt_str_strcasecmp(np->data + btlen + 1, b->subtype) == 0))
979  {
980  choice = b;
981  }
982  }
983  b = b->next;
984  }
985 
986  if (choice)
987  break;
988  }
989 
990  /* Next, look for an autoviewable type */
991  if (!choice)
992  {
993  if (a->parts)
994  b = a->parts;
995  else
996  b = a;
997  while (b)
998  {
999  if (is_autoview(b))
1000  choice = b;
1001  b = b->next;
1002  }
1003  }
1004 
1005  /* Then, look for a text entry */
1006  if (!choice)
1007  {
1008  if (a->parts)
1009  b = a->parts;
1010  else
1011  b = a;
1012  int type = 0;
1013  while (b)
1014  {
1015  if (b->type == TYPE_TEXT)
1016  {
1017  if ((mutt_str_strcasecmp("plain", b->subtype) == 0) && (type <= TXT_PLAIN))
1018  {
1019  choice = b;
1020  type = TXT_PLAIN;
1021  }
1022  else if ((mutt_str_strcasecmp("enriched", b->subtype) == 0) && (type <= TXT_ENRICHED))
1023  {
1024  choice = b;
1025  type = TXT_ENRICHED;
1026  }
1027  else if ((mutt_str_strcasecmp("html", b->subtype) == 0) && (type <= TXT_HTML))
1028  {
1029  choice = b;
1030  type = TXT_HTML;
1031  }
1032  }
1033  b = b->next;
1034  }
1035  }
1036 
1037  /* Finally, look for other possibilities */
1038  if (!choice)
1039  {
1040  if (a->parts)
1041  b = a->parts;
1042  else
1043  b = a;
1044  while (b)
1045  {
1046  if (mutt_can_decode(b))
1047  choice = b;
1048  b = b->next;
1049  }
1050  }
1051 
1052  if (choice)
1053  {
1054  if (s->flags & MUTT_DISPLAY && !C_Weed)
1055  {
1056  fseeko(s->fp_in, choice->hdr_offset, SEEK_SET);
1057  mutt_file_copy_bytes(s->fp_in, s->fp_out, choice->offset - choice->hdr_offset);
1058  }
1059 
1060  if (mutt_str_strcmp("info", C_ShowMultipartAlternative) == 0)
1061  {
1062  print_part_line(s, choice, 0);
1063  }
1064  mutt_body_handler(choice, s);
1065 
1066  if (mutt_str_strcmp("info", C_ShowMultipartAlternative) == 0)
1067  {
1068  if (a->parts)
1069  b = a->parts;
1070  else
1071  b = a;
1072  int count = 0;
1073  while (b)
1074  {
1075  if (choice != b)
1076  {
1077  count += 1;
1078  if (count == 1)
1079  state_putc('\n', s);
1080 
1081  print_part_line(s, b, count);
1082  }
1083  b = b->next;
1084  }
1085  }
1086  }
1087  else if (s->flags & MUTT_DISPLAY)
1088  {
1089  /* didn't find anything that we could display! */
1090  state_mark_attach(s);
1091  state_puts(_("[-- Error: Could not display any parts of "
1092  "Multipart/Alternative --]\n"),
1093  s);
1094  rc = -1;
1095  }
1096 
1097  if (mustfree)
1098  mutt_body_free(&a);
1099 
1100  return rc;
1101 }
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
static bool is_autoview(struct Body *b)
Should email body be filtered by mailcap.
Definition: handler.c:483
#define TXT_HTML
Definition: handler.c:75
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
#define _(a)
Definition: message.h:28
struct Body * mutt_parse_multipart(FILE *fp, const char *boundary, LOFF_T end_off, bool digest)
parse a multipart structure
Definition: parse.c:1341
struct Body * next
next attachment in the list
Definition: body.h:53
FILE * fp_out
File to write to.
Definition: state.h:47
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:666
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
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
#define TXT_PLAIN
Definition: handler.c:76
unsigned int encoding
content-transfer-encoding
Definition: body.h:66
Base-64 encoded text.
Definition: mime.h:52
char * subtype
content-type subtype
Definition: body.h:37
#define TXT_ENRICHED
Definition: handler.c:77
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:656
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
Type: &#39;text/*&#39;.
Definition: mime.h:38
bool mutt_can_decode(struct Body *a)
Will decoding the attachment produce any output.
Definition: handler.c:1748
static void print_part_line(struct State *s, struct Body *b, int n)
Print a separator for the Mime part.
Definition: handler.c:94
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
int mutt_file_copy_bytes(FILE *fp_in, FILE *fp_out, size_t size)
Copy some content from one file to another.
Definition: file.c:237
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
void state_mark_attach(struct State *s)
Write a unique marker around content.
Definition: state.c:41
unsigned int type
content-type primary type
Definition: body.h:65
#define TYPE(body)
Definition: mime.h:83
#define state_puts(str, state)
Definition: state.h:54
char * mutt_param_get(const struct ParameterList *p, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
void mutt_body_free(struct Body **p)
Free a Body.
Definition: body.c:57
char * data
Definition: list.h:35
#define state_putc(str, state)
Definition: state.h:55
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:628
Quoted-printable text.
Definition: mime.h:51
char * C_ShowMultipartAlternative
Config: How to display &#39;multipart/alternative&#39; MIME parts.
Definition: handler.c:70
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1544
long hdr_offset
Offset in stream where the headers begin.
Definition: body.h:42
A List node for strings.
Definition: list.h:33
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
UUEncoded text.
Definition: mime.h:54
bool C_Weed
Config: Filter headers when displaying/forwarding/printing/replying.
Definition: email_globals.c:40
static int multilingual_handler ( struct Body a,
struct State s 
)
static

Handler for multi-lingual emails - Implements handler_t.

Return values
0Always

Definition at line 1107 of file handler.c.

1108 {
1109  struct Body *b = NULL;
1110  bool mustfree = false;
1111  int rc = 0;
1112 
1114  "RFC8255 >> entering in handler multilingual handler\n");
1115  if ((a->encoding == ENC_BASE64) || (a->encoding == ENC_QUOTED_PRINTABLE) ||
1116  (a->encoding == ENC_UUENCODED))
1117  {
1118  struct stat st;
1119  mustfree = true;
1120  fstat(fileno(s->fp_in), &st);
1121  b = mutt_body_new();
1122  b->length = (long) st.st_size;
1124  s->fp_in, mutt_param_get(&a->parameter, "boundary"), (long) st.st_size,
1125  (mutt_str_strcasecmp("digest", a->subtype) == 0));
1126  }
1127  else
1128  b = a;
1129 
1130  a = b;
1131 
1132  if (a->parts)
1133  b = a->parts;
1134  else
1135  b = a;
1136 
1138  {
1139  struct Buffer *langs = mutt_buffer_pool_get();
1140  cs_str_string_get(Config, "preferred_languages", langs);
1141  mutt_debug(LL_DEBUG2, "RFC8255 >> preferred_languages set in config to '%s'\n",
1142  mutt_b2s(langs));
1143  mutt_buffer_pool_release(&langs);
1144  }
1145 
1146  struct Body *choice = NULL;
1147  struct Body *first_part = NULL;
1148  struct Body *zxx_part = NULL;
1149  struct ListNode *np = NULL;
1150 
1151  STAILQ_FOREACH(np, &C_PreferredLanguages->head, entries)
1152  {
1153  while (b)
1154  {
1155  if (mutt_can_decode(b))
1156  {
1157  if (!first_part)
1158  first_part = b;
1159 
1160  if (b->language && (mutt_str_strcmp("zxx", b->language) == 0))
1161  zxx_part = b;
1162 
1163  mutt_debug(LL_DEBUG2, "RFC8255 >> comparing configuration preferred_language='%s' to mail part content-language='%s'\n",
1164  np->data, b->language);
1165  if (b->language && (mutt_str_strcmp(np->data, b->language) == 0))
1166  {
1167  mutt_debug(LL_DEBUG2, "RFC8255 >> preferred_language='%s' matches content-language='%s' >> part selected to be displayed\n",
1168  np->data, b->language);
1169  choice = b;
1170  break;
1171  }
1172  }
1173 
1174  b = b->next;
1175  }
1176 
1177  if (choice)
1178  break;
1179 
1180  if (a->parts)
1181  b = a->parts;
1182  else
1183  b = a;
1184  }
1185 
1186  if (choice)
1187  mutt_body_handler(choice, s);
1188  else
1189  {
1190  if (zxx_part)
1191  mutt_body_handler(zxx_part, s);
1192  else
1193  mutt_body_handler(first_part, s);
1194  }
1195 
1196  if (mustfree)
1197  mutt_body_free(&a);
1198 
1199  return rc;
1200 }
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:75
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:86
String manipulation buffer.
Definition: buffer.h:33
WHERE struct ConfigSet * Config
Wrapper around the user&#39;s config settings.
Definition: globals.h:39
struct Body * mutt_parse_multipart(FILE *fp, const char *boundary, LOFF_T end_off, bool digest)
parse a multipart structure
Definition: parse.c:1341
struct Body * next
next attachment in the list
Definition: body.h:53
FILE * fp_in
File to read from.
Definition: state.h:46
The body of an email.
Definition: body.h:34
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
Log at debug level 2.
Definition: logging.h:57
struct ListHead head
Definition: slist.h:45
int cs_str_string_get(const struct ConfigSet *cs, const char *name, struct Buffer *result)
Get a config item as a string.
Definition: set.c:697
unsigned int encoding
content-transfer-encoding
Definition: body.h:66
Base-64 encoded text.
Definition: mime.h:52
char * subtype
content-type subtype
Definition: body.h:37
#define mutt_b2s(buf)
Definition: buffer.h:42
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
bool mutt_can_decode(struct Body *a)
Will decoding the attachment produce any output.
Definition: handler.c:1748
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
char * mutt_param_get(const struct ParameterList *p, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
void mutt_body_free(struct Body **p)
Free a Body.
Definition: body.c:57
char * data
Definition: list.h:35
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:628
Quoted-printable text.
Definition: mime.h:51
char * language
content-language (RFC8255)
Definition: body.h:38
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1544
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
A List node for strings.
Definition: list.h:33
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
struct Slist * C_PreferredLanguages
Config: Preferred languages for multilingual MIME.
Definition: handler.c:68
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
UUEncoded text.
Definition: mime.h:54
static int multipart_handler ( struct Body a,
struct State s 
)
static

Handler for multipart emails - Implements handler_t.

Definition at line 1205 of file handler.c.

1206 {
1207  struct Body *b = NULL, *p = NULL;
1208  struct stat st;
1209  int count;
1210  int rc = 0;
1211 
1212  if ((a->encoding == ENC_BASE64) || (a->encoding == ENC_QUOTED_PRINTABLE) ||
1213  (a->encoding == ENC_UUENCODED))
1214  {
1215  fstat(fileno(s->fp_in), &st);
1216  b = mutt_body_new();
1217  b->length = (long) st.st_size;
1219  s->fp_in, mutt_param_get(&a->parameter, "boundary"), (long) st.st_size,
1220  (mutt_str_strcasecmp("digest", a->subtype) == 0));
1221  }
1222  else
1223  b = a;
1224 
1225  for (p = b->parts, count = 1; p; p = p->next, count++)
1226  {
1227  if (s->flags & MUTT_DISPLAY)
1228  {
1229  state_mark_attach(s);
1230  if (p->description || p->filename || p->form_name)
1231  {
1232  /* L10N: %s is the attachment description, filename or form_name. */
1233  state_printf(s, _("[-- Attachment #%d: %s --]\n"), count,
1234  p->description ? p->description :
1235  p->filename ? p->filename : p->form_name);
1236  }
1237  else
1238  state_printf(s, _("[-- Attachment #%d --]\n"), count);
1239  print_part_line(s, p, 0);
1240  if (!C_Weed)
1241  {
1242  fseeko(s->fp_in, p->hdr_offset, SEEK_SET);
1243  mutt_file_copy_bytes(s->fp_in, s->fp_out, p->offset - p->hdr_offset);
1244  }
1245  else
1246  state_putc('\n', s);
1247  }
1248 
1249  rc = mutt_body_handler(p, s);
1250  state_putc('\n', s);
1251 
1252  if (rc != 0)
1253  {
1254  mutt_error(_("One or more parts of this message could not be displayed"));
1255  mutt_debug(LL_DEBUG1, "Failed on attachment #%d, type %s/%s\n", count,
1256  TYPE(p), NONULL(p->subtype));
1257  }
1258 
1259  if ((s->flags & MUTT_REPLYING) && C_IncludeOnlyfirst && (s->flags & MUTT_FIRSTDONE))
1260  {
1261  break;
1262  }
1263  }
1264 
1265  if ((a->encoding == ENC_BASE64) || (a->encoding == ENC_QUOTED_PRINTABLE) ||
1266  (a->encoding == ENC_UUENCODED))
1267  {
1268  mutt_body_free(&b);
1269  }
1270 
1271  /* make failure of a single part non-fatal */
1272  if (rc < 0)
1273  rc = 1;
1274  return rc;
1275 }
int state_printf(struct State *s, const char *fmt,...)
Write a formatted string to the State.
Definition: state.c:147
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
#define NONULL(x)
Definition: string2.h:37
#define _(a)
Definition: message.h:28
struct Body * mutt_parse_multipart(FILE *fp, const char *boundary, LOFF_T end_off, bool digest)
parse a multipart structure
Definition: parse.c:1341
struct Body * next
next attachment in the list
Definition: body.h:53
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
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
unsigned int encoding
content-transfer-encoding
Definition: body.h:66
Base-64 encoded text.
Definition: mime.h:52
char * subtype
content-type subtype
Definition: body.h:37
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
static void print_part_line(struct State *s, struct Body *b, int n)
Print a separator for the Mime part.
Definition: handler.c:94
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
int mutt_file_copy_bytes(FILE *fp_in, FILE *fp_out, size_t size)
Copy some content from one file to another.
Definition: file.c:237
void state_mark_attach(struct State *s)
Write a unique marker around content.
Definition: state.c:41
#define TYPE(body)
Definition: mime.h:83
char * mutt_param_get(const struct ParameterList *p, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
void mutt_body_free(struct Body **p)
Free a Body.
Definition: body.c:57
Log at debug level 1.
Definition: logging.h:56
#define mutt_error(...)
Definition: logging.h:84
#define state_putc(str, state)
Definition: state.h:55
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:628
Quoted-printable text.
Definition: mime.h:51
#define MUTT_REPLYING
Are we replying?
Definition: state.h:38
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1544
#define MUTT_FIRSTDONE
The first attachment has been done.
Definition: state.h:39
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
bool C_IncludeOnlyfirst
Config: Only include the first attachment when replying.
Definition: handler.c:67
UUEncoded text.
Definition: mime.h:54
bool C_Weed
Config: Filter headers when displaying/forwarding/printing/replying.
Definition: email_globals.c:40
static int run_decode_and_handler ( struct Body b,
struct State s,
handler_t  handler,
bool  plaintext 
)
static

Run an appropriate decoder for an email.

Parameters
bBody of the email
sState to work with
handlerCallback function to process the content - Implements handler_t
plaintextIs the content in plain text
Return values
0Success
-1Error

Definition at line 1286 of file handler.c.

1288 {
1289  char *save_prefix = NULL;
1290  FILE *fp = NULL;
1291  size_t tmplength = 0;
1292  LOFF_T tmpoffset = 0;
1293  int decode = 0;
1294  int rc = 0;
1295 
1296  fseeko(s->fp_in, b->offset, SEEK_SET);
1297 
1298 #ifdef USE_FMEMOPEN
1299  char *temp = NULL;
1300  size_t tempsize = 0;
1301 #endif
1302 
1303  /* see if we need to decode this part before processing it */
1304  if ((b->encoding == ENC_BASE64) || (b->encoding == ENC_QUOTED_PRINTABLE) ||
1305  (b->encoding == ENC_UUENCODED) || (plaintext || mutt_is_text_part(b)))
1306  /* text subtypes may require character set conversion even with 8bit encoding */
1307  {
1308  const int orig_type = b->type;
1309 #ifndef USE_FMEMOPEN
1310  char tempfile[PATH_MAX];
1311 #endif
1312  if (!plaintext)
1313  {
1314  /* decode to a tempfile, saving the original destination */
1315  fp = s->fp_out;
1316 #ifdef USE_FMEMOPEN
1317  s->fp_out = open_memstream(&temp, &tempsize);
1318  if (!s->fp_out)
1319  {
1320  mutt_error(_("Unable to open 'memory stream'"));
1321  mutt_debug(LL_DEBUG1, "Can't open 'memory stream'\n");
1322  return -1;
1323  }
1324 #else
1325  mutt_mktemp(tempfile, sizeof(tempfile));
1326  s->fp_out = mutt_file_fopen(tempfile, "w");
1327  if (!s->fp_out)
1328  {
1329  mutt_error(_("Unable to open temporary file"));
1330  mutt_debug(LL_DEBUG1, "Can't open %s\n", tempfile);
1331  return -1;
1332  }
1333 #endif
1334  /* decoding the attachment changes the size and offset, so save a copy
1335  * of the "real" values now, and restore them after processing */
1336  tmplength = b->length;
1337  tmpoffset = b->offset;
1338 
1339  /* if we are decoding binary bodies, we don't want to prefix each
1340  * line with the prefix or else the data will get corrupted. */
1341  save_prefix = s->prefix;
1342  s->prefix = NULL;
1343 
1344  decode = 1;
1345  }
1346  else
1347  b->type = TYPE_TEXT;
1348 
1349  mutt_decode_attachment(b, s);
1350 
1351  if (decode)
1352  {
1353  b->length = ftello(s->fp_out);
1354  b->offset = 0;
1355 #ifdef USE_FMEMOPEN
1356  /* When running under torify, mutt_file_fclose(&s->fp_out) does not seem to
1357  * update tempsize. On the other hand, fflush does. See
1358  * https://github.com/neomutt/neomutt/issues/440 */
1359  fflush(s->fp_out);
1360 #endif
1361  mutt_file_fclose(&s->fp_out);
1362 
1363  /* restore final destination and substitute the tempfile for input */
1364  s->fp_out = fp;
1365  fp = s->fp_in;
1366 #ifdef USE_FMEMOPEN
1367  if (tempsize)
1368  {
1369  s->fp_in = fmemopen(temp, tempsize, "r");
1370  }
1371  else
1372  { /* fmemopen can't handle zero-length buffers */
1373  s->fp_in = mutt_file_fopen("/dev/null", "r");
1374  }
1375  if (!s->fp_in)
1376  {
1377  mutt_perror(_("failed to re-open 'memory stream'"));
1378  return -1;
1379  }
1380 #else
1381  s->fp_in = fopen(tempfile, "r");
1382  unlink(tempfile);
1383 #endif
1384  /* restore the prefix */
1385  s->prefix = save_prefix;
1386  }
1387 
1388  b->type = orig_type;
1389  }
1390 
1391  /* process the (decoded) body part */
1392  if (handler)
1393  {
1394  rc = handler(b, s);
1395  if (rc != 0)
1396  {
1397  mutt_debug(LL_DEBUG1, "Failed on attachment of type %s/%s\n", TYPE(b),
1398  NONULL(b->subtype));
1399  }
1400 
1401  if (decode)
1402  {
1403  b->length = tmplength;
1404  b->offset = tmpoffset;
1405 
1406  /* restore the original source stream */
1407  mutt_file_fclose(&s->fp_in);
1408 #ifdef USE_FMEMOPEN
1409  FREE(&temp);
1410 #endif
1411  s->fp_in = fp;
1412  }
1413  }
1414  s->flags |= MUTT_FIRSTDONE;
1415 
1416  return rc;
1417 }
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1789
#define NONULL(x)
Definition: string2.h:37
#define mutt_perror(...)
Definition: logging.h:85
char * prefix
String to add to the beginning of each output line.
Definition: state.h:48
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
#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
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
unsigned int encoding
content-transfer-encoding
Definition: body.h:66
Base-64 encoded text.
Definition: mime.h:52
char * subtype
content-type subtype
Definition: body.h:37
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:76
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
#define PATH_MAX
Definition: mutt.h:50
Type: &#39;text/*&#39;.
Definition: mime.h:38
bool mutt_is_text_part(struct Body *b)
Is this part of an email in plain text?
Definition: muttlib.c:436
unsigned int type
content-type primary type
Definition: body.h:65
#define TYPE(body)
Definition: mime.h:83
Log at debug level 1.
Definition: logging.h:56
#define mutt_error(...)
Definition: logging.h:84
Quoted-printable text.
Definition: mime.h:51
#define FREE(x)
Definition: memory.h:40
#define MUTT_FIRSTDONE
The first attachment has been done.
Definition: state.h:39
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:584
UUEncoded text.
Definition: mime.h:54
static int valid_pgp_encrypted_handler ( struct Body b,
struct State s 
)
static

Handler for valid pgp-encrypted emails - Implements handler_t.

Definition at line 1422 of file handler.c.

1423 {
1424  struct Body *octetstream = b->parts->next;
1425 
1426  /* clear out any mime headers before the handler, so they can't be spoofed. */
1428  mutt_env_free(&octetstream->mime_headers);
1429 
1430  int rc;
1431  /* Some clients improperly encode the octetstream part. */
1432  if (octetstream->encoding != ENC_7BIT)
1433  rc = run_decode_and_handler(octetstream, s, crypt_pgp_encrypted_handler, 0);
1434  else
1435  rc = crypt_pgp_encrypted_handler(octetstream, s);
1436  b->goodsig |= octetstream->goodsig;
1437 
1438  /* Relocate protected headers onto the multipart/encrypted part */
1439  if (!rc && octetstream->mime_headers)
1440  {
1441  b->mime_headers = octetstream->mime_headers;
1442  octetstream->mime_headers = NULL;
1443  }
1444 
1445  return rc;
1446 }
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:63
7-bit text
Definition: mime.h:49
struct Body * next
next attachment in the list
Definition: body.h:53
The body of an email.
Definition: body.h:34
int crypt_pgp_encrypted_handler(struct Body *a, struct State *s)
Wrapper for CryptModuleSpecs::encrypted_handler()
Definition: cryptglue.c:219
unsigned int encoding
content-transfer-encoding
Definition: body.h:66
bool goodsig
Good cryptographic signature.
Definition: body.h:81
static int run_decode_and_handler(struct Body *b, struct State *s, handler_t handler, bool plaintext)
Run an appropriate decoder for an email.
Definition: handler.c:1286
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
void mutt_env_free(struct Envelope **p)
Free an Envelope.
Definition: envelope.c:63
static int malformed_pgp_encrypted_handler ( struct Body b,
struct State s 
)
static

Handler for invalid pgp-encrypted emails - Implements handler_t.

Definition at line 1451 of file handler.c.

1452 {
1453  struct Body *octetstream = b->parts->next->next;
1454 
1455  /* clear out any mime headers before the handler, so they can't be spoofed. */
1457  mutt_env_free(&octetstream->mime_headers);
1458 
1459  /* exchange encodes the octet-stream, so re-run it through the decoder */
1460  int rc = run_decode_and_handler(octetstream, s, crypt_pgp_encrypted_handler, false);
1461  b->goodsig |= octetstream->goodsig;
1462 
1463  /* Relocate protected headers onto the multipart/encrypted part */
1464  if (!rc && octetstream->mime_headers)
1465  {
1466  b->mime_headers = octetstream->mime_headers;
1467  octetstream->mime_headers = NULL;
1468  }
1469 
1470  return rc;
1471 }
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:63
struct Body * next
next attachment in the list
Definition: body.h:53
The body of an email.
Definition: body.h:34
int crypt_pgp_encrypted_handler(struct Body *a, struct State *s)
Wrapper for CryptModuleSpecs::encrypted_handler()
Definition: cryptglue.c:219
bool goodsig
Good cryptographic signature.
Definition: body.h:81
static int run_decode_and_handler(struct Body *b, struct State *s, handler_t handler, bool plaintext)
Run an appropriate decoder for an email.
Definition: handler.c:1286
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
void mutt_env_free(struct Envelope **p)
Free an Envelope.
Definition: envelope.c:63
void mutt_decode_base64 ( struct State s,
size_t  len,
bool  istext,
iconv_t  cd 
)

Decode base64-encoded text.

Parameters
sState to work with
lenLength of text to decode
istextMime part is plain text
cdIconv conversion descriptor

Definition at line 1480 of file handler.c.

1481 {
1482  char buf[5];
1483  int ch, i;
1484  char bufi[BUFI_SIZE];
1485  size_t l = 0;
1486 
1487  buf[4] = '\0';
1488 
1489  if (istext)
1490  state_set_prefix(s);
1491 
1492  while (len > 0)
1493  {
1494  for (i = 0; (i < 4) && (len > 0); len--)
1495  {
1496  ch = fgetc(s->fp_in);
1497  if (ch == EOF)
1498  break;
1499  if ((ch >= 0) && (ch < 128) && ((base64val(ch) != -1) || (ch == '=')))
1500  buf[i++] = ch;
1501  }
1502  if (i != 4)
1503  {
1504  /* "i" may be zero if there is trailing whitespace, which is not an error */
1505  if (i != 0)
1506  mutt_debug(LL_DEBUG2, "didn't get a multiple of 4 chars\n");
1507  break;
1508  }
1509 
1510  const int c1 = base64val(buf[0]);
1511  const int c2 = base64val(buf[1]);
1512  ch = (c1 << 2) | (c2 >> 4);
1513  bufi[l++] = ch;
1514 
1515  if (buf[2] == '=')
1516  break;
1517  const int c3 = base64val(buf[2]);
1518  ch = ((c2 & 0xf) << 4) | (c3 >> 2);
1519  bufi[l++] = ch;
1520 
1521  if (buf[3] == '=')
1522  break;
1523  const int c4 = base64val(buf[3]);
1524  ch = ((c3 & 0x3) << 6) | c4;
1525  bufi[l++] = ch;
1526 
1527  if ((l + 8) >= sizeof(bufi))
1528  convert_to_state(cd, bufi, &l, s);
1529  }
1530 
1531  convert_to_state(cd, bufi, &l, s);
1532  convert_to_state(cd, 0, 0, s);
1533 
1534  state_reset_prefix(s);
1535 }
#define state_reset_prefix(state)
Definition: state.h:53
FILE * fp_in
File to read from.
Definition: state.h:46
Log at debug level 2.
Definition: logging.h:57
#define BUFI_SIZE
Definition: handler.c:72
#define state_set_prefix(state)
Definition: state.h:52
#define base64val(ch)
Definition: base64.h:30
static void convert_to_state(iconv_t cd, char *bufi, size_t *l, struct State *s)
Convert text and write it to a file.
Definition: handler.c:121
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
int mutt_body_handler ( struct Body b,
struct State s 
)

Handler for the Body of an email.

Parameters
bBody of the email
sState to work with
Return values
0Success
-1Error

Definition at line 1544 of file handler.c.

1545 {
1546  if (!b || !s)
1547  return -1;
1548 
1549  bool plaintext = false;
1550  handler_t handler = NULL;
1551  handler_t encrypted_handler = NULL;
1552  int rc = 0;
1553 
1554  int oflags = s->flags;
1555 
1556  /* first determine which handler to use to process this part */
1557 
1558  if (is_autoview(b))
1559  {
1560  handler = autoview_handler;
1561  s->flags &= ~MUTT_CHARCONV;
1562  }
1563  else if (b->type == TYPE_TEXT)
1564  {
1565  if (mutt_str_strcasecmp("plain", b->subtype) == 0)
1566  {
1567  /* avoid copying this part twice since removing the transfer-encoding is
1568  * the only operation needed. */
1569  if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_is_application_pgp(b))
1570  {
1571  encrypted_handler = crypt_pgp_application_handler;
1572  handler = encrypted_handler;
1573  }
1574  else if (C_ReflowText &&
1575  (mutt_str_strcasecmp("flowed",
1576  mutt_param_get(&b->parameter, "format")) == 0))
1577  {
1578  handler = rfc3676_handler;
1579  }
1580  else
1581  {
1582  handler = text_plain_handler;
1583  }
1584  }
1585  else if (mutt_str_strcasecmp("enriched", b->subtype) == 0)
1586  handler = text_enriched_handler;
1587  else /* text body type without a handler */
1588  plaintext = false;
1589  }
1590  else if (b->type == TYPE_MESSAGE)
1591  {
1592  if (mutt_is_message_type(b->type, b->subtype))
1593  handler = message_handler;
1594  else if (mutt_str_strcasecmp("delivery-status", b->subtype) == 0)
1595  plaintext = true;
1596  else if (mutt_str_strcasecmp("external-body", b->subtype) == 0)
1597  handler = external_body_handler;
1598  }
1599  else if (b->type == TYPE_MULTIPART)
1600  {
1601  if ((mutt_str_strcmp("inline", C_ShowMultipartAlternative) != 0) &&
1602  (mutt_str_strcasecmp("alternative", b->subtype) == 0))
1603  {
1604  handler = alternative_handler;
1605  }
1606  else if ((mutt_str_strcmp("inline", C_ShowMultipartAlternative) != 0) &&
1607  (mutt_str_strcasecmp("multilingual", b->subtype) == 0))
1608  {
1609  handler = multilingual_handler;
1610  }
1611  else if ((WithCrypto != 0) && (mutt_str_strcasecmp("signed", b->subtype) == 0))
1612  {
1613  if (!mutt_param_get(&b->parameter, "protocol"))
1614  mutt_error(_("Error: multipart/signed has no protocol"));
1615  else if (s->flags & MUTT_VERIFY)
1616  handler = mutt_signed_handler;
1617  }
1619  {
1620  encrypted_handler = valid_pgp_encrypted_handler;
1621  handler = encrypted_handler;
1622  }
1624  {
1625  encrypted_handler = malformed_pgp_encrypted_handler;
1626  handler = encrypted_handler;
1627  }
1628 
1629  if (!handler)
1630  handler = multipart_handler;
1631 
1632  if ((b->encoding != ENC_7BIT) && (b->encoding != ENC_8BIT) && (b->encoding != ENC_BINARY))
1633  {
1634  mutt_debug(LL_DEBUG1, "Bad encoding type %d for multipart entity, assuming 7 bit\n",
1635  b->encoding);
1636  b->encoding = ENC_7BIT;
1637  }
1638  }
1639  else if ((WithCrypto != 0) && (b->type == TYPE_APPLICATION))
1640  {
1641  if (OptDontHandlePgpKeys && (mutt_str_strcasecmp("pgp-keys", b->subtype) == 0))
1642  {
1643  /* pass raw part through for key extraction */
1644  plaintext = true;
1645  }
1646  else if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_is_application_pgp(b))
1647  {
1648  encrypted_handler = crypt_pgp_application_handler;
1649  handler = encrypted_handler;
1650  }
1651  else if (((WithCrypto & APPLICATION_SMIME) != 0) && mutt_is_application_smime(b))
1652  {
1653  encrypted_handler = crypt_smime_application_handler;
1654  handler = encrypted_handler;
1655  }
1656  }
1657 
1658  /* only respect disposition == attachment if we're not
1659  * displaying from the attachment menu (i.e. pager) */
1660  if ((!C_HonorDisposition || ((b->disposition != DISP_ATTACH) || OptViewAttach)) &&
1661  (plaintext || handler))
1662  {
1663  /* Prevent encrypted attachments from being included in replies
1664  * unless $include_encrypted is set. */
1665  if ((s->flags & MUTT_REPLYING) && (s->flags & MUTT_FIRSTDONE) &&
1666  encrypted_handler && !C_IncludeEncrypted)
1667  {
1668  goto cleanup;
1669  }
1670 
1671  rc = run_decode_and_handler(b, s, handler, plaintext);
1672  }
1673  /* print hint to use attachment menu for disposition == attachment
1674  * if we're not already being called from there */
1675  else if ((s->flags & MUTT_DISPLAY) || ((b->disposition == DISP_ATTACH) && !OptViewAttach &&
1676  C_HonorDisposition && (plaintext || handler)))
1677  {
1678  const char *str = NULL;
1679  char keystroke[128];
1680  keystroke[0] = '\0';
1681 
1682  if (!OptViewAttach)
1683  {
1684  if (km_expand_key(keystroke, sizeof(keystroke),
1685  km_find_func(MENU_PAGER, OP_VIEW_ATTACHMENTS)))
1686  {
1688  {
1689  /* L10N: Caution: Arguments %1$s and %2$s are also defined but should
1690  not be used in this translation!
1691  %3$s expands to a keystroke/key binding, e.g. 'v'. */
1692  str = _(
1693  "[-- This is an attachment (use '%3$s' to view this part) --]\n");
1694  }
1695  else
1696  {
1697  /* L10N: %s/%s is a MIME type, e.g. "text/plain".
1698  The last %s expands to a keystroke/key binding, e.g. 'v'. */
1699  str =
1700  _("[-- %s/%s is unsupported (use '%s' to view this part) --]\n");
1701  }
1702  }
1703  else
1704  {
1706  {
1707  str = _("[-- This is an attachment (need 'view-attachments' bound to "
1708  "key) --]\n");
1709  }
1710  else
1711  {
1712  /* L10N: %s/%s is a MIME type, e.g. "text/plain". */
1713  str = _("[-- %s/%s is unsupported (need 'view-attachments' bound to "
1714  "key) --]\n");
1715  }
1716  }
1717  }
1718  else
1719  {
1721  str = _("[-- This is an attachment --]\n");
1722  else
1723  {
1724  /* L10N: %s/%s is a MIME type, e.g. "text/plain". */
1725  str = _("[-- %s/%s is unsupported --]\n");
1726  }
1727  }
1728  state_mark_attach(s);
1729  state_printf(s, str, TYPE(b), b->subtype, keystroke);
1730  }
1731 
1732 cleanup:
1733  s->flags = oflags | (s->flags & MUTT_FIRSTDONE);
1734  if (rc != 0)
1735  {
1736  mutt_debug(LL_DEBUG1, "Bailing on attachment of type %s/%s\n", TYPE(b),
1737  NONULL(b->subtype));
1738  }
1739 
1740  return rc;
1741 }
int state_printf(struct State *s, const char *fmt,...)
Write a formatted string to the State.
Definition: state.c:147
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
#define NONULL(x)
Definition: string2.h:37
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition: parse.c:1270
static bool is_autoview(struct Body *b)
Should email body be filtered by mailcap.
Definition: handler.c:483
static int alternative_handler(struct Body *a, struct State *s)
Handler for multipart alternative emails - Implements handler_t.
Definition: handler.c:925
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:36
int(* handler_t)(struct Body *b, struct State *s)
typedef handler_t - Manage a PGP or S/MIME encrypted MIME part
Definition: handler.c:86
int crypt_pgp_application_handler(struct Body *m, struct State *s)
Wrapper for CryptModuleSpecs::application_handler()
Definition: cryptglue.c:206
7-bit text
Definition: mime.h:49
int mutt_signed_handler(struct Body *a, struct State *s)
Verify a "multipart/signed" body - Implements handler_t.
Definition: crypt.c:1074
int mutt_is_valid_multipart_pgp_encrypted(struct Body *b)
Is this a valid multi-part encrypted message?
Definition: crypt.c:444
#define _(a)
Definition: message.h:28
int text_enriched_handler(struct Body *a, struct State *s)
Handler for enriched text - Implements handler_t.
Definition: enriched.c:460
8-bit text
Definition: mime.h:50
struct Keymap * km_find_func(int menu, int func)
Find a function&#39;s mapping in a Menu.
Definition: keymap.c:798
int crypt_smime_application_handler(struct Body *m, struct State *s)
Wrapper for CryptModuleSpecs::application_handler()
Definition: cryptglue.c:387
unsigned int disposition
content-disposition
Definition: body.h:67
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
Pager pager (email viewer)
Definition: keymap.h:77
static int malformed_pgp_encrypted_handler(struct Body *b, struct State *s)
Handler for invalid pgp-encrypted emails - Implements handler_t.
Definition: handler.c:1451
Content is attached.
Definition: mime.h:63
WHERE bool OptDontHandlePgpKeys
(pseudo) used to extract PGP keys
Definition: options.h:33
unsigned int encoding
content-transfer-encoding
Definition: body.h:66
static int message_handler(struct Body *a, struct State *s)
Handler for message/rfc822 body parts - Implements handler_t.
Definition: handler.c:703
bool C_ReflowText
Config: Reformat paragraphs of &#39;format=flowed&#39; text.
Definition: handler.c:69
char * subtype
content-type subtype
Definition: body.h:37
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:527
int km_expand_key(char *s, size_t len, struct Keymap *map)
Get the key string bound to a Keymap.
Definition: keymap.c:770
#define MUTT_VERIFY
Perform signature verification.
Definition: state.h:33
Type: &#39;text/*&#39;.
Definition: mime.h:38
static int valid_pgp_encrypted_handler(struct Body *b, struct State *s)
Handler for valid pgp-encrypted emails - Implements handler_t.
Definition: handler.c:1422
static int run_decode_and_handler(struct Body *b, struct State *s, handler_t handler, bool plaintext)
Run an appropriate decoder for an email.
Definition: handler.c:1286
SecurityFlags mutt_is_malformed_multipart_pgp_encrypted(struct Body *b)
Check for malformed layout.
Definition: crypt.c:482
static int multilingual_handler(struct Body *a, struct State *s)
Handler for multi-lingual emails - Implements handler_t.
Definition: handler.c:1107
bool C_IncludeEncrypted
Config: Whether to include encrypted content when replying.
Definition: handler.c:66
SecurityFlags mutt_is_application_smime(struct Body *m)
Does the message use S/MIME?
Definition: crypt.c:586
void state_mark_attach(struct State *s)
Write a unique marker around content.
Definition: state.c:41
bool C_HonorDisposition
Config: Don&#39;t display MIME parts inline if they have a disposition of &#39;attachment&#39;.
Definition: handler.c:64
unsigned int type
content-type primary type
Definition: body.h:65
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:130
Type: &#39;message/*&#39;.
Definition: mime.h:35
#define TYPE(body)
Definition: mime.h:83
char * mutt_param_get(const struct ParameterList *p, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
Log at debug level 1.
Definition: logging.h:56
static int autoview_handler(struct Body *a, struct State *s)
Handler for autoviewable attachments - Implements handler_t.
Definition: handler.c:528
#define mutt_error(...)
Definition: logging.h:84
Binary.
Definition: mime.h:53
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:628
char * C_ShowMultipartAlternative
Config: How to display &#39;multipart/alternative&#39; MIME parts.
Definition: handler.c:70
#define MUTT_REPLYING
Are we replying?
Definition: state.h:38
static int multipart_handler(struct Body *a, struct State *s)
Handler for multipart emails - Implements handler_t.
Definition: handler.c:1205
WHERE bool OptViewAttach
(pseudo) signals that we are viewing attachments
Definition: options.h:52
#define MUTT_FIRSTDONE
The first attachment has been done.
Definition: state.h:39
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
int rfc3676_handler(struct Body *a, struct State *s)
Body handler implementing RFC3676 for format=flowed - Implements handler_t.
Definition: rfc3676.c:316
static int external_body_handler(struct Body *b, struct State *s)
Handler for external-body emails - Implements handler_t.
Definition: handler.c:756
static int text_plain_handler(struct Body *b, struct State *s)
Handler for plain text - Implements handler_t.
Definition: handler.c:677
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
#define WithCrypto
Definition: ncrypt.h:156
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
Type: &#39;application/*&#39;.
Definition: mime.h:33
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: ncrypt.h:131
bool mutt_can_decode ( struct Body a)

Will decoding the attachment produce any output.

Parameters
aBody of email to test
Return values
trueDecoding the attachment will produce output

Definition at line 1748 of file handler.c.

1749 {
1750  if (is_autoview(a))
1751  return true;
1752  else if (a->type == TYPE_TEXT)
1753  return true;
1754  else if (a->type == TYPE_MESSAGE)
1755  return true;
1756  else if (a->type == TYPE_MULTIPART)
1757  {
1758  if (WithCrypto)
1759  {
1760  if ((mutt_str_strcasecmp(a->subtype, "signed") == 0) ||
1761  (mutt_str_strcasecmp(a->subtype, "encrypted") == 0))
1762  {
1763  return true;
1764  }
1765  }
1766 
1767  for (struct Body *b = a->parts; b; b = b->next)
1768  {
1769  if (mutt_can_decode(b))
1770  return true;
1771  }
1772  }
1773  else if ((WithCrypto != 0) && (a->type == TYPE_APPLICATION))
1774  {
1775  if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_is_application_pgp(a))
1776  return true;
1778  return true;
1779  }
1780 
1781  return false;
1782 }
static bool is_autoview(struct Body *b)
Should email body be filtered by mailcap.
Definition: handler.c:483
struct Body * next
next attachment in the list
Definition: body.h:53
The body of an email.
Definition: body.h:34
char * subtype
content-type subtype
Definition: body.h:37
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:527
Type: &#39;text/*&#39;.
Definition: mime.h:38
bool mutt_can_decode(struct Body *a)
Will decoding the attachment produce any output.
Definition: handler.c:1748
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
SecurityFlags mutt_is_application_smime(struct Body *m)
Does the message use S/MIME?
Definition: crypt.c:586
unsigned int type
content-type primary type
Definition: body.h:65
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:130
Type: &#39;message/*&#39;.
Definition: mime.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:628
#define WithCrypto
Definition: ncrypt.h:156
Type: &#39;application/*&#39;.
Definition: mime.h:33
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: ncrypt.h:131
void mutt_decode_attachment ( struct Body b,
struct State s 
)

Decode an email's attachment.

Parameters
bBody of the email
sState of text being processed

Definition at line 1789 of file handler.c.

1790 {
1791  int istext = mutt_is_text_part(b);
1792  iconv_t cd = (iconv_t)(-1);
1793 
1794  if (istext && s->flags & MUTT_CHARCONV)
1795  {
1796  char *charset = mutt_param_get(&b->parameter, "charset");
1797  if (!charset && C_AssumedCharset)
1798  charset = mutt_ch_get_default_charset();
1799  if (charset && C_Charset)
1801  }
1802  else if (istext && b->charset)
1804 
1805  fseeko(s->fp_in, b->offset, SEEK_SET);
1806  switch (b->encoding)
1807  {
1808  case ENC_QUOTED_PRINTABLE:
1809  decode_quoted(s, b->length,
1810  istext || (((WithCrypto & APPLICATION_PGP) != 0) &&
1812  cd);
1813  break;
1814  case ENC_BASE64:
1815  mutt_decode_base64(s, b->length,
1816  istext || (((WithCrypto & APPLICATION_PGP) != 0) &&
1818  cd);
1819  break;
1820  case ENC_UUENCODED:
1821  decode_uuencoded(s, b->length,
1822  istext || (((WithCrypto & APPLICATION_PGP) != 0) &&
1824  cd);
1825  break;
1826  default:
1827  decode_xbit(s, b->length,
1828  istext || (((WithCrypto & APPLICATION_PGP) != 0) &&
1830  cd);
1831  break;
1832  }
1833 
1834  if (cd != (iconv_t)(-1))
1835  iconv_close(cd);
1836 }
char * C_AssumedCharset
Config: If a message is missing a character set, assume this character set.
Definition: charset.c:53
static void decode_xbit(struct State *s, long len, bool istext, iconv_t cd)
Decode xbit-encoded text.
Definition: handler.c:170
static void decode_uuencoded(struct State *s, long len, bool istext, iconv_t cd)
Decode uuencoded text.
Definition: handler.c:371
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:36
static void decode_quoted(struct State *s, long len, bool istext, iconv_t cd)
Decode an attachment encoded with quoted-printable.
Definition: handler.c:307
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
FILE * fp_in
File to read from.
Definition: state.h:46
void mutt_decode_base64(struct State *s, size_t len, bool istext, iconv_t cd)
Decode base64-encoded text.
Definition: handler.c:1480
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
unsigned int encoding
content-transfer-encoding
Definition: body.h:66
Base-64 encoded text.
Definition: mime.h:52
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:527
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
iconv_t mutt_ch_iconv_open(const char *tocode, const char *fromcode, int flags)
Set up iconv for conversions.
Definition: charset.c:535
char * charset
Send mode: charset of attached file as stored on disk.
Definition: body.h:49
bool mutt_is_text_part(struct Body *b)
Is this part of an email in plain text?
Definition: muttlib.c:436
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:130
char * mutt_param_get(const struct ParameterList *p, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
Quoted-printable text.
Definition: mime.h:51
char * mutt_ch_get_default_charset(void)
Get the default character set.
Definition: charset.c:404
char * C_Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:54
#define MUTT_ICONV_HOOK_FROM
apply charset-hooks to fromcode
Definition: charset.h:81
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
#define WithCrypto
Definition: ncrypt.h:156
UUEncoded text.
Definition: mime.h:54

Variable Documentation

bool C_HonorDisposition

Config: Don't display MIME parts inline if they have a disposition of 'attachment'.

Definition at line 64 of file handler.c.

bool C_ImplicitAutoview

Config: Display MIME attachments inline if a 'copiousoutput' mailcap entry exists.

Definition at line 65 of file handler.c.

bool C_IncludeEncrypted

Config: Whether to include encrypted content when replying.

Definition at line 66 of file handler.c.

bool C_IncludeOnlyfirst

Config: Only include the first attachment when replying.

Definition at line 67 of file handler.c.

struct Slist* C_PreferredLanguages

Config: Preferred languages for multilingual MIME.

Definition at line 68 of file handler.c.

bool C_ReflowText

Config: Reformat paragraphs of 'format=flowed' text.

Definition at line 69 of file handler.c.

char* C_ShowMultipartAlternative

Config: How to display 'multipart/alternative' MIME parts.

Definition at line 70 of file handler.c.