NeoMutt  2019-11-11
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 "config/lib.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 "mailcap.h"
#include "mutt_attach.h"
#include "mutt_logging.h"
#include "muttlib.h"
#include "ncrypt/ncrypt.h"
#include "opcodes.h"
#include "options.h"
#include "rfc3676.h"
#include "state.h"
#include <libintl.h>
+ Include dependency graph for handler.c:

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

◆ BUFI_SIZE

#define BUFI_SIZE   1000

Definition at line 73 of file handler.c.

◆ BUFO_SIZE

#define BUFO_SIZE   2000

Definition at line 74 of file handler.c.

◆ TXT_HTML

#define TXT_HTML   1

Definition at line 76 of file handler.c.

◆ TXT_PLAIN

#define TXT_PLAIN   2

Definition at line 77 of file handler.c.

◆ TXT_ENRICHED

#define TXT_ENRICHED   3

Definition at line 78 of file handler.c.

Typedef Documentation

◆ handler_t

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 87 of file handler.c.

Function Documentation

◆ print_part_line()

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 95 of file handler.c.

96 {
97  char length[5];
98  mutt_str_pretty_size(length, sizeof(length), b->length);
100  char *charset = mutt_param_get(&b->parameter, "charset");
101  if (n == 0)
102  {
103  state_printf(s, _("[-- Type: %s/%s%s%s, Encoding: %s, Size: %s --]\n"),
104  TYPE(b), b->subtype, charset ? "; charset=" : "",
105  charset ? charset : "", ENCODING(b->encoding), length);
106  }
107  else
108  {
109  state_printf(s, _("[-- Alternative Type #%d: %s/%s%s%s, Encoding: %s, Size: %s --]\n"),
110  n, TYPE(b), b->subtype, charset ? "; charset=" : "",
111  charset ? charset : "", ENCODING(b->encoding), length);
112  }
113 }
int state_printf(struct State *s, const char *fmt,...)
Write a formatted string to the State.
Definition: state.c:153
#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 mutt_str_pretty_size(char *buf, size_t buflen, size_t num)
Display an abbreviated size, like 3.4K.
Definition: muttlib.c:1779
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 *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ convert_to_state()

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 122 of file handler.c.

123 {
124  char bufo[BUFO_SIZE];
125  const char *ib = NULL;
126  char *ob = NULL;
127  size_t ibl, obl;
128 
129  if (!bufi)
130  {
131  if (cd != (iconv_t)(-1))
132  {
133  ob = bufo;
134  obl = sizeof(bufo);
135  iconv(cd, NULL, NULL, &ob, &obl);
136  if (ob != bufo)
137  state_prefix_put(s, bufo, ob - bufo);
138  }
139  return;
140  }
141 
142  if (cd == (iconv_t)(-1))
143  {
144  state_prefix_put(s, bufi, *l);
145  *l = 0;
146  return;
147  }
148 
149  ib = bufi;
150  ibl = *l;
151  while (true)
152  {
153  ob = bufo;
154  obl = sizeof(bufo);
155  mutt_ch_iconv(cd, &ib, &ibl, &ob, &obl, 0, "?", NULL);
156  if (ob == bufo)
157  break;
158  state_prefix_put(s, bufo, ob - bufo);
159  }
160  memmove(bufi, ib, ibl);
161  *l = ibl;
162 }
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:612
void state_prefix_put(struct State *s, const char *buf, size_t buflen)
Write a prefixed fixed-string to the State.
Definition: state.c:171
#define BUFO_SIZE
Definition: handler.c:74
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ decode_xbit()

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 171 of file handler.c.

172 {
173  if (!istext)
174  {
175  mutt_file_copy_bytes(s->fp_in, s->fp_out, len);
176  return;
177  }
178 
179  state_set_prefix(s);
180 
181  int c;
182  char bufi[BUFI_SIZE];
183  size_t l = 0;
184  while (((c = fgetc(s->fp_in)) != EOF) && len--)
185  {
186  if ((c == '\r') && len)
187  {
188  const int ch = fgetc(s->fp_in);
189  if (ch == '\n')
190  {
191  c = ch;
192  len--;
193  }
194  else
195  ungetc(ch, s->fp_in);
196  }
197 
198  bufi[l++] = c;
199  if (l == sizeof(bufi))
200  convert_to_state(cd, bufi, &l, s);
201  }
202 
203  convert_to_state(cd, bufi, &l, s);
204  convert_to_state(cd, 0, 0, s);
205 
207 }
#define state_reset_prefix(state)
Definition: state.h:54
int ch
raw key pressed
Definition: keymap.h:62
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:73
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:240
#define state_set_prefix(state)
Definition: state.h:53
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:122
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ qp_decode_triple()

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 216 of file handler.c.

217 {
218  /* soft line break */
219  if ((s[0] == '=') && (s[1] == '\0'))
220  return 1;
221 
222  /* quoted-printable triple */
223  if ((s[0] == '=') && isxdigit((unsigned char) s[1]) && isxdigit((unsigned char) s[2]))
224  {
225  *d = (hexval(s[1]) << 4) | hexval(s[2]);
226  return 0;
227  }
228 
229  /* something else */
230  return -1;
231 }
#define hexval(ch)
Definition: mime.h:75
+ Here is the caller graph for this function:

◆ qp_decode_line()

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 240 of file handler.c.

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

◆ decode_quoted()

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 308 of file handler.c.

309 {
310  char line[256];
311  char decline[512];
312  size_t l = 0;
313  size_t l3;
314 
315  if (istext)
316  state_set_prefix(s);
317 
318  while (len > 0)
319  {
320  /* It's ok to use a fixed size buffer for input, even if the line turns
321  * out to be longer than this. Just process the line in chunks. This
322  * really shouldn't happen according the MIME spec, since Q-P encoded
323  * lines are at most 76 characters, but we should be liberal about what
324  * we accept. */
325  if (!fgets(line, MIN((ssize_t) sizeof(line), len + 1), s->fp_in))
326  break;
327 
328  size_t linelen = strlen(line);
329  len -= linelen;
330 
331  /* inspect the last character we read so we can tell if we got the
332  * entire line. */
333  const int last = (linelen != 0) ? line[linelen - 1] : 0;
334 
335  /* chop trailing whitespace if we got the full line */
336  if (last == '\n')
337  {
338  while ((linelen > 0) && IS_SPACE(line[linelen - 1]))
339  linelen--;
340  line[linelen] = '\0';
341  }
342 
343  /* decode and do character set conversion */
344  qp_decode_line(decline + l, line, &l3, last);
345  l += l3;
346  convert_to_state(cd, decline, &l, s);
347  }
348 
349  convert_to_state(cd, 0, 0, s);
351 }
#define MIN(a, b)
Definition: memory.h:31
#define state_reset_prefix(state)
Definition: state.h:54
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:240
const char * line
Definition: common.c:36
#define IS_SPACE(ch)
Definition: string2.h:38
#define state_set_prefix(state)
Definition: state.h:53
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:122
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ decode_byte()

