NeoMutt  2020-11-20
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 <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include "mutt/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "mutt.h"
#include "handler.h"
#include "ncrypt/lib.h"
#include "copy.h"
#include "enriched.h"
#include "keymap.h"
#include "mailcap.h"
#include "mutt_attach.h"
#include "mutt_globals.h"
#include "mutt_logging.h"
#include "muttlib.h"
#include "opcodes.h"
#include "options.h"
#include "pager.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)
 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)

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:92
unsigned int encoding
content-transfer-encoding, ContentEncoding
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:1659
void state_mark_attach(struct State *s)
Write a unique marker around content.
Definition: state.c:41
#define TYPE(body)
Definition: mime.h:89
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:618
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
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:241
#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:80
+ 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
#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 }
+ 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_len(tmps);
387  if (mutt_str_startswith(tmps, "begin "))
388  break;
389  }
390  while (len > 0)
391  {
392  if (!fgets(tmps, sizeof(tmps), s->fp_in))
393  return;
394  len -= mutt_str_len(tmps);
395  if (mutt_str_startswith(tmps, "end"))
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
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)
Check whether a string starts with a prefix.
Definition: string.c:160
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:631
#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_equal(val, "1"))
444  return true;
445 
446  mutt_str_copy(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_istrn_equal(buf, p, q - p))
457  return true;
458  }
459  else
460  {
461  if (mutt_istr_equal(buf, p))
462  return true;
463  }
464  }
465  else
466  {
467  const size_t plen = mutt_istr_startswith(buf, p);
468  if ((plen != 0) && (buf[plen] == '/'))
469  return true;
470  }
471 
472  p = NULL;
473  }
474 
475  return false;
476 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
static size_t plen
Length of cached packet.
Definition: pgppacket.c:39
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:991
bool mutt_istrn_equal(const char *a, const char *b, size_t l)
Check for equality of two strings ignoring case (to a maximum), safely.
Definition: string.c:621
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:172
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:716
+ 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_len(np->data) - 1;
504  if (((i > 0) && (np->data[i - 1] == '/') && (np->data[i] == '*') &&
505  mutt_istrn_equal(type, np->data, i)) ||
506  mutt_istr_equal(type, np->data))
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:62
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:465
bool mutt_istrn_equal(const char *a, const char *b, size_t l)
Check for equality of two strings ignoring case (to a maximum), safely.
Definition: string.c:621
static bool is_mmnoask(const char *buf)
Metamail compatibility: should the attachment be autoviewed?
Definition: handler.c:433
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
char * subtype
content-type subtype
Definition: body.h:37
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
#define TYPE(body)
Definition: mime.h:89
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:631
char * data
String.
Definition: list.h:36
void mutt_check_lookup_list(struct Body *b, char *type, size_t len)
Update the mime type.
Definition: mutt_attach.c:333
bool C_ImplicitAutoview
Config: Display MIME attachments inline if a &#39;copiousoutput&#39; mailcap entry exists.
Definition: handler.c:66
A List node for strings.
Definition: list.h:34
enum WindowType type
Window type, e.g. WT_SIDEBAR.
Definition: mutt_window.h:137
+ 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_dup(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 = filter_create_fd(mutt_b2s(cmd), NULL, &fp_out, &fp_err, fileno(fp_in), -1, -1);
582  }
583  else
584  {
585  mutt_file_fclose(&fp_in);
586  pid = filter_create(mutt_b2s(cmd), NULL, &fp_out, &fp_err);
587  }
588 
589  if (pid < 0)
590  {
591  mutt_perror(_("Can't create filter"));
592  if (s->flags & MUTT_DISPLAY)
593  {
595  state_printf(s, _("[-- Can't run %s. --]\n"), mutt_b2s(cmd));
596  }
597  rc = -1;
598  goto bail;
599  }
600 
601  if (s->prefix)
602  {
603  /* Remove ansi and formatting from autoview output in replies only. The
604  * user may want to see the formatting in the pager, but it shouldn't be
605  * in their quoted reply text too. */
606  struct Buffer *stripped = mutt_buffer_pool_get();
607  while (fgets(buf, sizeof(buf), fp_out))
608  {
609  mutt_buffer_strip_formatting(stripped, buf, false);
610  state_puts(s, s->prefix);
611  state_puts(s, mutt_b2s(stripped));
612  }
613  mutt_buffer_pool_release(&stripped);
614 
615  /* check for data on stderr */
616  if (fgets(buf, sizeof(buf), fp_err))
617  {
618  if (s->flags & MUTT_DISPLAY)
619  {
621  state_printf(s, _("[-- Autoview stderr of %s --]\n"), mutt_b2s(cmd));
622  }
623 
624  state_puts(s, s->prefix);
625  state_puts(s, buf);
626  while (fgets(buf, sizeof(buf), fp_err))
627  {
628  state_puts(s, s->prefix);
629  state_puts(s, buf);
630  }
631  }
632  }
633  else
634  {
635  mutt_file_copy_stream(fp_out, s->fp_out);
636  /* Check for stderr messages */
637  if (fgets(buf, sizeof(buf), fp_err))
638  {
639  if (s->flags & MUTT_DISPLAY)
640  {
642  state_printf(s, _("[-- Autoview stderr of %s --]\n"), mutt_b2s(cmd));
643  }
644 
645  state_puts(s, buf);
646  mutt_file_copy_stream(fp_err, s->fp_out);
647  }
648  }
649 
650  bail:
651  mutt_file_fclose(&fp_out);
652  mutt_file_fclose(&fp_err);
653 
654  filter_wait(pid);
655  if (piped)
656  mutt_file_fclose(&fp_in);
657  else
658  mutt_file_unlink(mutt_b2s(tempfile));
659 
660  if (s->flags & MUTT_DISPLAY)
662  }
663 
664 cleanup:
665  mailcap_entry_free(&entry);
666 
668  mutt_buffer_pool_release(&tempfile);
669 
670  return rc;
671 }
A mailcap entry.
Definition: mailcap.h:38
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:427
#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
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:206
#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:101
#define mutt_perror(...)
Definition: logging.h:85
Mailcap autoview field.
Definition: mailcap.h:62
#define mutt_message(...)
Definition: logging.h:83
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
String manipulation buffer.
Definition: buffer.h:33
char * prefix
String to add to the beginning of each output line.
Definition: state.h:48
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define _(a)
Definition: message.h:28
FILE * fp_out
File to write to.
Definition: state.h:47
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:465
int mailcap_expand_command(struct Body *a, const char *filename, const char *type, struct Buffer *command)
Expand expandos in a command.
Definition: mailcap.c:69
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:533
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:113
char * command
Definition: mailcap.h:40
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:618
#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:436
void mutt_buffer_strip_formatting(struct Buffer *dest, const char *src, bool strip_markers)
Removes ANSI and backspace formatting.
Definition: pager.c:1384
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:241
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:46
#define TYPE(body)
Definition: mime.h:89
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:271
pid_t filter_create_fd(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err, int fdin, int fdout, int fderr)
Run a command on a pipe (optionally connect stdin/stdout)
Definition: filter.c:61
#define FREE(x)
Definition: memory.h:40
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

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

