NeoMutt  2025-12-11-980-ge38c27
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
handler.c File Reference

Decide how to display email content. More...

#include "config.h"
#include <iconv.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include "mutt/lib.h"
#include "config/lib.h"
#include "core/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "handler.h"
#include "attach/lib.h"
#include "key/lib.h"
#include "ncrypt/lib.h"
#include "pager/lib.h"
#include "body.h"
#include "copy_email.h"
#include "enriched.h"
#include "envelope.h"
#include "globals.h"
#include "mailcap.h"
#include "mime.h"
#include "module_data.h"
#include "mutt_logging.h"
#include "muttlib.h"
#include "parameter.h"
#include "parse.h"
#include "rfc3676.h"
#include <libintl.h>
+ Include dependency graph for handler.c:

Go to the source code of this file.

Macros

#define BUFI_SIZE   1000
 Input buffer size for handler operations.
 
#define BUFO_SIZE   2000
 Output buffer size for handler operations.
 
#define TXT_HTML   1
 HTML text format.
 
#define TXT_PLAIN   2
 Plain text format.
 
#define TXT_ENRICHED   3
 Enriched text format.
 

Typedefs

typedef int(* handler_t) (struct Body *b_email, struct State *state)
 

Functions

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

Detailed Description

Decide how to display email content.

Authors
  • Michael R. Elkins
  • Pietro Cerutti
  • Richard Russon
  • Federico Kircheis
  • Reis Radomil
  • Ian Zimmerman
  • David Purton
  • Dennis Schön
  • Thomas Klausner

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

Input buffer size for handler operations.

Definition at line 72 of file handler.c.

◆ BUFO_SIZE

#define BUFO_SIZE   2000

Output buffer size for handler operations.

Definition at line 73 of file handler.c.

◆ TXT_HTML

#define TXT_HTML   1

HTML text format.

Definition at line 75 of file handler.c.

◆ TXT_PLAIN

#define TXT_PLAIN   2

Plain text format.

Definition at line 76 of file handler.c.

◆ TXT_ENRICHED

#define TXT_ENRICHED   3

Enriched text format.

Definition at line 77 of file handler.c.

Typedef Documentation

◆ handler_t

typedef int(* handler_t) (struct Body *b_email, struct State *state)

Definition at line 89 of file handler.c.

Function Documentation

◆ print_part_line()

static void print_part_line ( struct State * state,
struct Body * b_email,
int n )
static

Print a separator for the Mime part.

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

Definition at line 97 of file handler.c.

98{
99 struct Buffer *length = buf_pool_get();
100 mutt_str_pretty_size(length, b_email->length);
101 state_mark_attach(state);
102 char *charset = mutt_param_get(&b_email->parameter, "charset");
103 if (n == 0)
104 {
105 state_printf(state, _("[-- Type: %s/%s%s%s, Encoding: %s, Size: %s --]\n"),
106 BODY_TYPE(b_email), b_email->subtype, charset ? "; charset=" : "",
107 charset ? charset : "", ENCODING(b_email->encoding), buf_string(length));
108 }
109 else
110 {
111 state_printf(state, _("[-- Alternative Type #%d: %s/%s%s%s, Encoding: %s, Size: %s --]\n"),
112 n, BODY_TYPE(b_email), b_email->subtype,
113 charset ? "; charset=" : "", charset ? charset : "",
114 ENCODING(b_email->encoding), buf_string(length));
115 }
116 buf_pool_release(&length);
117}
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
#define BODY_TYPE(body)
Get the type name of a body part.
Definition mime.h:93
#define ENCODING(x)
Get the encoding name for an encoding type.
Definition mime.h:97
#define _(a)
Definition message.h:28
void state_mark_attach(struct State *state)
Write a unique marker around content.
Definition state.c:73
int state_printf(struct State *state, const char *fmt,...)
Write a formatted string to the State.
Definition state.c:190
int mutt_str_pretty_size(struct Buffer *buf, size_t num)
Display an abbreviated size, like 3.4K.
Definition muttlib.c:935
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition parameter.c:85
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
LOFF_T length
length (in bytes) of attachment
Definition body.h:53
struct ParameterList parameter
Parameters of the content-type.
Definition body.h:63
char * subtype
content-type subtype
Definition body.h:61
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition body.h:41
String manipulation buffer.
Definition buffer.h:36
+ 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 * state )
static

Convert text and write it to a file.

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

Definition at line 126 of file handler.c.

127{
128 char bufo[BUFO_SIZE] = { 0 };
129 const char *ib = NULL;
130 char *ob = NULL;
131 size_t ibl = 0;
132 size_t obl = 0;
133
134 if (!bufi)
135 {
136 if (iconv_t_valid(cd))
137 {
138 ob = bufo;
139 obl = sizeof(bufo);
140 iconv(cd, NULL, NULL, &ob, &obl);
141 if (ob != bufo)
142 state_prefix_put(state, bufo, ob - bufo);
143 }
144 return;
145 }
146
147 if (!iconv_t_valid(cd))
148 {
149 state_prefix_put(state, bufi, *l);
150 *l = 0;
151 return;
152 }
153
154 ib = bufi;
155 ibl = *l;
156 while (true)
157 {
158 ob = bufo;
159 obl = sizeof(bufo);
160 mutt_ch_iconv(cd, &ib, &ibl, &ob, &obl, 0, "?", NULL);
161 if (ob == bufo)
162 break;
163 state_prefix_put(state, bufo, ob - bufo);
164 }
165 memmove(bufi, ib, ibl);
166 *l = ibl;
167}
#define BUFO_SIZE
Output buffer size for handler operations.
Definition handler.c:73
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:685
static bool iconv_t_valid(const iconv_t cd)
Is the conversion descriptor valid?
Definition charset.h:123
void state_prefix_put(struct State *state, const char *buf, size_t buflen)
Write a prefixed fixed-string to the State.
Definition state.c:211
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ decode_xbit()