static unsigned char decode_byte ( char  ch)
static

Decode a uuencoded byte.

Parameters
chCharacter to decode
Return values
numDecoded value

Definition at line 358 of file handler.c.

359 {
360  if ((ch < 32) || (ch > 95))
361  return 0;
362  return ch - 32;
363 }
int ch
raw key pressed
Definition: keymap.h:62
+ Here is the caller graph for this function:

◆ decode_uuencoded()

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 372 of file handler.c.

373 {
374  char tmps[128];
375  char *pt = NULL;
376  char bufi[BUFI_SIZE];
377  size_t k = 0;
378 
379  if (istext)
380  state_set_prefix(s);
381 
382  while (len > 0)
383  {
384  if (!fgets(tmps, sizeof(tmps), s->fp_in))
385  return;
386  len -= mutt_str_strlen(tmps);
387  if (mutt_str_startswith(tmps, "begin ", CASE_MATCH))
388  break;
389  }
390  while (len > 0)
391  {
392  if (!fgets(tmps, sizeof(tmps), s->fp_in))
393  return;
394  len -= mutt_str_strlen(tmps);
395  if (mutt_str_startswith(tmps, "end", CASE_MATCH))
396  break;
397  pt = tmps;
398  const unsigned char linelen = decode_byte(*pt);
399  pt++;
400  for (unsigned char c = 0; c < linelen;)
401  {
402  for (char l = 2; l <= 6; l += 2)
403  {
404  char out = decode_byte(*pt) << l;
405  pt++;
406  out |= (decode_byte(*pt) >> (6 - l));
407  bufi[k++] = out;
408  c++;
409  if (c == linelen)
410  break;
411  }
412  convert_to_state(cd, bufi, &k, s);
413  pt++;
414  }
415  }
416 
417  convert_to_state(cd, bufi, &k, s);
418  convert_to_state(cd, 0, 0, s);
419 
421 }
#define state_reset_prefix(state)
Definition: state.h:54
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:358
FILE * fp_in
File to read from.
Definition: state.h:46
#define BUFI_SIZE
Definition: handler.c:73
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:53
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:122
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ is_mmnoask()

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 433 of file handler.c.

434 {
435  const char *val = mutt_str_getenv("MM_NOASK");
436  if (!val)
437  return false;
438 
439  char *p = NULL;
440  char tmp[1024];
441  char *q = NULL;
442 
443  if (mutt_str_strcmp(val, "1") == 0)
444  return true;
445 
446  mutt_str_strfcpy(tmp, val, sizeof(tmp));
447  p = tmp;
448 
449  while ((p = strtok(p, ",")))
450  {
451  q = strrchr(p, '/');
452  if (q)
453  {
454  if (q[1] == '*')
455  {
456  if (mutt_str_strncasecmp(buf, p, q - p) == 0)
457  return true;
458  }
459  else
460  {
461  if (mutt_str_strcasecmp(buf, p) == 0)
462  return true;
463  }
464  }
465  else
466  {
467  const size_t plen = mutt_str_startswith(buf, p, CASE_IGNORE);
468  if ((plen != 0) && (buf[plen] == '/'))
469  return true;
470  }
471 
472  p = NULL;
473  }
474 
475  return false;
476 }
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:1048
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
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ is_autoview()

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 484 of file handler.c.

485 {
486  char type[256];
487  bool is_av = false;
488 
489  snprintf(type, sizeof(type), "%s/%s", TYPE(b), b->subtype);
490 
491  if (C_ImplicitAutoview)
492  {
493  /* $implicit_autoview is essentially the same as "auto_view *" */
494  is_av = true;
495  }
496  else
497  {
498  /* determine if this type is on the user's auto_view list */
499  mutt_check_lookup_list(b, type, sizeof(type));
500  struct ListNode *np = NULL;
501  STAILQ_FOREACH(np, &AutoViewList, entries)
502  {
503  int i = mutt_str_strlen(np->data) - 1;
504  if (((i > 0) && (np->data[i - 1] == '/') && (np->data[i] == '*') &&
505  (mutt_str_strncasecmp(type, np->data, i) == 0)) ||
506  (mutt_str_strcasecmp(type, np->data) == 0))
507  {
508  is_av = true;
509  break;
510  }
511  }
512 
513  if (is_mmnoask(type))
514  is_av = true;
515  }
516 
517  /* determine if there is a mailcap entry suitable for auto_view
518  *
519  * @warning type is altered by this call as a result of 'mime_lookup' support */
520  if (is_av)
521  return mailcap_lookup(b, type, sizeof(type), NULL, MUTT_MC_AUTOVIEW);
522 
523  return false;
524 }
Mailcap autoview field.
Definition: mailcap.h:61
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:666
bool mailcap_lookup(struct Body *a, char *type, size_t typelen, struct MailcapEntry *entry, enum MailcapLookup opt)
Find given type in the list of mailcap files.
Definition: mailcap.c:467
static bool is_mmnoask(const char *buf)
Metamail compatibility: should the attachment be autoviewed?
Definition: handler.c:433
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
String.
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:330
bool C_ImplicitAutoview
Config: Display MIME attachments inline if a &#39;copiousoutput&#39; mailcap entry exists.
Definition: handler.c:66
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
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ autoview_handler()

static int autoview_handler ( struct Body a,
struct State s 
)
static

Handler for autoviewable attachments - Implements handler_t.

Definition at line 529 of file handler.c.