682 {
683  char *buf = NULL;
684  size_t sz = 0;
685 
686  while ((buf = mutt_file_read_line(buf, &sz, s->fp_in, NULL, 0)))
687  {
688  if (!mutt_str_equal(buf, "-- ") && C_TextFlowed)
689  {
690  size_t len = mutt_str_len(buf);
691  while ((len > 0) && (buf[len - 1] == ' '))
692  buf[--len] = '\0';
693  }
694  if (s->prefix)
695  state_puts(s, s->prefix);
696  state_puts(s, buf);
697  state_putc(s, '\n');
698  }
699 
700  FREE(&buf);
701  return 0;
702 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
#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:667
FILE * fp_in
File to read from.
Definition: state.h:46
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:631
#define FREE(x)
Definition: memory.h:40
#define state_putc(STATE, STR)
Definition: state.h:56
WHERE bool C_TextFlowed
Config: Generate &#39;format=flowed&#39; messages.
Definition: mutt_globals.h:166
+ 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 707 of file handler.c.

708 {
709  struct stat st;
710  struct Body *b = NULL;
711  LOFF_T off_start;
712  int rc = 0;
713 
714  off_start = ftello(s->fp_in);
715  if (off_start < 0)
716  return -1;
717 
718  if ((a->encoding == ENC_BASE64) || (a->encoding == ENC_QUOTED_PRINTABLE) ||
719  (a->encoding == ENC_UUENCODED))
720  {
721  fstat(fileno(s->fp_in), &st);
722  b = mutt_body_new();
723  b->length = (LOFF_T) st.st_size;
725  }
726  else
727  b = a;
728 
729  if (b->parts)
730  {
731  CopyHeaderFlags chflags = CH_DECODE | CH_FROM;
732  if ((s->flags & MUTT_WEED) || ((s->flags & (MUTT_DISPLAY | MUTT_PRINTING)) && C_Weed))
733  chflags |= CH_WEED | CH_REORDER;
734  if (s->prefix)
735  chflags |= CH_PREFIX;
736  if (s->flags & MUTT_DISPLAY)
737  chflags |= CH_DISPLAY;
738 
739  mutt_copy_hdr(s->fp_in, s->fp_out, off_start, b->parts->offset, chflags, s->prefix, 0);
740 
741  if (s->prefix)
742  state_puts(s, s->prefix);
743  state_putc(s, '\n');
744 
745  rc = mutt_body_handler(b->parts, s);
746  }
747 
748  if ((a->encoding == ENC_BASE64) || (a->encoding == ENC_QUOTED_PRINTABLE) ||
749  (a->encoding == ENC_UUENCODED))
750  {
751  mutt_body_free(&b);
752  }
753 
754  return rc;
755 }
#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
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
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:1672
#define CH_WEED
Weed the headers?
Definition: copy.h:52
unsigned int encoding
content-transfer-encoding, ContentEncoding
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
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
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:103
Quoted-printable text.
Definition: mime.h:51
bool C_Weed
Config: Filter headers when displaying/forwarding/printing/replying.
Definition: globals.c:40
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1593
#define state_putc(STATE, STR)
Definition: state.h:56
#define CH_PREFIX
Quote header using $indent_string string?
Definition: copy.h:56
UUEncoded text.
Definition: mime.h:54
+ 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 760 of file handler.c.

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

◆ alternative_handler()

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

Handler for multipart alternative emails - Implements handler_t.

Definition at line 931 of file handler.c.

932 {
933  struct Body *choice = NULL;
934  struct Body *b = NULL;
935  bool mustfree = false;
936  int rc = 0;
937 
938  if ((a->encoding == ENC_BASE64) || (a->encoding == ENC_QUOTED_PRINTABLE) ||
939  (a->encoding == ENC_UUENCODED))
940  {
941  struct stat st;
942  mustfree = true;
943  fstat(fileno(s->fp_in), &st);
944  b = mutt_body_new();
945  b->length = (long) st.st_size;
946  b->parts =
947  mutt_parse_multipart(s->fp_in, mutt_param_get(&a->parameter, "boundary"),
948  (long) st.st_size, mutt_istr_equal("digest", a->subtype));
949  }
950  else
951  b = a;
952 
953  a = b;
954 
955  /* First, search list of preferred types */
956  struct ListNode *np = NULL;
957  STAILQ_FOREACH(np, &AlternativeOrderList, entries)
958  {
959  int btlen; /* length of basetype */
960  bool wild; /* do we have a wildcard to match all subtypes? */
961 
962  char *c = strchr(np->data, '/');
963  if (c)
964  {
965  wild = ((c[1] == '*') && (c[2] == '\0'));
966  btlen = c - np->data;
967  }
968  else
969  {
970  wild = true;
971  btlen = mutt_str_len(np->data);
972  }
973 
974  if (a->parts)
975  b = a->parts;
976  else
977  b = a;
978  while (b)
979  {
980  const char *bt = TYPE(b);
981  if (mutt_istrn_equal(bt, np->data, btlen) && (bt[btlen] == 0))
982  {
983  /* the basetype matches */
984  if (wild || mutt_istr_equal(np->data + btlen + 1, b->subtype))
985  {
986  choice = b;
987  }
988  }
989  b = b->next;
990  }
991 
992  if (choice)
993  break;
994  }
995 
996  /* Next, look for an autoviewable type */
997  if (!choice)
998  {
999  if (a->parts)
1000  b = a->parts;
1001  else
1002  b = a;
1003  while (b)
1004  {
1005  if (is_autoview(b))
1006  choice = b;
1007  b = b->next;
1008  }
1009  }
1010 
1011  /* Then, look for a text entry */
1012  if (!choice)
1013  {
1014  if (a->parts)
1015  b = a->parts;
1016  else
1017  b = a;
1018  int type = 0;
1019  while (b)
1020  {
1021  if (b->type == TYPE_TEXT)
1022  {
1023  if (mutt_istr_equal("plain", b->subtype) && (type <= TXT_PLAIN))
1024  {
1025  choice = b;
1026  type = TXT_PLAIN;
1027  }
1028  else if (mutt_istr_equal("enriched", b->subtype) && (type <= TXT_ENRICHED))
1029  {
1030  choice = b;
1031  type = TXT_ENRICHED;
1032  }
1033  else if (mutt_istr_equal("html", b->subtype) && (type <= TXT_HTML))
1034  {
1035  choice = b;
1036  type = TXT_HTML;
1037  }
1038  }
1039  b = b->next;
1040  }
1041  }
1042 
1043  /* Finally, look for other possibilities */
1044  if (!choice)
1045  {
1046  if (a->parts)
1047  b = a->parts;
1048  else
1049  b = a;
1050  while (b)
1051  {
1052  if (mutt_can_decode(b))
1053  choice = b;
1054  b = b->next;
1055  }
1056  }
1057 
1058  if (choice)
1059  {
1060  if (s->flags & MUTT_DISPLAY && !C_Weed)
1061  {
1062  fseeko(s->fp_in, choice->hdr_offset, SEEK_SET);
1063  mutt_file_copy_bytes(s->fp_in, s->fp_out, choice->offset - choice->hdr_offset);
1064  }
1065 
1067  {
1068  print_part_line(s, choice, 0);
1069  }
1070  mutt_body_handler(choice, s);
1071 
1073  {
1074  if (a->parts)
1075  b = a->parts;
1076  else
1077  b = a;
1078  int count = 0;
1079  while (b)
1080  {
1081  if (choice != b)
1082  {
1083  count += 1;
1084  if (count == 1)
1085  state_putc(s, '\n');
1086 
1087  print_part_line(s, b, count);
1088  }
1089  b = b->next;
1090  }
1091  }
1092  }
1093  else if (s->flags & MUTT_DISPLAY)
1094  {
1095  /* didn't find anything that we could display! */
1096  state_mark_attach(s);
1097  state_puts(s, _("[-- Error: Could not display any parts of "
1098  "Multipart/Alternative --]\n"));
1099  rc = -1;
1100  }
1101 
1102  if (mustfree)
1103  mutt_body_free(&a);
1104 
1105  return rc;
1106 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
#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:1688
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
bool mutt_istrn_equal(const char *a, const char *b, size_t l)
Check for equality of two strings ignoring case (to a maximum), safely.
Definition: string.c:621
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
#define TXT_PLAIN
Definition: handler.c:77
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
Base-64 encoded text.
Definition: mime.h:52
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
char * subtype
content-type subtype
Definition: body.h:37
#define TXT_ENRICHED
Definition: handler.c:78
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:1803
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
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
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:241
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
void state_mark_attach(struct State *s)
Write a unique marker around content.
Definition: state.c:41
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
#define TYPE(body)
Definition: mime.h:89
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:631
char * data
String.
Definition: list.h:36
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
bool C_Weed
Config: Filter headers when displaying/forwarding/printing/replying.
Definition: globals.c:40
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1593
#define state_putc(STATE, STR)
Definition: state.h:56
long hdr_offset
Offset in stream where the headers begin.
Definition: body.h:42
A List node for strings.
Definition: list.h:34
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
UUEncoded text.
Definition: mime.h:54
+ 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 1112 of file handler.c.

1113 {
1114  struct Body *b = NULL;
1115  bool mustfree = false;
1116  int rc = 0;
1117 
1119  "RFC8255 >> entering in handler multilingual handler\n");
1120  if ((a->encoding == ENC_BASE64) || (a->encoding == ENC_QUOTED_PRINTABLE) ||
1121  (a->encoding == ENC_UUENCODED))
1122  {
1123  struct stat st;
1124  mustfree = true;
1125  fstat(fileno(s->fp_in), &st);
1126  b = mutt_body_new();
1127  b->length = (long) st.st_size;
1128  b->parts =
1129  mutt_parse_multipart(s->fp_in, mutt_param_get(&a->parameter, "boundary"),
1130  (long) st.st_size, mutt_istr_equal("digest", a->subtype));
1131  }
1132  else
1133  b = a;
1134 
1135  a = b;
1136 
1137  if (a->parts)
1138  b = a->parts;
1139  else
1140  b = a;
1141 
1142  struct Body *choice = NULL;
1143  struct Body *first_part = NULL;
1144  struct Body *zxx_part = NULL;
1145  struct ListNode *np = NULL;
1146 
1148  {
1149  struct Buffer *langs = mutt_buffer_pool_get();
1150  cs_subset_str_string_get(NeoMutt->sub, "preferred_languages", langs);
1151  mutt_debug(LL_DEBUG2, "RFC8255 >> preferred_languages set in config to '%s'\n",
1152  mutt_b2s(langs));
1153  mutt_buffer_pool_release(&langs);
1154 
1155  STAILQ_FOREACH(np, &C_PreferredLanguages->head, entries)
1156  {
1157  while (b)
1158  {
1159  if (mutt_can_decode(b))
1160  {
1161  if (!first_part)
1162  first_part = b;
1163 
1164  if (b->language && mutt_str_equal("zxx", b->language))
1165  zxx_part = b;
1166 
1167  mutt_debug(LL_DEBUG2, "RFC8255 >> comparing configuration preferred_language='%s' to mail part content-language='%s'\n",
1168  np->data, b->language);
1169  if (b->language && mutt_str_equal(np->data, b->language))
1170  {
1171  mutt_debug(LL_DEBUG2, "RFC8255 >> preferred_language='%s' matches content-language='%s' >> part selected to be displayed\n",
1172  np->data, b->language);
1173  choice = b;
1174  break;
1175  }
1176  }
1177 
1178  b = b->next;
1179  }
1180 
1181  if (choice)
1182  break;
1183 
1184  if (a->parts)
1185  b = a->parts;
1186  else
1187  b = a;
1188  }
1189  }
1190 
1191  if (choice)
1192  mutt_body_handler(choice, s);
1193  else
1194  {
1195  if (zxx_part)
1196  mutt_body_handler(zxx_part, s);
1197  else
1198  mutt_body_handler(first_part, s);
1199  }
1200 
1201  if (mustfree)
1202  mutt_body_free(&a);
1203 
1204  return rc;
1205 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
struct Body * mutt_parse_multipart(FILE *fp, const char *boundary, LOFF_T end_off, bool digest)
Parse a multipart structure.
Definition: parse.c:1688
struct Body * next
next attachment in the list
Definition: body.h:53
Container for Accounts, Notifications.
Definition: neomutt.h:36
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:41
struct ListHead head
Definition: slist.h:47
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
Base-64 encoded text.
Definition: mime.h:52
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
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:1803
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
int cs_subset_str_string_get(const struct ConfigSubset *sub, const char *name, struct Buffer *result)
Get a config item as a string.
Definition: subset.c:357
char * data
String.
Definition: list.h:36
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:1593
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
A List node for strings.
Definition: list.h:34
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
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 1210 of file handler.c.

1211 {
1212  struct Body *b = NULL, *p = NULL;
1213  struct stat st;
1214  int count;
1215  int rc = 0;
1216 
1217  if ((a->encoding == ENC_BASE64) || (a->encoding == ENC_QUOTED_PRINTABLE) ||
1218  (a->encoding == ENC_UUENCODED))
1219  {
1220  fstat(fileno(s->fp_in), &st);
1221  b = mutt_body_new();
1222  b->length = (long) st.st_size;
1223  b->parts =
1224  mutt_parse_multipart(s->fp_in, mutt_param_get(&a->parameter, "boundary"),
1225  (long) st.st_size, mutt_istr_equal("digest", a->subtype));
1226  }
1227  else
1228  b = a;
1229 
1230  for (p = b->parts, count = 1; p; p = p->next, count++)
1231  {
1232  if (s->flags & MUTT_DISPLAY)
1233  {
1234  state_mark_attach(s);
1235  if (p->description || p->filename || p->form_name)
1236  {
1237  /* L10N: %s is the attachment description, filename or form_name. */
1238  state_printf(s, _("[-- Attachment #%d: %s --]\n"), count,
1239  p->description ? p->description :
1240  p->filename ? p->filename : p->form_name);
1241  }
1242  else
1243  state_printf(s, _("[-- Attachment #%d --]\n"), count);
1244  print_part_line(s, p, 0);
1245  if (C_Weed)
1246  {
1247  state_putc(s, '\n');
1248  }
1249  else
1250  {
1251  fseeko(s->fp_in, p->hdr_offset, SEEK_SET);
1252  mutt_file_copy_bytes(s->fp_in, s->fp_out, p->offset - p->hdr_offset);
1253  }
1254  }
1255 
1256  rc = mutt_body_handler(p, s);
1257  state_putc(s, '\n');
1258 
1259  if (rc != 0)
1260  {
1261  mutt_error(_("One or more parts of this message could not be displayed"));
1262  mutt_debug(LL_DEBUG1, "Failed on attachment #%d, type %s/%s\n", count,
1263  TYPE(p), NONULL(p->subtype));
1264  }
1265 
1266  if ((s->flags & MUTT_REPLYING) && C_IncludeOnlyfirst && (s->flags & MUTT_FIRSTDONE))
1267  {
1268  break;
1269  }
1270  }
1271 
1272  if ((a->encoding == ENC_BASE64) || (a->encoding == ENC_QUOTED_PRINTABLE) ||
1273  (a->encoding == ENC_UUENCODED))
1274  {
1275  mutt_body_free(&b);
1276  }
1277 
1278  /* make failure of a single part non-fatal */
1279  if (rc < 0)
1280  rc = 1;
1281  return rc;
1282 }
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:1688
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
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
Base-64 encoded text.
Definition: mime.h:52
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
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
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
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:241
void state_mark_attach(struct State *s)
Write a unique marker around content.
Definition: state.c:41
#define TYPE(body)
Definition: mime.h:89
Log at debug level 1.
Definition: logging.h:40
#define mutt_error(...)
Definition: logging.h:84
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
bool C_Weed
Config: Filter headers when displaying/forwarding/printing/replying.
Definition: globals.c:40
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1593
#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
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
+ 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 1293 of file handler.c.

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

1434 {
1435  struct Body *octetstream = b->parts->next;
1436 
1437  /* clear out any mime headers before the handler, so they can't be spoofed. */
1439  mutt_env_free(&octetstream->mime_headers);
1440 
1441  int rc;
1442  /* Some clients improperly encode the octetstream part. */
1443  if (octetstream->encoding != ENC_7BIT)
1444  rc = run_decode_and_handler(octetstream, s, crypt_pgp_encrypted_handler, 0);
1445  else
1446  rc = crypt_pgp_encrypted_handler(octetstream, s);
1447  b->goodsig |= octetstream->goodsig;
1448 
1449  /* Relocate protected headers onto the multipart/encrypted part */
1450  if (!rc && octetstream->mime_headers)
1451  {
1452  b->mime_headers = octetstream->mime_headers;
1453  octetstream->mime_headers = NULL;
1454  }
1455 
1456  return rc;
1457 }
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:247
unsigned int encoding
content-transfer-encoding, ContentEncoding
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:1293
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 1462 of file handler.c.

1463 {
1464  struct Body *octetstream = b->parts->next->next;
1465 
1466  /* clear out any mime headers before the handler, so they can't be spoofed. */
1468  mutt_env_free(&octetstream->mime_headers);
1469 
1470  /* exchange encodes the octet-stream, so re-run it through the decoder */
1471  int rc = run_decode_and_handler(octetstream, s, crypt_pgp_encrypted_handler, false);
1472  b->goodsig |= octetstream->goodsig;
1473 #ifdef USE_AUTOCRYPT
1474  b->is_autocrypt |= octetstream->is_autocrypt;
1475 #endif
1476 
1477  /* Relocate protected headers onto the multipart/encrypted part */
1478  if (!rc && octetstream->mime_headers)
1479  {
1480  b->mime_headers = octetstream->mime_headers;
1481  octetstream->mime_headers = NULL;
1482  }
1483 
1484  return rc;
1485 }
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:247
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:1293
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 1494 of file handler.c.

1495 {
1496  char buf[5];
1497  int ch, i;
1498  bool cr = false;
1499  char bufi[BUFI_SIZE];
1500  size_t l = 0;
1501 
1502  buf[4] = '\0';
1503 
1504  if (istext)
1505  state_set_prefix(s);
1506 
1507  while (len > 0)
1508  {
1509  for (i = 0; (i < 4) && (len > 0); len--)
1510  {
1511  ch = fgetc(s->fp_in);
1512  if (ch == EOF)
1513  break;
1514  if ((ch >= 0) && (ch < 128) && ((base64val(ch) != -1) || (ch == '=')))
1515  buf[i++] = ch;
1516  }
1517  if (i != 4)
1518  {
1519  /* "i" may be zero if there is trailing whitespace, which is not an error */
1520  if (i != 0)
1521  mutt_debug(LL_DEBUG2, "didn't get a multiple of 4 chars\n");
1522  break;
1523  }
1524 
1525  const int c1 = base64val(buf[0]);
1526  const int c2 = base64val(buf[1]);
1527 
1528  /* first char */
1529  ch = (c1 << 2) | (c2 >> 4);
1530 
1531  if (cr && (ch != '\n'))
1532  bufi[l++] = '\r';
1533 
1534  cr = false;
1535 
1536  if (istext && (ch == '\r'))
1537  cr = true;
1538  else
1539  bufi[l++] = ch;
1540 
1541  /* second char */
1542  if (buf[2] == '=')
1543  break;
1544  const int c3 = base64val(buf[2]);
1545  ch = ((c2 & 0xf) << 4) | (c3 >> 2);
1546 
1547  if (cr && (ch != '\n'))
1548  bufi[l++] = '\r';
1549 
1550  cr = false;
1551 
1552  if (istext && (ch == '\r'))
1553  cr = true;
1554  else
1555  bufi[l++] = ch;
1556 
1557  /* third char */
1558  if (buf[3] == '=')
1559  break;
1560  const int c4 = base64val(buf[3]);
1561  ch = ((c3 & 0x3) << 6) | c4;
1562 
1563  if (cr && (ch != '\n'))
1564  bufi[l++] = '\r';
1565 
1566  cr = false;
1567 
1568  if (istext && (ch == '\r'))
1569  cr = true;
1570  else
1571  bufi[l++] = ch;
1572 
1573  if ((l + 8) >= sizeof(bufi))
1574  convert_to_state(cd, bufi, &l, s);
1575  }
1576 
1577  if (cr)
1578  bufi[l++] = '\r';
1579 
1580  convert_to_state(cd, bufi, &l, s);
1581  convert_to_state(cd, 0, 0, s);
1582 
1583  state_reset_prefix(s);
1584 }
#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:41
#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 1593 of file handler.c.

1594 {
1595  if (!b || !s)
1596  return -1;
1597 
1598  bool plaintext = false;
1599  handler_t handler = NULL;
1600  handler_t encrypted_handler = NULL;
1601  int rc = 0;
1602  static unsigned short recurse_level = 0;
1603 
1604  int oflags = s->flags;
1605 
1606  if (recurse_level >= MUTT_MIME_MAX_DEPTH)
1607  {
1608  mutt_debug(LL_DEBUG1, "recurse level too deep. giving up.\n");
1609  return 1;
1610  }
1611  recurse_level++;
1612 
1613  /* first determine which handler to use to process this part */
1614 
1615  if (is_autoview(b))
1616  {
1617  handler = autoview_handler;
1618  s->flags &= ~MUTT_CHARCONV;
1619  }
1620  else if (b->type == TYPE_TEXT)
1621  {
1622  if (mutt_istr_equal("plain", b->subtype))
1623  {
1624  /* avoid copying this part twice since removing the transfer-encoding is
1625  * the only operation needed. */
1626  if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_is_application_pgp(b))
1627  {
1628  encrypted_handler = crypt_pgp_application_handler;
1629  handler = encrypted_handler;
1630  }
1631  else if (C_ReflowText && mutt_istr_equal("flowed", mutt_param_get(&b->parameter, "format")))
1632  {
1633  handler = rfc3676_handler;
1634  }
1635  else
1636  {
1637  handler = text_plain_handler;
1638  }
1639  }
1640  else if (mutt_istr_equal("enriched", b->subtype))
1641  handler = text_enriched_handler;
1642  else /* text body type without a handler */
1643  plaintext = false;
1644  }
1645  else if (b->type == TYPE_MESSAGE)
1646  {
1647  if (mutt_is_message_type(b->type, b->subtype))
1648  handler = message_handler;
1649  else if (mutt_istr_equal("delivery-status", b->subtype))
1650  plaintext = true;
1651  else if (mutt_istr_equal("external-body", b->subtype))
1652  handler = external_body_handler;
1653  }
1654  else if (b->type == TYPE_MULTIPART)
1655  {
1656  if (!mutt_str_equal("inline", C_ShowMultipartAlternative) &&
1657  mutt_istr_equal("alternative", b->subtype))
1658  {
1659  handler = alternative_handler;
1660  }
1661  else if (!mutt_str_equal("inline", C_ShowMultipartAlternative) &&
1662  mutt_istr_equal("multilingual", b->subtype))
1663  {
1664  handler = multilingual_handler;
1665  }
1666  else if ((WithCrypto != 0) && mutt_istr_equal("signed", b->subtype))
1667  {
1668  if (!mutt_param_get(&b->parameter, "protocol"))
1669  mutt_error(_("Error: multipart/signed has no protocol"));
1670  else if (s->flags & MUTT_VERIFY)
1671  handler = mutt_signed_handler;
1672  }
1674  {
1675  encrypted_handler = valid_pgp_encrypted_handler;
1676  handler = encrypted_handler;
1677  }
1679  {
1680  encrypted_handler = malformed_pgp_encrypted_handler;
1681  handler = encrypted_handler;
1682  }
1683 
1684  if (!handler)
1685  handler = multipart_handler;
1686 
1687  if ((b->encoding != ENC_7BIT) && (b->encoding != ENC_8BIT) && (b->encoding != ENC_BINARY))
1688  {
1689  mutt_debug(LL_DEBUG1, "Bad encoding type %d for multipart entity, assuming 7 bit\n",
1690  b->encoding);
1691  b->encoding = ENC_7BIT;
1692  }
1693  }
1694  else if ((WithCrypto != 0) && (b->type == TYPE_APPLICATION))
1695  {
1696  if (OptDontHandlePgpKeys && mutt_istr_equal("pgp-keys", b->subtype))
1697  {
1698  /* pass raw part through for key extraction */
1699  plaintext = true;
1700  }
1701  else if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_is_application_pgp(b))
1702  {
1703  encrypted_handler = crypt_pgp_application_handler;
1704  handler = encrypted_handler;
1705  }
1706  else if (((WithCrypto & APPLICATION_SMIME) != 0) && mutt_is_application_smime(b))
1707  {
1708  encrypted_handler = crypt_smime_application_handler;
1709  handler = encrypted_handler;
1710  }
1711  }
1712 
1713  /* only respect disposition == attachment if we're not
1714  * displaying from the attachment menu (i.e. pager) */
1715  if ((!C_HonorDisposition || ((b->disposition != DISP_ATTACH) || OptViewAttach)) &&
1716  (plaintext || handler))
1717  {
1718  /* Prevent encrypted attachments from being included in replies
1719  * unless $include_encrypted is set. */
1720  if ((s->flags & MUTT_REPLYING) && (s->flags & MUTT_FIRSTDONE) &&
1721  encrypted_handler && !C_IncludeEncrypted)
1722  {
1723  goto cleanup;
1724  }
1725 
1726  rc = run_decode_and_handler(b, s, handler, plaintext);
1727  }
1728  /* print hint to use attachment menu for disposition == attachment
1729  * if we're not already being called from there */
1730  else if (s->flags & MUTT_DISPLAY)
1731  {
1732  struct Buffer msg = mutt_buffer_make(256);
1733 
1734  if (!OptViewAttach)
1735  {
1736  char keystroke[128] = { 0 };
1737  if (km_expand_key(keystroke, sizeof(keystroke),
1738  km_find_func(MENU_PAGER, OP_VIEW_ATTACHMENTS)))
1739  {
1741  {
1742  /* L10N: %s expands to a keystroke/key binding, e.g. 'v'. */
1743  mutt_buffer_printf(&msg, _("[-- This is an attachment (use '%s' to view this part) --]\n"),
1744  keystroke);
1745  }
1746  else
1747  {
1748  /* L10N: %s/%s is a MIME type, e.g. "text/plain".
1749  The last %s expands to a keystroke/key binding, e.g. 'v'. */
1750  mutt_buffer_printf(&msg, _("[-- %s/%s is unsupported (use '%s' to view this part) --]\n"),
1751  TYPE(b), b->subtype, keystroke);
1752  }
1753  }
1754  else
1755  {
1757  {
1758  mutt_buffer_strcpy(&msg, _("[-- This is an attachment (need "
1759  "'view-attachments' bound to key) --]\n"));
1760  }
1761  else
1762  {
1763  /* L10N: %s/%s is a MIME type, e.g. "text/plain". */
1764  mutt_buffer_printf(&msg, _("[-- %s/%s is unsupported (need 'view-attachments' bound to key) --]\n"),
1765  TYPE(b), b->subtype);
1766  }
1767  }
1768  }
1769  else
1770  {
1772  {
1773  mutt_buffer_strcpy(&msg, _("[-- This is an attachment --]\n"));
1774  }
1775  else
1776  {
1777  /* L10N: %s/%s is a MIME type, e.g. "text/plain". */
1778  mutt_buffer_printf(&msg, _("[-- %s/%s is unsupported --]\n"), TYPE(b), b->subtype);
1779  }
1780  }
1781  state_mark_attach(s);
1782  state_printf(s, "%s", mutt_b2s(&msg));
1783  mutt_buffer_dealloc(&msg);
1784  }
1785 
1786 cleanup:
1787  recurse_level--;
1788  s->flags = oflags | (s->flags & MUTT_FIRSTDONE);
1789  if (rc != 0)
1790  {
1791  mutt_debug(LL_DEBUG1, "Bailing on attachment of type %s/%s\n", TYPE(b),
1792  NONULL(b->subtype));
1793  }
1794 
1795  return rc;
1796 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
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 WithCrypto
Definition: lib.h:123
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition: parse.c:1366
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:931
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:36
int(* handler_t)(struct Body *b, struct State *s)
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:234
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:1113
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:471
#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:444
unsigned int disposition
content-disposition, ContentDisposition
Definition: body.h:67
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
Pager pager (email viewer)
Definition: keymap.h:81
static int malformed_pgp_encrypted_handler(struct Body *b, struct State *s)
Handler for invalid pgp-encrypted emails - Implements handler_t.
Definition: handler.c:1462
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:36
unsigned int encoding
content-transfer-encoding, ContentEncoding
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:707
bool C_ReflowText
Config: Reformat paragraphs of &#39;format=flowed&#39; text.
Definition: handler.c:70
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
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:939
#define mutt_b2s(buf)
Definition: buffer.h:41
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:98
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:552
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:97
#define MUTT_MIME_MAX_DEPTH
Definition: mime.h:69
int km_expand_key(char *s, size_t len, struct Keymap *map)
Get the key string bound to a Keymap.
Definition: keymap.c:911
#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:1433
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:1293
SecurityFlags mutt_is_malformed_multipart_pgp_encrypted(struct Body *b)
Check for malformed layout.
Definition: crypt.c:508
static int multilingual_handler(struct Body *a, struct State *s)
Handler for multi-lingual emails - Implements handler_t.
Definition: handler.c:1112
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:610
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, ContentType
Definition: body.h:65
Type: &#39;message/*&#39;.
Definition: mime.h:35
#define TYPE(body)
Definition: mime.h:89
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
Log at debug level 1.
Definition: logging.h:40
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
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:1210
WHERE bool OptViewAttach
(pseudo) signals that we are viewing attachments
Definition: options.h:55
#define MUTT_FIRSTDONE
The first attachment has been done.
Definition: state.h:39
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
int rfc3676_handler(struct Body *a, struct State *s)
Body handler implementing RFC3676 for format=flowed - Implements handler_t.
Definition: rfc3676.c:316
static int external_body_handler(struct Body *b, struct State *s)
Handler for external-body emails - Implements handler_t.
Definition: handler.c:760
static int text_plain_handler(struct Body *b, struct State *s)
Handler for plain text - Implements handler_t.
Definition: handler.c:681
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
Type: &#39;application/*&#39;.
Definition: mime.h:33
+ Here is the call graph for this function:
+ 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 1803 of file handler.c.

1804 {
1805  if (is_autoview(a))
1806  return true;
1807  if (a->type == TYPE_TEXT)
1808  return true;
1809  if (a->type == TYPE_MESSAGE)
1810  return true;
1811  if (a->type == TYPE_MULTIPART)
1812  {
1813  if (WithCrypto)
1814  {
1815  if (mutt_istr_equal(a->subtype, "signed") || mutt_istr_equal(a->subtype, "encrypted"))
1816  {
1817  return true;
1818  }
1819  }
1820 
1821  for (struct Body *b = a->parts; b; b = b->next)
1822  {
1823  if (mutt_can_decode(b))
1824  return true;
1825  }
1826  }
1827  else if ((WithCrypto != 0) && (a->type == TYPE_APPLICATION))
1828  {
1829  if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_is_application_pgp(a))
1830  return true;
1832  return true;
1833  }
1834 
1835  return false;
1836 }
#define WithCrypto
Definition: lib.h:123
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
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
char * subtype
content-type subtype
Definition: body.h:37
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:98
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:552
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:97
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:1803
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:610
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
Type: &#39;message/*&#39;.
Definition: mime.h:35
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
Type: &#39;application/*&#39;.
Definition: mime.h:33
+ 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 1843 of file handler.c.