static void decode_xbit ( struct State * state,
long len,
bool istext,
iconv_t cd )
static

Decode xbit-encoded text.

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

Definition at line 176 of file handler.c.

177{
178 if (!istext)
179 {
180 mutt_file_copy_bytes(state->fp_in, state->fp_out, len);
181 return;
182 }
183
184 state_set_prefix(state);
185
186 int c;
187 char bufi[BUFI_SIZE] = { 0 };
188 size_t l = 0;
189 while (((c = fgetc(state->fp_in)) != EOF) && len--)
190 {
191 if ((c == '\r') && len)
192 {
193 const int ch = fgetc(state->fp_in);
194 if (ch == '\n')
195 {
196 c = ch;
197 len--;
198 }
199 else
200 {
201 ungetc(ch, state->fp_in);
202 }
203 }
204
205 bufi[l++] = c;
206 if (l == sizeof(bufi))
207 convert_to_state(cd, bufi, &l, state);
208 }
209
210 convert_to_state(cd, bufi, &l, state);
211 convert_to_state(cd, 0, 0, state);
212
213 state_reset_prefix(state);
214}
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:192
#define BUFI_SIZE
Input buffer size for handler operations.
Definition handler.c:72
static void convert_to_state(iconv_t cd, char *bufi, size_t *l, struct State *state)
Convert text and write it to a file.
Definition handler.c:126
#define state_set_prefix(state)
Definition state.h:62
#define state_reset_prefix(state)
Definition state.h:63
FILE * fp_out
File to write to.
Definition state.h:56
FILE * fp_in
File to read from.
Definition state.h:55
+ 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 223 of file handler.c.

224{
225 /* soft line break */
226 if ((s[0] == '=') && (s[1] == '\0'))
227 return 1;
228
229 /* quoted-printable triple */
230 if ((s[0] == '=') && mutt_isxdigit(s[1]) && mutt_isxdigit(s[2]))
231 {
232 *d = (hexval(s[1]) << 4) | hexval(s[2]);
233 return 0;
234 }
235
236 /* something else */
237 return -1;
238}
bool mutt_isxdigit(int arg)
Wrapper for isxdigit(3)
Definition ctype.c:111
#define hexval(ch)
Convert hexadecimal character to its integer value.
Definition mime.h:82
+ Here is the call graph for this function:
+ 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 247 of file handler.c.

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

◆ decode_quoted()

static void decode_quoted ( struct State * state,
long len,
bool istext,
iconv_t cd )
static

Decode an attachment encoded with quoted-printable.

Parameters
stateState 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 316 of file handler.c.

317{
318 char line[256] = { 0 };
319 char decline[512] = { 0 };
320 size_t l = 0;
321 size_t l3 = 0;
322
323 if (istext)
324 state_set_prefix(state);
325
326 while (len > 0)
327 {
328 /* It's ok to use a fixed size buffer for input, even if the line turns
329 * out to be longer than this. Just process the line in chunks. This
330 * really shouldn't happen according the MIME spec, since Q-P encoded
331 * lines are at most 76 characters, but we should be liberal about what
332 * we accept. */
333 if (!fgets(line, MIN((ssize_t) sizeof(line), len + 1), state->fp_in))
334 break;
335
336 size_t linelen = strlen(line);
337 len -= linelen;
338
339 /* inspect the last character we read so we can tell if we got the
340 * entire line. */
341 const int last = (linelen != 0) ? line[linelen - 1] : 0;
342
343 /* chop trailing whitespace if we got the full line */
344 if (last == '\n')
345 {
346 while ((linelen > 0) && mutt_isspace(line[linelen - 1]))
347 linelen--;
348 line[linelen] = '\0';
349 }
350
351 /* decode and do character set conversion */
352 qp_decode_line(decline + l, line, &l3, last);
353 l += l3;
354 convert_to_state(cd, decline, &l, state);
355 }
356
357 convert_to_state(cd, 0, 0, state);
358 state_reset_prefix(state);
359}
bool mutt_isspace(int arg)
Wrapper for isspace(3)
Definition ctype.c:96
static void qp_decode_line(char *dest, char *src, size_t *l, int last)
Decode a line of quoted-printable text.
Definition handler.c:247
#define MIN(a, b)
Return the minimum of two values.
Definition memory.h:40
+ 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 366 of file handler.c.

367{
368 if ((ch < 32) || (ch > 95))
369 return 0;
370 return ch - 32;
371}
+ Here is the caller graph for this function:

◆ decode_uuencoded()

static void decode_uuencoded ( struct State * state,
long len,
bool istext,
iconv_t cd )
static

Decode uuencoded text.

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

Definition at line 380 of file handler.c.