530 {
531  struct MailcapEntry *entry = mailcap_entry_new();
532  char buf[1024];
533  char type[256];
534  struct Buffer *cmd = mutt_buffer_pool_get();
535  struct Buffer *tempfile = mutt_buffer_pool_get();
536  char *fname = NULL;
537  FILE *fp_in = NULL;
538  FILE *fp_out = NULL;
539  FILE *fp_err = NULL;
540  pid_t pid;
541  int rc = 0;
542 
543  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
544  mailcap_lookup(a, type, sizeof(type), entry, MUTT_MC_AUTOVIEW);
545 
546  fname = mutt_str_strdup(a->filename);
547  mutt_file_sanitize_filename(fname, true);
548  mailcap_expand_filename(entry->nametemplate, fname, tempfile);
549  FREE(&fname);
550 
551  if (entry->command)
552  {
553  mutt_buffer_strcpy(cmd, entry->command);
554 
555  /* mailcap_expand_command returns 0 if the file is required */
556  bool piped = mailcap_expand_command(a, mutt_b2s(tempfile), type, cmd);
557 
558  if (s->flags & MUTT_DISPLAY)
559  {
561  state_printf(s, _("[-- Autoview using %s --]\n"), mutt_b2s(cmd));
562  mutt_message(_("Invoking autoview command: %s"), mutt_b2s(cmd));
563  }
564 
565  fp_in = mutt_file_fopen(mutt_b2s(tempfile), "w+");
566  if (!fp_in)
567  {
568  mutt_perror("fopen");
569  mailcap_entry_free(&entry);
570  rc = -1;
571  goto cleanup;
572  }
573 
574  mutt_file_copy_bytes(s->fp_in, fp_in, a->length);
575 
576  if (piped)
577  {
578  unlink(mutt_b2s(tempfile));
579  fflush(fp_in);
580  rewind(fp_in);
581  pid = mutt_create_filter_fd(mutt_b2s(cmd), NULL, &fp_out, &fp_err,
582  fileno(fp_in), -1, -1);
583  }
584  else
585  {
586  mutt_file_fclose(&fp_in);
587  pid = mutt_create_filter(mutt_b2s(cmd), NULL, &fp_out, &fp_err);
588  }
589 
590  if (pid < 0)
591  {
592  mutt_perror(_("Can't create filter"));
593  if (s->flags & MUTT_DISPLAY)
594  {
596  state_printf(s, _("[-- Can't run %s. --]\n"), mutt_b2s(cmd));
597  }
598  rc = -1;
599  goto bail;
600  }
601 
602  if (s->prefix)
603  {
604  while (fgets(buf, sizeof(buf), fp_out))
605  {
606  state_puts(s, s->prefix);
607  state_puts(s, buf);
608  }
609  /* check for data on stderr */
610  if (fgets(buf, sizeof(buf), fp_err))
611  {
612  if (s->flags & MUTT_DISPLAY)
613  {
615  state_printf(s, _("[-- Autoview stderr of %s --]\n"), mutt_b2s(cmd));
616  }
617 
618  state_puts(s, s->prefix);
619  state_puts(s, buf);
620  while (fgets(buf, sizeof(buf), fp_err))
621  {
622  state_puts(s, s->prefix);
623  state_puts(s, buf);
624  }
625  }
626  }
627  else
628  {
629  mutt_file_copy_stream(fp_out, s->fp_out);
630  /* Check for stderr messages */
631  if (fgets(buf, sizeof(buf), fp_err))
632  {
633  if (s->flags & MUTT_DISPLAY)
634  {
636  state_printf(s, _("[-- Autoview stderr of %s --]\n"), mutt_b2s(cmd));
637  }
638 
639  state_puts(s, buf);
640  mutt_file_copy_stream(fp_err, s->fp_out);
641  }
642  }
643 
644  bail:
645  mutt_file_fclose(&fp_out);
646  mutt_file_fclose(&fp_err);
647 
648  mutt_wait_filter(pid);
649  if (piped)
650  mutt_file_fclose(&fp_in);
651  else
652  mutt_file_unlink(mutt_b2s(tempfile));
653 
654  if (s->flags & MUTT_DISPLAY)
656  }
657 
658 cleanup:
659  mailcap_entry_free(&entry);
660 
662  mutt_buffer_pool_release(&tempfile);
663 
664  return rc;
665 }
pid_t mutt_create_filter(const char *s, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:210
A mailcap entry.
Definition: mailcap.h:37
int state_printf(struct State *s, const char *fmt,...)
Write a formatted string to the State.
Definition: state.c:153
struct MailcapEntry * mailcap_entry_new(void)
Allocate memory for a new rfc1524 entry.
Definition: mailcap.c:429
#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
#define state_puts(STATE, STR)
Definition: state.h:55
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:100
#define mutt_perror(...)
Definition: logging.h:85
Mailcap autoview field.
Definition: mailcap.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:111
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:194
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
FILE * fp_out
File to write to.
Definition: state.h:47
FILE * fp_in
File to read from.
Definition: state.h:46
bool mailcap_lookup(struct Body *a, char *type, size_t typelen, struct MailcapEntry *entry, enum MailcapLookup opt)
Find given type in the list of mailcap files.
Definition: mailcap.c:467
int mailcap_expand_command(struct Body *a, const char *filename, const char *type, struct Buffer *command)
Expand expandos in a command.
Definition: mailcap.c:70
void mailcap_expand_filename(const char *nametemplate, const char *oldfile, struct Buffer *newfile)
Expand a new filename from a template or existing filename.
Definition: mailcap.c:522
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:152
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:115
char * command
Definition: mailcap.h:39
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:615
#define mutt_b2s(buf)
Definition: buffer.h:41
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
void mailcap_entry_free(struct MailcapEntry **ptr)
Deallocate an struct MailcapEntry.
Definition: mailcap.c:438
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:65
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:240
void state_mark_attach(struct State *s)
Write a unique marker around content.
Definition: state.c:41
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
char * nametemplate
Definition: mailcap.h:45
#define TYPE(body)
Definition: mime.h:83
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:270
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define FREE(x)
Definition: memory.h:40
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:585
int mutt_wait_filter(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:221
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ text_plain_handler()

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 675 of file handler.c.

676 {
677  char *buf = NULL;
678  size_t sz = 0;
679 
680  while ((buf = mutt_file_read_line(buf, &sz, s->fp_in, NULL, 0)))
681  {
682  if ((mutt_str_strcmp(buf, "-- ") != 0) && C_TextFlowed)
683  {
684  size_t len = mutt_str_strlen(buf);
685  while ((len > 0) && (buf[len - 1] == ' '))
686  buf[--len] = '\0';
687  }
688  if (s->prefix)
689  state_puts(s, s->prefix);
690  state_puts(s, buf);
691  state_putc(s, '\n');
692  }
693 
694  FREE(&buf);
695  return 0;
696 }
#define state_puts(STATE, STR)
Definition: state.h:55
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:664
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:266
#define FREE(x)
Definition: memory.h:40
#define state_putc(STATE, STR)
Definition: state.h:56
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ message_handler()

static int message_handler ( struct Body a,
struct State s 
)
static

Handler for message/rfc822 body parts - Implements handler_t.

Definition at line 701 of file handler.c.

702 {
703  struct stat st;
704  struct Body *b = NULL;
705  LOFF_T off_start;
706  int rc = 0;
707 
708  off_start = ftello(s->fp_in);
709  if (off_start < 0)
710  return -1;
711 
712  if ((a->encoding == ENC_BASE64) || (a->encoding == ENC_QUOTED_PRINTABLE) ||
713  (a->encoding == ENC_UUENCODED))
714  {
715  fstat(fileno(s->fp_in), &st);
716  b = mutt_body_new();
717  b->length = (LOFF_T) st.st_size;
719  }
720  else
721  b = a;
722 
723  if (b->parts)
724  {
725  CopyHeaderFlags chflags = CH_DECODE | CH_FROM;
726  if ((s->flags & MUTT_WEED) || ((s->flags & (MUTT_DISPLAY | MUTT_PRINTING)) && C_Weed))
727  chflags |= CH_WEED | CH_REORDER;
728  if (s->prefix)
729  chflags |= CH_PREFIX;
730  if (s->flags & MUTT_DISPLAY)
731  chflags |= CH_DISPLAY;
732 
733  mutt_copy_hdr(s->fp_in, s->fp_out, off_start, b->parts->offset, chflags, s->prefix, 0);
734 
735  if (s->prefix)
736  state_puts(s, s->prefix);
737  state_putc(s, '\n');
738 
739  rc = mutt_body_handler(b->parts, s);
740  }
741 
742  if ((a->encoding == ENC_BASE64) || (a->encoding == ENC_QUOTED_PRINTABLE) ||
743  (a->encoding == ENC_UUENCODED))
744  {
745  mutt_body_free(&b);
746  }
747 
748  return rc;
749 }
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
#define state_puts(STATE, STR)
Definition: state.h:55
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:1562
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
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition: copy.h:49
int mutt_copy_hdr(FILE *fp_in, FILE *fp_out, LOFF_T off_start, LOFF_T off_end, CopyHeaderFlags chflags, const char *prefix, int wraplen)
Copy header from one file to another.
Definition: copy.c:77
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:1551
#define state_putc(STATE, STR)
Definition: state.h:56
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
#define CH_PREFIX
Quote header using C_IndentString string?
Definition: copy.h:56
UUEncoded text.
Definition: mime.h:54
bool C_Weed
Config: Filter headers when displaying/forwarding/printing/replying.
Definition: email_globals.c:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ external_body_handler()

static int external_body_handler ( struct Body b,
struct State s 
)
static

Handler for external-body emails - Implements handler_t.

Definition at line 754 of file handler.c.

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

◆ alternative_handler()

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(s, '\n');
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(s, _("[-- Error: Could not display any parts of "
1092  "Multipart/Alternative --]\n"));
1093  rc = -1;
1094  }
1095 
1096  if (mustfree)
1097  mutt_body_free(&a);
1098 
1099  return rc;
1100 }
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
#define state_puts(STATE, STR)
Definition: state.h:55
static bool is_autoview(struct Body *b)
Should email body be filtered by mailcap.
Definition: handler.c:484
#define TXT_HTML
Definition: handler.c:76
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:1460
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:77
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:78
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:1756
static void print_part_line(struct State *s, struct Body *b, int n)
Print a separator for the Mime part.
Definition: handler.c:95
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:240
#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
char * data
String.
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 * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
char * C_ShowMultipartAlternative
Config: How to display &#39;multipart/alternative&#39; MIME parts.
Definition: handler.c:71
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1551
#define state_putc(STATE, STR)
Definition: state.h:56
long hdr_offset
Offset in stream where the headers begin.
Definition: body.h:42
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
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
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ multilingual_handler()

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 1106 of file handler.c.