1844 {
1845  int istext = mutt_is_text_part(b) && (b->disposition == DISP_INLINE);
1846  iconv_t cd = (iconv_t)(-1);
1847 
1848  if (istext && (b->charset || (s->flags & MUTT_CHARCONV)))
1849  {
1850  const char *charset = b->charset;
1851  if (!charset)
1852  {
1853  charset = mutt_param_get(&b->parameter, "charset");
1854  if (!charset && C_AssumedCharset)
1855  charset = mutt_ch_get_default_charset();
1856  }
1857  if (charset && C_Charset)
1859  }
1860 
1861  fseeko(s->fp_in, b->offset, SEEK_SET);
1862  switch (b->encoding)
1863  {
1864  case ENC_QUOTED_PRINTABLE:
1865  decode_quoted(s, b->length,
1866  istext || (((WithCrypto & APPLICATION_PGP) != 0) &&
1868  cd);
1869  break;
1870  case ENC_BASE64:
1871  mutt_decode_base64(s, b->length,
1872  istext || (((WithCrypto & APPLICATION_PGP) != 0) &&
1874  cd);
1875  break;
1876  case ENC_UUENCODED:
1877  decode_uuencoded(s, b->length,
1878  istext || (((WithCrypto & APPLICATION_PGP) != 0) &&
1880  cd);
1881  break;
1882  default:
1883  decode_xbit(s, b->length,
1884  istext || (((WithCrypto & APPLICATION_PGP) != 0) &&
1886  cd);
1887  break;
1888  }
1889 
1890  if (cd != (iconv_t)(-1))
1891  iconv_close(cd);
1892 }
static void decode_xbit(struct State *s, long len, bool istext, iconv_t cd)
Decode xbit-encoded text.
Definition: handler.c:171
#define WithCrypto
Definition: lib.h:123
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:1494
unsigned int disposition
content-disposition, ContentDisposition
Definition: body.h:67
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
Base-64 encoded text.
Definition: mime.h:52
char * mutt_ch_get_default_charset(void)
Get the default character set.
Definition: charset.c:440
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:552
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:97
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
#define MUTT_ICONV_HOOK_FROM
apply charset-hooks to fromcode
Definition: charset.h:72
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:433
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_AssumedCharset
Config: If a message is missing a character set, assume this character set.
Definition: charset.c:52
Content is inline.
Definition: mime.h:62
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
iconv_t mutt_ch_iconv_open(const char *tocode, const char *fromcode, int flags)
Set up iconv for conversions.
Definition: charset.c:565
char * C_Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:53
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.