381{
382 char tmps[128] = { 0 };
383 char *pt = NULL;
384 char bufi[BUFI_SIZE] = { 0 };
385 size_t k = 0;
386
387 if (istext)
388 state_set_prefix(state);
389
390 while (len > 0)
391 {
392 if (!fgets(tmps, sizeof(tmps), state->fp_in))
393 goto cleanup;
394 len -= mutt_str_len(tmps);
395 if (mutt_str_startswith(tmps, "begin "))
396 break;
397 }
398 while (len > 0)
399 {
400 if (!fgets(tmps, sizeof(tmps), state->fp_in))
401 goto cleanup;
402 len -= mutt_str_len(tmps);
403 if (mutt_str_startswith(tmps, "end"))
404 break;
405 pt = tmps;
406 const unsigned char linelen = decode_byte(*pt);
407 pt++;
408 for (unsigned char c = 0; (c < linelen) && *pt;)
409 {
410 for (char l = 2; (l <= 6) && pt[0] && pt[1]; l += 2)
411 {
412 char out = decode_byte(*pt) << l;
413 pt++;
414 out |= (decode_byte(*pt) >> (6 - l));
415 bufi[k++] = out;
416 c++;
417 if (c == linelen)
418 break;
419 }
420 convert_to_state(cd, bufi, &k, state);
421 pt++;
422 }
423 }
424
425cleanup:
426 convert_to_state(cd, bufi, &k, state);
427 convert_to_state(cd, 0, 0, state);
428
429 state_reset_prefix(state);
430}
static unsigned char decode_byte(char ch)
Decode a uuencoded byte.
Definition handler.c:366
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition string.c:234
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition string.c:503
+ 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 442 of file handler.c.

443{
444 const char *val = mutt_str_getenv("MM_NOASK");
445 if (!val)
446 return false;
447
448 char *p = NULL;
449 char tmp[1024] = { 0 };
450 char *q = NULL;
451
452 if (mutt_str_equal(val, "1"))
453 return true;
454
455 mutt_str_copy(tmp, val, sizeof(tmp));
456 p = tmp;
457
458 while ((p = strtok(p, ",")))
459 {
460 q = strrchr(p, '/');
461 if (q)
462 {
463 if (q[1] == '*')
464 {
465 if (mutt_istrn_equal(buf, p, q - p))
466 return true;
467 }
468 else
469 {
470 if (mutt_istr_equal(buf, p))
471 return true;
472 }
473 }
474 else
475 {
476 const size_t plen = mutt_istr_startswith(buf, p);
477 if ((plen != 0) && (buf[plen] == '/'))
478 return true;
479 }
480
481 p = NULL;
482 }
483
484 return false;
485}
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition string.c:678
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:666
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition string.c:732
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:587
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition string.c:246
bool mutt_istrn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings ignoring case (to a maximum), safely.
Definition string.c:457
+ 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 493 of file handler.c.

494{
495 char type[256] = { 0 };
496 bool is_av = false;
497
498 snprintf(type, sizeof(type), "%s/%s", BODY_TYPE(b), b->subtype);
499
501 ASSERT(mod_data);
502
503 const bool c_implicit_auto_view = cs_subset_bool(NeoMutt->sub, "implicit_auto_view");
504 if (c_implicit_auto_view)
505 {
506 /* $implicit_auto_view is essentially the same as "auto-view *" */
507 is_av = true;
508 }
509 else
510 {
511 /* determine if this type is on the user's auto-view list */
512 mutt_check_lookup_list(b, type, sizeof(type));
513 struct ListNode *np = NULL;
514 STAILQ_FOREACH(np, &mod_data->auto_view, entries)
515 {
516 int i = mutt_str_len(np->data);
517 i--;
518 if (((i > 0) && (np->data[i - 1] == '/') && (np->data[i] == '*') &&
519 mutt_istrn_equal(type, np->data, i)) ||
520 mutt_istr_equal(type, np->data))
521 {
522 is_av = true;
523 break;
524 }
525 }
526
527 if (is_mmnoask(type))
528 is_av = true;
529 }
530
531 /* determine if there is a mailcap entry suitable for auto-view
532 *
533 * @warning type is altered by this call as a result of 'mime-lookup' support */
534 if (is_av)
535 return mailcap_lookup(b, type, sizeof(type), NULL, MUTT_MC_AUTOVIEW);
536
537 return false;
538}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
static bool is_mmnoask(const char *buf)
Metamail compatibility: should the attachment be autoviewed?
Definition handler.c:442
bool mailcap_lookup(struct Body *b, char *type, size_t typelen, struct MailcapEntry *entry, enum MailcapLookup opt)
Find given type in the list of mailcap files.
Definition mailcap.c:484
@ MUTT_MC_AUTOVIEW
Mailcap autoview field.
Definition mailcap.h:61
@ MODULE_ID_EMAIL
ModuleEmail, Email code
Definition module_api.h:64
void mutt_check_lookup_list(struct Body *b, char *type, size_t len)
Update the mime type.
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
Definition neomutt.c:666
#define STAILQ_FOREACH(var, head, field)
Definition queue.h:390
#define ASSERT(COND)
Definition signal2.h:59
Email private Module data.
Definition module_data.h:32
struct ListHead auto_view
List of mime types to auto view.
Definition module_data.h:35
A List node for strings.
Definition list.h:37
char * data
String.
Definition list.h:38
Container for Accounts, Notifications.
Definition neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
+ 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 * state,
handler_t handler,
bool plaintext )
static

Run an appropriate decoder for an email.

Parameters
bBody of the email
stateState 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 1346 of file handler.c.