1107 {
1108  struct Body *b = NULL;
1109  bool mustfree = false;
1110  int rc = 0;
1111 
1113  "RFC8255 >> entering in handler multilingual handler\n");
1114  if ((a->encoding == ENC_BASE64) || (a->encoding == ENC_QUOTED_PRINTABLE) ||
1115  (a->encoding == ENC_UUENCODED))
1116  {
1117  struct stat st;
1118  mustfree = true;
1119  fstat(fileno(s->fp_in), &st);
1120  b = mutt_body_new();
1121  b->length = (long) st.st_size;
1123  s->fp_in, mutt_param_get(&a->parameter, "boundary"), (long) st.st_size,
1124  (mutt_str_strcasecmp("digest", a->subtype) == 0));
1125  }
1126  else
1127  b = a;
1128 
1129  a = b;
1130 
1131  if (a->parts)
1132  b = a->parts;
1133  else
1134  b = a;
1135 
1136  struct Body *choice = NULL;
1137  struct Body *first_part = NULL;
1138  struct Body *zxx_part = NULL;
1139  struct ListNode *np = NULL;
1140 
1142  {
1143  struct Buffer *langs = mutt_buffer_pool_get();
1144  cs_str_string_get(Config, "preferred_languages", langs);
1145  mutt_debug(LL_DEBUG2, "RFC8255 >> preferred_languages set in config to '%s'\n",
1146  mutt_b2s(langs));
1147  mutt_buffer_pool_release(&langs);
1148 
1149  STAILQ_FOREACH(np, &C_PreferredLanguages->head, entries)
1150  {
1151  while (b)
1152  {
1153  if (mutt_can_decode(b))
1154  {
1155  if (!first_part)
1156  first_part = b;
1157 
1158  if (b->language && (mutt_str_strcmp("zxx", b->language) == 0))
1159  zxx_part = b;
1160 
1161  mutt_debug(LL_DEBUG2, "RFC8255 >> comparing configuration preferred_language='%s' to mail part content-language='%s'\n",
1162  np->data, b->language);
1163  if (b->language && (mutt_str_strcmp(np->data, b->language) == 0))
1164  {
1165  mutt_debug(LL_DEBUG2, "RFC8255 >> preferred_language='%s' matches content-language='%s' >> part selected to be displayed\n",
1166  np->data, b->language);
1167  choice = b;
1168  break;
1169  }
1170  }
1171 
1172  b = b->next;
1173  }
1174 
1175  if (choice)
1176  break;
1177 
1178  if (a->parts)
1179  b = a->parts;
1180  else
1181  b = a;
1182  }
1183  }
1184 
1185  if (choice)
1186  mutt_body_handler(choice, s);
1187  else
1188  {
1189  if (zxx_part)
1190  mutt_body_handler(zxx_part, s);
1191  else
1192  mutt_body_handler(first_part, s);
1193  }
1194 
1195  if (mustfree)
1196  mutt_body_free(&a);
1197 
1198  return rc;
1199 }
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:100
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:111
String manipulation buffer.
Definition: buffer.h:33
WHERE struct ConfigSet * Config
Wrapper around the user&#39;s config settings.
Definition: globals.h:41
struct Body * mutt_parse_multipart(FILE *fp, const char *boundary, LOFF_T end_off, bool digest)
parse a multipart structure
Definition: parse.c:1460
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:698
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:41
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:1756
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 * data
String.
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 * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
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:1551
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
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:69
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
UUEncoded text.
Definition: mime.h:54
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ multipart_handler()

static int multipart_handler ( struct Body a,
struct State s 
)
static

Handler for multipart emails - Implements handler_t.

Definition at line 1204 of file handler.c.