1348{
1349 const char *save_prefix = NULL;
1350 FILE *fp = NULL;
1351 size_t tmplength = 0;
1352 LOFF_T tmpoffset = 0;
1353 int decode = 0;
1354 int rc = 0;
1355#ifndef USE_FMEMOPEN
1356 struct Buffer *tempfile = NULL;
1357#endif
1358
1359 if (!mutt_file_seek(state->fp_in, b->offset, SEEK_SET))
1360 {
1361 return -1;
1362 }
1363
1364#ifdef USE_FMEMOPEN
1365 char *temp = NULL;
1366 size_t tempsize = 0;
1367#endif
1368
1369 /* see if we need to decode this part before processing it */
1370 if ((b->encoding == ENC_BASE64) || (b->encoding == ENC_QUOTED_PRINTABLE) ||
1371 (b->encoding == ENC_UUENCODED) || (plaintext || mutt_is_text_part(b)))
1372 /* text subtypes may require character set conversion even with 8bit encoding */
1373 {
1374 const int orig_type = b->type;
1375 if (plaintext)
1376 {
1377 b->type = TYPE_TEXT;
1378 }
1379 else
1380 {
1381 /* decode to a tempfile, saving the original destination */
1382 fp = state->fp_out;
1383#ifdef USE_FMEMOPEN
1384 state->fp_out = open_memstream(&temp, &tempsize);
1385 if (!state->fp_out)
1386 {
1387 mutt_error(_("Unable to open 'memory stream'"));
1388 mutt_debug(LL_DEBUG1, "Can't open 'memory stream'\n");
1389 return -1;
1390 }
1391#else
1392 tempfile = buf_pool_get();
1393 buf_mktemp(tempfile);
1394 state->fp_out = mutt_file_fopen(buf_string(tempfile), "w");
1395 if (!state->fp_out)
1396 {
1397 mutt_error(_("Unable to open temporary file"));
1398 mutt_debug(LL_DEBUG1, "Can't open %s\n", buf_string(tempfile));
1399 buf_pool_release(&tempfile);
1400 return -1;
1401 }
1402#endif
1403 /* decoding the attachment changes the size and offset, so save a copy
1404 * of the "real" values now, and restore them after processing */
1405 tmplength = b->length;
1406 tmpoffset = b->offset;
1407
1408 /* if we are decoding binary bodies, we don't want to prefix each
1409 * line with the prefix or else the data will get corrupted. */
1410 save_prefix = state->prefix;
1411 state->prefix = NULL;
1412
1413 decode = 1;
1414 }
1415
1416 mutt_decode_attachment(b, state);
1417
1418 if (decode)
1419 {
1420 b->length = ftello(state->fp_out);
1421 b->offset = 0;
1422#ifdef USE_FMEMOPEN
1423 /* When running under torify, mutt_file_fclose(&state->fp_out) does not seem to
1424 * update tempsize. On the other hand, fflush does. See
1425 * https://github.com/neomutt/neomutt/issues/440 */
1426 fflush(state->fp_out);
1427#endif
1428 mutt_file_fclose(&state->fp_out);
1429
1430 /* restore final destination and substitute the tempfile for input */
1431 state->fp_out = fp;
1432 fp = state->fp_in;
1433#ifdef USE_FMEMOPEN
1434 if (tempsize)
1435 {
1436 state->fp_in = fmemopen(temp, tempsize, "r");
1437 }
1438 else
1439 { /* fmemopen can't handle zero-length buffers */
1440 state->fp_in = mutt_file_fopen("/dev/null", "r");
1441 }
1442 if (!state->fp_in)
1443 {
1444 mutt_perror(_("failed to re-open 'memory stream'"));
1445 FREE(&temp);
1446 state->fp_in = fp;
1447 state->prefix = save_prefix;
1448 b->length = tmplength;
1449 b->offset = tmpoffset;
1450 return -1;
1451 }
1452#else
1453 state->fp_in = mutt_file_fopen(buf_string(tempfile), "r");
1454 unlink(buf_string(tempfile));
1455 buf_pool_release(&tempfile);
1456 if (!state->fp_in)
1457 {
1458 mutt_perror(_("failed to re-open temporary file"));
1459 state->fp_in = fp;
1460 state->prefix = save_prefix;
1461 b->length = tmplength;
1462 b->offset = tmpoffset;
1463 return -1;
1464 }
1465#endif
1466 /* restore the prefix */
1467 state->prefix = save_prefix;
1468 }
1469
1470 b->type = orig_type;
1471 }
1472
1473 /* process the (decoded) body part */
1474 if (handler)
1475 {
1476 rc = handler(b, state);
1477 if (rc != 0)
1478 {
1479 mutt_debug(LL_DEBUG1, "Failed on attachment of type %s/%s\n",
1480 BODY_TYPE(b), NONULL(b->subtype));
1481 }
1482
1483 if (decode)
1484 {
1485 b->length = tmplength;
1486 b->offset = tmpoffset;
1487
1488 /* restore the original source stream */
1489 mutt_file_fclose(&state->fp_in);
1490 state->fp_in = fp;
1491 }
1492 }
1493 state->flags |= STATE_FIRSTDONE;
1494#ifdef USE_FMEMOPEN
1495 FREE(&temp);
1496#endif
1497
1498 return rc;
1499}
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition file.c:648
#define mutt_file_fclose(FP)
Definition file.h:144
#define mutt_file_fopen(PATH, MODE)
Definition file.h:143
#define mutt_error(...)
Definition logging2.h:94
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
#define mutt_perror(...)
Definition logging2.h:95
void mutt_decode_attachment(const struct Body *b, struct State *state)
Decode an email's attachment.
Definition handler.c:1943
@ LL_DEBUG1
Log at debug level 1.
Definition logging2.h:45
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
@ ENC_UUENCODED
UUEncoded text.
Definition mime.h:54
@ ENC_BASE64
Base-64 encoded text.
Definition mime.h:52
@ ENC_QUOTED_PRINTABLE
Quoted-printable text.
Definition mime.h:51
@ TYPE_TEXT
Type: 'text/*'.
Definition mime.h:38
@ STATE_FIRSTDONE
The first attachment has been done.
Definition state.h:44
bool mutt_is_text_part(const struct Body *b)
Is this part of an email in plain text?
Definition muttlib.c:396
#define NONULL(x)
Definition string2.h:44
LOFF_T offset
offset where the actual data begins
Definition body.h:52
unsigned int type
content-type primary type, ContentType
Definition body.h:40
StateFlags flags
Flags, e.g. STATE_DISPLAY.
Definition state.h:58
const char * prefix
String to add to the beginning of each output line.
Definition state.h:57
#define buf_mktemp(buf)
Definition tmp.h:33
+ 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 * state,
size_t len,
bool istext,
iconv_t cd )

Decode base64-encoded text.

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

Definition at line 1568 of file handler.c.

1569{
1570 char buf[5] = { 0 };
1571 int ch;
1572 int i;
1573 bool cr = false;
1574 char bufi[BUFI_SIZE] = { 0 };
1575 size_t l = 0;
1576
1577 buf[4] = '\0';
1578
1579 if (istext)
1580 state_set_prefix(state);
1581
1582 while (len > 0)
1583 {
1584 for (i = 0; (i < 4) && (len > 0); len--)
1585 {
1586 ch = fgetc(state->fp_in);
1587 if (ch == EOF)
1588 break;
1589 if ((ch >= 0) && (ch < 128) && ((base64val(ch) != -1) || (ch == '=')))
1590 buf[i++] = ch;
1591 }
1592 if (i != 4)
1593 {
1594 /* "i" may be zero if there is trailing whitespace, which is not an error */
1595 if (i != 0)
1596 mutt_debug(LL_DEBUG2, "didn't get a multiple of 4 chars\n");
1597 break;
1598 }
1599
1600 const int c1 = base64val(buf[0]);
1601 const int c2 = base64val(buf[1]);
1602
1603 /* first char */
1604 ch = (c1 << 2) | (c2 >> 4);
1605
1606 if (cr && (ch != '\n'))
1607 bufi[l++] = '\r';
1608
1609 cr = false;
1610
1611 if (istext && (ch == '\r'))
1612 cr = true;
1613 else
1614 bufi[l++] = ch;
1615
1616 /* second char */
1617 if (buf[2] == '=')
1618 break;
1619 const int c3 = base64val(buf[2]);
1620 ch = ((c2 & 0xf) << 4) | (c3 >> 2);
1621
1622 if (cr && (ch != '\n'))
1623 bufi[l++] = '\r';
1624
1625 cr = false;
1626
1627 if (istext && (ch == '\r'))
1628 cr = true;
1629 else
1630 bufi[l++] = ch;
1631
1632 /* third char */
1633 if (buf[3] == '=')
1634 break;
1635 const int c4 = base64val(buf[3]);
1636 ch = ((c3 & 0x3) << 6) | c4;
1637
1638 if (cr && (ch != '\n'))
1639 bufi[l++] = '\r';
1640
1641 cr = false;
1642
1643 if (istext && (ch == '\r'))
1644 cr = true;
1645 else
1646 bufi[l++] = ch;
1647
1648 if ((l + 8) >= sizeof(bufi))
1649 convert_to_state(cd, bufi, &l, state);
1650 }
1651
1652 if (cr)
1653 bufi[l++] = '\r';
1654
1655 convert_to_state(cd, bufi, &l, state);
1656 convert_to_state(cd, 0, 0, state);
1657
1658 state_reset_prefix(state);
1659}
#define base64val(ch)
Convert base64 character to its numeric value.
Definition base64.h:33
@ LL_DEBUG2
Log at debug level 2.
Definition logging2.h:46
+ 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 * state )

Handler for the Body of an email.

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

Definition at line 1668 of file handler.c.