1205 {
1206  struct Body *b = NULL, *p = NULL;
1207  struct stat st;
1208  int count;
1209  int rc = 0;
1210 
1211  if ((a->encoding == ENC_BASE64) || (a->encoding == ENC_QUOTED_PRINTABLE) ||
1212  (a->encoding == ENC_UUENCODED))
1213  {
1214  fstat(fileno(s->fp_in), &st);
1215  b = mutt_body_new();
1216  b->length = (long) st.st_size;
1218  s->fp_in, mutt_param_get(&a->parameter, "boundary"), (long) st.st_size,
1219  (mutt_str_strcasecmp("digest", a->subtype) == 0));
1220  }
1221  else
1222  b = a;
1223 
1224  for (p = b->parts, count = 1; p; p = p->next, count++)
1225  {
1226  if (s->flags & MUTT_DISPLAY)
1227  {
1228  state_mark_attach(s);
1229  if (p->description || p->filename || p->form_name)
1230  {
1231  /* L10N: %s is the attachment description, filename or form_name. */
1232  state_printf(s, _("[-- Attachment #%d: %s --]\n"), count,
1233  p->description ? p->description :
1234  p->filename ? p->filename : p->form_name);
1235  }
1236  else
1237  state_printf(s, _("[-- Attachment #%d --]\n"), count);
1238  print_part_line(s, p, 0);
1239  if (C_Weed)
1240  {
1241  state_putc(s, '\n');
1242  }
1243  else
1244  {
1245  fseeko(s->fp_in, p->hdr_offset, SEEK_SET);
1246  mutt_file_copy_bytes(s->fp_in, s->fp_out, p->offset - p->hdr_offset);
1247  }
1248  }
1249 
1250  rc = mutt_body_handler(p, s);
1251  state_putc(s, '\n');
1252 
1253  if (rc != 0)
1254  {
1255  mutt_error(_("One or more parts of this message could not be displayed"));
1256  mutt_debug(LL_DEBUG1, "Failed on attachment #%d, type %s/%s\n", count,
1257  TYPE(p), NONULL(p->subtype));
1258  }
1259 
1260  if ((s->flags & MUTT_REPLYING) && C_IncludeOnlyfirst && (s->flags & MUTT_FIRSTDONE))
1261  {
1262  break;
1263  }
1264  }
1265 
1266  if ((a->encoding == ENC_BASE64) || (a->encoding == ENC_QUOTED_PRINTABLE) ||
1267  (a->encoding == ENC_UUENCODED))
1268  {
1269  mutt_body_free(&b);
1270  }
1271 
1272  /* make failure of a single part non-fatal */
1273  if (rc < 0)
1274  rc = 1;
1275  return rc;
1276 }
int state_printf(struct State *s, const char *fmt,...)
Write a formatted string to the State.
Definition: state.c:153
#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:1460
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:95
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:240
void state_mark_attach(struct State *s)
Write a unique marker around content.
Definition: state.c:41
#define TYPE(body)
Definition: mime.h:83
Log at debug level 1.
Definition: logging.h:56
#define mutt_error(...)
Definition: logging.h:84
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 * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
#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:1551
#define MUTT_FIRSTDONE
The first attachment has been done.
Definition: state.h:39
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
#define state_putc(STATE, STR)
Definition: state.h:56
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
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:68
UUEncoded text.
Definition: mime.h:54
bool C_Weed
Config: Filter headers when displaying/forwarding/printing/replying.
Definition: email_globals.c:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ run_decode_and_handler()

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 1287 of file handler.c.

1289 {
1290  char *save_prefix = NULL;
1291  FILE *fp = NULL;
1292  size_t tmplength = 0;
1293  LOFF_T tmpoffset = 0;
1294  int decode = 0;
1295  int rc = 0;
1296 #ifndef USE_FMEMOPEN
1297  struct Buffer *tempfile = NULL;
1298 #endif
1299 
1300  fseeko(s->fp_in, b->offset, SEEK_SET);
1301 
1302 #ifdef USE_FMEMOPEN
1303  char *temp = NULL;
1304  size_t tempsize = 0;
1305 #endif
1306 
1307  /* see if we need to decode this part before processing it */
1308  if ((b->encoding == ENC_BASE64) || (b->encoding == ENC_QUOTED_PRINTABLE) ||
1309  (b->encoding == ENC_UUENCODED) || (plaintext || mutt_is_text_part(b)))
1310  /* text subtypes may require character set conversion even with 8bit encoding */
1311  {
1312  const int orig_type = b->type;
1313  if (!plaintext)
1314  {
1315  /* decode to a tempfile, saving the original destination */
1316  fp = s->fp_out;
1317 #ifdef USE_FMEMOPEN
1318  s->fp_out = open_memstream(&temp, &tempsize);
1319  if (!s->fp_out)
1320  {
1321  mutt_error(_("Unable to open 'memory stream'"));
1322  mutt_debug(LL_DEBUG1, "Can't open 'memory stream'\n");
1323  return -1;
1324  }
1325 #else
1326  tempfile = mutt_buffer_pool_get();
1327  mutt_buffer_mktemp(tempfile);
1328  s->fp_out = mutt_file_fopen(mutt_b2s(tempfile), "w");
1329  if (!s->fp_out)
1330  {
1331  mutt_error(_("Unable to open temporary file"));
1332  mutt_debug(LL_DEBUG1, "Can't open %s\n", mutt_b2s(tempfile));
1333  mutt_buffer_pool_release(&tempfile);
1334  return -1;
1335  }
1336 #endif
1337  /* decoding the attachment changes the size and offset, so save a copy
1338  * of the "real" values now, and restore them after processing */
1339  tmplength = b->length;
1340  tmpoffset = b->offset;
1341 
1342  /* if we are decoding binary bodies, we don't want to prefix each
1343  * line with the prefix or else the data will get corrupted. */
1344  save_prefix = s->prefix;
1345  s->prefix = NULL;
1346 
1347  decode = 1;
1348  }
1349  else
1350  b->type = TYPE_TEXT;
1351 
1352  mutt_decode_attachment(b, s);
1353 
1354  if (decode)
1355  {
1356  b->length = ftello(s->fp_out);
1357  b->offset = 0;
1358 #ifdef USE_FMEMOPEN
1359  /* When running under torify, mutt_file_fclose(&s->fp_out) does not seem to
1360  * update tempsize. On the other hand, fflush does. See
1361  * https://github.com/neomutt/neomutt/issues/440 */
1362  fflush(s->fp_out);
1363 #endif
1364  mutt_file_fclose(&s->fp_out);
1365 
1366  /* restore final destination and substitute the tempfile for input */
1367  s->fp_out = fp;
1368  fp = s->fp_in;
1369 #ifdef USE_FMEMOPEN
1370  if (tempsize)
1371  {
1372  s->fp_in = fmemopen(temp, tempsize, "r");
1373  }
1374  else
1375  { /* fmemopen can't handle zero-length buffers */
1376  s->fp_in = mutt_file_fopen("/dev/null", "r");
1377  }
1378  if (!s->fp_in)
1379  {
1380  mutt_perror(_("failed to re-open 'memory stream'"));
1381  return -1;
1382  }
1383 #else
1384  s->fp_in = fopen(mutt_b2s(tempfile), "r");
1385  unlink(mutt_b2s(tempfile));
1386  mutt_buffer_pool_release(&tempfile);
1387 #endif
1388  /* restore the prefix */
1389  s->prefix = save_prefix;
1390  }
1391 
1392  b->type = orig_type;
1393  }
1394 
1395  /* process the (decoded) body part */
1396  if (handler)
1397  {
1398  rc = handler(b, s);
1399  if (rc != 0)
1400  {
1401  mutt_debug(LL_DEBUG1, "Failed on attachment of type %s/%s\n", TYPE(b),
1402  NONULL(b->subtype));
1403  }
1404 
1405  if (decode)
1406  {
1407  b->length = tmplength;
1408  b->offset = tmpoffset;
1409 
1410  /* restore the original source stream */
1411  mutt_file_fclose(&s->fp_in);
1412 #ifdef USE_FMEMOPEN
1413  FREE(&temp);
1414 #endif
1415  s->fp_in = fp;
1416  }
1417  }
1418  s->flags |= MUTT_FIRSTDONE;
1419 
1420  return rc;
1421 }
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1797
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:79
#define NONULL(x)
Definition: string2.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:100
#define mutt_perror(...)
Definition: logging.h:85
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:111
String manipulation buffer.
Definition: buffer.h:33
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:152
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:41
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
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:453
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:585
UUEncoded text.
Definition: mime.h:54
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ valid_pgp_encrypted_handler()

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 1426 of file handler.c.