1669{
1670 if (!b || !state)
1671 return -1;
1672
1673 bool plaintext = false;
1674 handler_t handler = NULL;
1675 handler_t encrypted_handler = NULL;
1676 int rc = 0;
1677 static unsigned short recurse_level = 0;
1678
1679 const int oflags = state->flags;
1680 const bool is_attachment_display = (oflags & STATE_DISPLAY_ATTACH);
1681
1682 if (recurse_level >= MUTT_MIME_MAX_DEPTH)
1683 {
1684 mutt_debug(LL_DEBUG1, "recurse level too deep. giving up\n");
1685 return 1;
1686 }
1687 recurse_level++;
1688
1689 /* first determine which handler to use to process this part */
1690
1691 if (is_autoview(b))
1692 {
1693 handler = autoview_handler;
1694 state->flags &= ~STATE_CHARCONV;
1695 }
1696 else if (b->type == TYPE_TEXT)
1697 {
1698 if (mutt_istr_equal("plain", b->subtype))
1699 {
1700 const bool c_reflow_text = cs_subset_bool(NeoMutt->sub, "reflow_text");
1701 /* avoid copying this part twice since removing the transfer-encoding is
1702 * the only operation needed. */
1704 {
1705 encrypted_handler = crypt_pgp_application_handler;
1706 handler = encrypted_handler;
1707 }
1708 else if (c_reflow_text &&
1709 mutt_istr_equal("flowed", mutt_param_get(&b->parameter, "format")))
1710 {
1711 handler = rfc3676_handler;
1712 }
1713 else
1714 {
1715 handler = text_plain_handler;
1716 }
1717 }
1718 else if (mutt_istr_equal("enriched", b->subtype))
1719 {
1720 handler = text_enriched_handler;
1721 }
1722 else /* text body type without a handler */
1723 {
1724 plaintext = false;
1725 }
1726 }
1727 else if (b->type == TYPE_MESSAGE)
1728 {
1729 if (mutt_is_message_type(b->type, b->subtype))
1730 handler = message_handler;
1731 else if (mutt_istr_equal("delivery-status", b->subtype))
1732 plaintext = true;
1733 else if (mutt_istr_equal("external-body", b->subtype))
1734 handler = external_body_handler;
1735 }
1736 else if (b->type == TYPE_MULTIPART)
1737 {
1738 const char *const c_show_multipart_alternative = cs_subset_string(NeoMutt->sub, "show_multipart_alternative");
1739 if (!mutt_str_equal("inline", c_show_multipart_alternative) &&
1740 mutt_istr_equal("alternative", b->subtype))
1741 {
1742 handler = alternative_handler;
1743 }
1744 else if (!mutt_str_equal("inline", c_show_multipart_alternative) &&
1745 mutt_istr_equal("multilingual", b->subtype))
1746 {
1747 handler = multilingual_handler;
1748 }
1749 else if ((WithCrypto != 0) && mutt_istr_equal("signed", b->subtype))
1750 {
1751 if (!mutt_param_get(&b->parameter, "protocol"))
1752 mutt_error(_("Error: multipart/signed has no protocol"));
1753 else if (state->flags & STATE_VERIFY)
1754 handler = mutt_signed_handler;
1755 }
1757 {
1758 encrypted_handler = valid_pgp_encrypted_handler;
1759 handler = encrypted_handler;
1760 }
1762 {
1763 encrypted_handler = malformed_pgp_encrypted_handler;
1764 handler = encrypted_handler;
1765 }
1766
1767 if (!handler)
1768 handler = multipart_handler;
1769
1770 if ((b->encoding != ENC_7BIT) && (b->encoding != ENC_8BIT) && (b->encoding != ENC_BINARY))
1771 {
1772 mutt_debug(LL_DEBUG1, "Bad encoding type %d for multipart entity, assuming 7 bit\n",
1773 b->encoding);
1774 b->encoding = ENC_7BIT;
1775 }
1776 }
1777 else if ((WithCrypto != 0) && (b->type == TYPE_APPLICATION))
1778 {
1779 if (OptDontHandlePgpKeys && mutt_istr_equal("pgp-keys", b->subtype))
1780 {
1781 /* pass raw part through for key extraction */
1782 plaintext = true;
1783 }
1784 else if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_is_application_pgp(b))
1785 {
1786 encrypted_handler = crypt_pgp_application_handler;
1787 handler = encrypted_handler;
1788 }
1789 else if (((WithCrypto & APPLICATION_SMIME) != 0) && mutt_is_application_smime(b))
1790 {
1791 encrypted_handler = crypt_smime_application_handler;
1792 handler = encrypted_handler;
1793 }
1794 }
1795
1796 if ((plaintext || handler) && (is_attachment_display || !mutt_prefer_as_attachment(b)))
1797 {
1798 /* only respect disposition == attachment if we're not
1799 * displaying from the attachment menu (i.e. pager) */
1800 /* Prevent encrypted attachments from being included in replies
1801 * unless $include_encrypted is set. */
1802 const bool c_include_encrypted = cs_subset_bool(NeoMutt->sub, "include_encrypted");
1803 if ((state->flags & STATE_REPLYING) && (state->flags & STATE_FIRSTDONE) &&
1804 encrypted_handler && !c_include_encrypted)
1805 {
1806 goto cleanup;
1807 }
1808
1809 rc = run_decode_and_handler(b, state, handler, plaintext);
1810 }
1811 else if (state->flags & STATE_DISPLAY)
1812 {
1813 /* print hint to use attachment menu for disposition == attachment
1814 * if we're not already being called from there */
1815 const bool c_honor_disposition = cs_subset_bool(NeoMutt->sub, "honor_disposition");
1816 struct Buffer *msg = buf_pool_get();
1817
1818 if (is_attachment_display)
1819 {
1820 if (c_honor_disposition && (b->disposition == DISP_ATTACH))
1821 {
1822 buf_strcpy(msg, _("[-- This is an attachment --]\n"));
1823 }
1824 else
1825 {
1826 /* L10N: %s/%s is a MIME type, e.g. "text/plain". */
1827 buf_printf(msg, _("[-- %s/%s is unsupported --]\n"), BODY_TYPE(b), b->subtype);
1828 }
1829 }
1830 else
1831 {
1832 struct Buffer *keystroke = buf_pool_get();
1833 const struct MenuDefinition *md_pager = pager_get_menu_definition();
1834 if (keymap_expand_key(km_find_func(md_pager, OP_VIEW_ATTACHMENTS), keystroke))
1835 {
1836 if (c_honor_disposition && (b->disposition == DISP_ATTACH))
1837 {
1838 /* L10N: %s expands to a keystroke/key binding, e.g. 'v'. */
1839 buf_printf(msg, _("[-- This is an attachment (use '%s' to view this part) --]\n"),
1840 buf_string(keystroke));
1841 }
1842 else
1843 {
1844 /* L10N: %s/%s is a MIME type, e.g. "text/plain".
1845 The last %s expands to a keystroke/key binding, e.g. 'v'. */
1846 buf_printf(msg, _("[-- %s/%s is unsupported (use '%s' to view this part) --]\n"),
1847 BODY_TYPE(b), b->subtype, buf_string(keystroke));
1848 }
1849 }
1850 else
1851 {
1852 if (c_honor_disposition && (b->disposition == DISP_ATTACH))
1853 {
1854 buf_strcpy(msg, _("[-- This is an attachment (need 'view-attachments' bound to key) --]\n"));
1855 }
1856 else
1857 {
1858 /* L10N: %s/%s is a MIME type, e.g. "text/plain". */
1859 buf_printf(msg, _("[-- %s/%s is unsupported (need 'view-attachments' bound to key) --]\n"),
1860 BODY_TYPE(b), b->subtype);
1861 }
1862 }
1863 buf_pool_release(&keystroke);
1864 }
1865 state_mark_attach(state);
1866 state_printf(state, "%s", buf_string(msg));
1867 buf_pool_release(&msg);
1868 }
1869
1870cleanup:
1871 recurse_level--;
1872 state->flags = oflags | (state->flags & STATE_FIRSTDONE);
1873 if (rc != 0)
1874 {
1875 mutt_debug(LL_DEBUG1, "Bailing on attachment of type %s/%s\n", BODY_TYPE(b),
1876 NONULL(b->subtype));
1877 }
1878
1879 return rc;
1880}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:168
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:401
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition crypt.c:610
int mutt_is_valid_multipart_pgp_encrypted(struct Body *b)
Is this a valid multi-part encrypted message?
Definition crypt.c:468
SecurityFlags mutt_is_malformed_multipart_pgp_encrypted(struct Body *b)
Check for malformed layout.
Definition crypt.c:505
SecurityFlags mutt_is_application_pgp(const struct Body *b)
Does the message use PGP?
Definition crypt.c:549
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition parse.c:1620
bool OptDontHandlePgpKeys
(pseudo) used to extract PGP keys
Definition globals.c:46
int crypt_pgp_application_handler(struct Body *b_email, struct State *state)
Wrapper for CryptModuleSpecs::application_handler() - Implements handler_t -.
Definition cryptglue.c:266
static int alternative_handler(struct Body *b_email, struct State *state)
Handler for multipart alternative emails - Implements handler_t -.
Definition handler.c:952
int text_enriched_handler(struct Body *b_email, struct State *state)
Handler for enriched text - Implements handler_t -.
Definition enriched.c:474
static int text_plain_handler(struct Body *b_email, struct State *state)
Handler for plain text - Implements handler_t -.
Definition handler.c:696
int crypt_smime_application_handler(struct Body *b_email, struct State *state)
Wrapper for CryptModuleSpecs::application_handler() - Implements handler_t -.
Definition cryptglue.c:524
static int autoview_handler(struct Body *b_email, struct State *state)
Handler for autoviewable attachments - Implements handler_t -.
Definition handler.c:543
static int external_body_handler(struct Body *b_email, struct State *state)
Handler for external-body emails - Implements handler_t -.
Definition handler.c:781
int rfc3676_handler(struct Body *b_email, struct State *state)
Handler for format=flowed - Implements handler_t -.
Definition rfc3676.c:329
static int malformed_pgp_encrypted_handler(struct Body *b_email, struct State *state)
Handler for invalid pgp-encrypted emails - Implements handler_t -.
Definition handler.c:1533
static int valid_pgp_encrypted_handler(struct Body *b_email, struct State *state)
Handler for valid pgp-encrypted emails - Implements handler_t -.
Definition handler.c:1504
static int message_handler(struct Body *b_email, struct State *state)
Handler for message/rfc822 body parts - Implements handler_t -.
Definition handler.c:723
static int multipart_handler(struct Body *b_email, struct State *state)
Handler for multipart emails - Implements handler_t -.
Definition handler.c:1256
static int multilingual_handler(struct Body *b_email, struct State *state)
Handler for multi-lingual emails - Implements handler_t -.
Definition handler.c:1143
int mutt_signed_handler(struct Body *b_email, struct State *state)
Handler for "multipart/signed" - Implements handler_t -.
Definition crypt.c:1250
static bool is_autoview(struct Body *b)
Should email body be filtered by mailcap.
Definition handler.c:493
bool mutt_prefer_as_attachment(struct Body *b)
Do we want this part as an attachment?
Definition handler.c:1887
int(* handler_t)(struct Body *b_email, struct State *state)
Definition handler.c:89
static int run_decode_and_handler(struct Body *b, struct State *state, handler_t handler, bool plaintext)
Run an appropriate decoder for an email.
Definition handler.c:1346
bool keymap_expand_key(struct Keymap *km, struct Buffer *buf)
Get the key string bound to a Keymap.
Definition keymap.c:247
struct Keymap * km_find_func(const struct MenuDefinition *md, int func)
Find a function's mapping in a Menu.
Definition menu.c:141
@ ENC_7BIT
7-bit text
Definition mime.h:49
@ ENC_BINARY
Binary.
Definition mime.h:53
@ ENC_8BIT
8-bit text
Definition mime.h:50
#define MUTT_MIME_MAX_DEPTH
Maximum nesting depth for MIME parts to prevent stack overflow.
Definition mime.h:69
@ TYPE_MESSAGE
Type: 'message/*'.
Definition mime.h:35
@ TYPE_MULTIPART
Type: 'multipart/*'.
Definition mime.h:37
@ TYPE_APPLICATION
Type: 'application/*'.
Definition mime.h:33
@ DISP_ATTACH
Content is attached.
Definition mime.h:63
@ STATE_CHARCONV
Do character set conversions.
Definition state.h:41
@ STATE_REPLYING
Are we replying?
Definition state.h:43
@ STATE_VERIFY
Perform signature verification.
Definition state.h:38
@ STATE_DISPLAY_ATTACH
We are displaying an attachment.
Definition state.h:45
@ STATE_DISPLAY
Output is displayed to the user.
Definition state.h:37
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition lib.h:106
#define PGP_ENCRYPT
Email is PGP encrypted.
Definition lib.h:112
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition lib.h:107
#define WithCrypto
Definition lib.h:132
struct MenuDefinition * pager_get_menu_definition(void)
Get the Pager Menu Definition.
Definition functions.c:1115
unsigned int disposition
content-disposition, ContentDisposition
Definition body.h:42
Functions for a Dialog or Window.
Definition menudef.h:44
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_prefer_as_attachment()

bool mutt_prefer_as_attachment ( struct Body * b)

Do we want this part as an attachment?

Parameters
bBody of email to test
Return values
trueWe want this part as an attachment

Definition at line 1887 of file handler.c.

1888{
1889 if (!mutt_can_decode(b))
1890 return true;
1891
1892 if (b->disposition != DISP_ATTACH)
1893 return false;
1894
1895 return cs_subset_bool(NeoMutt->sub, "honor_disposition");
1896}
bool mutt_can_decode(struct Body *b)
Will decoding the attachment produce any output.
Definition handler.c:1903
+ 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 * b)

Will decoding the attachment produce any output.

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

Definition at line 1903 of file handler.c.

1904{
1905 if (is_autoview(b))
1906 return true;
1907 if (b->type == TYPE_TEXT)
1908 return true;
1909 if (b->type == TYPE_MESSAGE)
1910 return true;
1911 if (b->type == TYPE_MULTIPART)
1912 {
1913 if (WithCrypto)
1914 {
1915 if (mutt_istr_equal(b->subtype, "signed") || mutt_istr_equal(b->subtype, "encrypted"))
1916 {
1917 return true;
1918 }
1919 }
1920
1921 for (struct Body *part = b->parts; part; part = part->next)
1922 {
1923 if (mutt_can_decode(part))
1924 return true;
1925 }
1926 }
1927 else if ((WithCrypto != 0) && (b->type == TYPE_APPLICATION))
1928 {
1930 return true;
1932 return true;
1933 }
1934
1935 return false;
1936}
The body of an email.
Definition body.h:36
struct Body * parts
parts of a multipart or message/rfc822
Definition body.h:73
struct Body * next
next attachment in the list
Definition body.h:72
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_decode_attachment()