1427 {
1428  struct Body *octetstream = b->parts->next;
1429 
1430  /* clear out any mime headers before the handler, so they can't be spoofed. */
1432  mutt_env_free(&octetstream->mime_headers);
1433 
1434  int rc;
1435  /* Some clients improperly encode the octetstream part. */
1436  if (octetstream->encoding != ENC_7BIT)
1437  rc = run_decode_and_handler(octetstream, s, crypt_pgp_encrypted_handler, 0);
1438  else
1439  rc = crypt_pgp_encrypted_handler(octetstream, s);
1440  b->goodsig |= octetstream->goodsig;
1441 
1442  /* Relocate protected headers onto the multipart/encrypted part */
1443  if (!rc && octetstream->mime_headers)
1444  {
1445  b->mime_headers = octetstream->mime_headers;
1446  octetstream->mime_headers = NULL;
1447  }
1448 
1449  return rc;
1450 }
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:240
unsigned int encoding
content-transfer-encoding
Definition: body.h:66
bool goodsig
Good cryptographic signature.
Definition: body.h:75
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:96
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:1287
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ malformed_pgp_encrypted_handler()

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 1455 of file handler.c.

1456 {
1457  struct Body *octetstream = b->parts->next->next;
1458 
1459  /* clear out any mime headers before the handler, so they can't be spoofed. */
1461  mutt_env_free(&octetstream->mime_headers);
1462 
1463  /* exchange encodes the octet-stream, so re-run it through the decoder */
1464  int rc = run_decode_and_handler(octetstream, s, crypt_pgp_encrypted_handler, false);
1465  b->goodsig |= octetstream->goodsig;
1466 #ifdef USE_AUTOCRYPT
1467  b->is_autocrypt |= octetstream->is_autocrypt;
1468 #endif
1469 
1470  /* Relocate protected headers onto the multipart/encrypted part */
1471  if (!rc && octetstream->mime_headers)
1472  {
1473  b->mime_headers = octetstream->mime_headers;
1474  octetstream->mime_headers = NULL;
1475  }
1476 
1477  return rc;
1478 }
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:63
bool is_autocrypt
Flag autocrypt-decrypted messages for replying.
Definition: body.h:79
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:240
bool goodsig
Good cryptographic signature.
Definition: body.h:75
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:96
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:1287
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_decode_base64()

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 1487 of file handler.c.

1488 {
1489  char buf[5];
1490  int ch, i;
1491  char bufi[BUFI_SIZE];
1492  size_t l = 0;
1493 
1494  buf[4] = '\0';
1495 
1496  if (istext)
1497  state_set_prefix(s);
1498 
1499  while (len > 0)
1500  {
1501  for (i = 0; (i < 4) && (len > 0); len--)
1502  {
1503  ch = fgetc(s->fp_in);
1504  if (ch == EOF)
1505  break;
1506  if ((ch >= 0) && (ch < 128) && ((base64val(ch) != -1) || (ch == '=')))
1507  buf[i++] = ch;
1508  }
1509  if (i != 4)
1510  {
1511  /* "i" may be zero if there is trailing whitespace, which is not an error */
1512  if (i != 0)
1513  mutt_debug(LL_DEBUG2, "didn't get a multiple of 4 chars\n");
1514  break;
1515  }
1516 
1517  const int c1 = base64val(buf[0]);
1518  const int c2 = base64val(buf[1]);
1519  ch = (c1 << 2) | (c2 >> 4);
1520  bufi[l++] = ch;
1521 
1522  if (buf[2] == '=')
1523  break;
1524  const int c3 = base64val(buf[2]);
1525  ch = ((c2 & 0xf) << 4) | (c3 >> 2);
1526  bufi[l++] = ch;
1527 
1528  if (buf[3] == '=')
1529  break;
1530  const int c4 = base64val(buf[3]);
1531  ch = ((c3 & 0x3) << 6) | c4;
1532  bufi[l++] = ch;
1533 
1534  if ((l + 8) >= sizeof(bufi))
1535  convert_to_state(cd, bufi, &l, s);
1536  }
1537 
1538  convert_to_state(cd, bufi, &l, s);
1539  convert_to_state(cd, 0, 0, s);
1540 
1541  state_reset_prefix(s);
1542 }
#define state_reset_prefix(state)
Definition: state.h:54
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:73
#define state_set_prefix(state)
Definition: state.h:53
#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:122
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_body_handler()

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 1551 of file handler.c.

1552 {
1553  if (!b || !s)
1554  return -1;
1555 
1556  bool plaintext = false;
1557  handler_t handler = NULL;
1558  handler_t encrypted_handler = NULL;
1559  int rc = 0;
1560 
1561  int oflags = s->flags;
1562 
1563  /* first determine which handler to use to process this part */
1564 
1565  if (is_autoview(b))
1566  {
1567  handler = autoview_handler;
1568  s->flags &= ~MUTT_CHARCONV;
1569  }
1570  else if (b->type == TYPE_TEXT)
1571  {
1572  if (mutt_str_strcasecmp("plain", b->subtype) == 0)
1573  {
1574  /* avoid copying this part twice since removing the transfer-encoding is
1575  * the only operation needed. */
1576  if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_is_application_pgp(b))
1577  {
1578  encrypted_handler = crypt_pgp_application_handler;
1579  handler = encrypted_handler;
1580  }
1581  else if (C_ReflowText &&
1582  (mutt_str_strcasecmp("flowed",
1583  mutt_param_get(&b->parameter, "format")) == 0))
1584  {
1585  handler = rfc3676_handler;
1586  }
1587  else
1588  {
1589  handler = text_plain_handler;
1590  }
1591  }
1592  else if (mutt_str_strcasecmp("enriched", b->subtype) == 0)
1593  handler = text_enriched_handler;
1594  else /* text body type without a handler */
1595  plaintext = false;
1596  }
1597  else if (b->type == TYPE_MESSAGE)
1598  {
1599  if (mutt_is_message_type(b->type, b->subtype))
1600  handler = message_handler;
1601  else if (mutt_str_strcasecmp("delivery-status", b->subtype) == 0)
1602  plaintext = true;
1603  else if (mutt_str_strcasecmp("external-body", b->subtype) == 0)
1604  handler = external_body_handler;
1605  }
1606  else if (b->type == TYPE_MULTIPART)
1607  {
1608  if ((mutt_str_strcmp("inline", C_ShowMultipartAlternative) != 0) &&
1609  (mutt_str_strcasecmp("alternative", b->subtype) == 0))
1610  {
1611  handler = alternative_handler;
1612  }
1613  else if ((mutt_str_strcmp("inline", C_ShowMultipartAlternative) != 0) &&
1614  (mutt_str_strcasecmp("multilingual", b->subtype) == 0))
1615  {
1616  handler = multilingual_handler;
1617  }
1618  else if ((WithCrypto != 0) && (mutt_str_strcasecmp("signed", b->subtype) == 0))
1619  {
1620  if (!mutt_param_get(&b->parameter, "protocol"))
1621  mutt_error(_("Error: multipart/signed has no protocol"));
1622  else if (s->flags & MUTT_VERIFY)
1623  handler = mutt_signed_handler;
1624  }
1626  {
1627  encrypted_handler = valid_pgp_encrypted_handler;
1628  handler = encrypted_handler;
1629  }
1631  {
1632  encrypted_handler = malformed_pgp_encrypted_handler;
1633  handler = encrypted_handler;
1634  }
1635 
1636  if (!handler)
1637  handler = multipart_handler;
1638 
1639  if ((b->encoding != ENC_7BIT) && (b->encoding != ENC_8BIT) && (b->encoding != ENC_BINARY))
1640  {
1641  mutt_debug(LL_DEBUG1, "Bad encoding type %d for multipart entity, assuming 7 bit\n",
1642  b->encoding);
1643  b->encoding = ENC_7BIT;
1644  }
1645  }
1646  else if ((WithCrypto != 0) && (b->type == TYPE_APPLICATION))
1647  {
1648  if (OptDontHandlePgpKeys && (mutt_str_strcasecmp("pgp-keys", b->subtype) == 0))
1649  {
1650  /* pass raw part through for key extraction */
1651  plaintext = true;
1652  }
1653  else if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_is_application_pgp(b))
1654  {
1655  encrypted_handler = crypt_pgp_application_handler;
1656  handler = encrypted_handler;
1657  }
1658  else if (((WithCrypto & APPLICATION_SMIME) != 0) && mutt_is_application_smime(b))
1659  {
1660  encrypted_handler = crypt_smime_application_handler;
1661  handler = encrypted_handler;
1662  }
1663  }
1664 
1665  /* only respect disposition == attachment if we're not
1666  * displaying from the attachment menu (i.e. pager) */
1667  if ((!C_HonorDisposition || ((b->disposition != DISP_ATTACH) || OptViewAttach)) &&
1668  (plaintext || handler))
1669  {
1670  /* Prevent encrypted attachments from being included in replies
1671  * unless $include_encrypted is set. */
1672  if ((s->flags & MUTT_REPLYING) && (s->flags & MUTT_FIRSTDONE) &&
1673  encrypted_handler && !C_IncludeEncrypted)
1674  {
1675  goto cleanup;
1676  }
1677 
1678  rc = run_decode_and_handler(b, s, handler, plaintext);
1679  }
1680  /* print hint to use attachment menu for disposition == attachment
1681  * if we're not already being called from there */
1682  else if ((s->flags & MUTT_DISPLAY) || ((b->disposition == DISP_ATTACH) && !OptViewAttach &&
1683  C_HonorDisposition && (plaintext || handler)))
1684  {
1685  char keystroke[128];
1686  keystroke[0] = '\0';
1687  struct Buffer msg = mutt_buffer_make(256);
1688 
1689  if (!OptViewAttach)
1690  {
1691  if (km_expand_key(keystroke, sizeof(keystroke),
1692  km_find_func(MENU_PAGER, OP_VIEW_ATTACHMENTS)))
1693  {
1695  {
1696  /* L10N: %s expands to a keystroke/key binding, e.g. 'v'. */
1697  mutt_buffer_printf(&msg, _("[-- This is an attachment (use '%s' to view this part) --]\n"),
1698  keystroke);
1699  }
1700  else
1701  {
1702  /* L10N: %s/%s is a MIME type, e.g. "text/plain".
1703  The last %s expands to a keystroke/key binding, e.g. 'v'. */
1704  mutt_buffer_printf(&msg, _("[-- %s/%s is unsupported (use '%s' to view this part) --]\n"),
1705  TYPE(b), b->subtype, keystroke);
1706  }
1707  }
1708  else
1709  {
1711  {
1712  mutt_buffer_strcpy(&msg, _("[-- This is an attachment (need "
1713  "'view-attachments' bound to key) --]\n"));
1714  }
1715  else
1716  {
1717  /* L10N: %s/%s is a MIME type, e.g. "text/plain". */
1718  mutt_buffer_printf(&msg, _("[-- %s/%s is unsupported (need 'view-attachments' bound to key) --]\n"),
1719  TYPE(b), b->subtype);
1720  }
1721  }
1722  }
1723  else
1724  {
1726  {
1727  mutt_buffer_strcpy(&msg, _("[-- This is an attachment --]\n"));
1728  }
1729  else
1730  {
1731  /* L10N: %s/%s is a MIME type, e.g. "text/plain". */
1732  mutt_buffer_printf(&msg, _("[-- %s/%s is unsupported --]\n"), TYPE(b), b->subtype);
1733  }
1734  }
1735  state_mark_attach(s);
1736  state_printf(s, "%s", mutt_b2s(&msg));
1737  mutt_buffer_dealloc(&msg);
1738  }
1739 
1740 cleanup:
1741  s->flags = oflags | (s->flags & MUTT_FIRSTDONE);
1742  if (rc != 0)
1743  {
1744  mutt_debug(LL_DEBUG1, "Bailing on attachment of type %s/%s\n", TYPE(b),
1745  NONULL(b->subtype));
1746  }
1747 
1748  return rc;
1749 }
int state_printf(struct State *s, const char *fmt,...)
Write a formatted string to the State.
Definition: state.c:153
#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:1389
static bool is_autoview(struct Body *b)
Should email body be filtered by mailcap.
Definition: handler.c:484
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:87
int crypt_pgp_application_handler(struct Body *m, struct State *s)
Wrapper for CryptModuleSpecs::application_handler()
Definition: cryptglue.c:227
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:1122
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
int mutt_is_valid_multipart_pgp_encrypted(struct Body *b)
Is this a valid multi-part encrypted message?
Definition: crypt.c:477
#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
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
int crypt_smime_application_handler(struct Body *m, struct State *s)
Wrapper for CryptModuleSpecs::application_handler()
Definition: cryptglue.c:436
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:78
static int malformed_pgp_encrypted_handler(struct Body *b, struct State *s)
Handler for invalid pgp-encrypted emails - Implements handler_t.
Definition: handler.c:1455
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
Content is attached.
Definition: mime.h:63
WHERE bool OptDontHandlePgpKeys
(pseudo) used to extract PGP keys
Definition: options.h:34
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:701
bool C_ReflowText
Config: Reformat paragraphs of &#39;format=flowed&#39; text.
Definition: handler.c:70
char * subtype
content-type subtype
Definition: body.h:37
struct Keymap * km_find_func(enum MenuType menu, int func)
Find a function&#39;s mapping in a Menu.
Definition: keymap.c:856
#define mutt_b2s(buf)
Definition: buffer.h:41
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:559
int km_expand_key(char *s, size_t len, struct Keymap *map)
Get the key string bound to a Keymap.
Definition: keymap.c:828
#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:1426
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:1287
SecurityFlags mutt_is_malformed_multipart_pgp_encrypted(struct Body *b)
Check for malformed layout.
Definition: crypt.c:514
static int multilingual_handler(struct Body *a, struct State *s)
Handler for multi-lingual emails - Implements handler_t.
Definition: handler.c:1106
bool C_IncludeEncrypted
Config: Whether to include encrypted content when replying.
Definition: handler.c:67
SecurityFlags mutt_is_application_smime(struct Body *m)
Does the message use S/MIME?
Definition: crypt.c:618
void state_mark_attach(struct State *s)
Write a unique marker around content.
Definition: state.c:41
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
bool C_HonorDisposition
Config: Don&#39;t display MIME parts inline if they have a disposition of &#39;attachment&#39;.
Definition: handler.c:65
unsigned int type
content-type primary type
Definition: body.h:65
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:134
Type: &#39;message/*&#39;.
Definition: mime.h:35
#define TYPE(body)
Definition: mime.h:83
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:529
#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 * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
char * C_ShowMultipartAlternative
Config: How to display &#39;multipart/alternative&#39; MIME parts.
Definition: handler.c:71
#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:1204
WHERE bool OptViewAttach
(pseudo) signals that we are viewing attachments
Definition: options.h:53
#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:317
static int external_body_handler(struct Body *b, struct State *s)
Handler for external-body emails - Implements handler_t.
Definition: handler.c:754
static int text_plain_handler(struct Body *b, struct State *s)
Handler for plain text - Implements handler_t.
Definition: handler.c:675
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
#define WithCrypto
Definition: ncrypt.h:160
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:135
+ Here is the caller graph for this function:

◆ mutt_can_decode()

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 1756 of file handler.c.

1757 {
1758  if (is_autoview(a))
1759  return true;
1760  if (a->type == TYPE_TEXT)
1761  return true;
1762  if (a->type == TYPE_MESSAGE)
1763  return true;
1764  if (a->type == TYPE_MULTIPART)
1765  {
1766  if (WithCrypto)
1767  {
1768  if ((mutt_str_strcasecmp(a->subtype, "signed") == 0) ||
1769  (mutt_str_strcasecmp(a->subtype, "encrypted") == 0))
1770  {
1771  return true;
1772  }
1773  }
1774 
1775  for (struct Body *b = a->parts; b; b = b->next)
1776  {
1777  if (mutt_can_decode(b))
1778  return true;
1779  }
1780  }
1781  else if ((WithCrypto != 0) && (a->type == TYPE_APPLICATION))
1782  {
1783  if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_is_application_pgp(a))
1784  return true;
1786  return true;
1787  }
1788 
1789  return false;
1790 }
static bool is_autoview(struct Body *b)
Should email body be filtered by mailcap.
Definition: handler.c:484
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:559
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:1756
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:618
unsigned int type
content-type primary type
Definition: body.h:65
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:134
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:160
Type: &#39;application/*&#39;.
Definition: mime.h:33
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: ncrypt.h:135
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_decode_attachment()

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 1797 of file handler.c.

1798 {
1799  int istext = mutt_is_text_part(b);
1800  iconv_t cd = (iconv_t)(-1);
1801 
1802  if (istext && s->flags & MUTT_CHARCONV)
1803  {
1804  char *charset = mutt_param_get(&b->parameter, "charset");
1805  if (!charset && C_AssumedCharset)
1806  charset = mutt_ch_get_default_charset();
1807  if (charset && C_Charset)
1809  }
1810  else if (istext && b->charset)
1812 
1813  fseeko(s->fp_in, b->offset, SEEK_SET);
1814  switch (b->encoding)
1815  {
1816  case ENC_QUOTED_PRINTABLE:
1817  decode_quoted(s, b->length,
1818  istext || (((WithCrypto & APPLICATION_PGP) != 0) &&
1820  cd);
1821  break;
1822  case ENC_BASE64:
1823  mutt_decode_base64(s, b->length,
1824  istext || (((WithCrypto & APPLICATION_PGP) != 0) &&
1826  cd);
1827  break;
1828  case ENC_UUENCODED:
1829  decode_uuencoded(s, b->length,
1830  istext || (((WithCrypto & APPLICATION_PGP) != 0) &&
1832  cd);
1833  break;
1834  default:
1835  decode_xbit(s, b->length,
1836  istext || (((WithCrypto & APPLICATION_PGP) != 0) &&
1838  cd);
1839  break;
1840  }
1841 
1842  if (cd != (iconv_t)(-1))
1843  iconv_close(cd);
1844 }
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:171
static void decode_uuencoded(struct State *s, long len, bool istext, iconv_t cd)
Decode uuencoded text.
Definition: handler.c:372
#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:308
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:1487
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:559
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:559
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:453
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:134
Quoted-printable text.
Definition: mime.h:51
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
char * mutt_ch_get_default_charset(void)
Get the default character set.
Definition: charset.c:434
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:160
UUEncoded text.
Definition: mime.h:54
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ C_HonorDisposition

bool C_HonorDisposition

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

Definition at line 65 of file handler.c.

◆ C_ImplicitAutoview

bool C_ImplicitAutoview

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

Definition at line 66 of file handler.c.

◆ C_IncludeEncrypted

bool C_IncludeEncrypted

Config: Whether to include encrypted content when replying.

Definition at line 67 of file handler.c.

◆ C_IncludeOnlyfirst

bool C_IncludeOnlyfirst

Config: Only include the first attachment when replying.

Definition at line 68 of file handler.c.

◆ C_PreferredLanguages

struct Slist* C_PreferredLanguages

Config: Preferred languages for multilingual MIME.

Definition at line 69 of file handler.c.

◆ C_ReflowText

bool C_ReflowText

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

Definition at line 70 of file handler.c.

◆ C_ShowMultipartAlternative

char* C_ShowMultipartAlternative

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

Definition at line 71 of file handler.c.