void mutt_decode_attachment ( const struct Body * b,
struct State * state )

Decode an email's attachment.

Parameters
bBody of the email
stateState of text being processed

Definition at line 1943 of file handler.c.

1944{
1945 int istext = mutt_is_text_part(b) && (b->disposition == DISP_INLINE);
1946 iconv_t cd = ICONV_T_INVALID;
1947
1948 if (!mutt_file_seek(state->fp_in, b->offset, SEEK_SET))
1949 {
1950 return;
1951 }
1952
1953 if (istext && (b->charset || (state->flags & STATE_CHARCONV)))
1954 {
1955 const char *charset = b->charset;
1956 if (!charset)
1957 {
1958 charset = mutt_param_get(&b->parameter, "charset");
1959 if (!charset && !slist_is_empty(cc_assumed_charset()))
1961 }
1962 if (charset && cc_charset())
1964 }
1965
1966 switch (b->encoding)
1967 {
1969 decode_quoted(state, b->length,
1970 istext || (((WithCrypto & APPLICATION_PGP) != 0) &&
1972 cd);
1973 break;
1974 case ENC_BASE64:
1975 mutt_decode_base64(state, b->length,
1976 istext || (((WithCrypto & APPLICATION_PGP) != 0) &&
1978 cd);
1979 break;
1980 case ENC_UUENCODED:
1981 decode_uuencoded(state, b->length,
1982 istext || (((WithCrypto & APPLICATION_PGP) != 0) &&
1984 cd);
1985 break;
1986 default:
1987 decode_xbit(state, b->length,
1988 istext || (((WithCrypto & APPLICATION_PGP) != 0) &&
1990 cd);
1991 break;
1992 }
1993}
const char * cc_charset(void)
Get the cached value of $charset.
const struct Slist * cc_assumed_charset(void)
Get the cached value of $assumed_charset.
static void decode_uuencoded(struct State *state, long len, bool istext, iconv_t cd)
Decode uuencoded text.
Definition handler.c:380
void mutt_decode_base64(struct State *state, size_t len, bool istext, iconv_t cd)
Decode base64-encoded text.
Definition handler.c:1568
static void decode_quoted(struct State *state, long len, bool istext, iconv_t cd)
Decode an attachment encoded with quoted-printable.
Definition handler.c:316
static void decode_xbit(struct State *state, long len, bool istext, iconv_t cd)
Decode xbit-encoded text.
Definition handler.c:176
@ DISP_INLINE
Content is inline.
Definition mime.h:62
iconv_t mutt_ch_iconv_open(const char *tocode, const char *fromcode, uint8_t flags)
Set up iconv for conversions.
Definition charset.c:581
const char * mutt_ch_get_default_charset(const struct Slist *const assumed_charset)
Get the default character set.
Definition charset.c:452
#define MUTT_ICONV_HOOK_FROM
apply charset-hooks to fromcode
Definition charset.h:67
#define ICONV_T_INVALID
Error value for iconv functions.
Definition charset.h:111
bool slist_is_empty(const struct Slist *list)
Is the slist empty?
Definition slist.c:140
char * charset
Send mode: charset of attached file as stored on disk.
Definition body.h:79
+ Here is the call graph for this function:
+ Here is the caller graph for this function: